UNPKG

near-safe

Version:

An SDK for controlling Ethereum Smart Accounts via ERC4337 from a Near Account.

82 lines (81 loc) 3.55 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.MULTI_SEND_ABI = void 0; exports.encodeMulti = encodeMulti; exports.isMultisendTx = isMultisendTx; exports.decodeMulti = decodeMulti; const viem_1 = require("viem"); const types_1 = require("../types"); exports.MULTI_SEND_ABI = ["function multiSend(bytes memory transactions)"]; const MULTISEND_141 = "0x38869bf66a61cF6bDB996A6aE40D5853Fd43B526"; const MULTISEND_CALLONLY_141 = "0x9641d764fc13c8B624c04430C7356C1C7C8102e2"; /// Encodes the transaction as packed bytes of: /// - `operation` as a `uint8` with `0` for a `call` or `1` for a `delegatecall` (=> 1 byte), /// - `to` as an `address` (=> 20 bytes), /// - `value` as a `uint256` (=> 32 bytes), /// - length of `data` as a `uint256` (=> 32 bytes), /// - `data` as `bytes`. const encodeMetaTx = (tx) => (0, viem_1.encodePacked)(["uint8", "address", "uint256", "uint256", "bytes"], [ tx.operation || types_1.OperationType.Call, tx.to, BigInt(tx.value), BigInt((0, viem_1.size)(tx.data)), tx.data, ]); const remove0x = (hexString) => hexString.slice(2); // Encodes a batch of module transactions into a single multiSend module transaction. // A module transaction is an object with fields corresponding to a Gnosis Safe's (i.e., Zodiac IAvatar's) `execTransactionFromModule` method parameters. function encodeMulti(transactions, multiSendContractAddress = transactions.some((t) => t.operation === types_1.OperationType.DelegateCall) ? MULTISEND_141 : MULTISEND_CALLONLY_141) { const encodedTransactions = "0x" + transactions.map(encodeMetaTx).map(remove0x).join(""); return { operation: types_1.OperationType.DelegateCall, to: multiSendContractAddress, value: "0x00", data: (0, viem_1.encodeFunctionData)({ abi: (0, viem_1.parseAbi)(exports.MULTI_SEND_ABI), functionName: "multiSend", args: [encodedTransactions], }), }; } function isMultisendTx(args) { const to = args[0].toLowerCase(); return (to === MULTISEND_141.toLowerCase() || to === MULTISEND_CALLONLY_141.toLowerCase()); } function unpack(packed, startIndex) { // read operation from first 8 bits (= 2 hex digits) const operation = parseInt(packed.substring(startIndex, startIndex + 2), 16); // the next 40 characters are the to address const to = (0, viem_1.getAddress)(`0x${packed.substring(startIndex + 2, startIndex + 42)}`); // then comes the uint256 value (= 64 hex digits) const value = (0, viem_1.toHex)(BigInt(`0x${packed.substring(startIndex + 42, startIndex + 106)}`)); // and the uint256 data length (= 64 hex digits) const hexDataLength = parseInt(packed.substring(startIndex + 106, startIndex + 170), 16); const endIndex = startIndex + 170 + hexDataLength * 2; // * 2 because each hex item is represented with 2 digits const data = `0x${packed.substring(startIndex + 170, endIndex)}`; return { operation, to, value, data, endIndex, }; } function decodeMulti(data) { const tx = (0, viem_1.decodeFunctionData)({ abi: (0, viem_1.parseAbi)(exports.MULTI_SEND_ABI), data, }); const [transactionsEncoded] = tx.args; const result = []; let startIndex = 2; // skip over 0x while (startIndex < transactionsEncoded.length) { const { endIndex, ...tx } = unpack(transactionsEncoded, startIndex); result.push(tx); startIndex = endIndex; } return result; }