diff --git a/frontend/src/components/SendTip.jsx b/frontend/src/components/SendTip.jsx index d6d6b561..a35d9214 100644 --- a/frontend/src/components/SendTip.jsx +++ b/frontend/src/components/SendTip.jsx @@ -1,4 +1,4 @@ -import { useState } from 'react'; +import { useState, useMemo } from 'react'; import { openContractCall } from '@stacks/connect'; import { stringUtf8CV, @@ -11,6 +11,7 @@ import { network, appDetails, userSession } from '../utils/stacks'; import { CONTRACT_ADDRESS, CONTRACT_NAME } from '../config/contracts'; import { toMicroSTX, formatSTX } from '../lib/utils'; import { useTipContext } from '../context/TipContext'; +import { useBalance } from '../hooks/useBalance'; import ConfirmDialog from './ui/confirm-dialog'; import TxStatus from './ui/tx-status'; @@ -30,6 +31,18 @@ export default function SendTip({ addToast }) { const [recipientError, setRecipientError] = useState(''); const [amountError, setAmountError] = useState(''); + const senderAddress = useMemo(() => { + try { + return userSession.loadUserData().profile.stxAddress.mainnet; + } catch { + return null; + } + }, []); + + const { balance, loading: balanceLoading, refetch: refetchBalance } = useBalance(senderAddress); + + const balanceSTX = balance !== null ? Number(balance) / 1_000_000 : null; + const isValidStacksAddress = (address) => { if (!address) return false; const trimmed = address.trim(); @@ -59,6 +72,8 @@ export default function SendTip({ addToast }) { setAmountError(`Minimum tip is ${MIN_TIP_STX} STX`); } else if (parsed > MAX_TIP_STX) { setAmountError(`Maximum tip is ${MAX_TIP_STX.toLocaleString()} STX`); + } else if (balanceSTX !== null && parsed > balanceSTX) { + setAmountError('Insufficient balance'); } else { setAmountError(''); } @@ -97,6 +112,11 @@ export default function SendTip({ addToast }) { return; } + if (balanceSTX !== null && parsedAmount > balanceSTX) { + addToast('Insufficient STX balance for this tip', 'warning'); + return; + } + setShowConfirm(true); }; @@ -139,6 +159,7 @@ export default function SendTip({ addToast }) { setAmount(''); setMessage(''); notifyTipSent(); + refetchBalance(); addToast('Tip sent successfully! Transaction: ' + data.txId, 'success'); }, onCancel: () => { @@ -160,6 +181,31 @@ export default function SendTip({ addToast }) {
Your Balance
++ {balanceLoading + ? 'Loading...' + : balanceSTX !== null + ? `${balanceSTX.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 6 })} STX` + : 'Unavailable'} +
+