From 70b1e97ba022e68d4778224fd97a1f111646149b Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Tue, 16 Dec 2025 13:21:10 +0100 Subject: [PATCH 1/2] feat: Enable USDT to USDT-SPOT indirect token pair and update related tests and chain data imports. --- api/_dexes/utils-b2bi.ts | 20 ++--- api/swap/tokens/_service.ts | 9 +-- test/api/_dexes/utils-b2bi.test.ts | 126 ++++++++++++++--------------- 3 files changed, 68 insertions(+), 87 deletions(-) diff --git a/api/_dexes/utils-b2bi.ts b/api/_dexes/utils-b2bi.ts index 8d4e63884..554d5b7eb 100644 --- a/api/_dexes/utils-b2bi.ts +++ b/api/_dexes/utils-b2bi.ts @@ -18,29 +18,19 @@ import { buildMulticallHandlerMessage, } from "../_multicall-handler"; -import indirectChainsImport from "../../src/data/indirect_chains_1.json"; -import mainnetChains from "../../src/data/chains_1.json"; +import indirectChains from "../../src/data/indirect_chains_1.json"; import { CrossSwap, IndirectDestinationRoute } from "./types"; const ENABLED_INDIRECT_TOKEN_PAIRS: { inputToken: string; outputToken: string; }[] = [ - // TODO: Enable this once we replace MulticallHandler on HyperEVM with HyperliquidDepositHandler - // { - // inputToken: "USDT", - // outputToken: "USDT-SPOT", - // }, + { + inputToken: "USDT", + outputToken: "USDT-SPOT", + }, ]; -// Type cast to avoid TypeScript inferring never[] when indirect_chains_1.json or any of its nested arrays are empty. -// Extends mainnetChains type with intermediaryChain property specific to indirect chains. -const indirectChains = indirectChainsImport as Array< - (typeof mainnetChains)[number] & { - intermediaryChain: number; - } ->; - export function isIndirectDestinationRouteSupported(params: { originChainId: number; destinationChainId: number; diff --git a/api/swap/tokens/_service.ts b/api/swap/tokens/_service.ts index c5bbfffdd..a9912d832 100644 --- a/api/swap/tokens/_service.ts +++ b/api/swap/tokens/_service.ts @@ -1,7 +1,7 @@ import axios from "axios"; import { constants } from "ethers"; import mainnetChains from "../../../src/data/chains_1.json"; -import indirectChainsImport from "../../../src/data/indirect_chains_1.json"; +import indirectChains from "../../../src/data/indirect_chains_1.json"; import { CHAIN_IDs, TOKEN_SYMBOLS_MAP, @@ -13,13 +13,6 @@ import { getFallbackTokenLogoURI, } from "../../_utils"; -// Type cast to avoid TypeScript inferring never[] when indirect_chains_1.json is empty. -// Uses the same structure as mainnetChains since indirect chains share the same base schema. -const indirectChains = indirectChainsImport as Array< - (typeof mainnetChains)[number] & { - intermediaryChain: number; - } ->; export type SwapToken = { chainId: number; address: string; diff --git a/test/api/_dexes/utils-b2bi.test.ts b/test/api/_dexes/utils-b2bi.test.ts index 386b01e73..df5ed5abd 100644 --- a/test/api/_dexes/utils-b2bi.test.ts +++ b/test/api/_dexes/utils-b2bi.test.ts @@ -2,7 +2,7 @@ import { getIndirectDestinationRoute } from "../../../api/_dexes/utils-b2bi"; import { CHAIN_IDs, TOKEN_SYMBOLS_MAP } from "../../../api/_constants"; describe("_dexes/utils-b2bi", () => { - describe("#getIndirectDestinationRoutes()", () => { + describe("#getIndirectDestinationRoute()", () => { test("Optimism USDT -> Arbitrum USDT - should return empty array", () => { const params = { originChainId: CHAIN_IDs.OPTIMISM, @@ -14,70 +14,68 @@ describe("_dexes/utils-b2bi", () => { expect(indirectDestinationRoute).toEqual(undefined); }); - // TODO: Enable this test once USDT to HyperCore routes are enabled again. - // test("Optimism USDT -> HyperCore USDT - should return indirect destination routes", () => { - // const params = { - // originChainId: CHAIN_IDs.OPTIMISM, - // destinationChainId: CHAIN_IDs.HYPERCORE, - // inputToken: TOKEN_SYMBOLS_MAP.USDT.addresses[CHAIN_IDs.OPTIMISM], - // outputToken: - // TOKEN_SYMBOLS_MAP["USDT-SPOT"].addresses[CHAIN_IDs.HYPERCORE], - // }; - // const indirectDestinationRoutes = getIndirectDestinationRoutes(params); - // expect(indirectDestinationRoutes.length).toEqual(1); - // expect( - // indirectDestinationRoutes[0].intermediaryOutputToken.symbol - // ).toEqual("USDT"); - // expect( - // indirectDestinationRoutes[0].intermediaryOutputToken.chainId - // ).toEqual(CHAIN_IDs.HYPEREVM); - // expect( - // indirectDestinationRoutes[0].intermediaryOutputToken.decimals - // ).toEqual(6); - // expect(indirectDestinationRoutes[0].outputToken.symbol).toEqual( - // "USDT-SPOT" - // ); - // expect(indirectDestinationRoutes[0].outputToken.chainId).toEqual( - // CHAIN_IDs.HYPERCORE - // ); - // expect(indirectDestinationRoutes[0].outputToken.decimals).toEqual(8); - // }); + test("Optimism USDT -> HyperCore USDT - should return indirect destination routes", () => { + const params = { + originChainId: CHAIN_IDs.OPTIMISM, + destinationChainId: CHAIN_IDs.HYPERCORE, + inputToken: TOKEN_SYMBOLS_MAP.USDT.addresses[CHAIN_IDs.OPTIMISM], + outputToken: + TOKEN_SYMBOLS_MAP["USDT-SPOT"].addresses[CHAIN_IDs.HYPERCORE], + }; + const indirectDestinationRoute = getIndirectDestinationRoute(params); + expect(indirectDestinationRoute).not.toBeUndefined(); + if (!indirectDestinationRoute) { + throw new Error("indirectDestinationRoute is undefined"); + } + expect(indirectDestinationRoute.intermediaryOutputToken.symbol).toEqual( + "USDT" + ); + expect(indirectDestinationRoute.intermediaryOutputToken.chainId).toEqual( + CHAIN_IDs.HYPEREVM + ); + expect(indirectDestinationRoute.intermediaryOutputToken.decimals).toEqual( + 6 + ); + expect(indirectDestinationRoute.outputToken.symbol).toEqual("USDT-SPOT"); + expect(indirectDestinationRoute.outputToken.chainId).toEqual( + CHAIN_IDs.HYPERCORE + ); + expect(indirectDestinationRoute.outputToken.decimals).toEqual(8); + }); - // TODO: Enable this test once USDT to HyperCore routes are enabled again. - // test("BSC USDT -> HyperCore USDT - should return indirect destination routes", () => { - // const params = { - // originChainId: CHAIN_IDs.BSC, - // destinationChainId: CHAIN_IDs.HYPERCORE, - // inputToken: TOKEN_SYMBOLS_MAP["USDT-BNB"].addresses[CHAIN_IDs.BSC], - // outputToken: - // TOKEN_SYMBOLS_MAP["USDT-SPOT"].addresses[CHAIN_IDs.HYPERCORE], - // }; - // const indirectDestinationRoutes = getIndirectDestinationRoutes(params); - // expect(indirectDestinationRoutes.length).toEqual(1); - // expect(indirectDestinationRoutes[0].inputToken.symbol).toEqual( - // "USDT-BNB" - // ); - // expect(indirectDestinationRoutes[0].inputToken.chainId).toEqual( - // CHAIN_IDs.BSC - // ); - // expect(indirectDestinationRoutes[0].inputToken.decimals).toEqual(18); - // expect( - // indirectDestinationRoutes[0].intermediaryOutputToken.symbol - // ).toEqual("USDT"); - // expect( - // indirectDestinationRoutes[0].intermediaryOutputToken.chainId - // ).toEqual(CHAIN_IDs.HYPEREVM); - // expect( - // indirectDestinationRoutes[0].intermediaryOutputToken.decimals - // ).toEqual(6); - // expect(indirectDestinationRoutes[0].outputToken.symbol).toEqual( - // "USDT-SPOT" - // ); - // expect(indirectDestinationRoutes[0].outputToken.chainId).toEqual( - // CHAIN_IDs.HYPERCORE - // ); - // expect(indirectDestinationRoutes[0].outputToken.decimals).toEqual(8); - // }); + test("BSC USDT -> HyperCore USDT - should return indirect destination routes", () => { + const params = { + originChainId: CHAIN_IDs.BSC, + destinationChainId: CHAIN_IDs.HYPERCORE, + inputToken: TOKEN_SYMBOLS_MAP["USDT-BNB"].addresses[CHAIN_IDs.BSC], + outputToken: + TOKEN_SYMBOLS_MAP["USDT-SPOT"].addresses[CHAIN_IDs.HYPERCORE], + }; + const indirectDestinationRoute = getIndirectDestinationRoute(params); + expect(indirectDestinationRoute).not.toBeUndefined(); + if (!indirectDestinationRoute) { + throw new Error("indirectDestinationRoute is undefined"); + } + expect(indirectDestinationRoute.inputToken.symbol).toEqual("USDT-BNB"); + expect(indirectDestinationRoute.inputToken.chainId).toEqual( + CHAIN_IDs.BSC + ); + expect(indirectDestinationRoute.inputToken.decimals).toEqual(18); + expect(indirectDestinationRoute.intermediaryOutputToken.symbol).toEqual( + "USDT" + ); + expect(indirectDestinationRoute.intermediaryOutputToken.chainId).toEqual( + CHAIN_IDs.HYPEREVM + ); + expect(indirectDestinationRoute.intermediaryOutputToken.decimals).toEqual( + 6 + ); + expect(indirectDestinationRoute.outputToken.symbol).toEqual("USDT-SPOT"); + expect(indirectDestinationRoute.outputToken.chainId).toEqual( + CHAIN_IDs.HYPERCORE + ); + expect(indirectDestinationRoute.outputToken.decimals).toEqual(8); + }); test("HyperEVM USDT -> HyperCore USDT - should return indirect destination routes", () => { const params = { From 74876a0217a25c8cb98573cbfdb223682fe78a11 Mon Sep 17 00:00:00 2001 From: Nikolas Haimerl Date: Tue, 16 Dec 2025 16:57:20 +0100 Subject: [PATCH 2/2] add pairing --- api/_dexes/utils-b2bi.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/api/_dexes/utils-b2bi.ts b/api/_dexes/utils-b2bi.ts index 554d5b7eb..c985aa256 100644 --- a/api/_dexes/utils-b2bi.ts +++ b/api/_dexes/utils-b2bi.ts @@ -29,6 +29,10 @@ const ENABLED_INDIRECT_TOKEN_PAIRS: { inputToken: "USDT", outputToken: "USDT-SPOT", }, + { + inputToken: "USDT-BNB", + outputToken: "USDT-SPOT", + }, ]; export function isIndirectDestinationRouteSupported(params: {