Skip to content

Commit e0b89e7

Browse files
committed
fix: surface StakeKit API errors to user when yield quote fails
When a yield quote API call fails (e.g. StakeKit returns DriftLendingInsufficientSolForRentError), the error was silently swallowed — the deposit button was disabled with no explanation. Changes: - Return quoteError from useYieldTransactionFlow hook - Show red error text above the action button in: - YieldEnterModal - YieldForm - YieldActionModal - Change button text to 'Quote Failed' when error present - Change button color scheme to red when error present - Parse StakeKit/Axios error responses for user-friendly messages Closes #12052
1 parent cec2f73 commit e0b89e7

File tree

4 files changed

+70
-3
lines changed

4 files changed

+70
-3
lines changed

src/pages/Yields/components/YieldActionModal.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ export const YieldActionModal = memo(function YieldActionModal({
8181
handleClose,
8282
isQuoteLoading,
8383
quoteData,
84+
quoteError,
8485
isAllowanceCheckPending,
8586
isUsdtResetRequired,
8687
} = useYieldTransactionFlow({
@@ -202,7 +203,20 @@ export const YieldActionModal = memo(function YieldActionModal({
202203
yieldItem.mechanics.type,
203204
])
204205

206+
const quoteErrorMessage = useMemo(() => {
207+
if (!quoteError) return null
208+
try {
209+
const axiosError = quoteError as { response?: { data?: { message?: string } } }
210+
if (axiosError?.response?.data?.message) return axiosError.response.data.message
211+
if (quoteError instanceof Error) return quoteError.message
212+
} catch {
213+
// ignore parsing errors
214+
}
215+
return translate('yieldXYZ.errors.quoteFailedDescription')
216+
}, [quoteError, translate])
217+
205218
const buttonText = useMemo(() => {
219+
if (quoteError && amount) return translate('yieldXYZ.errors.quoteFailedTitle')
206220
const yieldType = yieldItem.mechanics.type
207221
// Use the current step's type/title for a clean button label (e.g., "Stake", "Unstake", "Approve")
208222
if (activeStepIndex >= 0 && transactionSteps[activeStepIndex]) {
@@ -226,6 +240,8 @@ export const YieldActionModal = memo(function YieldActionModal({
226240
}, [
227241
action,
228242
translate,
243+
quoteError,
244+
amount,
229245
activeStepIndex,
230246
transactionSteps,
231247
quoteData,
@@ -412,8 +428,13 @@ export const YieldActionModal = memo(function YieldActionModal({
412428
</DialogBody>
413429
{isInProgress && (
414430
<DialogFooter borderTop='1px solid' borderColor='border.base' pt={4} pb={4}>
431+
{quoteErrorMessage && (
432+
<Text fontSize='sm' color='red.500' mb={3} textAlign='center'>
433+
{quoteErrorMessage}
434+
</Text>
435+
)}
415436
<Button
416-
colorScheme='blue'
437+
colorScheme={quoteErrorMessage ? 'red' : 'blue'}
417438
size='lg'
418439
width='full'
419440
height='56px'

src/pages/Yields/components/YieldEnterModal.tsx

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,7 @@ export const YieldEnterModal = memo(
319319
handleClose: hookHandleClose,
320320
isQuoteLoading,
321321
quoteData,
322+
quoteError,
322323
isAllowanceCheckPending,
323324
isUsdtResetRequired,
324325
} = useYieldTransactionFlow({
@@ -357,9 +358,24 @@ export const YieldEnterModal = memo(
357358
[isConnected, isLoading, yieldItem.status.enter, cryptoAmount, isBelowMinimum, quoteData],
358359
)
359360

361+
const quoteErrorMessage = useMemo(() => {
362+
if (!quoteError) return null
363+
try {
364+
// Axios errors have response.data with error details
365+
const axiosError = quoteError as { response?: { data?: { message?: string } } }
366+
if (axiosError?.response?.data?.message) return axiosError.response.data.message
367+
// Fall back to error message
368+
if (quoteError instanceof Error) return quoteError.message
369+
} catch {
370+
// ignore parsing errors
371+
}
372+
return translate('yieldXYZ.errors.quoteFailedDescription')
373+
}, [quoteError, translate])
374+
360375
const enterButtonText = useMemo(() => {
361376
if (!isConnected) return translate('common.connectWallet')
362377
if (isQuoteActive) return translate('yieldXYZ.loadingQuote')
378+
if (quoteError && cryptoAmount) return translate('yieldXYZ.errors.quoteFailedTitle')
363379

364380
if (isSubmitting && transactionSteps.length > 0) {
365381
const activeStep = transactionSteps.find(s => s.status !== 'success')
@@ -397,6 +413,8 @@ export const YieldEnterModal = memo(
397413
}, [
398414
isConnected,
399415
isQuoteActive,
416+
quoteError,
417+
cryptoAmount,
400418
isSubmitting,
401419
transactionSteps,
402420
activeStepIndex,
@@ -673,8 +691,13 @@ export const YieldEnterModal = memo(
673691
</DialogBody>
674692
{isInProgress && (
675693
<DialogFooter borderTop='1px solid' borderColor='border.base' pt={4} pb={4}>
694+
{quoteErrorMessage && (
695+
<Text fontSize='sm' color='red.500' mb={3} textAlign='center'>
696+
{quoteErrorMessage}
697+
</Text>
698+
)}
676699
<Button
677-
colorScheme='blue'
700+
colorScheme={quoteErrorMessage ? 'red' : 'blue'}
678701
size='lg'
679702
width='full'
680703
height='56px'

src/pages/Yields/components/YieldForm.tsx

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,7 @@ export const YieldForm = memo(
343343
handleConfirm,
344344
isQuoteLoading,
345345
quoteData,
346+
quoteError,
346347
isAllowanceCheckPending,
347348
isUsdtResetRequired,
348349
} = useYieldTransactionFlow({
@@ -402,9 +403,22 @@ export const YieldForm = memo(
402403
quoteData,
403404
])
404405

406+
const quoteErrorMessage = useMemo(() => {
407+
if (!quoteError) return null
408+
try {
409+
const axiosError = quoteError as { response?: { data?: { message?: string } } }
410+
if (axiosError?.response?.data?.message) return axiosError.response.data.message
411+
if (quoteError instanceof Error) return quoteError.message
412+
} catch {
413+
// ignore parsing errors
414+
}
415+
return translate('yieldXYZ.errors.quoteFailedDescription')
416+
}, [quoteError, translate])
417+
405418
const buttonText = useMemo(() => {
406419
if (!isConnected) return translate('common.connectWallet')
407420
if (isQuoteActive) return translate('yieldXYZ.loadingQuote')
421+
if (quoteError && cryptoAmount) return translate('yieldXYZ.errors.quoteFailedTitle')
408422

409423
if (isSubmitting && transactionSteps.length > 0) {
410424
const activeStep = transactionSteps.find(s => s.status !== 'success')
@@ -451,6 +465,8 @@ export const YieldForm = memo(
451465
}, [
452466
isConnected,
453467
isQuoteActive,
468+
quoteError,
469+
cryptoAmount,
454470
isSubmitting,
455471
transactionSteps,
456472
activeStepIndex,
@@ -737,8 +753,13 @@ export const YieldForm = memo(
737753
</Flex>
738754

739755
<Box pt={4} pb={4}>
756+
{quoteErrorMessage && (
757+
<Text fontSize='sm' color='red.500' mb={3} textAlign='center'>
758+
{quoteErrorMessage}
759+
</Text>
760+
)}
740761
<Button
741-
colorScheme='blue'
762+
colorScheme={quoteErrorMessage ? 'red' : 'blue'}
742763
size='lg'
743764
width='full'
744765
height='56px'

src/pages/Yields/hooks/useYieldTransactionFlow.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -829,6 +829,7 @@ export const useYieldTransactionFlow = ({
829829
handleClose,
830830
isQuoteLoading,
831831
quoteData,
832+
quoteError,
832833
isAllowanceCheckPending,
833834
isUsdtResetRequired,
834835
}),
@@ -843,6 +844,7 @@ export const useYieldTransactionFlow = ({
843844
handleClose,
844845
isQuoteLoading,
845846
quoteData,
847+
quoteError,
846848
isAllowanceCheckPending,
847849
isUsdtResetRequired,
848850
],

0 commit comments

Comments
 (0)