import { type AbiFunction, type ParseAbiItem, parseAbiItem } from "abitype"; import { toFunctionSelector } from "viem"; import { LruMap } from "../caching/lru.js"; import type { Hex } from "../encoding/hex.js"; import { stringify } from "../json.js"; type ParseMethod = // if the method IS an AbiFunction, return it method extends AbiFunction ? method : method extends `function ${string}` ? ParseAbiItem extends AbiFunction ? ParseAbiItem : never : never; export type PreparedMethod = // ["fn signature", "inputs", "outputs"] [Hex, ParseMethod["inputs"], ParseMethod["outputs"]]; const prepareMethodCache = new LruMap>(4096); /** * Prepares a method for usage by converting it into a prepared method object. * @param method The method to prepare. * @returns The prepared method object. * @example * ```ts * import { prepareMethod } from "thirdweb/utils"; * const method = "function transfer(address to, uint256 value)"; * const preparedMethod = prepareMethod(method); * ``` * @contract */ export function prepareMethod< const TMethod extends AbiFunction | `function ${string}`, >(method: TMethod): PreparedMethod { const key = typeof method === "string" ? method : stringify(method); if (prepareMethodCache.has(key)) { return prepareMethodCache.get(key) as PreparedMethod; } type ParsedAbiFn = ParseMethod; const abiFn = typeof method === "string" ? // @ts-expect-error - we're sure it's a string... (parseAbiItem(method) as ParsedAbiFn) : (method as ParsedAbiFn); // encode the method signature const sig = toFunctionSelector(abiFn); const ret: PreparedMethod = [sig, abiFn.inputs, abiFn.outputs]; prepareMethodCache.set(key, ret); return ret; }