UNPKG

@xlink-network/xlink-sdk

Version:
170 lines (157 loc) 5 kB
import { getBtc2StacksFeeInfo } from "../bitcoinUtils/peggingHelpers" import { getStacks2EvmFeeInfo } from "../evmUtils/peggingHelpers" import { BigNumber } from "../utils/BigNumber" import { KnownRoute, KnownRoute_FromBitcoin_ToEVM, KnownRoute_FromBitcoin_ToStacks, } from "../utils/buildSupportedRoutes" import { UnsupportedBridgeRouteError } from "../utils/errors" import { assertExclude, checkNever } from "../utils/typeHelpers" import { PublicTransferProphetAggregated, transformToPublicTransferProphet, transformToPublicTransferProphetAggregated, } from "../utils/types/TransferProphet" import { KnownChainId, KnownTokenId } from "../utils/types/knownIds" import { supportedRoutes } from "./bridgeFromBitcoin" import { ChainId, SDKNumber, TokenId } from "./types" import { SDKGlobalContext } from "./types.internal" export interface BridgeInfoFromBitcoinInput { fromChain: ChainId toChain: ChainId fromToken: TokenId toToken: TokenId amount: SDKNumber } export interface BridgeInfoFromBitcoinOutput extends PublicTransferProphetAggregated {} export const bridgeInfoFromBitcoin = async ( ctx: SDKGlobalContext, info: BridgeInfoFromBitcoinInput, ): Promise<BridgeInfoFromBitcoinOutput> => { const route = await supportedRoutes.checkRouteValid(ctx, info) if (KnownChainId.isBitcoinChain(route.fromChain)) { if (KnownChainId.isStacksChain(route.toChain)) { if ( KnownTokenId.isBitcoinToken(route.fromToken) && KnownTokenId.isStacksToken(route.toToken) ) { return bridgeInfoFromBitcoin_toStacks({ ...info, fromChain: route.fromChain, toChain: route.toChain, fromToken: route.fromToken, toToken: route.toToken, }) } } else if (KnownChainId.isEVMChain(route.toChain)) { if ( KnownTokenId.isBitcoinToken(route.fromToken) && KnownTokenId.isEVMToken(route.toToken) ) { return bridgeInfoFromBitcoin_toEVM({ ...info, fromChain: route.fromChain, toChain: route.toChain, fromToken: route.fromToken, toToken: route.toToken, }) } } else if ( KnownChainId.isBRC20Chain(route.toChain) || KnownChainId.isRunesChain(route.toChain) ) { assertExclude(route.toChain, assertExclude.i<KnownChainId.BRC20Chain>()) assertExclude(route.toChain, assertExclude.i<KnownChainId.RunesChain>()) // TODO: bitcoin to brc20/runes is not supported yet } else { assertExclude(route.toChain, assertExclude.i<KnownChainId.BitcoinChain>()) checkNever(route) } } else { assertExclude(route.fromChain, assertExclude.i<KnownChainId.StacksChain>()) assertExclude(route.fromChain, assertExclude.i<KnownChainId.EVMChain>()) checkNever(route) } throw new UnsupportedBridgeRouteError( info.fromChain, info.toChain, info.fromToken, info.toToken, ) } async function bridgeInfoFromBitcoin_toStacks( info: Omit< BridgeInfoFromBitcoinInput, "fromChain" | "toChain" | "fromToken" | "toToken" > & KnownRoute_FromBitcoin_ToStacks, ): Promise<BridgeInfoFromBitcoinOutput> { const step1 = await getBtc2StacksFeeInfo(info) if (step1 == null) { throw new UnsupportedBridgeRouteError( info.fromChain, info.toChain, info.fromToken, info.toToken, ) } return { ...transformToPublicTransferProphet(info, info.amount, step1), transferProphets: [], } } async function bridgeInfoFromBitcoin_toEVM( info: Omit< BridgeInfoFromBitcoinInput, "fromChain" | "toChain" | "fromToken" | "toToken" > & KnownRoute_FromBitcoin_ToEVM, ): Promise<BridgeInfoFromBitcoinOutput> { const transitStacksChainId = info.fromChain === KnownChainId.Bitcoin.Mainnet ? KnownChainId.Stacks.Mainnet : KnownChainId.Stacks.Testnet const step1Route: KnownRoute = { fromChain: info.fromChain, fromToken: KnownTokenId.Bitcoin.BTC, toChain: transitStacksChainId, toToken: KnownTokenId.Stacks.aBTC, } const step2Route: KnownRoute = { fromChain: transitStacksChainId, fromToken: KnownTokenId.Stacks.aBTC, toChain: info.toChain, toToken: info.toToken, } const [step1, step2] = await Promise.all([ getBtc2StacksFeeInfo(step1Route), getStacks2EvmFeeInfo(step2Route), ]) if (step1 == null || step2 == null) { throw new UnsupportedBridgeRouteError( info.fromChain, info.toChain, info.fromToken, info.toToken, ) } const step1TransferProphet = transformToPublicTransferProphet( step1Route, info.amount, step1, ) const step2TransferProphet = transformToPublicTransferProphet( step2Route, step1TransferProphet.toAmount, step2, ) return { ...transformToPublicTransferProphetAggregated( [step1TransferProphet, step2TransferProphet], [BigNumber.ONE], ), transferProphets: [step1TransferProphet, step2TransferProphet], } }