Skip to content

Commit

Permalink
test: fixed unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Logan Nguyen <[email protected]>
  • Loading branch information
quiet-node committed Nov 6, 2024
1 parent b0617e5 commit d4302bd
Showing 1 changed file with 45 additions and 56 deletions.
101 changes: 45 additions & 56 deletions packages/relay/tests/lib/eth/eth_sendRawTransaction.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import { ConfigService } from '@hashgraph/json-rpc-config-service/dist/services';
import { expect, use } from 'chai';
import createHash from 'keccak';
import sinon from 'sinon';
import chaiAsPromised from 'chai-as-promised';
import {
Expand Down Expand Up @@ -51,9 +52,7 @@ import * as utils from '../../../src/formatters';
use(chaiAsPromised);

let sdkClientStub: sinon.SinonStubbedInstance<SDKClient>;
let mirrorNodeStub: sinon.SinonStubbedInstance<MirrorNodeClient>;
let getSdkClientStub: sinon.SinonStub;
let formatTransactionIdWithoutQueryParamsStub: sinon.SinonStub;

describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function () {
this.timeout(10000);
Expand All @@ -74,7 +73,6 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
await cacheService.clear(requestDetails);
restMock.reset();
sdkClientStub = sinon.createStubInstance(SDKClient);
mirrorNodeStub = sinon.createStubInstance(MirrorNodeClient);
getSdkClientStub = sinon.stub(hapiServiceInstance, 'getSDKClient').returns(sdkClientStub);
restMock.onGet('network/fees').reply(200, DEFAULT_NETWORK_FEES);
});
Expand All @@ -91,7 +89,7 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
const transactionIdServicesFormat = '[email protected]';
const transactionId = '0.0.902-1684375868-230217103';
const value = '0x511617DE831B9E173';
const contractResultEndpoint = `contracts/results/${transactionId}`;
const getTransactionByIdEndpoint = `transactions/${transactionId}?nonce=0`;
const networkExchangeRateEndpoint = 'network/exchangerate';
const ethereumHash = '0x6d20b034eecc8d455c4c040fb3763082d499353a8b7d318b1085ad8d7de15f7e';
const mockedExchangeRate = {
Expand Down Expand Up @@ -160,17 +158,20 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
sdkClientStub.logger = pino();
sdkClientStub.deleteFile.resolves();

restMock.onGet(contractResultEndpoint).reply(200, { hash: ethereumHash });
restMock.onGet(getTransactionByIdEndpoint).reply(200, {});

const signed = await signTransaction({
...transaction,
data: '0x' + '22'.repeat(13000),
});
const txBuffer = Buffer.from(signed.replace('0x', ''), 'hex');
const expectedHash = utils.prepend0x(createHash('keccak256').update(txBuffer).digest('hex'));

const resultingHash = await ethImpl.sendRawTransaction(signed, requestDetails);

expect(eventEmitterMock.emit.callCount).to.equal(1);
expect(hbarLimiterMock.shouldLimit.callCount).to.equal(1);
expect(resultingHash).to.equal(ethereumHash);
expect(resultingHash).to.equal(expectedHash);
});

