PHP WebShell

Текущая директория: /opt/BitGoJS/node_modules/micro-eth-signer/lib

Просмотр файла: tx-validator.js

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateFields = exports.validateField = exports.createTxMapFromFields = exports.parseUnit = void 0;
const index_js_1 = require("./index.js");
const formatters_js_1 = require("./formatters.js");
const GWEI_PRECISION = 9;
const ETHER_PRECISION = 18;
const GWEI = 10n ** BigInt(GWEI_PRECISION);
const ETHER = 10n ** BigInt(ETHER_PRECISION);
// const MICROETH = 10n ** 12n;
const MAX_AMOUNT = ETHER * 100000000n; // 100m ether
const MAX_GAS_PRICE = Number(GWEI * 10000n); // 10,000 gwei. Arbitrage HFT bots can use more.
// etherscan.io/chart/gasprice
const MIN_GAS_LIMIT = 21000;
const MAX_GAS_LIMIT = 20000000; // 20m wei. It's dynamic; a block limit in 2021 is 12m.
const MAX_NONCE = 10000000; // 10M
const MAX_DATA_SIZE = 10000000;
function minmax(val, min, max, err) {
    if (!err)
        err = `>= ${min} and <= ${max}`;
    if (Number.isNaN(val) || val < min || val > max)
        throw new Error(`Must be ${err}`);
    return true;
}
function ensureNot16x(val, isBig = false) {
    if (typeof val === 'string' && val.startsWith('0x')) {
        return isBig ? BigInt(val) : Number.parseInt(val, 16);
    }
    return val;
}
const checks = {
    nonce(num) {
        return minmax(num, 0, MAX_NONCE);
    },
    maxFeePerGas(num) {
        return minmax(num, 1, MAX_GAS_PRICE, '>= 1 wei and < 10000 gwei');
    },
    maxPriorityFeePerGas(num) {
        return minmax(num, 0, MAX_GAS_PRICE, '>= 1 wei and < 10000 gwei');
    },
    gasLimit(num) {
        return minmax(num, MIN_GAS_LIMIT, MAX_GAS_LIMIT);
    },
    to(addr) {
        if (addr.length !== 40 && addr.length !== 42)
            throw new Error('Address length must be 40 or 42 symbols');
        addr = (0, index_js_1.add0x)(addr);
        if (!/^0x[0-9a-f]+$/i.test(addr))
            throw new Error('Address must be hex');
        if (!index_js_1.Address.verifyChecksum(addr))
            throw new Error('Address checksum does not match');
        return true;
    },
    value(num) {
        return minmax(num, 0n, MAX_AMOUNT, '>= 0 and < 100M eth');
    },
    data(val) {
        if (typeof val === 'string' && val.length > MAX_DATA_SIZE)
            throw new Error('Data is too big');
        return true;
    },
    chainId(num) {
        if (!num)
            return true;
        return minmax(num, 1, 2 ** 32 - 1, '>= 1 and <= 2**32-1');
    },
};
function parseHex(val) {
    if (val === '0x')
        val = '0x00';
    return Number.parseInt(val, 16);
}
function parseUnit(val, unit) {
    const str = ensureNot16x(val, true).toString();
    if (unit === 'wei')
        return BigInt(str);
    let precision;
    if (unit === 'gwei')
        precision = GWEI_PRECISION;
    else if (unit === 'eth')
        precision = ETHER_PRECISION;
    else
        throw new Error(`Wrong unit name: ${unit}`);
    return (0, formatters_js_1.parseDecimal)(str, precision);
}
exports.parseUnit = parseUnit;
// Raw transaction to humanized
const r2h = {
    nonce: parseHex,
    maxFeePerGas: parseHex,
    gasLimit: parseHex,
    to: (val) => index_js_1.Address.checksum(val),
    value: (val) => BigInt(val),
    data: (val) => val,
    chainId: (val) => (val ? parseHex(val) : 1),
};
// Humanized to raw.
const h2r = {
    nonce(val) {
        return Number.parseInt(ensureNot16x(val).toString());
    },
    maxFeePerGas(val, opts) {
        return parseUnit(val, (opts && opts.maxFeePerGasUnit) || 'gwei');
    },
    maxPriorityFeePerGas(val, opts) {
        return parseUnit(val, (opts && opts.maxPriorityFeePerGasUnit) || 'gwei');
    },
    gasLimit(val) {
        return Number.parseInt(ensureNot16x(val).toString()) || MIN_GAS_LIMIT;
    },
    to(val, opts) {
        if (opts && opts.from && opts.from === val)
            throw new Error('Must differ from sender address');
        return val;
    },
    value(val, opts) {
        return parseUnit(val, (opts && opts.amountUnit) || 'eth');
    },
    data(val) {
        return val || '';
    },
    chainId(val) {
        return Number.parseInt(val) || 1;
    },
};
function hasOwnProperty(obj, prop) {
    return obj.hasOwnProperty(prop);
}
function numberToHexUnpadded(num) {
    let hex = num.toString(16);
    hex = hex.length & 1 ? `0${hex}` : hex;
    return hex;
}
function dataToString(snb) {
    if (snb == null)
        return '';
    if (typeof snb === 'string')
        return snb;
    if (typeof snb === 'number' || typeof snb === 'bigint')
        return numberToHexUnpadded(snb);
    throw new Error('Invalid type');
}
class TransactionFieldError extends Error {
    constructor(message, errors) {
        super(message + '. ' + JSON.stringify(errors));
        this.errors = errors;
    }
}
const requiredFields = ['maxFeePerGas', 'maxPriorityFeePerGas', 'to', 'value', 'nonce'];
const optionFields = {
    value: ['amountUnit'],
    to: ['from'],
    maxFeePerGas: ['maxFeePerGasUnit'],
    maxPriorityFeePerGas: ['maxPriorityFeePerGasUnit'],
    chainId: [],
};
const allOptionFields = Object.values(optionFields).flat();
function createTxMapFromFields(fields) {
    // prettier-ignore
    const normalized = {};
    const errors = {};
    requiredFields.forEach((f) => {
        if (fields[f] == null)
            errors[f] = 'Cannot be empty';
    });
    Object.keys(fields).forEach((f) => {
        if (allOptionFields.includes(f))
            return;
        const field = f;
        const opts = {};
        if (hasOwnProperty(optionFields, field)) {
            const list = optionFields[field];
            for (const optionalField of list) {
                const ofVal = fields[optionalField];
                if (ofVal != null)
                    opts[optionalField] = ofVal;
            }
        }
        const val = fields[field];
        try {
            const normVal = h2r[field](val, opts);
            // @ts-ignore
            checks[field](normVal);
            normalized[field] = dataToString(normVal);
        }
        catch (error) {
            errors[field] = error.messages || error.message;
        }
    });
    if (Object.keys(errors).length)
        throw new TransactionFieldError('Invalid transaction', errors);
    Object.keys(normalized).forEach((f) => {
        const field = f;
        if (field === 'accessList')
            return;
        normalized[field] = (0, index_js_1.add0x)(normalized[field]);
    });
    const raw = Object.assign({
        nonce: '0x',
        to: '0x',
        value: '0x',
        gasLimit: '0x5208',
        maxFeePerGas: '0x',
        data: '0x',
        v: '0x',
        r: '0x',
        s: '0x',
        chainId: 1,
    }, normalized);
    return raw;
}
exports.createTxMapFromFields = createTxMapFromFields;
function validateField(field, val, opts) {
    const normVal = h2r[field](val, opts);
    // @ts-ignore
    checks[field](normVal);
    return dataToString(normVal);
}
exports.validateField = validateField;
function validateFields(raw) {
    Object.keys(raw).forEach((f) => {
        const field = f;
        if (field === 'accessList')
            return;
        const fn = r2h[field];
        if (typeof fn === 'function') {
            const value = raw[field];
            const normVal = fn(value || '');
            checks[field](normVal);
        }
    });
}
exports.validateFields = validateFields;

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


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