PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo/node_modules/ox/_esm/core/internal

Просмотр файла: abiParameters.js

import * as AbiParameters from '../AbiParameters.js';
import * as Address from '../Address.js';
import * as Bytes from '../Bytes.js';
import * as Errors from '../Errors.js';
import * as Hex from '../Hex.js';
import { integerRegex } from '../Solidity.js';
/** @internal */
export function decodeParameter(cursor, param, options) {
    const { checksumAddress, staticPosition } = options;
    const arrayComponents = getArrayComponents(param.type);
    if (arrayComponents) {
        const [length, type] = arrayComponents;
        return decodeArray(cursor, { ...param, type }, { checksumAddress, length, staticPosition });
    }
    if (param.type === 'tuple')
        return decodeTuple(cursor, param, {
            checksumAddress,
            staticPosition,
        });
    if (param.type === 'address')
        return decodeAddress(cursor, { checksum: checksumAddress });
    if (param.type === 'bool')
        return decodeBool(cursor);
    if (param.type.startsWith('bytes'))
        return decodeBytes(cursor, param, { staticPosition });
    if (param.type.startsWith('uint') || param.type.startsWith('int'))
        return decodeNumber(cursor, param);
    if (param.type === 'string')
        return decodeString(cursor, { staticPosition });
    throw new AbiParameters.InvalidTypeError(param.type);
}
const sizeOfLength = 32;
const sizeOfOffset = 32;
/** @internal */
export function decodeAddress(cursor, options = {}) {
    const { checksum = false } = options;
    const value = cursor.readBytes(32);
    const wrap = (address) => checksum ? Address.checksum(address) : address;
    return [wrap(Hex.fromBytes(Bytes.slice(value, -20))), 32];
}
/** @internal */
export function decodeArray(cursor, param, options) {
    const { checksumAddress, length, staticPosition } = options;
    // If the length of the array is not known in advance (dynamic array),
    // this means we will need to wonder off to the pointer and decode.
    if (!length) {
        // Dealing with a dynamic type, so get the offset of the array data.
        const offset = Bytes.toNumber(cursor.readBytes(sizeOfOffset));
        // Start is the static position of current slot + offset.
        const start = staticPosition + offset;
        const startOfData = start + sizeOfLength;
        // Get the length of the array from the offset.
        cursor.setPosition(start);
        const length = Bytes.toNumber(cursor.readBytes(sizeOfLength));
        // Check if the array has any dynamic children.
        const dynamicChild = hasDynamicChild(param);
        let consumed = 0;
        const value = [];
        for (let i = 0; i < length; ++i) {
            // If any of the children is dynamic, then all elements will be offset pointer, thus size of one slot (32 bytes).
            // Otherwise, elements will be the size of their encoding (consumed bytes).
            cursor.setPosition(startOfData + (dynamicChild ? i * 32 : consumed));
            const [data, consumed_] = decodeParameter(cursor, param, {
                checksumAddress,
                staticPosition: startOfData,
            });
            consumed += consumed_;
            value.push(data);
        }
        // As we have gone wondering, restore to the original position + next slot.
        cursor.setPosition(staticPosition + 32);
        return [value, 32];
    }
    // If the length of the array is known in advance,
    // and the length of an element deeply nested in the array is not known,
    // we need to decode the offset of the array data.
    if (hasDynamicChild(param)) {
        // Dealing with dynamic types, so get the offset of the array data.
        const offset = Bytes.toNumber(cursor.readBytes(sizeOfOffset));
        // Start is the static position of current slot + offset.
        const start = staticPosition + offset;
        const value = [];
        for (let i = 0; i < length; ++i) {
            // Move cursor along to the next slot (next offset pointer).
            cursor.setPosition(start + i * 32);
            const [data] = decodeParameter(cursor, param, {
                checksumAddress,
                staticPosition: start,
            });
            value.push(data);
        }
        // As we have gone wondering, restore to the original position + next slot.
        cursor.setPosition(staticPosition + 32);
        return [value, 32];
    }
    // If the length of the array is known in advance and the array is deeply static,
    // then we can just decode each element in sequence.
    let consumed = 0;
    const value = [];
    for (let i = 0; i < length; ++i) {
        const [data, consumed_] = decodeParameter(cursor, param, {
            checksumAddress,
            staticPosition: staticPosition + consumed,
        });
        consumed += consumed_;
        value.push(data);
    }
    return [value, consumed];
}
/** @internal */
export function decodeBool(cursor) {
    return [Bytes.toBoolean(cursor.readBytes(32), { size: 32 }), 32];
}
/** @internal */
export function decodeBytes(cursor, param, { staticPosition }) {
    const [_, size] = param.type.split('bytes');
    if (!size) {
        // Dealing with dynamic types, so get the offset of the bytes data.
        const offset = Bytes.toNumber(cursor.readBytes(32));
        // Set position of the cursor to start of bytes data.
        cursor.setPosition(staticPosition + offset);
        const length = Bytes.toNumber(cursor.readBytes(32));
        // If there is no length, we have zero data.
        if (length === 0) {
            // As we have gone wondering, restore to the original position + next slot.
            cursor.setPosition(staticPosition + 32);
            return ['0x', 32];
        }
        const data = cursor.readBytes(length);
        // As we have gone wondering, restore to the original position + next slot.
        cursor.setPosition(staticPosition + 32);
        return [Hex.fromBytes(data), 32];
    }
    const value = Hex.fromBytes(cursor.readBytes(Number.parseInt(size, 10), 32));
    return [value, 32];
}
/** @internal */
export function decodeNumber(cursor, param) {
    const signed = param.type.startsWith('int');
    const size = Number.parseInt(param.type.split('int')[1] || '256', 10);
    const value = cursor.readBytes(32);
    return [
        size > 48
            ? Bytes.toBigInt(value, { signed })
            : Bytes.toNumber(value, { signed }),
        32,
    ];
}
/** @internal */
export function decodeTuple(cursor, param, options) {
    const { checksumAddress, staticPosition } = options;
    // Tuples can have unnamed components (i.e. they are arrays), so we must
    // determine whether the tuple is named or unnamed. In the case of a named
    // tuple, the value will be an object where each property is the name of the
    // component. In the case of an unnamed tuple, the value will be an array.
    const hasUnnamedChild = param.components.length === 0 || param.components.some(({ name }) => !name);
    // Initialize the value to an object or an array, depending on whether the
    // tuple is named or unnamed.
    const value = hasUnnamedChild ? [] : {};
    let consumed = 0;
    // If the tuple has a dynamic child, we must first decode the offset to the
    // tuple data.
    if (hasDynamicChild(param)) {
        // Dealing with dynamic types, so get the offset of the tuple data.
        const offset = Bytes.toNumber(cursor.readBytes(sizeOfOffset));
        // Start is the static position of referencing slot + offset.
        const start = staticPosition + offset;
        for (let i = 0; i < param.components.length; ++i) {
            const component = param.components[i];
            cursor.setPosition(start + consumed);
            const [data, consumed_] = decodeParameter(cursor, component, {
                checksumAddress,
                staticPosition: start,
            });
            consumed += consumed_;
            value[hasUnnamedChild ? i : component?.name] = data;
        }
        // As we have gone wondering, restore to the original position + next slot.
        cursor.setPosition(staticPosition + 32);
        return [value, 32];
    }
    // If the tuple has static children, we can just decode each component
    // in sequence.
    for (let i = 0; i < param.components.length; ++i) {
        const component = param.components[i];
        const [data, consumed_] = decodeParameter(cursor, component, {
            checksumAddress,
            staticPosition,
        });
        value[hasUnnamedChild ? i : component?.name] = data;
        consumed += consumed_;
    }
    return [value, consumed];
}
/** @internal */
export function decodeString(cursor, { staticPosition }) {
    // Get offset to start of string data.
    const offset = Bytes.toNumber(cursor.readBytes(32));
    // Start is the static position of current slot + offset.
    const start = staticPosition + offset;
    cursor.setPosition(start);
    const length = Bytes.toNumber(cursor.readBytes(32));
    // If there is no length, we have zero data (empty string).
    if (length === 0) {
        cursor.setPosition(staticPosition + 32);
        return ['', 32];
    }
    const data = cursor.readBytes(length, 32);
    const value = Bytes.toString(Bytes.trimLeft(data));
    // As we have gone wondering, restore to the original position + next slot.
    cursor.setPosition(staticPosition + 32);
    return [value, 32];
}
/** @internal */
export function prepareParameters({ checksumAddress, parameters, values, }) {
    const preparedParameters = [];
    for (let i = 0; i < parameters.length; i++) {
        preparedParameters.push(prepareParameter({
            checksumAddress,
            parameter: parameters[i],
            value: values[i],
        }));
    }
    return preparedParameters;
}
/** @internal */
export function prepareParameter({ checksumAddress = false, parameter: parameter_, value, }) {
    const parameter = parameter_;
    const arrayComponents = getArrayComponents(parameter.type);
    if (arrayComponents) {
        const [length, type] = arrayComponents;
        return encodeArray(value, {
            checksumAddress,
            length,
            parameter: {
                ...parameter,
                type,
            },
        });
    }
    if (parameter.type === 'tuple') {
        return encodeTuple(value, {
            checksumAddress,
            parameter: parameter,
        });
    }
    if (parameter.type === 'address') {
        return encodeAddress(value, {
            checksum: checksumAddress,
        });
    }
    if (parameter.type === 'bool') {
        return encodeBoolean(value);
    }
    if (parameter.type.startsWith('uint') || parameter.type.startsWith('int')) {
        const signed = parameter.type.startsWith('int');
        const [, , size = '256'] = integerRegex.exec(parameter.type) ?? [];
        return encodeNumber(value, {
            signed,
            size: Number(size),
        });
    }
    if (parameter.type.startsWith('bytes')) {
        return encodeBytes(value, { type: parameter.type });
    }
    if (parameter.type === 'string') {
        return encodeString(value);
    }
    throw new AbiParameters.InvalidTypeError(parameter.type);
}
/** @internal */
export function encode(preparedParameters) {
    // 1. Compute the size of the static part of the parameters.
    let staticSize = 0;
    for (let i = 0; i < preparedParameters.length; i++) {
        const { dynamic, encoded } = preparedParameters[i];
        if (dynamic)
            staticSize += 32;
        else
            staticSize += Hex.size(encoded);
    }
    // 2. Split the parameters into static and dynamic parts.
    const staticParameters = [];
    const dynamicParameters = [];
    let dynamicSize = 0;
    for (let i = 0; i < preparedParameters.length; i++) {
        const { dynamic, encoded } = preparedParameters[i];
        if (dynamic) {
            staticParameters.push(Hex.fromNumber(staticSize + dynamicSize, { size: 32 }));
            dynamicParameters.push(encoded);
            dynamicSize += Hex.size(encoded);
        }
        else {
            staticParameters.push(encoded);
        }
    }
    // 3. Concatenate static and dynamic parts.
    return Hex.concat(...staticParameters, ...dynamicParameters);
}
/** @internal */
export function encodeAddress(value, options) {
    const { checksum = false } = options;
    Address.assert(value, { strict: checksum });
    return {
        dynamic: false,
        encoded: Hex.padLeft(value.toLowerCase()),
    };
}
/** @internal */
export function encodeArray(value, options) {
    const { checksumAddress, length, parameter } = options;
    const dynamic = length === null;
    if (!Array.isArray(value))
        throw new AbiParameters.InvalidArrayError(value);
    if (!dynamic && value.length !== length)
        throw new AbiParameters.ArrayLengthMismatchError({
            expectedLength: length,
            givenLength: value.length,
            type: `${parameter.type}[${length}]`,
        });
    let dynamicChild = false;
    const preparedParameters = [];
    for (let i = 0; i < value.length; i++) {
        const preparedParam = prepareParameter({
            checksumAddress,
            parameter,
            value: value[i],
        });
        if (preparedParam.dynamic)
            dynamicChild = true;
        preparedParameters.push(preparedParam);
    }
    if (dynamic || dynamicChild) {
        const data = encode(preparedParameters);
        if (dynamic) {
            const length = Hex.fromNumber(preparedParameters.length, { size: 32 });
            return {
                dynamic: true,
                encoded: preparedParameters.length > 0 ? Hex.concat(length, data) : length,
            };
        }
        if (dynamicChild)
            return { dynamic: true, encoded: data };
    }
    return {
        dynamic: false,
        encoded: Hex.concat(...preparedParameters.map(({ encoded }) => encoded)),
    };
}
/** @internal */
export function encodeBytes(value, { type }) {
    const [, parametersize] = type.split('bytes');
    const bytesSize = Hex.size(value);
    if (!parametersize) {
        let value_ = value;
        // If the size is not divisible by 32 bytes, pad the end
        // with empty bytes to the ceiling 32 bytes.
        if (bytesSize % 32 !== 0)
            value_ = Hex.padRight(value_, Math.ceil((value.length - 2) / 2 / 32) * 32);
        return {
            dynamic: true,
            encoded: Hex.concat(Hex.padLeft(Hex.fromNumber(bytesSize, { size: 32 })), value_),
        };
    }
    if (bytesSize !== Number.parseInt(parametersize, 10))
        throw new AbiParameters.BytesSizeMismatchError({
            expectedSize: Number.parseInt(parametersize, 10),
            value,
        });
    return { dynamic: false, encoded: Hex.padRight(value) };
}
/** @internal */
export function encodeBoolean(value) {
    if (typeof value !== 'boolean')
        throw new Errors.BaseError(`Invalid boolean value: "${value}" (type: ${typeof value}). Expected: \`true\` or \`false\`.`);
    return { dynamic: false, encoded: Hex.padLeft(Hex.fromBoolean(value)) };
}
/** @internal */
export function encodeNumber(value, { signed, size }) {
    if (typeof size === 'number') {
        const max = 2n ** (BigInt(size) - (signed ? 1n : 0n)) - 1n;
        const min = signed ? -max - 1n : 0n;
        if (value > max || value < min)
            throw new Hex.IntegerOutOfRangeError({
                max: max.toString(),
                min: min.toString(),
                signed,
                size: size / 8,
                value: value.toString(),
            });
    }
    return {
        dynamic: false,
        encoded: Hex.fromNumber(value, {
            size: 32,
            signed,
        }),
    };
}
/** @internal */
export function encodeString(value) {
    const hexValue = Hex.fromString(value);
    const partsLength = Math.ceil(Hex.size(hexValue) / 32);
    const parts = [];
    for (let i = 0; i < partsLength; i++) {
        parts.push(Hex.padRight(Hex.slice(hexValue, i * 32, (i + 1) * 32)));
    }
    return {
        dynamic: true,
        encoded: Hex.concat(Hex.padRight(Hex.fromNumber(Hex.size(hexValue), { size: 32 })), ...parts),
    };
}
/** @internal */
export function encodeTuple(value, options) {
    const { checksumAddress, parameter } = options;
    let dynamic = false;
    const preparedParameters = [];
    for (let i = 0; i < parameter.components.length; i++) {
        const param_ = parameter.components[i];
        const index = Array.isArray(value) ? i : param_.name;
        const preparedParam = prepareParameter({
            checksumAddress,
            parameter: param_,
            value: value[index],
        });
        preparedParameters.push(preparedParam);
        if (preparedParam.dynamic)
            dynamic = true;
    }
    return {
        dynamic,
        encoded: dynamic
            ? encode(preparedParameters)
            : Hex.concat(...preparedParameters.map(({ encoded }) => encoded)),
    };
}
/** @internal */
export function getArrayComponents(type) {
    const matches = type.match(/^(.*)\[(\d+)?\]$/);
    return matches
        ? // Return `null` if the array is dynamic.
            [matches[2] ? Number(matches[2]) : null, matches[1]]
        : undefined;
}
/** @internal */
export function hasDynamicChild(param) {
    const { type } = param;
    if (type === 'string')
        return true;
    if (type === 'bytes')
        return true;
    if (type.endsWith('[]'))
        return true;
    if (type === 'tuple')
        return param.components?.some(hasDynamicChild);
    const arrayComponents = getArrayComponents(param.type);
    if (arrayComponents &&
        hasDynamicChild({
            ...param,
            type: arrayComponents[1],
        }))
        return true;
    return false;
}
//# sourceMappingURL=abiParameters.js.map

Выполнить команду


Для локальной разработки. Не используйте в интернете!