UNPKG

caver-js

Version:

caver-js is a JavaScript API library that allows developers to interact with a Klaytn node

882 lines (669 loc) 39.2 kB
/* Copyright 2020 The caver-js Authors This file is part of the caver-js library. The caver-js library is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. The caver-js library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the caver-js. If not, see <http://www.gnu.org/licenses/>. */ const _ = require('lodash') const chai = require('chai') const sinon = require('sinon') const sinonChai = require('sinon-chai') const chaiAsPromised = require('chai-as-promised') chai.use(chaiAsPromised) chai.use(sinonChai) const expect = chai.expect const testRPCURL = require('../testrpc') const Caver = require('../../index') const SingleKeyring = require('../../packages/caver-wallet/src/keyring/singleKeyring') const MultipleKeyring = require('../../packages/caver-wallet/src/keyring/multipleKeyring') const RoleBasedKeyring = require('../../packages/caver-wallet/src/keyring/roleBasedKeyring') const PrivateKey = require('../../packages/caver-wallet/src/keyring/privateKey') const ValueTransfer = require('../../packages/caver-transaction/src/transactionTypes/valueTransfer/valueTransfer') const FeeDelegatedValueTransfer = require('../../packages/caver-transaction/src/transactionTypes/valueTransfer/feeDelegatedValueTransfer') const AccountUpdate = require('../../packages/caver-transaction/src/transactionTypes/accountUpdate/accountUpdate') const SignatureData = require('../../packages/caver-wallet/src/keyring/signatureData') const { generateDecoupledKeyring, generateMultiSigKeyring, generateRoleBasedKeyring } = require('./utils') let caver beforeEach(() => { caver = new Caver(testRPCURL) }) function validateKeyringInWallet(data, { expectedAddress, expectedKey } = {}) { expect(data instanceof SingleKeyring || data instanceof MultipleKeyring || data instanceof RoleBasedKeyring).to.be.true const objectKeys = ['_address'] if (data instanceof SingleKeyring) { objectKeys.push('_key') } else { objectKeys.push('_keys') } expect(Object.getOwnPropertyNames(data)).to.deep.equal(objectKeys) expect(caver.utils.isAddress(data.address)).to.equal(true) if (expectedAddress !== undefined) { expect(data.address.toLowerCase()).to.equal(expectedAddress.toLowerCase()) } if (expectedKey !== undefined) { if (data instanceof SingleKeyring) { comparePrivateKey(expectedKey, data.key) } else if (data instanceof MultipleKeyring) { for (let i = 0; i < data.keys.length; i++) { comparePrivateKey(expectedKey[i], data.keys[i]) } } else { for (let i = 0; i < data.keys.length; i++) { for (let j = 0; j < data.keys[i].length; j++) { comparePrivateKey(expectedKey[i][j], data.keys[i][j]) } } } } } function comparePrivateKey(expected, actual) { const privateKeyString = expected instanceof PrivateKey ? expected.privateKey : expected expect(actual.privateKey.toLowerCase()).to.equal(privateKeyString.toLowerCase()) } describe('wallet.generate', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-001: input: valid number of keyring to make', () => { it('should generate keyring instances and add to in-memory wallet', () => { const addSpy = sinon.spy(caver.wallet, 'add') const addresses = caver.wallet.generate(10) for (const address of addresses) { expect(caver.utils.isAddress(address)).to.be.true } expect(addresses.length).to.equal(10) expect(caver.wallet.length).to.equal(10) expect(addSpy).to.have.been.callCount(10) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-002: input: valid number of keyring to make, entropy', () => { it('should generate keyring instances and add to in-memory wallet', () => { const addSpy = sinon.spy(caver.wallet, 'add') const entropy = caver.utils.randomHex(32) const addresses = caver.wallet.generate(10, entropy) for (const address of addresses) { expect(caver.utils.isAddress(address)).to.be.true } expect(addresses.length).to.equal(10) expect(caver.wallet.length).to.equal(10) expect(addSpy).to.have.been.callCount(10) }) }) }) describe('wallet.newKeyring', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-003: input: address, single private key string', () => { it('should create keyring instances with parameters and add to in-memory wallet', () => { const addSpy = sinon.spy(caver.wallet, 'add') const keyring = caver.wallet.keyring.generate() const added = caver.wallet.newKeyring(keyring.address, keyring.key.privateKey) validateKeyringInWallet(added, { expectedAddress: keyring.address, expectedKey: keyring.key }) expect(addSpy).to.have.been.calledOnce expect(caver.wallet.length).to.equal(1) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-004: input: address, multiple private key strings', () => { it('should create keyring instances with parameters and add to in-memory wallet', () => { const addSpy = sinon.spy(caver.wallet, 'add') const address = caver.wallet.keyring.generate().address const multiplePrivateKeys = caver.wallet.keyring.generateMultipleKeys(3) const added = caver.wallet.newKeyring(address, multiplePrivateKeys) validateKeyringInWallet(added, { expectedAddress: address, expectedKey: multiplePrivateKeys }) expect(addSpy).to.have.been.calledOnce expect(caver.wallet.length).to.equal(1) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-005: input: address, private keys by roles(without empty role)', () => { it('should create keyring instances with parameters and add to in-memory wallet', () => { const addSpy = sinon.spy(caver.wallet, 'add') const address = caver.wallet.keyring.generate().address const roleBasedPrivateKeys = caver.wallet.keyring.generateRoleBasedKeys([3, 1, 2]) const added = caver.wallet.newKeyring(address, roleBasedPrivateKeys) validateKeyringInWallet(added, { expectedAddress: address, expectedKey: roleBasedPrivateKeys }) expect(addSpy).to.have.been.calledOnce expect(caver.wallet.length).to.equal(1) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-006: input: address, private keys by roles(with empty role)', () => { it('should create keyring instances with parameters and add to in-memory wallet', () => { const addSpy = sinon.spy(caver.wallet, 'add') const address = caver.wallet.keyring.generate().address const roleBasedPrivateKeys = caver.wallet.keyring.generateRoleBasedKeys([0, 0, 2]) const added = caver.wallet.newKeyring(address, roleBasedPrivateKeys) validateKeyringInWallet(added, { expectedAddress: address, expectedKey: roleBasedPrivateKeys }) expect(addSpy).to.have.been.calledOnce expect(caver.wallet.length).to.equal(1) }) }) }) describe('wallet.updateKeyring', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-007: input: coupled keyring', () => { it('should update key of keyring', () => { const coupled = caver.wallet.keyring.generate() const decoupled = caver.wallet.keyring.createWithSingleKey(coupled.address, caver.wallet.keyring.generateSingleKey()) caver.wallet.add(decoupled) const updated = caver.wallet.updateKeyring(coupled) const keyringFromContainer = caver.wallet.getKeyring(coupled.address) validateKeyringInWallet(updated, { expectedAddress: decoupled.address, expectedKey: coupled.key }) validateKeyringInWallet(keyringFromContainer, { expectedAddress: coupled.address, expectedKey: coupled.key }) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-008: input: decoupled keyring', () => { it('should update key of keyring', () => { const coupled = caver.wallet.keyring.generate() const decoupled = caver.wallet.keyring.createWithSingleKey(coupled.address, caver.wallet.keyring.generateSingleKey()) caver.wallet.add(coupled) const updated = caver.wallet.updateKeyring(decoupled) const keyringFromContainer = caver.wallet.getKeyring(coupled.address) validateKeyringInWallet(updated, { expectedAddress: coupled.address, expectedKey: decoupled.key }) validateKeyringInWallet(keyringFromContainer, { expectedAddress: coupled.address, expectedKey: decoupled.key }) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-009: input: multiSig keyring', () => { it('should update key of keyring', () => { const coupled = caver.wallet.keyring.generate() const multiSig = generateMultiSigKeyring() multiSig.address = coupled.address caver.wallet.add(coupled) const updated = caver.wallet.updateKeyring(multiSig) const keyringFromContainer = caver.wallet.getKeyring(coupled.address) validateKeyringInWallet(updated, { expectedAddress: coupled.address, expectedKey: multiSig.keys }) validateKeyringInWallet(keyringFromContainer, { expectedAddress: coupled.address, expectedKey: multiSig.keys }) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-010: input: roleBased keyring', () => { it('should update key of keyring', () => { const coupled = caver.wallet.keyring.generate() const copySpy = sinon.spy(coupled, 'copy') const roleBased = generateRoleBasedKeyring() roleBased.address = coupled.address caver.wallet.add(coupled) const updated = caver.wallet.updateKeyring(roleBased) const keyringFromContainer = caver.wallet.getKeyring(coupled.address) validateKeyringInWallet(updated, { expectedAddress: coupled.address, expectedKey: roleBased.keys }) validateKeyringInWallet(keyringFromContainer, { expectedAddress: coupled.address, expectedKey: roleBased.keys }) expect(copySpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-011: input: keyring not existed in wallet', () => { it('should throw error when fail to find keyring', () => { const expectedError = `Failed to find keyring to update` expect(() => caver.wallet.updateKeyring(caver.wallet.keyring.generate())).to.throw(expectedError) }) }) }) describe('wallet.getKeyring', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-012: input: valid address', () => { it('return keyring from wallet', () => { const added = caver.wallet.add(caver.wallet.keyring.generate()) const keyring = caver.wallet.getKeyring(added.address) validateKeyringInWallet(keyring, { expectedAddress: added.address, expectedKey: added.key }) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-013: input: not exist address', () => { it('return undefined when fail to find keyring in wallet', () => { const generated = caver.wallet.keyring.generate() const keyring = caver.wallet.getKeyring(generated.address) expect(keyring).to.be.undefined }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-014: input: invalid address', () => { it('should throw error when parameter is invalid', () => { const invalidAddress = 'invalid address' const expectedError = `Invalid address ${invalidAddress}. To get keyring from wallet, you need to pass a valid address string as a parameter.` expect(() => caver.wallet.getKeyring(invalidAddress)).to.throw(expectedError) }) }) }) describe('wallet.add', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-015: input: coupled keyring', () => { it('return added keyring which use single private key', () => { const keyringToAdd = caver.wallet.keyring.generate() const added = caver.wallet.add(keyringToAdd) const keyringFromContainer = caver.wallet.getKeyring(added.address) validateKeyringInWallet(added, { expectedAddress: keyringToAdd.address, expectedKey: keyringToAdd.key }) validateKeyringInWallet(keyringFromContainer, { expectedAddress: keyringToAdd.address, expectedKey: keyringToAdd.key }) expect(caver.wallet.length).to.equal(1) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-016: input: decoupled keyring', () => { it('return added keyring which use decoupled private key', () => { const keyringToAdd = generateDecoupledKeyring() const added = caver.wallet.add(keyringToAdd) const keyringFromContainer = caver.wallet.getKeyring(added.address) validateKeyringInWallet(added, { expectedAddress: keyringToAdd.address, expectedKey: keyringToAdd.key }) validateKeyringInWallet(keyringFromContainer, { expectedAddress: keyringToAdd.address, expectedKey: keyringToAdd.key }) expect(caver.wallet.length).to.equal(1) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-017: input: multiSig keyring', () => { it('return added keyring which use multiple private keys', () => { const keyringToAdd = generateMultiSigKeyring() const added = caver.wallet.add(keyringToAdd) const keyringFromContainer = caver.wallet.getKeyring(added.address) validateKeyringInWallet(added, { expectedAddress: keyringToAdd.address, expectedKey: keyringToAdd.keys }) validateKeyringInWallet(keyringFromContainer, { expectedAddress: keyringToAdd.address, expectedKey: keyringToAdd.keys }) expect(caver.wallet.length).to.equal(1) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-018: input: roleBased keyring', () => { it('return added keyring which use different private keys by roles', () => { const keyringToAdd = generateRoleBasedKeyring() const added = caver.wallet.add(keyringToAdd) const keyringFromContainer = caver.wallet.getKeyring(added.address) validateKeyringInWallet(added, { expectedAddress: keyringToAdd.address, expectedKey: keyringToAdd.keys }) validateKeyringInWallet(keyringFromContainer, { expectedAddress: keyringToAdd.address, expectedKey: keyringToAdd.keys }) expect(caver.wallet.length).to.equal(1) }) }) }) describe('wallet.remove', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-019: input: coupled keyring', () => { it('should remove keyring from keyringContainer and return remove result with boolean value', () => { const keyringToAdd = caver.wallet.keyring.generate() const added = caver.wallet.add(keyringToAdd) const result = caver.wallet.remove(added.address) expect(result).to.be.true expect(caver.wallet.length).to.equal(0) expect(caver.wallet.getKeyring(added.address)).to.be.undefined }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-020: input: decoupled keyring', () => { it('should remove keyring from keyringContainer and return remove result with boolean value', () => { const keyringToAdd = generateDecoupledKeyring() const added = caver.wallet.add(keyringToAdd) const result = caver.wallet.remove(added.address) expect(result).to.be.true expect(caver.wallet.length).to.equal(0) expect(caver.wallet.getKeyring(added.address)).to.be.undefined }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-021: input: multiSig keyring', () => { it('should remove keyring from keyringContainer and return remove result with boolean value', () => { const keyringToAdd = generateMultiSigKeyring() const added = caver.wallet.add(keyringToAdd) const result = caver.wallet.remove(added.address) expect(result).to.be.true expect(caver.wallet.length).to.equal(0) expect(caver.wallet.getKeyring(added.address)).to.be.undefined }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-022: input: roleBased keyring', () => { it('should remove keyring from keyringContainer and return remove result with boolean value', () => { const keyringToAdd = generateRoleBasedKeyring() const added = caver.wallet.add(keyringToAdd) const result = caver.wallet.remove(added.address) expect(result).to.be.true expect(caver.wallet.length).to.equal(0) expect(caver.wallet.getKeyring(added.address)).to.be.undefined }) }) }) describe('wallet.sign', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-023: input: address, value transfer transaction', () => { it('should sign to transaction and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateValueTransfer(keyring) const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendSignatures') await caver.wallet.sign(keyring.address, vt) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledOnce expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-024: input: address, value transfer transaction, valid index', () => { it('should sign to transaction and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateValueTransfer(keyring) const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendSignatures') await caver.wallet.sign(keyring.address, vt, 2) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledOnce expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-025: input: address, value transfer transaction, custom hasher', () => { it('should sign to transaction and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateValueTransfer(keyring) const txHash = '0xd4aab6590bdb708d1d3eafe95a967dafcd2d7cde197e512f3f0b8158e7b65fd1' const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendSignatures') await caver.wallet.sign(keyring.address, vt, () => txHash) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledWith(txHash, '0x7e3', 0, undefined) expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-026: input: address, value transfer transaction, index, custom hasher', () => { it('should sign to transaction and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateValueTransfer(keyring) const txHash = '0xd4aab6590bdb708d1d3eafe95a967dafcd2d7cde197e512f3f0b8158e7b65fd1' const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendSignatures') await caver.wallet.sign(keyring.address, vt, 1, () => txHash) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledWith(txHash, '0x7e3', 0, 1) expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-027: input: address, account update transaction, index, custom hasher', () => { it('should sign to transaction and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const updateTx = generateAccountUpdate(keyring) const txHash = '0xd4aab6590bdb708d1d3eafe95a967dafcd2d7cde197e512f3f0b8158e7b65fd1' const fillFormatSpy = sinon.spy(updateTx, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(updateTx, 'appendSignatures') await caver.wallet.sign(keyring.address, updateTx, 1, () => txHash) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledWith(txHash, '0x7e3', 1, 1) expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-028: input: address, value transfer transaction, invalid index', () => { it('should throw error when index is invalid', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateValueTransfer(keyring) const invalidIndex = 3 const expectedError = `Invalid index(${invalidIndex}): index must be less than the length of keys(${invalidIndex}).` await expect(caver.wallet.sign(keyring.address, vt, invalidIndex)).to.be.rejectedWith(expectedError) }) }) context( 'CAVERJS-UNIT-KEYRINGCONTAINER-029: input: address, value transfer transaction, valid index, invalid hasher custom funtion', () => { it('should throw error when transaction hash is invalid', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateValueTransfer(keyring) const invalidTxHash = 'invalidTxHash' const expectedError = `Invalid transaction hash: ${invalidTxHash}` await expect(caver.wallet.sign(keyring.address, vt, 0, () => invalidTxHash)).to.be.rejectedWith(expectedError) }) } ) context('CAVERJS-UNIT-KEYRINGCONTAINER-030: input: not exist keyring address, value transfer transaction', () => { it('should throw error when keyring is not existed in wallet', async () => { const keyring = generateRoleBasedKeyring([3, 2, 4]) const vt = generateValueTransfer(keyring) const expectedError = `Failed to find keyring from wallet with ${keyring.address}` await expect(caver.wallet.sign(keyring.address, vt)).to.be.rejectedWith(expectedError) }) }) }) describe('wallet.sign', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-031: input: address, value transfer transaction', () => { it('should sign to transaction and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateValueTransfer(keyring) const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendSignatures') await caver.wallet.sign(keyring.address, vt) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledOnce expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-032: input: address, value transfer transaction, custom hasher', () => { it('should sign to transaction and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateValueTransfer(keyring) const txHash = '0xe9a11d9ef95fb437f75d07ce768d43e74f158dd54b106e7d3746ce29d545b550' const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendSignatures') await caver.wallet.sign(keyring.address, vt, () => txHash) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledWith(txHash, '0x7e3', 0) expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-033: input: address, account update transaction, custom hasher', () => { it('should sign to transaction and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const updateTx = generateAccountUpdate(keyring) const txHash = '0xe9a11d9ef95fb437f75d07ce768d43e74f158dd54b106e7d3746ce29d545b550' const fillFormatSpy = sinon.spy(updateTx, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(updateTx, 'appendSignatures') await caver.wallet.sign(keyring.address, updateTx, () => txHash) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledWith(txHash, '0x7e3', 1) expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-034: input: address, value transfer transaction, invalid hasher custom funtion', () => { it('should throw error when transaction hash is invalid', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateValueTransfer(keyring) const invalidTxHash = 'invalidTxHash' const expectedError = `Invalid transaction hash: ${invalidTxHash}` await expect(caver.wallet.sign(keyring.address, vt, () => invalidTxHash)).to.be.rejectedWith(expectedError) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-035: input: not exist keyring address, value transfer transaction', () => { it('should throw error when keyring is not existed in wallet', async () => { const keyring = generateRoleBasedKeyring([3, 2, 4]) const vt = generateValueTransfer(keyring) const expectedError = `Failed to find keyring from wallet with ${keyring.address}` await expect(caver.wallet.sign(keyring.address, vt)).to.be.rejectedWith(expectedError) }) }) }) describe('wallet.signMessage', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-036: input: address, data, role', () => { it('should sign to message and return signed result', () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const data = 'Some data' const getKeyringSpy = sinon.spy(caver.wallet, 'getKeyring') const signMessageSpy = sinon.spy(keyring, 'signMessage') const signed = caver.wallet.signMessage(keyring.address, data, caver.wallet.keyring.role.roleTransactionKey) expect(signed.messageHash).to.equal(caver.utils.hashMessage(data)) expect(_.isArray(signed.signatures)).to.be.true expect(signed.signatures.length).to.equal(keyring.roleTransactionKey.length) expect(signed.signatures[0] instanceof SignatureData).to.be.true expect(signed.message).to.equal(data) expect(getKeyringSpy).to.have.been.calledOnce expect(signMessageSpy).to.have.been.calledWith(data, 0, undefined) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-051: input: address, data, role, index', () => { it('should sign to message and return signed result', () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const data = 'Some data' const getKeyringSpy = sinon.spy(caver.wallet, 'getKeyring') const signMessageSpy = sinon.spy(keyring, 'signMessage') const signed = caver.wallet.signMessage(keyring.address, data, caver.wallet.keyring.role.roleTransactionKey, 0) expect(signed.messageHash).to.equal(caver.utils.hashMessage(data)) expect(_.isArray(signed.signatures)).to.be.true expect(signed.signatures.length).to.equal(1) expect(signed.signatures[0] instanceof SignatureData).to.be.true expect(signed.message).to.equal(data) expect(getKeyringSpy).to.have.been.calledOnce expect(signMessageSpy).to.have.been.calledWith(data, 0, 0) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-037: input: not exist keyring address, data', () => { it('should throw error when keyring is not existed in wallet', () => { const keyring = generateRoleBasedKeyring([3, 2, 4]) const data = 'Some data' const expectedError = `Failed to find keyring from wallet with ${keyring.address}` expect(() => caver.wallet.signMessage(keyring.address, data)).to.throw(expectedError) }) }) }) describe('wallet.signAsFeePayer', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-038: input: address, value transfer transaction', () => { it('should sign to transaction with roleFeePayerKey and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateFeeDelegatedValueTransfer(keyring) const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendFeePayerSignatures') await caver.wallet.signAsFeePayer(keyring.address, vt) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledOnce expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-039: input: address, value transfer transaction, valid index', () => { it('should sign to transaction with roleFeePayerKey and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateFeeDelegatedValueTransfer(keyring) const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendFeePayerSignatures') await caver.wallet.signAsFeePayer(keyring.address, vt, 2) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledOnce expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-040: input: address, value transfer transaction, custom hasher', () => { it('should sign to transaction with roleFeePayerKey and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateFeeDelegatedValueTransfer(keyring) const txHash = '0xe9a11d9ef95fb437f75d07ce768d43e74f158dd54b106e7d3746ce29d545b550' const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendFeePayerSignatures') await caver.wallet.signAsFeePayer(keyring.address, vt, () => txHash) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledWith(txHash, '0x7e3', 2, undefined) expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-041: input: address, value transfer transaction, index, custom hasher', () => { it('should sign to transaction with roleFeePayerKey and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateFeeDelegatedValueTransfer(keyring) const txHash = '0xe9a11d9ef95fb437f75d07ce768d43e74f158dd54b106e7d3746ce29d545b550' const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendFeePayerSignatures') await caver.wallet.signAsFeePayer(keyring.address, vt, 1, () => txHash) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledWith(txHash, '0x7e3', 2, 1) expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-042: input: address, value transfer transaction, invalid index', () => { it('should throw error when index is invalid', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateFeeDelegatedValueTransfer(keyring) const invalidIndex = 4 const expectedError = `Invalid index(${invalidIndex}): index must be less than the length of keys(${invalidIndex}).` await expect(caver.wallet.signAsFeePayer(keyring.address, vt, invalidIndex)).to.be.rejectedWith(expectedError) }) }) context( 'CAVERJS-UNIT-KEYRINGCONTAINER-043: input: address, value transfer transaction, valid index, invalid hasher custom funtion', () => { it('should throw error when transaction hash is invalid', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateFeeDelegatedValueTransfer(keyring) const invalidTxHash = 'invalidTxHash' const expectedError = `Invalid transaction hash: ${invalidTxHash}` await expect(caver.wallet.signAsFeePayer(keyring.address, vt, 0, () => invalidTxHash)).to.be.rejectedWith(expectedError) }) } ) context('CAVERJS-UNIT-KEYRINGCONTAINER-044: input: not exist keyring address, value transfer transaction', () => { it('should throw error when keyring is not existed in wallet', async () => { const keyring = generateRoleBasedKeyring([3, 2, 4]) const vt = generateFeeDelegatedValueTransfer(keyring) const expectedError = `Failed to find keyring from wallet with ${keyring.address}` await expect(caver.wallet.signAsFeePayer(keyring.address, vt)).to.be.rejectedWith(expectedError) }) }) }) describe('wallet.signAsFeePayer', () => { context('CAVERJS-UNIT-KEYRINGCONTAINER-045: input: address, value transfer transaction', () => { it('should sign to transaction with keys in roleFeePayerKey and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateFeeDelegatedValueTransfer(keyring) const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendFeePayerSignatures') await caver.wallet.signAsFeePayer(keyring.address, vt) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledOnce expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-046: input: address, value transfer transaction, custom hasher', () => { it('should sign to transaction with keys in roleFeePayerKey and return hash', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateFeeDelegatedValueTransfer(keyring) const txHash = '0xe9a11d9ef95fb437f75d07ce768d43e74f158dd54b106e7d3746ce29d545b550' const fillFormatSpy = sinon.spy(vt, 'fillTransaction') const signSpy = sinon.spy(keyring, 'sign') const appendSpy = sinon.spy(vt, 'appendFeePayerSignatures') await caver.wallet.signAsFeePayer(keyring.address, vt, () => txHash) expect(fillFormatSpy).to.have.been.calledOnce expect(signSpy).to.have.been.calledWith(txHash, '0x7e3', 2) expect(appendSpy).to.have.been.calledOnce }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-047: input: address, value transfer transaction, invalid hasher custom funtion', () => { it('should throw error when transaction hash is invalid', async () => { const keyring = caver.wallet.add(generateRoleBasedKeyring([3, 2, 4])) const vt = generateFeeDelegatedValueTransfer(keyring) const invalidTxHash = 'invalidTxHash' const expectedError = `Invalid transaction hash: ${invalidTxHash}` await expect(caver.wallet.signAsFeePayer(keyring.address, vt, () => invalidTxHash)).to.be.rejectedWith(expectedError) }) }) context('CAVERJS-UNIT-KEYRINGCONTAINER-048: input: not exist keyring address, value transfer transaction', () => { it('should throw error when keyring is not existed in wallet', async () => { const keyring = generateRoleBasedKeyring([3, 2, 4]) const vt = generateFeeDelegatedValueTransfer(keyring) const expectedError = `Failed to find keyring from wallet with ${keyring.address}` await expect(caver.wallet.signAsFeePayer(keyring.address, vt)).to.be.rejectedWith(expectedError) }) }) }) function generateValueTransfer(keyring) { return new ValueTransfer({ from: keyring.address, to: keyring.address, value: '0x1', gas: '0x15f90', chainId: '0x7e3', nonce: '0x0', gasPrice: '0x5d21dba00', }) } function generateFeeDelegatedValueTransfer(keyring) { return new FeeDelegatedValueTransfer({ from: keyring.address, to: keyring.address, value: '0x1', gas: '0x15f90', chainId: '0x7e3', nonce: '0x0', gasPrice: '0x5d21dba00', }) } function generateAccountUpdate(keyring) { return new AccountUpdate({ from: keyring.address, account: keyring.toAccount(), gas: '0x15f90', chainId: '0x7e3', nonce: '0x0', gasPrice: '0x5d21dba00', }) }