import { Address, address } from '@solana/kit'; export const SLOTS_PER_MINUTE = (60 * 1000) / 400; export const DEFAULT_TIMEOUT_MS = 700; // Single source of truth for all supported router types export const SUPPORTED_ROUTER_TYPES = [ 'okx', 'jupiter', 'per', 'dflow', 'fluxbeam', 'raydium', 'autobahn', // Deprecated 'jupiterU', 'jupiterZ', 'hashflow', 'kinetic', 'jupiterLite', // deprecated - kept for backward compatibility, returns no results 'jupiterSelfHosted', 'jupiterEuropa', // Deprecated 'metis', 'clover', 'openOcean', 'spur', 'zeroEx', // "0x", but prefer all letters because identifiers cannot start with a number and "0x" is also prefix for hex numbers 'lifi', 'titan', 'kobayashi', ] as const; /** * Non-composable routers do not allow ixs to be added to the transaction * Typically the response will only contain a transaction, not an ixsRouter field, or the ixsRouter field contains only supplemental ixs */ export const NON_COMPOSABLE_ROUTERS: RouterType[] = [ 'per', // no ixsRouter field, only a transaction 'hashflow', // ixsRouter field only contains supplemental ixs ]; /** * Routers that support the `preferredMaxAccounts` parameter * These routers can optimize for fewer accounts when requested */ export const PREFERRED_MAX_ACCOUNT_SUPPORTED_ROUTERS: RouterType[] = [ 'autobahn', 'jupiter', 'jupiterEuropa', 'jupiterSelfHosted', 'metis', 'titan', 'kobayashi', 'zeroEx', ]; export const CLOVER_DEX_TYPES = ['limo', 'exponent', 'hastra'] as const; export type CloverDexType = (typeof CLOVER_DEX_TYPES)[number]; export const RFQ_ROUTERS: RouterType[] = ['per', 'hashflow', 'jupiterZ']; export const EXCLUDED_QUOTES_ROUTERS = ['fluxbeam']; // bogdan: do we need incremental IDs? Using the public keys seems simpler and more consistent export const ROUTER_TYPE_IDS = { okx: 1, jupiter: 2, per: 3, dflow: 4, fluxbeam: 5, raydium: 6, autobahn: 7, jupiterU: 8, jupiterZ: 9, hashflow: 10, jupiterLite: 11, jupiterSelfHosted: 12, clover: 13, openOcean: 14, spur: 15, zeroEx: 16, lifi: 17, jupiterEuropa: 18, metis: 19, kinetic: 20, titan: 21, kobayashi: 22, } as const; // Type that represents the router ID values export type RouterTypeID = (typeof ROUTER_TYPE_IDS)[RouterType]; // Utility functions to convert between types and IDs export function getRouterTypeID(routerType: RouterType): RouterTypeID { return ROUTER_TYPE_IDS[routerType]; } export function getAllRouterTypeIDsMap() { const mapping = ROUTER_TYPE_IDS; return { mapping }; } // Define RouterType directly from the constant export type RouterType = (typeof SUPPORTED_ROUTER_TYPES)[number]; // Helper function to check if a string is a valid router type export function isValidRouterType(type: string): type is RouterType { return SUPPORTED_ROUTER_TYPES.includes(type as RouterType); } export const JUP_ULTRA_BASE_URL = 'https://lite-api.jup.ag/ultra/v1'; export const JUPITER_PRICE_API = 'https://lite-api.jup.ag/price/v3'; export const JUP_V6_BASE_URL = 'https://lite-api.jup.ag/swap/v1/'; // Map of router program IDs - make sure this contains entries for all SUPPORTED_ROUTER_TYPES const ROUTER_PROGRAM_IDS = { okx: address('proVF4pMXVaYqmy4NjniPh4pqKNfMmsihgd4wdkCX3u'), jupiter: address('JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'), per: address('PytERJFhAKuNNuaiXkApLfWzwNwSNDACpigT3LwQfou'), dflow: address('DF1ow4tspfHX9JwWJsAb9epbkA8hmpSEAtxXy1V27QBH'), fluxbeam: address('FLUXubRmkEi2q6K3Y9kBPg9248ggaZVsoSFhtJHSrm1X'), raydium: address('routeUGWgWzqBWFcrCfv8tritsqukccJPu3q5GPP3xS'), autobahn: address('AutobNFLMzX1rFCDgwWpwr3ztG5c1oDbSrGq7Jj2LgE'), jupiterU: address('JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'), jupiterZ: address('61DFfeTKM7trxYcPQCM78bJ794ddZprZpAwAnLiwTpYH'), metis: address('JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'), hashflow: address('CRhtqXk98ATqo1R8gLg7qcpEMuvoPzqD5GNicPPqLMD'), jupiterLite: address('JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'), jupiterSelfHosted: address('JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'), jupiterEuropa: address('JUP6LkbZbjS1jKKwapdHNy74zcZ3tLUZoi5QNyVTaV4'), clover: address('11111111111111111111111111111111'), // This won't have a single program ID for the swaps, we can't really use this within limo logs openOcean: address('DF6c7dTBdZ9cb59pywKAVwy5NMSXiSfmXzYNwYFPNz9F'), spur: address('SPURp82qAR9nvzy8j1gP31zmzGytrgDBKcpGzeGkka8'), zeroEx: address('Sett1erwx2eqT5A8uvu8GBxDFT2W5TNnhirL7hLmb8m'), lifi: address('3i5JeuZuUxeKtVysUnwQNGerJP2bSMX9fTFfS4Nxe3Br'), titan: address('T1TANpTeScyeqVzzgNViGDNrkQ6qHz9KrSBS4aNXvGT'), kinetic: address('KiNetiCAToLExLv5w7PrfiiKK1iYHNjrUM3RAF2V3A4'), kobayashi: address('kobaA5FRmWnT8w6dDkduJQKYWHdGGMx4rNzz2eXGKRt'), }; // When adding a new router type: // 1. Add it to SUPPORTED_ROUTER_TYPES in consts.ts (SDK and API) // 2. Add the program ID here in ROUTER_PROGRAM_IDS // Dynamically create the map using SUPPORTED_ROUTER_TYPES to ensure all are present export const ROUTER_PROGRAM_MAP = Object.fromEntries( SUPPORTED_ROUTER_TYPES.map((router) => [router, ROUTER_PROGRAM_IDS[router]]), ) as Record; export const TRITON_VOTE_ACCOUNT = address('9GJmEHGom9eWo4np4L5vC6b6ri1Df2xN8KFoWixvD1Bs');