@ledgerhq/live-common
Version:
Common ground for the Ledger Live apps
458 lines • 26.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const helper_1 = require("./helper");
const mock_1 = require("./mock");
const index_1 = require("../currencies/index");
const currencies_1 = require("../currencies");
const TOKEN_ONLY_ASSETS = mock_1.MOCK_TOKENS_ONLY;
const listSupportedTokens = () => (0, currencies_1.listTokens)().filter(t => (0, currencies_1.isCurrencySupported)(t.parentCurrency));
describe("Deposit logic", () => {
afterEach(() => {
(0, index_1.setSupportedCurrencies)([]);
});
describe("searchByProviderId", () => {
test("should find assets by provider ID", () => {
const result = (0, helper_1.searchByProviderId)(TOKEN_ONLY_ASSETS, "tether");
expect(result).toEqual(TOKEN_ONLY_ASSETS);
});
test("should return empty array for non-existent provider ID", () => {
const result = (0, helper_1.searchByProviderId)(TOKEN_ONLY_ASSETS, "non-existent-provider");
expect(result).toEqual([]);
});
test("should handle case insensitive search", () => {
const result = (0, helper_1.searchByProviderId)(TOKEN_ONLY_ASSETS, "TETHER");
expect(result).toEqual(TOKEN_ONLY_ASSETS);
});
test("should handle empty assets list", () => {
const result = (0, helper_1.searchByProviderId)([], "tether");
expect(result).toEqual([]);
});
test("should handle empty provider ID", () => {
const result = (0, helper_1.searchByProviderId)(TOKEN_ONLY_ASSETS, "");
expect(result).toEqual([]);
});
test("should handle special characters in provider ID", () => {
const mockAssets = [
{ ...TOKEN_ONLY_ASSETS[0], providerId: "test-provider_123" },
];
const result = (0, helper_1.searchByProviderId)(mockAssets, "test-provider_123");
expect(result).toHaveLength(1);
});
});
describe("searchByNameOrTicker", () => {
test("should find assets by name or ticker", () => {
const result = (0, helper_1.searchByNameOrTicker)(TOKEN_ONLY_ASSETS, "usdt");
expect(result.length).toBeGreaterThan(0);
});
test("should handle case insensitive search", () => {
const result = (0, helper_1.searchByNameOrTicker)(TOKEN_ONLY_ASSETS, "USDT");
expect(result.length).toBeGreaterThan(0);
});
test("should find partial matches", () => {
const result = (0, helper_1.searchByNameOrTicker)(TOKEN_ONLY_ASSETS, "usd");
expect(result.length).toBeGreaterThan(0);
});
test("should return empty array for non-matching search", () => {
const result = (0, helper_1.searchByNameOrTicker)(TOKEN_ONLY_ASSETS, "non-existent-token");
expect(result).toEqual([]);
});
test("should handle empty search term", () => {
const result = (0, helper_1.searchByNameOrTicker)(TOKEN_ONLY_ASSETS, "");
expect(result).toEqual(TOKEN_ONLY_ASSETS);
});
test("should handle empty assets list", () => {
const result = (0, helper_1.searchByNameOrTicker)([], "usdt");
expect(result).toEqual([]);
});
test("should search in both name and ticker fields", () => {
const mockAssets = [
{ ...TOKEN_ONLY_ASSETS[0], name: "Test Token", ticker: "TTK" },
{ ...TOKEN_ONLY_ASSETS[0], name: "Another Token", ticker: "USDT" },
];
const nameResult = (0, helper_1.searchByNameOrTicker)(mockAssets, "Test");
const tickerResult = (0, helper_1.searchByNameOrTicker)(mockAssets, "USDT");
expect(nameResult).toHaveLength(1);
expect(tickerResult).toHaveLength(1);
});
});
describe("groupCurrenciesByProvider", () => {
test("should group currencies by provider", () => {
const currencies = TOKEN_ONLY_ASSETS.map(asset => (0, index_1.findTokenById)(asset.ledgerId)).filter((t) => t !== undefined);
const { currenciesByProvider } = (0, helper_1.groupCurrenciesByProvider)(TOKEN_ONLY_ASSETS, currencies);
expect(currenciesByProvider).toEqual([
{
providerId: "tether",
currenciesByNetwork: currencies,
},
]);
});
test("should handle POL assets correctly", () => {
const currenciesPol = mock_1.MOCK_POL.map(asset => asset.$type === "Token"
? (0, index_1.findTokenById)(asset.ledgerId)
: (0, index_1.getCryptoCurrencyById)(asset.ledgerId)).filter((c) => c !== undefined);
const { currenciesByProvider: currenciesByProviderBis, sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mock_1.MOCK_POL, currenciesPol);
expect(currenciesByProviderBis).toEqual([
{
providerId: "matic-network",
currenciesByNetwork: currenciesPol,
},
]);
expect(sortedCryptoCurrencies).toEqual([currenciesPol[1]]);
});
test("should handle empty assets array", () => {
const currencies = TOKEN_ONLY_ASSETS.map(asset => (0, index_1.findTokenById)(asset.ledgerId)).filter((t) => t !== undefined);
const { currenciesByProvider, sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)([], currencies);
expect(currenciesByProvider).toEqual([]);
expect(sortedCryptoCurrencies).toEqual([]);
});
test("should handle empty currencies array", () => {
const { currenciesByProvider, sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(TOKEN_ONLY_ASSETS, []);
expect(currenciesByProvider).toEqual([]);
expect(sortedCryptoCurrencies).toEqual([]);
});
test("should handle currencies without corresponding assets", () => {
(0, index_1.setSupportedCurrencies)(["bitcoin"]);
const btcCurrency = (0, index_1.getCryptoCurrencyById)("bitcoin");
const { currenciesByProvider, sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(TOKEN_ONLY_ASSETS, [btcCurrency]);
expect(currenciesByProvider).toEqual([]);
expect(sortedCryptoCurrencies).toEqual([]);
});
test("should prioritize crypto currencies over tokens in sortedCryptoCurrencies", () => {
const mockAssets = [
{ ...TOKEN_ONLY_ASSETS[0], providerId: "test-provider" },
];
(0, index_1.setSupportedCurrencies)(["ethereum"]);
const ethCurrency = (0, index_1.getCryptoCurrencyById)("ethereum");
const tokenCurrency = (0, index_1.findTokenById)(TOKEN_ONLY_ASSETS[0].ledgerId);
if (!tokenCurrency)
throw new Error("Token not found");
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mockAssets, [
tokenCurrency,
ethCurrency,
]);
expect(sortedCryptoCurrencies.length).toBeGreaterThan(0);
});
test("should handle duplicate provider IDs correctly", () => {
const duplicateAssets = [
TOKEN_ONLY_ASSETS[0],
{ ...TOKEN_ONLY_ASSETS[0], ledgerId: "different-id" },
];
const token = (0, index_1.findTokenById)(TOKEN_ONLY_ASSETS[0].ledgerId);
if (!token)
throw new Error("Token not found");
const currencies = [token];
const { currenciesByProvider } = (0, helper_1.groupCurrenciesByProvider)(duplicateAssets, currencies);
expect(currenciesByProvider).toHaveLength(1);
expect(currenciesByProvider[0].currenciesByNetwork).toHaveLength(1);
});
});
describe("getTokenOrCryptoCurrencyById", () => {
test("should return crypto currency by ID", () => {
const result = (0, helper_1.getTokenOrCryptoCurrencyById)("bitcoin");
expect(result).toBeDefined();
expect(result.type).toBe("CryptoCurrency");
});
test("should return token by ID", () => {
const result = (0, helper_1.getTokenOrCryptoCurrencyById)("ethereum/erc20/usd_tether__erc20_");
expect(result).toBeDefined();
expect(result.type).toBe("TokenCurrency");
});
test("should handle invalid crypto currency ID", () => {
expect(() => (0, helper_1.getTokenOrCryptoCurrencyById)("invalid-crypto-id")).toThrow();
});
test("should handle invalid token ID", () => {
expect(() => (0, helper_1.getTokenOrCryptoCurrencyById)("invalid/token/id")).toThrow();
});
test("should handle empty ID", () => {
expect(() => (0, helper_1.getTokenOrCryptoCurrencyById)("")).toThrow();
});
});
describe("loadCurrenciesByProvider", () => {
test("should load currencies by provider successfully", async () => {
(0, index_1.setSupportedCurrencies)(["ethereum", "bitcoin"]);
const supportedCurrencies = (0, currencies_1.listSupportedCurrencies)();
const result = await (0, helper_1.loadCurrenciesByProvider)(supportedCurrencies);
expect(result).toBeDefined();
expect(result.currenciesByProvider).toBeDefined();
expect(result.sortedCryptoCurrencies).toBeDefined();
expect(Array.isArray(result.currenciesByProvider)).toBe(true);
expect(Array.isArray(result.sortedCryptoCurrencies)).toBe(true);
});
test("should handle empty currencies array", async () => {
const result = await (0, helper_1.loadCurrenciesByProvider)([]);
expect(result).toBeDefined();
expect(result.currenciesByProvider).toEqual([]);
expect(result.sortedCryptoCurrencies).toEqual([]);
});
test("should handle currencies with no corresponding assets", async () => {
(0, index_1.setSupportedCurrencies)(["bitcoin"]);
const supportedCurrencies = [(0, index_1.getCryptoCurrencyById)("bitcoin")];
const result = await (0, helper_1.loadCurrenciesByProvider)(supportedCurrencies);
expect(result).toBeDefined();
expect(Array.isArray(result.currenciesByProvider)).toBe(true);
expect(Array.isArray(result.sortedCryptoCurrencies)).toBe(true);
});
});
describe("Currency support scenarios", () => {
it("should return Arbitrum and not Optimism in the sortedCryptoCurrencies", () => {
(0, index_1.setSupportedCurrencies)(["arbitrum", "arbitrum_sepolia"]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mock_1.MOCK_WITH_TOKEN_AND_CURRENCY_ASSET, currencies);
expect(sortedCryptoCurrencies).toEqual([(0, index_1.getCryptoCurrencyById)("arbitrum")]);
});
it("should return Optimism only in the sortedCryptoCurrencies", () => {
(0, index_1.setSupportedCurrencies)(["optimism", "optimism_sepolia"]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mock_1.MOCK_WITH_TOKEN_AND_CURRENCY_ASSET, currencies);
expect(sortedCryptoCurrencies).toEqual([(0, index_1.getCryptoCurrencyById)("optimism")]);
});
it("should return currencies based on what's actually supported and available in mock data", () => {
(0, index_1.setSupportedCurrencies)(["optimism", "optimism_sepolia", "arbitrum", "arbitrum_sepolia"]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mock_1.MOCK_WITH_TOKEN_AND_CURRENCY_ASSET, currencies);
expect(Array.isArray(sortedCryptoCurrencies)).toBe(true);
expect(sortedCryptoCurrencies.length).toBeGreaterThanOrEqual(0);
sortedCryptoCurrencies.forEach(currency => {
expect(["optimism", "arbitrum"].includes(currency.id)).toBe(true);
});
});
});
describe("Token-only scenarios", () => {
it("should return only Polygon token while its currency is supported in the list", () => {
(0, index_1.setSupportedCurrencies)(["polygon"]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mock_1.MOCK_TOKENS_ONLY, currencies);
expect(sortedCryptoCurrencies).toEqual([(0, index_1.findTokenById)("polygon/erc20/(pos)_tether_usd")]);
});
it("should return only BSC token while its currency is supported in the list", () => {
(0, index_1.setSupportedCurrencies)(["bsc"]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mock_1.MOCK_TOKENS_ONLY, currencies);
expect(sortedCryptoCurrencies).toEqual([(0, index_1.findTokenById)("bsc/bep20/binance-peg_bsc-usd")]);
});
it("should return tokens that are actually supported based on mock data", () => {
(0, index_1.setSupportedCurrencies)(["ethereum", "bsc", "polygon"]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mock_1.MOCK_TOKENS_ONLY, currencies);
expect(Array.isArray(sortedCryptoCurrencies)).toBe(true);
expect(sortedCryptoCurrencies.length).toBeGreaterThanOrEqual(0);
sortedCryptoCurrencies.forEach(currency => {
expect(currency.type).toBe("TokenCurrency");
expect(["ethereum", "polygon", "bsc"].some(network => currency.id.includes(network))).toBe(true);
});
});
it("should return specific Ethereum and Polygon USDT tokens when both currencies are supported", () => {
(0, index_1.setSupportedCurrencies)(["ethereum", "polygon"]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mock_1.MOCK_TOKENS_ONLY, currencies);
expect(Array.isArray(sortedCryptoCurrencies)).toBe(true);
expect(sortedCryptoCurrencies.length).toBeGreaterThan(0);
const tokenIds = sortedCryptoCurrencies.map(currency => currency.id);
expect(tokenIds).toContain("ethereum/erc20/usd_tether__erc20_");
sortedCryptoCurrencies.forEach(currency => {
expect(currency.type).toBe("TokenCurrency");
expect(currency.id).toMatch(/tether|usdt/i);
});
});
it("should return all supported USDT tokens when multiple currencies are enabled", () => {
(0, index_1.setSupportedCurrencies)(["ethereum", "bsc", "polygon"]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(mock_1.MOCK_TOKENS_ONLY, currencies);
expect(Array.isArray(sortedCryptoCurrencies)).toBe(true);
expect(sortedCryptoCurrencies.length).toBeGreaterThan(0);
const tokenIds = sortedCryptoCurrencies.map(currency => currency.id);
expect(tokenIds).toContain("ethereum/erc20/usd_tether__erc20_");
sortedCryptoCurrencies.forEach(currency => {
expect(currency.type).toBe("TokenCurrency");
});
const hasExpectedNetworks = sortedCryptoCurrencies.every(currency => ["ethereum", "polygon", "bsc"].some(network => currency.id.includes(network)));
expect(hasExpectedNetworks).toBe(true);
});
it("should return empty array when no supported currencies", () => {
(0, index_1.setSupportedCurrencies)([]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)([...TOKEN_ONLY_ASSETS, ...mock_1.MOCK_WITH_TOKEN_AND_CURRENCY_ASSET], currencies);
expect(sortedCryptoCurrencies).toEqual([]);
});
});
describe("Comprehensive integration tests", () => {
it("should handle all supported currencies and tokens in the system", async () => {
// Set all major supported currencies from the live-common setup
(0, index_1.setSupportedCurrencies)([
"bitcoin",
"ethereum",
"bsc",
"polygon",
"arbitrum",
"optimism",
"avalanche_c_chain",
"solana",
"cardano",
"polkadot",
"cosmos",
"tron",
"stellar",
"hedera",
"near",
"sui",
]);
const allSupportedCurrencies = (0, currencies_1.listSupportedCurrencies)();
const allSupportedTokens = listSupportedTokens();
// Test the full loadCurrenciesByProvider functionality
const result = await (0, helper_1.loadCurrenciesByProvider)(allSupportedCurrencies.concat(allSupportedTokens));
// Comprehensive validation
expect(result).toBeDefined();
expect(result.currenciesByProvider).toBeDefined();
expect(result.sortedCryptoCurrencies).toBeDefined();
expect(Array.isArray(result.currenciesByProvider)).toBe(true);
expect(Array.isArray(result.sortedCryptoCurrencies)).toBe(true);
// Should have meaningful results with this many currencies
expect(result.currenciesByProvider.length).toBeGreaterThan(0);
expect(result.sortedCryptoCurrencies.length).toBeGreaterThan(0);
// Validate structure of each provider group
result.currenciesByProvider.forEach(providerGroup => {
expect(providerGroup.providerId).toBeDefined();
expect(typeof providerGroup.providerId).toBe("string");
expect(Array.isArray(providerGroup.currenciesByNetwork)).toBe(true);
expect(providerGroup.currenciesByNetwork.length).toBeGreaterThan(0);
// Each currency in the group should be valid
providerGroup.currenciesByNetwork.forEach(currency => {
expect(currency.id).toBeDefined();
expect(currency.type).toMatch(/^(CryptoCurrency|TokenCurrency)$/);
});
});
// Validate sortedCryptoCurrencies
result.sortedCryptoCurrencies.forEach(currency => {
expect(currency.id).toBeDefined();
expect(currency.type).toMatch(/^(CryptoCurrency|TokenCurrency)$/);
});
// Should not have duplicates in sortedCryptoCurrencies
const sortedIds = result.sortedCryptoCurrencies.map(c => c.id);
const uniqueIds = new Set(sortedIds);
expect(sortedIds.length).toBe(uniqueIds.size);
});
it("should efficiently handle the intersection of all mock assets with all supported currencies", () => {
(0, index_1.setSupportedCurrencies)([
"bitcoin",
"ethereum",
"bsc",
"polygon",
"arbitrum",
"optimism",
"avalanche_c_chain",
"solana",
"cardano",
"polkadot",
"cosmos",
"tron",
"stellar",
"hedera",
"near",
"sui",
"litecoin",
"dogecoin",
]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const allMockAssets = [
...TOKEN_ONLY_ASSETS,
...mock_1.MOCK_WITH_TOKEN_AND_CURRENCY_ASSET,
...mock_1.MOCK_POL,
];
const startTime = Date.now();
const { currenciesByProvider, sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)(allMockAssets, currencies);
const endTime = Date.now();
expect(endTime - startTime).toBeLessThan(100);
expect(Array.isArray(currenciesByProvider)).toBe(true);
expect(Array.isArray(sortedCryptoCurrencies)).toBe(true);
if (currenciesByProvider.length > 0) {
currenciesByProvider.forEach(provider => {
expect(provider.providerId).toBeDefined();
expect(provider.currenciesByNetwork.length).toBeGreaterThan(0);
});
}
if (sortedCryptoCurrencies.length > 0) {
sortedCryptoCurrencies.forEach(currency => {
expect(currency.type).toMatch(/^(CryptoCurrency|TokenCurrency)$/);
});
}
});
it("should demonstrate provider grouping behavior with diverse mock data", () => {
(0, index_1.setSupportedCurrencies)(["ethereum", "polygon", "arbitrum", "optimism"]);
const currencies = (0, index_1.sortCurrenciesByIds)((0, currencies_1.listSupportedCurrencies)().concat(listSupportedTokens()), mock_1.MOCK_IDS);
const { currenciesByProvider, sortedCryptoCurrencies } = (0, helper_1.groupCurrenciesByProvider)([...TOKEN_ONLY_ASSETS, ...mock_1.MOCK_WITH_TOKEN_AND_CURRENCY_ASSET, ...mock_1.MOCK_POL], currencies);
const providerIds = new Set(currenciesByProvider.map(p => p.providerId));
const expectedProviders = ["tether", "ethereum", "matic-network"];
expectedProviders.forEach(expectedProvider => {
if (currenciesByProvider.some(p => p.providerId === expectedProvider)) {
expect(providerIds.has(expectedProvider)).toBe(true);
}
});
currenciesByProvider.forEach(provider => {
expect(provider.currenciesByNetwork.length).toBeGreaterThan(0);
provider.currenciesByNetwork.forEach(currency => {
expect(currency.id).toBeDefined();
expect(["CryptoCurrency", "TokenCurrency"].includes(currency.type)).toBe(true);
});
});
expect(sortedCryptoCurrencies.length).toBeLessThanOrEqual(providerIds.size);
});
});
describe("Error handling", () => {
test("should handle malformed asset data by throwing error", () => {
const malformedAssets = [
{ ...TOKEN_ONLY_ASSETS[0], ledgerId: undefined },
{ ...TOKEN_ONLY_ASSETS[0], providerId: null },
];
const token = (0, index_1.findTokenById)(TOKEN_ONLY_ASSETS[0].ledgerId);
if (!token)
throw new Error("Token not found");
const currencies = [token];
expect(() => {
(0, helper_1.groupCurrenciesByProvider)(malformedAssets, currencies);
}).toThrow();
});
test("should handle assets with null/undefined fields gracefully where possible", () => {
const partiallyMalformedAssets = [
{ ...TOKEN_ONLY_ASSETS[0], providerId: "" },
];
const token = (0, index_1.findTokenById)(TOKEN_ONLY_ASSETS[0].ledgerId);
if (!token)
throw new Error("Token not found");
const currencies = [token];
expect(() => {
(0, helper_1.groupCurrenciesByProvider)(partiallyMalformedAssets, currencies);
}).not.toThrow();
});
test("should handle very large datasets efficiently", () => {
const largeAssetList = Array(10000)
.fill(TOKEN_ONLY_ASSETS[0])
.map((asset, index) => ({
...asset,
ledgerId: `${asset.ledgerId}_${index}`,
providerId: `provider_${index % 10}`,
}));
const token = (0, index_1.findTokenById)(TOKEN_ONLY_ASSETS[0].ledgerId);
if (!token)
throw new Error("Token not found");
const currencies = [token];
const startTime = Date.now();
const result = (0, helper_1.groupCurrenciesByProvider)(largeAssetList, currencies);
const endTime = Date.now();
expect(endTime - startTime).toBeLessThan(1000);
expect(result.currenciesByProvider).toBeDefined();
expect(result.sortedCryptoCurrencies).toBeDefined();
});
test("should handle case sensitivity in ledger IDs correctly", () => {
const mixedCaseAssets = [
{ ...TOKEN_ONLY_ASSETS[0], ledgerId: TOKEN_ONLY_ASSETS[0].ledgerId.toUpperCase() },
];
const token = (0, index_1.findTokenById)(TOKEN_ONLY_ASSETS[0].ledgerId);
if (!token)
throw new Error("Token not found");
const currencies = [token];
const { currenciesByProvider } = (0, helper_1.groupCurrenciesByProvider)(mixedCaseAssets, currencies);
expect(currenciesByProvider).toHaveLength(1);
});
});
});
//# sourceMappingURL=deposit.test.js.map