mirror of
https://github.com/Brotocol-xyz/bro-sdk.git
synced 2026-01-12 14:54:21 +08:00
feat: update fee info reading logic
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 },
|
||||
),
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
//
|
||||
|
||||
@@ -265,6 +265,7 @@ async function bridgeInfoFromEVM_toEVM(
|
||||
const [step1, step2] = await Promise.all([
|
||||
getEvm2StacksFeeInfo(ctx, step1Route),
|
||||
getStacks2EvmFeeInfo(ctx, step2Route, {
|
||||
initialRoute: step1Route,
|
||||
toDexAggregator: false,
|
||||
}),
|
||||
])
|
||||
|
||||
@@ -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,
|
||||
}),
|
||||
])
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user