UNPKG

@xlink-network/xlink-sdk

Version:
207 lines (191 loc) 6.26 kB
import { getStacksToken } from "../stacksUtils/xlinkContractHelpers" import { requestAPI } from "../utils/apiHelpers" import { BigNumber } from "../utils/BigNumber" import { isNotNull } from "../utils/typeHelpers" import { createBRC20Token, createRunesToken, KnownChainId, KnownTokenId, } from "../utils/types/knownIds" import { SDKGlobalContext } from "../xlinkSdkUtils/types.internal" export interface BRC20SupportedRoute { brc20Tick: string brc20Token: KnownTokenId.BRC20Token stacksToken: KnownTokenId.StacksToken pegInPaused: boolean pegInFeeRate: BigNumber pegInFeeBitcoinAmount: null | BigNumber pegOutPaused: boolean pegOutFeeRate: BigNumber pegOutFeeBitcoinAmount: null | BigNumber } export async function getBRC20SupportedRoutes( sdkContext: SDKGlobalContext, chainId: KnownChainId.BRC20Chain, ): Promise<BRC20SupportedRoute[]> { if ( sdkContext.brc20.routesConfigCache != null && sdkContext.brc20.routesConfigCache.get(chainId) != null ) { return sdkContext.brc20.routesConfigCache.get(chainId)! } const promise = _getBRC20SupportedRoutes(sdkContext, chainId).catch(err => { const cachedPromise = sdkContext.brc20.routesConfigCache?.get(chainId) if (promise === cachedPromise) { sdkContext.brc20.routesConfigCache?.delete(chainId) } throw err }) sdkContext.brc20.routesConfigCache?.set(chainId, promise) return promise } async function _getBRC20SupportedRoutes( sdkContext: Pick<SDKGlobalContext, "backendAPI">, chainId: KnownChainId.BRC20Chain, ): Promise<BRC20SupportedRoute[]> { const stacksChainId = chainId === KnownChainId.BRC20.Mainnet ? KnownChainId.Stacks.Mainnet : KnownChainId.Stacks.Testnet const resp = await requestAPI<{ routes: SupportedBRC20BridgeRoute[] }>( sdkContext, { method: "GET", path: "/2024-10-01/brc20/supported-routes", query: { network: chainId === KnownChainId.BRC20.Mainnet ? "mainnet" : "testnet", }, }, ) const routes = await Promise.all( resp.routes.map(async (route): Promise<null | BRC20SupportedRoute> => { const stacksToken = await getStacksToken( stacksChainId, route.stacksTokenContractAddress, ) if (stacksToken == null) return null return { brc20Tick: route.brc20Tick, brc20Token: createBRC20Token(route.brc20Tick), stacksToken, pegInPaused: route.pegInPaused, pegInFeeRate: BigNumber.from(route.pegInFeeRate), pegInFeeBitcoinAmount: route.pegInFeeBitcoinAmount == null ? null : BigNumber.from(route.pegInFeeBitcoinAmount), pegOutPaused: route.pegOutPaused, pegOutFeeRate: BigNumber.from(route.pegOutFeeRate), pegOutFeeBitcoinAmount: route.pegOutFeeBitcoinAmount == null ? null : BigNumber.from(route.pegOutFeeBitcoinAmount), } }), ) return routes.filter(isNotNull) } interface SupportedBRC20BridgeRoute { brc20Tick: string stacksTokenContractAddress: { deployerAddress: string contractName: string } pegInPaused: boolean pegInFeeRate: `${number}` pegInFeeBitcoinAmount: null | `${number}` pegOutPaused: boolean pegOutFeeRate: `${number}` pegOutFeeBitcoinAmount: null | `${number}` } export interface RunesSupportedRoute { runesId: `${number}:${number}` runesToken: KnownTokenId.RunesToken stacksToken: KnownTokenId.StacksToken pegInPaused: boolean pegInFeeRate: BigNumber pegInFeeBitcoinAmount: null | BigNumber pegOutPaused: boolean pegOutFeeRate: BigNumber pegOutFeeBitcoinAmount: null | BigNumber } export async function getRunesSupportedRoutes( sdkContext: SDKGlobalContext, chainId: KnownChainId.RunesChain, ): Promise<RunesSupportedRoute[]> { if ( sdkContext.runes.routesConfigCache != null && sdkContext.runes.routesConfigCache.get(chainId) != null ) { return sdkContext.runes.routesConfigCache.get(chainId)! } const promise = _getRunesSupportedRoutes(sdkContext, chainId).catch(err => { const cachedPromise = sdkContext.runes.routesConfigCache?.get(chainId) if (promise === cachedPromise) { sdkContext.runes.routesConfigCache?.delete(chainId) } throw err }) sdkContext.runes.routesConfigCache?.set(chainId, promise) return promise } async function _getRunesSupportedRoutes( sdkContext: Pick<SDKGlobalContext, "backendAPI">, chainId: KnownChainId.RunesChain, ): Promise<RunesSupportedRoute[]> { const stacksChainId = chainId === KnownChainId.Runes.Mainnet ? KnownChainId.Stacks.Mainnet : KnownChainId.Stacks.Testnet const resp = await requestAPI<{ routes: SupportedRunesBridgeRoute[] }>( sdkContext, { method: "GET", path: "/2024-10-01/runes/supported-routes", query: { network: chainId === KnownChainId.Runes.Mainnet ? "mainnet" : "testnet", }, }, ) const routes = await Promise.all( resp.routes.map(async (route): Promise<null | RunesSupportedRoute> => { const stacksToken = await getStacksToken( stacksChainId, route.stacksTokenContractAddress, ) if (stacksToken == null) return null return { runesId: route.runesId, runesToken: createRunesToken(route.runesId), stacksToken, pegInPaused: route.pegInPaused, pegInFeeRate: BigNumber.from(route.pegInFeeRate), pegInFeeBitcoinAmount: route.pegInFeeBitcoinAmount == null ? null : BigNumber.from(route.pegInFeeBitcoinAmount), pegOutPaused: route.pegOutPaused, pegOutFeeRate: BigNumber.from(route.pegOutFeeRate), pegOutFeeBitcoinAmount: route.pegOutFeeBitcoinAmount == null ? null : BigNumber.from(route.pegOutFeeBitcoinAmount), } }), ) return routes.filter(isNotNull) } interface SupportedRunesBridgeRoute { runesId: `${number}:${number}` stacksTokenContractAddress: { deployerAddress: string contractName: string } pegInPaused: boolean pegInFeeRate: `${number}` pegInFeeBitcoinAmount: null | `${number}` pegOutPaused: boolean pegOutFeeRate: `${number}` pegOutFeeBitcoinAmount: null | `${number}` }