Merge branch 'i328-MultiVault' of github.com:MetaMask/metamask-plugin into i328-MultiVault

feature/default_network_editable
Dan Finlay 8 years ago
commit 4352c7031a
  1. 2
      .eslintrc
  2. 8
      CHANGELOG.md
  3. 2
      app/manifest.json
  4. 6
      app/scripts/contentscript.js
  5. 55
      app/scripts/keyring-controller.js
  6. 22
      app/scripts/keyrings/hd.js
  7. 1
      app/scripts/keyrings/simple.js
  8. 1
      app/scripts/lib/auto-reload.js
  9. 9
      app/scripts/lib/config-manager.js
  10. 2
      app/scripts/lib/encryptor.js
  11. 26
      app/scripts/lib/idStore.js
  12. 4
      app/scripts/lib/notifications.js
  13. 5
      app/scripts/lib/sig-util.js
  14. 31
      app/scripts/metamask-controller.js
  15. 2
      development/states.js
  16. 2
      development/states.json
  17. 2
      development/states/account-detail-with-shapeshift-tx.json
  18. 2
      development/states/account-detail-with-transaction-history.json
  19. 2
      development/states/account-detail.json
  20. 2
      development/states/accounts.json
  21. 2
      development/states/config.json
  22. 2
      development/states/create-vault-password.json
  23. 2
      development/states/custom-rpc.json
  24. 2
      development/states/empty-account-detail.json
  25. 2
      development/states/first-time.json
  26. 2
      development/states/help.json
  27. 2
      development/states/locked.json
  28. 2
      development/states/new-vault.json
  29. 2
      development/states/pending-crash.json
  30. 2
      development/states/pending-signature.json
  31. 2
      development/states/pending-tx-contract.json
  32. 2
      development/states/pending-tx-send-coin.json
  33. 2
      development/states/pending-tx-value.json
  34. 2
      development/states/restore-vault.json
  35. 2
      development/states/send.json
  36. 2
      development/states/shapeshift.json
  37. 2
      development/states/show-seed-words.json
  38. 28
      test/unit/config-manager-test.js
  39. 10
      test/unit/idStore-test.js
  40. 5
      test/unit/keyring-controller-test.js
  41. 6
      test/unit/keyrings/hd-test.js
  42. 44
      ui/app/actions.js
  43. 8
      ui/app/app.js
  44. 6
      ui/app/components/coinbase-form.js
  45. 2
      ui/app/components/copyButton.js
  46. 6
      ui/app/components/drop-menu-item.js
  47. 2
      ui/app/components/network.js
  48. 9
      ui/app/components/pending-tx.js
  49. 4
      ui/app/components/shapeshift-form.js
  50. 1
      ui/app/components/shift-list-item.js
  51. 2
      ui/app/components/tooltip.js
  52. 6
      ui/app/conf-tx.js
  53. 18
      ui/app/keychains/hd/recover-seed/confirmation.js
  54. 1
      ui/app/reducers/app.js
  55. 2
      ui/app/reducers/metamask.js
  56. 3
      ui/lib/contract-namer.js

@ -127,7 +127,7 @@
"no-whitespace-before-property": 2,
"no-with": 2,
"one-var": [2, { "initialized": "never" }],
"operator-linebreak": [1, "after", { "overrides": { "?": "before", ":": "before" } }],
"operator-linebreak": [1, "after", { "overrides": { "?": "ignore", ":": "ignore" } }],
"padded-blocks": [1, "never"],
"quotes": [2, "single", {"avoidEscape": true, "allowTemplateLiterals": true}],
"semi": [2, "never"],

@ -1,8 +1,14 @@
# Changelog
## Current Master
- Show a warning when a transaction fails during simulation.
- Fix bug where 20% of gas estimate was not being added properly.
- Render error messages in our confirmation screen more gracefully.
- Fix gas estimation bug.
## 2.13.7 2016-11-8
- Fix bug where gas estimate would sometimes be very high.
- Increased our gas estimate from 100k gas to 20% of estimate.
- Fix github link on info page to point at current repository.
## 2.13.6 2016-10-26

