@xlink-network/xlink-sdk
Version:
207 lines (191 loc) • 6.26 kB
text/typescript
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}`
}