UNPKG

@metamask/ethjs-query

Version:

A simple query layer for the Ethereum RPC.

763 lines (619 loc) 28.4 kB
require('hard-rejection')(); const { assert } = require('chai'); const { getBinarySize } = require('@metamask/ethjs-util'); const Ganache = require('ganache-cli'); const BigNumber = require('bn.js'); const abi = require('ethjs-abi'); const Eth = require('../index.js'); const Eth2 = require('../index.js'); describe('ethjs-query', () => { let provider; beforeEach(() => { provider = Ganache.provider(); }); describe('construction', () => { it('should construct normally', () => { const eth = new Eth(provider); assert.equal(typeof eth, 'object'); assert.equal(typeof eth.accounts, 'function'); assert.equal(typeof eth.getBalance, 'function'); assert.equal(typeof eth.sendTransaction, 'function'); assert.equal(typeof eth.sendRawTransaction, 'function'); assert.equal(typeof eth.personal_sign, 'function'); assert.equal(typeof eth.personal_ecRecover, 'function'); }); it('should construct normally with non Eth name', () => { const eth = new Eth2(provider); assert.equal(typeof eth, 'object'); assert.equal(typeof eth.accounts, 'function'); assert.equal(typeof eth.getBalance, 'function'); assert.equal(typeof eth.sendTransaction, 'function'); assert.equal(typeof eth.sendRawTransaction, 'function'); }); it('should fail when provider is not valid', (done) => { try { const eth = new Eth(''); // eslint-disable-line } catch (error) { assert.equal(typeof error, 'object'); done(); } }); it('should fail when provider is not valid', (done) => { try { const eth = new Eth(342323); // eslint-disable-line } catch (error) { assert.equal(typeof error, 'object'); done(); } }); it('debugger should function', (done) => { const eth = new Eth(provider, { debug: true, logger: { log: (message) => { assert.equal(typeof message, 'string'); }}}); // eslint-disable-line eth.accounts((err, result) => { assert.equal(err, null); assert.equal(Array.isArray(result), true); done(); }); }); it('should fail with response error payload', (done) => { const eth = new Eth({ sendAsync: (opts, cb) => { cb(false, { error: 'bad data..' }); }, }); // eslint-disable-line eth.accounts((err, result) => { assert.equal(typeof err, 'object'); assert.equal(result, null); done(); }); }); it('should handle empty getTransactionReceipt', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.getTransactionReceipt('0x7f9de10bdd8686734c1b2dd2b7e53ea3e1ffe7fd4698a3a521ec8e09570ca121', (err, result) => { assert.equal(typeof err, 'object'); assert.equal(result, null); done(); }); }); it('should fail with invalid payload response (formatting error)', (done) => { const eth = new Eth({ sendAsync: (opts, cb) => { cb(false, { result: [38274978, 983428943] }); }, }); // eslint-disable-line eth.accounts((err, result) => { assert.equal(typeof err, 'object'); assert.equal(result, null); done(); }); }); it('should fail with invalid method input (formatting error)', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.getBalance(234842387, (err, result) => { assert.equal(typeof err, 'object'); assert.equal(result, null); done(); }); }); it('should fail when no new flag is present', (done) => { try { const eth = Eth2(provider); // eslint-disable-line } catch (error) { assert.equal(typeof error, 'object'); done(); } }); it('should fail nicely when too little params on getBalance', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.getBalance((err, result) => { assert.equal(typeof err, 'object'); assert.equal(result, null); done(); }); }); it('should fail nicely when too many paramsEncoded on getBalance', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.getBalance('fsdfsd', 'sdffsd', 'dsfdfssf', (error, result) => { assert.equal(typeof error, 'object'); assert.equal(result, null); done(); }); }); it('should check if the rpc is eth_syncing', (done) => { const eth = new Eth(provider); eth.syncing((err, result) => { assert.equal(err, null); assert.equal(typeof result, 'boolean'); done(); }); }); it('should function while eth_coinbase', (done) => { const eth = new Eth(provider); eth.coinbase((err, result) => { assert.equal(err, null); assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 42); done(); }); }); it('should function while eth_coinbase using promise', (done) => { const eth = new Eth(provider); eth.coinbase() .then((result) => { assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 42); done(); }) .catch((err) => { assert.equal(err, null); }); }); it('should get acconts with promise', (done) => { const eth = new Eth(provider); eth.accounts() .then((result) => { assert.equal(typeof result, 'object'); assert.equal(result.length > 0, true); done(); }) .catch((err) => { assert.equal(err, null); }); }); it('should reject bad getBalance call with an error', (done) => { const eth = new Eth(provider); eth.accounts((accountsError, accounts) => { eth.sendTransaction({ from: accounts[0], to: accounts[1], gas: 10, value: 100000, data: '0x', }).catch((err) => { assert.equal(typeof err, 'object'); done(); }); }); }); it('should function while eth_getBalance using promise', (done) => { const eth = new Eth(provider); eth.coinbase() .then((result) => { assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 42); eth.getBalance(result) .then((balance) => { assert.equal(typeof balance, 'object'); done(); }) .catch((err) => { assert.equal(err, null); }); }) .catch((err) => { assert.equal(err, null); }); }); it('should function while eth_getBalance, optional and non optional latest', (done) => { const eth = new Eth(provider); eth.coinbase((err, coinbase) => { assert.equal(err, null); assert.equal(typeof coinbase, 'string'); assert.equal(getBinarySize(coinbase), 42); eth.getBalance(coinbase, (balanceError, balance) => { assert.equal(balanceError, null); assert.equal(typeof balance, 'object'); eth.getBalance(coinbase, 'latest', (balanceLatestError, balanceLatest) => { assert.equal(balanceLatestError, null); assert.equal(typeof balanceLatest, 'object'); assert.equal(balance.toString(10), balanceLatest.toString(10)); done(); }); }); }); }); it('should function while get_accounts', (done) => { const eth = new Eth(provider); eth.accounts((err, result) => { assert.equal(err, null); assert.equal(typeof result, 'object'); assert.equal(Array.isArray(result), true); assert.equal(result.length > 0, true); assert.equal(typeof result[0], 'string'); assert.equal(getBinarySize(result[0]), 42); done(); }); }); it('should function while eth_blockNumber', (done) => { const eth = new Eth(provider); eth.blockNumber((err, result) => { assert.equal(err, null); assert.equal(typeof result, 'object'); assert.equal(result.toNumber() >= 0, true); done(); }); }); it('should function while eth_estimateGas', (done) => { const eth = new Eth(provider); eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); const testTransactionObject = { from: accounts[0], to: accounts[4], gas: new BigNumber(23472), gasPrice: '92384242', data: '0x', }; eth.estimateGas(testTransactionObject, (err, result) => { assert.equal(err, null); assert.equal(typeof result, 'object'); assert.equal(typeof result.toString(10), 'string'); assert.equal(result.toNumber(10) > 0, true); done(); }); }); }); it('should function while eth_gasPrice', (done) => { const eth = new Eth(provider); eth.gasPrice((err, result) => { assert.equal(err, null); assert.equal(typeof result, 'object'); assert.equal(result.toNumber() > 0, true); done(); }); }); it('should function while eth_getBalance', (done) => { const eth = new Eth(provider); eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); eth.getBalance(accounts[0], (err, result) => { assert.equal(err, null); assert.equal(typeof result, 'object'); assert.equal(result.gt(0), true); eth.getBalance(accounts[0], 'latest', (err2, result2) => { assert.equal(err2, null); assert.equal(typeof result2, 'object'); assert.equal(result2.gt(0), true); done(); }); }); }); }); it('should function while eth_getBlockByNumber', (done) => { // eslint-disable-line const eth = new Eth(provider); eth.getBlockByNumber(0, true, (blockError, result) => { assert.equal(blockError, null); assert.equal(typeof result, 'object'); assert.equal(getBinarySize(result.hash), 66); assert.equal(getBinarySize(result.sha3Uncles), 66); assert.equal(getBinarySize(result.parentHash), 66); assert.equal(result.size.toNumber(10) > 0, true); assert.equal(result.gasLimit.toNumber(10) > 0, true); assert.equal(result.timestamp.toNumber(10) > 0, true); done(); }); }); it('should function while eth_getBlockByHash', (done) => { const eth = new Eth(provider); eth.getBlockByNumber(0, true, (blockError, block) => { assert.equal(blockError, null); assert.equal(typeof block, 'object'); eth.getBlockByHash(block.hash, true, (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'object'); assert.equal(getBinarySize(result.hash), 66); assert.equal(getBinarySize(result.sha3Uncles), 66); assert.equal(getBinarySize(result.parentHash), 66); assert.equal(result.size.toNumber(10) > 0, true); assert.equal(result.gasLimit.toNumber(10) > 0, true); assert.equal(result.timestamp.toNumber(10) > 0, true); done(); }); }); }); it('should function while eth_getCode', (done) => { const eth = new Eth(provider); // eslint-disable-line done(); }); it('should function while eth_hashrate', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.hashrate((error, result) => { assert.equal(error, null); assert.equal(typeof result, 'object'); assert.equal(result.toNumber(10) >= 0, true); done(); }); }); it('should function while eth_mining', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.mining((error, result) => { assert.equal(error, null); assert.equal(typeof result, 'boolean'); done(); }); }); it('should function while eth_getTransactionCount', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); eth.getTransactionCount(accounts[0], (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'object'); assert.equal(result.toNumber(10) >= 0, true); done(); }); }); }); it('should function while eth_getTransactionByBlockHashAndIndex', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); const testTransaction = { from: accounts[0], to: accounts[2], gas: 3000000, data: '0x', }; eth.sendTransaction(testTransaction, (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 66); eth.getTransactionReceipt(result, (receiptError, receipt) => { assert.equal(receiptError, null); assert.equal(typeof receipt, 'object'); eth.getTransactionByBlockHashAndIndex(receipt.blockHash, 0, (blockError, block) => { assert.equal(blockError, null); assert.equal(typeof block, 'object'); assert.equal(getBinarySize(block.blockHash), 66); assert.equal(block.gas.toNumber(10) >= 0, true); assert.equal(block.gasPrice.toNumber(10) >= 0, true); assert.equal(block.transactionIndex.toNumber(10) >= 0, true); assert.equal(block.blockNumber.toNumber(10) >= 0, true); done(); }); }); }); }); }); it('should function while eth_getTransactionByBlockNumberAndIndex', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); const testTransaction = { from: accounts[0], to: accounts[2], gas: 3000000, data: '0x', }; eth.sendTransaction(testTransaction, (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 66); eth.getTransactionReceipt(result, (receiptError, receipt) => { assert.equal(receiptError, null); assert.equal(typeof receipt, 'object'); eth.getTransactionByBlockNumberAndIndex(1, 0, (blockError, block) => { assert.equal(blockError, null); assert.equal(typeof block, 'object'); assert.equal(getBinarySize(block.blockHash), 66); assert.equal(block.gas.toNumber(10) >= 0, true); assert.equal(block.gasPrice.toNumber(10) >= 0, true); assert.equal(block.transactionIndex.toNumber(10) >= 0, true); assert.equal(block.blockNumber.toNumber(10) >= 0, true); done(); }); }); }); }); }); it('should function while eth_sendTransaction', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); const testTransaction = { from: accounts[0], to: accounts[2], gas: 3000000, data: '0x', }; eth.sendTransaction(testTransaction, (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 66); done(); }); }); }); it('should function while eth_sendTransaction with contract', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); const testTransaction = { from: accounts[0], gas: '3000000', data: '606060405234610000575b61016a806100186000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063119c56bd1461004e57806360fe47b11461008e5780636d4ce63c146100c1575b610000565b346100005761005b6100e4565b604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b34610000576100a960048080359060200190919050506100f5565b60405180821515815260200191505060405180910390f35b34610000576100ce61015f565b6040518082815260200191505060405180910390f35b60006000610d7d91503390505b9091565b6000816000819055507f10e8e9bc5a1bde3dd6bb7245b52503fcb9d9b1d7c7b26743f82c51cc7cce917d60005433604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1600190505b919050565b600060005490505b9056', }; eth.sendTransaction(testTransaction, (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 66); done(); }); }); }); it('should function while eth_sign', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); const testTxData = '0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470'; eth.sign(accounts[0], testTxData, (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result) > 0, true); done(); }); }); }); it('should function while eth_getTransactionReceipt', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); const testTransaction = { from: accounts[0], to: accounts[2], gas: 3000000, data: '0x', }; eth.sendTransaction(testTransaction, (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 66); setTimeout(() => { eth.getTransactionReceipt(result, (receiptError, receipt) => { assert.equal(receiptError, null); assert.equal(typeof receipt, 'object'); assert.equal(getBinarySize(receipt.transactionHash), 66); assert.equal(receipt.transactionIndex.toNumber(10) >= 0, true); assert.equal(receipt.blockNumber.toNumber(10) >= 0, true); assert.equal(receipt.cumulativeGasUsed.toNumber(10) >= 0, true); assert.equal(receipt.gasUsed.toNumber(10) >= 0, true); assert.equal(Array.isArray(receipt.logs), true); done(); }); }, 340); }); }); }); it('should function while deploy, use contract via eth_call, eth_getCode', (done) => { const eth = new Eth(provider); // eslint-disable-line eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); const testContractTransaction = { from: accounts[0], gas: 3000000, data: '606060405234610000575b61016a806100186000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063119c56bd1461004e57806360fe47b11461008e5780636d4ce63c146100c1575b610000565b346100005761005b6100e4565b604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b34610000576100a960048080359060200190919050506100f5565b60405180821515815260200191505060405180910390f35b34610000576100ce61015f565b6040518082815260200191505060405180910390f35b60006000610d7d91503390505b9091565b6000816000819055507f10e8e9bc5a1bde3dd6bb7245b52503fcb9d9b1d7c7b26743f82c51cc7cce917d60005433604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1600190505b919050565b600060005490505b9056', }; const contractABI = [{'constant': false,'inputs': [],'name': 'setcompeltereturn','outputs': [{'name': '_newValue','type': 'uint256'},{'name': '_sender','type': 'address'}],'payable': false,'type': 'function'},{'constant': false,'inputs': [{'name': '_value','type': 'uint256'}],'name': 'set','outputs': [{'name': '','type': 'bool'}],'payable': false,'type': 'function'},{'constant': false,'inputs': [],'name': 'get','outputs': [{'name': 'storeValue','type': 'uint256'}],'payable': false,'type': 'function'},{'anonymous':false,'inputs':[{'indexed':false,'name':'_newValue','type':'uint256'},{'indexed':false,'name':'_sender','type':'address'}],'name':'SetComplete','type':'event'}]; // eslint-disable-line eth.sendTransaction(testContractTransaction, (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 66); setTimeout(() => { eth.getTransactionReceipt(result, (receiptError, receipt) => { assert.equal(receiptError, null); assert.equal(typeof receipt, 'object'); assert.equal(getBinarySize(receipt.transactionHash), 66); assert.equal(receipt.transactionIndex.toNumber(10) >= 0, true); assert.equal(receipt.blockNumber.toNumber(10) >= 0, true); assert.equal(receipt.cumulativeGasUsed.toNumber(10) >= 0, true); assert.equal(receipt.gasUsed.toNumber(10) >= 0, true); assert.equal(Array.isArray(receipt.logs), true); assert.equal(typeof receipt.contractAddress, 'string'); const uintValue = 350000; const setMethodTransaction = { from: accounts[0], to: receipt.contractAddress, gas: 3000000, data: abi.encodeMethod(contractABI[1], [uintValue]), }; eth.sendTransaction(setMethodTransaction, (setMethodError, setMethodTx) => { assert.equal(setMethodError, null); assert.equal(typeof setMethodTx, 'string'); assert.equal(getBinarySize(setMethodTx), 66); setTimeout(() => { const callMethodTransaction = { to: receipt.contractAddress, data: abi.encodeMethod(contractABI[2], []), }; eth.call(callMethodTransaction, (callError, callResult) => { // eslint-disable-line assert.equal(setMethodError, null); const decodedUint = abi.decodeMethod(contractABI[2], callResult); assert.equal(decodedUint[0].toNumber(10), uintValue); eth.getCode(receipt.contractAddress, 'latest', (codeError, codeResult) => { assert.equal(codeError, null); assert.equal(typeof codeResult, 'string'); done(); }); }); }, 400); }); }); }, 1000); }); }); }); it('should function while deploy, use contract via eth_call, eth_getCode with debug, logger', (done) => { const eth = new Eth(provider, { debug: true, logger: { log: () => {} }, jsonSpace: 2 }); // eslint-disable-line eth.accounts((accountsError, accounts) => { assert.equal(accountsError, null); assert.equal(typeof accounts, 'object'); const testContractTransaction = { from: accounts[0], gas: 3000000, data: '606060405234610000575b61016a806100186000396000f360606040526000357c010000000000000000000000000000000000000000000000000000000090048063119c56bd1461004e57806360fe47b11461008e5780636d4ce63c146100c1575b610000565b346100005761005b6100e4565b604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390f35b34610000576100a960048080359060200190919050506100f5565b60405180821515815260200191505060405180910390f35b34610000576100ce61015f565b6040518082815260200191505060405180910390f35b60006000610d7d91503390505b9091565b6000816000819055507f10e8e9bc5a1bde3dd6bb7245b52503fcb9d9b1d7c7b26743f82c51cc7cce917d60005433604051808381526020018273ffffffffffffffffffffffffffffffffffffffff1681526020019250505060405180910390a1600190505b919050565b600060005490505b9056', }; const contractABI = [{'constant': false,'inputs': [],'name': 'setcompeltereturn','outputs': [{'name': '_newValue','type': 'uint256'},{'name': '_sender','type': 'address'}],'payable': false,'type': 'function'},{'constant': false,'inputs': [{'name': '_value','type': 'uint256'}],'name': 'set','outputs': [{'name': '','type': 'bool'}],'payable': false,'type': 'function'},{'constant': false,'inputs': [],'name': 'get','outputs': [{'name': 'storeValue','type': 'uint256'}],'payable': false,'type': 'function'},{'anonymous':false,'inputs':[{'indexed':false,'name':'_newValue','type':'uint256'},{'indexed':false,'name':'_sender','type':'address'}],'name':'SetComplete','type':'event'}]; // eslint-disable-line eth.sendTransaction(testContractTransaction, (error, result) => { assert.equal(error, null); assert.equal(typeof result, 'string'); assert.equal(getBinarySize(result), 66); setTimeout(() => { eth.getTransactionReceipt(result, (receiptError, receipt) => { assert.equal(receiptError, null); assert.equal(typeof receipt, 'object'); assert.equal(getBinarySize(receipt.transactionHash), 66); assert.equal(receipt.transactionIndex.toNumber(10) >= 0, true); assert.equal(receipt.blockNumber.toNumber(10) >= 0, true); assert.equal(receipt.cumulativeGasUsed.toNumber(10) >= 0, true); assert.equal(receipt.gasUsed.toNumber(10) >= 0, true); assert.equal(Array.isArray(receipt.logs), true); assert.equal(typeof receipt.contractAddress, 'string'); const uintValue = 350000; const setMethodTransaction = { from: accounts[0], to: receipt.contractAddress, gas: 3000000, data: abi.encodeMethod(contractABI[1], [uintValue]), }; eth.sendTransaction(setMethodTransaction, (setMethodError, setMethodTx) => { assert.equal(setMethodError, null); assert.equal(typeof setMethodTx, 'string'); assert.equal(getBinarySize(setMethodTx), 66); setTimeout(() => { const callMethodTransaction = { to: receipt.contractAddress, data: abi.encodeMethod(contractABI[2], []), }; eth.call(callMethodTransaction, (callError, callResult) => { // eslint-disable-line assert.equal(setMethodError, null); const decodedUint = abi.decodeMethod(contractABI[2], callResult); assert.equal(decodedUint[0].toNumber(10), uintValue); eth.getCode(receipt.contractAddress, 'latest', (codeError, codeResult) => { assert.equal(codeError, null); assert.equal(typeof codeResult, 'string'); done(); }); }); }, 400); }); }); }, 1000); }); }); }); }); });