UNPKG

ox

Version:

Ethereum Standard Library

142 lines 5.6 kB
import * as Address from '../Address.js'; import * as Errors from '../Errors.js'; /** @internal */ export function normalizeSignature(signature) { let active = true; let current = ''; let level = 0; let result = ''; let valid = false; for (let i = 0; i < signature.length; i++) { const char = signature[i]; // If the character is a separator, we want to reactivate. if (['(', ')', ','].includes(char)) active = true; // If the character is a "level" token, we want to increment/decrement. if (char === '(') level++; if (char === ')') level--; // If we aren't active, we don't want to mutate the result. if (!active) continue; // If level === 0, we are at the definition level. if (level === 0) { if (char === ' ' && ['event', 'function', 'error', ''].includes(result)) result = ''; else { result += char; // If we are at the end of the definition, we must be finished. if (char === ')') { valid = true; break; } } continue; } // Ignore spaces if (char === ' ') { // If the previous character is a separator, and the current section isn't empty, we want to deactivate. if (signature[i - 1] !== ',' && current !== ',' && current !== ',(') { current = ''; active = false; } continue; } result += char; current += char; } if (!valid) throw new Errors.BaseError('Unable to normalize signature.'); return result; } /** * `(u)int<M>` regex: (un)signed integer type of `M` bits, `0 < M <= 256`, * `M % 8 == 0`. Hoisted to module scope; the prior literal at the call * site was recompiled per overload-resolution iteration. * * @internal */ const integerTypeRegex = /^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)?$/; /** * `bytes<M>` regex: binary type of `M` bytes, `0 < M <= 32`. * * @internal */ const fixedBytesTypeRegex = /^bytes([1-9]|1[0-9]|2[0-9]|3[0-2])?$/; /** * Fixed-length (`<type>[M]`) / dynamic (`<type>[]`) array regex. * * @internal */ const arrayTypeRegex = /[a-z]+[1-9]{0,3}(\[[0-9]{0,}\])+$/; /** * Strips a single trailing `[...]` array suffix from a type. * * @internal */ const arraySuffixStripRegex = /(\[[0-9]{0,}\])$/; /** @internal */ export function isArgOfType(arg, abiParameter) { const argType = typeof arg; const abiParameterType = abiParameter.type; switch (abiParameterType) { case 'address': return Address.validate(arg, { strict: false }); case 'bool': return argType === 'boolean'; case 'function': return argType === 'string'; case 'string': return argType === 'string'; default: { if (abiParameterType === 'tuple' && 'components' in abiParameter) return Object.values(abiParameter.components).every((component, index) => { return isArgOfType(Object.values(arg)[index], component); }); if (integerTypeRegex.test(abiParameterType)) return argType === 'number' || argType === 'bigint'; if (fixedBytesTypeRegex.test(abiParameterType)) return argType === 'string' || arg instanceof Uint8Array; if (arrayTypeRegex.test(abiParameterType)) { return (Array.isArray(arg) && arg.every((x) => isArgOfType(x, { ...abiParameter, // Pop off `[]` or `[M]` from end of type type: abiParameterType.replace(arraySuffixStripRegex, ''), }))); } return false; } } } /** @internal */ export function getAmbiguousTypes(sourceParameters, targetParameters, args) { // Indexed `for` loop instead of `for...in` (which iterates inherited // enumerable keys and is materially slower on arrays). for (let parameterIndex = 0; parameterIndex < sourceParameters.length; parameterIndex++) { const sourceParameter = sourceParameters[parameterIndex]; const targetParameter = targetParameters[parameterIndex]; if (sourceParameter.type === 'tuple' && targetParameter.type === 'tuple' && 'components' in sourceParameter && 'components' in targetParameter) return getAmbiguousTypes(sourceParameter.components, targetParameter.components, args[parameterIndex]); const sourceType = sourceParameter.type; const targetType = targetParameter.type; const arg = args[parameterIndex]; let ambiguous = false; if ((sourceType === 'address' && targetType === 'bytes20') || (sourceType === 'bytes20' && targetType === 'address')) ambiguous = true; else if ((sourceType === 'address' && targetType === 'string') || (sourceType === 'string' && targetType === 'address') || (sourceType === 'address' && targetType === 'bytes') || (sourceType === 'bytes' && targetType === 'address')) ambiguous = Address.validate(arg, { strict: false }); if (ambiguous) return [sourceType, targetType]; } return; } //# sourceMappingURL=abiItem.js.map