ваше сообщение коммита

This commit is contained in:
2025-12-30 23:43:54 +03:00
parent 546e92ffb2
commit ea059565f9
15 changed files with 1975 additions and 302 deletions

View File

@@ -53,10 +53,89 @@ export function useProposalValidation() {
errors.push('Отсутствует описание предложения');
}
if (!proposal.transactionHash) {
errors.push('Отсутствует хеш транзакции');
} else if (!isValidTransactionHash(proposal.transactionHash)) {
errors.push('Неверный формат хеша транзакции');
// Для мультичейн предложений проверяем chains
// Если есть chains массив (даже с одним элементом), используем валидацию через chains
const hasChains = proposal.chains && Array.isArray(proposal.chains) && proposal.chains.length > 0;
if (hasChains) {
// Для мультичейн предложений проверяем, что есть хотя бы одна валидная цепочка
if (proposal.chains.length === 0) {
errors.push('Мультичейн предложение не содержит цепочек');
} else {
// Проверяем каждую цепочку
let validChainsCount = 0;
proposal.chains.forEach((chain, chainIndex) => {
const chainErrors = [];
if (!chain.id && chain.id !== 0) {
chainErrors.push(`Цепочка ${chainIndex}: отсутствует ID`);
}
if (!chain.chainId) {
chainErrors.push(`Цепочка ${chainIndex}: отсутствует chainId`);
} else if (!isValidChainId(chain.chainId)) {
chainErrors.push(`Цепочка ${chainIndex}: неподдерживаемый chainId ${chain.chainId}`);
}
if (!chain.transactionHash) {
chainErrors.push(`Цепочка ${chainIndex}: отсутствует хеш транзакции`);
} else if (!isValidTransactionHash(chain.transactionHash)) {
chainErrors.push(`Цепочка ${chainIndex}: неверный формат хеша транзакции`);
}
if (chain.state === undefined || chain.state === null) {
chainErrors.push(`Цепочка ${chainIndex}: отсутствует статус`);
}
if (typeof chain.forVotes !== 'number' || chain.forVotes < 0) {
chainErrors.push(`Цепочка ${chainIndex}: неверное значение голосов "за"`);
}
if (typeof chain.againstVotes !== 'number' || chain.againstVotes < 0) {
chainErrors.push(`Цепочка ${chainIndex}: неверное значение голосов "против"`);
}
if (typeof chain.quorumRequired !== 'number' || chain.quorumRequired < 0) {
chainErrors.push(`Цепочка ${chainIndex}: неверное значение требуемого кворума`);
}
if (chainErrors.length === 0) {
validChainsCount++;
} else {
errors.push(...chainErrors);
}
});
if (validChainsCount === 0) {
errors.push('Мультичейн предложение не содержит валидных цепочек');
}
}
} else {
// Для одиночных предложений проверяем стандартные поля
if (!proposal.transactionHash) {
errors.push('Отсутствует хеш транзакции');
} else if (!isValidTransactionHash(proposal.transactionHash)) {
errors.push('Неверный формат хеша транзакции');
}
if (!proposal.chainId) {
errors.push('Отсутствует chainId');
} else if (!isValidChainId(proposal.chainId)) {
errors.push('Неподдерживаемый chainId');
}
// Проверка числовых значений для одиночных предложений
if (typeof proposal.forVotes !== 'number' || proposal.forVotes < 0) {
errors.push('Неверное значение голосов "за"');
}
if (typeof proposal.againstVotes !== 'number' || proposal.againstVotes < 0) {
errors.push('Неверное значение голосов "против"');
}
if (typeof proposal.quorumRequired !== 'number' || proposal.quorumRequired < 0) {
errors.push('Неверное значение требуемого кворума');
}
}
if (!proposal.initiator) {
@@ -65,29 +144,10 @@ export function useProposalValidation() {
errors.push('Неверный формат адреса инициатора');
}
if (!proposal.chainId) {
errors.push('Отсутствует chainId');
} else if (!isValidChainId(proposal.chainId)) {
errors.push('Неподдерживаемый chainId');
}
if (proposal.state === undefined || proposal.state === null) {
errors.push('Отсутствует статус предложения');
}
// Проверка числовых значений
if (typeof proposal.forVotes !== 'number' || proposal.forVotes < 0) {
errors.push('Неверное значение голосов "за"');
}
if (typeof proposal.againstVotes !== 'number' || proposal.againstVotes < 0) {
errors.push('Неверное значение голосов "против"');
}
if (typeof proposal.quorumRequired !== 'number' || proposal.quorumRequired < 0) {
errors.push('Неверное значение требуемого кворума');
}
return {
isValid: errors.length === 0,
errors
@@ -112,6 +172,9 @@ export function useProposalValidation() {
allErrors.push({
proposalIndex: index,
proposalId: proposal.id,
description: proposal.description,
hasChains: !!(proposal.chains && Array.isArray(proposal.chains)),
chainsCount: proposal.chains?.length || 0,
errors: validation.errors
});
}
@@ -124,6 +187,18 @@ export function useProposalValidation() {
console.log(`[Proposal Validation] Проверено предложений: ${proposals.length}`);
console.log(`[Proposal Validation] Валидных: ${validProposals.length}`);
console.log(`[Proposal Validation] С ошибками: ${allErrors.length}`);
// Логируем ошибки для отладки
if (allErrors.length > 0) {
console.log(`[Proposal Validation] Детали ошибок:`, allErrors);
allErrors.forEach((error, idx) => {
console.log(`[Proposal Validation] Предложение ${idx + 1} (ID: ${error.proposalId}, описание: "${error.description || 'N/A'}"):`, {
hasChains: error.hasChains,
chainsCount: error.chainsCount,
errors: error.errors
});
});
}
return {
validProposals,
@@ -150,24 +225,37 @@ export function useProposalValidation() {
});
// Проверка, является ли предложение реальным (на основе хеша транзакции)
// Важно: после группировки мультичейн-предложений хеши транзакций могут жить только в proposal.chains[].transactionHash,
// поэтому проверяем и верхний уровень, и цепочки.
const isRealProposal = (proposal) => {
if (!proposal.transactionHash) return false;
// Проверяем, что хеш имеет правильный формат
if (!isValidTransactionHash(proposal.transactionHash)) return false;
// Проверяем, что это не тестовые/фейковые хеши
const fakeHashes = [
'0x0000000000000000000000000000000000000000000000000000000000000000',
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
];
if (fakeHashes.includes(proposal.transactionHash.toLowerCase())) return false;
// Проверяем, что хеш не начинается с нулей (подозрительно)
if (proposal.transactionHash.startsWith('0x0000')) return false;
return true;
const isRealTxHash = (txHash) => {
if (!txHash || typeof txHash !== 'string') return false;
// Проверяем, что хеш имеет правильный формат
if (!isValidTransactionHash(txHash)) return false;
const lower = txHash.toLowerCase();
// Проверяем, что это не тестовые/фейковые хеши
const fakeHashes = [
'0x0000000000000000000000000000000000000000000000000000000000000000',
'0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
];
if (fakeHashes.includes(lower)) return false;
return true;
};
// 1) Одиночные предложения (или если бэкенд положил хеш на верхний уровень)
if (isRealTxHash(proposal?.transactionHash)) return true;
// 2) Сгруппированные предложения: проверяем любую цепочку
if (proposal?.chains && Array.isArray(proposal.chains) && proposal.chains.length > 0) {
return proposal.chains.some(chain => isRealTxHash(chain?.transactionHash));
}
return false;
};
// Фильтрация только реальных предложений