@xlink-network/xlink-sdk
Version:
411 lines (409 loc) • 13.7 kB
JavaScript
import {
props
} from "./chunk-EEY7UWSA.mjs";
import {
BridgeRegistryAbi
} from "./chunk-CY5XDHIQ.mjs";
import {
BridgeEndpointAbi
} from "./chunk-UNVARCOY.mjs";
import {
getEVMContractCallInfo,
getEVMTokenContractInfo,
numberFromSolidityContractNumber
} from "./chunk-A6P6ZEKP.mjs";
import {
getBRC20SupportedRoutes,
getRunesSupportedRoutes
} from "./chunk-RPEYYVCV.mjs";
import {
contractAssignedChainIdFromKnownChain
} from "./chunk-RGOLYR47.mjs";
import {
executeReadonlyCallXLINK,
getStacksContractCallInfo,
getStacksTokenContractInfo,
numberFromStacksContractNumber
} from "./chunk-BAWSEGXM.mjs";
import {
getTerminatingStacksTokenContractAddress,
stxTokenContractAddresses
} from "./chunk-YFQCRPOW.mjs";
import {
nativeCurrencyAddress
} from "./chunk-ZXKZ4Z37.mjs";
import {
KnownChainId,
KnownTokenId,
_allNoLongerSupportedEVMChains
} from "./chunk-GZDQGY7B.mjs";
import {
assertExclude,
checkNever
} from "./chunk-E5Y3FGR6.mjs";
import {
BigNumber
} from "./chunk-KHTJNOQE.mjs";
// src/evmUtils/peggingHelpers.ts
import { callReadOnlyFunction } from "@stacks/transactions";
import { unwrapResponse } from "clarity-codegen";
import { readContract } from "viem/actions";
var getEvm2StacksFeeInfo = async (ctx, route) => {
const stacksContractCallInfo = getStacksContractCallInfo(
route.toChain,
"cross-peg-in-endpoint-v2-04"
);
const evmContractCallInfo = await getEVMContractCallInfo(ctx, route.fromChain);
const evmTokenContractCallInfo = await getEVMTokenContractInfo(
ctx,
route.fromChain,
route.fromToken
);
if (stacksContractCallInfo == null || evmContractCallInfo == null || evmTokenContractCallInfo == null) {
return;
}
if (evmTokenContractCallInfo.tokenContractAddress === nativeCurrencyAddress) {
return getEvm2StacksNativeBridgeFeeInfo(ctx, route);
}
const executeOptions = {
deployerAddress: stacksContractCallInfo.deployerAddress,
callReadOnlyFunction: (callOptions) => callReadOnlyFunction({
...callOptions,
network: stacksContractCallInfo.network
})
};
const { client, tokenContractAddress } = evmTokenContractCallInfo;
const registryAddr = evmContractCallInfo.registryContractAddress ?? await readContract(client, {
abi: BridgeEndpointAbi,
address: evmContractCallInfo.bridgeEndpointContractAddress,
functionName: "registry"
});
const resp = await props({
isApproved: readContract(client, {
abi: BridgeRegistryAbi,
address: registryAddr,
functionName: "APPROVED_TOKEN"
}).then(
(key) => readContract(client, {
abi: BridgeRegistryAbi,
address: registryAddr,
functionName: "hasRole",
args: [key, tokenContractAddress]
})
),
feeRate: readContract(client, {
abi: BridgeRegistryAbi,
address: registryAddr,
functionName: "feePctPerToken",
args: [tokenContractAddress]
}).then(numberFromSolidityContractNumber),
minFeeAmount: readContract(client, {
abi: BridgeRegistryAbi,
address: registryAddr,
functionName: "minFeePerToken",
args: [tokenContractAddress]
}).then(numberFromSolidityContractNumber),
minAmount: readContract(client, {
abi: BridgeRegistryAbi,
address: registryAddr,
functionName: "minAmountPerToken",
args: [tokenContractAddress]
}).then(numberFromSolidityContractNumber),
maxAmount: readContract(client, {
abi: BridgeRegistryAbi,
address: registryAddr,
functionName: "maxAmountPerToken",
args: [tokenContractAddress]
}).then(numberFromSolidityContractNumber),
isPaused: executeReadonlyCallXLINK(
stacksContractCallInfo.contractName,
"get-paused",
{},
executeOptions
)
});
if (!resp.isApproved) return void 0;
const minAmount = BigNumber.max([resp.minAmount, resp.minFeeAmount]);
const maxAmount = BigNumber.min([resp.maxAmount]);
return {
isPaused: resp.isPaused,
bridgeToken: route.fromToken,
fees: [
{
type: "rate",
token: route.fromToken,
rate: resp.feeRate,
minimumAmount: resp.minFeeAmount
}
],
minBridgeAmount: BigNumber.isZero(minAmount) ? null : minAmount,
maxBridgeAmount: BigNumber.isZero(maxAmount) ? null : maxAmount
};
};
var getEvm2StacksNativeBridgeFeeInfo = async (ctx, route) => {
const stacksContractCallInfo = getStacksContractCallInfo(
route.toChain,
"cross-peg-in-endpoint-v2-04"
);
const evmContractCallInfo = await getEVMContractCallInfo(ctx, route.fromChain);
if (stacksContractCallInfo == null || evmContractCallInfo?.nativeBridgeEndpointContractAddress == null) {
return;
}
const executeOptions = {
deployerAddress: stacksContractCallInfo.deployerAddress,
callReadOnlyFunction: (callOptions) => callReadOnlyFunction({
...callOptions,
network: stacksContractCallInfo.network
})
};
const resp = await props({
isPaused: executeReadonlyCallXLINK(
stacksContractCallInfo.contractName,
"get-paused",
{},
executeOptions
)
});
return {
isPaused: resp.isPaused,
bridgeToken: route.fromToken,
fees: [],
minBridgeAmount: null,
maxBridgeAmount: null
};
};
var getStacks2EvmFeeInfo = async (route) => {
const stacksContractCallInfo = getStacksContractCallInfo(
route.fromChain,
"cross-peg-out-endpoint-v2-01"
);
const stacksTokenContractCallInfo = getStacksTokenContractInfo(
route.fromChain,
route.fromToken
);
const toChainId = contractAssignedChainIdFromKnownChain(route.toChain);
if (stacksContractCallInfo == null || stacksTokenContractCallInfo == null) {
return;
}
const terminatingStacksTokenAddress = getTerminatingStacksTokenContractAddress(route) ?? stacksTokenContractCallInfo;
const executeOptions = {
deployerAddress: stacksContractCallInfo.deployerAddress,
callReadOnlyFunction: (callOptions) => callReadOnlyFunction({
...callOptions,
network: stacksContractCallInfo.network
})
};
const tokenConf = await Promise.all([
executeReadonlyCallXLINK(
stacksContractCallInfo.contractName,
"get-approved-pair-or-fail",
{
pair: {
token: `${terminatingStacksTokenAddress.deployerAddress}.${terminatingStacksTokenAddress.contractName}`,
"chain-id": toChainId
}
},
executeOptions
),
executeReadonlyCallXLINK(
stacksContractCallInfo.contractName,
"get-paused",
{},
executeOptions
)
]).then(([resp, isPaused]) => {
if (resp.type !== "success") return void 0;
return {
...unwrapResponse(resp),
isPaused
};
});
if (tokenConf == null) return void 0;
const feeRate = numberFromStacksContractNumber(tokenConf.fee);
const minFee = numberFromStacksContractNumber(tokenConf["min-fee"]);
const reserve = numberFromStacksContractNumber(tokenConf.reserve);
const minAmount = BigNumber.max([
numberFromStacksContractNumber(tokenConf["min-amount"]),
minFee
]);
const maxAmount = BigNumber.min([
numberFromStacksContractNumber(tokenConf["max-amount"]),
reserve
]);
return {
isPaused: tokenConf.isPaused || tokenConf.approved === false,
bridgeToken: route.fromToken,
fees: [
{
type: "rate",
token: route.fromToken,
rate: feeRate,
minimumAmount: minFee
}
],
minBridgeAmount: BigNumber.isZero(minAmount) ? null : minAmount,
maxBridgeAmount: BigNumber.isZero(maxAmount) ? null : maxAmount
};
};
async function fromCorrespondingStacksToken(toChain, stacksToken) {
const EVMToken = KnownTokenId.EVM;
const StacksToken = KnownTokenId.Stacks;
const restEVMTokenPossibilities = assertExclude.i();
if (stacksToken === StacksToken.sLUNR) {
return [EVMToken.LUNR];
}
assertExclude(restEVMTokenPossibilities, EVMToken.LUNR);
if (stacksToken === StacksToken.ALEX) {
return [EVMToken.ALEX];
}
assertExclude(restEVMTokenPossibilities, EVMToken.ALEX);
if (stacksToken === StacksToken.sSKO) {
return [EVMToken.SKO];
}
assertExclude(restEVMTokenPossibilities, EVMToken.SKO);
if (stacksToken === StacksToken.vLiSTX) {
return [EVMToken.vLiSTX];
}
assertExclude(restEVMTokenPossibilities, EVMToken.vLiSTX);
if (stacksToken === StacksToken.vLiALEX) {
return [EVMToken.vLiALEX];
}
assertExclude(restEVMTokenPossibilities, EVMToken.vLiALEX);
if (stacksToken === StacksToken.sUSDT) {
return [EVMToken.sUSDT, EVMToken.USDT, EVMToken.USDC];
}
assertExclude(restEVMTokenPossibilities, EVMToken.sUSDT);
assertExclude(restEVMTokenPossibilities, EVMToken.USDT);
assertExclude(restEVMTokenPossibilities, EVMToken.USDC);
if (stacksToken === StacksToken.aBTC) {
return [EVMToken.aBTC, EVMToken.WBTC, EVMToken.BTCB, EVMToken.cbBTC];
}
assertExclude(restEVMTokenPossibilities, EVMToken.aBTC);
assertExclude(restEVMTokenPossibilities, EVMToken.WBTC);
assertExclude(restEVMTokenPossibilities, EVMToken.BTCB);
assertExclude(restEVMTokenPossibilities, EVMToken.cbBTC);
if (stacksToken === StacksToken.uBTC) {
return [EVMToken.uBTC, EVMToken.wuBTC];
}
assertExclude(restEVMTokenPossibilities, EVMToken.uBTC);
assertExclude(restEVMTokenPossibilities, EVMToken.wuBTC);
if (stacksToken === StacksToken.DB20) {
return [EVMToken.DB20];
}
assertExclude(restEVMTokenPossibilities, EVMToken.DB20);
if (stacksToken === StacksToken.DOG) {
return [EVMToken.DOG];
}
assertExclude(restEVMTokenPossibilities, EVMToken.DOG);
checkNever(restEVMTokenPossibilities);
return [];
}
async function toCorrespondingStacksToken(evmToken) {
const EVMToken = KnownTokenId.EVM;
const StacksToken = KnownTokenId.Stacks;
switch (evmToken) {
case EVMToken.LUNR:
return StacksToken.sLUNR;
case EVMToken.ALEX:
return StacksToken.ALEX;
case EVMToken.SKO:
return StacksToken.sSKO;
case EVMToken.vLiSTX:
return StacksToken.vLiSTX;
case EVMToken.vLiALEX:
return StacksToken.vLiALEX;
case EVMToken.sUSDT:
case EVMToken.USDT:
case EVMToken.USDC:
return StacksToken.sUSDT;
case EVMToken.aBTC:
case EVMToken.BTCB:
case EVMToken.WBTC:
case EVMToken.cbBTC:
return StacksToken.aBTC;
case EVMToken.uBTC:
case EVMToken.wuBTC:
return StacksToken.uBTC;
case EVMToken.DB20:
return StacksToken.DB20;
case EVMToken.DOG:
return StacksToken.DOG;
default:
checkNever(evmToken);
return;
}
}
var isSupportedEVMRoute = async (ctx, route) => {
const { fromChain, fromToken, toChain, toToken } = route;
if (fromChain === toChain && fromToken === toToken) {
return false;
}
if (KnownChainId.isEVMChain(fromChain) && _allNoLongerSupportedEVMChains.includes(fromChain)) {
return false;
}
if (KnownChainId.isEVMChain(toChain) && _allNoLongerSupportedEVMChains.includes(toChain)) {
return false;
}
if (!KnownChainId.isEVMChain(fromChain) || !KnownTokenId.isEVMToken(fromToken)) {
return false;
}
if (!KnownChainId.isKnownChain(toChain)) return false;
const fromContractInfo = await getEVMContractCallInfo(ctx, fromChain);
if (fromContractInfo == null) return false;
const fromTokenInfo = await getEVMTokenContractInfo(ctx, fromChain, fromToken);
if (fromTokenInfo == null) return false;
if (fromTokenInfo.tokenContractAddress === nativeCurrencyAddress) {
if (fromContractInfo.bridgeEndpointContractAddress == null) return false;
if (!KnownChainId.isBitcoinChain(toChain)) return false;
}
if (KnownChainId.isStacksChain(toChain)) {
if (!KnownTokenId.isStacksToken(toToken)) return false;
const stacksToken = await toCorrespondingStacksToken(fromToken);
if (stacksToken == null) return false;
if (stxTokenContractAddresses[stacksToken]?.[toChain] == null) {
return false;
}
return stacksToken === toToken;
}
if (KnownChainId.isEVMChain(toChain)) {
if (!KnownTokenId.isEVMToken(toToken)) return false;
const toTokenInfo = await getEVMTokenContractInfo(ctx, toChain, toToken);
if (toTokenInfo == null) return false;
const transitStacksToken = await toCorrespondingStacksToken(fromToken);
if (transitStacksToken == null) return false;
const toEVMTokens = await fromCorrespondingStacksToken(
toChain,
transitStacksToken
);
return toEVMTokens.includes(toToken);
}
if (KnownChainId.isBitcoinChain(toChain)) {
if (!KnownTokenId.isBitcoinToken(toToken)) return false;
const stacksToken = await toCorrespondingStacksToken(fromToken);
return stacksToken === KnownTokenId.Stacks.aBTC;
}
if (KnownChainId.isRunesChain(toChain)) {
if (!KnownTokenId.isRunesToken(toToken)) return false;
const transitStacksToken = await toCorrespondingStacksToken(fromToken);
if (transitStacksToken == null) return false;
const runesRoutes = await getRunesSupportedRoutes(ctx, toChain);
return runesRoutes.some((route2) => route2.stacksToken === transitStacksToken);
}
if (KnownChainId.isBRC20Chain(toChain)) {
if (!KnownTokenId.isBRC20Token(toToken)) return false;
const transitStacksToken = await toCorrespondingStacksToken(fromToken);
if (transitStacksToken == null) return false;
const brc20Routes = await getBRC20SupportedRoutes(ctx, toChain);
return brc20Routes.some((route2) => route2.stacksToken === transitStacksToken);
}
checkNever(toChain);
return false;
};
export {
getEvm2StacksFeeInfo,
getStacks2EvmFeeInfo,
fromCorrespondingStacksToken,
toCorrespondingStacksToken,
isSupportedEVMRoute
};
//# sourceMappingURL=chunk-D2X23GOD.mjs.map