Merge pull request #888 from MetaMask/i844-AsyncKeyrings

Modify Keyring protocol to always return promises for public methods
feature/default_network_editable
Kevin Serrano 8 years ago committed by GitHub
commit feae6235cb
  1. 190
      app/scripts/keyring-controller.js
  2. 17
      app/scripts/keyrings/hd.js
  3. 18
      app/scripts/keyrings/simple.js
  4. 49
      test/unit/keyring-controller-test.js
  5. 69
      test/unit/keyrings/hd-test.js
  6. 37
      test/unit/keyrings/simple-test.js

@ -98,17 +98,20 @@ module.exports = class KeyringController extends EventEmitter {
this.addNewKeyring('HD Key Tree', { this.addNewKeyring('HD Key Tree', {
mnemonic: seed, mnemonic: seed,
numberOfAccounts: 1, numberOfAccounts: 1,
}, (err) => { }).then(() => {
if (err) return cb(err)
const firstKeyring = this.keyrings[0] const firstKeyring = this.keyrings[0]
const accounts = firstKeyring.getAccounts() return firstKeyring.getAccounts()
})
.then((accounts) => {
const firstAccount = accounts[0] const firstAccount = accounts[0]
const hexAccount = normalize(firstAccount) const hexAccount = normalize(firstAccount)
this.configManager.setSelectedAccount(hexAccount) this.configManager.setSelectedAccount(hexAccount)
this.setupAccounts(accounts) this.setupAccounts(accounts)
this.persistAllKeyrings()
this.emit('update') .then(() => {
cb() this.emit('update')
cb(err, this.getState())
})
}) })
}) })
} }
@ -117,14 +120,20 @@ module.exports = class KeyringController extends EventEmitter {
const shouldMigrate = !!this.configManager.getWallet() && !this.configManager.getVault() const shouldMigrate = !!this.configManager.getWallet() && !this.configManager.getVault()
return this.idStoreMigrator.migratedVaultForPassword(password) return this.idStoreMigrator.migratedVaultForPassword(password)
.then((serialized) => { .then((serialized) => {
this.password = password
if (serialized && shouldMigrate) { if (serialized && shouldMigrate) {
this.password = password return this.restoreKeyring(serialized)
const keyring = this.restoreKeyring(serialized) .then((keyring) => {
this.keyrings.push(keyring) return keyring.getAccounts()
this.configManager.setSelectedAccount(keyring.getAccounts()[0]) })
return this.persistAllKeyrings() .then((accounts) => {
this.configManager.setSelectedAccount(accounts[0])
return this.persistAllKeyrings()
})
} else {
return Promise.resolve()
} }
return
}) })
} }
@ -145,17 +154,20 @@ module.exports = class KeyringController extends EventEmitter {
createFirstKeyTree (password, cb) { createFirstKeyTree (password, cb) {
this.clearKeyrings() this.clearKeyrings()
this.addNewKeyring('HD Key Tree', {numberOfAccounts: 1}, (err) => { this.addNewKeyring('HD Key Tree', {numberOfAccounts: 1}, (err) => {
const accounts = this.keyrings[0].getAccounts() if (err) return cb(err)
const firstAccount = accounts[0] this.keyrings[0].getAccounts()
const hexAccount = normalize(firstAccount) .then((accounts) => {
this.configManager.setSelectedAccount(firstAccount) const firstAccount = accounts[0]
const hexAccount = normalize(firstAccount)
this.configManager.setSelectedAccount(firstAccount)
this.placeSeedWords() this.placeSeedWords()
this.emit('newAccount', hexAccount) this.emit('newAccount', hexAccount)
this.setupAccounts(accounts) this.setupAccounts(accounts)
this.persistAllKeyrings() return this.persistAllKeyrings()
})
.then(() => { .then(() => {
cb(err) cb()
}) })
.catch((reason) => { .catch((reason) => {
cb(reason) cb(reason)
@ -165,13 +177,17 @@ module.exports = class KeyringController extends EventEmitter {
placeSeedWords (cb) { placeSeedWords (cb) {
const firstKeyring = this.keyrings[0] const firstKeyring = this.keyrings[0]
const seedWords = firstKeyring.serialize().mnemonic firstKeyring.serialize()
this.configManager.setSeedWords(seedWords) .then((serialized) => {
const seedWords = serialized.mnemonic
this.configManager.setSeedWords(seedWords)
if (cb) { if (cb) {
cb() cb()
} }
this.emit('update')
this.emit('update')
})
} }
submitPassword (password, cb) { submitPassword (password, cb) {
@ -193,24 +209,35 @@ module.exports = class KeyringController extends EventEmitter {
addNewKeyring (type, opts, cb) { addNewKeyring (type, opts, cb) {
const Keyring = this.getKeyringClassForType(type) const Keyring = this.getKeyringClassForType(type)
const keyring = new Keyring(opts) const keyring = new Keyring(opts)
const accounts = keyring.getAccounts() return keyring.getAccounts()
.then((accounts) => {
this.keyrings.push(keyring) this.keyrings.push(keyring)
this.setupAccounts(accounts) return this.setupAccounts(accounts)
this.persistAllKeyrings() }).then(() => {
.then(() => { return this.persistAllKeyrings()
cb() }).then(() => {
if (cb) {
cb(null, keyring)
}
return keyring
}) })
.catch((reason) => { .catch((reason) => {
cb(reason) if (cb) {
cb(reason)
}
return reason
}) })
} }
addNewAccount (keyRingNum = 0, cb) { addNewAccount (keyRingNum = 0, cb) {
const ring = this.keyrings[keyRingNum] const ring = this.keyrings[keyRingNum]
const accounts = ring.addAccounts(1) return ring.addAccounts(1)
this.setupAccounts(accounts) .then((accounts) => {
this.persistAllKeyrings() return this.setupAccounts(accounts)
})
.then(() => {
return this.persistAllKeyrings()
})
.then(() => { .then(() => {
cb() cb()
}) })
@ -220,9 +247,12 @@ module.exports = class KeyringController extends EventEmitter {
} }
setupAccounts (accounts) { setupAccounts (accounts) {
var arr = accounts || this.getAccounts() return this.getAccounts()
arr.forEach((account) => { .then((loadedAccounts) => {
this.getBalanceAndNickname(account) const arr = accounts || loadedAccounts
arr.forEach((account) => {
this.getBalanceAndNickname(account)
})
}) })
} }
@ -259,13 +289,19 @@ module.exports = class KeyringController extends EventEmitter {
} }
persistAllKeyrings () { persistAllKeyrings () {
const serialized = this.keyrings.map((keyring) => { return Promise.all(this.keyrings.map((keyring) => {
return { return Promise.all([keyring.type, keyring.serialize()])
type: keyring.type, .then((serializedKeyringArray) => {
data: keyring.serialize(), // Label the output values on each serialized Keyring:
} return {
type: serializedKeyringArray[0],
data: serializedKeyringArray[1],
}
})
}))
.then((serializedKeyrings) => {
return this.encryptor.encrypt(this.password, serializedKeyrings)
}) })
return this.encryptor.encrypt(this.password, serialized)
.then((encryptedString) => { .then((encryptedString) => {
this.configManager.setVault(encryptedString) this.configManager.setVault(encryptedString)
return true return true
@ -286,13 +322,15 @@ module.exports = class KeyringController extends EventEmitter {
const { type, data } = serialized const { type, data } = serialized
const Keyring = this.getKeyringClassForType(type) const Keyring = this.getKeyringClassForType(type)
const keyring = new Keyring() const keyring = new Keyring()
keyring.deserialize(data) return keyring.deserialize(data)
.then(() => {
const accounts = keyring.getAccounts() return keyring.getAccounts()
this.setupAccounts(accounts) })
.then((accounts) => {
this.keyrings.push(keyring) this.setupAccounts(accounts)
return keyring this.keyrings.push(keyring)
return keyring
})
} }
getKeyringClassForType (type) { getKeyringClassForType (type) {
@ -308,10 +346,10 @@ module.exports = class KeyringController extends EventEmitter {
getAccounts () { getAccounts () {
const keyrings = this.keyrings || [] const keyrings = this.keyrings || []
return keyrings.map(kr => kr.getAccounts()) return Promise.all(keyrings.map(kr => kr.getAccounts())
.reduce((res, arr) => { .reduce((res, arr) => {
return res.concat(arr) return res.concat(arr)
}, []) }, []))
} }
setSelectedAccount (address, cb) { setSelectedAccount (address, cb) {
@ -514,18 +552,19 @@ module.exports = class KeyringController extends EventEmitter {
txParams.gasLimit = normalize(txParams.gasLimit || txParams.gas) txParams.gasLimit = normalize(txParams.gasLimit || txParams.gas)
txParams.nonce = normalize(txParams.nonce) txParams.nonce = normalize(txParams.nonce)
let tx = new Transaction(txParams) const tx = new Transaction(txParams)
tx = keyring.signTransaction(address, tx) keyring.signTransaction(address, tx)
.then((tx) => {
// Add the tx hash to the persisted meta-tx object // Add the tx hash to the persisted meta-tx object
var txHash = ethUtil.bufferToHex(tx.hash()) var txHash = ethUtil.bufferToHex(tx.hash())
var metaTx = this.configManager.getTx(txParams.metamaskId) var metaTx = this.configManager.getTx(txParams.metamaskId)
metaTx.hash = txHash metaTx.hash = txHash
this.configManager.updateTx(metaTx) this.configManager.updateTx(metaTx)
// return raw serialized tx // return raw serialized tx
var rawTx = ethUtil.bufferToHex(tx.serialize()) var rawTx = ethUtil.bufferToHex(tx.serialize())
cb(null, rawTx) cb(null, rawTx)
})
} catch (e) { } catch (e) {
cb(e) cb(e)
} }
@ -535,8 +574,11 @@ module.exports = class KeyringController extends EventEmitter {
try { try {
const keyring = this.getKeyringForAccount(msgParams.from) const keyring = this.getKeyringForAccount(msgParams.from)
const address = normalize(msgParams.from) const address = normalize(msgParams.from)
const rawSig = keyring.signMessage(address, msgParams.data) return keyring.signMessage(address, msgParams.data)
cb(null, rawSig) .then((rawSig) => {
cb(null, rawSig)
return rawSig
})
} catch (e) { } catch (e) {
cb(e) cb(e)
} }
@ -567,10 +609,14 @@ module.exports = class KeyringController extends EventEmitter {
exportAccount (address, cb) { exportAccount (address, cb) {
try { try {
const keyring = this.getKeyringForAccount(address) const keyring = this.getKeyringForAccount(address)
const privateKey = keyring.exportAccount(normalize(address)) return keyring.exportAccount(normalize(address))
cb(null, privateKey) .then((privateKey) => {
cb(null, privateKey)
return privateKey
})
} catch (e) { } catch (e) {
cb(e) cb(e)
return Promise.reject(e)
} }
} }

@ -21,10 +21,10 @@ class HdKeyring extends EventEmitter {
} }
serialize () { serialize () {
return { return Promise.resolve({
mnemonic: this.mnemonic, mnemonic: this.mnemonic,
numberOfAccounts: this.wallets.length, numberOfAccounts: this.wallets.length,
} })
} }
deserialize (opts = {}) { deserialize (opts = {}) {
@ -40,6 +40,8 @@ class HdKeyring extends EventEmitter {
if ('numberOfAccounts' in opts) { if ('numberOfAccounts' in opts) {
this.addAccounts(opts.numberOfAccounts) this.addAccounts(opts.numberOfAccounts)
} }
return Promise.resolve()
} }
addAccounts (numberOfAccounts = 1) { addAccounts (numberOfAccounts = 1) {
@ -55,11 +57,12 @@ class HdKeyring extends EventEmitter {
newWallets.push(wallet) newWallets.push(wallet)
this.wallets.push(wallet) this.wallets.push(wallet)
} }
return newWallets.map(w => w.getAddress().toString('hex')) const hexWallets = newWallets.map(w => w.getAddress().toString('hex'))
return Promise.resolve(hexWallets)
} }
getAccounts () { getAccounts () {
return this.wallets.map(w => w.getAddress().toString('hex')) return Promise.resolve(this.wallets.map(w => w.getAddress().toString('hex')))
} }
// tx is an instance of the ethereumjs-transaction class. // tx is an instance of the ethereumjs-transaction class.
@ -67,7 +70,7 @@ class HdKeyring extends EventEmitter {
const wallet = this._getWalletForAccount(address) const wallet = this._getWalletForAccount(address)
var privKey = wallet.getPrivateKey() var privKey = wallet.getPrivateKey()
tx.sign(privKey) tx.sign(privKey)
return tx return Promise.resolve(tx)
} }
// For eth_sign, we need to sign transactions: // For eth_sign, we need to sign transactions:
@ -77,12 +80,12 @@ class HdKeyring extends EventEmitter {
var privKey = wallet.getPrivateKey() var privKey = wallet.getPrivateKey()
var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey)
var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s))
return rawMsgSig return Promise.resolve(rawMsgSig)
} }
exportAccount (address) { exportAccount (address) {
const wallet = this._getWalletForAccount(address) const wallet = this._getWalletForAccount(address)
return wallet.getPrivateKey().toString('hex') return Promise.resolve(wallet.getPrivateKey().toString('hex'))
} }

@ -8,10 +8,6 @@ class SimpleKeyring extends EventEmitter {
/* PUBLIC METHODS */ /* PUBLIC METHODS */
static type () {
return type
}
constructor (opts) { constructor (opts) {
super() super()
this.type = type this.type = type
@ -20,7 +16,7 @@ class SimpleKeyring extends EventEmitter {
} }
serialize () { serialize () {
return this.wallets.map(w => w.getPrivateKey().toString('hex')) return Promise.resolve(this.wallets.map(w => w.getPrivateKey().toString('hex')))
} }
deserialize (wallets = []) { deserialize (wallets = []) {
@ -29,6 +25,7 @@ class SimpleKeyring extends EventEmitter {
const wallet = Wallet.fromPrivateKey(b) const wallet = Wallet.fromPrivateKey(b)
return wallet return wallet
}) })
return Promise.resolve()
} }
addAccounts (n = 1) { addAccounts (n = 1) {
@ -37,11 +34,12 @@ class SimpleKeyring extends EventEmitter {
newWallets.push(Wallet.generate()) newWallets.push(Wallet.generate())
} }
this.wallets = this.wallets.concat(newWallets) this.wallets = this.wallets.concat(newWallets)
return newWallets.map(w => w.getAddress().toString('hex')) const hexWallets = newWallets.map(w => w.getAddress().toString('hex'))
return Promise.resolve(hexWallets)
} }
getAccounts () { getAccounts () {
return this.wallets.map(w => w.getAddress().toString('hex')) return Promise.resolve(this.wallets.map(w => w.getAddress().toString('hex')))
} }
// tx is an instance of the ethereumjs-transaction class. // tx is an instance of the ethereumjs-transaction class.
@ -49,7 +47,7 @@ class SimpleKeyring extends EventEmitter {
const wallet = this._getWalletForAccount(address) const wallet = this._getWalletForAccount(address)
var privKey = wallet.getPrivateKey() var privKey = wallet.getPrivateKey()
tx.sign(privKey) tx.sign(privKey)
return tx return Promise.resolve(tx)
} }
// For eth_sign, we need to sign transactions: // For eth_sign, we need to sign transactions:
@ -59,12 +57,12 @@ class SimpleKeyring extends EventEmitter {
var privKey = wallet.getPrivateKey() var privKey = wallet.getPrivateKey()
var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey) var msgSig = ethUtil.ecsign(new Buffer(message, 'hex'), privKey)
var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s)) var rawMsgSig = ethUtil.bufferToHex(sigUtil.concatSig(msgSig.v, msgSig.r, msgSig.s))
return rawMsgSig return Promise.resolve(rawMsgSig)
} }
exportAccount (address) { exportAccount (address) {
const wallet = this._getWalletForAccount(address) const wallet = this._getWalletForAccount(address)
return wallet.getPrivateKey().toString('hex') return Promise.resolve(wallet.getPrivateKey().toString('hex'))
} }

@ -61,7 +61,7 @@ describe('KeyringController', function() {
describe('#restoreKeyring', function() { describe('#restoreKeyring', function() {
it(`should pass a keyring's serialized data back to the correct type.`, function() { it(`should pass a keyring's serialized data back to the correct type.`, function(done) {
const mockSerialized = { const mockSerialized = {
type: 'HD Key Tree', type: 'HD Key Tree',
data: { data: {
@ -74,12 +74,21 @@ describe('KeyringController', function() {
mock.expects('getBalanceAndNickname') mock.expects('getBalanceAndNickname')
.exactly(1) .exactly(1)
var keyring = keyringController.restoreKeyring(mockSerialized) keyringController.restoreKeyring(mockSerialized)
assert.equal(keyring.wallets.length, 1, 'one wallet restored') .then((keyring) => {
assert.equal(keyring.getAccounts()[0], addresses[0]) assert.equal(keyring.wallets.length, 1, 'one wallet restored')
mock.verify() return keyring.getAccounts()
})
.then((accounts) => {
assert.equal(accounts[0], addresses[0])
mock.verify()
done()
})
.catch((reason) => {
assert.ifError(reason)
done()
})
}) })
}) })
describe('#migrateOldVaultIfAny', function() { describe('#migrateOldVaultIfAny', function() {
@ -92,6 +101,7 @@ describe('KeyringController', function() {
}) })
.catch((reason) => { .catch((reason) => {
assert.ifError(reason) assert.ifError(reason)
done()
}) })
}) })
}) })
@ -110,15 +120,17 @@ describe('KeyringController', function() {
}) })
describe('#saveAccountLabel', function() { describe('#saveAccountLabel', function() {
it ('sets the nickname', function() { it ('sets the nickname', function(done) {
const account = addresses[0] const account = addresses[0]
var nick = 'Test nickname' var nick = 'Test nickname'
keyringController.identities[ethUtil.addHexPrefix(account)] = {} keyringController.identities[ethUtil.addHexPrefix(account)] = {}
const label = keyringController.saveAccountLabel(account, nick) keyringController.saveAccountLabel(account, nick, (err, label) => {
assert.equal(label, nick) assert.ifError(err)
assert.equal(label, nick)
const persisted = keyringController.configManager.nicknameForWallet(account) const persisted = keyringController.configManager.nicknameForWallet(account)
assert.equal(persisted, nick) assert.equal(persisted, nick)
done()
})
}) })
this.timeout(10000) this.timeout(10000)
@ -126,9 +138,7 @@ describe('KeyringController', function() {
const account = addresses[0] const account = addresses[0]
var nick = 'Test nickname' var nick = 'Test nickname'
keyringController.configManager.setNicknameForWallet(account, nick) keyringController.configManager.setNicknameForWallet(account, nick)
console.log('calling to restore')
keyringController.createNewVaultAndRestore(password, seedWords, (err, state) => { keyringController.createNewVaultAndRestore(password, seedWords, (err, state) => {
console.dir({err})
assert.ifError(err) assert.ifError(err)
const identity = keyringController.identities['0x' + account] const identity = keyringController.identities['0x' + account]
@ -143,12 +153,15 @@ describe('KeyringController', function() {
describe('#getAccounts', function() { describe('#getAccounts', function() {
it('returns the result of getAccounts for each keyring', function() { it('returns the result of getAccounts for each keyring', function() {
keyringController.keyrings = [ keyringController.keyrings = [
{ getAccounts() { return [1,2,3] } }, { getAccounts() { return Promise.resolve([1,2,3]) } },
{ getAccounts() { return [4,5,6] } }, { getAccounts() { return Promise.resolve([4,5,6]) } },
] ]
const result = keyringController.getAccounts() keyringController.getAccounts()
assert.deepEqual(result, [1,2,3,4,5,6]) .then((result) => {
assert.deepEqual(result, [1,2,3,4,5,6])
done()
})
}) })
}) })

@ -16,15 +16,18 @@ describe('hd-keyring', function() {
keyring = new HdKeyring() keyring = new HdKeyring()
}) })
describe('constructor', function() { describe('constructor', function(done) {
keyring = new HdKeyring({ keyring = new HdKeyring({
mnemonic: sampleMnemonic, mnemonic: sampleMnemonic,
numberOfAccounts: 2, numberOfAccounts: 2,
}) })
const accounts = keyring.getAccounts() const accounts = keyring.getAccounts()
assert.equal(accounts[0], firstAcct) .then((accounts) => {
assert.equal(accounts[1], secondAcct) assert.equal(accounts[0], firstAcct)
assert.equal(accounts[1], secondAcct)
done()
})
}) })
describe('Keyring.type', function() { describe('Keyring.type', function() {
@ -44,49 +47,64 @@ describe('hd-keyring', function() {
describe('#serialize empty wallets.', function() { describe('#serialize empty wallets.', function() {
it('serializes a new mnemonic', function() { it('serializes a new mnemonic', function() {
const output = keyring.serialize() keyring.serialize()
assert.equal(output.numberOfAccounts, 0) .then((output) => {
assert.equal(output.mnemonic, null) assert.equal(output.numberOfAccounts, 0)
assert.equal(output.mnemonic, null)
})
}) })
}) })
describe('#deserialize a private key', function() { describe('#deserialize a private key', function() {
it('serializes what it deserializes', function() { it('serializes what it deserializes', function(done) {
console.log('deserializing ' + sampleMnemonic)
keyring.deserialize({ keyring.deserialize({
mnemonic: sampleMnemonic, mnemonic: sampleMnemonic,
numberOfAccounts: 1 numberOfAccounts: 1
}) })
assert.equal(keyring.wallets.length, 1, 'restores two accounts') .then(() => {
keyring.addAccounts(1) console.dir(keyring)
assert.equal(keyring.wallets.length, 1, 'restores two accounts')
const accounts = keyring.getAccounts() return keyring.addAccounts(1)
assert.equal(accounts[0], firstAcct) }).then(() => {
assert.equal(accounts[1], secondAcct) return keyring.getAccounts()
assert.equal(accounts.length, 2) }).then((accounts) => {
assert.equal(accounts[0], firstAcct)
const serialized = keyring.serialize() assert.equal(accounts[1], secondAcct)
assert.equal(serialized.mnemonic, sampleMnemonic) assert.equal(accounts.length, 2)
return keyring.serialize()
}).then((serialized) => {
assert.equal(serialized.mnemonic, sampleMnemonic)
done()
})
}) })
}) })
describe('#addAccounts', function() { describe('#addAccounts', function() {
describe('with no arguments', function() { describe('with no arguments', function() {
it('creates a single wallet', function() { it('creates a single wallet', function(done) {
keyring.addAccounts() keyring.addAccounts()
assert.equal(keyring.wallets.length, 1) .then(() => {
assert.equal(keyring.wallets.length, 1)
done()
})
}) })
}) })
describe('with a numeric argument', function() { describe('with a numeric argument', function() {
it('creates that number of wallets', function() { it('creates that number of wallets', function(done) {
keyring.addAccounts(3) keyring.addAccounts(3)
assert.equal(keyring.wallets.length, 3) .then(() => {
assert.equal(keyring.wallets.length, 3)
done()
})
}) })
}) })
}) })
describe('#getAccounts', function() { describe('#getAccounts', function() {
it('calls getAddress on each wallet', function() { it('calls getAddress on each wallet', function(done) {
// Push a mock wallet // Push a mock wallet
const desiredOutput = 'foo' const desiredOutput = 'foo'
@ -101,8 +119,11 @@ describe('hd-keyring', function() {
}) })
const output = keyring.getAccounts() const output = keyring.getAccounts()
assert.equal(output[0], desiredOutput) .then((output) => {
assert.equal(output.length, 1) assert.equal(output[0], desiredOutput)
assert.equal(output.length, 1)
done()
})
}) })
}) })
}) })

@ -28,19 +28,23 @@ describe('simple-keyring', function() {
}) })
describe('#serialize empty wallets.', function() { describe('#serialize empty wallets.', function() {
it('serializes an empty array', function() { it('serializes an empty array', function(done) {
const output = keyring.serialize() keyring.serialize()
assert.deepEqual(output, []) .then((output) => {
assert.deepEqual(output, [])
done()
})
}) })
}) })
describe('#deserialize a private key', function() { describe('#deserialize a private key', function() {
it('serializes what it deserializes', function() { it('serializes what it deserializes', function() {
keyring.deserialize([privKeyHex]) keyring.deserialize([privKeyHex])
assert.equal(keyring.wallets.length, 1, 'has one wallet') .then(() => {
assert.equal(keyring.wallets.length, 1, 'has one wallet')
const serialized = keyring.serialize() const serialized = keyring.serialize()
assert.equal(serialized[0], privKeyHex) assert.equal(serialized[0], privKeyHex)
})
}) })
}) })
@ -48,20 +52,24 @@ describe('simple-keyring', function() {
describe('with no arguments', function() { describe('with no arguments', function() {
it('creates a single wallet', function() { it('creates a single wallet', function() {
keyring.addAccounts() keyring.addAccounts()
assert.equal(keyring.wallets.length, 1) .then(() => {
assert.equal(keyring.wallets.length, 1)
})
}) })
}) })
describe('with a numeric argument', function() { describe('with a numeric argument', function() {
it('creates that number of wallets', function() { it('creates that number of wallets', function() {
keyring.addAccounts(3) keyring.addAccounts(3)
assert.equal(keyring.wallets.length, 3) .then(() => {
assert.equal(keyring.wallets.length, 3)
})
}) })
}) })
}) })
describe('#getAccounts', function() { describe('#getAccounts', function() {
it('calls getAddress on each wallet', function() { it('calls getAddress on each wallet', function(done) {
// Push a mock wallet // Push a mock wallet
const desiredOutput = 'foo' const desiredOutput = 'foo'
@ -75,9 +83,12 @@ describe('simple-keyring', function() {
} }
}) })
const output = keyring.getAccounts() keyring.getAccounts()
assert.equal(output[0], desiredOutput) .then((output) => {
assert.equal(output.length, 1) assert.equal(output[0], desiredOutput)
assert.equal(output.length, 1)
done()
})
}) })
}) })
}) })

Loading…
Cancel
Save