UNPKG

@biconomy/abstractjs

Version:

SDK for Biconomy integration with support for account abstraction, smart accounts, ERC-4337.

296 lines 11.1 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getRuntimeValueLength = exports.getFunctionContextFromAbi = exports.encodeRuntimeFunctionData = exports.encodeAddress = void 0; const viem_1 = require("viem"); const composabilityCalls_1 = require("./composabilityCalls.js"); const integerRegex = /^(u?int)(8|16|24|32|40|48|56|64|72|80|88|96|104|112|120|128|136|144|152|160|168|176|184|192|200|208|216|224|232|240|248|256)?$/; const encodeString = (value) => { const hexValue = (0, viem_1.stringToHex)(value); const partsLength = Math.ceil((0, viem_1.size)(hexValue) / 32); const parts = []; for (let i = 0; i < partsLength; i++) { parts.push((0, viem_1.padHex)((0, viem_1.slice)(hexValue, i * 32, (i + 1) * 32), { dir: "right" })); } return { dynamic: true, data: [ (0, viem_1.concat)([(0, viem_1.padHex)((0, viem_1.numberToHex)((0, viem_1.size)(hexValue), { size: 32 })), ...parts]) ] }; }; const encodeBytes = (value, { param }) => { const [, paramSize] = param.type.split("bytes"); if ((0, composabilityCalls_1.isRuntimeComposableValue)(value)) { if (paramSize) { return { dynamic: false, data: [value] }; } const inputParamsLength = (0, exports.getRuntimeValueLength)(value.inputParams); const firstInputParam = { fetcherType: composabilityCalls_1.InputParamFetcherType.RAW_BYTES, paramData: (0, viem_1.numberToHex)(inputParamsLength, { size: 32 }), constraints: [] }; value.inputParams = [firstInputParam, ...value.inputParams]; return { dynamic: true, data: [value] }; } const bytesSize = (0, viem_1.size)(value); if (!paramSize) { let value_ = value; if (bytesSize % 32 !== 0) value_ = (0, viem_1.padHex)(value_, { dir: "right", size: Math.ceil((value.length - 2) / 2 / 32) * 32 }); return { dynamic: true, data: [(0, viem_1.padHex)((0, viem_1.numberToHex)(bytesSize, { size: 32 })), value_] }; } if (bytesSize !== Number.parseInt(paramSize)) throw new viem_1.AbiEncodingBytesSizeMismatchError({ expectedSize: Number.parseInt(paramSize), value: value }); return { dynamic: false, data: [(0, viem_1.padHex)(value, { dir: "right" })] }; }; const encodeNumber = (value, { signed, size = 256 }) => { if (typeof size === "number") { const max = BigInt(2) ** (BigInt(size) - (signed ? BigInt(1) : BigInt(0))) - BigInt(1); const min = signed ? -max - BigInt(1) : BigInt(0); if (value > max || value < min) throw new viem_1.IntegerOutOfRangeError({ max: max.toString(), min: min.toString(), signed, size: size / 8, value: value.toString() }); } return { dynamic: false, data: [ (0, viem_1.numberToHex)(value, { size: 32, signed }) ] }; }; const encodeBool = (value) => { if (typeof value !== "boolean") throw new viem_1.BaseError(`Invalid boolean value: "${value}" (type: ${typeof value}). Expected: \`true\` or \`false\`.`); return { dynamic: false, data: [(0, viem_1.padHex)((0, viem_1.boolToHex)(value))] }; }; const encodeAddress = (value) => { if (!(0, viem_1.isAddress)(value)) throw new viem_1.InvalidAddressError({ address: value }); return { dynamic: false, data: [(0, viem_1.padHex)(value.toLowerCase())] }; }; exports.encodeAddress = encodeAddress; const encodeArray = (value, { length, param }) => { const dynamic = length === null; if (!Array.isArray(value)) throw new viem_1.InvalidArrayError(value); if (!dynamic && value.length !== length) throw new viem_1.AbiEncodingArrayLengthMismatchError({ expectedLength: length, givenLength: value.length, type: `${param.type}[${length}]` }); let dynamicChild = false; const preparedParams = []; for (let i = 0; i < value.length; i++) { const preparedParam = prepareParam({ param, value: value[i] }); if (preparedParam.dynamic) dynamicChild = true; preparedParams.push(preparedParam); } if (dynamic || dynamicChild) { const data = encodeParams(preparedParams); if (dynamic) { const length = (0, viem_1.numberToHex)(preparedParams.length, { size: 32 }); return { dynamic: true, data: preparedParams.length > 0 ? [length, ...data] : [length] }; } if (dynamicChild) return { dynamic: true, data: data }; } const data = preparedParams.flatMap(({ data }) => data); return { dynamic: false, data: data }; }; const encodeTuple = (value, { param }) => { let dynamic = false; const preparedParams = []; for (let i = 0; i < param.components.length; i++) { const param_ = param.components[i]; const index = Array.isArray(value) ? i : param_.name; const preparedParam = prepareParam({ param: param_, value: value[index] }); preparedParams.push(preparedParam); if (preparedParam.dynamic) dynamic = true; } return { dynamic, data: dynamic ? encodeParams(preparedParams) : preparedParams.flatMap(({ data }) => data) }; }; const getArrayComponents = (type) => { const matches = type.match(/^(.*)\[(\d+)?\]$/); return matches ? [matches[2] ? Number(matches[2]) : null, matches[1]] : undefined; }; const encodeParams = (preparedParams) => { let staticSize = 0; for (let i = 0; i < preparedParams.length; i++) { const { dynamic, data } = preparedParams[i]; if (dynamic) { staticSize += 32; } else { const len = data.reduce((acc, val) => { if ((0, composabilityCalls_1.isRuntimeComposableValue)(val)) { const inputParamsLength = (0, exports.getRuntimeValueLength)(val.inputParams); return acc + inputParamsLength; } return acc + (0, viem_1.size)(val); }, 0); staticSize += len; } } const staticParams = []; const dynamicParams = []; let dynamicSize = 0; for (let i = 0; i < preparedParams.length; i++) { const { dynamic, data } = preparedParams[i]; if (dynamic) { staticParams.push((0, viem_1.numberToHex)(staticSize + dynamicSize, { size: 32 })); const len = data.reduce((acc, val) => { if ((0, composabilityCalls_1.isRuntimeComposableValue)(val)) { const inputParamsLength = (0, exports.getRuntimeValueLength)(val.inputParams); return acc + inputParamsLength; } return acc + (0, viem_1.size)(val); }, 0); dynamicParams.push(...data); dynamicSize += len; } else { staticParams.push(...data); } } return [...staticParams, ...dynamicParams]; }; const prepareParams = ({ params, values }) => { const preparedParams = []; for (let i = 0; i < params.length; i++) { preparedParams.push(prepareParam({ param: params[i], value: values[i] })); } return preparedParams; }; const prepareParam = ({ param, value }) => { const runtimeValue = { dynamic: false, data: [value] }; const arrayComponents = getArrayComponents(param.type); if (arrayComponents) { const [length, type] = arrayComponents; return encodeArray(value, { length, param: { ...param, type } }); } if (param.type === "address") { if ((0, composabilityCalls_1.isRuntimeComposableValue)(value)) return runtimeValue; return (0, exports.encodeAddress)(value); } if (param.type === "bool") { if ((0, composabilityCalls_1.isRuntimeComposableValue)(value)) return runtimeValue; return encodeBool(value); } if (param.type.startsWith("uint") || param.type.startsWith("int")) { if ((0, composabilityCalls_1.isRuntimeComposableValue)(value)) return runtimeValue; const signed = param.type.startsWith("int"); const [, , size = "256"] = integerRegex.exec(param.type) ?? []; return encodeNumber(value, { signed, size: Number(size) }); } if (param.type.startsWith("bytes")) { return encodeBytes(value, { param }); } if (param.type === "string") { if ((0, composabilityCalls_1.isRuntimeComposableValue)(value)) return runtimeValue; return encodeString(value); } if (param.type === "tuple") { return encodeTuple(value, { param: param }); } throw new viem_1.InvalidAbiEncodingTypeError(param.type, { docsPath: "/docs/contract/encodeAbiParameters" }); }; const encodeRuntimeFunctionData = (inputs, args) => { if (!inputs || inputs.length === 0) { return ["0x"]; } if (inputs.length !== args.length) { throw new viem_1.AbiEncodingLengthMismatchError({ expectedLength: inputs.length, givenLength: args.length }); } const preparedParams = prepareParams({ params: inputs, values: args }); const data = encodeParams(preparedParams); if (data.length === 0) return ["0x"]; return data; }; exports.encodeRuntimeFunctionData = encodeRuntimeFunctionData; const getFunctionContextFromAbi = (functionSig, abi) => { if (abi.length === 0) { throw new Error("Invalid ABI"); } const [functionInfo] = abi.filter((item) => item.type === "function" && item.name === functionSig); if (!functionInfo) { throw new Error(`${functionSig} not found on the ABI`); } const { inputs, name, outputs, stateMutability } = functionInfo; return { inputs, name, outputs, functionType: ["view", "pure"].includes(stateMutability) ? "read" : "write", functionSig: (0, viem_1.toFunctionSelector)(functionInfo) }; }; exports.getFunctionContextFromAbi = getFunctionContextFromAbi; const getRuntimeValueLength = (inputParams) => { return inputParams.reduce((acc, inputParam) => { if (inputParam.fetcherType === composabilityCalls_1.InputParamFetcherType.STATIC_CALL || inputParam.fetcherType === composabilityCalls_1.InputParamFetcherType.BALANCE) { return acc + 32; } return acc + (0, viem_1.size)(inputParam.paramData); }, 0); }; exports.getRuntimeValueLength = getRuntimeValueLength; //# sourceMappingURL=runtimeAbiEncoding.js.map