Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions eslint-suppressions.json
Original file line number Diff line number Diff line change
Expand Up @@ -1702,11 +1702,6 @@
"count": 4
}
},
"packages/tron-wallet-snap/src/services/transactions/TransactionsService.test.ts": {
"@typescript-eslint/no-explicit-any": {
"count": 1
}
},
"packages/tron-wallet-snap/src/services/wallet/WalletService.test.ts": {
"@typescript-eslint/explicit-function-return-type": {
"count": 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,13 @@ type WithTransactionServiceCallback<ReturnValue> = (payload: {
async function withTransactionService<ReturnValue>(
testFunction: WithTransactionServiceCallback<ReturnValue>,
): Promise<ReturnValue> {
// Mock the global snap object
Object.defineProperty(globalThis, 'snap', {
value: { request: jest.fn() },
writable: true,
configurable: true,
});

const mockTransactionsRepository: jest.Mocked<
Pick<
TransactionsRepository,
Expand Down Expand Up @@ -135,14 +142,6 @@ async function withTransactionService<ReturnValue>(
// Import simplified mock data (each file now contains only one transaction)

describe('TransactionsService', () => {
let transactionsService: TransactionsService;
let mockLogger: jest.Mocked<ILogger>;
let mockTransactionsRepository: jest.Mocked<TransactionsRepository>;
let mockTrongridApiClient: jest.Mocked<TrongridApiClient>;
let mockTronHttpClient: jest.Mocked<TronHttpClient>;
let mockPriceApiClient: jest.Mocked<PriceApiClient>;
let mockSnapClient: jest.Mocked<SnapClient>;

const mockAccount: TronKeyringAccount = {
id: 'test-account-id',
address: 'TGJn1wnUYHJbvN88cynZbsAz2EMeZq73yx',
Expand All @@ -167,65 +166,6 @@ describe('TransactionsService', () => {
index: 1,
};

beforeEach(() => {
// Mock the global snap object
const snap = {
request: jest.fn(),
};
(globalThis as any).snap = snap;

// Create mocks
mockLogger = {
log: jest.fn(),
debug: jest.fn(),
info: jest.fn(),
warn: jest.fn(),
error: jest.fn(),
};

// Create mock repository
mockTransactionsRepository = {
getAll: jest.fn(),
findByAccountId: jest.fn().mockResolvedValue([]),
getTransactionIdsByAccountId: jest.fn().mockResolvedValue(new Set()),
getConfirmedTransactionIds: jest.fn().mockResolvedValue(new Set()),
save: jest.fn(),
saveMany: jest.fn(),
} as unknown as jest.Mocked<TransactionsRepository>;

// Create mock API client
mockTrongridApiClient = {
getAccountInfoByAddress: jest.fn(),
getTransactionInfoByAddress: jest.fn(),
getContractTransactionInfoByAddress: jest.fn(),
} as unknown as jest.Mocked<TrongridApiClient>;

// Create mock TronHttpClient
mockTronHttpClient = {
getTRC10TokenMetadata: jest.fn(),
getTransactionInfoById: jest.fn(),
} as unknown as jest.Mocked<TronHttpClient>;

// Create mock PriceApiClient — default: no price data (all tokens filtered unless overridden)
mockPriceApiClient = {
getMultipleSpotPrices: jest.fn().mockResolvedValue({}),
} as unknown as jest.Mocked<PriceApiClient>;

mockSnapClient = {
trackError: jest.fn().mockResolvedValue(undefined),
} as unknown as jest.Mocked<SnapClient>;

// Create service instance
transactionsService = new TransactionsService({
logger: mockLogger,
transactionsRepository: mockTransactionsRepository,
trongridApiClient: mockTrongridApiClient,
tronHttpClient: mockTronHttpClient,
priceApiClient: mockPriceApiClient,
snapClient: mockSnapClient,
});
});

describe('checkAddressActivity', () => {
it('returns true when the address has at least one transaction', async () => {
await withTransactionService(
Expand Down Expand Up @@ -361,7 +301,7 @@ describe('TransactionsService', () => {

it('should fetch and map transactions for an account using native transfers mock data', async () => {
await withTransactionService(
async ({ mockTrongridApiClient, transactionsService, mockLogger }) => {
async ({ mockTrongridApiClient, transactionsService }) => {
// Setup mock responses with simplified single-transaction structure
mockTrongridApiClient.getTransactionInfoByAddress.mockResolvedValue([
nativeTransferMock,
Expand Down Expand Up @@ -626,7 +566,7 @@ describe('TransactionsService', () => {

it('should handle API errors gracefully', async () => {
await withTransactionService(
async ({ mockTrongridApiClient, transactionsService, mockLogger }) => {
async ({ mockTrongridApiClient, transactionsService }) => {
// Setup API to throw error
const apiError = new Error('API request failed');
mockTrongridApiClient.getTransactionInfoByAddress.mockRejectedValue(
Expand Down Expand Up @@ -988,7 +928,6 @@ describe('TransactionsService', () => {
async ({
mockPriceApiClient,
mockTrongridApiClient,
mockLogger,
mockSnapClient,
transactionsService,
}) => {
Expand Down Expand Up @@ -1402,51 +1341,63 @@ describe('TransactionsService', () => {

describe('Integration scenarios', () => {
it('should handle a complete flow: fetch, process, and save transactions', async () => {
// Setup API responses with simplified single-transaction structure
mockTrongridApiClient.getTransactionInfoByAddress.mockResolvedValue([
nativeTransferMock,
] as TransactionInfo[]);
mockTrongridApiClient.getContractTransactionInfoByAddress.mockResolvedValue(
contractInfoMock.data.slice(0, 1) as ContractTransactionInfo[],
);
await withTransactionService(
async ({
mockTransactionsRepository,
mockTrongridApiClient,
transactionsService,
}) => {
// Setup API responses with simplified single-transaction structure
mockTrongridApiClient.getTransactionInfoByAddress.mockResolvedValue([
nativeTransferMock,
] as TransactionInfo[]);
mockTrongridApiClient.getContractTransactionInfoByAddress.mockResolvedValue(
contractInfoMock.data.slice(0, 1) as ContractTransactionInfo[],
);

// Fetch transactions
const fetchedTransactions =
await transactionsService.fetchNewTransactionsForAccount(
Network.Mainnet,
mockAccount,
);
// Fetch transactions
const fetchedTransactions =
await transactionsService.fetchNewTransactionsForAccount(
Network.Mainnet,
mockAccount,
);

// Save the fetched transactions
await transactionsService.saveMany(fetchedTransactions);
// Save the fetched transactions
await transactionsService.saveMany(fetchedTransactions);

expect(mockTransactionsRepository.saveMany).toHaveBeenCalledWith(
fetchedTransactions,
expect(mockTransactionsRepository.saveMany).toHaveBeenCalledWith(
fetchedTransactions,
);
expect(true).toBe(true);
},
);
expect(true).toBe(true);
});

it('should handle mixed transaction types from different mock data sources', async () => {
// Mix different types of transactions with simplified structure
const mixedRawTransactions = [
nativeTransferMock, // Native TRX transfer
trc10TransferMock, // TRC10 transfer
trc20TransferMock, // TRC20 transfer
] as TransactionInfo[];

mockTrongridApiClient.getTransactionInfoByAddress.mockResolvedValue(
mixedRawTransactions,
);
mockTrongridApiClient.getContractTransactionInfoByAddress.mockResolvedValue(
[],
);
await withTransactionService(
async ({ mockTrongridApiClient, transactionsService }) => {
// Mix different types of transactions with simplified structure
const mixedRawTransactions = [
nativeTransferMock, // Native TRX transfer
trc10TransferMock, // TRC10 transfer
trc20TransferMock, // TRC20 transfer
] as TransactionInfo[];

await transactionsService.fetchNewTransactionsForAccount(
Network.Mainnet,
mockAccount2,
);
mockTrongridApiClient.getTransactionInfoByAddress.mockResolvedValue(
mixedRawTransactions,
);
mockTrongridApiClient.getContractTransactionInfoByAddress.mockResolvedValue(
[],
);

expect(true).toBe(true);
await transactionsService.fetchNewTransactionsForAccount(
Network.Mainnet,
mockAccount2,
);

expect(true).toBe(true);
},
);
});
});
});
Loading