Skip to content

Commit

Permalink
feat(frontend): add sol-transactions.services.ts
Browse files Browse the repository at this point in the history
  • Loading branch information
loki344 committed Jan 8, 2025
1 parent 1bb4050 commit 0819d91
Show file tree
Hide file tree
Showing 2 changed files with 201 additions and 0 deletions.
84 changes: 84 additions & 0 deletions src/frontend/src/sol/services/sol-transactions.services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import type { SolAddress } from '$lib/types/address';
import { getSolTransactions } from '$sol/api/solana.api';
import { type SolCertifiedTransaction, solTransactionsStore } from '$sol/stores/sol-transactions.store';
import { SolanaNetworks, type SolanaNetworkType } from '$sol/types/network';
import {
SOLANA_DEVNET_TOKEN_ID,
SOLANA_LOCAL_TOKEN_ID,
SOLANA_TESTNET_TOKEN_ID,
SOLANA_TOKEN_ID
} from '$env/tokens/tokens.sol.env';

export const loadNextSolTransactions = async ({
address,
network,
before,
limit,
signalEnd
}: {
address: SolAddress;
network: SolanaNetworkType;
before?: string;
limit?: number;
signalEnd: () => void;
}): Promise<SolCertifiedTransaction[]> => {
const transactions = await loadSolTransactions({
address,
network,
before,
limit
});

if (transactions.length === 0) {
signalEnd();
return [];
}

return transactions;
};

const networkToSolTokenIdMap = {
[SolanaNetworks.mainnet]: SOLANA_TOKEN_ID,
[SolanaNetworks.testnet]: SOLANA_TESTNET_TOKEN_ID,
[SolanaNetworks.devnet]: SOLANA_DEVNET_TOKEN_ID,
[SolanaNetworks.local]: SOLANA_LOCAL_TOKEN_ID
};

const loadSolTransactions = async ({
address,
network,
before,
limit
}: {
address: SolAddress;
network: SolanaNetworkType;
before?: string;
limit?: number;
}): Promise<SolCertifiedTransaction[]> => {

const solTokenIdForNetwork = networkToSolTokenIdMap[network];

try {
const transactions = await getSolTransactions({
address,
network,
before,
limit
});

solTransactionsStore.append({
tokenId: solTokenIdForNetwork,
transactions: transactions
});

return transactions;
} catch (error: unknown) {
solTransactionsStore.reset(solTokenIdForNetwork);

console.error(
`Failed to load transactions for ${solTokenIdForNetwork.description}:`,
error
);
return [];
}
};
117 changes: 117 additions & 0 deletions src/frontend/src/tests/sol/services/sol-transactions.services.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
import { SOLANA_TOKEN_ID } from '$env/tokens/tokens.sol.env';
import * as solanaApi from '$sol/api/solana.api';
import { loadNextSolTransactions } from '$sol/services/sol-transactions.services';
import { solTransactionsStore } from '$sol/stores/sol-transactions.store';
import { SolanaNetworks } from '$sol/types/network';
import { mockSolCertifiedTransactions } from '$tests/mocks/sol-transactions.mock';

Check failure on line 6 in src/frontend/src/tests/sol/services/sol-transactions.services.spec.ts

View workflow job for this annotation

GitHub Actions / test

'"$tests/mocks/sol-transactions.mock"' has no exported member named 'mockSolCertifiedTransactions'. Did you mean 'mockSolRpcSendTransaction'?
import { mockSolAddress } from '$tests/mocks/sol.mock';
import { get } from 'svelte/store';
import type { MockInstance } from 'vitest';
import { mockSolSignature } from '$tests/mocks/sol-signatures.mock';

describe('sol-transactions.services', () => {
let spyGetTransactions: MockInstance;
const signalEnd = vi.fn();

beforeEach(() => {
vi.clearAllMocks();
solTransactionsStore.reset(SOLANA_TOKEN_ID);
spyGetTransactions = vi.spyOn(solanaApi, 'getSolTransactions');
});

describe('loadNextSolTransactions', () => {
it('should load and return transactions successfully', async () => {
spyGetTransactions.mockResolvedValue(mockSolCertifiedTransactions);

const transactions = await loadNextSolTransactions({
address: mockSolAddress,
network: SolanaNetworks.mainnet,
signalEnd
});

expect(transactions).toEqual(mockSolCertifiedTransactions);
expect(signalEnd).not.toHaveBeenCalled();
expect(spyGetTransactions).toHaveBeenCalledWith({
address: mockSolAddress,
network: SolanaNetworks.mainnet
});
});

it('should handle pagination parameters', async () => {
spyGetTransactions.mockResolvedValue(mockSolCertifiedTransactions);
const before = mockSolSignature();
const limit = 10;

await loadNextSolTransactions({
address: mockSolAddress,
network: SolanaNetworks.mainnet,
before,
limit,
signalEnd
});

expect(spyGetTransactions).toHaveBeenCalledWith({
address: mockSolAddress,
network: SolanaNetworks.mainnet,
before,
limit
});
});

it('should signal end when no transactions are returned', async () => {
spyGetTransactions.mockResolvedValue([]);

const transactions = await loadNextSolTransactions({
address: mockSolAddress,
network: SolanaNetworks.mainnet,
signalEnd
});

expect(transactions).toEqual([]);
expect(signalEnd).toHaveBeenCalled();
});

it('should append transactions to the store', async () => {
spyGetTransactions.mockResolvedValue(mockSolCertifiedTransactions);

await loadNextSolTransactions({
address: mockSolAddress,
network: SolanaNetworks.mainnet,
signalEnd
});

const storeData = get(solTransactionsStore)?.[SOLANA_TOKEN_ID];
expect(storeData).toEqual(mockSolCertifiedTransactions);
});

it('should handle errors and reset store', async () => {
const error = new Error('Failed to load transactions');
spyGetTransactions.mockRejectedValue(error);

const transactions = await loadNextSolTransactions({
address: mockSolAddress,
network: SolanaNetworks.mainnet,
signalEnd
});

expect(transactions).toEqual([]);
const storeData = get(solTransactionsStore)?.[SOLANA_TOKEN_ID];
expect(storeData).toBeNull();
});

it('should work with different networks', async () => {
spyGetTransactions.mockResolvedValue(mockSolCertifiedTransactions);

await loadNextSolTransactions({
address: mockSolAddress,
network: SolanaNetworks.devnet,
signalEnd
});

expect(spyGetTransactions).toHaveBeenCalledWith({
address: mockSolAddress,
network: SolanaNetworks.devnet
});
});
});
});

0 comments on commit 0819d91

Please sign in to comment.