Files
gridpilot.gg/apps/website/hooks/league/useLeagueWalletWithdrawalWithBlockers.ts
2026-01-16 01:00:03 +01:00

60 lines
1.9 KiB
TypeScript

'use client';
import { usePageMutation } from '@/lib/page/usePageData';
import { useInject } from '@/lib/di/hooks/useInject';
import { LEAGUE_WALLET_SERVICE_TOKEN } from '@/lib/di/tokens';
import { SubmitBlocker } from '@/lib/blockers/SubmitBlocker';
import { ThrottleBlocker } from '@/lib/blockers/ThrottleBlocker';
import type { LeagueWalletViewModel } from '@/lib/view-models/LeagueWalletViewModel';
/**
* Hook for wallet withdrawals with client-side blockers
* Handles UX prevention mechanisms (rate limiting, duplicate submission prevention)
*/
export function useLeagueWalletWithdrawalWithBlockers(leagueId: string, data: LeagueWalletViewModel | null, refetch: () => void) {
const leagueWalletService = useInject(LEAGUE_WALLET_SERVICE_TOKEN);
// Client-side blockers for UX improvement
const submitBlocker = new SubmitBlocker();
const throttle = new ThrottleBlocker(500);
const withdrawMutation = usePageMutation(
async ({ amount }: { amount: number }) => {
if (!data) throw new globalThis.Error('Wallet data not available');
// Client-side blockers (UX only, not security)
if (!submitBlocker.canExecute() || !throttle.canExecute()) {
throw new globalThis.Error('Request blocked due to rate limiting');
}
submitBlocker.block();
throttle.block();
try {
const result = await leagueWalletService.withdraw(
leagueId,
amount,
data.currency,
'season-2', // Current active season
'bank-account-***1234'
);
if (!result.success) {
throw new globalThis.Error(result.message || 'Withdrawal failed');
}
return result;
} finally {
submitBlocker.release();
}
},
{
onSuccess: () => {
// Refetch wallet data after successful withdrawal
refetch();
},
}
);
return withdrawMutation;
}