feat: update fee info reading logic

This commit is contained in:
c4605
2025-03-13 21:25:16 +01:00
parent a9cc85d816
commit c3aba43837
9 changed files with 372 additions and 154 deletions

View File

@@ -48,3 +48,9 @@ export const contractNameOverrides_testnet: Record<string, string> = {
// cross router
"cross-router-v2-03": "cross-router-v2-03-dk",
}
/**
* Currently, we use the swap contract to retrieve fee information for the basic peg-in process.
* This approach is temporary and will be reverted to the standard contract in the future.
*/
export const EVM_BARE_PEG_IN_USE_SWAP_CONTRACT = true

View File

@@ -1,5 +1,6 @@
import { unwrapResponse } from "clarity-codegen"
import { readContract } from "viem/actions"
import { EVM_BARE_PEG_IN_USE_SWAP_CONTRACT } from "../config"
import { getBRC20SupportedRoutes } from "../metaUtils/apiHelpers/getBRC20SupportedRoutes"
import { getRunesSupportedRoutes } from "../metaUtils/apiHelpers/getRunesSupportedRoutes"
import { contractAssignedChainIdFromKnownChain } from "../stacksUtils/crossContractDataMapping"
@@ -11,15 +12,22 @@ import {
numberFromStacksContractNumber,
} from "../stacksUtils/xlinkContractHelpers"
import { BigNumber } from "../utils/BigNumber"
import { getAndCheckTransitStacksTokens } from "../utils/SwapRouteHelpers"
import {
getAndCheckTransitStacksTokens,
getSpecialFeeDetailsForSwapRoute,
} from "../utils/SwapRouteHelpers"
import {
IsSupportedFn,
KnownRoute_FromEVM_ToStacks,
KnownRoute_FromStacks_ToEVM,
KnownRoute_ToStacks,
} from "../utils/buildSupportedRoutes"
import { props } from "../utils/promiseHelpers"
import { checkNever } from "../utils/typeHelpers"
import { TransferProphet } from "../utils/types/TransferProphet"
import {
TransferProphet,
TransferProphet_Fee_Fixed,
} from "../utils/types/TransferProphet"
import {
_allNoLongerSupportedEVMChains,
KnownChainId,
@@ -60,14 +68,15 @@ const _getEvm2StacksFeeInfo = async (
ctx: SDKGlobalContext,
route: KnownRoute_FromEVM_ToStacks,
): Promise<undefined | TransferProphet> => {
const stacksContractCallInfo = getStacksContractCallInfo(
route.toChain,
StacksContractName.EVMPegInEndpoint,
)
const stacksSwapContractCallInfo = getStacksContractCallInfo(
route.toChain,
StacksContractName.EVMPegInEndpointSwap,
)
const stacksContractCallInfo = EVM_BARE_PEG_IN_USE_SWAP_CONTRACT
? getStacksContractCallInfo(
route.toChain,
StacksContractName.EVMPegInEndpointSwap,
)
: getStacksContractCallInfo(
route.toChain,
StacksContractName.EVMPegInEndpoint,
)
const evmContractCallInfo = await getEVMContractCallInfo(ctx, route.fromChain)
const evmTokenContractCallInfo = await getEVMTokenContractInfo(
ctx,
@@ -76,7 +85,6 @@ const _getEvm2StacksFeeInfo = async (
)
if (
stacksContractCallInfo == null ||
stacksSwapContractCallInfo == null ||
evmContractCallInfo == null ||
evmTokenContractCallInfo == null
) {
@@ -134,14 +142,11 @@ const _getEvm2StacksFeeInfo = async (
functionName: "maxAmountPerToken",
args: [tokenContractAddress],
}).then(numberFromSolidityContractNumber),
/**
* temp fix, should be back to `stacksContractCallInfo` in the future
*/
isPaused: executeReadonlyCallXLINK(
stacksSwapContractCallInfo.contractName,
stacksContractCallInfo.contractName,
"get-paused",
{},
stacksSwapContractCallInfo.executeOptions,
stacksContractCallInfo.executeOptions,
),
})
@@ -205,11 +210,21 @@ export const getStacks2EvmFeeInfo = async (
route: KnownRoute_FromStacks_ToEVM,
options: {
toDexAggregator: boolean
/**
* checkout the comments in getSpecialFeeDetailsForSwapRoute
*/
initialRoute: null | KnownRoute_ToStacks
},
): Promise<undefined | TransferProphet> => {
return withGlobalContextCache(
ctx.evm.feeRateCache,
`${withGlobalContextCache.cacheKeyFromRoute(route)}:${options.toDexAggregator ? "agg" : ""}`,
[
withGlobalContextCache.cacheKeyFromRoute(route),
options.toDexAggregator ? "agg" : "",
options.initialRoute == null
? ""
: withGlobalContextCache.cacheKeyFromRoute(options.initialRoute),
].join("#"),
() => _getStacks2EvmFeeInfo(ctx, route, options),
)
}
@@ -218,6 +233,10 @@ const _getStacks2EvmFeeInfo = async (
route: KnownRoute_FromStacks_ToEVM,
options: {
toDexAggregator: boolean
/**
* checkout the comments in getSpecialFeeDetailsForSwapRoute
*/
initialRoute: null | KnownRoute_ToStacks
},
): Promise<undefined | TransferProphet> => {
const stacksBaseContractCallInfo = getStacksContractCallInfo(
@@ -253,6 +272,13 @@ const _getStacks2EvmFeeInfo = async (
stacksChain: route.fromChain,
})) ?? stacksTokenContractCallInfo
const specialFeeInfo = await getSpecialFeeDetailsForSwapRoute(ctx, route, {
initialRoute: options.initialRoute,
swapRoute: {
via: options.toDexAggregator ? "evmDexAggregator" : "ALEX",
},
})
const tokenConf = await Promise.all([
executeReadonlyCallXLINK(
stacksContractCallInfo.contractName,
@@ -282,21 +308,48 @@ const _getStacks2EvmFeeInfo = async (
if (tokenConf == null) return undefined
const feeRate = numberFromStacksContractNumber(tokenConf.fee)
const minFee = numberFromStacksContractNumber(tokenConf["min-fee"])
const isPaused = tokenConf.isPaused || tokenConf.approved === false
const reserve = numberFromStacksContractNumber(tokenConf.reserve)
const minAmount = BigNumber.max([
numberFromStacksContractNumber(tokenConf["min-amount"]),
minFee,
])
const minAmount = numberFromStacksContractNumber(tokenConf["min-amount"])
const maxAmount = BigNumber.min([
numberFromStacksContractNumber(tokenConf["max-amount"]),
reserve,
])
if (specialFeeInfo != null) {
return {
isPaused,
bridgeToken: route.fromToken,
fees: [
{
type: "rate",
token: route.fromToken,
rate: specialFeeInfo.feeRate,
minimumAmount: specialFeeInfo.minFeeAmount,
},
...(specialFeeInfo.gasFee == null
? []
: [
{
type: "fixed",
token: specialFeeInfo.gasFee.token,
amount: specialFeeInfo.gasFee.amount,
} satisfies TransferProphet_Fee_Fixed,
]),
],
minBridgeAmount: BigNumber.isZero(minAmount)
? specialFeeInfo.minFeeAmount
: BigNumber.max([minAmount, specialFeeInfo.minFeeAmount]),
maxBridgeAmount: maxAmount,
}
}
const feeRate = numberFromStacksContractNumber(tokenConf.fee)
const minFee = numberFromStacksContractNumber(tokenConf["min-fee"])
return {
isPaused: tokenConf.isPaused || tokenConf.approved === false,
isPaused,
bridgeToken: route.fromToken,
fees: [
{
@@ -306,7 +359,9 @@ const _getStacks2EvmFeeInfo = async (
minimumAmount: minFee,
},
],
minBridgeAmount: BigNumber.isZero(minAmount) ? null : minAmount,
minBridgeAmount: BigNumber.isZero(minAmount)
? minFee
: BigNumber.max([minAmount, minFee]),
maxBridgeAmount: maxAmount,
}
}

View File

@@ -53,10 +53,12 @@ export enum StacksContractName {
BTCPegInEndpointAggregator = "btc-peg-in-endpoint-v2-07-agg",
BTCPegInEndpointLaunchpad = "btc-peg-in-endpoint-v2-05-launchpad",
BTCPegOutEndpoint = "btc-peg-out-endpoint-v2-01",
MetaPegInEndpoint = "meta-peg-in-endpoint-v2-04",
MetaPegInEndpointSwap = "meta-peg-in-endpoint-v2-06-swap",
MetaPegInEndpointAggregator = "meta-peg-in-endpoint-v2-06-agg",
MetaPegOutEndpoint = "meta-peg-out-endpoint-v2-04",
EVMPegInEndpoint = "cross-peg-in-endpoint-v2-04",
EVMPegInEndpointSwap = "cross-peg-in-endpoint-v2-04-swap",
EVMPegOutEndpoint = "cross-peg-out-endpoint-v2-01",

View File

@@ -1,3 +1,4 @@
import { EVM_BARE_PEG_IN_USE_SWAP_CONTRACT } from "../config"
import { evmTokenToCorrespondingStacksToken } from "../evmUtils/peggingHelpers"
import { metaTokenToCorrespondingStacksToken } from "../metaUtils/peggingHelpers"
import { StacksContractName } from "../stacksUtils/stxContractAddresses"
@@ -335,7 +336,21 @@ export async function getSpecialFeeDetailsForSwapRoute(
route: KnownRoute_FromStacks,
options: {
/**
* the initial route step
* The entry route step that triggered the Stacks transaction.
* It's crucial for correctly calculating fees in multi-step bridging
* processes.
*
* Examples:
*
* * BTC > Runes (`via: ALEX`):
* 1. btc > stacks (initialRoute)
* 2. stacks > runes
* * BTC > Runes (`via: evmDexAggregator`):
* 1. btc > stacks (initialRoute as well, but not what we want)
* 2. stacks > evm
* 3. evm swap
* 4. evm > stacks (initialRoute for this partition)
* 5. stacks > runes
*/
initialRoute: null | KnownRoute_ToStacks
/**
@@ -344,135 +359,125 @@ export async function getSpecialFeeDetailsForSwapRoute(
swapRoute: null | Pick<SwapRoute, "via">
},
): Promise<undefined | SpecialFeeDetailsForSwapRoute> {
const stacksContractCallInfo = getStacksContractCallInfo(
route.fromChain,
StacksContractName.BTCPegOutEndpoint,
)
const btcPegInSwapContractCallInfo = getStacksContractCallInfo(
route.fromChain,
StacksContractName.BTCPegInEndpointSwap,
)
const metaPegInSwapContractCallInfo = getStacksContractCallInfo(
route.fromChain,
StacksContractName.MetaPegInEndpointSwap,
)
if (
stacksContractCallInfo == null ||
btcPegInSwapContractCallInfo == null ||
metaPegInSwapContractCallInfo == null
) {
return
}
let feeInfo: undefined | SpecialFeeDetailsForSwapRoute
if (options.initialRoute != null) {
if (options.swapRoute == null) {
// not a swap route, skip...
} else if (options.swapRoute.via === "ALEX") {
if (KnownChainId.isBitcoinChain(options.initialRoute.fromChain)) {
const feeRate = executeReadonlyCallXLINK(
btcPegInSwapContractCallInfo.contractName,
"get-peg-out-fee",
{},
btcPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber)
if (
options.swapRoute == null ||
options.swapRoute.via === "evmDexAggregator"
) {
/**
* most of the bare peg in contract doesn't yet support this feature
*/
if (!EVM_BARE_PEG_IN_USE_SWAP_CONTRACT) return
let minFeeAmount: Promise<
SpecialFeeDetailsForSwapRoute["minFeeAmount"]
> = Promise.resolve(BigNumber.ZERO)
let gasFee: Promise<SpecialFeeDetailsForSwapRoute["gasFee"]> =
Promise.resolve(undefined)
if (
KnownChainId.isBitcoinChain(route.toChain) ||
KnownChainId.isBRC20Chain(route.toChain) ||
KnownChainId.isRunesChain(route.toChain)
) {
gasFee = executeReadonlyCallXLINK(
btcPegInSwapContractCallInfo.contractName,
"get-peg-out-gas-fee",
{},
btcPegInSwapContractCallInfo.executeOptions,
)
.then(numberFromStacksContractNumber)
.then(amount =>
props({
token: KnownTokenId.Bitcoin.BTC,
amount,
}),
)
} else if (KnownChainId.isEVMChain(route.toChain)) {
minFeeAmount = executeReadonlyCallXLINK(
btcPegInSwapContractCallInfo.contractName,
"get-peg-out-gas-fee",
{},
btcPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber)
} else {
checkNever(route.toChain)
}
feeInfo = await props({
feeRate,
minFeeAmount,
gasFee,
})
} else if (
KnownChainId.isBRC20Chain(options.initialRoute.fromChain) ||
KnownChainId.isRunesChain(options.initialRoute.fromChain)
) {
const feeRate = executeReadonlyCallXLINK(
metaPegInSwapContractCallInfo.contractName,
"get-peg-out-fee",
{},
metaPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber)
let minFeeAmount: Promise<
SpecialFeeDetailsForSwapRoute["minFeeAmount"]
> = Promise.resolve(BigNumber.ZERO)
let gasFee: Promise<SpecialFeeDetailsForSwapRoute["gasFee"]> =
Promise.resolve(undefined)
if (
KnownChainId.isBitcoinChain(route.toChain) ||
KnownChainId.isBRC20Chain(route.toChain) ||
KnownChainId.isRunesChain(route.toChain)
) {
gasFee = executeReadonlyCallXLINK(
metaPegInSwapContractCallInfo.contractName,
"get-peg-out-gas-fee",
{},
metaPegInSwapContractCallInfo.executeOptions,
)
.then(numberFromStacksContractNumber)
.then(amount =>
props({
token: KnownTokenId.Bitcoin.BTC,
amount,
}),
)
} else if (KnownChainId.isEVMChain(route.toChain)) {
minFeeAmount = executeReadonlyCallXLINK(
metaPegInSwapContractCallInfo.contractName,
"get-peg-out-gas-fee",
{},
metaPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber)
} else {
checkNever(route.toChain)
}
feeInfo = await props({
feeRate,
minFeeAmount,
gasFee,
})
} else if (KnownChainId.isEVMChain(options.initialRoute.fromChain)) {
// we don't have evm-peg-in-swap contract yet, skip...
} else {
checkNever(options.initialRoute.fromChain)
const evmPegInContractCallInfo = getStacksContractCallInfo(
route.fromChain,
StacksContractName.EVMPegInEndpointSwap,
)
if (evmPegInContractCallInfo == null) {
return
}
} else if (options.swapRoute.via === "evmDexAggregator") {
// do not yet have special fee rate for evm dex aggregator function, skip...
return getFeeInfo(
{
fromEVM: {
getFeeRate: () =>
executeReadonlyCallXLINK(
evmPegInContractCallInfo.contractName,
"get-peg-out-fee",
{},
evmPegInContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber),
getFixedFeeAmount: () =>
executeReadonlyCallXLINK(
evmPegInContractCallInfo.contractName,
"get-peg-out-gas-fee",
{},
evmPegInContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber),
},
},
{
initialRoute: options.initialRoute,
},
)
} else if (options.swapRoute.via === "ALEX") {
const btcPegInSwapContractCallInfo = getStacksContractCallInfo(
route.fromChain,
StacksContractName.BTCPegInEndpointSwap,
)
const metaPegInSwapContractCallInfo = getStacksContractCallInfo(
route.fromChain,
StacksContractName.MetaPegInEndpointSwap,
)
const evmPegInSwapContractCallInfo = getStacksContractCallInfo(
route.fromChain,
StacksContractName.EVMPegInEndpointSwap,
)
if (
btcPegInSwapContractCallInfo == null ||
metaPegInSwapContractCallInfo == null ||
evmPegInSwapContractCallInfo == null
) {
return
}
return getFeeInfo(
{
fromBitcoin: {
getFeeRate: () =>
executeReadonlyCallXLINK(
btcPegInSwapContractCallInfo.contractName,
"get-peg-out-fee",
{},
btcPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber),
getFixedFeeAmount: () =>
executeReadonlyCallXLINK(
btcPegInSwapContractCallInfo.contractName,
"get-peg-out-gas-fee",
{},
btcPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber),
},
fromMeta: {
getFeeRate: () =>
executeReadonlyCallXLINK(
metaPegInSwapContractCallInfo.contractName,
"get-peg-out-fee",
{},
metaPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber),
getFixedFeeAmount: () =>
executeReadonlyCallXLINK(
metaPegInSwapContractCallInfo.contractName,
"get-peg-out-gas-fee",
{},
metaPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber),
},
fromEVM: {
getFeeRate: () =>
executeReadonlyCallXLINK(
evmPegInSwapContractCallInfo.contractName,
"get-peg-out-fee",
{},
evmPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber),
getFixedFeeAmount: () =>
executeReadonlyCallXLINK(
evmPegInSwapContractCallInfo.contractName,
"get-peg-out-gas-fee",
{},
evmPegInSwapContractCallInfo.executeOptions,
).then(numberFromStacksContractNumber),
},
},
{
initialRoute: options.initialRoute,
},
)
} else {
checkNever(options.swapRoute.via)
}
@@ -481,4 +486,134 @@ export async function getSpecialFeeDetailsForSwapRoute(
if (feeInfo == null) return undefined
return props(feeInfo)
async function getFeeInfo(
context: {
fromBitcoin?: {
getFeeRate: () => Promise<BigNumber>
getFixedFeeAmount: () => Promise<BigNumber>
}
fromMeta?: {
getFeeRate: () => Promise<BigNumber>
getFixedFeeAmount: () => Promise<BigNumber>
}
fromEVM?: {
getFeeRate: () => Promise<BigNumber>
getFixedFeeAmount: () => Promise<BigNumber>
}
},
options: {
initialRoute: KnownRoute_ToStacks
},
): Promise<undefined | SpecialFeeDetailsForSwapRoute> {
let feeInfo: undefined | SpecialFeeDetailsForSwapRoute
if (KnownChainId.isBitcoinChain(options.initialRoute.fromChain)) {
if (context.fromBitcoin == null) return
const feeRate = context.fromBitcoin.getFeeRate()
let minFeeAmount: Promise<SpecialFeeDetailsForSwapRoute["minFeeAmount"]> =
Promise.resolve(BigNumber.ZERO)
let gasFee: Promise<SpecialFeeDetailsForSwapRoute["gasFee"]> =
Promise.resolve(undefined)
if (
KnownChainId.isBitcoinChain(route.toChain) ||
KnownChainId.isBRC20Chain(route.toChain) ||
KnownChainId.isRunesChain(route.toChain)
) {
gasFee = context.fromBitcoin.getFixedFeeAmount().then(amount =>
props({
token: KnownTokenId.Bitcoin.BTC,
amount,
}),
)
} else if (KnownChainId.isEVMChain(route.toChain)) {
minFeeAmount = context.fromBitcoin.getFixedFeeAmount()
} else {
checkNever(route.toChain)
}
feeInfo = await props({
feeRate,
minFeeAmount,
gasFee,
})
} else if (
KnownChainId.isBRC20Chain(options.initialRoute.fromChain) ||
KnownChainId.isRunesChain(options.initialRoute.fromChain)
) {
if (context.fromMeta == null) return
const feeRate = context.fromMeta.getFeeRate()
let minFeeAmount: Promise<SpecialFeeDetailsForSwapRoute["minFeeAmount"]> =
Promise.resolve(BigNumber.ZERO)
let gasFee: Promise<SpecialFeeDetailsForSwapRoute["gasFee"]> =
Promise.resolve(undefined)
if (
KnownChainId.isBitcoinChain(route.toChain) ||
KnownChainId.isBRC20Chain(route.toChain) ||
KnownChainId.isRunesChain(route.toChain)
) {
gasFee = context.fromMeta.getFixedFeeAmount().then(amount =>
props({
token: KnownTokenId.Bitcoin.BTC,
amount,
}),
)
} else if (KnownChainId.isEVMChain(route.toChain)) {
minFeeAmount = context.fromMeta.getFixedFeeAmount()
} else {
checkNever(route.toChain)
}
feeInfo = await props({
feeRate,
minFeeAmount,
gasFee,
})
} else if (KnownChainId.isEVMChain(options.initialRoute.fromChain)) {
if (context.fromEVM == null) return
const feeRate = context.fromEVM.getFeeRate()
let minFeeAmount: Promise<SpecialFeeDetailsForSwapRoute["minFeeAmount"]> =
Promise.resolve(BigNumber.ZERO)
let gasFee: Promise<SpecialFeeDetailsForSwapRoute["gasFee"]> =
Promise.resolve(undefined)
if (
KnownChainId.isBitcoinChain(route.toChain) ||
KnownChainId.isBRC20Chain(route.toChain) ||
KnownChainId.isRunesChain(route.toChain)
) {
gasFee = context.fromEVM.getFixedFeeAmount().then(amount =>
props({
token: KnownTokenId.Bitcoin.BTC,
amount,
}),
)
} else if (KnownChainId.isEVMChain(route.toChain)) {
minFeeAmount = context.fromEVM.getFixedFeeAmount()
} else {
checkNever(route.toChain)
}
feeInfo = await props({
feeRate,
minFeeAmount,
gasFee,
})
} else {
checkNever(options.initialRoute.fromChain)
}
return feeInfo
}
}

View File

@@ -12,6 +12,7 @@ import {
KnownRoute_FromBitcoin,
KnownRoute_FromBRC20,
KnownRoute_FromRunes,
KnownRoute_ToStacks,
} from "../buildSupportedRoutes"
import { applyTransferProphets } from "../feeRateHelpers"
import { toCorrespondingStacksToken } from "../SwapRouteHelpers"
@@ -99,6 +100,12 @@ export async function getPossibleEVMDexAggregatorSwapParametersImpl(
return Promise.all(
possibleSwapOnEVMChains.map(async evmChain =>
_getEVMDexAggregatorSwapParametersImpl(sdkContext, {
initialToStacksRoute: {
fromChain: info.fromChain as KnownChainId.BitcoinChain,
fromToken: info.fromToken as KnownTokenId.BitcoinToken,
toChain: transitStacksChain,
toToken: firstStepToStacksToken,
},
initialToStacksTransferProphet,
transitStacksChain,
firstStepToStacksToken,
@@ -112,6 +119,7 @@ export async function getPossibleEVMDexAggregatorSwapParametersImpl(
async function _getEVMDexAggregatorSwapParametersImpl(
sdkContext: SDKGlobalContext,
info: {
initialToStacksRoute: KnownRoute_ToStacks
initialToStacksTransferProphet: TransferProphet
transitStacksChain: KnownChainId.StacksChain
firstStepToStacksToken: KnownTokenId.StacksToken
@@ -164,7 +172,10 @@ async function _getEVMDexAggregatorSwapParametersImpl(
toChain: evmChain,
toToken: token,
},
{ toDexAggregator: true },
{
toDexAggregator: true,
initialRoute: info.initialToStacksRoute,
},
).then(info =>
info == null || info.isPaused ? null : { token, transferProphet: info },
),

View File

@@ -20,7 +20,7 @@ import {
SwapRoute_WithExchangeRate_Public,
SwapRouteViaEVMDexAggregator_WithExchangeRate_Public,
} from "../utils/SwapRouteHelpers"
import { hasAny } from "../utils/arrayHelpers"
import { hasAny, last } from "../utils/arrayHelpers"
import {
checkRouteValid,
KnownRoute,
@@ -28,6 +28,7 @@ import {
KnownRoute_FromBitcoin_ToEVM,
KnownRoute_FromBitcoin_ToRunes,
KnownRoute_FromBitcoin_ToStacks,
KnownRoute_ToStacks,
} from "../utils/buildSupportedRoutes"
import { UnsupportedBridgeRouteError } from "../utils/errors"
import { props } from "../utils/promiseHelpers"
@@ -300,6 +301,7 @@ async function bridgeInfoFromBitcoin_toEVM(
swapRoute: info.swapRoute ?? null,
}),
getStacks2EvmFeeInfo(ctx, _routes[1], {
initialRoute: _routes[0],
toDexAggregator: false,
}),
])
@@ -355,6 +357,7 @@ async function bridgeInfoFromBitcoin_toEVM(
}),
...intermediaryInfo.steps,
getStacks2EvmFeeInfo(ctx, evmPegOutRoute, {
initialRoute: last(intermediaryInfo.routes) as KnownRoute_ToStacks,
toDexAggregator: false,
}),
])
@@ -615,6 +618,7 @@ export async function constructDexAggregatorIntermediaryInfo(
const steps = [
// evm peg out agg
getStacks2EvmFeeInfo(ctx, routes[0], {
initialRoute: null,
toDexAggregator: true,
}),
//

View File

@@ -265,6 +265,7 @@ async function bridgeInfoFromEVM_toEVM(
const [step1, step2] = await Promise.all([
getEvm2StacksFeeInfo(ctx, step1Route),
getStacks2EvmFeeInfo(ctx, step2Route, {
initialRoute: step1Route,
toDexAggregator: false,
}),
])

View File

@@ -11,7 +11,7 @@ import {
getAndCheckTransitStacksTokens,
SwapRoute_WithExchangeRate_Public,
} from "../utils/SwapRouteHelpers"
import { hasAny } from "../utils/arrayHelpers"
import { hasAny, last } from "../utils/arrayHelpers"
import {
checkRouteValid,
KnownRoute,
@@ -25,6 +25,7 @@ import {
KnownRoute_FromRunes_ToEVM,
KnownRoute_FromRunes_ToRunes,
KnownRoute_FromRunes_ToStacks,
KnownRoute_ToStacks,
} from "../utils/buildSupportedRoutes"
import { UnsupportedBridgeRouteError } from "../utils/errors"
import { assertExclude, checkNever, isNotNull } from "../utils/typeHelpers"
@@ -410,6 +411,7 @@ async function bridgeInfoFromMeta_toEVM(
swapRoute: info.swapRoute ?? null,
}),
getStacks2EvmFeeInfo(ctx, _routes[1], {
initialRoute: _routes[0],
toDexAggregator: false,
}),
])
@@ -465,6 +467,7 @@ async function bridgeInfoFromMeta_toEVM(
}),
...intermediaryInfo.steps,
getStacks2EvmFeeInfo(ctx, evmPegOutRoute, {
initialRoute: last(intermediaryInfo.routes) as KnownRoute_ToStacks,
toDexAggregator: false,
}),
])

View File

@@ -145,6 +145,7 @@ async function bridgeInfoFromStacks_toEVM(
KnownRoute_FromStacks_ToEVM,
): Promise<BridgeInfoFromStacksOutput> {
const step1 = await getStacks2EvmFeeInfo(ctx, info, {
initialRoute: null,
toDexAggregator: false,
})
if (step1 == null) {