UNPKG

@uniswap/smart-wallet-sdk

Version:

⚒️ An SDK for building applications with smart wallets on Uniswap

102 lines 4.29 kB
import { concatHex, encodeFunctionData } from 'viem'; import abi from '../abis/MinimalDelegationEntry.json'; import { ModeType, getSmartWalletAddress } from './constants'; import { CallPlanner } from './utils'; import { BatchedCallPlanner } from './utils/batchedCallPlanner'; /** * Main SDK class for interacting with Uniswap smart wallet contracts */ export class SmartWallet { /** * Creates method parameters for a UserOperation to be executed through a smart wallet * @dev Compatible with EntryPoint versions v0.7.0 and v0.8.0 (not v0.6.0) * * @param calls Array of calls to encode * @param options Basic options for the execution * @returns Method parameters with userOp calldata and value */ static encodeUserOp(calls, options = {}) { const planner = new CallPlanner(calls); const batchedCallPlanner = new BatchedCallPlanner(planner, options.revertOnFailure); // UserOp callData format: executeUserOp selector (0x8dd7712f) + abi.encode(abi.encode(Call[]), revertOnFailure) // The EntryPoint recognizes this selector and calls executeUserOp(userOp, userOpHash) on the account. // The account then extracts the execution data from userOp.callData (slicing off the selector). // We manually concat the selector + encoded data rather than using encodeFunctionData because // the callData is not a standard ABI-encoded function call to executeUserOp. const EXECUTE_USER_OP_SELECTOR = '0x8dd7712f'; const calldata = concatHex([EXECUTE_USER_OP_SELECTOR, batchedCallPlanner.encode()]); return { calldata, value: planner.value, }; } /** * Creates method parameters for executing a simple batch of calls through a smart wallet * @param calls Array of calls to encode * @param options Basic options for the execution * @returns Method parameters with calldata and value */ static encodeBatchedCall(calls, options = {}) { const planner = new CallPlanner(calls); const batchedCallPlanner = new BatchedCallPlanner(planner, options.revertOnFailure); const encoded = encodeFunctionData({ abi, functionName: '0x99e1d016', // execute(((address,uint256,bytes)[],bool)) args: [batchedCallPlanner.toBatchedCall()], }); return { calldata: encoded, value: planner.value, }; } /** * ERC7821 compatible entrypoint for executing batched calls through the contract * @deprecated use encodeBatchedCall instead unless you need to use the ERC7821 entrypoint */ static encodeERC7821BatchedCall(calls, options = {}) { const mode = this.getModeFromOptions(options); if (mode != ModeType.BATCHED_CALL && mode != ModeType.BATCHED_CALL_CAN_REVERT) { throw new Error(`Invalid mode: ${mode}`); } const planner = new CallPlanner(calls); const executionData = planner.encode(); const encoded = this._encodeERC7821Execute(mode, executionData); return { calldata: encoded, value: planner.value, }; } /** * Creates a call to execute a method through a smart wallet * @dev can be refactored to return a Transaction object as well * @param methodParameters The method parameters to execute * @param chainId The chain ID for the smart wallet * @returns The call to execute */ static createExecute(methodParameters, chainId) { const address = getSmartWalletAddress(chainId); return { to: address, data: methodParameters.calldata, value: methodParameters.value, }; } /** * Get the mode type from the options */ static getModeFromOptions(options) { if (options.revertOnFailure) { return ModeType.BATCHED_CALL; } return ModeType.BATCHED_CALL_CAN_REVERT; } /** Internal methods */ static _encodeERC7821Execute(mode, data) { return encodeFunctionData({ abi, functionName: '0xe9ae5c53', // execute(bytes32,bytes) args: [mode, data], }); } } //# sourceMappingURL=smartWallet.js.map