UNPKG

ox

Version:

Ethereum Standard Library

79 lines 3.37 kB
import { execTyped, isTupleRegex } from '../regex.js'; import { UnknownTypeError } from '../errors.js'; import { InvalidAbiTypeParameterError } from '../errors.js'; import { InvalidSignatureError, InvalidStructSignatureError, } from '../errors.js'; import { CircularReferenceError } from '../errors.js'; import { execStructSignature, isStructSignature } from './signatures.js'; import { isSolidityType, parseAbiParameter } from './utils.js'; export function parseStructs(signatures) { // Create "shallow" version of each struct (and filter out non-structs or invalid structs) const shallowStructs = {}; const signaturesLength = signatures.length; for (let i = 0; i < signaturesLength; i++) { const signature = signatures[i]; if (!isStructSignature(signature)) continue; const match = execStructSignature(signature); if (!match) throw new InvalidSignatureError({ signature, type: 'struct' }); const properties = match.properties.split(';'); const components = []; const propertiesLength = properties.length; for (let k = 0; k < propertiesLength; k++) { const property = properties[k]; const trimmed = property.trim(); if (!trimmed) continue; const abiParameter = parseAbiParameter(trimmed, { type: 'struct', }); components.push(abiParameter); } if (!components.length) throw new InvalidStructSignatureError({ signature }); shallowStructs[match.name] = components; } // Resolve nested structs inside each parameter const resolvedStructs = {}; const entries = Object.entries(shallowStructs); const entriesLength = entries.length; for (let i = 0; i < entriesLength; i++) { const [name, parameters] = entries[i]; resolvedStructs[name] = resolveStructs(parameters, shallowStructs); } return resolvedStructs; } const typeWithoutTupleRegex = /^(?<type>[a-zA-Z$_][a-zA-Z0-9$_]*)(?<array>(?:\[\d*?\])+?)?$/; function resolveStructs(abiParameters = [], structs = {}, ancestors = new Set()) { const components = []; const length = abiParameters.length; for (let i = 0; i < length; i++) { const abiParameter = abiParameters[i]; const isTuple = isTupleRegex.test(abiParameter.type); if (isTuple) components.push(abiParameter); else { const match = execTyped(typeWithoutTupleRegex, abiParameter.type); if (!match?.type) throw new InvalidAbiTypeParameterError({ abiParameter }); const { array, type } = match; if (type in structs) { if (ancestors.has(type)) throw new CircularReferenceError({ type }); components.push({ ...abiParameter, type: `tuple${array ?? ''}`, components: resolveStructs(structs[type], structs, new Set([...ancestors, type])), }); } else { if (isSolidityType(type)) components.push(abiParameter); else throw new UnknownTypeError({ type }); } } } return components; } //# sourceMappingURL=structs.js.map