aboutsummaryrefslogtreecommitdiffstats
path: root/app/scripts/keyrings/simple.js
blob: 8f339cf803963b436ea76aaf886cd94eed3849d8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
const EventEmitter = require('events').EventEmitter
const Wallet = require('ethereumjs-wallet')
const ethUtil = require('ethereumjs-util')
const type = 'Simple Key Pair'
const sigUtil = require('../lib/sig-util')

class SimpleKeyring extends EventEmitter {

  /* PUBLIC METHODS */

  constructor (opts) {
    super()
    this.type = type
    this.opts = opts || {}
    this.wallets = []
  }

  serialize () {
    return Promise.resolve(this.wallets.map(w => w.getPrivateKey().toString('hex')))
  }

  deserialize (wallets = []) {
    this.wallets = wallets.map((w) => {
      var b = new Buffer(w, 'hex')
      const wallet = Wallet.fromPrivateKey(b)
      return wallet
    })
    return Promise.resolve()
  }

  addAccounts (n = 1) {
    var newWallets = []
    for (var i = 0; i < n; i++) {
      newWallets.push(Wallet.generate())
    }
    this.wallets = this.wallets.concat(newWallets)
    const hexWallets = newWallets.map(w => w.getAddress().toString('hex'))
    return Promise.resolve(hexWallets)
  }

  getAccounts () {
    return Promise.resolve(this.wallets.map(w => w.getAddress().toString('hex')))
  }

  // tx is an instance of the ethereumjs-transaction class.
  signTransaction (address, tx) {
    const wallet = this._getWalletForAccount(address)
    var privKey = wallet.getPrivateKey()
    tx.sign(privKey)
    return Promise.resolve(tx)
  }

  // For eth_sign, we need to sign transactions:
  signMessage (withAccount, data) {
    const wallet = this._getWalletForAccount(withAccount)
    const message = ethUtil.removeHexPrefix(data)
    var privKey = wallet.getPrivateKey()
    var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey)
    var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s))
    return Promise.resolve(rawMsgSig)
  }

  exportAccount (address) {
    const wallet = this._getWalletForAccount(address)
    return Promise.resolve(wallet.getPrivateKey().toString('hex'))
  }


  /* PRIVATE METHODS */

  _getWalletForAccount (account) {
    return this.wallets.find(w => w.getAddress().toString('hex') === account)
  }

}

SimpleKeyring.type = type
module.exports = SimpleKeyring
: key }), }), ]) } renderCurrentConversion () { const { metamask: { currentCurrency, conversionDate }, setCurrentCurrency } = this.props return h('div.settings__content-row', [ h('div.settings__content-item', [ h('span', 'Current Conversion'), h('span.settings__content-description', `Updated ${Date(conversionDate)}`), ]), h('div.settings__content-item', [ h('div.settings__content-item-col', [ h(SimpleDropdown, { placeholder: 'Select Currency', options: getInfuraCurrencyOptions(), selectedOption: currentCurrency, onSelect: newCurrency => setCurrentCurrency(newCurrency), }), ]), ]), ]) } renderCurrentProvider () { const { metamask: { provider = {} } } = this.props let title, value, color switch (provider.type) { case 'mainnet': title = 'Current Network' value = 'Main Ethereum Network' color = '#038789' break case 'ropsten': title = 'Current Network' value = 'Ropsten Test Network' color = '#e91550' break case 'kovan': title = 'Current Network' value = 'Kovan Test Network' color = '#690496' break case 'rinkeby': title = 'Current Network' value = 'Rinkeby Test Network' color = '#ebb33f' break default: title = 'Current RPC' value = provider.rpcTarget } return h('div.settings__content-row', [ h('div.settings__content-item', title), h('div.settings__content-item', [ h('div.settings__content-item-col', [ h('div.settings__provider-wrapper', [ h('div.settings__provider-icon', { style: { background: color } }), h('div', value), ]), ]), ]), ]) } renderNewRpcUrl () { return ( h('div.settings__content-row', [ h('div.settings__content-item', [ h('span', 'New RPC URL'), ]), h('div.settings__content-item', [ h('div.settings__content-item-col', [ h('input.settings__input', { placeholder: 'New RPC URL', onChange: event => this.setState({ newRpc: event.target.value }), onKeyPress: event => { if (event.key === 'Enter') { this.validateRpc(this.state.newRpc) } }, }), h('div.settings__rpc-save-button', { onClick: event => { event.preventDefault() this.validateRpc(this.state.newRpc) }, }, 'Save'), ]), ]), ]) ) } validateRpc (newRpc) { const { setRpcTarget, displayWarning } = this.props if (validUrl.isWebUri(newRpc)) { setRpcTarget(newRpc) } else { const appendedRpc = `http://${newRpc}` if (validUrl.isWebUri(appendedRpc)) { displayWarning('URIs require the appropriate HTTP/HTTPS prefix.') } else { displayWarning('Invalid RPC URI') } } } renderStateLogs () { return ( h('div.settings__content-row', [ h('div.settings__content-item', [ h('div', 'State Logs'), h( 'div.settings__content-description', 'State logs contain your public account addresses and sent transactions.' ), ]), h('div.settings__content-item', [ h('div.settings__content-item-col', [ h('button.settings__clear-button', { onClick (event) { exportAsFile('MetaMask State Logs', window.logState()) }, }, 'Download State Logs'), ]), ]), ]) ) } renderSeedWords () { const { revealSeedConfirmation } = this.props return ( h('div.settings__content-row', [ h('div.settings__content-item', 'Reveal Seed Words'), h('div.settings__content-item', [ h('div.settings__content-item-col', [ h('button.settings__clear-button.settings__clear-button--red', { onClick (event) { event.preventDefault() revealSeedConfirmation() }, }, 'Reveal Seed Words'), ]), ]), ]) ) } renderSettingsContent () { const { warning } = this.props return ( h('div.settings__content', [ warning && h('div.settings__error', warning), this.renderCurrentConversion(), this.renderCurrentProvider(), this.renderNewRpcUrl(), this.renderStateLogs(), this.renderSeedWords(), ]) ) } renderInfoContent () { } render () { const { goHome } = this.props const { activeTab } = this.state return ( h('.main-container.settings', {}, [ h('.settings__header', [ h('div.settings__close-button', { onClick: goHome, }), this.renderTabs(), ]), activeTab === 'settings' ? this.renderSettingsContent() : this.renderInfoContent(), ]) ) } } const mapStateToProps = state => { return { metamask: state.metamask, warning: state.appState.warning, } } const mapDispatchToProps = dispatch => { return { goHome: () => dispatch(actions.goHome()), setCurrentCurrency: currency => dispatch(actions.setCurrentCurrency(currency)), setRpcTarget: newRpc => dispatch(actions.setRpcTarget(newRpc)), displayWarning: warning => dispatch(actions.displayWarning(warning)), revealSeedConfirmation: () => dispatch(actions.revealSeedConfirmation()), } } module.exports = connect(mapStateToProps, mapDispatchToProps)(Settings)