@biconomy/abstractjs
Version:
SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.
99 lines • 4.79 kB
JavaScript
import { resolveInstructions } from "../../utils/index.js";
/**
* Builds a batch of instructions for a single userOp to be included in a supertransaction
* UserOps must be on the same chain for the batch to be valid
* If a composable call is passed to this method, this call should already be built via
* one of the buildComposable methods.
* @param baseParams - Base parameters for the instruction
* @param parameters - Parameters for the batch instruction
* @param parameters.instructions - Instructions to be executed in the batch
* @returns The built instruction
*
* @example
* ```typescript
* const instructions = await buildBatch(
* { accountAddress: '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' },
* { instructions: [buildApprove, buildSwap] }
* )
* ```
*/
export const buildBatch = async (baseParams, parameters) => {
const { currentInstructions = [] } = baseParams;
const { instructions } = parameters;
if (instructions.length < 2) {
throw new Error("A Batch must contain at least 2 instructions");
}
const resolvedInstructions = await resolveInstructions(instructions);
let maxTimeWindow = 0;
let maxExecutionSimulationRetryDelay = 0;
let finalLowerBoundTimestamp = 0;
let finalUpperBoundTimestamp = 0;
const customOverrides = [];
const tokenOverrides = [];
for (const { lowerBoundTimestamp, upperBoundTimestamp, executionSimulationRetryDelay, simulationOverrides } of resolvedInstructions) {
if (executionSimulationRetryDelay !== undefined) {
// The last defined max executionSimulationRetryDelay will be considered
const isMax = executionSimulationRetryDelay >= maxExecutionSimulationRetryDelay;
if (isMax) {
maxExecutionSimulationRetryDelay = executionSimulationRetryDelay;
}
}
if (lowerBoundTimestamp !== undefined &&
upperBoundTimestamp !== undefined) {
if (upperBoundTimestamp <= lowerBoundTimestamp) {
throw new Error("Invalid lowerbound and upperbound timestamps.");
}
const timeWindow = upperBoundTimestamp - lowerBoundTimestamp;
// The last defined max execution window will be considered
const isMax = timeWindow >= maxTimeWindow;
if (isMax) {
maxTimeWindow = timeWindow;
finalLowerBoundTimestamp = lowerBoundTimestamp;
finalUpperBoundTimestamp = upperBoundTimestamp;
}
}
if (simulationOverrides !== undefined) {
if (simulationOverrides.customOverrides !== undefined) {
customOverrides.push(...simulationOverrides.customOverrides);
}
if (simulationOverrides.tokenOverrides !== undefined) {
tokenOverrides.push(...simulationOverrides.tokenOverrides);
}
}
}
if (resolvedInstructions.some(({ chainId }) => Number(chainId) !== Number(resolvedInstructions[0].chainId))) {
throw new Error("All instructions must be on the same chain");
}
const isComposable = resolvedInstructions.some(({ isComposable }) => isComposable === true);
// If any one instruction in a batch is composable, every other instructions should follow composable encoding.
if (!resolvedInstructions.every((inx) => !!inx.isComposable === !!isComposable)) {
throw new Error(`${isComposable ? "All the instructions must be built with buildComposable in order to support the runtime time parameters." : "All the instructions must be non composable when there are no runtime parameters"}`);
}
const calls = resolvedInstructions.flatMap(({ calls }) => calls);
const metadata = resolvedInstructions.flatMap(({ metadata }) => metadata || []);
return [
...currentInstructions,
{
calls: isComposable
? calls
: calls,
chainId: resolvedInstructions[0].chainId, // Batch instructions must be on the same chain
isComposable,
metadata,
...(finalLowerBoundTimestamp !== 0
? { lowerBoundTimestamp: finalLowerBoundTimestamp }
: {}),
...(finalUpperBoundTimestamp !== 0
? { upperBoundTimestamp: finalUpperBoundTimestamp }
: {}),
...(maxExecutionSimulationRetryDelay !== 0
? { executionSimulationRetryDelay: maxExecutionSimulationRetryDelay }
: {}),
...(tokenOverrides.length > 0 || customOverrides.length > 0
? { simulationOverrides: { tokenOverrides, customOverrides } }
: {})
}
];
};
export default buildBatch;
//# sourceMappingURL=buildBatch.js.map