@ -1,7 +1,7 @@
{
"name": "MetaMask",
"short_name": "Metamask",
"version": "2.13.6",
"version": "2.13.7",
"manifest_version": 2,
"author": "https://metamask.io",
"description": "Ethereum Browser Extension",

@ -6,7 +6,7 @@ const extension = require('./lib/extension')
const fs = require('fs')
const path = require('path')
const inpageText = fs.readFileSync(path.join(__dirname + '/inpage.js')).toString()
const inpageText = fs.readFileSync(path.join(__dirname, 'inpage.js')).toString()
// Eventually this streaming injection could be replaced with:
// https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Language_Bindings/Components.utils.exportFunction
@ -22,7 +22,6 @@ if (shouldInjectWeb3()) {
function setupInjection () {
try {
// inject in-page script
var scriptTag = document.createElement('script')
scriptTag.src = extension.extension.getURL('scripts/inpage.js')
@ -31,14 +30,12 @@ function setupInjection(){
var container = document.head || document.documentElement
// append as first child
container.insertBefore(scriptTag, container.children[0])
} catch (e) {
console.error('Metamask injection failed.', e)
}
}
function setupStreams () {
// setup communication to page and plugin
var pageStream = new LocalMessageDuplexStream({
name: 'contentscript',
@ -65,7 +62,6 @@ function setupStreams(){
mx.ignoreStream('provider')
mx.ignoreStream('publicConfig')
mx.ignoreStream('reload')
}
function shouldInjectWeb3 () {

@ -1,17 +1,17 @@
const async = require('async')
const EventEmitter = require('events').EventEmitter
const encryptor = require('./lib/encryptor')
const messageManager = require('./lib/message-manager')
const ethUtil = require('ethereumjs-util')
const ethBinToOps = require('eth-bin-to-ops')
const EthQuery = require('eth-query')
const BN = ethUtil.BN
const Transaction = require('ethereumjs-tx')
const autoFaucet = require('./lib/auto-faucet')
const bip39 = require('bip39')
const Transaction = require('ethereumjs-tx')
const EventEmitter = require('events').EventEmitter
// TEMPORARY UNTIL FULL DEPRECATION:
const normalize = require('./lib/sig-util').normalize
const encryptor = require('./lib/encryptor')
const messageManager = require('./lib/message-manager')
const autoFaucet = require('./lib/auto-faucet')
const IdStoreMigrator = require('./lib/idStore-migrator')
const BN = ethUtil.BN
// Keyrings:
const SimpleKeyring = require('./keyrings/simple')
@ -27,7 +27,6 @@ module.exports = class KeyringController extends EventEmitter {
constructor (opts) {
super()
this.web3 = opts.web3
this.configManager = opts.configManager
this.ethStore = opts.ethStore
this.encryptor = encryptor
@ -39,7 +38,7 @@ module.exports = class KeyringController extends EventEmitter {
this._unconfTxCbs = {}
this._unconfMsgCbs = {}
this.network = opts.network
this.getNetwork = opts.getNetwork
// TEMPORARY UNTIL FULL DEPRECATION:
this.idStoreMigrator = new IdStoreMigrator({
@ -57,7 +56,7 @@ module.exports = class KeyringController extends EventEmitter {
seedWords: this.configManager.getSeedWords(),
isInitialized: (!!wallet || !!vault),
isUnlocked: !!this.key,
isConfirmed: true, // AUDIT this.configManager.getConfirmed(),
isDisclaimerConfirmed: this.configManager.getConfirmedDisclaimer(), // AUDIT this.configManager.getConfirmedDisclaimer(),
unconfTxs: this.configManager.unconfirmedTxs(),
transactions: this.configManager.getTxList(),
unconfMsgs: messageManager.unconfirmedMsgs(),
@ -99,7 +98,7 @@ module.exports = class KeyringController extends EventEmitter {
if (err) return cb(err)
this.addNewKeyring('HD Key Tree', {
mnemonic: seed,
n: 1,
numberOfAccounts: 1,
}, (err) => {
if (err) return cb(err)
const firstKeyring = this.keyrings[0]
@ -110,7 +109,7 @@ module.exports = class KeyringController extends EventEmitter {
this.setupAccounts(accounts)
this.emit('update')
cb(null, this.getState())
cb()
})
})
}
@ -145,7 +144,7 @@ module.exports = class KeyringController extends EventEmitter {
return this.persistAllKeyrings()
})
.then(() => {
cb(null)
cb()
})
.catch((err) => {
cb(err)
@ -154,19 +153,18 @@ module.exports = class KeyringController extends EventEmitter {
createFirstKeyTree (password, cb) {
this.clearKeyrings()
this.addNewKeyring('HD Key Tree', {n: 1}, (err) => {
const firstKeyring = this.keyrings[0]
const accounts = firstKeyring.getAccounts()
this.addNewKeyring('HD Key Tree', {numberOfAccounts: 1}, (err) => {
const accounts = this.keyrings[0].getAccounts()
const firstAccount = accounts[0]
const hexAccount = normalize(firstAccount)
const seedWords = firstKeyring.serialize().mnemonic
this.configManager.setSelectedAccount(firstAccount)
this.configManager.setSeedWords(seedWords)
this.placeSeedWords()
autoFaucet(hexAccount)
this.setupAccounts(accounts)
this.persistAllKeyrings()
.then(() => {
cb(err, this.getState())
cb(err)
})
.catch((reason) => {
cb(reason)
@ -174,7 +172,7 @@ module.exports = class KeyringController extends EventEmitter {
})
}
placeSeedWords (cb) {
placeSeedWords () {
const firstKeyring = this.keyrings[0]
const seedWords = firstKeyring.serialize().mnemonic
this.configManager.setSeedWords(seedWords)
@ -216,7 +214,7 @@ module.exports = class KeyringController extends EventEmitter {
this.setupAccounts(accounts)
this.persistAllKeyrings()
.then(() => {
cb(null, this.getState())
cb()
})
.catch((reason) => {
cb(reason)
@ -229,7 +227,7 @@ module.exports = class KeyringController extends EventEmitter {
this.setupAccounts(accounts)
this.persistAllKeyrings()
.then(() => {
cb(null, this.getState())
cb()
})
.catch((reason) => {
cb(reason)
@ -239,13 +237,13 @@ module.exports = class KeyringController extends EventEmitter {
setupAccounts (accounts) {
var arr = accounts || this.getAccounts()
arr.forEach((account) => {
this.loadBalanceAndNickname(account)
this.getBalanceAndNickname(account)
})
}
// Takes an account address and an iterator representing
// the current number of named accounts.
loadBalanceAndNickname(account) {
getBalanceAndNickname (account) {
const address = normalize(account)
this.ethStore.addAccount(address)
this.createNickname(address)
@ -345,13 +343,14 @@ module.exports = class KeyringController extends EventEmitter {
var time = (new Date()).getTime()
var txId = createId()
txParams.metamaskId = txId
txParams.metamaskNetworkId = this.network
txParams.metamaskNetworkId = this.getNetwork()
var txData = {
id: txId,
txParams: txParams,
time: time,
status: 'unconfirmed',
gasMultiplier: configManager.getGasMultiplier() || 1,
metamaskNetworkId: this.getNetwork(),
}
@ -521,6 +520,7 @@ module.exports = class KeyringController extends EventEmitter {
setLocked (cb) {
this.key = null
this.keyrings = []
this.emit('update')
cb()
}
@ -564,9 +564,4 @@ module.exports = class KeyringController extends EventEmitter {
}
function normalize(address) {
if (!address) return
return ethUtil.addHexPrefix(address.toLowerCase())
}
function noop () {}

@ -2,9 +2,10 @@ const EventEmitter = require('events').EventEmitter
const hdkey = require('ethereumjs-wallet/hdkey')
const bip39 = require('bip39')
const ethUtil = require('ethereumjs-util')
const type = 'HD Key Tree'
const sigUtil = require('../lib/sig-util')
const type = 'HD Key Tree'
const hdPathString = `m/44'/60'/0'/0`
module.exports = class HdKeyring extends EventEmitter {
@ -29,8 +30,8 @@ module.exports = class HdKeyring extends EventEmitter {
this.initFromMnemonic(opts.mnemonic)
}
if ('n' in opts) {
this.addAccounts(opts.n)
if ('numberOfAccounts' in opts) {
this.addAccounts(opts.numberOfAccounts)
}
}
@ -44,7 +45,7 @@ module.exports = class HdKeyring extends EventEmitter {
serialize () {
return {
mnemonic: this.mnemonic,
n: this.wallets.length,
numberOfAccounts: this.wallets.length,
}
}
@ -53,14 +54,14 @@ module.exports = class HdKeyring extends EventEmitter {
return wallet.getPrivateKey().toString('hex')
}
addAccounts(n = 1) {
addAccounts (numberOfAccounts = 1) {
if (!this.root) {
this.initFromMnemonic(bip39.generateMnemonic())
}
const oldLen = this.wallets.length
const newWallets = []
for (let i = oldLen; i < n + oldLen; i++) {
for (let i = oldLen; i < numberOfAccounts + oldLen; i++) {
const child = this.root.deriveChild(i)
const wallet = child.getWallet()
newWallets.push(wallet)
@ -94,14 +95,7 @@ module.exports = class HdKeyring extends EventEmitter {
getWalletForAccount (account) {
return this.wallets.find((w) => {
const address = w.getAddress().toString('hex')
return ((address === account) || (normalize(address) === account))
return ((address === account) || (sigUtil.normalize(address) === account))
})
}
}
function normalize(address) {
return ethUtil.addHexPrefix(address.toLowerCase())
}

@ -65,4 +65,3 @@ module.exports = class SimpleKeyring extends EventEmitter {
}
}

@ -25,7 +25,6 @@ function setupDappAutoReload (web3) {
// reload after short timeout
setTimeout(triggerReset, 500)
}
}
// reload the page

@ -313,15 +313,15 @@ ConfigManager.prototype._emitUpdates = function (state) {
})
}
ConfigManager.prototype.setConfirmed = function (confirmed) {
ConfigManager.prototype.setConfirmedDisclaimer = function (confirmed) {
var data = this.getData()
data.isConfirmed = confirmed
data.isDisclaimerConfirmed = confirmed
this.setData(data)
}
ConfigManager.prototype.getConfirmed = function () {
ConfigManager.prototype.getConfirmedDisclaimer = function () {
var data = this.getData()
return ('isConfirmed' in data) && data.isConfirmed
return ('isDisclaimerConfirmed' in data) && data.isDisclaimerConfirmed
}
ConfigManager.prototype.setTOSHash = function (hash) {
@ -358,7 +358,6 @@ ConfigManager.prototype.updateConversionRate = function () {
this.setConversionPrice(0)
this.setConversionDate('N/A')
})
}
ConfigManager.prototype.setConversionPrice = function (price) {

@ -26,7 +26,7 @@ module.exports = {
generateSalt,
}
// Takes a Pojo, returns encrypted text.
// Takes a Pojo, returns cypher text.
function encrypt (password, dataObj) {
return keyFromPassword(password)
.then(function (passwordDerivedKey) {

@ -102,7 +102,7 @@ IdentityStore.prototype.getState = function () {
isInitialized: !!configManager.getWallet() && !seedWords,
isUnlocked: this._isUnlocked(),
seedWords: seedWords,
isConfirmed: configManager.getConfirmed(),
isDisclaimerConfirmed: configManager.getConfirmedDisclaimer(),
unconfTxs: configManager.unconfirmedTxs(),
transactions: configManager.getTxList(),
unconfMsgs: messageManager.unconfirmedMsgs(),
@ -246,7 +246,7 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
function analyzeForDelegateCall (cb) {
if (txParams.to) {
query.getCode(txParams.to, (err, result) => {
if (err) return cb(err)
if (err) return cb(err.message || err)
var containsDelegateCall = self.checkForDelegateCall(result)
txData.containsDelegateCall = containsDelegateCall
cb()
@ -257,15 +257,30 @@ IdentityStore.prototype.addUnconfirmedTransaction = function (txParams, onTxDone
}
function estimateGas (cb) {
query.estimateGas(txParams, function(err, result){
var estimationParams = extend(txParams)
// 1 billion gas for estimation
var gasLimit = '0x3b9aca00'
estimationParams.gas = gasLimit
query.estimateGas(estimationParams, function (err, result) {
if (err) return cb(err.message || err)
if (result === estimationParams.gas) {
txData.simulationFails = true
query.getBlockByNumber('latest', true, function (err, block) {
if (err) return cb(err)
txData.estimatedGas = block.gasLimit
txData.txParams.gas = block.gasLimit
cb()
})
return
}
txData.estimatedGas = self.addGasBuffer(result)
txData.txParams.gas = txData.estimatedGas
cb()
})
}
function didComplete (err) {
if (err) return cb(err)
if (err) return cb(err.message || err)
configManager.addTx(txData)
// signal update
self._didUpdate()
@ -285,9 +300,10 @@ IdentityStore.prototype.checkForDelegateCall = function (codeHex) {
}
}
const gasBuffer = new BN('100000', 10)
IdentityStore.prototype.addGasBuffer = function (gas) {
const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16)
const five = new BN('5', 10)
const gasBuffer = bnGas.div(five)
const correct = bnGas.add(gasBuffer)
return ethUtil.addHexPrefix(correct.toString(16))
}

@ -15,12 +15,9 @@ function show () {
if (err) throw err
if (popup) {
// bring focus to existing popup
extension.windows.update(popup.id, { focused: true })
} else {
// create new popup
extension.windows.create({
url: 'notification.html',
@ -29,7 +26,6 @@ function show () {
width,
height,
})
}
})
}

@ -12,6 +12,11 @@ module.exports = {
return ethUtil.addHexPrefix(rStr.concat(sStr, vStr)).toString('hex')
},
normalize: function (address) {
if (!address) return
return ethUtil.addHexPrefix(address.toLowerCase())
},
}
function padWithZeroes (number, length) {

@ -17,6 +17,7 @@ module.exports = class MetamaskController {
this.configManager = new ConfigManager(opts)
this.keyringController = new KeyringController({
configManager: this.configManager,
getNetwork: this.getStateNetwork.bind(this),
})
this.provider = this.initializeProvider(opts)
this.ethStore = new EthStore(this.provider)
@ -86,23 +87,6 @@ module.exports = class MetamaskController {
}
onRpcRequest (stream, originDomain, request) {
/* Commented out for Parity compliance
* Parity does not permit additional keys, like `origin`,
* and Infura is not currently filtering this key out.
var payloads = Array.isArray(request) ? request : [request]
payloads.forEach(function (payload) {
// Append origin to rpc payload
payload.origin = originDomain
// Append origin to signature request
if (payload.method === 'eth_sendTransaction') {
payload.params[0].origin = originDomain
} else if (payload.method === 'eth_sign') {
payload.params.push({ origin: originDomain })
}
})
*/
// handle rpc request
this.provider.sendAsync(request, function onPayloadHandled (err, response) {
logger(err, request, response)
@ -215,10 +199,8 @@ module.exports = class MetamaskController {
newUnsignedTransaction (txParams, onTxDoneCb) {
const keyringController = this.keyringController
let err = this.enforceTxValidations(txParams)
const err = this.enforceTxValidations(txParams)
if (err) return onTxDoneCb(err)
keyringController.addUnconfirmedTransaction(txParams, onTxDoneCb, (err, txData) => {
if (err) return onTxDoneCb(err)
this.sendUpdate()
@ -291,12 +273,11 @@ module.exports = class MetamaskController {
} catch (e) {
console.error('Error in checking TOS change.')
}
}
agreeToDisclaimer (cb) {
try {
this.configManager.setConfirmed(true)
this.configManager.setConfirmedDisclaimer(true)
cb()
} catch (e) {
cb(e)
@ -305,7 +286,7 @@ module.exports = class MetamaskController {
resetDisclaimer () {
try {
this.configManager.setConfirmed(false)
this.configManager.setConfirmedDisclaimer(false)
} catch (e) {
console.error(e)
}
@ -400,4 +381,8 @@ module.exports = class MetamaskController {
cb(e)
}
}
getStateNetwork () {
return this.state.network
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -136,7 +136,7 @@
"selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
"network": "1",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"provider": {

@ -102,7 +102,7 @@
"selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
"network": "2",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"provider": {

@ -60,7 +60,7 @@
"selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
"network": "2",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"provider": {

@ -91,7 +91,7 @@
"transactions": [],
"selectedAddress": "0x0abdd95cafcabec9b3e99dcd09fc4b441037cb80",
"network": "2",
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"shapeShiftTxList": [],

@ -59,7 +59,7 @@
"transactions": [],
"selectedAddress": "0x843963b837841dad3b0f5969ff271108776616df",
"network": "2",
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"provider": {

@ -10,7 +10,7 @@
"transactions": [],
"network": "2",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"provider": {

@ -160,7 +160,7 @@
"selectedAddress": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825",
"network": "166",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"provider": {

@ -57,7 +57,7 @@
"selectedAddress": "0x0dcd5d886577d5081b0c52e242ef29e70be3e7bc",
"network": "2",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"provider": {

@ -11,7 +11,7 @@
"network": null,
"accounts": {},
"transactions": [],
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"shapeShiftTxList": [],

@ -55,7 +55,7 @@
},
"transactions": [],
"network": "2",
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"provider": {

@ -14,7 +14,7 @@
"selectedAddress": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825",
"network": "1473186153102",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"shapeShiftTxList": [],

@ -10,7 +10,7 @@
"transactions": [],
"network": "2",
"seedWords": null,
"isConfirmed": false,
"isDisclaimerConfirmed": false,
"unconfMsgs": {},
"messages": [],
"provider": {

File diff suppressed because one or more lines are too long

@ -354,7 +354,7 @@
"selectedAddress": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825",
"network": "1471904489432",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {
"1472076978535283": {
"id": 1472076978535283,

File diff suppressed because one or more lines are too long

@ -1 +1 @@
{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"name":"Wallet 1","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","mayBeFauceting":false},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"name":"Wallet 2","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb","mayBeFauceting":false},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"name":"Wallet 3","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d","mayBeFauceting":false}},"unconfTxs":{"1467868023090690":{"id":1467868023090690,"txParams":{"data":"0xa9059cbb0000000000000000000000008deb4d106090c3eb8f1950f727e87c4f884fb06f0000000000000000000000000000000000000000000000000000000000000064","from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","value":"0x16345785d8a0000","to":"0xbeb0ed3034c4155f3d16a64a5c5e7c8d4ea9e9c9","origin":"MetaMask","metamaskId":1467868023090690,"metamaskNetworkId":"2"},"time":1467868023090,"status":"unconfirmed","containsDelegateCall":false}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"code":"0x","balance":"0x38326dc32cf80800","nonce":"0x10000c","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"code":"0x","balance":"0x15e578bd8e9c8000","nonce":"0x100000","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"code":"0x","nonce":"0x100000","balance":"0x2386f26fc10000","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d"}},"transactions":[],"selectedAddress":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"2","seedWords":null,"isConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}}
{"metamask":{"isInitialized":true,"isUnlocked":true,"currentDomain":"example.com","rpcTarget":"https://rawtestrpc.metamask.io/","identities":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"name":"Wallet 1","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","mayBeFauceting":false},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"name":"Wallet 2","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb","mayBeFauceting":false},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"name":"Wallet 3","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d","mayBeFauceting":false}},"unconfTxs":{"1467868023090690":{"id":1467868023090690,"txParams":{"data":"0xa9059cbb0000000000000000000000008deb4d106090c3eb8f1950f727e87c4f884fb06f0000000000000000000000000000000000000000000000000000000000000064","from":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","value":"0x16345785d8a0000","to":"0xbeb0ed3034c4155f3d16a64a5c5e7c8d4ea9e9c9","origin":"MetaMask","metamaskId":1467868023090690,"metamaskNetworkId":"2"},"time":1467868023090,"status":"unconfirmed","containsDelegateCall":false}},"accounts":{"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825":{"code":"0x","balance":"0x38326dc32cf80800","nonce":"0x10000c","address":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb":{"code":"0x","balance":"0x15e578bd8e9c8000","nonce":"0x100000","address":"0xc5b8dbac4c1d3f152cdeb400e2313f309c410acb"},"0x2f8d4a878cfa04a6e60d46362f5644deab66572d":{"code":"0x","nonce":"0x100000","balance":"0x2386f26fc10000","address":"0x2f8d4a878cfa04a6e60d46362f5644deab66572d"}},"transactions":[],"selectedAddress":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825","network":"2","seedWords":null,"isDisclaimerConfirmed":true,"unconfMsgs":{},"messages":[],"provider":{"type":"testnet"},"selectedAccount":"0xfdea65c8e26263f6d9a1b5de9555d2931a33b825"},"appState":{"menuOpen":false,"currentView":{"name":"confTx","context":0},"accountDetail":{"subview":"transactions"},"currentDomain":"extensions","transForward":true,"isLoading":false,"warning":null},"identities":{}}

File diff suppressed because one or more lines are too long

@ -12,7 +12,7 @@
"accounts": {},
"transactions": [],
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"shapeShiftTxList": [],

@ -48,7 +48,7 @@
"transactions": [],
"network": "2",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"shapeShiftTxList": [],

@ -49,7 +49,7 @@
"selectedAddress": "0xfdea65c8e26263f6d9a1b5de9555d2931a33b825",
"network": "1",
"seedWords": null,
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"shapeShiftTxList": [],

@ -45,7 +45,7 @@
"transactions": [],
"network": "2",
"seedWords": "debris dizzy just program just float decrease vacant alarm reduce speak stadium",
"isConfirmed": true,
"isDisclaimerConfirmed": true,
"unconfMsgs": {},
"messages": [],
"provider": {

@ -100,31 +100,31 @@ describe('config-manager', function() {
describe('confirmation', function() {
describe('#getConfirmed', function() {
describe('#getConfirmedDisclaimer', function() {
it('should return false if no previous key exists', function() {
var result = configManager.getConfirmed()
var result = configManager.getConfirmedDisclaimer()
assert.ok(!result)
})
})
describe('#setConfirmed', function() {
it('should make getConfirmed return true once set', function() {
assert.equal(configManager.getConfirmed(), false)
configManager.setConfirmed(true)
var result = configManager.getConfirmed()
describe('#setConfirmedDisclaimer', function() {
it('should make getConfirmedDisclaimer return true once set', function() {
assert.equal(configManager.getConfirmedDisclaimer(), false)
configManager.setConfirmedDisclaimer(true)
var result = configManager.getConfirmedDisclaimer()
assert.equal(result, true)
})
it('should be able to set false', function() {
configManager.setConfirmed(false)
var result = configManager.getConfirmed()
configManager.setConfirmedDisclaimer(false)
var result = configManager.getConfirmedDisclaimer()
assert.equal(result, false)
})
it('should persist to local storage', function() {
configManager.setConfirmed(true)
configManager.setConfirmedDisclaimer(true)
var data = configManager.getData()
assert.equal(data.isConfirmed, true)
assert.equal(data.isDisclaimerConfirmed, true)
})
})
})
@ -153,7 +153,7 @@ describe('config-manager', function() {
rpcTarget: 'foobar'
},
}
configManager.setConfirmed(true)
configManager.setConfirmedDisclaimer(true)
configManager.setConfig(testConfig)
var testWallet = {
@ -164,7 +164,7 @@ describe('config-manager', function() {
var result = configManager.getData()
assert.equal(result.wallet.name, testWallet.name, 'wallet name is set')
assert.equal(result.config.provider.rpcTarget, testConfig.provider.rpcTarget)
assert.equal(configManager.getConfirmed(), true)
assert.equal(configManager.getConfirmedDisclaimer(), true)
testConfig.provider.type = 'something else!'
configManager.setConfig(testConfig)
@ -173,7 +173,7 @@ describe('config-manager', function() {
assert.equal(result.wallet.name, testWallet.name, 'wallet name is set')
assert.equal(result.config.provider.rpcTarget, testConfig.provider.rpcTarget)
assert.equal(result.config.provider.type, testConfig.provider.type)
assert.equal(configManager.getConfirmed(), true)
assert.equal(configManager.getConfirmedDisclaimer(), true)
})
})

@ -159,7 +159,7 @@ describe('IdentityStore', function() {
assert.equal(result.indexOf('0x'), 0, 'include hex prefix')
})
it('buffers reasonably', function() {
it('buffers 20%', function() {
const idStore = new IdentityStore({
configManager: configManagerGen(),
ethStore: {
@ -168,20 +168,18 @@ describe('IdentityStore', function() {
})
const gas = '0x04ee59' // Actual estimated gas example
const tooBigOutput = '0x80674f9' // Actual bad output
const bnGas = new BN(ethUtil.stripHexPrefix(gas), 16)
const correctBuffer = new BN('100000', 10)
const five = new BN('5', 10)
const correctBuffer = bnGas.div(five)
const correct = bnGas.add(correctBuffer)
const tooBig = new BN(tooBigOutput, 16)
const result = idStore.addGasBuffer(gas)
const bnResult = new BN(ethUtil.stripHexPrefix(result), 16)
assert.equal(result.indexOf('0x'), 0, 'included hex prefix')
assert(bnResult.gt(bnGas), 'Estimate increased in value.')
assert.equal(bnResult.sub(bnGas).toString(10), '100000', 'added 100k gas')
assert.equal(bnResult.sub(bnGas).toString(10), correctBuffer.toString(10), 'added 20% gas')
assert.equal(result, '0x' + correct.toString(16), 'Added the right amount')
assert.notEqual(result, tooBigOutput, 'not that bad estimate')
})
})

@ -67,12 +67,12 @@ describe('KeyringController', function() {
type: 'HD Key Tree',
data: {
mnemonic: seedWords,
n: 1,
numberOfAccounts: 1,
}
}
const mock = this.sinon.mock(keyringController)
mock.expects('loadBalanceAndNickname')
mock.expects('getBalanceAndNickname')
.exactly(1)
var keyring = keyringController.restoreKeyring(mockSerialized)
@ -170,4 +170,3 @@ describe('KeyringController', function() {
})
})
})

@ -19,7 +19,7 @@ describe('hd-keyring', function() {
describe('constructor', function() {
keyring = new HdKeyring({
mnemonic: sampleMnemonic,
n: 2,
numberOfAccounts: 2,
})
const accounts = keyring.getAccounts()
@ -45,7 +45,7 @@ describe('hd-keyring', function() {
describe('#serialize empty wallets.', function() {
it('serializes a new mnemonic', function() {
const output = keyring.serialize()
assert.equal(output.n, 0)
assert.equal(output.numberOfAccounts, 0)
assert.equal(output.mnemonic, null)
})
})
@ -54,7 +54,7 @@ describe('hd-keyring', function() {
it('serializes what it deserializes', function() {
keyring.deserialize({
mnemonic: sampleMnemonic,
n: 1
numberOfAccounts: 1
})
assert.equal(keyring.wallets.length, 1, 'restores two accounts')
keyring.addAccounts(1)

@ -44,7 +44,6 @@ var actions = {
unlockInProgress: unlockInProgress,
// error handling
displayWarning: displayWarning,
showWarning: showWarning, // alias
DISPLAY_WARNING: 'DISPLAY_WARNING',
HIDE_WARNING: 'HIDE_WARNING',
hideWarning: hideWarning,
@ -167,7 +166,6 @@ function tryUnlockMetamask (password) {
if (err) {
dispatch(actions.unlockFailed(err.message))
} else {
dispatch(this.updateMetamaskState(newState))
let selectedAccount
try {
selectedAccount = newState.metamask.selectedAccount
@ -184,7 +182,7 @@ function confirmSeedWords () {
background.clearSeedWordCache((err, account) => {
dispatch(actions.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err.message))
return dispatch(actions.displayWarning(err.message))
}
console.log('Seed word cache cleared. ' + account)
@ -196,23 +194,19 @@ function confirmSeedWords () {
function createNewVaultAndRestore (password, seed) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
background.createNewVaultAndRestore(password, seed, (err, newState) => {
background.createNewVaultAndRestore(password, seed, (err) => {
dispatch(actions.hideLoadingIndication())
if (err) return dispatch(actions.displayWarning(err.message))
dispatch(this.updateMetamaskState(newState))
})
}
}
function createNewVaultAndKeychain (password, entropy) {
return (dispatch) => {
background.createNewVaultAndKeychain(password, entropy, (err, newState) => {
background.createNewVaultAndKeychain(password, entropy, (err) => {
if (err) {
return dispatch(actions.showWarning(err.message))
}
dispatch(this.updateMetamaskState(newState))
dispatch(this.showNewVaultSeed())
})
}
}
@ -226,11 +220,10 @@ function revealSeedConfirmation () {
function requestRevealSeed (password) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
background.submitPassword(password, (err, newState) => {
background.submitPassword(password, (err) => {
dispatch(actions.hideLoadingIndication())
if (err) return dispatch(actions.displayWarning(err.message))
background.placeSeedWords()
dispatch(actions.showNewVaultSeed())
})
}
}
@ -239,13 +232,11 @@ function requestRevealSeed (password) {
function addNewKeyring (type, opts) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
background.addNewKeyring(type, opts, (err, newState) => {
background.addNewKeyring(type, opts, (err) => {
dispatch(this.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err))
}
dispatch(this.updateMetamaskState(newState))
dispatch(this.showAccountsPage())
})
}
}
@ -253,12 +244,11 @@ function addNewKeyring (type, opts) {
function addNewAccount (ringNumber = 0) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
background.addNewAccount(ringNumber, (err, newState) => {
background.addNewAccount(ringNumber, (err) => {
dispatch(this.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err))
}
dispatch(this.updateMetamaskState(newState))
})
}
}
@ -384,7 +374,7 @@ function agreeToDisclaimer () {
dispatch(this.showLoadingIndication())
background.agreeToDisclaimer((err) => {
if (err) {
return dispatch(actions.showWarning(err.message))
return dispatch(actions.displayWarning(err.message))
}
dispatch(this.hideLoadingIndication())
@ -456,12 +446,8 @@ function lockMetamask () {
background.setLocked((err) => {
dispatch(actions.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err.message))
return dispatch(actions.displayWarning(err.message))
}
dispatch({
type: actions.LOCK_METAMASK,
})
})
}
}
@ -472,7 +458,7 @@ function showAccountDetail (address) {
background.setSelectedAddress(address, (err, address) => {
dispatch(actions.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err.message))
return dispatch(actions.displayWarning(err.message))
}
dispatch({
@ -586,10 +572,6 @@ function hideSubLoadingIndication () {
}
}
function showWarning (text) {
return this.displayWarning(text)
}
function displayWarning (text) {
return {
type: actions.DISPLAY_WARNING,
@ -641,7 +623,7 @@ function saveAccountLabel (account, label) {
background.saveAccountLabel(account, label, (err) => {
dispatch(actions.hideLoadingIndication())
if (err) {
return dispatch(actions.showWarning(err.message))
return dispatch(actions.displayWarning(err.message))
}
dispatch({
type: actions.SAVE_ACCOUNT_LABEL,
@ -717,7 +699,7 @@ function shapeShiftSubview (network) {
shapeShiftRequest('marketinfo', {pair}, (mktResponse) => {
shapeShiftRequest('getcoins', {}, (response) => {
dispatch(actions.hideSubLoadingIndication())
if (mktResponse.error) return dispatch(actions.showWarning(mktResponse.error))
if (mktResponse.error) return dispatch(actions.displayWarning(mktResponse.error))
dispatch({
type: actions.SHAPESHIFT_SUBVIEW,
value: {
@ -734,7 +716,7 @@ function coinShiftRquest (data, marketData) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
shapeShiftRequest('shift', { method: 'POST', data}, (response) => {
if (response.error) return dispatch(actions.showWarning(response.error))
if (response.error) return dispatch(actions.displayWarning(response.error))
var message = `
Deposit your ${response.depositType} to the address bellow:`
background.createShapeShiftTx(response.deposit, response.depositType)
@ -756,7 +738,7 @@ function reshowQrCode (data, coin) {
return (dispatch) => {
dispatch(actions.showLoadingIndication())
shapeShiftRequest('marketinfo', {pair: `${coin.toLowerCase()}_eth`}, (mktResponse) => {
if (mktResponse.error) return dispatch(actions.showWarning(mktResponse.error))
if (mktResponse.error) return dispatch(actions.displayWarning(mktResponse.error))
var message = [
`Deposit your ${coin} to the address bellow:`,

@ -39,7 +39,7 @@ function mapStateToProps (state) {
return {
// state from plugin
isLoading: state.appState.isLoading,
isConfirmed: state.metamask.isConfirmed,
isDisclaimerConfirmed: state.metamask.isDisclaimerConfirmed,
isInitialized: state.metamask.isInitialized,
isUnlocked: state.metamask.isUnlocked,
currentView: state.appState.currentView,
@ -98,7 +98,6 @@ App.prototype.render = function () {
}
App.prototype.renderAppBar = function () {
if (window.METAMASK_UI_TYPE === 'notification') {
return null
}
@ -324,7 +323,7 @@ App.prototype.renderBackButton = function (style, justArrow = false) {
App.prototype.renderBackToInitButton = function () {
var props = this.props
var button = null
if (!props.isConfirmed) return button
if (!props.isDisclaimerConfirmed) return button
if (!props.isUnlocked) {
if (props.currentView.name === 'InitMenu') {
@ -357,7 +356,7 @@ App.prototype.renderBackToInitButton = function () {
App.prototype.renderPrimary = function () {
var props = this.props
if (!props.isConfirmed) {
if (!props.isDisclaimerConfirmed) {
return h(DisclaimerScreen, {key: 'disclaimerScreen'})
}
@ -367,7 +366,6 @@ App.prototype.renderPrimary = function () {
// show initialize screen
if (!props.isInitialized || props.forgottenPassword) {
// show current view
switch (props.currentView.name) {

@ -116,15 +116,14 @@ CoinbaseForm.prototype.toCoinbase = function () {
props.dispatch(actions.buyEth(address, props.buyView.amount))
} else if (!isValidAmountforCoinBase(amount).valid) {
message = isValidAmountforCoinBase(amount).message
return props.dispatch(actions.showWarning(message))
return props.dispatch(actions.displayWarning(message))
} else {
message = 'Receiving address is invalid.'
return props.dispatch(actions.showWarning(message))
return props.dispatch(actions.displayWarning(message))
}
}
CoinbaseForm.prototype.renderLoading = function () {
return h('img', {
style: {
width: '27px',
@ -136,7 +135,6 @@ CoinbaseForm.prototype.renderLoading = function () {
function isValidAmountforCoinBase (amount) {
amount = parseFloat(amount)
if (amount) {
if (amount <= 5 && amount > 0) {
return {

@ -51,11 +51,9 @@ CopyButton.prototype.render = function () {
}
CopyButton.prototype.debounceRestore = function () {
this.setState({ copied: true })
clearTimeout(this.timeout)
this.timeout = setTimeout(() => {
this.setState({ copied: false })
}, 850)
}

@ -32,9 +32,9 @@ DropMenuItem.prototype.render = function () {
}
DropMenuItem.prototype.activeNetworkRender = function () {
let activeNetwork = this.props.activeNetworkRender
let { provider } = this.props
let providerType = provider ? provider.type : null
const activeNetwork = this.props.activeNetworkRender
const { provider } = this.props
const providerType = provider ? provider.type : null
if (activeNetwork === undefined) return
switch (this.props.label) {

@ -22,7 +22,6 @@ Network.prototype.render = function () {
let iconName, hoverText
if (networkNumber === 'loading') {
return h('img.network-indicator', {
title: 'Attempting to connect to blockchain.',
onClick: (event) => this.props.onClick(event),
@ -32,7 +31,6 @@ Network.prototype.render = function () {
},
src: 'images/loading.svg',
})
} else if (providerName === 'mainnet') {
hoverText = 'Main Ethereum Network'
iconName = 'ethereum-network'

@ -30,6 +30,15 @@ PendingTx.prototype.render = function () {
}
`),
txData.simulationFails ?
h('.error', {
style: {
marginLeft: 50,
fontSize: '0.9em',
},
}, 'Transaction Error. Exception thrown in contract code.')
: null,
state.insufficientBalance ?
h('span.error', {
style: {

@ -25,7 +25,6 @@ function ShapeshiftForm () {
}
ShapeshiftForm.prototype.render = function () {
return h(ReactCSSTransitionGroup, {
className: 'css-transition-group',
transitionName: 'main',
@ -34,7 +33,6 @@ ShapeshiftForm.prototype.render = function () {
}, [
this.props.qrRequested ? h(Qr, {key: 'qr'}) : this.renderMain(),
])
}
ShapeshiftForm.prototype.renderMain = function () {
@ -244,7 +242,7 @@ ShapeshiftForm.prototype.updateCoin = function (event) {
if (!coinOptions[coin.toUpperCase()] || coin.toUpperCase() === 'ETH') {
var message = 'Not a valid coin'
return props.dispatch(actions.showWarning(message))
return props.dispatch(actions.displayWarning(message))
} else {
return props.dispatch(actions.pairUpdate(coin))
}

@ -26,7 +26,6 @@ function ShiftListItem () {
}
ShiftListItem.prototype.render = function () {
return (
h('.transaction-list-item.flex-row', {
style: {

@ -11,7 +11,6 @@ function Tooltip () {
}
Tooltip.prototype.render = function () {
const props = this.props
const { position, title, children } = props
@ -20,5 +19,4 @@ Tooltip.prototype.render = function () {
title,
fixed: false,
}, children)
}

@ -170,6 +170,10 @@ function warningIfExists (warning) {
if (warning &&
// Do not display user rejections on this screen:
warning.indexOf('User denied transaction signature') === -1) {
return h('span.error', { style: { margin: 'auto' } }, warning)
return h('.error', {
style: {
margin: 'auto',
},
}, warning)
}
}

@ -5,10 +5,10 @@ const connect = require('react-redux').connect
const h = require('react-hyperscript')
const actions = require('../../../actions')
module.exports = connect(mapStateToProps)(RevealSeedConfirmatoin)
module.exports = connect(mapStateToProps)(RevealSeedConfirmation)
inherits(RevealSeedConfirmatoin, Component)
function RevealSeedConfirmatoin () {
inherits(RevealSeedConfirmation, Component)
function RevealSeedConfirmation () {
Component.call(this)
}
@ -18,9 +18,9 @@ function mapStateToProps (state) {
}
}
RevealSeedConfirmatoin.prototype.confirmationPhrase = 'I understand'
RevealSeedConfirmation.prototype.confirmationPhrase = 'I understand'
RevealSeedConfirmatoin.prototype.render = function () {
RevealSeedConfirmation.prototype.render = function () {
const props = this.props
const state = this.state
@ -116,24 +116,24 @@ RevealSeedConfirmatoin.prototype.render = function () {
)
}
RevealSeedConfirmatoin.prototype.componentDidMount = function () {
RevealSeedConfirmation.prototype.componentDidMount = function () {
document.getElementById('password-box').focus()
}
RevealSeedConfirmatoin.prototype.goHome = function () {
RevealSeedConfirmation.prototype.goHome = function () {
this.props.dispatch(actions.showConfigPage(false))
}
// create vault
RevealSeedConfirmatoin.prototype.checkConfirmation = function (event) {
RevealSeedConfirmation.prototype.checkConfirmation = function (event) {
if (event.key === 'Enter') {
event.preventDefault()
this.revealSeedWords()
}
}
RevealSeedConfirmatoin.prototype.revealSeedWords = function () {
RevealSeedConfirmation.prototype.revealSeedWords = function () {
this.setState({ confirmationWrong: false })
const confirmBox = document.getElementById('confirm-box')

@ -278,7 +278,6 @@ function reduceApp (state, action) {
warning: null,
})
} else {
notification.closePopup()
return extend(appState, {

@ -30,7 +30,7 @@ function reduceMetamask (state, action) {
case actions.AGREE_TO_DISCLAIMER:
return extend(metamaskState, {
isConfirmed: true,
isDisclaimerConfirmed: true,
})
case actions.UNLOCK_METAMASK:

@ -9,7 +9,6 @@
const nicknames = {}
module.exports = function (addr, identities = {}) {
const address = addr.toLowerCase()
const ids = hashFromIdentities(identities)
@ -18,7 +17,7 @@ module.exports = function(addr, identities = {}) {
function hashFromIdentities (identities) {
const result = {}
for (let key in identities) {
for (const key in identities) {
result[key] = identities[key].name
}
return result

Loading…
Cancel
Save