ox
Version:
Ethereum Standard Library
79 lines • 3.37 kB
JavaScript
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