mirror of
https://github.com/Brotocol-xyz/bro-sdk.git
synced 2026-01-12 06:44:18 +08:00
feat: upgrade evm fee model
This commit is contained in:
@@ -3,12 +3,12 @@ import {
|
||||
defineContract,
|
||||
booleanT,
|
||||
responseSimpleT,
|
||||
principalT,
|
||||
bufferT,
|
||||
uintT,
|
||||
tupleT,
|
||||
uintT,
|
||||
optionalT,
|
||||
bufferT,
|
||||
listT,
|
||||
principalT,
|
||||
traitT,
|
||||
stringT,
|
||||
noneT
|
||||
@@ -21,29 +21,11 @@ export const crossPegInEndpointV204Swap = defineContract({
|
||||
output: responseSimpleT(booleanT, ),
|
||||
mode: 'public'
|
||||
},
|
||||
callback: {
|
||||
input: [
|
||||
{ name: 'sender', type: principalT },
|
||||
{ name: 'payload', type: bufferT }
|
||||
],
|
||||
output: responseSimpleT(booleanT, ),
|
||||
mode: 'public'
|
||||
},
|
||||
'set-paused': {
|
||||
input: [ { name: 'paused', type: booleanT } ],
|
||||
output: responseSimpleT(booleanT, ),
|
||||
mode: 'public'
|
||||
},
|
||||
'set-peg-out-fee': {
|
||||
input: [ { name: 'new-peg-out-fee', type: uintT } ],
|
||||
output: responseSimpleT(booleanT, ),
|
||||
mode: 'public'
|
||||
},
|
||||
'set-peg-out-gas-fee': {
|
||||
input: [ { name: 'new-peg-out-gas-fee', type: uintT } ],
|
||||
output: responseSimpleT(booleanT, ),
|
||||
mode: 'public'
|
||||
},
|
||||
'transfer-to-cross-swap': {
|
||||
input: [
|
||||
{
|
||||
@@ -172,8 +154,6 @@ export const crossPegInEndpointV204Swap = defineContract({
|
||||
mode: 'readonly'
|
||||
},
|
||||
'get-paused': { input: [], output: booleanT, mode: 'readonly' },
|
||||
'get-peg-out-fee': { input: [], output: uintT, mode: 'readonly' },
|
||||
'get-peg-out-gas-fee': { input: [], output: uintT, mode: 'readonly' },
|
||||
'get-required-validators': { input: [], output: uintT, mode: 'readonly' },
|
||||
'get-token-reserve-or-default': {
|
||||
input: [
|
||||
@@ -269,8 +249,6 @@ export const crossPegInEndpointV204Swap = defineContract({
|
||||
mode: 'mapEntry'
|
||||
},
|
||||
'is-paused': { input: noneT, output: booleanT, mode: 'variable' },
|
||||
'peg-out-fee': { input: noneT, output: uintT, mode: 'variable' },
|
||||
'peg-out-gas-fee': { input: noneT, output: uintT, mode: 'variable' },
|
||||
'use-whitelist': { input: noneT, output: booleanT, mode: 'variable' }
|
||||
}
|
||||
} as const)
|
||||
|
||||
@@ -1,13 +1,17 @@
|
||||
import { getEVMSupportedRoutes } from "../evmUtils/apiHelpers/getEVMSupportedRoutes"
|
||||
import { getBRC20SupportedRoutes } from "../metaUtils/apiHelpers/getBRC20SupportedRoutes"
|
||||
import { getRunesSupportedRoutes } from "../metaUtils/apiHelpers/getRunesSupportedRoutes"
|
||||
import { StacksContractName } from "../stacksUtils/stxContractAddresses"
|
||||
import {
|
||||
SDKGlobalContext,
|
||||
withGlobalContextCache,
|
||||
} from "../sdkUtils/types.internal"
|
||||
import {
|
||||
executeReadonlyCallBro,
|
||||
getStacksContractCallInfo,
|
||||
getStacksTokenContractInfo,
|
||||
numberFromStacksContractNumber,
|
||||
} from "../stacksUtils/contractHelpers"
|
||||
import { StacksContractName } from "../stacksUtils/stxContractAddresses"
|
||||
import { BigNumber } from "../utils/BigNumber"
|
||||
import {
|
||||
IsSupportedFn,
|
||||
@@ -19,7 +23,8 @@ import { props } from "../utils/promiseHelpers"
|
||||
import {
|
||||
getAndCheckTransitStacksTokens,
|
||||
getSpecialFeeDetailsForSwapRoute,
|
||||
SpecialFeeDetailsForSwapRoute,
|
||||
NormalizedSpecialFeeDetails,
|
||||
normalizeSpecialFeeDetails,
|
||||
SwapRoute,
|
||||
} from "../utils/SwapRouteHelpers"
|
||||
import { checkNever, isNotNull } from "../utils/typeHelpers"
|
||||
@@ -33,10 +38,6 @@ import {
|
||||
TransferProphet_Fee_Fixed,
|
||||
TransferProphet_Fee_Rate,
|
||||
} from "../utils/types/TransferProphet"
|
||||
import {
|
||||
SDKGlobalContext,
|
||||
withGlobalContextCache,
|
||||
} from "../sdkUtils/types.internal"
|
||||
import { getBTCPegInAddress } from "./btcAddresses"
|
||||
|
||||
export const getBtc2StacksFeeInfo = async (
|
||||
@@ -235,22 +236,31 @@ const _getStacks2BtcFeeInfo = async (
|
||||
console.log("[getStacks2BtcFeeInfo/specialFeeInfo]", route, specialFeeInfo)
|
||||
}
|
||||
|
||||
const feeDetails: SpecialFeeDetailsForSwapRoute =
|
||||
specialFeeInfo ??
|
||||
(await props({
|
||||
feeRate: executeReadonlyCallBro(
|
||||
stacksContractCallInfo.contractName,
|
||||
"get-peg-out-fee",
|
||||
{},
|
||||
stacksContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
minFeeAmount: executeReadonlyCallBro(
|
||||
stacksContractCallInfo.contractName,
|
||||
"get-peg-out-min-fee",
|
||||
{},
|
||||
stacksContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
}))
|
||||
const feeDetails: NormalizedSpecialFeeDetails =
|
||||
specialFeeInfo != null
|
||||
? await normalizeSpecialFeeDetails(ctx, specialFeeInfo, {
|
||||
getFeeRate: () =>
|
||||
executeReadonlyCallBro(
|
||||
stacksContractCallInfo.contractName,
|
||||
"get-peg-out-fee",
|
||||
{},
|
||||
stacksContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
})
|
||||
: await props({
|
||||
feeRate: executeReadonlyCallBro(
|
||||
stacksContractCallInfo.contractName,
|
||||
"get-peg-out-fee",
|
||||
{},
|
||||
stacksContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
minFeeAmount: executeReadonlyCallBro(
|
||||
stacksContractCallInfo.contractName,
|
||||
"get-peg-out-min-fee",
|
||||
{},
|
||||
stacksContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
})
|
||||
|
||||
const resp = await props({
|
||||
...feeDetails,
|
||||
|
||||
@@ -28,7 +28,7 @@ export const contractNameOverrides_mainnet: Record<string, string> = {
|
||||
"btc-peg-in-endpoint-v2-05-launchpad": "btc-peg-in-v2-05-launchpad-3c",
|
||||
"meta-peg-in-endpoint-v2-06-swap": "meta-peg-in-v2-06e-swap",
|
||||
"meta-peg-in-endpoint-v2-06-agg": "meta-peg-in-v2-06i-agg",
|
||||
"cross-peg-in-endpoint-v2-04-swap": "cross-peg-in-v2-04b-swap",
|
||||
"cross-peg-in-endpoint-v2-04-swap": "cross-peg-in-v2-04c-swap",
|
||||
"cross-peg-in-endpoint-v2-04-launchpad": "cross-peg-in-v2-04-launchpad-3c",
|
||||
"cross-peg-out-endpoint-v2-01-agg": "cross-peg-out-v2-01c-agg",
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import { BigNumber } from "../utils/BigNumber"
|
||||
import {
|
||||
getAndCheckTransitStacksTokens,
|
||||
getSpecialFeeDetailsForSwapRoute,
|
||||
normalizeSpecialFeeDetails,
|
||||
} from "../utils/SwapRouteHelpers"
|
||||
import {
|
||||
IsSupportedFn,
|
||||
@@ -385,7 +386,16 @@ const _getStacks2EvmFeeInfo = async (
|
||||
reserve,
|
||||
])
|
||||
|
||||
const feeRate = numberFromStacksContractNumber(tokenConf.fee)
|
||||
const minFee = numberFromStacksContractNumber(tokenConf["min-fee"])
|
||||
|
||||
if (specialFeeInfo != null) {
|
||||
const normalizedFeeDetails = await normalizeSpecialFeeDetails(
|
||||
ctx,
|
||||
specialFeeInfo,
|
||||
{ getFeeRate: async () => feeRate },
|
||||
)
|
||||
|
||||
return {
|
||||
isPaused,
|
||||
bridgeToken: route.fromToken,
|
||||
@@ -393,29 +403,26 @@ const _getStacks2EvmFeeInfo = async (
|
||||
{
|
||||
type: "rate",
|
||||
token: route.fromToken,
|
||||
rate: specialFeeInfo.feeRate,
|
||||
minimumAmount: specialFeeInfo.minFeeAmount,
|
||||
rate: normalizedFeeDetails.feeRate,
|
||||
minimumAmount: normalizedFeeDetails.minFeeAmount,
|
||||
},
|
||||
...(specialFeeInfo.gasFee == null
|
||||
...(normalizedFeeDetails.gasFee == null
|
||||
? []
|
||||
: [
|
||||
{
|
||||
type: "fixed",
|
||||
token: specialFeeInfo.gasFee.token,
|
||||
amount: specialFeeInfo.gasFee.amount,
|
||||
token: normalizedFeeDetails.gasFee.token,
|
||||
amount: normalizedFeeDetails.gasFee.amount,
|
||||
} satisfies TransferProphet_Fee_Fixed,
|
||||
]),
|
||||
],
|
||||
minBridgeAmount: BigNumber.isZero(minAmount)
|
||||
? specialFeeInfo.minFeeAmount
|
||||
: BigNumber.max([minAmount, specialFeeInfo.minFeeAmount]),
|
||||
? normalizedFeeDetails.minFeeAmount
|
||||
: BigNumber.max([minAmount, normalizedFeeDetails.minFeeAmount]),
|
||||
maxBridgeAmount: maxAmount,
|
||||
}
|
||||
}
|
||||
|
||||
const feeRate = numberFromStacksContractNumber(tokenConf.fee)
|
||||
const minFee = numberFromStacksContractNumber(tokenConf["min-fee"])
|
||||
|
||||
return {
|
||||
isPaused,
|
||||
bridgeToken: route.fromToken,
|
||||
|
||||
@@ -9,6 +9,8 @@ import { BigNumber } from "../utils/BigNumber"
|
||||
import {
|
||||
getAndCheckTransitStacksTokens,
|
||||
getSpecialFeeDetailsForSwapRoute,
|
||||
NormalizedSpecialFeeDetails,
|
||||
normalizeSpecialFeeDetails,
|
||||
SwapRoute,
|
||||
} from "../utils/SwapRouteHelpers"
|
||||
import {
|
||||
@@ -315,19 +317,22 @@ const _getStacks2MetaFeeInfo = async (
|
||||
console.log("[getStacks2MetaFeeInfo/specialFeeInfo]", route, specialFeeInfo)
|
||||
}
|
||||
|
||||
const feeDetails =
|
||||
specialFeeInfo ??
|
||||
(await props({
|
||||
feeRate: filteredRoute.pegOutFeeRate,
|
||||
minFeeAmount: BigNumber.ZERO,
|
||||
gasFee:
|
||||
filteredRoute.pegOutFeeBitcoinAmount == null
|
||||
? undefined
|
||||
: props({
|
||||
token: KnownTokenId.Stacks.aBTC,
|
||||
amount: filteredRoute.pegOutFeeBitcoinAmount,
|
||||
}),
|
||||
}))
|
||||
const feeDetails: NormalizedSpecialFeeDetails =
|
||||
specialFeeInfo != null
|
||||
? await normalizeSpecialFeeDetails(ctx, specialFeeInfo, {
|
||||
getFeeRate: async () => filteredRoute.pegOutFeeRate,
|
||||
})
|
||||
: await props({
|
||||
feeRate: filteredRoute.pegOutFeeRate,
|
||||
minFeeAmount: BigNumber.ZERO,
|
||||
gasFee:
|
||||
filteredRoute.pegOutFeeBitcoinAmount == null
|
||||
? undefined
|
||||
: props({
|
||||
token: KnownTokenId.Stacks.aBTC,
|
||||
amount: filteredRoute.pegOutFeeBitcoinAmount,
|
||||
}),
|
||||
})
|
||||
if (ctx.debugLog) {
|
||||
console.log("[getStacks2MetaFeeInfo]", route, feeDetails)
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import { GeneralCacheInterface } from "../utils/types/GeneralCacheInterface"
|
||||
import { KnownChainId } from "../utils/types/knownIds"
|
||||
import { TransferProphet } from "../utils/types/TransferProphet"
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
||||
export interface SDKGlobalContextCache<K, V>
|
||||
extends GeneralCacheInterface<K, V> {}
|
||||
|
||||
|
||||
@@ -15,6 +15,9 @@ export const contractsMultisigMainnet =
|
||||
export const contractsMultisigTestnet =
|
||||
"ST2QXSK64YQX3CQPC530K79XWQ98XFAM9W3XKEH3N"
|
||||
|
||||
export const contractsDeployerMainnet_v2 =
|
||||
"SP2FGHFNGMH6NF2427Y20271Q6CKJ67FDX2V2JG6X"
|
||||
|
||||
export const alexContractDeployerMainnet =
|
||||
"SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM"
|
||||
export const alexContractDeployerTestnet =
|
||||
@@ -128,7 +131,7 @@ export const stxContractAddresses = {
|
||||
},
|
||||
[StacksContractName.EVMPegInEndpointSwap]: {
|
||||
[KnownChainId.Stacks.Mainnet]: wrapContractAddress("mainnet", {
|
||||
deployerAddress: contractsMultisigMainnet,
|
||||
deployerAddress: contractsDeployerMainnet_v2,
|
||||
contractName: StacksContractName.EVMPegInEndpointSwap,
|
||||
}),
|
||||
[KnownChainId.Stacks.Testnet]: wrapContractAddress("testnet", {
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
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"
|
||||
import { SDKNumber, StacksContractAddress } from "../sdkUtils/types"
|
||||
import { SDKGlobalContext } from "../sdkUtils/types.internal"
|
||||
import {
|
||||
executeReadonlyCallBro,
|
||||
getStacksContractCallInfo,
|
||||
getStacksToken,
|
||||
numberFromStacksContractNumber,
|
||||
} from "../stacksUtils/contractHelpers"
|
||||
import { SDKNumber, StacksContractAddress } from "../sdkUtils/types"
|
||||
import { SDKGlobalContext } from "../sdkUtils/types.internal"
|
||||
import { StacksContractName } from "../stacksUtils/stxContractAddresses"
|
||||
import { last } from "./arrayHelpers"
|
||||
import { BigNumber } from "./BigNumber"
|
||||
import {
|
||||
@@ -327,8 +327,9 @@ export async function toCorrespondingStacksToken(
|
||||
return toStacksTokenPromise
|
||||
}
|
||||
|
||||
const inheritFeeInfoSymbol = Symbol("inheritFeeInfo")
|
||||
export interface SpecialFeeDetailsForSwapRoute {
|
||||
feeRate: BigNumber
|
||||
feeRate: BigNumber | typeof inheritFeeInfoSymbol
|
||||
minFeeAmount: BigNumber
|
||||
gasFee?: { token: KnownTokenId.KnownToken; amount: BigNumber }
|
||||
}
|
||||
@@ -381,22 +382,14 @@ export async function getSpecialFeeDetailsForSwapRoute(
|
||||
|
||||
return getFeeInfo(
|
||||
{
|
||||
fromEVM: {
|
||||
getFeeRate: () =>
|
||||
executeReadonlyCallBro(
|
||||
evmPegInContractCallInfo.contractName,
|
||||
"get-peg-out-fee",
|
||||
{},
|
||||
evmPegInContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
getFixedFeeAmount: () =>
|
||||
executeReadonlyCallBro(
|
||||
evmPegInContractCallInfo.contractName,
|
||||
"get-peg-out-gas-fee",
|
||||
{},
|
||||
evmPegInContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
},
|
||||
fromEVM:
|
||||
KnownChainId.isBRC20Chain(route.toChain) ||
|
||||
KnownChainId.isRunesChain(route.toChain)
|
||||
? {
|
||||
getFeeRate: async () => inheritFeeInfoSymbol,
|
||||
getFixedFeeAmount: async () => BigNumber.ZERO,
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
{
|
||||
initialRoute: options.initialRoute,
|
||||
@@ -458,22 +451,14 @@ export async function getSpecialFeeDetailsForSwapRoute(
|
||||
metaPegInSwapContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
},
|
||||
fromEVM: {
|
||||
getFeeRate: () =>
|
||||
executeReadonlyCallBro(
|
||||
evmPegInSwapContractCallInfo.contractName,
|
||||
"get-peg-out-fee",
|
||||
{},
|
||||
evmPegInSwapContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
getFixedFeeAmount: () =>
|
||||
executeReadonlyCallBro(
|
||||
evmPegInSwapContractCallInfo.contractName,
|
||||
"get-peg-out-gas-fee",
|
||||
{},
|
||||
evmPegInSwapContractCallInfo.executeOptions,
|
||||
).then(numberFromStacksContractNumber),
|
||||
},
|
||||
fromEVM:
|
||||
KnownChainId.isBRC20Chain(route.toChain) ||
|
||||
KnownChainId.isRunesChain(route.toChain)
|
||||
? {
|
||||
getFeeRate: async () => inheritFeeInfoSymbol,
|
||||
getFixedFeeAmount: async () => BigNumber.ZERO,
|
||||
}
|
||||
: undefined,
|
||||
},
|
||||
{
|
||||
initialRoute: options.initialRoute,
|
||||
@@ -491,15 +476,15 @@ export async function getSpecialFeeDetailsForSwapRoute(
|
||||
async function getFeeInfo(
|
||||
context: {
|
||||
fromBitcoin?: {
|
||||
getFeeRate: () => Promise<BigNumber>
|
||||
getFeeRate: () => Promise<BigNumber | typeof inheritFeeInfoSymbol>
|
||||
getFixedFeeAmount: () => Promise<BigNumber>
|
||||
}
|
||||
fromMeta?: {
|
||||
getFeeRate: () => Promise<BigNumber>
|
||||
getFeeRate: () => Promise<BigNumber | typeof inheritFeeInfoSymbol>
|
||||
getFixedFeeAmount: () => Promise<BigNumber>
|
||||
}
|
||||
fromEVM?: {
|
||||
getFeeRate: () => Promise<BigNumber>
|
||||
getFeeRate: () => Promise<BigNumber | typeof inheritFeeInfoSymbol>
|
||||
getFixedFeeAmount: () => Promise<BigNumber>
|
||||
}
|
||||
},
|
||||
@@ -618,3 +603,27 @@ export async function getSpecialFeeDetailsForSwapRoute(
|
||||
return feeInfo
|
||||
}
|
||||
}
|
||||
|
||||
export interface NormalizedSpecialFeeDetails {
|
||||
feeRate: BigNumber
|
||||
minFeeAmount: BigNumber
|
||||
gasFee?: { token: KnownTokenId.KnownToken; amount: BigNumber }
|
||||
}
|
||||
export async function normalizeSpecialFeeDetails(
|
||||
ctx: SDKGlobalContext,
|
||||
rawFeeDetails: SpecialFeeDetailsForSwapRoute,
|
||||
getters: {
|
||||
getFeeRate: () => Promise<BigNumber>
|
||||
},
|
||||
): Promise<NormalizedSpecialFeeDetails> {
|
||||
const feeRate =
|
||||
rawFeeDetails.feeRate === inheritFeeInfoSymbol
|
||||
? await getters.getFeeRate()
|
||||
: rawFeeDetails.feeRate
|
||||
|
||||
return {
|
||||
feeRate,
|
||||
minFeeAmount: rawFeeDetails.minFeeAmount,
|
||||
gasFee: rawFeeDetails.gasFee,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user