Skip to content

Commit 1a4e886

Browse files
committed
feat: handle tx success and error states
1 parent b47e9f8 commit 1a4e886

File tree

4 files changed

+110
-17
lines changed

4 files changed

+110
-17
lines changed

packages/frontend/src/components/Lp/MintAndLp/DepositPreviewModal.tsx

+54-11
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const useWaitForConfirmationStyles = makeStyles((theme) =>
2727
}),
2828
)
2929

30-
const WaitForConfirmation: React.FC<{ onComplete: () => void }> = ({ onComplete }) => {
30+
const WaitForConfirmation: React.FC = () => {
3131
const classes = useWaitForConfirmationStyles()
3232

3333
return (
@@ -39,11 +39,6 @@ const WaitForConfirmation: React.FC<{ onComplete: () => void }> = ({ onComplete
3939
</div>
4040

4141
<Typography className={classes.title}>Confirm transaction in your wallet</Typography>
42-
<Box>
43-
<AltPrimaryButton id="confirm-tx-btn" onClick={onComplete} fullWidth>
44-
Simulate confirm transaction
45-
</AltPrimaryButton>
46-
</Box>
4742
</Box>
4843
)
4944
}
@@ -87,6 +82,9 @@ const useTxStatusStyles = makeStyles({
8782
fontWeight: 700,
8883
letterSpacing: '-0.01em',
8984
},
85+
errorMessage: {
86+
fontSize: '18px',
87+
},
9088
stepLabel: {
9189
fontSize: '16px',
9290
color: 'rgba(255, 255, 255, 0.7)',
@@ -96,9 +94,12 @@ const useTxStatusStyles = makeStyles({
9694
fontWeight: 700,
9795
color: 'rgba(255, 255, 255, 1)',
9896
},
97+
buttonMargin: {
98+
marginTop: '32px',
99+
},
99100
})
100101

101-
const TxStatus: React.FC<{ onComplete: () => void }> = ({ onComplete }) => {
102+
const TxStatusSuccess: React.FC<{ onComplete: () => void }> = ({ onComplete }) => {
102103
const classes = useTxStatusStyles()
103104
const stepperClasses = useStepperStyles()
104105

@@ -131,6 +132,23 @@ const TxStatus: React.FC<{ onComplete: () => void }> = ({ onComplete }) => {
131132
)
132133
}
133134

135+
const TxStatusFail: React.FC<{ message: string; onBackClick: () => void }> = ({ message, onBackClick }) => {
136+
const classes = useTxStatusStyles()
137+
138+
return (
139+
<Box display="flex" flexDirection="column" gridGap="24px">
140+
<Typography className={classes.title}>Deposit failed!</Typography>
141+
<Typography variant="body1" className={classes.errorMessage}>
142+
{message}
143+
</Typography>
144+
145+
<AltPrimaryButton id="go-back-btn" onClick={onBackClick} fullWidth className={classes.buttonMargin}>
146+
Go back
147+
</AltPrimaryButton>
148+
</Box>
149+
)
150+
}
151+
134152
const useModalStyles = makeStyles((theme) =>
135153
createStyles({
136154
container: {
@@ -154,23 +172,48 @@ type DepositPreviewModalProps = {
154172

155173
const DepositPreviewModal: React.FC<DepositPreviewModalProps> = ({ isOpen, onClose, squeethToMint }) => {
156174
const [activeStep, setActiveStep] = React.useState(0)
175+
const [txError, setTxError] = React.useState('')
157176

158-
const handleNext = () => setActiveStep((prevActiveStep) => prevActiveStep + 1)
177+
const toConfirmationStep = () => setActiveStep(1)
178+
const toTxStatusStep = () => setActiveStep(2)
159179
const resetStep = () => setActiveStep(0)
160180

161181
const handleClose = () => {
182+
setTxError('')
162183
resetStep()
163184
onClose()
164185
}
165186

187+
const handleTxFail = (message: string) => {
188+
setTxError(message)
189+
toTxStatusStep()
190+
}
191+
192+
const resetErrorAndGoBack = () => {
193+
setTxError('')
194+
resetStep
195+
}
196+
166197
const classes = useModalStyles()
167198

168199
return (
169200
<Modal open={isOpen} onClose={handleClose} aria-labelledby="modal-title">
170201
<Box className={classes.container}>
171-
{activeStep === 0 && <LpSettings onComplete={handleNext} squeethToMint={squeethToMint} />}
172-
{activeStep === 1 && <WaitForConfirmation onComplete={handleNext} />}
173-
{activeStep === 2 && <TxStatus onComplete={handleClose} />}
202+
{activeStep === 0 && (
203+
<LpSettings
204+
squeethToMint={squeethToMint}
205+
onConfirm={toConfirmationStep}
206+
onTxSuccess={toTxStatusStep}
207+
onTxFail={(message) => handleTxFail(message)}
208+
/>
209+
)}
210+
{activeStep === 1 && <WaitForConfirmation />}
211+
{activeStep === 2 &&
212+
(!!txError ? (
213+
<TxStatusFail message={txError} onBackClick={resetErrorAndGoBack} />
214+
) : (
215+
<TxStatusSuccess onComplete={handleClose} />
216+
))}
174217
</Box>
175218
</Modal>
176219
)

packages/frontend/src/components/Lp/MintAndLp/LpSettings.tsx

+25-6
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { useGetDepositAmounts, useGetTicksFromPriceRange, useOpenPositionDeposit
1717
import { slippageAmountAtom } from '@state/trade/atoms'
1818
import { toTokenAmount } from '@utils/calculations'
1919
import { formatNumber } from '@utils/formatter'
20+
import { getErrorMessage } from '@utils/error'
2021
import { OSQUEETH_DECIMALS } from '@constants/index'
2122

2223
import InfoBox from './InfoBox'
@@ -113,7 +114,12 @@ const formatTokenAmount = (amount: string | number) => {
113114
return Number(withPrecision).toFixed(2)
114115
}
115116

116-
const LpSettings: React.FC<{ onComplete: () => void; squeethToMint: string }> = ({ onComplete, squeethToMint }) => {
117+
const LpSettings: React.FC<{
118+
squeethToMint: string
119+
onConfirm: () => void
120+
onTxSuccess: () => void
121+
onTxFail: (message: string) => void
122+
}> = ({ squeethToMint, onConfirm, onTxSuccess, onTxFail }) => {
117123
const { oSqueeth } = useAtomValue(addressesAtom)
118124
const { value: squeethBalance } = useTokenBalance(oSqueeth, 15, OSQUEETH_DECIMALS)
119125
const ethPrice = useETHPrice()
@@ -188,16 +194,29 @@ const LpSettings: React.FC<{ onComplete: () => void; squeethToMint: string }> =
188194
collatRatioVal,
189195
slippageAmountVal,
190196
0,
197+
() => {
198+
onConfirm()
199+
},
191200
() => {
192201
console.log('successfully deposited')
193-
onComplete()
202+
onTxSuccess()
194203
},
195204
)
196-
} catch (e) {
197-
console.log('transaction failed')
198-
console.log(e)
205+
} catch (error: unknown) {
206+
console.log('deposit failed', error)
207+
onTxFail(getErrorMessage(error))
199208
}
200-
}, [squeethToMint, lowerTick, upperTick, collatRatioVal, slippageAmountVal, openLpPosition, onComplete])
209+
}, [
210+
squeethToMint,
211+
lowerTick,
212+
upperTick,
213+
collatRatioVal,
214+
slippageAmountVal,
215+
openLpPosition,
216+
onConfirm,
217+
onTxSuccess,
218+
onTxFail,
219+
])
201220

202221
return (
203222
<>

packages/frontend/src/state/lp/hooks.ts

+3
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ export const useOpenPositionDeposit = () => {
110110
collatRatio: number,
111111
slippage: number,
112112
withdrawAmount: number,
113+
onTxRequested?: () => void,
113114
onTxConfirmed?: () => void,
114115
) => {
115116
if (!squeethPoolContract || !contract || !address) return null
@@ -157,6 +158,8 @@ export const useOpenPositionDeposit = () => {
157158
}),
158159
onTxConfirmed,
159160
)
161+
162+
onTxRequested && onTxRequested()
160163
return txHash
161164
},
162165
[address, squeethPool, contract, handleTransaction, squeethPoolContract, isWethToken0, getDepositAmounts],

packages/frontend/src/utils/error.ts

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
type ErrorWithMessage = {
2+
message: string
3+
}
4+
5+
function isErrorWithMessage(error: unknown): error is ErrorWithMessage {
6+
return (
7+
typeof error === 'object' &&
8+
error !== null &&
9+
'message' in error &&
10+
typeof (error as Record<string, unknown>).message === 'string'
11+
)
12+
}
13+
14+
function toErrorWithMessage(maybeError: unknown): ErrorWithMessage {
15+
if (isErrorWithMessage(maybeError)) return maybeError
16+
17+
try {
18+
return new Error(JSON.stringify(maybeError))
19+
} catch {
20+
// fallback in case there's an error stringifying the maybeError
21+
// like with circular references for example.
22+
return new Error(String(maybeError))
23+
}
24+
}
25+
26+
export function getErrorMessage(error: unknown) {
27+
return toErrorWithMessage(error).message
28+
}

0 commit comments

Comments
 (0)