UNPKG

caver-js

Version:

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

924 lines (772 loc) 92.3 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 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 RLP = require('eth-lib/lib/rlp') const { propertiesForUnnecessary } = require('../utils') const testRPCURL = require('../../testrpc') const Caver = require('../../../index') const Keyring = require('../../../packages/caver-wallet/src/keyring/keyringFactory') const SingleKeyring = require('../../../packages/caver-wallet/src/keyring/singleKeyring') const TransactionHasher = require('../../../packages/caver-transaction/src/transactionHasher/transactionHasher') const { generateRoleBasedKeyring, makeAccount, accountKeyTestCases, checkSignature, checkFeePayerSignature } = require('../utils') let caver let sender let feePayer let roleBasedKeyring let txObjWithLegacy let txObjWithPublic let txObjWithFail let txObjWithMultiSig let txObjWithRoleBased const expectedValues = [] let txsByAccountKeys = [] const sandbox = sinon.createSandbox() function makeAccountUpdateObjectWithExpectedValues() { { const testAddress = '0xac1aec09ef5f8dde6a0baf709ea388bbd7965f72' const account = caver.account.createWithAccountKeyLegacy(testAddress) const tx = { from: testAddress, account, gas: '0x493e0', nonce: '0x0', gasPrice: '0x5d21dba00', signatures: [ [ '0x0fe9', '0xd10f11309a670e133a408b7ebccf277e57af7d0701d5d811daec0dd8025ad961', '0x123e6dc3ca7a3603de954297fdf3d308c7ecdd43023f61121394182316313f82', ], ], feePayer: '0x23bf3d4eb274621e56ce65f6fa05da9e24785bb8', feePayerSignatures: [ [ '0x0fe9', '0x6d13eff0efc972b0ecf89c65e502eda4f97ebbd5cbcedcaa99af0c063b0d59cf', '0x4cc0be553bb13a4549eae8f2b140282e1baf29728ae118f2f575e53a25cc305b', ], ], chainId: '0x7e3', } expectedValues.push({}) expectedValues[accountKeyTestCases.LEGACY].tx = tx expectedValues[accountKeyTestCases.LEGACY].rlpEncodingForSigning = '0xeba5e421808505d21dba00830493e094ac1aec09ef5f8dde6a0baf709ea388bbd7965f728201c08207e38080' expectedValues[accountKeyTestCases.LEGACY].rlpEncodingForFeePayerSigning = '0xf840a5e421808505d21dba00830493e094ac1aec09ef5f8dde6a0baf709ea388bbd7965f728201c09423bf3d4eb274621e56ce65f6fa05da9e24785bb88207e38080' expectedValues[accountKeyTestCases.LEGACY].senderTxHash = '0xed17e28df6ed7ad8ae1b7fb25e1a81ce03c5b145fd62ea2281c866bd1a39ba43' expectedValues[accountKeyTestCases.LEGACY].transactionHash = '0x4ef87ddc379e003ff736085cd98842c085712b3218402052e318e12da752f810' expectedValues[accountKeyTestCases.LEGACY].rlpEncoding = '0x21f8ca808505d21dba00830493e094ac1aec09ef5f8dde6a0baf709ea388bbd7965f728201c0f847f845820fe9a0d10f11309a670e133a408b7ebccf277e57af7d0701d5d811daec0dd8025ad961a0123e6dc3ca7a3603de954297fdf3d308c7ecdd43023f61121394182316313f829423bf3d4eb274621e56ce65f6fa05da9e24785bb8f847f845820fe9a06d13eff0efc972b0ecf89c65e502eda4f97ebbd5cbcedcaa99af0c063b0d59cfa04cc0be553bb13a4549eae8f2b140282e1baf29728ae118f2f575e53a25cc305b' } { const testAddress = '0xac1aec09ef5f8dde6a0baf709ea388bbd7965f72' const pubKey = '0xd032771e5d927fb568cdf7605496b700277d7b9bcabe7657f45602348964e3963e290efde1cb8d1204659548bd50824cfa4b4d5199c66dbcceb3fb8de7f8b5b9' const account = caver.account.createWithAccountKeyPublic(testAddress, pubKey) const tx = { from: testAddress, account, gas: '0x493e0', nonce: '0x1', gasPrice: '0x5d21dba00', signatures: [ [ '0x0fe9', '0x0e1a3542288951226c66e6e8de320ddef4e0c0d6650baec828998a7ce411fe', '0x52d0766f3b84f35787d2a810f97057d215dcbe070cd890b7ccb8aaa3aac8eacc', ], ], feePayer: '0x23bf3d4eb274621e56ce65f6fa05da9e24785bb8', feePayerSignatures: [ [ '0x0fea', '0xfaca4cf91418c6fea61e9439620b656c7b0717b058fd8787865f4564a0f9974e', '0x3a483582435426e7b2aeffe3131a678ae54c7aa948fa5442b5ded209ba373221', ], ], chainId: '0x7e3', } expectedValues.push({}) expectedValues[accountKeyTestCases.PUBLIC].tx = tx expectedValues[accountKeyTestCases.PUBLIC].rlpEncodingForSigning = '0xf84eb847f84521018505d21dba00830493e094ac1aec09ef5f8dde6a0baf709ea388bbd7965f72a302a103d032771e5d927fb568cdf7605496b700277d7b9bcabe7657f45602348964e3968207e38080' expectedValues[accountKeyTestCases.PUBLIC].rlpEncodingForFeePayerSigning = '0xf863b847f84521018505d21dba00830493e094ac1aec09ef5f8dde6a0baf709ea388bbd7965f72a302a103d032771e5d927fb568cdf7605496b700277d7b9bcabe7657f45602348964e3969423bf3d4eb274621e56ce65f6fa05da9e24785bb88207e38080' expectedValues[accountKeyTestCases.PUBLIC].senderTxHash = '0x9fee61b7611d069477b9dec87f58cec7ef96d2559e441f7baf3f4468b3669784' expectedValues[accountKeyTestCases.PUBLIC].transactionHash = '0xe939f967e154f9d3400e9042fb9d0c58bcee914274d883aac8d2fe8aec8d56e9' expectedValues[accountKeyTestCases.PUBLIC].rlpEncoding = '0x21f8ea018505d21dba00830493e094ac1aec09ef5f8dde6a0baf709ea388bbd7965f72a302a103d032771e5d927fb568cdf7605496b700277d7b9bcabe7657f45602348964e396f846f844820fe99f0e1a3542288951226c66e6e8de320ddef4e0c0d6650baec828998a7ce411fea052d0766f3b84f35787d2a810f97057d215dcbe070cd890b7ccb8aaa3aac8eacc9423bf3d4eb274621e56ce65f6fa05da9e24785bb8f847f845820feaa0faca4cf91418c6fea61e9439620b656c7b0717b058fd8787865f4564a0f9974ea03a483582435426e7b2aeffe3131a678ae54c7aa948fa5442b5ded209ba373221' } { const testAddress = '0xac1aec09ef5f8dde6a0baf709ea388bbd7965f72' const account = caver.account.createWithAccountKeyFail(testAddress) const tx = { from: testAddress, account, gas: '0x186a0', nonce: '0x4', gasPrice: '0x5d21dba00', signatures: [ [ '0x0fea', '0x31115ed4fdf3cdc9c3071be0c14a992d1ca70b02382b3fadb2428a60f411edcb', '0x33530406db890a6c144759f72977739edfe2f9718966de52d6dada0a70be27ae', ], [ '0x0fe9', '0x2b50229dc8d4c18414d1f8f943658ca22e6c08a57f52e7e77910d01c1bb49286', '0x795fc16b6327c41593eb9b7ea5bbf2c61e3b4b3e5cd3176d3ebd57007fa4842b', ], [ '0x0fea', '0xd5e3d18cd12fb36180adad4df5b9f15089ac9f8448e7a7eeb0fc0f6497faa98d', '0x246503976acea8e9a91e630963eaa344b193fc4e747c1ccaae253083d2695e96', ], ], feePayer: '0x23bf3d4eb274621e56ce65f6fa05da9e24785bb8', feePayerSignatures: [ [ '0x0fea', '0x4dfc5650bf203652b440ba53791f0adc07c2fae0e746efbda2b5117c568474d3', '0x72bea336107273fd0e1624d4f70425bb040e59e8f2b5d856fc22ab898c2b156e', ], ], chainId: '0x7e3', } expectedValues.push({}) expectedValues[accountKeyTestCases.FAIL].tx = tx expectedValues[accountKeyTestCases.FAIL].rlpEncodingForSigning = '0xeba5e421048505d21dba00830186a094ac1aec09ef5f8dde6a0baf709ea388bbd7965f728203c08207e38080' expectedValues[accountKeyTestCases.FAIL].rlpEncodingForFeePayerSigning = '0xf840a5e421048505d21dba00830186a094ac1aec09ef5f8dde6a0baf709ea388bbd7965f728203c09423bf3d4eb274621e56ce65f6fa05da9e24785bb88207e38080' expectedValues[accountKeyTestCases.FAIL].senderTxHash = '0xed215e3932acb07b94a5b0482f48c04e76e41749f88bfddfa70c7fe2f6daa278' expectedValues[accountKeyTestCases.FAIL].transactionHash = '0xd8b8da94309ca9495d16e3d8e04df3a386ba338c5839bdcf8cee7f796b10e1a7' expectedValues[accountKeyTestCases.FAIL].rlpEncoding = '0x21f90158048505d21dba00830186a094ac1aec09ef5f8dde6a0baf709ea388bbd7965f728203c0f8d5f845820feaa031115ed4fdf3cdc9c3071be0c14a992d1ca70b02382b3fadb2428a60f411edcba033530406db890a6c144759f72977739edfe2f9718966de52d6dada0a70be27aef845820fe9a02b50229dc8d4c18414d1f8f943658ca22e6c08a57f52e7e77910d01c1bb49286a0795fc16b6327c41593eb9b7ea5bbf2c61e3b4b3e5cd3176d3ebd57007fa4842bf845820feaa0d5e3d18cd12fb36180adad4df5b9f15089ac9f8448e7a7eeb0fc0f6497faa98da0246503976acea8e9a91e630963eaa344b193fc4e747c1ccaae253083d2695e969423bf3d4eb274621e56ce65f6fa05da9e24785bb8f847f845820feaa04dfc5650bf203652b440ba53791f0adc07c2fae0e746efbda2b5117c568474d3a072bea336107273fd0e1624d4f70425bb040e59e8f2b5d856fc22ab898c2b156e' } { const testAddress = '0xed2f77b1962805385512c18ad6d66f3dee3def15' const pubArray = [ '0xac1350e8b234a7dac087e4899d5b30687bd153d181faaf4ef11fea7d1acbecf45669b120fd488cf638f7ea83cfe009d85b949aacd51cde80e3162a17aa5160f7', '0x798096c2691444e7c579e04f13c6edeb122b9e35718c041a51b74ccd5f1a086f2e499900717c718a434b15a989d4c33bae18a65f4c1e6b48f8103478cf1e5ef5', '0xaeb9ab821099f4c5d80caafbc0d1980a1a1a701cab8cd0cca8e2f187263a992d5bbf8ea44a1f9bf577175fdccc953c8b8d1bbeeefdabd839be1fcf89f532f470', ] const options = new caver.account.weightedMultiSigOptions(2, [1, 2, 3]) const account = caver.account.createWithAccountKeyWeightedMultiSig(testAddress, pubArray, options) const tx = { from: testAddress, account, gas: '0x55730', nonce: '0x2', gasPrice: '0x5d21dba00', signatures: [ [ '0x0fe9', '0x3665a7ef1b6bc74171c00cca93380e4a28ff01090a28b9e7f861ca5c01cc26ae', '0x0bb148b53761c946bd154506317625aab8b910cf55185d16158e0fef67dd0a6c', ], ], feePayer: '0x23bf3d4eb274621e56ce65f6fa05da9e24785bb8', feePayerSignatures: [ [ '0x0fe9', '0xd0275ad7a55bf6b3f30c5cd27a2940ba574f05d9650e41f08dce929a1b7985b3', '0x15576c4473dc7c42df9b1d9f106fbfc8a38646f4adca26f4a14a04ea5bd7351d', ], ], chainId: '0x7e3', } expectedValues.push({}) expectedValues[accountKeyTestCases.MULTISIG].tx = tx expectedValues[accountKeyTestCases.MULTISIG].rlpEncodingForSigning = '0xf89eb897f89521028505d21dba008305573094ed2f77b1962805385512c18ad6d66f3dee3def15b87204f86f02f86ce301a103ac1350e8b234a7dac087e4899d5b30687bd153d181faaf4ef11fea7d1acbecf4e302a103798096c2691444e7c579e04f13c6edeb122b9e35718c041a51b74ccd5f1a086fe303a102aeb9ab821099f4c5d80caafbc0d1980a1a1a701cab8cd0cca8e2f187263a992d8207e38080' expectedValues[accountKeyTestCases.MULTISIG].rlpEncodingForFeePayerSigning = '0xf8b3b897f89521028505d21dba008305573094ed2f77b1962805385512c18ad6d66f3dee3def15b87204f86f02f86ce301a103ac1350e8b234a7dac087e4899d5b30687bd153d181faaf4ef11fea7d1acbecf4e302a103798096c2691444e7c579e04f13c6edeb122b9e35718c041a51b74ccd5f1a086fe303a102aeb9ab821099f4c5d80caafbc0d1980a1a1a701cab8cd0cca8e2f187263a992d9423bf3d4eb274621e56ce65f6fa05da9e24785bb88207e38080' expectedValues[accountKeyTestCases.MULTISIG].senderTxHash = '0x873f2a5f234a276c64a05c8036720db0c0dbf75770a137746952d925b6fff0a1' expectedValues[accountKeyTestCases.MULTISIG].transactionHash = '0xd2b7b5487b530e4ae3e164837cef3da078f4ba5ef6fbdafa4498edc83fb5ee45' expectedValues[accountKeyTestCases.MULTISIG].rlpEncoding = '0x21f9013b028505d21dba008305573094ed2f77b1962805385512c18ad6d66f3dee3def15b87204f86f02f86ce301a103ac1350e8b234a7dac087e4899d5b30687bd153d181faaf4ef11fea7d1acbecf4e302a103798096c2691444e7c579e04f13c6edeb122b9e35718c041a51b74ccd5f1a086fe303a102aeb9ab821099f4c5d80caafbc0d1980a1a1a701cab8cd0cca8e2f187263a992df847f845820fe9a03665a7ef1b6bc74171c00cca93380e4a28ff01090a28b9e7f861ca5c01cc26aea00bb148b53761c946bd154506317625aab8b910cf55185d16158e0fef67dd0a6c9423bf3d4eb274621e56ce65f6fa05da9e24785bb8f847f845820fe9a0d0275ad7a55bf6b3f30c5cd27a2940ba574f05d9650e41f08dce929a1b7985b3a015576c4473dc7c42df9b1d9f106fbfc8a38646f4adca26f4a14a04ea5bd7351d' } { const testAddress = '0xed2f77b1962805385512c18ad6d66f3dee3def15' const pubArray = [ [ '0xca112896b2025047790bbcc74f48af339f71390b5335b5e657b50ef8f634fb9fb4f7caf09ec53e8ec0d78253c37d30367631ac44c4b4825b9b5a7bfb6b55b5af', '0xec93c2f3990b61e692467cc2c49b9ff2f595002234c8116bae8807ff0236bd5e99e943b81be279230a218d297069099d873f49b12557ce6ac5bdeee8ddb83665', '0x99a40e6be991d48c9a5604059517cf489c77d35df64d1ff0233469ff27350652e907ed7a6e1662730d9d22a6b102e44b499dd271802452bd668229db0fc4750c', ], [ '0xf890dfeca00111977dd6be8198466099ba6528e40403fe32a9994cd03ad18f3d24f3776a5e445b34b8654d9c56fe2397d8ed4989614dfefb776f038e024436ea', '0xfeedab225d4008d162e495fef4aba1b315369a140837d1150acecb71bb1c7faaef896b4a3e917824b18626fc86c2ab2f11307870a0ed2e72a2d8cfdaef5509bc', '0xfff2068f7ab4ae7faed86395647502ec6c8219eebe13858ddaaf01112bf40de6dfe82af9538d96465bf11d49d3d5d56b7868476bfb3a1d930177aa05b0345603', ], [ '0x3a8547ed514797bac885e5aaf2d8ee7a5b3df542efdf28b3886bd5b925f5231c1f2e0d8c9fedae714a5bd71411cb0ec60d63246b04daeedd3ff4ccd1fc95ecc4', '0x13c45e4cbb231ba8150e5943a85a0ac9d6e7a347fcbc27833067e6ee0e63346dbf4c3e290296d9ea700f721b4f056582383be954b6a68525aae197a0f5813f73', '0xc45e5eb35215d1a945ef3790b4689e9644e0b14661bdb2f5d0e3bb1b729f091d054a3c972a93421ccb80e29b0af9ce0c0d7ec5f773b25d7769837114a339c935', ], ] const account = caver.account.createWithAccountKeyRoleBased(testAddress, pubArray) const transactionWithRolebased = { from: testAddress, account, gas: '0x61a80', nonce: '0x3', gasPrice: '0x5d21dba00', signatures: [ [ '0x0fea', '0xbedc71cfef422e80c32b752b4ebac9ee9e047f3beea07f1929b3f2543dddfd6d', '0x5454e3c2164fb6b844ccf74e07ca8420d427a3ca0f2f15b20be6c285ba308f45', ], [ '0x0fea', '0x66530029fde1835b844505657d15e6457e432744107c3111b998ce1e76a548f6', '0x2b045a9959d522f738390f47a528045845896bf818e35355367e017bd1f41644', ], [ '0x0fea', '0x15e210db2922121c4a8f1223149846844a1923212892acf66df0d0b3daab8b58', '0x07680c111780bada54d62c62c8182984e92ec4817d59c313046d1f8030c001e7', ], ], feePayer: '0x23bf3d4eb274621e56ce65f6fa05da9e24785bb8', feePayerSignatures: [ [ '0x0fe9', '0x5801ee7887b401d34888d9141915c167c5bfce429d836c1acbc229b9c6938481', '0x0f4c01747d3e5f6221063d7e74efc5c7d59020a74dce1c7e37e9a78d5d31de44', ], ], chainId: '0x7e3', } expectedValues.push({}) expectedValues[accountKeyTestCases.ROLEBAED].tx = transactionWithRolebased expectedValues[accountKeyTestCases.ROLEBAED].rlpEncodingForSigning = '0xf9018fb90187f9018421038505d21dba0083061a8094ed2f77b1962805385512c18ad6d66f3dee3def15b9016005f9015cb87204f86f01f86ce301a103ca112896b2025047790bbcc74f48af339f71390b5335b5e657b50ef8f634fb9fe301a103ec93c2f3990b61e692467cc2c49b9ff2f595002234c8116bae8807ff0236bd5ee301a10299a40e6be991d48c9a5604059517cf489c77d35df64d1ff0233469ff27350652b87204f86f01f86ce301a102f890dfeca00111977dd6be8198466099ba6528e40403fe32a9994cd03ad18f3de301a102feedab225d4008d162e495fef4aba1b315369a140837d1150acecb71bb1c7faae301a103fff2068f7ab4ae7faed86395647502ec6c8219eebe13858ddaaf01112bf40de6b87204f86f01f86ce301a1023a8547ed514797bac885e5aaf2d8ee7a5b3df542efdf28b3886bd5b925f5231ce301a10313c45e4cbb231ba8150e5943a85a0ac9d6e7a347fcbc27833067e6ee0e63346de301a103c45e5eb35215d1a945ef3790b4689e9644e0b14661bdb2f5d0e3bb1b729f091d8207e38080' expectedValues[accountKeyTestCases.ROLEBAED].rlpEncodingForFeePayerSigning = '0xf901a4b90187f9018421038505d21dba0083061a8094ed2f77b1962805385512c18ad6d66f3dee3def15b9016005f9015cb87204f86f01f86ce301a103ca112896b2025047790bbcc74f48af339f71390b5335b5e657b50ef8f634fb9fe301a103ec93c2f3990b61e692467cc2c49b9ff2f595002234c8116bae8807ff0236bd5ee301a10299a40e6be991d48c9a5604059517cf489c77d35df64d1ff0233469ff27350652b87204f86f01f86ce301a102f890dfeca00111977dd6be8198466099ba6528e40403fe32a9994cd03ad18f3de301a102feedab225d4008d162e495fef4aba1b315369a140837d1150acecb71bb1c7faae301a103fff2068f7ab4ae7faed86395647502ec6c8219eebe13858ddaaf01112bf40de6b87204f86f01f86ce301a1023a8547ed514797bac885e5aaf2d8ee7a5b3df542efdf28b3886bd5b925f5231ce301a10313c45e4cbb231ba8150e5943a85a0ac9d6e7a347fcbc27833067e6ee0e63346de301a103c45e5eb35215d1a945ef3790b4689e9644e0b14661bdb2f5d0e3bb1b729f091d9423bf3d4eb274621e56ce65f6fa05da9e24785bb88207e38080' expectedValues[accountKeyTestCases.ROLEBAED].senderTxHash = '0x21a6004af918a61c1f0b6420cb85b329ac65a5cca0a668d207cfd1796470313e' expectedValues[accountKeyTestCases.ROLEBAED].transactionHash = '0x73540a1b47ec1836dae7657cfb8a7e7ae3e7e5cc54fd33f58b9f7efca6d8692c' expectedValues[accountKeyTestCases.ROLEBAED].rlpEncoding = '0x21f902b8038505d21dba0083061a8094ed2f77b1962805385512c18ad6d66f3dee3def15b9016005f9015cb87204f86f01f86ce301a103ca112896b2025047790bbcc74f48af339f71390b5335b5e657b50ef8f634fb9fe301a103ec93c2f3990b61e692467cc2c49b9ff2f595002234c8116bae8807ff0236bd5ee301a10299a40e6be991d48c9a5604059517cf489c77d35df64d1ff0233469ff27350652b87204f86f01f86ce301a102f890dfeca00111977dd6be8198466099ba6528e40403fe32a9994cd03ad18f3de301a102feedab225d4008d162e495fef4aba1b315369a140837d1150acecb71bb1c7faae301a103fff2068f7ab4ae7faed86395647502ec6c8219eebe13858ddaaf01112bf40de6b87204f86f01f86ce301a1023a8547ed514797bac885e5aaf2d8ee7a5b3df542efdf28b3886bd5b925f5231ce301a10313c45e4cbb231ba8150e5943a85a0ac9d6e7a347fcbc27833067e6ee0e63346de301a103c45e5eb35215d1a945ef3790b4689e9644e0b14661bdb2f5d0e3bb1b729f091df8d5f845820feaa0bedc71cfef422e80c32b752b4ebac9ee9e047f3beea07f1929b3f2543dddfd6da05454e3c2164fb6b844ccf74e07ca8420d427a3ca0f2f15b20be6c285ba308f45f845820feaa066530029fde1835b844505657d15e6457e432744107c3111b998ce1e76a548f6a02b045a9959d522f738390f47a528045845896bf818e35355367e017bd1f41644f845820feaa015e210db2922121c4a8f1223149846844a1923212892acf66df0d0b3daab8b58a007680c111780bada54d62c62c8182984e92ec4817d59c313046d1f8030c001e79423bf3d4eb274621e56ce65f6fa05da9e24785bb8f847f845820fe9a05801ee7887b401d34888d9141915c167c5bfce429d836c1acbc229b9c6938481a00f4c01747d3e5f6221063d7e74efc5c7d59020a74dce1c7e37e9a78d5d31de44' } } before(() => { caver = new Caver(testRPCURL) sender = caver.wallet.add(caver.wallet.keyring.generate()) feePayer = caver.wallet.add(caver.wallet.keyring.generate()) roleBasedKeyring = generateRoleBasedKeyring([3, 3, 3]) const commonObj = { from: sender.address, gas: '0x3b9ac9ff', feePayer: feePayer.address, } txObjWithLegacy = { account: makeAccount(sender.address, accountKeyTestCases.LEGACY), ...commonObj } txObjWithPublic = { account: makeAccount(sender.address, accountKeyTestCases.PUBLIC), ...commonObj } txObjWithFail = { account: makeAccount(sender.address, accountKeyTestCases.FAIL), ...commonObj } txObjWithMultiSig = { account: makeAccount(sender.address, accountKeyTestCases.MULTISIG), ...commonObj } txObjWithRoleBased = { account: makeAccount(sender.address, accountKeyTestCases.ROLEBAED, [ { threshold: 2, weights: [1, 1, 1] }, {}, { threshold: 1, weights: [1, 1] }, ]), ...commonObj, } makeAccountUpdateObjectWithExpectedValues() }) describe('TxTypeFeeDelegatedAccountUpdate', () => { let getGasPriceSpy let getHeaderSpy let getNonceSpy let getChainIdSpy beforeEach(() => { txsByAccountKeys = [] txsByAccountKeys.push(caver.transaction.feeDelegatedAccountUpdate.create(txObjWithLegacy)) txsByAccountKeys.push(caver.transaction.feeDelegatedAccountUpdate.create(txObjWithPublic)) txsByAccountKeys.push(caver.transaction.feeDelegatedAccountUpdate.create(txObjWithFail)) txsByAccountKeys.push(caver.transaction.feeDelegatedAccountUpdate.create(txObjWithMultiSig)) txsByAccountKeys.push(caver.transaction.feeDelegatedAccountUpdate.create(txObjWithRoleBased)) getGasPriceSpy = sandbox.stub(caver.transaction.klaytnCall, 'getGasPrice') getGasPriceSpy.returns('0x5d21dba00') getHeaderSpy = sandbox.stub(caver.transaction.klaytnCall, 'getHeaderByNumber') getHeaderSpy.returns({ baseFeePerGas: '0x5d21dba00' }) getNonceSpy = sandbox.stub(caver.transaction.klaytnCall, 'getTransactionCount') getNonceSpy.returns('0x3a') getChainIdSpy = sandbox.stub(caver.transaction.klaytnCall, 'getChainId') getChainIdSpy.returns('0x7e3') }) afterEach(() => { sandbox.restore() }) context('create feeDelegatedAccountUpdate instance', () => { it('CAVERJS-UNIT-TRANSACTIONFD-150: If feeDelegatedAccountUpdate not define from, return error', () => { const testUpdateObj = { ...txObjWithPublic } delete testUpdateObj.from const expectedError = '"from" is missing' expect(() => caver.transaction.feeDelegatedAccountUpdate.create(testUpdateObj)).to.throw(expectedError) }) it('CAVERJS-UNIT-TRANSACTIONFD-151: If feeDelegatedAccountUpdate not define gas, return error', () => { const testUpdateObj = { ...txObjWithPublic } delete testUpdateObj.gas const expectedError = '"gas" is missing' expect(() => caver.transaction.feeDelegatedAccountUpdate.create(testUpdateObj)).to.throw(expectedError) }) it('CAVERJS-UNIT-TRANSACTIONFD-152: If accountUpdate not define gas, return error', () => { const testUpdateObj = { ...txObjWithPublic } delete testUpdateObj.account const expectedError = 'Missing account information with TxTypeFeeDelegatedAccountUpdate transaction' expect(() => caver.transaction.feeDelegatedAccountUpdate.create(testUpdateObj)).to.throw(expectedError) }) it('CAVERJS-UNIT-TRANSACTIONFD-153: If feeDelegatedAccountUpdate define from property with invalid address, return error', () => { const testUpdateObj = { ...txObjWithPublic } testUpdateObj.from = 'invalid' const expectedError = `Invalid address of from: ${testUpdateObj.from}` expect(() => caver.transaction.feeDelegatedAccountUpdate.create(testUpdateObj)).to.throw(expectedError) }) it('CAVERJS-UNIT-TRANSACTIONFD-154: If feeDelegatedAccountUpdate define feePayer property with invalid address, return error', () => { const testUpdateObj = { ...txObjWithPublic } testUpdateObj.feePayer = 'invalid' const expectedError = `Invalid address of fee payer: ${testUpdateObj.feePayer}` expect(() => caver.transaction.feeDelegatedAccountUpdate.create(testUpdateObj)).to.throw(expectedError) }) it('CAVERJS-UNIT-TRANSACTIONFD-155: If feeDelegatedAccountUpdate define feePayerSignatures property without feePayer, return error', () => { const testUpdateObj = { ...txObjWithPublic } testUpdateObj.feePayer = '0x' testUpdateObj.feePayerSignatures = [ [ '0x26', '0xf45cf8d7f88c08e6b6ec0b3b562f34ca94283e4689021987abb6b0772ddfd80a', '0x298fe2c5aeabb6a518f4cbb5ff39631a5d88be505d3923374f65fdcf63c2955b', ], ] const expectedError = '"feePayer" is missing: feePayer must be defined with feePayerSignatures.' expect(() => caver.transaction.feeDelegatedAccountUpdate.create(testUpdateObj)).to.throw(expectedError) testUpdateObj.feePayer = '0x0000000000000000000000000000000000000000' expect(() => caver.transaction.feeDelegatedAccountUpdate.create(testUpdateObj)).to.throw(expectedError) }) it('CAVERJS-UNIT-TRANSACTIONFD-156: If feeDelegatedAccountUpdate define unnecessary property, return error', () => { const testUpdateObj = { ...txObjWithPublic } const unnecessaries = [ propertiesForUnnecessary.data, propertiesForUnnecessary.input, propertiesForUnnecessary.to, propertiesForUnnecessary.value, propertiesForUnnecessary.codeFormat, propertiesForUnnecessary.failKey, propertiesForUnnecessary.feeRatio, propertiesForUnnecessary.key, propertiesForUnnecessary.legacyKey, propertiesForUnnecessary.publicKey, propertiesForUnnecessary.failKey, propertiesForUnnecessary.multisig, propertiesForUnnecessary.roleTransactionKey, propertiesForUnnecessary.roleAccountUpdateKey, propertiesForUnnecessary.roleFeePayerKey, propertiesForUnnecessary.humanReadable, propertiesForUnnecessary.accessList, propertiesForUnnecessary.maxPriorityFeePerGas, propertiesForUnnecessary.maxFeePerGas, ] for (let i = 0; i < unnecessaries.length; i++) { if (i > 0) delete testUpdateObj[unnecessaries[i - 1].name] testUpdateObj[unnecessaries[i].name] = unnecessaries[i].value const expectedError = `"${unnecessaries[i].name}" cannot be used with ${caver.transaction.type.TxTypeFeeDelegatedAccountUpdate} transaction` expect(() => caver.transaction.feeDelegatedAccountUpdate.create(testUpdateObj)).to.throw(expectedError) } }) }) context('feeDelegatedAccountUpdate.getRLPEncoding', () => { it('CAVERJS-UNIT-TRANSACTIONFD-157: returns RLP-encoded string.', () => { for (let i = 0; i < expectedValues.length; i++) { const tx = caver.transaction.feeDelegatedAccountUpdate.create(expectedValues[i].tx) expect(tx.getRLPEncoding()).to.equal(expectedValues[i].rlpEncoding) } }) it('CAVERJS-UNIT-TRANSACTIONFD-158: getRLPEncoding should throw error when nonce is undefined', () => { for (let i = 0; i < expectedValues.length; i++) { const tx = caver.transaction.feeDelegatedAccountUpdate.create(expectedValues[i].tx) delete tx._nonce const expectedError = `nonce is undefined. Define nonce in transaction or use 'transaction.fillTransaction' to fill values.` expect(() => tx.getRLPEncoding()).to.throw(expectedError) } }) it('CAVERJS-UNIT-TRANSACTIONFD-159: getRLPEncoding should throw error when gasPrice is undefined', () => { for (let i = 0; i < expectedValues.length; i++) { const tx = caver.transaction.feeDelegatedAccountUpdate.create(expectedValues[i].tx) delete tx._gasPrice const expectedError = `gasPrice is undefined. Define gasPrice in transaction or use 'transaction.fillTransaction' to fill values.` expect(() => tx.getRLPEncoding()).to.throw(expectedError) } }) }) context('feeDelegatedAccountUpdate.sign', () => { const txHash = '0xe9a11d9ef95fb437f75d07ce768d43e74f158dd54b106e7d3746ce29d545b550' const fillTransactionSpys = [] const appendSignaturesSpys = [] let createFromPrivateKeySpy let senderSignSpy let hasherSpy beforeEach(() => { for (let i = 0; i < txsByAccountKeys.length; i++) { fillTransactionSpys.push(sandbox.spy(txsByAccountKeys[i], 'fillTransaction')) appendSignaturesSpys.push(sandbox.spy(txsByAccountKeys[i], 'appendSignatures')) } createFromPrivateKeySpy = sandbox.spy(Keyring, 'createFromPrivateKey') senderSignSpy = sandbox.spy(sender, 'sign') hasherSpy = sandbox.stub(TransactionHasher, 'getHashForSignature') hasherSpy.returns(txHash) }) afterEach(() => { sandbox.restore() }) function checkFunctionCall(idx, customHasher = false) { expect(fillTransactionSpys[idx]).to.have.been.calledOnce expect(appendSignaturesSpys[idx]).to.have.been.calledOnce if (!customHasher) expect(hasherSpy).to.have.been.calledWith(txsByAccountKeys[idx]) } it('CAVERJS-UNIT-TRANSACTIONFD-161: input: keyring. should sign transaction.', async () => { for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.sign(sender) checkFunctionCall(i) checkSignature(tx) expect(senderSignSpy).to.have.been.calledWith(txHash, '0x7e3', 1, undefined) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-162: input: private key string. should sign transaction.', async () => { const signProtoSpy = sandbox.spy(SingleKeyring.prototype, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.sign(sender.key.privateKey) checkFunctionCall(i) checkSignature(tx) expect(signProtoSpy).to.have.been.calledWith(txHash, '0x7e3', 1, undefined) } expect(createFromPrivateKeySpy).to.have.been.callCount(Object.keys(txsByAccountKeys).length) }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-163: input: KlaytnWalletKey. should sign transaction.', async () => { const signProtoSpy = sandbox.spy(SingleKeyring.prototype, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.sign(sender.getKlaytnWalletKey()) checkFunctionCall(i) checkSignature(tx) expect(signProtoSpy).to.have.been.calledWith(txHash, '0x7e3', 1, undefined) } expect(createFromPrivateKeySpy).to.have.been.callCount(Object.keys(txsByAccountKeys).length) }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-164: input: keyring, index. should sign transaction with specific index.', async () => { const roleBasedSignSpy = sandbox.spy(roleBasedKeyring, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.from = roleBasedKeyring.address await tx.sign(roleBasedKeyring, 1) checkFunctionCall(i) checkSignature(tx) expect(roleBasedSignSpy).to.have.been.calledWith(txHash, '0x7e3', 1, 1) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-165: input: keyring, custom hasher. should use custom hasher.', async () => { const hashForCustomHasher = '0x9e4b4835f6ea5ce55bd1037fe92040dd070af6154aefc30d32c65364a1123cae' const customHasher = () => hashForCustomHasher const roleBasedSignSpy = sandbox.spy(roleBasedKeyring, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.from = roleBasedKeyring.address await tx.sign(roleBasedKeyring, customHasher) checkFunctionCall(i, true) checkSignature(tx, { expectedLength: roleBasedKeyring.roleAccountUpdateKey.length }) expect(createFromPrivateKeySpy).not.to.have.been.calledOnce expect(roleBasedSignSpy).to.have.been.calledWith(hashForCustomHasher, '0x7e3', 1, undefined) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-166: input: keyring, index, custom hasher. should use custom hasher when sign transaction.', async () => { const hashForCustomHasher = '0x9e4b4835f6ea5ce55bd1037fe92040dd070af6154aefc30d32c65364a1123cae' const customHasher = () => hashForCustomHasher const roleBasedSignSpy = sandbox.spy(roleBasedKeyring, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.from = roleBasedKeyring.address await tx.sign(roleBasedKeyring, 1, customHasher) checkFunctionCall(i, true) checkSignature(tx) expect(createFromPrivateKeySpy).not.to.have.been.calledOnce expect(roleBasedSignSpy).to.have.been.calledWith(hashForCustomHasher, '0x7e3', 1, 1) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-167: input: keyring. should throw error when from is different.', async () => { for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.from = roleBasedKeyring.address const expectedError = `The from address of the transaction is different with the address of the keyring to use.` await expect(tx.sign(sender)).to.be.rejectedWith(expectedError) } }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-168: input: rolebased keyring, index out of range. should throw error.', async () => { for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.from = roleBasedKeyring.address const expectedError = `Invalid index(10): index must be less than the length of keys(${roleBasedKeyring.keys[0].length}).` await expect(tx.sign(roleBasedKeyring, 10)).to.be.rejectedWith(expectedError) } }) }) context('feeDelegatedAccountUpdate.signAsFeePayer', () => { const txHash = '0xe9a11d9ef95fb437f75d07ce768d43e74f158dd54b106e7d3746ce29d545b550' const fillTransactionSpys = [] const appendSignaturesSpys = [] let createFromPrivateKeySpy let feePayerSignSpy let hasherSpy beforeEach(() => { for (let i = 0; i < txsByAccountKeys.length; i++) { fillTransactionSpys.push(sandbox.spy(txsByAccountKeys[i], 'fillTransaction')) appendSignaturesSpys.push(sandbox.spy(txsByAccountKeys[i], 'appendFeePayerSignatures')) } createFromPrivateKeySpy = sandbox.spy(Keyring, 'createFromPrivateKey') feePayerSignSpy = sandbox.spy(feePayer, 'sign') hasherSpy = sandbox.stub(TransactionHasher, 'getHashForFeePayerSignature') hasherSpy.returns(txHash) }) afterEach(() => { sandbox.restore() }) function checkFunctionCall(idx, customHasher = false) { expect(fillTransactionSpys[idx]).to.have.been.calledOnce expect(appendSignaturesSpys[idx]).to.have.been.calledOnce if (!customHasher) expect(hasherSpy).to.have.been.calledWith(txsByAccountKeys[idx]) } it('CAVERJS-UNIT-TRANSACTIONFD-169: input: keyring. If feePayer is not defined, should be set with keyring address.', async () => { for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.feePayer = '0x' await tx.signAsFeePayer(feePayer) expect(tx.feePayer.toLowerCase()).to.equal(feePayer.address.toLowerCase()) checkFunctionCall(i) checkFeePayerSignature(tx) expect(feePayerSignSpy).to.have.been.calledWith(txHash, '0x7e3', 2, undefined) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-170: input: keyring. should sign transaction.', async () => { for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.signAsFeePayer(feePayer) checkFunctionCall(i) checkFeePayerSignature(tx) expect(feePayerSignSpy).to.have.been.calledWith(txHash, '0x7e3', 2, undefined) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-171: input: private key string. should sign transaction.', async () => { const signProtoSpy = sandbox.spy(SingleKeyring.prototype, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.signAsFeePayer(feePayer.key.privateKey) checkFunctionCall(i) checkFeePayerSignature(tx) expect(signProtoSpy).to.have.been.calledWith(txHash, '0x7e3', 2, undefined) } expect(createFromPrivateKeySpy).to.have.been.callCount(Object.keys(txsByAccountKeys).length) }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-172: input: KlaytnWalletKey. should sign transaction.', async () => { const signProtoSpy = sandbox.spy(SingleKeyring.prototype, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.signAsFeePayer(feePayer.getKlaytnWalletKey()) checkFunctionCall(i) checkFeePayerSignature(tx) expect(signProtoSpy).to.have.been.calledWith(txHash, '0x7e3', 2, undefined) } expect(createFromPrivateKeySpy).to.have.been.callCount(Object.keys(txsByAccountKeys).length) }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-173: input: keyring, index. should sign transaction with specific index.', async () => { const roleBasedSignSpy = sandbox.spy(roleBasedKeyring, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.feePayer = roleBasedKeyring.address await tx.signAsFeePayer(roleBasedKeyring, 1) checkFunctionCall(i) checkFeePayerSignature(tx) expect(roleBasedSignSpy).to.have.been.calledWith(txHash, '0x7e3', 2, 1) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-174: input: keyring, custom hasher. should use custom hasher.', async () => { const hashForCustomHasher = '0x9e4b4835f6ea5ce55bd1037fe92040dd070af6154aefc30d32c65364a1123cae' const customHasher = () => hashForCustomHasher const roleBasedSignSpy = sandbox.spy(roleBasedKeyring, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.feePayer = roleBasedKeyring.address await tx.signAsFeePayer(roleBasedKeyring, customHasher) checkFunctionCall(i, true) checkFeePayerSignature(tx, { expectedLength: roleBasedKeyring.roleFeePayerKey.length }) expect(createFromPrivateKeySpy).not.to.have.been.calledOnce expect(roleBasedSignSpy).to.have.been.calledWith(hashForCustomHasher, '0x7e3', 2, undefined) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-175: input: keyring, index, custom hasher. should use custom hasher when sign transaction.', async () => { const hashForCustomHasher = '0x9e4b4835f6ea5ce55bd1037fe92040dd070af6154aefc30d32c65364a1123cae' const customHasher = () => hashForCustomHasher const roleBasedSignSpy = sandbox.spy(roleBasedKeyring, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.feePayer = roleBasedKeyring.address await tx.signAsFeePayer(roleBasedKeyring, 1, customHasher) checkFunctionCall(i, true) checkFeePayerSignature(tx) expect(createFromPrivateKeySpy).not.to.have.been.calledOnce expect(roleBasedSignSpy).to.have.been.calledWith(hashForCustomHasher, '0x7e3', 2, 1) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-176: input: keyring. should throw error when feePayer is different.', async () => { for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.feePayer = roleBasedKeyring.address const expectedError = `The feePayer address of the transaction is different with the address of the keyring to use.` await expect(tx.signAsFeePayer(sender)).to.be.rejectedWith(expectedError) } }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-177: input: rolebased keyring, index out of range. should throw error.', async () => { for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.feePayer = roleBasedKeyring.address const expectedError = `Invalid index(10): index must be less than the length of keys(${roleBasedKeyring.keys[0].length}).` await expect(tx.signAsFeePayer(roleBasedKeyring, 10)).to.be.rejectedWith(expectedError) } }).timeout(200000) }) context('feeDelegatedAccountUpdate.sign with multiple keys', () => { const txHash = '0xe9a11d9ef95fb437f75d07ce768d43e74f158dd54b106e7d3746ce29d545b550' const fillTransactionSpys = [] const appendSignaturesSpys = [] let createFromPrivateKeySpy let senderSignWithKeysSpy let hasherSpy beforeEach(() => { for (let i = 0; i < txsByAccountKeys.length; i++) { fillTransactionSpys.push(sandbox.spy(txsByAccountKeys[i], 'fillTransaction')) appendSignaturesSpys.push(sandbox.spy(txsByAccountKeys[i], 'appendSignatures')) } createFromPrivateKeySpy = sandbox.spy(Keyring, 'createFromPrivateKey') senderSignWithKeysSpy = sandbox.spy(sender, 'sign') hasherSpy = sandbox.stub(TransactionHasher, 'getHashForSignature') hasherSpy.returns(txHash) }) afterEach(() => { sandbox.restore() }) function checkFunctionCall(idx, customHasher = false) { expect(fillTransactionSpys[idx]).to.have.been.calledOnce expect(appendSignaturesSpys[idx]).to.have.been.calledOnce if (!customHasher) expect(hasherSpy).to.have.been.calledWith(txsByAccountKeys[idx]) } it('CAVERJS-UNIT-TRANSACTIONFD-178: input: keyring. should sign transaction.', async () => { for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.sign(sender) checkFunctionCall(i) checkSignature(tx) expect(senderSignWithKeysSpy).to.have.been.calledWith(txHash, '0x7e3', 1) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-179: input: private key string. should sign transaction.', async () => { const signProtoSpy = sandbox.spy(SingleKeyring.prototype, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.sign(sender.key.privateKey) checkFunctionCall(i) checkSignature(tx) expect(signProtoSpy).to.have.been.calledWith(txHash, '0x7e3', 1) } expect(createFromPrivateKeySpy).to.have.been.callCount(Object.keys(txsByAccountKeys).length) }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-180: input: KlaytnWalletKey. should sign transaction.', async () => { const signProtoSpy = sandbox.spy(SingleKeyring.prototype, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.sign(sender.getKlaytnWalletKey()) checkFunctionCall(i) checkSignature(tx) expect(signProtoSpy).to.have.been.calledWith(txHash, '0x7e3', 1) } expect(createFromPrivateKeySpy).to.have.been.callCount(Object.keys(txsByAccountKeys).length) }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-181: input: keyring, custom hasher. should use custom hasher when sign transaction.', async () => { const hashForCustomHasher = '0x9e4b4835f6ea5ce55bd1037fe92040dd070af6154aefc30d32c65364a1123cae' const customHasher = () => hashForCustomHasher for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] await tx.sign(sender, customHasher) checkFunctionCall(i, true) checkSignature(tx) expect(senderSignWithKeysSpy).to.have.been.calledWith(hashForCustomHasher, '0x7e3', 1) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-182: input: keyring. should throw error when from is different.', async () => { for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.from = roleBasedKeyring.address const expectedError = `The from address of the transaction is different with the address of the keyring to use.` await expect(tx.sign(sender)).to.be.rejectedWith(expectedError) } }).timeout(200000) it('CAVERJS-UNIT-TRANSACTIONFD-183: input: roleBased keyring. should sign with multiple keys and append signatures', async () => { const roleBasedSignWithKeysSpy = sandbox.spy(roleBasedKeyring, 'sign') for (let i = 0; i < txsByAccountKeys.length; i++) { const tx = txsByAccountKeys[i] tx.from = roleBasedKeyring.address await tx.sign(roleBasedKeyring) checkFunctionCall(i, true) checkSignature(tx, { expectedLength: roleBasedKeyring.keys[0].length }) expect(createFromPrivateKeySpy).not.to.have.been.calledOnce expect(roleBasedSignWithKeysSpy).to.have.been.calledWith(txHash, '0x7e3', 1) } expect(createFromPrivateKeySpy).not.to.have.been.called }).timeout(200000) }) context('feeDelegatedAccountUpdate.signAsFeePayer with multiple keys', () => { const txHash = '0xe9a11d9ef95fb437f75d07ce768d43e74f158dd54b106e7d3746ce29d545b550' const fillTransactionSpys = [] const appendSignaturesSpys = [] let createFromPrivateKeySpy let feePayerSignWithKeysSpy let hasherSpy beforeEach(() => { for (let i = 0; i < txsByAccountKeys.length; i++) { fillTransactionSpys.push(sandbox.spy(txsByAccountKeys[i], 'fillTransaction')) appendSignaturesSpys.push(sandbox.spy(txsByAccountKeys[i], 'appendFeePayerSignatures')) } createFromPrivateKeySpy = sandbox.spy(Keyring, 'createFromPrivateKey') feePayerSignWithKeysSpy = sandbox.spy(feePayer, 'sign') hasherSpy = sandbox.stub(TransactionHasher, 'getHashForFeeP