import { getEnv } from "@ledgerhq/live-env"; import { getTestProviderInfo, type ExchangeProviderNameAndSignature } from "."; import calService, { SWAP_DATA_CDN } from "@ledgerhq/ledger-cal-service"; import { isIntegrationTestEnv } from "../swap/utils/isIntegrationTestEnv"; export type SwapProviderConfig = { needsKYC: boolean; needsBearerToken?: boolean; }; export type CEXProviderConfig = ExchangeProviderNameAndSignature & SwapProviderConfig & { type: "CEX" }; export type DEXProviderConfig = SwapProviderConfig & { type: "DEX" }; export type AdditionalProviderConfig = SwapProviderConfig & { type: "DEX" | "CEX" } & { version?: number; termsOfUseUrl: string; supportUrl: string; usefulUrls?: string[]; mainUrl: string; useInExchangeApp: boolean; displayName: string; }; export type ProviderConfig = CEXProviderConfig | DEXProviderConfig; const DEFAULT_SWAP_PROVIDERS: Record> = { changelly: { name: "Changelly", publicKey: { curve: "secp256k1", data: Buffer.from( "0480d7c0d3a9183597395f58dda05999328da6f18fabd5cda0aff8e8e3fc633436a2dbf48ecb23d40df7c3c7d3e774b77b4b5df0e9f7e08cf1cdf2dba788eb085b", "hex", ), }, signature: Buffer.from( "3045022100e73339e5071b5d232e8cacecbd7c118c919122a43f8abb8b2062d4bfcd58274e022050b11605d8b7e199f791266146227c43fd11d7645b1d881f705a2f8841d21de5", "hex", ), needsKYC: false, needsBearerToken: false, type: "CEX", usefulUrls: [ "https://changelly.com/terms-of-use", "https://changelly.com/aml-kyc", "https://support.changelly.com/en/support/tickets/new", ], termsOfUseUrl: "https://changelly.com/terms-of-use", supportUrl: "https://support.changelly.com/en/support/home", mainUrl: "https://changelly.com/", }, changelly_v2: { name: "Changelly", publicKey: { curve: "secp256k1", data: Buffer.from( "0480d7c0d3a9183597395f58dda05999328da6f18fabd5cda0aff8e8e3fc633436a2dbf48ecb23d40df7c3c7d3e774b77b4b5df0e9f7e08cf1cdf2dba788eb085b", "hex", ), }, signature: Buffer.from( "3045022100c2db00da651cfcc84702f75ab5f131a3f037592080ea750a6f665a8cb36797c802200e594938cdf2c836b34717f57487002a0588f2088f64f00a6c4d320fd37db6fa", "hex", ), needsKYC: false, needsBearerToken: false, type: "CEX", usefulUrls: [ "https://changelly.com/terms-of-use", "https://changelly.com/aml-kyc", "https://support.changelly.com/en/support/tickets/new", ], termsOfUseUrl: "https://changelly.com/terms-of-use", supportUrl: "https://support.changelly.com/en/support/home", mainUrl: "https://changelly.com/", version: 2, }, exodus: { name: "exodus", publicKey: { curve: "secp256k1", data: Buffer.from( "048abacf1b1027b7c5f96d77826eada263e21d2ba8a2a037a84e0679e05d997a91ff34df181f88bdaf3521c26fb70eb028622f3afd66d0c282d5bb61da38ad76c1", "hex", ), }, signature: Buffer.from( "30450221009278b9a6d7b69e56a7f58004072bd4ec741f4c6134ac0a0b83d42e8d246159760220317b334a465d9b056e9da5bfbccbac31d36c0b564b06c60e28d6e8b010782c3e", "hex", ), needsKYC: false, needsBearerToken: false, type: "CEX", termsOfUseUrl: "https://www.exodus.com/legal/exodus-tos-20240219-v29.pdf", supportUrl: "https://www.exodus.com/contact-support/", mainUrl: "https://www.exodus.com/", }, cic: { name: "CIC", publicKey: { curve: "secp256k1", data: Buffer.from( "0444a71652995d15ef0d4d6fe8de21a0c8ad48bdbfea7f789319973669785ca96abca9fd0c504c3074d9b654f0e3a76dde642a03efe4ccdee3af3ca4ba4afa202d", "hex", ), }, signature: Buffer.from( "3044022078a73433ab6289027b7a169a260f180d16346f7ab55b06a22109f68a756d691d0220190edd6e1214c3309dc1b0afe90d217b728377491561383f2ee543e2c90188eb", "hex", ), needsKYC: false, needsBearerToken: false, type: "CEX", termsOfUseUrl: "https://criptointercambio.com/terms-of-use", supportUrl: "https://criptointercambio.com/en/about", mainUrl: "https://criptointercambio.com/", }, cic_v2: { name: "CIC", publicKey: { curve: "secp256k1", data: Buffer.from( "0444a71652995d15ef0d4d6fe8de21a0c8ad48bdbfea7f789319973669785ca96abca9fd0c504c3074d9b654f0e3a76dde642a03efe4ccdee3af3ca4ba4afa202d", "hex", ), }, signature: Buffer.from( "3044022078a73433ab6289027b7a169a260f180d16346f7ab55b06a22109f68a756d691d0220190edd6e1214c3309dc1b0afe90d217b728377491561383f2ee543e2c90188eb", "hex", ), needsKYC: false, needsBearerToken: false, type: "CEX", termsOfUseUrl: "https://criptointercambio.com/terms-of-use", supportUrl: "https://criptointercambio.com/en/about", mainUrl: "https://criptointercambio.com/", }, moonpay: { name: "moonpay", publicKey: { curve: "secp256k1", data: Buffer.from( "044989cad389020fadfb9d7a85d29338a450beec571347d2989fb57b99ecddbc8907cf8c229deee30fb8ac139e978cab8f6efad76bde2a9c6d6710ceda1fe0a4d8", "hex", ), }, signature: Buffer.from( "304402202ea20dd1a67185a14503f073a387ec22564cc06bbb2545444efc929d69c70d1002201622ac8e34a7f332ac50d67c1d9221dcc3334ad7c1fb84e674654cd306bbda73", "hex", ), needsKYC: true, needsBearerToken: false, type: "CEX", version: 2, termsOfUseUrl: "https://www.moonpay.com/legal/terms_of_use_row", supportUrl: "https://support.moonpay.com/", mainUrl: "https://www.moonpay.com/", }, oneinch: { type: "DEX", needsKYC: false, needsBearerToken: false, termsOfUseUrl: "https://1inch.com/assets/Widget_1inch.com_Terms_of_Use.pdf", supportUrl: "https://help.1inch.com/en/", mainUrl: "https://1inch.com/", }, paraswap: { type: "DEX", needsKYC: false, needsBearerToken: false, termsOfUseUrl: "https://files.paraswap.io/tos_v4.pdf", supportUrl: "https://help.paraswap.io/en/", mainUrl: "https://www.paraswap.io/", }, thorswap: { type: "CEX", name: "thorswap", needsBearerToken: false, termsOfUseUrl: "https://docs.thorswap.finance/thorswap/resources/terms-of-service", supportUrl: "mailto:support@thorswap.finance", mainUrl: "https://www.thorswap.finance/", needsKYC: false, version: 2, publicKey: { curve: "secp256r1", data: Buffer.from( "0480a453a91e728c5f622d966b90d15de6fdb6c267bb8147dd0e0d4e1c730d631594e724aaf2b2f526600f3713ce6bc2adbfdbaafd2121bfee64fce93fd59a9050", "hex", ), }, signature: Buffer.from( "304402207a9676f6971575cad70e4ef4d937ebdba82c51e6a0ab5343c11fefa18dff326d0220643f0718da68ead3fd9900eb90bca782d533d1698c8ea1435ae232ddf2e94229", "hex", ), }, nearintents: { type: "CEX", name: "NEAR Intents", needsBearerToken: false, termsOfUseUrl: "https://swapkit.dev/terms-of-service/", supportUrl: "https://ledgerhelp.swapkit.dev/", mainUrl: "https://www.near.org/intents", needsKYC: false, version: 2, publicKey: { curve: "secp256r1", data: Buffer.from( "0480a453a91e728c5f622d966b90d15de6fdb6c267bb8147dd0e0d4e1c730d631594e724aaf2b2f526600f3713ce6bc2adbfdbaafd2121bfee64fce93fd59a9050", "hex", ), }, signature: Buffer.from( "30440220331fca95bc6b8cf2264d72a0da9d791888c4ead9ed02bee4f6525f7e512911ca02204a78d416baa7b3fc8d6a82abbadda2e096abcbfa9a57769a8a20260d3e553b7d", "hex", ), }, swapsxyz: { type: "CEX", name: "Swaps.xyz", needsBearerToken: false, termsOfUseUrl: "https://docs.swaps.xyz/resources/terms-of-service", supportUrl: "https://scan.swaps.xyz/", mainUrl: "https://swaps.xyz/", needsKYC: false, version: 2, publicKey: { curve: "secp256k1", data: Buffer.from( "04e6f96d95d770cab9cc1c45037fe6be92675ed6f2eba405c984b61043a76f0cebdf1ad46fcf2cdcc624a018b6287d6db72138cded3bd0f190eb799d7b071e21c9", "hex", ), }, signature: Buffer.from( "3045022074a307a01df16c69c5d4497619d8d78ad872a0e53b28871b17f1843f47d98ca9022100c2c2c96d0ad81aa0127f85805e783aa8ebd3546ceba3815adf613d3a5057903d", "hex", ), }, lifi: { type: "CEX", name: "lifi", needsBearerToken: false, termsOfUseUrl: "https://li.fi/legal/terms-and-conditions/", supportUrl: "https://discord.gg/jumperexchange", mainUrl: "https://li.fi/", needsKYC: false, version: 2, publicKey: { curve: "secp256k1", data: Buffer.from( "04e5f4fa0f28dec3b1f52934f29bd91ab862b003a531d67ba3864e3ba4303be8e815a619ee6f78e8079acf46f0d0d8fc664be2f343d1c9a20c4d2420f51a56ccea", "hex", ), }, signature: Buffer.from( "3044022041344dba7353fe94a4d24a20285b5afaa8fa9a022a62e1042d059b0f1d37cbc302200a3ed5d661df0c44d78c439939c4c49868936c7357da3807a19104bcfb323d24", "hex", ), }, velora: { type: "DEX", needsKYC: false, needsBearerToken: false, termsOfUseUrl: "https://files.paraswap.io/tos_v4.pdf", supportUrl: "https://help.paraswap.io/en/", mainUrl: "https://www.velora.xyz/", }, okx: { type: "DEX", displayName: "OKX", needsBearerToken: false, termsOfUseUrl: "https://web3.okx.com/help/okx-web3-build-user-agreement", supportUrl: "https://web3.okx.com/build/dev-docs/wallet-api/support", mainUrl: "https://web3.okx.com/", needsKYC: false, }, }; export const dexProvidersContractAddress: { [key: string]: string } = { "0x3fc91a3afd70395cd496c647d5a6cc9d4b2b7fad": "Uniswap", "0x111111125421ca6dc452d289314280a0f8842a65": "1inch", "0x6a000f20005980200259b80c5102003040001068": "velora", }; export const termsOfUse: { [key: string]: string } = { paraswap: "https://paraswap.io/tos", "1inch": "https://1inch.com/assets/Widget_1inch.com_Terms_of_Use.pdf", Uniswap: "https://uniswap.org/terms-of-service", velora: "https://www.velora.xyz/terms/terms-of-use", okx: "https://web3.okx.com/help/okx-web3-build-user-agreement", }; export const privacyPolicy: { [key: string]: string } = { Uniswap: "https://uniswap.org/privacy-policy", }; type CurrencyData = { id: string; config: string; signature: string; }; let providerDataCache: Record | null = null; export const getSwapProvider = async ( providerName: string, ): Promise => { const testProviderInfo = getTestProviderInfo(); const ledgerSignatureEnv = getEnv("MOCK_EXCHANGE_TEST_CONFIG") ? "test" : "prod"; const partnerSignatureEnv = getEnv("MOCK_EXCHANGE_TEST_PARTNER") ? "test" : "prod"; if (ledgerSignatureEnv === "test" && testProviderInfo) { return { needsKYC: false, useInExchangeApp: true, needsBearerToken: false, type: "CEX", termsOfUseUrl: "https://example.com", supportUrl: "https://example.com", mainUrl: "https://example.com", displayName: providerName, ...testProviderInfo, }; } const res = await fetchAndMergeProviderData({ ledgerSignatureEnv, partnerSignatureEnv }); if (!res[providerName.toLowerCase()]) { throw new Error(`Unknown partner ${providerName}`); } return res[providerName.toLowerCase()]; }; /** * Retrieves the currency data for a given ID * @param currencyId The unique identifier for the currency. * @returns A promise that resolves to the currency data including ID, serialized config, and signature. * @deprecated Use cal module `findCurrencyData` method. */ export const findExchangeCurrencyData = async (currencyId: string): Promise => calService.findCurrencyData(currencyId); export const fetchAndMergeProviderData = async env => { if (providerDataCache) { return providerDataCache; } try { const [providersData, providersExtraData] = await Promise.all([ calService.getProvidersData({ type: "swap", ...env }), calService.getProvidersCDNData(), ]); const finalProvidersData = mergeProviderData(providersData, providersExtraData); providerDataCache = finalProvidersData; return finalProvidersData; } catch (error) { console.error("Error fetching or processing provider data:", error); const finalProvidersData = mergeProviderData(DEFAULT_SWAP_PROVIDERS, SWAP_DATA_CDN); return finalProvidersData; } }; function mergeProviderData(baseData, additionalData) { const mergedData = { ...baseData }; Object.keys(additionalData).forEach(key => { mergedData[key] = { ...mergedData[key], ...additionalData[key], }; }); return mergedData; } export const getAvailableProviders = async (): Promise => { const ledgerSignatureEnv = getEnv("MOCK_EXCHANGE_TEST_CONFIG") ? "test" : "prod"; const partnerSignatureEnv = getEnv("MOCK_EXCHANGE_TEST_PARTNER") ? "test" : "prod"; if (isIntegrationTestEnv()) { return Object.keys(DEFAULT_SWAP_PROVIDERS).filter(p => p !== "changelly"); } return Object.keys(await fetchAndMergeProviderData({ ledgerSignatureEnv, partnerSignatureEnv })); }; export const getDefaultSwapProviderKeys = (): string[] => { return Object.keys(DEFAULT_SWAP_PROVIDERS); };