UNPKG

caver-js

Version:

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

1,023 lines (915 loc) 68.9 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') const testRPCURL = require('../testrpc') chai.use(chaiAsPromised) chai.use(sinonChai) const expect = chai.expect const sandbox = sinon.createSandbox() const Caver = require('../../index') let caver let testKeyring let sender beforeEach(() => { caver = new Caver(testRPCURL) testKeyring = caver.wallet.keyring.generate() const senderPrvKey = process.env.privateKey && String(process.env.privateKey).indexOf('0x') === -1 ? `0x${process.env.privateKey}` : process.env.privateKey sender = caver.wallet.add(caver.wallet.keyring.createFromPrivateKey(senderPrvKey)) }) afterEach(() => { sandbox.restore() }) describe('caver.rpc.klay', () => { context('CAVERJS-UNIT-RPC-001: caver.rpc.klay.encodeAccountKey', () => { it('should encode an account key using the Recursive Length Prefix (RLP) encoding scheme.', async () => { // AccountKeyNil let result = await caver.rpc.klay.encodeAccountKey({ keyType: 0, key: {} }) expect(_.isString(result)).to.be.true expect(result).to.be.equal('0x80') // AccountKeyLegacy result = await caver.rpc.klay.encodeAccountKey({ keyType: 1, key: {} }) expect(_.isString(result)).to.be.true expect(result).to.be.equal('0x01c0') let account = caver.account.createWithAccountKeyLegacy(testKeyring.address) let encoded = await caver.rpc.klay.encodeAccountKey(account.accountKey) expect(result).to.be.equal(encoded) // AccountKeyPublic let keyObject = { keyType: 2, key: { x: '0xdbac81e8486d68eac4e6ef9db617f7fbd79a04a3b323c982a09cdfc61f0ae0e8', y: '0x906d7170ba349c86879fb8006134cbf57bda9db9214a90b607b6b4ab57fc026e', }, } result = await caver.rpc.klay.encodeAccountKey(keyObject) expect(_.isString(result)).to.be.true expect(result).to.be.equal('0x02a102dbac81e8486d68eac4e6ef9db617f7fbd79a04a3b323c982a09cdfc61f0ae0e8') account = caver.account.create( testKeyring.address, '0xdbac81e8486d68eac4e6ef9db617f7fbd79a04a3b323c982a09cdfc61f0ae0e8906d7170ba349c86879fb8006134cbf57bda9db9214a90b607b6b4ab57fc026e' ) encoded = await caver.rpc.klay.encodeAccountKey(account.accountKey) expect(result).to.be.equal(encoded) // AccountKeyFail result = await caver.rpc.klay.encodeAccountKey({ keyType: 3, key: {} }) expect(_.isString(result)).to.be.true expect(result).to.be.equal('0x03c0') account = caver.account.createWithAccountKeyFail(testKeyring.address) encoded = await caver.rpc.klay.encodeAccountKey(account.accountKey) expect(result).to.be.equal(encoded) // AccountKeyWeightedMultiSig keyObject = { keyType: 4, key: { threshold: 3, keys: [ { weight: 1, key: { x: '0xc734b50ddb229be5e929fc4aa8080ae8240a802d23d3290e5e6156ce029b110e', y: '0x61a443ac3ffff164d1fb3617875f07641014cf17af6b7dc38e429fe838763712', }, }, { weight: 1, key: { x: '0x12d45f1cc56fbd6cd8fc877ab63b5092ac77db907a8a42c41dad3e98d7c64dfb', y: '0x8ef355a8d524eb444eba507f236309ce08370debaa136cb91b2f445774bff842', }, }, { weight: 1, key: { x: '0xea9a9f85065a00d7b9ffd3a8532a574035984587fd08107d8f4cbad6b786b0cd', y: '0xb95ebb02d9397b4a8faceb58d485d612f0379a923ec0ddcf083378460a56acca', }, }, { weight: 1, key: { x: '0x8551bc489d62fa2e6f767ba87fe93a62b679fca8ff3114eb5805e6487b51e8f6', y: '0x4206aa84bc8955fcbfcc396854228aa63ebacd81b7311a31ab9d71d90b7ec3d7', }, }, ], }, } result = await caver.rpc.klay.encodeAccountKey(keyObject) expect(_.isString(result)).to.be.true expect(result).to.be.equal( '0x04f89303f890e301a102c734b50ddb229be5e929fc4aa8080ae8240a802d23d3290e5e6156ce029b110ee301a10212d45f1cc56fbd6cd8fc877ab63b5092ac77db907a8a42c41dad3e98d7c64dfbe301a102ea9a9f85065a00d7b9ffd3a8532a574035984587fd08107d8f4cbad6b786b0cde301a1038551bc489d62fa2e6f767ba87fe93a62b679fca8ff3114eb5805e6487b51e8f6' ) let options = new caver.account.weightedMultiSigOptions(3, [1, 1, 1, 1]) account = caver.account.create( testKeyring.address, [ '0xc734b50ddb229be5e929fc4aa8080ae8240a802d23d3290e5e6156ce029b110e61a443ac3ffff164d1fb3617875f07641014cf17af6b7dc38e429fe838763712', '0x12d45f1cc56fbd6cd8fc877ab63b5092ac77db907a8a42c41dad3e98d7c64dfb8ef355a8d524eb444eba507f236309ce08370debaa136cb91b2f445774bff842', '0xea9a9f85065a00d7b9ffd3a8532a574035984587fd08107d8f4cbad6b786b0cdb95ebb02d9397b4a8faceb58d485d612f0379a923ec0ddcf083378460a56acca', '0x8551bc489d62fa2e6f767ba87fe93a62b679fca8ff3114eb5805e6487b51e8f64206aa84bc8955fcbfcc396854228aa63ebacd81b7311a31ab9d71d90b7ec3d7', ], options ) encoded = await caver.rpc.klay.encodeAccountKey(account.accountKey) expect(result).to.be.equal(encoded) // AccountKeyRoleBased keyObject = { keyType: 5, key: [ { keyType: 2, key: { x: '0xe4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512d', y: '0xa5735a23ce1654b14680054a993441eae7c261983a56f8e0da61280758b5919', }, }, { keyType: 4, key: { threshold: 2, keys: [ { weight: 1, key: { x: '0xe4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512d', y: '0xa5735a23ce1654b14680054a993441eae7c261983a56f8e0da61280758b5919', }, }, { weight: 1, key: { x: '0x36f6355f5b532c3c1606f18fa2be7a16ae200c5159c8031dd25bfa389a4c9c06', y: '0x6fdf9fc87a16ac359e66d9761445d5ccbb417fb7757a3f5209d713824596a50d', }, }, ], }, }, { keyType: 2, key: { x: '0xc8785266510368d9372badd4c7f4a94b692e82ba74e0b5e26b34558b0f081447', y: '0x94c27901465af0a703859ab47f8ae17e54aaba453b7cde5a6a9e4a32d45d72b2', }, }, ], } result = await caver.rpc.klay.encodeAccountKey(keyObject) expect(_.isString(result)).to.be.true expect(result).to.be.equal( '0x05f898a302a103e4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512db84e04f84b02f848e301a103e4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512de301a10336f6355f5b532c3c1606f18fa2be7a16ae200c5159c8031dd25bfa389a4c9c06a302a102c8785266510368d9372badd4c7f4a94b692e82ba74e0b5e26b34558b0f081447' ) options = [ new caver.account.weightedMultiSigOptions(), new caver.account.weightedMultiSigOptions(2, [1, 1]), new caver.account.weightedMultiSigOptions(), ] account = caver.account.create( testKeyring.address, [ [ '0xe4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512d0a5735a23ce1654b14680054a993441eae7c261983a56f8e0da61280758b5919', ], [ '0xe4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512d0a5735a23ce1654b14680054a993441eae7c261983a56f8e0da61280758b5919', '0x36f6355f5b532c3c1606f18fa2be7a16ae200c5159c8031dd25bfa389a4c9c066fdf9fc87a16ac359e66d9761445d5ccbb417fb7757a3f5209d713824596a50d', ], [ '0xc8785266510368d9372badd4c7f4a94b692e82ba74e0b5e26b34558b0f08144794c27901465af0a703859ab47f8ae17e54aaba453b7cde5a6a9e4a32d45d72b2', ], ], options ) encoded = await caver.rpc.klay.encodeAccountKey(account.accountKey) expect(result).to.be.equal(encoded) }).timeout(100000) }) context('CAVERJS-UNIT-RPC-002: caver.rpc.klay.decodeAccountKey', () => { it('should encode an account key using the Recursive Length Prefix (RLP) encoding scheme.', async () => { // AccountKeyNil let decoded = await caver.rpc.klay.decodeAccountKey('0x80') expect(decoded.keyType).to.equal(0) // AccountKeyLegacy decoded = await caver.rpc.klay.decodeAccountKey('0x01c0') expect(decoded.keyType).to.equal(1) // AccountKeyPublic let keyObject = { keyType: 2, key: { x: '0xdbac81e8486d68eac4e6ef9db617f7fbd79a04a3b323c982a09cdfc61f0ae0e8', y: '0x906d7170ba349c86879fb8006134cbf57bda9db9214a90b607b6b4ab57fc026e', }, } decoded = await caver.rpc.klay.decodeAccountKey('0x02a102dbac81e8486d68eac4e6ef9db617f7fbd79a04a3b323c982a09cdfc61f0ae0e8') expect(decoded.keyType).to.equal(keyObject.keyType) expect(decoded.key.x).to.equal(keyObject.key.x) expect(decoded.key.y).to.equal(keyObject.key.y) // AccountKeyFail decoded = await caver.rpc.klay.decodeAccountKey('0x03c0') expect(decoded.keyType).to.equal(3) // AccountKeyWeightedMultiSig keyObject = { keyType: 4, key: { threshold: 3, keys: [ { weight: 1, key: { x: '0xc734b50ddb229be5e929fc4aa8080ae8240a802d23d3290e5e6156ce029b110e', y: '0x61a443ac3ffff164d1fb3617875f07641014cf17af6b7dc38e429fe838763712', }, }, { weight: 1, key: { x: '0x12d45f1cc56fbd6cd8fc877ab63b5092ac77db907a8a42c41dad3e98d7c64dfb', y: '0x8ef355a8d524eb444eba507f236309ce08370debaa136cb91b2f445774bff842', }, }, { weight: 1, key: { x: '0xea9a9f85065a00d7b9ffd3a8532a574035984587fd08107d8f4cbad6b786b0cd', y: '0xb95ebb02d9397b4a8faceb58d485d612f0379a923ec0ddcf083378460a56acca', }, }, { weight: 1, key: { x: '0x8551bc489d62fa2e6f767ba87fe93a62b679fca8ff3114eb5805e6487b51e8f6', y: '0x4206aa84bc8955fcbfcc396854228aa63ebacd81b7311a31ab9d71d90b7ec3d7', }, }, ], }, } decoded = await caver.rpc.klay.decodeAccountKey( '0x04f89303f890e301a102c734b50ddb229be5e929fc4aa8080ae8240a802d23d3290e5e6156ce029b110ee301a10212d45f1cc56fbd6cd8fc877ab63b5092ac77db907a8a42c41dad3e98d7c64dfbe301a102ea9a9f85065a00d7b9ffd3a8532a574035984587fd08107d8f4cbad6b786b0cde301a1038551bc489d62fa2e6f767ba87fe93a62b679fca8ff3114eb5805e6487b51e8f6' ) expect(decoded.keyType).to.equal(keyObject.keyType) expect(decoded.key.threshold).to.equal(keyObject.key.threshold) for (let i = 0; i < decoded.key.keys.length; i++) { expect(decoded.key.keys[i].weight).to.equal(keyObject.key.keys[i].weight) expect(decoded.key.keys[i].key.x).to.equal(keyObject.key.keys[i].key.x) expect(decoded.key.keys[i].key.y).to.equal(keyObject.key.keys[i].key.y) } // AccountKeyRoleBased keyObject = { keyType: 5, key: [ { keyType: 2, key: { x: '0xe4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512d', y: '0xa5735a23ce1654b14680054a993441eae7c261983a56f8e0da61280758b5919', }, }, { keyType: 4, key: { threshold: 2, keys: [ { weight: 1, key: { x: '0xe4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512d', y: '0xa5735a23ce1654b14680054a993441eae7c261983a56f8e0da61280758b5919', }, }, { weight: 1, key: { x: '0x36f6355f5b532c3c1606f18fa2be7a16ae200c5159c8031dd25bfa389a4c9c06', y: '0x6fdf9fc87a16ac359e66d9761445d5ccbb417fb7757a3f5209d713824596a50d', }, }, ], }, }, { keyType: 2, key: { x: '0xc8785266510368d9372badd4c7f4a94b692e82ba74e0b5e26b34558b0f081447', y: '0x94c27901465af0a703859ab47f8ae17e54aaba453b7cde5a6a9e4a32d45d72b2', }, }, ], } decoded = await caver.rpc.klay.decodeAccountKey( '0x05f898a302a103e4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512db84e04f84b02f848e301a103e4a01407460c1c03ac0c82fd84f303a699b210c0b054f4aff72ff7dcdf01512de301a10336f6355f5b532c3c1606f18fa2be7a16ae200c5159c8031dd25bfa389a4c9c06a302a102c8785266510368d9372badd4c7f4a94b692e82ba74e0b5e26b34558b0f081447' ) expect(decoded.keyType).to.equal(keyObject.keyType) for (let i = 0; i < decoded.key.length; i++) { expect(decoded.key[i].keyType).to.equal(keyObject.key[i].keyType) if (decoded.key[i].keyType === 2) { expect(decoded.key[i].key.x).to.equal(keyObject.key[i].key.x) expect(decoded.key[i].key.y).to.equal(keyObject.key[i].key.y) } else { expect(decoded.key[i].key.threshold).to.equal(keyObject.key[i].key.threshold) for (let j = 0; j < decoded.key[i].key.keys.length; j++) { expect(decoded.key[i].key.keys[j].weight).to.equal(keyObject.key[i].key.keys[j].weight) expect(decoded.key[i].key.keys[j].key.x).to.equal(keyObject.key[i].key.keys[j].key.x) expect(decoded.key[i].key.keys[j].key.y).to.equal(keyObject.key[i].key.keys[j].key.y) } } } }).timeout(100000) }) context('CAVERJS-UNIT-RPC-003: caver.rpc.klay.signTransaction', () => { it('should return result of signing as a sender', async () => { const passphrase = 'passphrase' let keyringToImport = caver.wallet.keyring.generate() keyringToImport = caver.wallet.add(keyringToImport) const address = await caver.klay.personal.importRawKey(keyringToImport.key.privateKey, passphrase) expect(address.toLowerCase()).to.equals(keyringToImport.address.toLowerCase()) const isUnlock = await caver.klay.personal.unlockAccount(keyringToImport.address, passphrase, 100) expect(typeof isUnlock).to.equals('boolean') expect(isUnlock).to.be.true const feeDelegated = caver.transaction.feeDelegatedValueTransfer.create({ from: keyringToImport.address, to: sender.address, value: 1, gas: 50000, feePayer: sender.address, nonce: await caver.rpc.klay.getTransactionCount(keyringToImport.address), }) const result = await caver.rpc.klay.signTransaction(feeDelegated) const signed = await feeDelegated.sign(keyringToImport) expect(caver.utils.makeEven(result.tx.signatures[0].V)).to.equal(signed.signatures[0].v) expect(caver.utils.makeEven(result.tx.signatures[0].R)).to.equal(signed.signatures[0].r) expect(caver.utils.makeEven(result.tx.signatures[0].S)).to.equal(signed.signatures[0].s) }).timeout(100000) }) context('CAVERJS-UNIT-RPC-004: caver.rpc.klay.signTransactionAsFeePayer', () => { it('should return result of signing as a fee payer', async () => { const passphrase = 'passphrase' let keyringToImport = caver.wallet.keyring.generate() keyringToImport = caver.wallet.add(keyringToImport) const address = await caver.klay.personal.importRawKey(keyringToImport.key.privateKey, passphrase) expect(address.toLowerCase()).to.equals(keyringToImport.address.toLowerCase()) const isUnlock = await caver.klay.personal.unlockAccount(keyringToImport.address, passphrase, 100) expect(typeof isUnlock).to.equals('boolean') expect(isUnlock).to.be.true const feeDelegated = caver.transaction.feeDelegatedValueTransfer.create({ from: sender.address, to: keyringToImport.address, value: 1, gas: 50000, feePayer: keyringToImport.address, nonce: await caver.rpc.klay.getTransactionCount(sender.address), }) await feeDelegated.sign(sender) const result = await caver.rpc.klay.signTransactionAsFeePayer(feeDelegated) const signed = await feeDelegated.signAsFeePayer(keyringToImport) expect(result.tx.feePayerSignatures[0].toString()).to.equal( caver.utils.transformSignaturesToObject(signed.feePayerSignatures).toString() ) }).timeout(100000) }) context('CAVERJS-UNIT-RPC-005: caver.rpc.klay.sendTransactionAsFeePayer', () => { it('should send transaction to Klaytn node as a fee payer', async () => { const passphrase = 'passphrase' let keyringToImport = caver.wallet.keyring.generate() keyringToImport = caver.wallet.add(keyringToImport) // Send KLAY to test keyring const valueTransfer = caver.transaction.valueTransfer.create({ from: sender.address, to: keyringToImport.address, value: caver.utils.toPeb(1, 'KLAY'), gas: 30000, }) await valueTransfer.sign(sender) await caver.rpc.klay.sendRawTransaction(valueTransfer) // Import key in Klaytn node const address = await caver.klay.personal.importRawKey(keyringToImport.key.privateKey, passphrase) expect(address.toLowerCase()).to.equals(keyringToImport.address.toLowerCase()) const isUnlock = await caver.klay.personal.unlockAccount(keyringToImport.address, passphrase, 100) expect(typeof isUnlock).to.equals('boolean') expect(isUnlock).to.be.true const feeDelegated = caver.transaction.feeDelegatedValueTransfer.create({ from: sender.address, to: keyringToImport.address, value: 1, gas: 50000, feePayer: keyringToImport.address, nonce: await caver.rpc.klay.getTransactionCount(sender.address), }) await feeDelegated.sign(sender) const result = await caver.rpc.klay.signTransactionAsFeePayer(feeDelegated) const signed = await feeDelegated.signAsFeePayer(keyringToImport) expect(result.tx.feePayerSignatures[0].toString()).to.equal( caver.utils.transformSignaturesToObject(signed.feePayerSignatures).toString() ) }).timeout(100000) }) context('caver.rpc.klay.getFeeHistory', () => { function checkFeeHistoryResult(blockCount, blockNumberOrTag, rewardPercentiles, ret) { const bc = caver.utils.hexToNumber(blockCount) let bn = blockNumberOrTag try { bn = caver.utils.hexToNumber(bn) expect(ret.oldestBlock).to.equal(caver.utils.toHex(bn - bc + 1)) } catch (e) { // blockNumberOrTag is tag } expect(ret.oldestBlock).not.to.be.undefined expect(ret.reward.length).to.equal(bc) expect(ret.reward[0].length).to.equal(rewardPercentiles.length) expect(ret.baseFeePerGas.length).to.equal(bc + 1) // include next base fee expect(ret.baseFeePerGas.every(bf => caver.utils.isHexStrict(bf))).to.be.true expect(ret.gasUsedRatio.length).to.equal(bc) expect(ret.gasUsedRatio.every(gur => _.isNumber(gur))).to.be.true } it('CAVERJS-UNIT-RPC-023: should call klay_feeHistory', async () => { const blockCount = 5 const blockNumber = 'latest' const rewardPercentiles = [0.1, 0.3, 0.8] sandbox.stub(caver.rpc.klay._requestManager, 'send').callsFake((data, callback) => { expect(data.method).to.equal('klay_feeHistory') callback(undefined, {}) }) await caver.rpc.klay.getFeeHistory(blockCount, blockNumber, rewardPercentiles) }).timeout(100000) it('CAVERJS-UNIT-RPC-024: should return fee history with various parameter types', async () => { let nonce = caver.utils.hexToNumber(await caver.rpc.klay.getTransactionCount(sender.address)) const txsCount = 30 let receipt for (let i = 0; i < txsCount; i++) { const tx = caver.transaction.valueTransfer.create({ from: sender.address, to: caver.wallet.keyring.generate().address, value: 1, gas: 50000, nonce, }) await caver.wallet.sign(sender.address, tx) nonce++ // To track last transaction's receipt if (i !== txsCount - 1) { caver.rpc.klay.sendRawTransaction(tx) continue } receipt = await caver.rpc.klay.sendRawTransaction(tx) } // Test with hex string let blockCount = caver.utils.numberToHex(5) let blockNumber = receipt.blockNumber let rewardPercentiles = [0.1, 0.3, 0.8] let ret = await caver.rpc.klay.getFeeHistory(blockCount, blockNumber, rewardPercentiles) checkFeeHistoryResult(blockCount, blockNumber, rewardPercentiles, ret) // Test with hex string blockCount = 5 blockNumber = caver.utils.hexToNumber(receipt.blockNumber) rewardPercentiles = [0.1, 0.3, 0.8] ret = await caver.rpc.klay.getFeeHistory(blockCount, blockNumber, rewardPercentiles) checkFeeHistoryResult(blockCount, blockNumber, rewardPercentiles, ret) // Test with BN blockCount = caver.utils.toBN(5) blockNumber = caver.utils.toBN(receipt.blockNumber) rewardPercentiles = [0.1, 0.3, 0.8] ret = await caver.rpc.klay.getFeeHistory(blockCount, blockNumber, rewardPercentiles) checkFeeHistoryResult(blockCount, blockNumber, rewardPercentiles, ret) // Test with BigNumber blockCount = new caver.utils.BigNumber(5) blockNumber = new caver.utils.BigNumber(receipt.blockNumber) rewardPercentiles = [0.1, 0.3, 0.8] ret = await caver.rpc.klay.getFeeHistory(blockCount, blockNumber, rewardPercentiles) checkFeeHistoryResult(blockCount, blockNumber, rewardPercentiles, ret) // Test with block tag string blockCount = 5 blockNumber = 'latest' rewardPercentiles = [0.1, 0.3, 0.8] ret = await caver.rpc.klay.getFeeHistory(blockCount, blockNumber, rewardPercentiles) checkFeeHistoryResult(blockCount, blockNumber, rewardPercentiles, ret) }).timeout(100000) }) context('caver.rpc.klay.getMaxPriorityFeePerGas', () => { it('CAVERJS-UNIT-RPC-025: should call klay_maxPriorityFeePerGas', async () => { sandbox.stub(caver.rpc.klay._requestManager, 'send').callsFake((data, callback) => { expect(data.method).to.equal('klay_maxPriorityFeePerGas') callback(undefined, {}) }) await caver.rpc.klay.getMaxPriorityFeePerGas() }).timeout(100000) it('CAVERJS-UNIT-RPC-026: should return suggested max priority fee per gas', async () => { const ret = await caver.rpc.klay.getMaxPriorityFeePerGas() const gasPrice = await caver.rpc.klay.getGasPrice() expect(_.isString(ret)).to.be.true expect(ret).to.equal(gasPrice) }).timeout(100000) }) context('caver.rpc.klay.getUpperBoundGasPrice', () => { it('CAVERJS-UNIT-RPC-035: should call klay_upperBoundGasPrice', async () => { sandbox.stub(caver.rpc.klay._requestManager, 'send').callsFake((data, callback) => { expect(data.method).to.equal('klay_upperBoundGasPrice') callback(undefined, {}) }) await caver.rpc.klay.getUpperBoundGasPrice() }).timeout(100000) it('CAVERJS-UNIT-RPC-036: should return an upper bound gas price', async () => { const ret = await caver.rpc.klay.getUpperBoundGasPrice() const gasPrice = await caver.rpc.klay.getGasPrice() expect(_.isString(ret)).to.be.true expect(caver.utils.hexToNumber(ret) >= caver.utils.hexToNumber(gasPrice)).to.be.true }).timeout(100000) }) context('caver.rpc.klay.getLowerBoundGasPrice', () => { it('CAVERJS-UNIT-RPC-037: should call klay_lowerBoundGasPrice', async () => { sandbox.stub(caver.rpc.klay._requestManager, 'send').callsFake((data, callback) => { expect(data.method).to.equal('klay_lowerBoundGasPrice') callback(undefined, {}) }) await caver.rpc.klay.getLowerBoundGasPrice() }).timeout(100000) it('CAVERJS-UNIT-RPC-038: should return an lower bound gas price', async () => { const ret = await caver.rpc.klay.getLowerBoundGasPrice() const gasPrice = await caver.rpc.klay.getGasPrice() expect(_.isString(ret)).to.be.true expect(caver.utils.hexToNumber(ret) <= caver.utils.hexToNumber(gasPrice)).to.be.true }).timeout(100000) }) context('caver.rpc.klay.createAccessList', () => { const txArgs = { from: '0x3bc5885c2941c5cda454bdb4a8c88aa7f248e312', data: '0x20965255', gasPrice: '0x3b9aca00', gas: '0x3d0900', to: '0x00f5f5f3a25f142fafd0af24a754fafa340f32c7', } function checkAccessListResult(blockNumberOrTag, ret) { expect(_.isArray(ret.accessList)).to.be.true expect(ret.accessList.length).to.equal(0) // For now Klaytn will return empty access list expect(ret.gasUsed).to.equal('0x0') // For now Klaytn will return zero gasUsed } it('CAVERJS-UNIT-RPC-027: should call klay_createAccessList', async () => { sandbox.stub(caver.rpc.klay._requestManager, 'send').callsFake((data, callback) => { expect(data.method).to.equal('klay_createAccessList') callback(undefined, {}) }) await caver.rpc.klay.createAccessList(txArgs, 'latest') }).timeout(100000) it('CAVERJS-UNIT-RPC-028: should return access list used by transaction', async () => { const blocTag = 'latest' let ret = await caver.rpc.klay.createAccessList(txArgs, blocTag) checkAccessListResult(blocTag, ret) const hexBlockNumber = await caver.rpc.klay.getBlockNumber() ret = await caver.rpc.klay.createAccessList(txArgs, hexBlockNumber) checkAccessListResult(hexBlockNumber, ret) const blockNumber = caver.utils.hexToNumber(hexBlockNumber) ret = await caver.rpc.klay.createAccessList(txArgs, blockNumber) checkAccessListResult(blockNumber, ret) const blockBN = caver.utils.toBN(blockNumber) ret = await caver.rpc.klay.createAccessList(txArgs, blockBN) checkAccessListResult(blockBN, ret) const blockBigNumber = new caver.utils.BigNumber(blockNumber) ret = await caver.rpc.klay.createAccessList(txArgs, blockBigNumber) checkAccessListResult(blockBigNumber, ret) }).timeout(100000) }) context('caver.rpc.klay.getHeader', () => { it('CAVERJS-UNIT-RPC-029: caver.rpc.klay.getHeader should call correct RPC call depends on param type', async () => { // Have to call klay_getHeaderByHash with hex string param sandbox.stub(caver.rpc.klay._requestManager, 'send').callsFake((data, callback) => { expect(data.params.length).to.equal(1) if (caver.utils.isValidHash(data.params[0])) { expect(data.method).to.equal('klay_getHeaderByHash') } else { expect(data.method).to.equal('klay_getHeaderByNumber') } callback(undefined, {}) }) await caver.rpc.klay.getHeader('latest') await caver.rpc.klay.getHeader(0) await caver.rpc.klay.getHeader('0x489ef4696baa7f5c9548cb4affa1b969a5b18de221b0cc0ed2483a1b2f84ac69') }).timeout(100000) }) context('caver.rpc.klay.getRewards', () => { it('CAVERJS-UNIT-RPC-030: caver.rpc.klay.getRewards should call correct RPC call depends on param type', async () => { // Have to call klay_getRewards with hex string param sandbox.stub(caver.rpc.klay._requestManager, 'send').callsFake((data, callback) => { expect(data.params.length).to.equal(1) if (caver.utils.isValidHash(data.params[0])) { expect(data.method).to.equal('klay_getRewards') } else { expect(data.method).to.equal('klay_getRewards') } callback(undefined, {}) }) await caver.rpc.klay.getRewards('latest') await caver.rpc.klay.getRewards(0) await caver.rpc.klay.getRewards('0x489ef4696baa7f5c9548cb4affa1b969a5b18de221b0cc0ed2483a1b2f84ac69') }).timeout(100000) }) context('caver.rpc.klay.getChainConfig', () => { it('CAVERJS-UNIT-RPC-031: should return the latest chain configuration', async () => { const klayRPCStub = sandbox .stub(caver.rpc.klay.getChainConfig.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('klay_getChainConfig') expect(payload.params.length).to.equal(caver.rpc.klay.getChainConfig.method.params) const ret = { chainId: 1001, istanbulCompatibleBlock: 0, londonCompatibleBlock: 0, ethTxTypeCompatibleBlock: 0, magmaCompatibleBlock: 0, koreCompatibleBlock: 1000, deriveShaImpl: 2, governance: { govParamContract: '0x0000000000000000000000000000000000000000', governanceMode: 'single', governingNode: '0x7313f6c9c40bb421838495c79043240220dfaea7', reward: { deferredTxFee: true, kip82ratio: '20/80', minimumStake: 5000000, mintingAmount: 9600000000000000000, proposerUpdateInterval: 30, ratio: '50/40/10', stakingUpdateInterval: 60, useGiniCoeff: true, }, kip71: { lowerboundbasefee: 25000000000, upperboundbasefee: 750000000000, gastarget: 30000000, maxblockgasusedforbasefee: 60000000, basefeedenominator: 20, }, }, istanbul: { epoch: 30, policy: 2, sub: 22, }, unitPrice: 25000000000, } sendTxCallback(null, ret) }) await caver.rpc.klay.getChainConfig() expect(klayRPCStub.callCount).to.equal(1) }).timeout(100000) }) context('caver.rpc.klay.getChainConfigAt', () => { it('CAVERJS-UNIT-RPC-032: should return the latest chain configuration like getChainCofig', async () => { const klayRPCStub = sandbox .stub(caver.rpc.klay.getChainConfigAt.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('klay_chainConfigAt') expect(payload.params.length).to.equal(caver.rpc.klay.getChainConfigAt.method.params) const ret = { chainId: 1001, istanbulCompatibleBlock: 0, londonCompatibleBlock: 0, ethTxTypeCompatibleBlock: 0, magmaCompatibleBlock: 0, koreCompatibleBlock: 1000, deriveShaImpl: 2, governance: { govParamContract: '0x0000000000000000000000000000000000000000', governanceMode: 'single', governingNode: '0x7313f6c9c40bb421838495c79043240220dfaea7', reward: { deferredTxFee: true, kip82ratio: '20/80', minimumStake: 5000000, mintingAmount: 9600000000000000000, proposerUpdateInterval: 30, ratio: '50/40/10', stakingUpdateInterval: 60, useGiniCoeff: true, }, kip71: { lowerboundbasefee: 25000000000, upperboundbasefee: 750000000000, gastarget: 30000000, maxblockgasusedforbasefee: 60000000, basefeedenominator: 20, }, }, istanbul: { epoch: 30, policy: 2, sub: 22, }, unitPrice: 25000000000, } sendTxCallback(null, ret) }) await caver.rpc.klay.getChainConfigAt() expect(klayRPCStub.callCount).to.equal(1) }).timeout(100000) }) context('caver.rpc.klay.getNodeAddress', () => { it('CAVERJS-UNIT-RPC-033: should return the address of the node that a user is using', async () => { const klayRPCStub = sandbox .stub(caver.rpc.klay.getNodeAddress.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('klay_nodeAddress') expect(payload.params.length).to.equal(caver.rpc.klay.getNodeAddress.method.params) sendTxCallback(null, '0xa80de139de3fb29fba7e2d20bda593c5ffe63ce9') }) await caver.rpc.klay.getNodeAddress() expect(klayRPCStub.callCount).to.equal(1) }).timeout(100000) }) context('caver.rpc.klay.getGovParamsAt', () => { it('CAVERJS-UNIT-RPC-034: should return governance params at specific block', async () => { const klayRPCStub = sandbox .stub(caver.rpc.klay.getGovParamsAt.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('klay_govParamsAt') expect(payload.params.length).to.equal(caver.rpc.klay.getGovParamsAt.method.params) const ret = { 'governance.governancemode': 'single', 'governance.governingnode': '0xa80de139de3fb29fba7e2d20bda593c5ffe63ce9', 'governance.unitprice': 25000000000, 'istanbul.committeesize': 22, 'istanbul.epoch': 30, 'istanbul.policy': 2, 'reward.deferredtxfee': true, 'reward.minimumstake': '5000000', 'reward.mintingamount': '9600000000000000000', 'reward.proposerupdateinterval': 30, 'reward.ratio': '50/40/10', 'reward.stakingupdateinterval': 60, 'reward.useginicoeff': true, } sendTxCallback(null, ret) }) await caver.rpc.klay.getGovParamsAt(0) expect(klayRPCStub.callCount).to.equal(1) }).timeout(100000) }) context('caver.rpc.klay.getStakingInfo', () => { it('CAVERJS-UNIT-RPC-035: should return returns staking information at a specific block', async () => { const klayRPCStub = sandbox .stub(caver.rpc.klay.getStakingInfo.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('klay_getStakingInfo') expect(payload.params.length).to.equal(caver.rpc.klay.getStakingInfo.method.params) const ret = { BlockNum: 57801600, CouncilNodeAddrs: [ '0x99fb17d324fa0e07f23b49d09028ac0919414db6', '0x571e53df607be97431a5bbefca1dffe5aef56f4d', '0xb74ff9dea397fe9e231df545eb53fe2adf776cb2', '0x5cb1a7dccbd0dc446e3640898ede8820368554c8', '0x776817c0ef3d06d794cf01ae9afa33d7397b9b40', '0xc180ca565b34b5b63877674f5fe647e7da079022', '0x03497f51c31fe8b402df0bde90fd5a85f87aa943', ], CouncilRewardAddrs: [ '0xb2bd3178affccd9f9f5189457f1cad7d17a01c9d', '0x6559a7b6248b342bc11fbcdf9343212bbc347edc', '0x82829a60c6eac4e3e9d6ed00891c69e88537fd4d', '0xa86fd667c6a340c53cc5d796ba84dbe1f29cb2f7', '0x6e22cbe2b8bbd1df9f1d3c8ebae6d7ff5414a734', '0x24e593fb29731e54905025c230727dc28d229f77', '0x2b2a7a1d29a203f60e0a964fc64231265a49cd97', ], CouncilStakingAddrs: [ '0x12fa1ab4c3e17c1c08c1b5a945c864c8e8bf707e', '0xfd56604f1a20268ff7a0eab2ab48e25ee1e0f653', '0x1e0f6aaa9baa6081dc4910a854eebf8854c262ab', '0x5e6988415ebe0f6b088f5a676003ba60f572875a', '0xbb44998c2af35b8faee694cffe216558056d747e', '0x68cba498b7175cde9de08fc2e85ad3e9c8caefa8', '0x98efb31eeccafe35d53a6926e2a54c0858d9eebc', ], CouncilStakingAmounts: [5000000, 5000000, 5000000, 5000000, 5000000, 5000000, 5000000], Gini: 0, KIRAddr: '0x716f89d9bc333286c79db4ebb05516897c8d208a', PoCAddr: '0x2bcf9d3e4a846015e7e3152a614c684de16f37c6', UseGini: true, } sendTxCallback(null, ret) }) await caver.rpc.klay.getStakingInfo() expect(klayRPCStub.callCount).to.equal(1) }).timeout(100000) }) }) describe('caver.rpc.governance', () => { context('caver.rpc.governance.vote', () => { it('CAVERJS-UNIT-RPC-006: should submit voting to the Klaytn', async () => { let key = 'governance.governancemode' let value = 'ballot' const govRPCStub = sandbox .stub(caver.rpc.governance.vote.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('governance_vote') expect(payload.params.length).to.equal(caver.rpc.governance.vote.method.params) expect(payload.params[0]).to.equal(key) expect(payload.params[1]).to.equal(value) sendTxCallback(null, 'Your vote was successfully placed.') }) await caver.rpc.governance.vote(key, value) expect(govRPCStub.callCount).to.equal(1) key = 'governance.governingnode' value = '0x12345678990123456789901234567899012345678990' await caver.rpc.governance.vote(key, value) expect(govRPCStub.callCount).to.equal(2) key = 'istanbul.epoch' value = 604800 await caver.rpc.governance.vote(key, value) expect(govRPCStub.callCount).to.equal(3) key = 'governance.unitprice' value = 25000000000 await caver.rpc.governance.vote(key, value) expect(govRPCStub.callCount).to.equal(4) key = 'istanbul.committeesize' value = 7 await caver.rpc.governance.vote(key, value) expect(govRPCStub.callCount).to.equal(5) key = 'reward.mintingamount' value = '9600000000000000000' await caver.rpc.governance.vote(key, value) expect(govRPCStub.callCount).to.equal(6) key = 'reward.ratio' value = '50/40/10' await caver.rpc.governance.vote(key, value) expect(govRPCStub.callCount).to.equal(7) key = 'reward.useginicoeff' value = false await caver.rpc.governance.vote(key, value) expect(govRPCStub.callCount).to.equal(8) key = 'reward.ratio' value = 100 await caver.rpc.governance.vote(key, value) expect(govRPCStub.callCount).to.equal(9) }).timeout(100000) }) context('caver.rpc.governance.getMyVotes', () => { it('CAVERJS-UNIT-RPC-007: should return my votes', async () => { const govRPCStub = sandbox .stub(caver.rpc.governance.getMyVotes.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('governance_myVotes') expect(payload.params.length).to.equal(caver.rpc.governance.getMyVotes.method.params) const ret = [ { Key: 'governance.governancemode', Value: 'ballot', Casted: false, BlockNum: 0, }, ] sendTxCallback(null, ret) }) await caver.rpc.governance.getMyVotes() expect(govRPCStub.callCount).to.equal(1) }).timeout(100000) }) context('caver.rpc.governance.getMyVotingPower', () => { it('CAVERJS-UNIT-RPC-008: should return my voting power', async () => { const govRPCStub = sandbox .stub(caver.rpc.governance.getMyVotingPower.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('governance_myVotingPower') expect(payload.params.length).to.equal(caver.rpc.governance.getMyVotingPower.method.params) sendTxCallback(null, 1.323) }) await caver.rpc.governance.getMyVotingPower() expect(govRPCStub.callCount).to.equal(1) }).timeout(100000) it('CAVERJS-UNIT-RPC-009: should return error when in current governing mode voting power is not supported', async () => { const govRPCStub = sandbox .stub(caver.rpc.governance.getMyVotingPower.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('governance_myVotingPower') expect(payload.params.length).to.equal(caver.rpc.governance.getMyVotingPower.method.params) sendTxCallback(null, 'In current governance mode, voting power is not available') }) const expectedError = 'In current governance mode, voting power is not available' await expect(caver.rpc.governance.getMyVotingPower()).to.be.rejectedWith(expectedError) expect(govRPCStub.callCount).to.equal(1) }).timeout(100000) }) context('caver.rpc.governance.getTotalVotingPower', () => { it('CAVERJS-UNIT-RPC-010: should return total voting power', async () => { const govRPCStub = sandbox .stub(caver.rpc.governance.getTotalVotingPower.method.requestManager, 'send') .callsFake((payload, sendTxCallback) => { expect(payload.method).to.equal('governance_totalVotingPower') expect(payload.params.