1- import { useState , useMemo } from 'react' ;
1+ import { useState , useMemo , useRef , useCallback , useEffect } from 'react' ;
22import { openContractCall } from '@stacks/connect' ;
33import {
44 stringUtf8CV ,
@@ -19,6 +19,7 @@ const FEE_BASIS_POINTS = 50;
1919const BASIS_POINTS_DIVISOR = 10000 ;
2020const MIN_TIP_STX = 0.001 ;
2121const MAX_TIP_STX = 10000 ;
22+ const COOLDOWN_SECONDS = 10 ;
2223
2324export default function SendTip ( { addToast } ) {
2425 const { notifyTipSent } = useTipContext ( ) ;
@@ -30,6 +31,28 @@ export default function SendTip({ addToast }) {
3031 const [ pendingTx , setPendingTx ] = useState ( null ) ;
3132 const [ recipientError , setRecipientError ] = useState ( '' ) ;
3233 const [ amountError , setAmountError ] = useState ( '' ) ;
34+ const [ cooldown , setCooldown ] = useState ( 0 ) ;
35+ const cooldownRef = useRef ( null ) ;
36+
37+ useEffect ( ( ) => {
38+ return ( ) => {
39+ if ( cooldownRef . current ) clearInterval ( cooldownRef . current ) ;
40+ } ;
41+ } , [ ] ) ;
42+
43+ const startCooldown = useCallback ( ( ) => {
44+ setCooldown ( COOLDOWN_SECONDS ) ;
45+ cooldownRef . current = setInterval ( ( ) => {
46+ setCooldown ( prev => {
47+ if ( prev <= 1 ) {
48+ clearInterval ( cooldownRef . current ) ;
49+ cooldownRef . current = null ;
50+ return 0 ;
51+ }
52+ return prev - 1 ;
53+ } ) ;
54+ } , 1000 ) ;
55+ } , [ ] ) ;
3356
3457 const senderAddress = useMemo ( ( ) => {
3558 try {
@@ -80,6 +103,11 @@ export default function SendTip({ addToast }) {
80103 } ;
81104
82105 const validateAndConfirm = ( ) => {
106+ if ( cooldown > 0 ) {
107+ addToast ( `Please wait ${ cooldown } s before sending another tip` , 'warning' ) ;
108+ return ;
109+ }
110+
83111 if ( ! recipient || ! amount ) {
84112 addToast ( 'Please fill in all required fields' , 'warning' ) ;
85113 return ;
@@ -160,6 +188,7 @@ export default function SendTip({ addToast }) {
160188 setMessage ( '' ) ;
161189 notifyTipSent ( ) ;
162190 refetchBalance ( ) ;
191+ startCooldown ( ) ;
163192 addToast ( 'Tip sent successfully! Transaction: ' + data . txId , 'success' ) ;
164193 } ,
165194 onCancel : ( ) => {
@@ -293,7 +322,7 @@ export default function SendTip({ addToast }) {
293322
294323 < button
295324 onClick = { validateAndConfirm }
296- disabled = { loading }
325+ disabled = { loading || cooldown > 0 }
297326 className = "w-full bg-gray-900 hover:bg-black text-white font-bold py-3 px-4 rounded-lg shadow-md hover:shadow-lg transform active:scale-95 transition-all disabled:bg-gray-400 disabled:shadow-none"
298327 >
299328 { loading ? (
@@ -304,7 +333,7 @@ export default function SendTip({ addToast }) {
304333 </ svg >
305334 Processing...
306335 </ span >
307- ) : 'Send Tip' }
336+ ) : cooldown > 0 ? `Wait ${ cooldown } s` : 'Send Tip' }
308337 </ button >
309338 </ div >
310339
0 commit comments