UNPKG

@ledgerhq/coin-stacks

Version:
264 lines (233 loc) 7.71 kB
import { TransactionResponse } from "../types/api"; import { extractTokenTransferTransactions, extractSendManyTransactions, extractContractTransactions, } from "./transformers"; import * as api from "./api"; import * as cryptoAssets from "@ledgerhq/cryptoassets/state"; // Mock the CryptoAssets module jest.mock("@ledgerhq/cryptoassets/state"); // Mock the API module to prevent actual network calls jest.mock("./api", () => { const originalModule = jest.requireActual("./api"); return { ...originalModule, fetchFungibleTokenMetadataCached: jest.fn(), }; }); describe("Stacks API Transformers", () => { const mockTransactions: TransactionResponse[] = [ { tx: { tx_id: "0xabc123", tx_type: "token_transfer", // Other token transfer specific fields }, }, { tx: { tx_id: "0xdef456", tx_type: "contract_call", contract_call: { contract_id: "SP123.TOKEN-A", function_name: "send-many", }, }, }, { tx: { tx_id: "0xghi789", tx_type: "contract_call", contract_call: { contract_id: "SP456.TOKEN-B", function_name: "transfer", }, post_conditions: [ { type: "fungible", asset: { asset_name: "TOKEN-B", }, }, ], }, }, { tx: { tx_id: "0xjkl012", tx_type: "contract_call", contract_call: { contract_id: "SP789.TOKEN-C", function_name: "transfer", }, post_conditions: [ { type: "fungible", asset: { asset_name: "TOKEN-C", }, }, ], }, }, { tx: { tx_id: "0xmno345", tx_type: "smart_contract", // Other smart contract specific fields }, }, { tx: { tx_id: "0xpqr678", tx_type: "contract_call", contract_call: { contract_id: "SP456.TOKEN-B", function_name: "other-function", }, }, }, { tx: { tx_id: "0xstu901", tx_type: "contract_call", contract_call: { contract_id: "SP456.TOKEN-B", function_name: "transfer", }, // Missing post_conditions }, }, { tx: { tx_id: "0xvwx234", tx_type: "contract_call", contract_call: { // Missing contract_id function_name: "transfer", }, post_conditions: [ { type: "fungible", asset: { asset_name: "TOKEN-D", }, }, ], }, }, ] as TransactionResponse[]; describe("extractTokenTransferTransactions", () => { it("should extract only token transfer transactions", () => { const result = extractTokenTransferTransactions(mockTransactions); expect(result).toHaveLength(1); expect(result[0].tx?.tx_id).toEqual("0xabc123"); expect(result[0].tx?.tx_type).toEqual("token_transfer"); }); it("should return empty array when no token transfers exist", () => { const noTokenTransfers = mockTransactions.filter(tx => tx.tx?.tx_type !== "token_transfer"); const result = extractTokenTransferTransactions(noTokenTransfers); expect(result).toHaveLength(0); }); }); describe("extractSendManyTransactions", () => { it("should extract only send-many transactions", () => { const result = extractSendManyTransactions(mockTransactions); expect(result).toHaveLength(1); expect(result[0].tx?.tx_id).toEqual("0xdef456"); expect(result[0].tx?.tx_type).toEqual("contract_call"); expect(result[0].tx?.contract_call?.function_name).toEqual("send-many"); }); it("should return empty array when no send-many transactions exist", () => { const noSendManyTxs = mockTransactions.filter( tx => !( tx.tx?.tx_type === "contract_call" && tx.tx?.contract_call?.function_name === "send-many" ), ); const result = extractSendManyTransactions(noSendManyTxs); expect(result).toHaveLength(0); }); }); describe("extractContractTransactions", () => { beforeEach(() => { // Reset all mocks before each test jest.clearAllMocks(); // Mock CryptoAssetsStore (cryptoAssets.getCryptoAssetsStore as jest.Mock).mockReturnValue({ findTokenById: jest.fn().mockResolvedValue(null), findTokenByAddressInCurrency: jest.fn().mockResolvedValue(null), }); // Mock fetchFungibleTokenMetadataCached to return empty results by default // This prevents actual network calls and simulates tokens not found in metadata (api.fetchFungibleTokenMetadataCached as unknown as jest.Mock).mockResolvedValue({ results: [], }); }); it("should extract and group transfer transactions by token ID", async () => { const result = await extractContractTransactions(mockTransactions); // We expect two tokens with transfer function expect(Object.keys(result)).toHaveLength(2); // Check sp456.token-b::token-b expect(result["sp456.token-b::token-b"]).toEqual([ expect.objectContaining({ tx: expect.objectContaining({ tx_id: "0xghi789", }), }), ]); // Check sp789.token-c::token-c expect(result["sp789.token-c::token-c"]).toEqual([ expect.objectContaining({ tx: expect.objectContaining({ tx_id: "0xjkl012", }), }), ]); }); it("should exclude non-contract calls", async () => { const result = await extractContractTransactions(mockTransactions); // Make sure token_transfer and smart_contract are excluded const allTxIds = Object.values(result) .flat() .map(tx => tx.tx?.tx_id); expect(allTxIds).not.toContain("0xabc123"); // token_transfer expect(allTxIds).not.toContain("0xmno345"); // smart_contract }); it("should exclude send-many transactions", async () => { const result = await extractContractTransactions(mockTransactions); const allTxIds = Object.values(result) .flat() .map(tx => tx.tx?.tx_id); expect(allTxIds).not.toContain("0xdef456"); // send-many }); it("should exclude non-transfer function calls", async () => { const result = await extractContractTransactions(mockTransactions); const allTxIds = Object.values(result) .flat() .map(tx => tx.tx?.tx_id); expect(allTxIds).not.toContain("0xpqr678"); // other-function }); it("should handle missing post_conditions", async () => { const result = await extractContractTransactions(mockTransactions); const allTxIds = Object.values(result) .flat() .map(tx => tx.tx?.tx_id); expect(allTxIds).not.toContain("0xstu901"); // Missing post_conditions }); it("should handle missing contract_id", async () => { const result = await extractContractTransactions(mockTransactions); const allTxIds = Object.values(result) .flat() .map(tx => tx.tx?.tx_id); expect(allTxIds).not.toContain("0xvwx234"); // Missing contract_id }); it("should return empty object when no valid contract transactions exist", async () => { const noContractTxs = mockTransactions.filter(tx => tx.tx?.tx_type !== "contract_call"); const result = await extractContractTransactions(noContractTxs); expect(result).toEqual({}); }); }); });