UNPKG

stellar-plus

Version:

beta version of stellar-plus, an all-in-one sdk for the Stellar blockchain

224 lines (223 loc) 13.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const stellar_sdk_1 = require("@stellar/stellar-sdk"); const soroban_get_transaction_1 = require("../../../../stellar-plus/core/pipelines/soroban-get-transaction"); const errors_1 = require("../../../../stellar-plus/core/pipelines/soroban-get-transaction/errors"); const types_1 = require("../../../../stellar-plus/core/pipelines/soroban-get-transaction/types"); const network_1 = require("../../../../stellar-plus/network"); const default_handler_1 = require("../../../../stellar-plus/rpc/default-handler"); jest.mock('stellar-plus/rpc/default-handler', () => ({ DefaultRpcHandler: jest.fn().mockImplementation(() => ({ getTransaction: jest.fn(), })), })); const MOCKED_RPC_HANDLER = default_handler_1.DefaultRpcHandler; const TESTNET_CONFIG = (0, network_1.TestNet)(); const MOCKED_PK_A = 'GACF23GKVFTU77K6W6PWSVN7YBM63UHDULILIEXJO6FR4YKMJ7FW3DTI'; const MOCKED_ACCOUNT_A = new stellar_sdk_1.Account(MOCKED_PK_A, '100'); const MOCKED_TX_OPTIONS = { fee: '100', networkPassphrase: TESTNET_CONFIG.networkPassphrase, timebounds: { minTime: 0, maxTime: 0, }, }; const MOCKED_SOROBAN_SUBMISSION = { status: 'PENDING', hash: 'mocked-hash', latestLedger: 0, latestLedgerCloseTime: 0, }; const MOCKED_SUCCESSFUL_RESPONSE = { status: stellar_sdk_1.rpc.Api.GetTransactionStatus.SUCCESS, }; const MOCKED_FAILED_RESPONSE = { status: stellar_sdk_1.rpc.Api.GetTransactionStatus.FAILED, resultXdr: stellar_sdk_1.xdr.TransactionResult.fromXDR('AAAAAAAAAGT////4AAAAAA==', 'base64'), resultMetaXdr: stellar_sdk_1.xdr.TransactionMeta.fromXDR('AAAAAwAAAAAAAAACAAAAAwAOgggAAAAAAAAAAFBASCSXn/T00voyqd7Oqs2WBynZaF3xrCVh+ffvMXR7AAAAF0h255wADoHgAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAQAOgggAAAAAAAAAAFBASCSXn/T00voyqd7Oqs2WBynZaF3xrCVh+ffvMXR7AAAAF0h255wADoHgAAAAAQAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAAAAAAAAAMAAAAAAA6CCAAAAABmDqzhAAAAAAAAAAEAAAAAAAAAAAAAAAA=', 'base64'), }; const MOCKED_MISSING_RESPONSE = { status: stellar_sdk_1.rpc.Api.GetTransactionStatus.NOT_FOUND, }; const mockConveyorBeltErrorMeta = (item) => { return { item, meta: { itemId: 'mocked-id', beltId: 'mocked-belt-id', beltType: types_1.SorobanGetTransactionPipelineType.id, }, }; }; describe('SorobanGetTransaction', () => { describe('Initialize', () => { it('should initialize the pipeline', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline(); expect(pipeline).toBeDefined(); })); it('should initialize the pipeline with the default options', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline(); // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment const mockedOptions = jest.mocked(pipeline.options); expect(mockedOptions).toBeDefined(); expect(mockedOptions.defaultSecondsToWait).toBe(30); expect(mockedOptions.useEnvelopeTimeout).toBe(true); })); it('should initialize the pipeline with the given options', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const customOptions = { defaultSecondsToWait: 10, useEnvelopeTimeout: false, }; const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline({ options: customOptions }); // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment const spyOptions = jest.mocked(pipeline.options); expect(spyOptions).toBeDefined(); expect(spyOptions.defaultSecondsToWait).toBe(customOptions.defaultSecondsToWait); expect(spyOptions.useEnvelopeTimeout).toBe(customOptions.useEnvelopeTimeout); })); it('should initialize the pipeline with the given plugins', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { const mockedPlugin = jest.fn().mockImplementation(() => ({ preProcess: jest.fn(), type: types_1.SorobanGetTransactionPipelineType.id, })); const customPlugins = [mockedPlugin]; const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline({ plugins: customPlugins }); // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment const spyPlugins = jest.mocked(pipeline.plugins); expect(spyPlugins).toBeDefined(); expect(spyPlugins).toBe(customPlugins); })); }); describe('Core functionalities', () => { beforeEach(() => { jest.clearAllMocks(); }); it('should process the transaction and return if successful', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { MOCKED_RPC_HANDLER.mockImplementationOnce(() => ({ getTransaction: jest.fn().mockResolvedValue(MOCKED_SUCCESSFUL_RESPONSE), })); const mockedRpcHandler = new default_handler_1.DefaultRpcHandler(TESTNET_CONFIG); const mockedTransactionEnvelope = new stellar_sdk_1.TransactionBuilder(MOCKED_ACCOUNT_A, MOCKED_TX_OPTIONS).build(); const mockedItem = { rpcHandler: mockedRpcHandler, sorobanSubmission: MOCKED_SOROBAN_SUBMISSION, transactionEnvelope: mockedTransactionEnvelope, }; const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline(); const spyGetTransaction = jest.spyOn(mockedRpcHandler, 'getTransaction'); const response = yield pipeline.execute(mockedItem); expect(response).toBeDefined(); expect(response).toEqual({ response: MOCKED_SUCCESSFUL_RESPONSE }); expect(spyGetTransaction).toHaveBeenCalledTimes(1); expect(spyGetTransaction).toHaveBeenCalledWith(MOCKED_SOROBAN_SUBMISSION.hash); })); it('should process the transaction and continue trying if missing', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { MOCKED_RPC_HANDLER.mockImplementationOnce(() => ({ getTransaction: jest .fn() .mockResolvedValue(MOCKED_SUCCESSFUL_RESPONSE) .mockResolvedValueOnce(MOCKED_MISSING_RESPONSE) .mockResolvedValueOnce(MOCKED_MISSING_RESPONSE), })); const mockedRpcHandler = new default_handler_1.DefaultRpcHandler(TESTNET_CONFIG); const mockedTransactionEnvelope = new stellar_sdk_1.TransactionBuilder(MOCKED_ACCOUNT_A, MOCKED_TX_OPTIONS).build(); const mockedItem = { rpcHandler: mockedRpcHandler, sorobanSubmission: MOCKED_SOROBAN_SUBMISSION, transactionEnvelope: mockedTransactionEnvelope, }; const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline(); const spyGetTransaction = jest.spyOn(mockedRpcHandler, 'getTransaction'); const response = yield pipeline.execute(mockedItem); expect(response).toBeDefined(); expect(response).toEqual({ response: MOCKED_SUCCESSFUL_RESPONSE }); expect(spyGetTransaction).toHaveBeenCalledTimes(3); expect(spyGetTransaction).toHaveBeenCalledWith(MOCKED_SOROBAN_SUBMISSION.hash); })); it('should get the timeout from the transaction envelope when useEnvelopeTimeout is true', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { MOCKED_RPC_HANDLER.mockImplementationOnce(() => ({ getTransaction: jest.fn().mockResolvedValue(MOCKED_SUCCESSFUL_RESPONSE), })); const mockedRpcHandler = new default_handler_1.DefaultRpcHandler(TESTNET_CONFIG); const timeoutSeconds = 100; const mockedTransactionEnvelope = new stellar_sdk_1.TransactionBuilder(MOCKED_ACCOUNT_A, MOCKED_TX_OPTIONS) .setTimeout(timeoutSeconds) .build(); const mockedItem = { rpcHandler: mockedRpcHandler, sorobanSubmission: MOCKED_SOROBAN_SUBMISSION, transactionEnvelope: mockedTransactionEnvelope, }; const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline({ options: { defaultSecondsToWait: 30, useEnvelopeTimeout: true }, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any const spyGetSecondsToWait = jest.spyOn(pipeline, 'getSecondsToWait'); yield pipeline.execute(mockedItem); expect(spyGetSecondsToWait).toHaveBeenCalledTimes(1); expect(spyGetSecondsToWait).toHaveReturnedWith(timeoutSeconds); })); it('should get the timeout from the inner transaction envelope when useEnvelopeTimeout is true and transaction is a fee bump', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { MOCKED_RPC_HANDLER.mockImplementationOnce(() => ({ getTransaction: jest.fn().mockResolvedValue(MOCKED_SUCCESSFUL_RESPONSE), })); const mockedRpcHandler = new default_handler_1.DefaultRpcHandler(TESTNET_CONFIG); const timeoutSeconds = 17; const mockedInnerTransactionEnvelope = new stellar_sdk_1.TransactionBuilder(MOCKED_ACCOUNT_A, MOCKED_TX_OPTIONS) .setTimeout(timeoutSeconds) .build(); const mockedFeeBumpTransactionEnvelope = stellar_sdk_1.TransactionBuilder.buildFeeBumpTransaction(MOCKED_PK_A, MOCKED_TX_OPTIONS.fee + 1, // Fee bump fee needs to be higher than ineer transaction fee mockedInnerTransactionEnvelope, TESTNET_CONFIG.networkPassphrase); const mockedItem = { rpcHandler: mockedRpcHandler, sorobanSubmission: MOCKED_SOROBAN_SUBMISSION, transactionEnvelope: mockedFeeBumpTransactionEnvelope, }; const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline({ options: { defaultSecondsToWait: 30, useEnvelopeTimeout: true }, }); // eslint-disable-next-line @typescript-eslint/no-explicit-any const spyGetSecondsToWait = jest.spyOn(pipeline, 'getSecondsToWait'); yield pipeline.execute(mockedItem); expect(spyGetSecondsToWait).toHaveBeenCalledTimes(1); expect(spyGetSecondsToWait).toHaveReturnedWith(timeoutSeconds); })); }); describe('Error handling', () => { beforeEach(() => { jest.clearAllMocks(); }); it('should throw an error if the transaction failed', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { MOCKED_RPC_HANDLER.mockImplementationOnce(() => ({ getTransaction: jest.fn().mockResolvedValue(MOCKED_FAILED_RESPONSE), })); const mockedRpcHandler = new default_handler_1.DefaultRpcHandler(TESTNET_CONFIG); const mockedTransactionEnvelope = new stellar_sdk_1.TransactionBuilder(MOCKED_ACCOUNT_A, MOCKED_TX_OPTIONS).build(); const mockedItem = { rpcHandler: mockedRpcHandler, sorobanSubmission: MOCKED_SOROBAN_SUBMISSION, transactionEnvelope: mockedTransactionEnvelope, }; const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline(); yield expect(pipeline.execute(mockedItem)).rejects.toThrow(errors_1.SGTError.transactionFailed(mockConveyorBeltErrorMeta(mockedItem), MOCKED_FAILED_RESPONSE)); })); it('should throw an error if the transaction is not found', () => tslib_1.__awaiter(void 0, void 0, void 0, function* () { MOCKED_RPC_HANDLER.mockImplementationOnce(() => ({ getTransaction: jest.fn().mockResolvedValue(MOCKED_MISSING_RESPONSE), })); const mockedRpcHandler = new default_handler_1.DefaultRpcHandler(TESTNET_CONFIG); const mockedTransactionEnvelope = new stellar_sdk_1.TransactionBuilder(MOCKED_ACCOUNT_A, MOCKED_TX_OPTIONS).build(); const mockedItem = { rpcHandler: mockedRpcHandler, sorobanSubmission: MOCKED_SOROBAN_SUBMISSION, transactionEnvelope: mockedTransactionEnvelope, }; const pipeline = new soroban_get_transaction_1.SorobanGetTransactionPipeline({ options: { defaultSecondsToWait: 3, useEnvelopeTimeout: false }, }); yield expect(pipeline.execute(mockedItem)).rejects.toThrow(errors_1.SGTError.transactionNotFound(mockConveyorBeltErrorMeta(mockedItem), 30, MOCKED_SOROBAN_SUBMISSION.hash)); })); }); });