it('should return a predefined GAS_LIMIT_TOO_HIGH instead of NUMERIC_FAULT as precheck exception', async function () {
Expand All @@ -189,7 +190,7 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
it('should return a computed hash if unable to retrieve EthereumHash from record due to contract revert', async function () {
const signed = await signTransaction(transaction);

restMock.onGet(`transactions/${transactionId}`).reply(200, null);
restMock.onGet(getTransactionByIdEndpoint).reply(200, null);

const resultingHash = await ethImpl.sendRawTransaction(signed, requestDetails);
expect(resultingHash).to.equal(ethereumHash);
Expand All @@ -198,12 +199,11 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
it('should throw internal error when transaction returned from mirror node is null', async function () {
const signed = await signTransaction(transaction);

restMock.onGet(contractResultEndpoint).reply(404, mockData.notFound);
restMock.onGet(`transactions/${transactionId}?nonce=0`).reply(200, null);
restMock.onGet(getTransactionByIdEndpoint).reply(200, null);

sdkClientStub.submitEthereumTransaction.resolves({
txResponse: {
transactionId: '',
transactionId: transactionIdServicesFormat,
} as unknown as TransactionResponse,
fileId: null,
});
Expand All @@ -217,7 +217,7 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
it('should throw internal error when transactionID is invalid', async function () {
const signed = await signTransaction(transaction);

restMock.onGet(contractResultEndpoint).reply(200, { hash: ethereumHash });
restMock.onGet(getTransactionByIdEndpoint).reply(200, {});

sdkClientStub.submitEthereumTransaction.resolves({
txResponse: {
Expand All @@ -232,8 +232,8 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
expect(`Error invoking RPC: ${response.message}`).to.equal(predefined.INTERNAL_ERROR(response.message).message);
});

it('should return hash from ContractResult mirror node api', async function () {
restMock.onGet(contractResultEndpoint).reply(200, { hash: ethereumHash });
it('should return hash by calculating transaction hash using keccak256', async function () {
restMock.onGet(getTransactionByIdEndpoint).reply(200, {});

sdkClientStub.submitEthereumTransaction.resolves({
txResponse: {
Expand All @@ -242,13 +242,15 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
fileId: null,
});
const signed = await signTransaction(transaction);
const txBuffer = Buffer.from(signed.replace('0x', ''), 'hex');
const expectedHash = utils.prepend0x(createHash('keccak256').update(txBuffer).digest('hex'));

const resultingHash = await ethImpl.sendRawTransaction(signed, requestDetails);
expect(resultingHash).to.equal(ethereumHash);
expect(resultingHash).to.equal(expectedHash);
});

it('should not send second transaction upon succession', async function () {
restMock.onGet(contractResultEndpoint).reply(200, { hash: ethereumHash });
restMock.onGet(getTransactionByIdEndpoint).reply(200, {});

sdkClientStub.submitEthereumTransaction.resolves({
txResponse: {
Expand Down Expand Up @@ -295,54 +297,41 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
);
});

it('should call mirror node upon time out and return successful if found', async function () {
const transactionId = '0.0.902';
const contractResultEndpoint = `contracts/results/${transactionId}`;
formatTransactionIdWithoutQueryParamsStub = sinon.stub(utils, 'formatTransactionIdWithoutQueryParams');
formatTransactionIdWithoutQueryParamsStub.returns(transactionId);

restMock.onGet(contractResultEndpoint).reply(200, { hash: ethereumHash });
['timeout exceeded', 'Connection dropped'].forEach((error) => {
it(`should poll mirror node upon ${error} error for valid transaction and return correct transaction hash`, async function () {
restMock
.onGet(getTransactionByIdEndpoint)
.replyOnce(404, mockData.notFound)
.onGet(getTransactionByIdEndpoint)
.reply(200, {});

sdkClientStub.submitEthereumTransaction.restore();
mirrorNodeStub.repeatedRequest = sinon.stub();
mirrorNodeStub.getTransactionById = sinon.stub();
sdkClientStub.deleteFile.resolves();
sdkClientStub.createFile.resolves(new FileId(0, 0, 5644));
sdkClientStub.executeTransaction
.onCall(0)
.throws(new SDKClientError({ status: 21 }, 'timeout exceeded', transactionId));
const signed = await signTransaction(transaction);

const resultingHash = await ethImpl.sendRawTransaction(signed, requestDetails);
expect(resultingHash).to.equal(ethereumHash);
});
sdkClientStub.submitEthereumTransaction
.onCall(0)
.throws(new SDKClientError({ status: 21 }, error, transactionIdServicesFormat));

it('should call mirror node upon time out and throw error if not found', async function () {
sdkClientStub.submitEthereumTransaction.restore();
mirrorNodeStub.repeatedRequest = sinon.stub();
mirrorNodeStub.getTransactionById = sinon.stub();
const signed = await signTransaction(transaction);

sdkClientStub.createFile.resolves(new FileId(0, 0, 5644));
sdkClientStub.executeTransaction.onCall(0).throws(new SDKClientError({ status: 21 }, 'timeout exceeded'));
const signed = await signTransaction(transaction);
const resultingHash = await ethImpl.sendRawTransaction(signed, requestDetails);
expect(resultingHash).to.equal(ethereumHash);
});

const response = (await ethImpl.sendRawTransaction(signed, requestDetails)) as JsonRpcError;
expect(response).to.be.instanceOf(JsonRpcError);
expect(response.message).to.include('timeout exceeded');
});
it(`should poll mirror node upon ${error} error for valid transaction and return correct ${error} error if no transaction is found`, async function () {
restMock
.onGet(getTransactionByIdEndpoint)
.replyOnce(404, mockData.notFound)
.onGet(getTransactionByIdEndpoint)
.reply(200, null);

it('should call mirror node upon connection dropped and throw error if not found', async function () {
sdkClientStub.submitEthereumTransaction.restore();
mirrorNodeStub.repeatedRequest = sinon.stub();
mirrorNodeStub.getTransactionById = sinon.stub();
sdkClientStub.submitEthereumTransaction
.onCall(0)
.throws(new SDKClientError({ status: 21 }, error, transactionIdServicesFormat));

sdkClientStub.createFile.resolves(new FileId(0, 0, 5644));
sdkClientStub.executeTransaction.onCall(0).throws(new SDKClientError({ status: 21 }, 'Connection dropped'));
const signed = await signTransaction(transaction);
const signed = await signTransaction(transaction);

const response = (await ethImpl.sendRawTransaction(signed, requestDetails)) as JsonRpcError;
expect(response).to.be.instanceOf(JsonRpcError);
expect(response.message).to.include('Connection dropped');
const response = (await ethImpl.sendRawTransaction(signed, requestDetails)) as JsonRpcError;
expect(response).to.be.instanceOf(JsonRpcError);
expect(response.message).to.include(error);
});
});
});
});

0 comments on commit d4302bd

Please sign in to comment.