@exromany/lido-csm-sdk
Version:
[](https://github.com/lidofinance/lido-csm-sdk/blob/main/LICENSE.txt) [](h
167 lines • 6.74 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateDepositDataSync = exports.validateDepositData = void 0;
const compare_lowercase_js_1 = require("../common/utils/compare-lowercase.js");
const index_js_1 = require("../common/utils/index.js");
const types_js_1 = require("./types.js");
const constants_js_1 = require("./constants.js");
const signature_js_1 = require("./signature.js");
const validateBasicFields = (data, index, config) => {
const errors = [];
if (!(0, index_js_1.isHexadecimalString)(data.pubkey, constants_js_1.PUBKEY_LENGTH)) {
errors.push({
index,
field: 'pubkey',
message: 'pubkey is not valid string',
code: types_js_1.ValidationErrorCode.INVALID_PUBKEY,
});
}
if (!(0, index_js_1.isHexadecimalString)(data.signature, constants_js_1.SIGNATURE_LENGTH)) {
errors.push({
index,
field: 'signature',
message: 'signature is not valid string',
code: types_js_1.ValidationErrorCode.INVALID_SIGNATURE,
});
}
if (!(0, index_js_1.isHexadecimalString)(data.deposit_message_root, constants_js_1.DEPOSIT_ROOT_LENGTH)) {
errors.push({
index,
field: 'deposit_message_root',
message: 'deposit_message_root is not a valid string',
code: types_js_1.ValidationErrorCode.INVALID_DEPOSIT_ROOT,
});
}
if (!(0, index_js_1.isHexadecimalString)(data.deposit_data_root, constants_js_1.DEPOSIT_ROOT_LENGTH)) {
errors.push({
index,
field: 'deposit_data_root',
message: 'deposit_data_root is not a valid string',
code: types_js_1.ValidationErrorCode.INVALID_DEPOSIT_ROOT,
});
}
if (!(0, index_js_1.isHexadecimalString)(data.withdrawal_credentials, constants_js_1.WITHDRAWAL_CREDENTIALS_LENGTH)) {
errors.push({
index,
field: 'withdrawal_credentials',
message: 'withdrawal_credentials is not a valid string',
code: types_js_1.ValidationErrorCode.INVALID_WITHDRAWAL_CREDENTIALS,
});
}
else if (!(0, compare_lowercase_js_1.compareLowercase)((0, index_js_1.trimHexPrefix)(data.withdrawal_credentials), `${constants_js_1.FIXED_WC_PREFIX}${(0, index_js_1.trimHexPrefix)(config.withdrawalCredentials)}`) &&
!(0, compare_lowercase_js_1.compareLowercase)((0, index_js_1.trimHexPrefix)(data.withdrawal_credentials), (0, index_js_1.trimHexPrefix)(config.withdrawalCredentials))) {
errors.push({
index,
field: 'withdrawal_credentials',
message: `withdrawal_credentials is not the Lido Withdrawal Vault`,
code: types_js_1.ValidationErrorCode.INVALID_WITHDRAWAL_CREDENTIALS,
});
}
if (data.amount !== constants_js_1.FIXED_AMOUNT) {
errors.push({
index,
field: 'amount',
message: 'amount is not equal to 32 eth',
code: types_js_1.ValidationErrorCode.INVALID_AMOUNT,
});
}
const requiredNetworkName = constants_js_1.FIXED_NETWORK[config.chainId];
const networkName = data.network_name ||
data.eth2_network_name;
if (!(networkName === requiredNetworkName)) {
errors.push({
index,
field: 'network_name',
message: `network_name or eth2_network_name is not equal to ${requiredNetworkName}`,
code: types_js_1.ValidationErrorCode.INVALID_NETWORK,
});
}
const forkVersion = constants_js_1.FIXED_FORK_VERSION[config.chainId];
if (data.fork_version !== forkVersion) {
errors.push({
index,
field: 'fork_version',
message: `fork_version is not equal to ${forkVersion}`,
code: types_js_1.ValidationErrorCode.INVALID_FORK_VERSION,
});
}
return errors;
};
const processDuplicatePubkey = (config) => {
const existingIndices = config.pubkeyMap.get(config.pubkey);
if (!existingIndices) {
config.pubkeyMap.set(config.pubkey, [config.index]);
return;
}
existingIndices.push(config.index);
existingIndices.forEach((idx) => {
const hasExistingError = config.errors.some((e) => e.index === idx && e.code === types_js_1.ValidationErrorCode.DUPLICATE_PUBKEY);
if (hasExistingError) {
return;
}
config.errors.push({
index: idx,
field: 'pubkey',
message: 'pubkey is duplicated in deposit data',
code: types_js_1.ValidationErrorCode.DUPLICATE_PUBKEY,
});
});
};
const performBasicValidation = (depositData, config) => {
const errors = [];
const pubkeyMap = new Map();
for (const [i, data] of depositData.entries()) {
if (!data) {
errors.push({
index: i,
message: 'deposit data item is missing',
code: types_js_1.ValidationErrorCode.MISSING_FIELD,
});
continue;
}
const basicErrors = validateBasicFields(data, i, config);
errors.push(...basicErrors);
const pubkey = data.pubkey?.toLowerCase();
if (pubkey) {
processDuplicatePubkey({
pubkey,
index: i,
pubkeyMap,
errors,
});
}
}
return errors;
};
const validateDepositData = async (depositData, options) => {
const errors = performBasicValidation(depositData, {
chainId: options.chainId,
withdrawalCredentials: options.withdrawalCredentials,
});
const signatureVerificationPromises = depositData.map((data, index) => {
if (!data) {
return Promise.resolve({ index, isValid: false });
}
return (0, signature_js_1.verifyDepositSignature)(data, options.chainId)
.then((isValid) => ({ index, isValid }))
.catch(() => ({ index, isValid: false }));
});
const signatureResults = await Promise.all(signatureVerificationPromises);
signatureResults.forEach(({ index, isValid }) => {
if (!isValid) {
errors.push({
index,
field: 'signature',
message: 'invalid signature',
code: types_js_1.ValidationErrorCode.INVALID_BLS_SIGNATURE,
});
}
});
return errors;
};
exports.validateDepositData = validateDepositData;
const validateDepositDataSync = (depositData, config) => {
return performBasicValidation(depositData, config);
};
exports.validateDepositDataSync = validateDepositDataSync;
//# sourceMappingURL=validator.js.map