UNPKG

@ledgerhq/coin-stellar

Version:
405 lines (390 loc) 11.8 kB
// SPDX-FileCopyrightText: © 2026 LEDGER SAS // SPDX-License-Identifier: Apache-2.0 import { Horizon } from '@stellar/stellar-sdk' import coinConfig from '../config' import { listOperations } from './listOperations' jest.mock('@stellar/stellar-sdk') describe('listOperations', () => { coinConfig.setCoinConfig(() => ({ status: { type: 'active' }, explorer: { url: 'https://stellar.coin.ledger.com' }, })) const mockCall = jest.fn() beforeEach(() => { ;(Horizon.Server as jest.Mock).mockImplementation(() => ({ operations: () => ({ forAccount: () => ({ limit: () => ({ order: () => ({ cursor: () => ({ includeFailed: () => ({ join: () => ({ call: mockCall, }), }), }), }), }), }), }), })) }) afterEach(() => { jest.clearAllMocks() }) it('lists operations associated with an address', async () => { mockCall.mockResolvedValueOnce({ records: [ { id: 'operation_id1', transaction_hash: 'transaction_hash1', paging_token: 'token1', source_account: 'address', from: 'address', to: 'receiver1', amount: '46.0600000', type: Horizon.HorizonApi.OperationResponseType.payment, transaction_successful: true, created_at: '2025-01-01', transaction: () => ({ fee_charged: '111900', fee_account: 'address', ledger_attr: 42, ledger: () => ({ hash: 'block_hash1', closed_at: '2025-01-01', }), }), }, { id: 'operation_id2', transaction_hash: 'transaction_hash1', paging_token: 'token2', source_account: 'address', from: 'address', to: 'receiver2', amount: '666.0000000', type: Horizon.HorizonApi.OperationResponseType.payment, transaction_successful: false, created_at: '2025-01-01', transaction: () => ({ fee_charged: '11100', fee_account: 'address', ledger_attr: 42, ledger: () => ({ hash: 'block_hash1', closed_at: '2025-01-01', }), }), }, { id: 'operation_id3', transaction_hash: 'transaction_hash2', paging_token: 'token3', source_account: 'sender', from: 'sender', to: 'address', amount: '50.5000000', type: Horizon.HorizonApi.OperationResponseType.payment, transaction_successful: true, created_at: '2025-01-01', transaction: () => ({ fee_charged: '111', fee_account: 'sender', ledger_attr: 42, ledger: () => ({ hash: 'block_hash1', closed_at: '2025-01-01', }), }), }, ], } as any) expect(await listOperations('address', { order: 'asc', minHeight: 0 })).toEqual({ items: [ { id: 'transaction_hash1-operation_id1', asset: { type: 'native' }, details: { assetAmount: '460600000', ledgerOpType: 'OUT', sequence: undefined, memo: undefined, }, senders: ['address'], recipients: ['receiver1'], tx: { block: { hash: 'block_hash1', height: 42, time: new Date('2025-01-01') }, date: new Date('2025-01-01'), fees: 111900n, feesPayer: 'address', hash: 'transaction_hash1', failed: false, }, type: 'OUT', value: 460600000n, }, { id: 'transaction_hash1-operation_id2', asset: { type: 'native' }, details: { assetAmount: '11100', ledgerOpType: 'OUT', sequence: undefined, memo: undefined, }, senders: ['address'], recipients: ['receiver2'], tx: { block: { hash: 'block_hash1', height: 42, time: new Date('2025-01-01') }, date: new Date('2025-01-01'), fees: 11100n, feesPayer: 'address', hash: 'transaction_hash1', failed: true, }, type: 'OUT', value: 11100n, }, { id: 'transaction_hash2-operation_id3', asset: { type: 'native' }, details: { assetAmount: '505000000', ledgerOpType: 'IN', sequence: undefined, memo: undefined, }, senders: ['sender'], recipients: ['address'], tx: { block: { hash: 'block_hash1', height: 42, time: new Date('2025-01-01') }, date: new Date('2025-01-01'), fees: 111n, feesPayer: 'sender', hash: 'transaction_hash2', failed: false, }, type: 'IN', value: 505000000n, }, ], next: '', }) }) it('stops at minHeight', async () => { mockCall.mockResolvedValueOnce({ records: [ { id: 'operation_id1', transaction_hash: 'transaction_hash1', paging_token: 'token1', source_account: 'address', from: 'address', to: 'receiver1', amount: '46.0600000', type: Horizon.HorizonApi.OperationResponseType.payment, transaction_successful: true, created_at: '2025-01-01', transaction: () => ({ fee_charged: '111900', fee_account: 'address', ledger_attr: 42, ledger: () => ({ hash: 'block_hash1', closed_at: '2025-01-01', }), }), }, { id: 'operation_id2', transaction_hash: 'transaction_hash1', paging_token: 'token2', source_account: 'address', from: 'address', to: 'receiver2', amount: '666.0000000', type: Horizon.HorizonApi.OperationResponseType.payment, transaction_successful: false, created_at: '2025-01-01', transaction: () => ({ fee_charged: '11100', fee_account: 'address', ledger_attr: 41, ledger: () => ({ hash: 'block_hash1', closed_at: '2025-01-01', }), }), }, { id: 'operation_id3', transaction_hash: 'transaction_hash2', paging_token: 'token3', source_account: 'sender', from: 'sender', to: 'address', amount: '50.5000000', type: Horizon.HorizonApi.OperationResponseType.payment, transaction_successful: true, created_at: '2025-01-01', transaction: () => ({ fee_charged: '111', fee_account: 'sender', ledger_attr: 40, ledger: () => ({ hash: 'block_hash1', closed_at: '2025-01-01', }), }), }, ], } as any) expect(await listOperations('address', { order: 'asc', minHeight: 41 })).toEqual({ items: [ { id: 'transaction_hash1-operation_id1', asset: { type: 'native' }, details: { assetAmount: '460600000', ledgerOpType: 'OUT', sequence: undefined, memo: undefined, }, senders: ['address'], recipients: ['receiver1'], tx: { block: { hash: 'block_hash1', height: 42, time: new Date('2025-01-01') }, date: new Date('2025-01-01'), fees: 111900n, feesPayer: 'address', hash: 'transaction_hash1', failed: false, }, type: 'OUT', value: 460600000n, }, { id: 'transaction_hash1-operation_id2', asset: { type: 'native' }, details: { assetAmount: '11100', ledgerOpType: 'OUT', sequence: undefined, memo: undefined, }, senders: ['address'], recipients: ['receiver2'], tx: { block: { hash: 'block_hash1', height: 41, time: new Date('2025-01-01') }, date: new Date('2025-01-01'), fees: 11100n, feesPayer: 'address', hash: 'transaction_hash1', failed: true, }, type: 'OUT', value: 11100n, }, ], next: '', }) }) it('should return memo if set', async () => { mockCall.mockResolvedValueOnce({ records: [ { id: 'operation_id1', transaction_hash: 'transaction_hash1', paging_token: 'token1', source_account: 'address', from: 'address', to: 'receiver1', amount: '46.0600000', type: Horizon.HorizonApi.OperationResponseType.payment, transaction_successful: true, created_at: '2025-01-01', transaction: () => ({ fee_charged: '111900', fee_account: 'address', ledger_attr: 42, memo_type: 'text', memo: 'momo', ledger: () => ({ hash: 'block_hash1', closed_at: '2025-01-01', }), }), }, ], } as any) expect(await listOperations('address', { order: 'asc', minHeight: 0 })).toEqual({ items: [ { id: 'transaction_hash1-operation_id1', asset: { type: 'native' }, senders: ['address'], recipients: ['receiver1'], tx: { block: { hash: 'block_hash1', height: 42, time: new Date('2025-01-01') }, date: new Date('2025-01-01'), fees: 111900n, feesPayer: 'address', hash: 'transaction_hash1', failed: false, }, type: 'OUT', value: 460600000n, details: { assetAmount: '460600000', ledgerOpType: 'OUT', sequence: undefined, memo: { type: 'MEMO_TEXT', value: 'momo', }, }, }, ], next: '', }) }) it('uses fee_account as feesPayer for fee bump transactions when fee_account differs from source_account', async () => { mockCall.mockResolvedValueOnce({ records: [ { id: 'operation_id1', transaction_hash: 'transaction_hash1', paging_token: 'token1', source_account: 'address', from: 'address', to: 'receiver1', amount: '10.0000000', type: Horizon.HorizonApi.OperationResponseType.payment, transaction_successful: true, created_at: '2025-01-01', transaction: () => ({ fee_charged: '500', fee_account: 'sponsor_address', source_account: 'address', ledger_attr: 42, ledger: () => ({ hash: 'block_hash1', closed_at: '2025-01-01', }), }), }, ], } as any) const { items: operations } = await listOperations('address', { order: 'asc', minHeight: 0 }) expect(operations).toHaveLength(1) expect(operations[0]).toMatchObject({ tx: { fees: 500n, feesPayer: 'sponsor_address', }, senders: ['address'], recipients: ['receiver1'], }) }) })