Skip to content

Commit

Permalink
Adds unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Konstantina Blazhukova <[email protected]>
  • Loading branch information
konstantinabl committed Oct 31, 2024
1 parent cc16db5 commit b4ec668
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 32 deletions.
3 changes: 2 additions & 1 deletion packages/relay/src/lib/clients/sdkClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -473,9 +473,10 @@ export class SDKClient {
if (e instanceof SDKClientError && (e.isConnectionDropped() || e.isTimeoutExceeded())) {
if (!(await this.isFailedTransaction(requestDetails, e.transactionId))) {
txResponse = { transactionId: e.transactionId };
} else {
throw e;
}
}
throw e;
}

return {
Expand Down
74 changes: 43 additions & 31 deletions packages/relay/tests/lib/eth/eth_sendRawTransaction.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
import { HbarLimitService } from '../../../src/lib/services/hbarLimitService';
import { EventEmitter } from 'events';
import pino from 'pino';
import { SDKClient } from '../../../src/lib/clients';
import { MirrorNodeClient, SDKClient } from '../../../src/lib/clients';
import { ACCOUNT_ADDRESS_1, DEFAULT_NETWORK_FEES, MAX_GAS_LIMIT_HEX, NO_TRANSACTIONS } from './eth-config';
import { Eth, JsonRpcError, predefined } from '../../../src';
import RelayAssertions from '../../assertions';
Expand All @@ -46,11 +46,14 @@ import { RequestDetails } from '../../../src/lib/types';
import MockAdapter from 'axios-mock-adapter';
import HAPIService from '../../../src/lib/services/hapiService/hapiService';
import { CacheService } from '../../../src/lib/services/cacheService/cacheService';
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 @@ -71,6 +74,7 @@ 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 Down Expand Up @@ -291,53 +295,61 @@ describe('@ethSendRawTransaction eth_sendRawTransaction spec', async function ()
);
});

it('should not send second transaction upon succession', async function () {
restMock.onGet(contractResultEndpoint).reply(200, { hash: ethereumHash });
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);

sdkClientStub.submitEthereumTransaction.resolves({
txResponse: {
transactionId: TransactionId.fromString(transactionIdServicesFormat),
} as TransactionResponse,
fileId: null,
});
restMock.onGet(contractResultEndpoint).reply(200, { hash: ethereumHash });

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));
sdkClientStub.isFailedTransaction.resolves(false);
const signed = await signTransaction(transaction);

const resultingHash = await ethImpl.sendRawTransaction(signed, requestDetails);
expect(resultingHash).to.equal(ethereumHash);
sinon.assert.calledOnce(sdkClientStub.submitEthereumTransaction);
});

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

sdkClientStub.submitEthereumTransaction.onCall(0).throws(new SDKClientError({ status: 21 }, 'timeout exceeded'));

sdkClientStub.submitEthereumTransaction.onCall(1).resolves({
txResponse: {
transactionId: TransactionId.fromString(transactionIdServicesFormat),
} as TransactionResponse,
fileId: null,
});
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();

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

const resultingHash = await ethImpl.sendRawTransaction(signed, requestDetails);
expect(resultingHash).to.equal(ethereumHash);
sinon.assert.calledTwice(sdkClientStub.submitEthereumTransaction);
const response = (await ethImpl.sendRawTransaction(signed, requestDetails)) as JsonRpcError;
console.log(response);
expect(response).to.be.instanceOf(JsonRpcError);
expect(response.message).to.include('timeout exceeded');
sinon.assert.called(sdkClientStub.isFailedTransaction);
});

it('should not send second transaction on error different from timeout', async function () {
sdkClientStub.submitEthereumTransaction
.onCall(0)
.throws(new SDKClientError({ status: 50 }, 'wrong transaction body'));
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.createFile.resolves(new FileId(0, 0, 5644));
sdkClientStub.executeTransaction.onCall(0).throws(new SDKClientError({ status: 21 }, 'Connection dropped'));
sdkClientStub.isFailedTransaction.resolves(true);
const signed = await signTransaction(transaction);

const response = (await ethImpl.sendRawTransaction(signed, requestDetails)) as JsonRpcError;
expect(response.code).to.equal(predefined.INTERNAL_ERROR().code);
expect(`Error invoking RPC: ${response.message}`).to.equal(predefined.INTERNAL_ERROR(response.message).message);
sinon.assert.calledOnce(sdkClientStub.submitEthereumTransaction);
console.log(response);
expect(response).to.be.instanceOf(JsonRpcError);
expect(response.message).to.include('Connection dropped');
sinon.assert.called(sdkClientStub.isFailedTransaction);
});
});
});
1 change: 1 addition & 0 deletions packages/relay/tests/lib/sdkClient.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ describe('SdkClient', async function () {
new CacheService(logger.child({ name: `cache` }), registry),
eventEmitter,
hbarLimitService,
register,
);

instance = axios.create({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ describe('Metric Service', function () {
new CacheService(logger.child({ name: `cache` }), registry),
eventEmitter,
hbarLimitService,
register,
);
// Init new MetricService instance
metricService = new MetricService(logger, sdkClient, mirrorNodeClient, registry, eventEmitter, hbarLimitService);
Expand Down

0 comments on commit b4ec668

Please sign in to comment.