ваше сообщение коммита
This commit is contained in:
@@ -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;
|
||||
};
|
||||
|
||||
// Фильтрация только реальных предложений
|
||||
|
||||
Reference in New Issue
Block a user