UNPKG

@xlink-network/xlink-sdk

Version:
411 lines (409 loc) 13.7 kB
import { BridgeRegistryAbi } from "./chunk-CY5XDHIQ.mjs"; import { BridgeEndpointAbi } from "./chunk-UNVARCOY.mjs"; import { props } from "./chunk-EEY7UWSA.mjs"; import { getEVMContractCallInfo, getEVMTokenContractInfo, numberFromSolidityContractNumber } from "./chunk-UJDCORME.mjs"; import { contractAssignedChainIdFromKnownChain } from "./chunk-RGOLYR47.mjs"; import { getBRC20SupportedRoutes, getRunesSupportedRoutes } from "./chunk-BNOOAGFD.mjs"; import { executeReadonlyCallXLINK, getStacksContractCallInfo, getStacksTokenContractInfo, numberFromStacksContractNumber } from "./chunk-JJNS722O.mjs"; import { getTerminatingStacksTokenContractAddress, stxTokenContractAddresses } from "./chunk-6UKYXMCX.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-COUTRDKA.mjs.map