UNPKG

bitcore-node

Version:

A blockchain indexing node with extended capabilities using bitcore

284 lines 13.1 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || (function () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); const bson_1 = require("bson"); const chai_1 = require("chai"); const events_1 = require("events"); const sinon = __importStar(require("sinon")); const csp_1 = require("../../../../src/modules/matic/api/csp"); const csp_2 = require("../../../../src/providers/chain-state/evm/api/csp"); const helpers_1 = require("../../../helpers"); describe('MATIC Chain State Provider', function () { const chain = 'MATIC'; const network = 'regtest'; it('should be able to get web3', async () => { const sandbox = sinon.createSandbox(); const web3Stub = { eth: { getBlockNumber: sandbox.stub().resolves(1) } }; sandbox.stub(csp_2.BaseEVMStateProvider, 'rpcs').value({ MATIC: { [network]: [{ web3: web3Stub, rpc: sinon.stub(), dataType: 'combined' }] } }); const { web3 } = await csp_1.MATIC.getWeb3(network); const block = await web3.eth.getBlockNumber(); const stub = web3.eth.getBlockNumber; (0, chai_1.expect)(stub.callCount).to.eq(2); (0, chai_1.expect)(block).to.eq(1); sandbox.restore(); }); it('should make a new web3 if getBlockNumber fails', async () => { const sandbox = sinon.createSandbox(); const web3Stub = { eth: { getBlockNumber: sandbox.stub().throws('Block number fails') } }; sandbox.stub(csp_2.BaseEVMStateProvider, 'rpcs').value({ MATIC: { [network]: [{ web3: web3Stub, rpc: sinon.stub(), dataType: 'combined' }] } }); const { web3 } = await csp_1.MATIC.getWeb3(network); const stub = web3.eth.getBlockNumber; (0, chai_1.expect)(stub.callCount).to.not.exist; sandbox.restore(); }); it('should get ERC20 information', async () => { const sandbox = sinon.createSandbox(); const expected = { name: 'Test Token', decimals: 10, symbol: 'TST' }; const tokenStub = { methods: { name: () => ({ call: sandbox.stub().resolves(expected.name) }), decimals: () => ({ call: sandbox.stub().resolves(expected.decimals) }), symbol: () => ({ call: sandbox.stub().resolves(expected.symbol) }) } }; sandbox.stub(csp_1.MATIC, 'erc20For').resolves(tokenStub); const token = await csp_1.MATIC.getERC20TokenInfo(network, '0x123'); (0, chai_1.expect)(token.name).to.eq(expected.name); (0, chai_1.expect)(token.symbol).to.eq(expected.symbol); (0, chai_1.expect)(token.decimals).to.eq(expected.decimals); sandbox.restore(); }); it('should be able to find an MATIC transaction', async () => { const sandbox = sinon.createSandbox(); const mockTx = { _id: new bson_1.ObjectId(), chain: 'MATIC', network: 'testnet', txid: '123', blockHeight: 1, gasPrice: 10, data: Buffer.from('') }; sandbox.stub(csp_1.MATIC, 'getReceipt').resolves({ gasUsed: 21000 }); sandbox.stub(csp_1.MATIC, 'getLocalTip').resolves({ height: 1 }); (0, helpers_1.mockModel)('transactions', mockTx); const found = await csp_1.MATIC.getTransaction({ chain: 'MATIC', network: 'testnet', txId: '123' }); (0, chai_1.expect)(found).to.exist; (0, chai_1.expect)(found.fee).to.eq(21000 * 10); (0, chai_1.expect)(found.confirmations).to.eq(1); sandbox.restore(); }); it('should be able to broadcast an array of txs', async () => { const sandbox = sinon.createSandbox(); const web3Stub = { eth: { getBlockNumber: sandbox.stub().resolves(1), sendSignedTransaction: sandbox.stub().callsFake(tx => { const emitter = new events_1.EventEmitter(); emitter.catch = sandbox.stub().returnsThis(); setTimeout(() => { emitter.emit('transactionHash', tx); }, 10); return emitter; }) } }; sandbox.stub(csp_2.BaseEVMStateProvider, 'rpcs').value({ MATIC: { [network]: [{ web3: web3Stub, rpc: sinon.stub(), dataType: 'combined' }] } }); const txids = await csp_1.MATIC.broadcastTransaction({ chain, network, rawTx: ['123', '456'] }); (0, chai_1.expect)(web3Stub.eth.sendSignedTransaction.calledWith('123')).to.eq(true); (0, chai_1.expect)(web3Stub.eth.sendSignedTransaction.calledWith('456')).to.eq(true); (0, chai_1.expect)(txids).to.deep.eq(['123', '456']); sandbox.restore(); }); it('should be able to broadcast a single tx', async () => { const sandbox = sinon.createSandbox(); const web3Stub = { eth: { getBlockNumber: sandbox.stub().resolves(1), sendSignedTransaction: sandbox.stub().callsFake((tx) => { const emitter = new events_1.EventEmitter(); emitter.catch = sandbox.stub().returnsThis(); setTimeout(() => { emitter.emit('transactionHash', tx); }, 10); return emitter; }) } }; sandbox.stub(csp_2.BaseEVMStateProvider, 'rpcs').value({ MATIC: { [network]: [{ web3: web3Stub, rpc: sinon.stub(), dataType: 'combined' }] } }); const txid = await csp_1.MATIC.broadcastTransaction({ chain, network, rawTx: '123' }); (0, chai_1.expect)(web3Stub.eth.sendSignedTransaction.calledWith('123')).to.eq(true); (0, chai_1.expect)(txid).to.eq('123'); sandbox.restore(); }); it('should stop broadcasting txs on error', async () => { const sandbox = sinon.createSandbox(); let shouldThrow = false; const web3Stub = { eth: { getBlockNumber: sandbox.stub().resolves(1), sendSignedTransaction: sandbox.stub().callsFake(() => { const emitter = new events_1.EventEmitter(); const err = new Error('fake error'); emitter.catch = cb => cb(err); if (!shouldThrow) { setTimeout(() => { emitter.emit('transactionHash'); }, 10); shouldThrow = true; } else { setTimeout(() => { emitter.emit('error', err); }, 10); } return emitter; }) } }; sandbox.stub(csp_2.BaseEVMStateProvider, 'rpcs').value({ MATIC: { [network]: [{ web3: web3Stub, rpc: sinon.stub(), dataType: 'combined' }] } }); let thrown = false; try { await csp_1.MATIC.broadcastTransaction({ chain, network, rawTx: ['123', '456'] }); } catch (e) { thrown = true; } (0, chai_1.expect)(thrown).to.eq(true); (0, chai_1.expect)(web3Stub.eth.sendSignedTransaction.calledWith('123')).to.eq(true); (0, chai_1.expect)(web3Stub.eth.sendSignedTransaction.calledWith('456')).to.eq(false); sandbox.restore(); }); it('should be able to find an MATIC block', async () => { const sandbox = sinon.createSandbox(); const mockBlock = { _id: new bson_1.ObjectId(), hash: '55555', height: 1 }; (0, helpers_1.mockModel)('blocks', mockBlock); const found = await csp_1.MATIC.getBlocks({ chain, network, blockId: mockBlock.hash }); (0, chai_1.expect)(found).to.exist; (0, chai_1.expect)(found[0]).to.exist; (0, chai_1.expect)(found[0].hash).to.eq(mockBlock.hash); (0, chai_1.expect)(found[0].height).to.eq(mockBlock.height); sandbox.restore(); }); describe('estimateGas', () => { const sandbox = sinon.createSandbox(); const web3Stub = { utils: { toHex: (val) => val && Buffer.from(val.toString()).toString('hex') }, eth: { getBlockNumber: sandbox.stub().resolves(1) }, currentProvider: { send: sandbox.stub() } }; beforeEach(() => { sandbox.stub(csp_2.BaseEVMStateProvider, 'rpcs').value({ MATIC: { [network]: [{ web3: web3Stub, rpc: sinon.stub(), dataType: 'combined' }] } }); }); afterEach(() => { sandbox.restore(); }); it('it should return gas', async () => { web3Stub.currentProvider.send.callsArgWith(1, null, { result: '12345' }); const gas = await csp_1.MATIC.estimateGas({ network, to: '0x123', from: '0xabc', gasPrice: 123, value: 'lorem' }); (0, chai_1.expect)(gas).to.equal(12345); }); it('should return gas for optional params', async () => { web3Stub.currentProvider.send.callsArgWith(1, null, { result: '1234' }); const gas = await csp_1.MATIC.estimateGas({ network }); (0, chai_1.expect)(gas).to.equal(1234); }); it('should reject an error response', async () => { web3Stub.currentProvider.send.callsArgWith(1, 'Unavailable server', null); // body is null try { await csp_1.MATIC.estimateGas({ network }); throw new Error('should have thrown'); } catch (err) { (0, chai_1.expect)(err).to.equal('Unavailable server'); } }); it('should reject if response body is missing result', async () => { web3Stub.currentProvider.send.callsArgWith(1, null, { message: 'need some param' }); try { await csp_1.MATIC.estimateGas({ network }); throw new Error('should have thrown'); } catch (err) { (0, chai_1.expect)(err).to.deep.equal({ message: 'need some param' }); } }); it('should reject if response body is missing result and has error', async () => { web3Stub.currentProvider.send.callsArgWith(1, null, { error: { code: 2, message: 'need some param' } }); try { await csp_1.MATIC.estimateGas({ network }); throw new Error('should have thrown'); } catch (err) { (0, chai_1.expect)(err).to.deep.equal({ code: 2, message: 'need some param' }); } }); it('should reject on unexpected error', async () => { web3Stub.currentProvider.send.callsArgWith(1, null, { result: '12345' }); try { await csp_1.MATIC.estimateGas({ network: 'unexpected' }); throw new Error('should have thrown'); } catch (err) { (0, chai_1.expect)(err.message).to.equal('No configuration found for unexpected and "realtime" compatible dataType'); } }); it('should reject on unexpected error in callback', async () => { web3Stub.currentProvider.send.callsArgWith(1, null, null); // body is null try { await csp_1.MATIC.estimateGas({ network }); throw new Error('should have thrown'); } catch (err) { (0, chai_1.expect)(err.message).to.equal('Cannot read properties of null (reading \'result\')'); } }); }); }); //# sourceMappingURL=csp.spec.js.map