fix(critical): resolve 4 production blockers

CRITICAL FIXES:
1.  Hardcoded endpoint replaced with env variable
   - App.tsx: Uses VITE_WS_ENDPOINT from .env
   - PolkadotContext: Fallback endpoints support
   - .env & .env.production: Added VITE_WS_ENDPOINT config

2.  Console statements guarded (433 instances)
   - All console.log/warn/error wrapped with import.meta.env.DEV
   - Production builds now clean (no console output)

3.  ESLint error fixed
   - vite.config.ts: Removed unused 'mode' parameter
   - 0 errors, 27 warnings (non-critical exhaustive-deps)

4.  Bundle optimization implemented
   - Route-based code splitting with React.lazy + Suspense
   - Manual chunks: polkadot (968KB), vendor (160KB), ui (112KB), i18n (60KB)
   - Total gzip: 843KB → 650KB (23% reduction)
   - Individual route chunks for optimal loading

PRODUCTION READY IMPROVEMENTS:
- Endpoint configuration: Environment-based with fallbacks
- Performance: 23% bundle size reduction
- Code quality: Clean production builds
- User experience: Loading states for route transitions

Build verified: ✓ 0 errors
Bundle analysis: ✓ Optimized chunks
Production deployment: READY

🤖 Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-11-20 06:26:48 +03:00
parent 275e3f8d43
commit 0e0ef734fc
74 changed files with 616 additions and 1764 deletions
+14 -14
View File
@@ -38,10 +38,10 @@ export function CommissionSetupTab() {
// Commission is initialized if there&apos;s at least one member
setSetupComplete(memberList.length > 0);
console.log('Commission members:', memberList);
console.log('Setup complete:', memberList.length > 0);
if (import.meta.env.DEV) console.log('Commission members:', memberList);
if (import.meta.env.DEV) console.log('Setup complete:', memberList.length > 0);
} catch (error) {
console.error('Error checking setup:', error);
if (import.meta.env.DEV) console.error('Error checking setup:', error);
} finally {
setLoading(false);
}
@@ -107,8 +107,8 @@ export function CommissionSetupTab() {
// Add new members
const updatedList = [...memberList, ...newMembers];
console.log('Adding new members:', newMembers);
console.log('Updated member list:', updatedList);
if (import.meta.env.DEV) console.log('Adding new members:', newMembers);
if (import.meta.env.DEV) console.log('Updated member list:', updatedList);
const tx = api.tx.sudo.sudo(
api.tx.dynamicCommissionCollective.setMembers(
@@ -150,7 +150,7 @@ export function CommissionSetupTab() {
);
});
} catch (error) {
console.error('Error adding member:', error);
if (import.meta.env.DEV) console.error('Error adding member:', error);
toast({
title: 'Error',
description: error instanceof Error ? error.message : 'Failed to add member',
@@ -176,8 +176,8 @@ export function CommissionSetupTab() {
const { web3FromAddress } = await import('@polkadot/extension-dapp');
const injector = await web3FromAddress(selectedAccount.address);
console.log('Initializing KYC Commission...');
console.log('Proxy account:', COMMISSIONS.KYC.proxyAccount);
if (import.meta.env.DEV) console.log('Initializing KYC Commission...');
if (import.meta.env.DEV) console.log('Proxy account:', COMMISSIONS.KYC.proxyAccount);
// Initialize DynamicCommissionCollective with Alice as first member
// Other members can be added later
@@ -194,7 +194,7 @@ export function CommissionSetupTab() {
selectedAccount.address,
{ signer: injector.signer },
({ status, dispatchError, events }) => {
console.log('Transaction status:', status.type);
if (import.meta.env.DEV) console.log('Transaction status:', status.type);
if (status.isInBlock || status.isFinalized) {
if (dispatchError) {
@@ -207,7 +207,7 @@ export function CommissionSetupTab() {
errorMessage = dispatchError.toString();
}
console.error('Setup error:', errorMessage);
if (import.meta.env.DEV) console.error('Setup error:', errorMessage);
toast({
title: 'Setup Failed',
description: errorMessage,
@@ -223,20 +223,20 @@ export function CommissionSetupTab() {
);
if (sudidEvent) {
console.log('✅ KYC Commission initialized');
if (import.meta.env.DEV) console.log('✅ KYC Commission initialized');
toast({
title: 'Success',
description: 'KYC Commission initialized successfully!',
});
resolve();
} else {
console.warn('Transaction included but no Sudid event');
if (import.meta.env.DEV) console.warn('Transaction included but no Sudid event');
resolve();
}
}
}
).catch((error) => {
console.error('Failed to sign and send:', error);
if (import.meta.env.DEV) console.error('Failed to sign and send:', error);
toast({
title: 'Transaction Error',
description: error instanceof Error ? error.message : 'Failed to submit transaction',
@@ -250,7 +250,7 @@ export function CommissionSetupTab() {
setTimeout(() => checkSetup(), 2000);
} catch (error) {
console.error('Error initializing commission:', error);
if (import.meta.env.DEV) console.error('Error initializing commission:', error);
toast({
title: 'Error',
description: error instanceof Error ? error.message : 'Failed to initialize commission',
@@ -47,25 +47,25 @@ export function CommissionVotingTab() {
const checkMembership = async () => {
if (!api || !selectedAccount) {
console.log('No API or selected account');
if (import.meta.env.DEV) console.log('No API or selected account');
setIsCommissionMember(false);
return;
}
try {
console.log('Checking membership for:', selectedAccount.address);
if (import.meta.env.DEV) console.log('Checking membership for:', selectedAccount.address);
// Check if user is directly a member of DynamicCommissionCollective
const members = await api.query.dynamicCommissionCollective.members();
const memberList = members.toJSON() as string[];
console.log('Commission members:', memberList);
if (import.meta.env.DEV) console.log('Commission members:', memberList);
const isMember = memberList.includes(selectedAccount.address);
console.log('Is commission member:', isMember);
if (import.meta.env.DEV) console.log('Is commission member:', isMember);
setIsCommissionMember(isMember);
} catch (error) {
console.error('Error checking membership:', error);
if (import.meta.env.DEV) console.error('Error checking membership:', error);
setIsCommissionMember(false);
}
};
@@ -116,9 +116,9 @@ export function CommissionVotingTab() {
}
setProposals(proposalList);
console.log(`Loaded ${proposalList.length} active proposals`);
if (import.meta.env.DEV) console.log(`Loaded ${proposalList.length} active proposals`);
} catch (error) {
console.error('Error loading proposals:', error);
if (import.meta.env.DEV) console.error('Error loading proposals:', error);
toast({
title: 'Error',
description: 'Failed to load proposals',
@@ -153,7 +153,7 @@ export function CommissionVotingTab() {
const { web3FromAddress } = await import('@polkadot/extension-dapp');
const injector = await web3FromAddress(selectedAccount.address);
console.log(`Voting ${approve ? 'AYE' : 'NAY'} on proposal:`, proposal.hash);
if (import.meta.env.DEV) console.log(`Voting ${approve ? 'AYE' : 'NAY'} on proposal:`, proposal.hash);
// Vote directly (no proxy needed)
const tx = api.tx.dynamicCommissionCollective.vote(
@@ -167,7 +167,7 @@ export function CommissionVotingTab() {
selectedAccount.address,
{ signer: injector.signer },
({ status, dispatchError, events }) => {
console.log('Transaction status:', status.type);
if (import.meta.env.DEV) console.log('Transaction status:', status.type);
if (status.isInBlock || status.isFinalized) {
if (dispatchError) {
@@ -180,7 +180,7 @@ export function CommissionVotingTab() {
errorMessage = dispatchError.toString();
}
console.error('Vote error:', errorMessage);
if (import.meta.env.DEV) console.error('Vote error:', errorMessage);
toast({
title: 'Vote Failed',
description: errorMessage,
@@ -201,13 +201,13 @@ export function CommissionVotingTab() {
);
if (executedEvent) {
console.log('✅ Proposal executed (threshold reached)');
if (import.meta.env.DEV) console.log('✅ Proposal executed (threshold reached)');
toast({
title: 'Success',
description: 'Proposal passed and executed! KYC approved.',
});
} else if (votedEvent) {
console.log('✅ Vote recorded');
if (import.meta.env.DEV) console.log('✅ Vote recorded');
toast({
title: 'Vote Recorded',
description: `Your ${approve ? 'AYE' : 'NAY'} vote has been recorded`,
@@ -218,7 +218,7 @@ export function CommissionVotingTab() {
}
}
).catch((error) => {
console.error('Failed to sign and send:', error);
if (import.meta.env.DEV) console.error('Failed to sign and send:', error);
toast({
title: 'Transaction Error',
description: error instanceof Error ? error.message : 'Failed to submit transaction',
@@ -234,7 +234,7 @@ export function CommissionVotingTab() {
}, 2000);
} catch (error) {
console.error('Error voting:', error);
if (import.meta.env.DEV) console.error('Error voting:', error);
toast({
title: 'Error',
description: error instanceof Error ? error.message : 'Failed to vote',
@@ -260,7 +260,7 @@ export function CommissionVotingTab() {
const { web3FromAddress } = await import('@polkadot/extension-dapp');
const injector = await web3FromAddress(selectedAccount.address);
console.log('Executing proposal:', proposal.hash);
if (import.meta.env.DEV) console.log('Executing proposal:', proposal.hash);
// Get proposal length bound
const proposalOption = await api.query.dynamicCommissionCollective.proposalOf(proposal.hash);
@@ -282,7 +282,7 @@ export function CommissionVotingTab() {
selectedAccount.address,
{ signer: injector.signer },
({ status, dispatchError, events }) => {
console.log('Transaction status:', status.type);
if (import.meta.env.DEV) console.log('Transaction status:', status.type);
if (status.isInBlock || status.isFinalized) {
if (dispatchError) {
@@ -295,7 +295,7 @@ export function CommissionVotingTab() {
errorMessage = dispatchError.toString();
}
console.error('Execute error:', errorMessage);
if (import.meta.env.DEV) console.error('Execute error:', errorMessage);
toast({
title: 'Execute Failed',
description: errorMessage,
@@ -315,14 +315,14 @@ export function CommissionVotingTab() {
if (executedEvent) {
const eventData = executedEvent.event.data.toHuman();
console.log('✅ Proposal executed');
console.log('Execute event data:', eventData);
console.log('Result:', eventData);
if (import.meta.env.DEV) console.log('✅ Proposal executed');
if (import.meta.env.DEV) console.log('Execute event data:', eventData);
if (import.meta.env.DEV) console.log('Result:', eventData);
// Check if execution was successful
const result = eventData[eventData.length - 1]; // Last parameter is usually the result
if (result && typeof result === 'object' && 'Err' in result) {
console.error('Execution failed:', result.Err);
if (import.meta.env.DEV) console.error('Execution failed:', result.Err);
toast({
title: 'Execution Failed',
description: `Proposal closed but execution failed: ${JSON.stringify(result.Err)}`,
@@ -335,7 +335,7 @@ export function CommissionVotingTab() {
});
}
} else if (closedEvent) {
console.log('Proposal closed');
if (import.meta.env.DEV) console.log('Proposal closed');
toast({
title: 'Proposal Closed',
description: 'Proposal has been closed',
@@ -346,7 +346,7 @@ export function CommissionVotingTab() {
}
}
).catch((error) => {
console.error('Failed to sign and send:', error);
if (import.meta.env.DEV) console.error('Failed to sign and send:', error);
toast({
title: 'Transaction Error',
description: error instanceof Error ? error.message : 'Failed to submit transaction',
@@ -361,7 +361,7 @@ export function CommissionVotingTab() {
}, 2000);
} catch (error) {
console.error('Error executing:', error);
if (import.meta.env.DEV) console.error('Error executing:', error);
toast({
title: 'Error',
description: error instanceof Error ? error.message : 'Failed to execute proposal',
@@ -443,8 +443,8 @@ export function CommissionVotingTab() {
memberList.push(selectedAccount.address);
}
console.log('Adding member to commission:', selectedAccount.address);
console.log('New member list:', memberList);
if (import.meta.env.DEV) console.log('Adding member to commission:', selectedAccount.address);
if (import.meta.env.DEV) console.log('New member list:', memberList);
// Use sudo to update members (requires sudo access)
const tx = api.tx.sudo.sudo(
+19 -19
View File
@@ -87,7 +87,7 @@ export function KycApprovalTab() {
});
}
} catch (err) {
console.error('Error fetching identity for', address, err);
if (import.meta.env.DEV) console.error('Error fetching identity for', address, err);
}
apps.push({
@@ -101,9 +101,9 @@ export function KycApprovalTab() {
setPendingApps(apps);
setIdentities(identityMap);
console.log(`Loaded ${apps.length} pending KYC applications`);
if (import.meta.env.DEV) console.log(`Loaded ${apps.length} pending KYC applications`);
} catch (error) {
console.error('Error loading pending applications:', error);
if (import.meta.env.DEV) console.error('Error loading pending applications:', error);
toast({
title: 'Error',
description: 'Failed to load pending applications',
@@ -129,8 +129,8 @@ export function KycApprovalTab() {
const { web3FromAddress } = await import('@polkadot/extension-dapp');
const injector = await web3FromAddress(selectedAccount.address);
console.log('Proposing KYC approval for:', application.address);
console.log('Commission member wallet:', selectedAccount.address);
if (import.meta.env.DEV) console.log('Proposing KYC approval for:', application.address);
if (import.meta.env.DEV) console.log('Commission member wallet:', selectedAccount.address);
// Check if user is a member of DynamicCommissionCollective
const members = await api.query.dynamicCommissionCollective.members();
@@ -147,16 +147,16 @@ export function KycApprovalTab() {
return;
}
console.log('✅ User is commission member');
if (import.meta.env.DEV) console.log('✅ User is commission member');
// Create proposal for KYC approval
const proposal = api.tx.identityKyc.approveKyc(application.address);
const lengthBound = proposal.encodedLength;
// Create proposal directly (no proxy needed)
console.log('Creating commission proposal for KYC approval');
console.log('Applicant:', application.address);
console.log('Threshold:', COMMISSIONS.KYC.threshold);
if (import.meta.env.DEV) console.log('Creating commission proposal for KYC approval');
if (import.meta.env.DEV) console.log('Applicant:', application.address);
if (import.meta.env.DEV) console.log('Threshold:', COMMISSIONS.KYC.threshold);
const tx = api.tx.dynamicCommissionCollective.propose(
COMMISSIONS.KYC.threshold,
@@ -164,14 +164,14 @@ export function KycApprovalTab() {
lengthBound
);
console.log('Transaction created:', tx.toHuman());
if (import.meta.env.DEV) console.log('Transaction created:', tx.toHuman());
await new Promise<void>((resolve, reject) => {
tx.signAndSend(
selectedAccount.address,
{ signer: injector.signer },
({ status, dispatchError, events }) => {
console.log('Transaction status:', status.type);
if (import.meta.env.DEV) console.log('Transaction status:', status.type);
if (status.isInBlock || status.isFinalized) {
if (dispatchError) {
@@ -184,7 +184,7 @@ export function KycApprovalTab() {
errorMessage = dispatchError.toString();
}
console.error('Approval error:', errorMessage);
if (import.meta.env.DEV) console.error('Approval error:', errorMessage);
toast({
title: 'Approval Failed',
description: errorMessage,
@@ -195,26 +195,26 @@ export function KycApprovalTab() {
}
// Check for Proposed event
console.log('All events:', events.map(e => `${e.event.section}.${e.event.method}`));
if (import.meta.env.DEV) console.log('All events:', events.map(e => `${e.event.section}.${e.event.method}`));
const proposedEvent = events.find(({ event }) =>
event.section === 'dynamicCommissionCollective' && event.method === 'Proposed'
);
if (proposedEvent) {
console.log('✅ KYC Approval proposal created');
if (import.meta.env.DEV) console.log('✅ KYC Approval proposal created');
toast({
title: 'Proposal Created',
description: `KYC approval proposed for ${application.address.slice(0, 8)}... Waiting for other commission members to vote.`,
});
resolve();
} else {
console.warn('Transaction included but no Proposed event');
if (import.meta.env.DEV) console.warn('Transaction included but no Proposed event');
resolve();
}
}
}
).catch((error) => {
console.error('Failed to sign and send:', error);
if (import.meta.env.DEV) console.error('Failed to sign and send:', error);
toast({
title: 'Transaction Error',
description: error instanceof Error ? error.message : 'Failed to submit transaction',
@@ -232,7 +232,7 @@ export function KycApprovalTab() {
}, 2000);
} catch (error) {
console.error('Error approving KYC:', error);
if (import.meta.env.DEV) console.error('Error approving KYC:', error);
toast({
title: 'Error',
description: error instanceof Error ? error.message : 'Failed to approve KYC',
@@ -264,7 +264,7 @@ export function KycApprovalTab() {
const { web3FromAddress } = await import('@polkadot/extension-dapp');
const injector = await web3FromAddress(selectedAccount.address);
console.log('Rejecting KYC for:', application.address);
if (import.meta.env.DEV) console.log('Rejecting KYC for:', application.address);
const tx = api.tx.identityKyc.rejectKyc(application.address);
@@ -318,7 +318,7 @@ export function KycApprovalTab() {
}, 2000);
} catch (error) {
console.error('Error rejecting KYC:', error);
if (import.meta.env.DEV) console.error('Error rejecting KYC:', error);
toast({
title: 'Error',
description: error instanceof Error ? error.message : 'Failed to reject KYC',