UNPKG

ox

Version:

Ethereum Standard Library

87 lines (82 loc) 2.96 kB
import type { AbiEventParameter, AbiParameter } from 'abitype' import { execTyped } from './regex.js' import type { IsNarrowable, Join } from './types.js' import type { AssertName } from './types/signatures.js' /** * Formats `AbiParameter` to human-readable ABI parameter. * * @param abiParameter - ABI parameter * @returns Human-readable ABI parameter */ export type FormatAbiParameter< abiParameter extends AbiParameter | AbiEventParameter, > = abiParameter extends { name?: infer name extends string type: `tuple${infer array}` components: infer components extends readonly AbiParameter[] indexed?: infer indexed extends boolean } ? FormatAbiParameter< { type: `(${Join< { [key in keyof components]: FormatAbiParameter< { type: components[key]['type'] } & (IsNarrowable<components[key]['name'], string> extends true ? { name: components[key]['name'] } : unknown) & (components[key] extends { components: readonly AbiParameter[] } ? { components: components[key]['components'] } : unknown) > }, ', ' >})${array}` } & (IsNarrowable<name, string> extends true ? { name: name } : unknown) & (IsNarrowable<indexed, boolean> extends true ? { indexed: indexed } : unknown) > : `${abiParameter['type']}${abiParameter extends { indexed: true } ? ' indexed' : ''}${abiParameter['name'] extends infer name extends string ? name extends '' ? '' : ` ${AssertName<name>}` : ''}` // https://regexr.com/7f7rv const tupleRegex = /^tuple(?<array>(\[(\d*)\])*)$/ /** * Formats `AbiParameter` to human-readable ABI parameter. * * @param abiParameter - ABI parameter * @returns Human-readable ABI parameter */ export function formatAbiParameter< const abiParameter extends AbiParameter | AbiEventParameter, >(abiParameter: abiParameter): FormatAbiParameter<abiParameter> { type Result = FormatAbiParameter<abiParameter> let type = abiParameter.type if (tupleRegex.test(abiParameter.type) && 'components' in abiParameter) { type = '(' const length = abiParameter.components.length as number for (let i = 0; i < length; i++) { const component = abiParameter.components[i]! type += formatAbiParameter(component) if (i < length - 1) type += ', ' } const result = execTyped<{ array?: string }>(tupleRegex, abiParameter.type) type += `)${result?.array || ''}` return formatAbiParameter({ ...abiParameter, type, }) as Result } // Add `indexed` to type if in `abiParameter` if ('indexed' in abiParameter && abiParameter.indexed) type = `${type} indexed` // Return human-readable ABI parameter if (abiParameter.name) return `${type} ${abiParameter.name}` as Result return type as Result }