@biconomy/abstractjs
Version:
SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.
230 lines • 10.5 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.buildAcrossIntentComposable = void 0;
exports.getAcrossSuggestedFees = getAcrossSuggestedFees;
exports.calculateAcrossFees = calculateAcrossFees;
exports.formatAcrossFeePercentage = formatAcrossFeePercentage;
const viem_1 = require("viem");
const composabilityCalls_1 = require("../../../modules/utils/composabilityCalls.js");
const createChainAddressMap_1 = require("../../../modules/utils/createChainAddressMap.js");
const buildBatch_1 = require("./buildBatch.js");
const buildComposable_1 = require("./buildComposable.js");
const buildTransfer_1 = require("./buildTransfer.js");
const defaultAcrossIntentWrapperAddress = "0x000000E2E47D694bDAa5a46056A894e747ED2854";
const acrossIntentWrappers = (0, createChainAddressMap_1.createChainAddressMap)([]);
const acrossSpokePool = (0, createChainAddressMap_1.createChainAddressMap)([
[41455, "0x13fDac9F9b4777705db45291bbFF3c972c6d1d97"],
[42161, "0xe35e9842fceaca96570b734083f4a58e8f7c5f2a"],
[421614, "0x7E63A5f1a8F0B4d0934B2f2327DAED3F6bb2ee75"],
[8453, "0x09aea4b2242abC8bb4BB78D537A67a245A7bEC64"],
[84532, "0x82B564983aE7274c86695917BBf8C99ECb6F0F8F"],
[81457, "0x2D509190Ed0172ba588407D4c2df918F955Cc6E1"],
[168587773, "0x5545092553Cf5Bf786e87a87192E902D50D8f022"],
[56, "0x4e8E101924eDE233C13e2D8622DC8aED2872d505"],
[1, "0x5c7BCd6E7De5423a257D81B442095A1a6ced35C5"],
[11155111, "0x5ef6C01E11889d86803e0B23e3cB3F9E9d97B662"],
[57073, "0xeF684C38F94F48775959ECf2012D7E864ffb9dd4"],
[232, "0xe7cb3e167e7475dE1331Cf6E0CEb187654619E12"],
[59144, "0x7E63A5f1a8F0B4d0934B2f2327DAED3F6bb2ee75"],
[1135, "0x9552a0a6624A23B848060AE5901659CDDa1f83f8"],
[4202, "0xeF684C38F94F48775959ECf2012D7E864ffb9dd4"],
[34443, "0x3baD7AD0728f9917d1Bf08af5782dCbD516cDd96"],
[919, "0xbd886FC0725Cc459b55BbFEb3E4278610331f83b"],
[10, "0x6f26Bf09B1C792e3228e5467807a900A503c0281"],
[11155420, "0x4e8E101924eDE233C13e2D8622DC8aED2872d505"],
[137, "0x9295ee1d8C5b022Be115A2AD3c30C72E34e7F096"],
[80002, "0xd08baaE74D6d2eAb1F3320B2E1a53eeb391ce8e5"],
[690, "0x13fDac9F9b4777705db45291bbFF3c972c6d1d97"],
[534352, "0x3bad7ad0728f9917d1bf08af5782dcbd516cdd96"],
[1868, "0x3baD7AD0728f9917d1Bf08af5782dCbD516cDd96"],
[130, "0x09aea4b2242abC8bb4BB78D537A67a245A7bEC64"],
[1301, "0x6999526e507Cc3b03b180BbE05E1Ff938259A874"],
[480, "0x09aea4b2242abC8bb4BB78D537A67a245A7bEC64"],
[324, "0xE0B015E54d54fc84a6cB9B666099c46adE9335FF"],
[7777777, "0x13fDac9F9b4777705db45291bbFF3c972c6d1d97"]
]);
const buildAcrossIntentComposable = async (baseParams, parameters, composabilityParams) => {
const { depositor, recipient, inputToken, outputToken, inputAmountRuntimeParams, approximateExpectedInputAmount, originChainId, destinationChainId, message, relayerAddress, gasLimit, pool = acrossSpokePool[originChainId], fees: fees_, metadata, lowerBoundTimestamp, upperBoundTimestamp, executionSimulationRetryDelay, simulationOverrides } = parameters;
if (destinationChainId === originChainId) {
throw new Error("Destination chain and origin should be different");
}
if (!pool) {
throw new Error("Across SpokePool seems not to be present on the origin chain");
}
const acrossIntentWrapperOnOrigin = _getAcrossIntentWrapper(originChainId);
const transferFromNexusToWrapperInstruction = await (0, buildTransfer_1.default)(baseParams, {
chainId: originChainId,
tokenAddress: inputToken,
amount: (0, composabilityCalls_1.runtimeERC20BalanceOf)(inputAmountRuntimeParams),
recipient: acrossIntentWrapperOnOrigin,
lowerBoundTimestamp,
upperBoundTimestamp,
executionSimulationRetryDelay,
simulationOverrides
}, composabilityParams);
const fees = fees_ ??
(await getAcrossSuggestedFees({
amount: approximateExpectedInputAmount,
originChainId,
inputToken,
destinationChainId,
outputToken
}));
const { outputAmount: approximateExpectedOutputAmount } = calculateAcrossFees({
fees,
amount: approximateExpectedInputAmount
});
const outputRatioPrecision = 10000n;
const outputRatio = (approximateExpectedOutputAmount * outputRatioPrecision) /
approximateExpectedInputAmount;
const outputRatioPacked = (0, viem_1.concatHex)([
(0, viem_1.padHex)(outputRatio.toString(16), { size: 16 }),
(0, viem_1.padHex)(outputRatioPrecision.toString(16), { size: 16 })
]);
const acrossSpokePoolWrapperAbi = (0, viem_1.parseAbi)([
"function depositV3Composable(address pool, address depositor, address recipient, address inputToken, address outputToken, uint256 inputAmount, uint256 outputRatioPacked, uint256 destinationChainId, address exclusiveRelayer, uint32 quoteTimestamp, uint32 fillDeadline, uint32 exclusivityDeadline, bytes calldata message) external payable"
]);
const { constraints } = inputAmountRuntimeParams;
const wrapperRuntimeBalance = (0, composabilityCalls_1.runtimeERC20BalanceOf)({
targetAddress: acrossIntentWrapperOnOrigin,
tokenAddress: inputAmountRuntimeParams.tokenAddress,
constraints: constraints ?? [(0, composabilityCalls_1.greaterThanOrEqualTo)(1n)]
});
const bridgeMetadata = [
{
type: "BRIDGE",
fromAddress: depositor,
toAddress: recipient,
fromTokenAddress: inputToken,
toTokenAddress: outputToken,
amount: "RUNTIME_VALUE",
fromChainId: originChainId,
toChainId: destinationChainId,
protocolNames: ["Across"]
}
];
const depositToPoolInstruction = await (0, buildComposable_1.buildComposableUtil)(baseParams, {
to: acrossIntentWrapperOnOrigin,
abi: acrossSpokePoolWrapperAbi,
functionName: "depositV3Composable",
args: [
pool,
depositor,
recipient,
inputToken,
outputToken,
wrapperRuntimeBalance,
outputRatioPacked,
destinationChainId,
relayerAddress ?? viem_1.zeroAddress,
Number(fees.timestamp),
Number(fees.fillDeadline),
0,
message ?? "0x"
],
chainId: originChainId,
gasLimit,
metadata: metadata || bridgeMetadata,
lowerBoundTimestamp,
upperBoundTimestamp,
executionSimulationRetryDelay,
simulationOverrides
}, composabilityParams);
return (0, buildBatch_1.default)(baseParams, {
instructions: [
...transferFromNexusToWrapperInstruction,
...depositToPoolInstruction
]
});
};
exports.buildAcrossIntentComposable = buildAcrossIntentComposable;
exports.default = exports.buildAcrossIntentComposable;
async function getAcrossSuggestedFees(parameters) {
const { inputToken, outputToken, originChainId, destinationChainId, amount, depositor, recipient, message, relayerAddress, referrer } = parameters;
const url = new URL("https://app.across.to/api/suggested-fees");
url.searchParams.append("inputToken", (0, viem_1.getAddress)(inputToken));
url.searchParams.append("outputToken", (0, viem_1.getAddress)(outputToken));
url.searchParams.append("originChainId", originChainId.toString());
url.searchParams.append("destinationChainId", destinationChainId.toString());
url.searchParams.append("amount", amount.toString());
if (depositor) {
url.searchParams.append("depositor", (0, viem_1.getAddress)(depositor));
}
if (recipient) {
url.searchParams.append("recipient", (0, viem_1.getAddress)(recipient));
}
if (message) {
url.searchParams.append("message", message);
}
if (relayerAddress) {
url.searchParams.append("relayerAddress", (0, viem_1.getAddress)(relayerAddress));
}
if (referrer) {
url.searchParams.append("referrer", (0, viem_1.getAddress)(referrer));
}
const response = await fetch(url.toString(), {
method: "GET",
headers: {
Accept: "application/json"
}
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}, message: ${response.statusText} <= with url: ${url.toString()}`);
}
const data = (await response.json());
return {
totalRelayFee: {
pct: BigInt(data.totalRelayFee.pct),
total: BigInt(data.totalRelayFee.total)
},
relayerCapitalFee: {
pct: BigInt(data.relayerCapitalFee.pct),
total: BigInt(data.relayerCapitalFee.total)
},
relayerGasFee: {
pct: BigInt(data.relayerGasFee.pct),
total: BigInt(data.relayerGasFee.total)
},
lpFee: {
pct: BigInt(data.lpFee.pct),
total: BigInt(data.lpFee.total)
},
timestamp: BigInt(data.timestamp),
isAmountTooLow: data.isAmountTooLow,
quoteBlock: BigInt(data.quoteBlock),
spokePoolAddress: (0, viem_1.getAddress)(data.spokePoolAddress),
fillDeadline: BigInt(data.fillDeadline),
limits: {
minDeposit: BigInt(data.limits.minDeposit),
maxDeposit: BigInt(data.limits.maxDeposit),
maxDepositInstant: BigInt(data.limits.maxDepositInstant),
maxDepositShortDelay: BigInt(data.limits.maxDepositShortDelay),
recommendedDepositInstant: BigInt(data.limits.recommendedDepositInstant)
}
};
}
function calculateAcrossFees(parameters) {
const { fees, amount } = parameters;
const PRECISION = 10n ** 18n;
const relayerFees = (amount * fees.totalRelayFee.pct) / PRECISION;
const lpFees = (amount * fees.lpFee.pct) / PRECISION;
const totalFees = relayerFees + lpFees;
const outputAmount = amount - totalFees;
return {
totalFees,
relayerFees,
lpFees,
outputAmount
};
}
function formatAcrossFeePercentage(pct) {
return (0, viem_1.formatUnits)(pct, 16);
}
const _getAcrossIntentWrapper = (chainId) => {
const acrossIntentWrapper = acrossIntentWrappers.get(chainId);
if (acrossIntentWrapper) {
return acrossIntentWrapper;
}
return defaultAcrossIntentWrapperAddress;
};
//# sourceMappingURL=buildAcrossIntentComposable.js.map