Skip to content

Commit

Permalink
feat(Account): Add ability to pass keypair or MemoryAccount as nA…
Browse files Browse the repository at this point in the history
…ccount` option (#847)

* feat(Account): Add ability to pass `keypair` or `MemoryAccount` as `onAccount` option

* feat(Account): Remove deprecated test
  • Loading branch information
nduchak authored Jan 3, 2020
1 parent e2a8576 commit 75d8ad8
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 17 deletions.
44 changes: 35 additions & 9 deletions es/account/selector.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,46 @@
import Account from './'
import required from '@stamp/required'
import { assertedType } from '../utils/crypto'
import MemoryAccount from './memory'

const isMemoryAccount = (acc) => !['sign', 'address'].find(f => typeof acc[f] !== 'function')

async function sign (data, { onAccount } = {}) {
if (onAccount && !assertedType(onAccount, 'ak', true)) throw new Error('Invalid account address, check "onAccount" value')
return this.signWith(onAccount || this.Selector.address, data)
if (!onAccount) return this.signWith(this.Selector.address, data)
// onAccount can be account address(should exist in sdk instance) or MemoryAccount
return this.resolveOnAccount(onAccount, 'sign', data)
}

async function resolveOnAccount (onAccount, operation = 'address', data) {
switch (typeof onAccount) {
case 'string':
if (!assertedType(onAccount, 'ak', true)) throw new Error('Invalid account address, check "onAccount" value')
if (!this.accounts[onAccount]) throw Error(`Account for ${onAccount} not available`)
if (operation === 'sign') return this.signWith(onAccount, data)
if (operation === 'address') return onAccount
break
case 'object':
try {
const memoryAccount = isMemoryAccount(onAccount)
? onAccount
: MemoryAccount({ keypair: onAccount })
if (operation === 'sign') return memoryAccount.sign(data)
if (operation === 'address') return memoryAccount.address()
break
} catch (e) {
e.message = `Invalid 'onAccount' option: ${e.message}`
throw e
}
default:
throw new Error('Invalid `onAccount` option: should be keyPair object or account address')
}
}
async function address ({ onAccount } = {}) {
if (onAccount) {
if (!assertedType(onAccount, 'ak', true)) throw new Error('Invalid account address, check "onAccount" value')
if (!this.accounts[onAccount]) throw Error(`Account for ${onAccount} not available`)
return Promise.resolve(onAccount)
if (!onAccount) {
if (this.Selector.address) return Promise.resolve(this.Selector.address)
throw new Error('You don\'t have selected account')
}
if (this.Selector.address) return Promise.resolve(this.Selector.address)
throw new Error('You don\'t have selected account')
return this.resolveOnAccount(onAccount, 'address')
}

/**
Expand Down Expand Up @@ -72,7 +98,7 @@ const Selector = Account.compose({
if (address && !assertedType(address, 'ak', true)) throw new Error('Invalid account address')
this.Selector.address = address
},
methods: { sign, address, selectAccount },
methods: { sign, address, selectAccount, resolveOnAccount },
deepProps: {
Selector: {}
}
Expand Down
40 changes: 38 additions & 2 deletions test/integration/accounts.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ describe('Accounts', function () {
try {
await wallet.spend(1, await wallet.address(), { onAccount: 1 })
} catch (e) {
e.message.should.be.equal('Invalid account address, check "onAccount" value')
e.message.should.be.equal('Invalid `onAccount` option: should be keyPair object or account address')
}
})

Expand All @@ -137,12 +137,48 @@ describe('Accounts', function () {
e.message.should.be.equal('Account for ak_q2HatMwDnwCBpdNtN9oXf5gpD9pGSgFxaa8i2Evcam6gjiggk not available')
}
})
it('Invalid on account options', async () => {
try {
await wallet.sign('tx_Aasdasd', { onAccount: 123 })
} catch (e) {
e.message.should.be.equal('Invalid `onAccount` option: should be keyPair object or account address')
}
})
it('Make operation on account using keyPair/MemoryAccount', async () => {
const keypair = generateKeyPair()
const memoryAccount = MemoryAccount({ keypair })
const data = 'Hello'
const signature = await memoryAccount.sign(data)
const sigUsingKeypair = await wallet.sign(data, { onAccount: keypair })
const sigUsingMemoryAccount = await wallet.sign(data, { onAccount: memoryAccount })
signature.toString('hex').should.be.equal(sigUsingKeypair.toString('hex'))
signature.toString('hex').should.be.equal(sigUsingMemoryAccount.toString('hex'))
// address
const addressFromKeypair = await wallet.address({ onAccount: keypair })
const addressFrommemoryAccount = await wallet.address({ onAccount: memoryAccount })
addressFromKeypair.should.be.equal(keypair.publicKey)
addressFrommemoryAccount.should.be.equal(keypair.publicKey)
})
it('Make operation on account using keyPair: Invalid keypair', async () => {
const keypair = generateKeyPair()
keypair.publicKey = 'ak_bev1aPMdAeJTuUiCJ7mHbdQiAizrkRGgoV9FfxHYb6pAxo5WY'
const data = 'Hello'
try {
await wallet.sign(data, { onAccount: keypair })
} catch (e) {
e.message.should.be.equal('Invalid \'onAccount\' option: Invalid Key Pair')
}
try {
await wallet.address({ onAccount: keypair })
} catch (e) {
e.message.should.be.equal('Invalid \'onAccount\' option: Invalid Key Pair')
}
})
})

describe('can be configured to return th', () => {
it('on creation', async () => {
const wallet = await ready(this)
// const wallet = await BaseAe.compose({deepProps: {Chain: {defaults: {waitMined: false}}}})()
const th = await wallet.spend(1, receiver)
th.should.be.a('object')
th.hash.slice(0, 3).should.equal('th_')
Expand Down
6 changes: 0 additions & 6 deletions test/integration/node.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,6 @@ describe('Node client', function () {
)
})
describe('Node Pool', () => {
it('init using old style (url, internalUrl)', async () => {
const node = await NodePool({ url, internalUrl })
const nodeInfoKeys = ['name', 'url', 'internalUrl', 'nodeNetworkId', 'version', 'consensusProtocolVersion']
const isNodeInfo = !Object.keys(node.getNodeInfo).find(k => !nodeInfoKeys.includes(k))
isNodeInfo.should.be.equal(true)
})
it('throw error on invalid node object', async () => {
const node = await NodePool()
expect(() => node.addNode('test', {})).to.throw(Error)
Expand Down

0 comments on commit 75d8ad8

Please sign in to comment.