@huma-finance/widgets 0.0.72-beta.883 → 0.0.72-beta.895
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/index.cjs +219 -87
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.js +221 -89
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/components/CreditLine/solanaBorrow/index.tsx +3 -2
- package/src/components/CreditLine/solanaPayment/index.tsx +3 -2
- package/src/components/ErrorModal.tsx +25 -7
- package/src/components/Lend/components/ApproveLenderBase.tsx +30 -23
- package/src/components/Lend/solanaAddRedemption/index.tsx +3 -2
- package/src/components/Lend/solanaCancelRedemption/index.tsx +3 -2
- package/src/components/Lend/solanaEnableAutoRedemption/index.tsx +3 -2
- package/src/components/Lend/solanaSupply/index.tsx +3 -2
- package/src/components/SolanaErrorModal.tsx +43 -0
- package/src/components/SolanaTxSendModal.tsx +147 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@huma-finance/widgets",
|
|
3
|
-
"version": "0.0.72-beta.
|
|
3
|
+
"version": "0.0.72-beta.895+0df1d3a",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"@ethersproject/experimental": "^5.7.0",
|
|
30
30
|
"@ethersproject/providers": "^5.6.0",
|
|
31
31
|
"@ethersproject/units": "^5.6.0",
|
|
32
|
-
"@huma-finance/sdk": "^0.0.72-beta.
|
|
33
|
-
"@huma-finance/shared": "^0.0.72-beta.
|
|
34
|
-
"@huma-finance/web-shared": "^0.0.72-beta.
|
|
32
|
+
"@huma-finance/sdk": "^0.0.72-beta.895+0df1d3a",
|
|
33
|
+
"@huma-finance/shared": "^0.0.72-beta.895+0df1d3a",
|
|
34
|
+
"@huma-finance/web-shared": "^0.0.72-beta.895+0df1d3a",
|
|
35
35
|
"@mui/x-date-pickers": "^5.0.7",
|
|
36
36
|
"@notifi-network/notifi-frontend-client": "^1.1.2",
|
|
37
37
|
"@notifi-network/notifi-react": "^1.1.2",
|
|
@@ -201,5 +201,5 @@
|
|
|
201
201
|
"optionalDependencies": {
|
|
202
202
|
"encoding": "^0.1.13"
|
|
203
203
|
},
|
|
204
|
-
"gitHead": "
|
|
204
|
+
"gitHead": "0df1d3a122dc84c3d351becf9ef5a99f578b436f"
|
|
205
205
|
}
|
|
@@ -8,10 +8,10 @@ import { selectWidgetState } from '../../../store/widgets.selectors'
|
|
|
8
8
|
import { WidgetWrapper } from '../../WidgetWrapper'
|
|
9
9
|
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
10
10
|
import { setStep } from '../../../store/widgets.reducers'
|
|
11
|
-
import { ErrorModal } from '../../ErrorModal'
|
|
12
11
|
import { ChooseAmount } from './1-ChooseAmount'
|
|
13
12
|
import { Transfer } from './2-Transfer'
|
|
14
13
|
import { Done } from './3-Done'
|
|
14
|
+
import { SolanaErrorModal } from '../../SolanaErrorModal'
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Lend pool supply props
|
|
@@ -81,7 +81,8 @@ export function SolanaBorrow({
|
|
|
81
81
|
/>
|
|
82
82
|
)}
|
|
83
83
|
{step === WIDGET_STEP.Error && (
|
|
84
|
-
<
|
|
84
|
+
<SolanaErrorModal
|
|
85
|
+
chainId={poolInfo.chainId}
|
|
85
86
|
title={title}
|
|
86
87
|
errorReason='Sorry there was an error'
|
|
87
88
|
errorMessage={errorMessage}
|
|
@@ -8,10 +8,10 @@ import { selectWidgetState } from '../../../store/widgets.selectors'
|
|
|
8
8
|
import { WidgetWrapper } from '../../WidgetWrapper'
|
|
9
9
|
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
10
10
|
import { setStep } from '../../../store/widgets.reducers'
|
|
11
|
-
import { ErrorModal } from '../../ErrorModal'
|
|
12
11
|
import { ChooseAmount } from './1-ChooseAmount'
|
|
13
12
|
import { Transfer } from './2-Transfer'
|
|
14
13
|
import { Done } from './3-Done'
|
|
14
|
+
import { SolanaErrorModal } from '../../SolanaErrorModal'
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Lend pool supply props
|
|
@@ -74,7 +74,8 @@ export function SolanaPayment({
|
|
|
74
74
|
<Done poolInfo={poolInfo} handleAction={handleClose} />
|
|
75
75
|
)}
|
|
76
76
|
{step === WIDGET_STEP.Error && (
|
|
77
|
-
<
|
|
77
|
+
<SolanaErrorModal
|
|
78
|
+
chainId={poolInfo.chainId}
|
|
78
79
|
title={title}
|
|
79
80
|
errorReason='Sorry there was an error'
|
|
80
81
|
errorMessage={errorMessage}
|
|
@@ -4,6 +4,7 @@ import { txAtom } from '@huma-finance/web-shared'
|
|
|
4
4
|
import { useResetAtom } from 'jotai/utils'
|
|
5
5
|
import React, { useCallback } from 'react'
|
|
6
6
|
|
|
7
|
+
import { openInNewTab } from '@huma-finance/shared'
|
|
7
8
|
import { useAppDispatch } from '../hooks/useRedux'
|
|
8
9
|
import { resetState } from '../store/widgets.reducers'
|
|
9
10
|
import { SorryImg } from './images'
|
|
@@ -12,6 +13,7 @@ type Props = {
|
|
|
12
13
|
title: string
|
|
13
14
|
errorReason?: string
|
|
14
15
|
errorMessage?: string
|
|
16
|
+
errorUrl?: string
|
|
15
17
|
handleOk: () => void
|
|
16
18
|
okText?: string
|
|
17
19
|
shouldResetState?: boolean
|
|
@@ -21,6 +23,7 @@ export function ErrorModal({
|
|
|
21
23
|
title,
|
|
22
24
|
errorReason,
|
|
23
25
|
errorMessage,
|
|
26
|
+
errorUrl,
|
|
24
27
|
handleOk,
|
|
25
28
|
okText = 'OKAY',
|
|
26
29
|
shouldResetState = true,
|
|
@@ -85,11 +88,17 @@ export function ErrorModal({
|
|
|
85
88
|
text-overflow: ellipsis;
|
|
86
89
|
margin-right: ${theme.spacing(2)};
|
|
87
90
|
`,
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
91
|
+
bottomButtonGroup: css`
|
|
92
|
+
width: 100%;
|
|
93
|
+
position: absolute;
|
|
94
|
+
bottom: 0;
|
|
95
|
+
display: flex;
|
|
96
|
+
row-gap: ${theme.spacing(1)};
|
|
97
|
+
column-gap: ${theme.spacing(1)};
|
|
98
|
+
|
|
99
|
+
button {
|
|
100
|
+
height: 40px;
|
|
101
|
+
margin-top: ${theme.spacing(1)};
|
|
93
102
|
}
|
|
94
103
|
`,
|
|
95
104
|
}
|
|
@@ -119,8 +128,17 @@ export function ErrorModal({
|
|
|
119
128
|
</Tooltip>
|
|
120
129
|
</Box>
|
|
121
130
|
</Box>
|
|
122
|
-
<Box css={styles.
|
|
123
|
-
|
|
131
|
+
<Box css={styles.bottomButtonGroup}>
|
|
132
|
+
{errorUrl && (
|
|
133
|
+
<Button
|
|
134
|
+
variant='outlined'
|
|
135
|
+
fullWidth
|
|
136
|
+
onClick={() => openInNewTab(errorUrl)}
|
|
137
|
+
>
|
|
138
|
+
SEE DETAILS
|
|
139
|
+
</Button>
|
|
140
|
+
)}
|
|
141
|
+
<Button variant='contained' fullWidth onClick={handleCloseModal}>
|
|
124
142
|
{okText}
|
|
125
143
|
</Button>
|
|
126
144
|
</Box>
|
|
@@ -2,14 +2,15 @@
|
|
|
2
2
|
import {
|
|
3
3
|
CHAIN_TYPE,
|
|
4
4
|
checkIsDev,
|
|
5
|
+
COMMON_ERROR_MESSAGE,
|
|
5
6
|
IdentityServiceV2,
|
|
6
7
|
NETWORK_TYPE,
|
|
8
|
+
SOLANA_TRANSACTION_EXPIRED_BLOCKHEIGHT_EXCEEDED_ERROR,
|
|
7
9
|
timeUtil,
|
|
8
10
|
TrancheType,
|
|
9
11
|
} from '@huma-finance/shared'
|
|
10
12
|
import { useChainInfo } from '@huma-finance/web-shared'
|
|
11
13
|
import React, { useCallback, useEffect } from 'react'
|
|
12
|
-
|
|
13
14
|
import { useAppDispatch } from '../../../hooks/useRedux'
|
|
14
15
|
import { setError, setStep } from '../../../store/widgets.reducers'
|
|
15
16
|
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
@@ -59,11 +60,7 @@ export function ApproveLenderBase({
|
|
|
59
60
|
tryAttempts = 0
|
|
60
61
|
} catch (e: unknown) {
|
|
61
62
|
if (tryAttempts === 0) {
|
|
62
|
-
|
|
63
|
-
setError({
|
|
64
|
-
errorMessage: 'Something went wrong, please try again later.',
|
|
65
|
-
}),
|
|
66
|
-
)
|
|
63
|
+
throw e
|
|
67
64
|
} else {
|
|
68
65
|
await timeUtil.sleep(3000)
|
|
69
66
|
console.error(e)
|
|
@@ -71,28 +68,38 @@ export function ApproveLenderBase({
|
|
|
71
68
|
}
|
|
72
69
|
}
|
|
73
70
|
},
|
|
74
|
-
[
|
|
75
|
-
account,
|
|
76
|
-
chainId,
|
|
77
|
-
chainSpecificData,
|
|
78
|
-
dispatch,
|
|
79
|
-
documentHash,
|
|
80
|
-
isDev,
|
|
81
|
-
networkType,
|
|
82
|
-
],
|
|
71
|
+
[account, chainId, chainSpecificData, documentHash, isDev, networkType],
|
|
83
72
|
)
|
|
84
73
|
|
|
85
74
|
useEffect(() => {
|
|
86
75
|
const approveLenderAsync = async () => {
|
|
87
76
|
if (account && chainId) {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
77
|
+
try {
|
|
78
|
+
if (isUniTranche) {
|
|
79
|
+
await approveLender(juniorTrancheVault)
|
|
80
|
+
changeTranche('junior')
|
|
81
|
+
dispatch(setStep(WIDGET_STEP.ChooseAmount))
|
|
82
|
+
} else {
|
|
83
|
+
await approveLender(juniorTrancheVault)
|
|
84
|
+
await approveLender(seniorTrancheVault)
|
|
85
|
+
dispatch(setStep(WIDGET_STEP.ChooseTranche))
|
|
86
|
+
}
|
|
87
|
+
} catch (e: unknown) {
|
|
88
|
+
console.error(e)
|
|
89
|
+
// @ts-ignore
|
|
90
|
+
let errorMessage = e.message ?? COMMON_ERROR_MESSAGE
|
|
91
|
+
if (
|
|
92
|
+
errorMessage.indexOf(
|
|
93
|
+
SOLANA_TRANSACTION_EXPIRED_BLOCKHEIGHT_EXCEEDED_ERROR,
|
|
94
|
+
) >= 0
|
|
95
|
+
) {
|
|
96
|
+
errorMessage = `Transaction failed due to blockchain congestion. Please try again.`
|
|
97
|
+
}
|
|
98
|
+
dispatch(
|
|
99
|
+
setError({
|
|
100
|
+
errorMessage,
|
|
101
|
+
}),
|
|
102
|
+
)
|
|
96
103
|
}
|
|
97
104
|
}
|
|
98
105
|
}
|
|
@@ -14,10 +14,10 @@ import { WidgetWrapper } from '../../WidgetWrapper'
|
|
|
14
14
|
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
15
15
|
import { ChooseAmount } from './2-ChooseAmount'
|
|
16
16
|
import { setStep } from '../../../store/widgets.reducers'
|
|
17
|
-
import { ErrorModal } from '../../ErrorModal'
|
|
18
17
|
import { ChooseTranche } from './1-ChooseTranche'
|
|
19
18
|
import { Done } from './4-Done'
|
|
20
19
|
import { Transfer } from './3-Transfer'
|
|
20
|
+
import { SolanaErrorModal } from '../../SolanaErrorModal'
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Lend pool supply props
|
|
@@ -143,7 +143,8 @@ export function SolanaLendAddRedemption({
|
|
|
143
143
|
<Done poolInfo={poolInfo} handleAction={handleClose} />
|
|
144
144
|
)}
|
|
145
145
|
{step === WIDGET_STEP.Error && (
|
|
146
|
-
<
|
|
146
|
+
<SolanaErrorModal
|
|
147
|
+
chainId={poolInfo.chainId}
|
|
147
148
|
title={title}
|
|
148
149
|
errorReason='Sorry there was an error'
|
|
149
150
|
errorMessage={errorMessage}
|
|
@@ -9,10 +9,10 @@ import { selectWidgetState } from '../../../store/widgets.selectors'
|
|
|
9
9
|
import { WidgetWrapper } from '../../WidgetWrapper'
|
|
10
10
|
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
11
11
|
import { setStep } from '../../../store/widgets.reducers'
|
|
12
|
-
import { ErrorModal } from '../../ErrorModal'
|
|
13
12
|
import { Transfer } from './2-Transfer'
|
|
14
13
|
import { ChooseTranche } from './1-ChooseTranche'
|
|
15
14
|
import { Done } from './3-Done'
|
|
15
|
+
import { SolanaErrorModal } from '../../SolanaErrorModal'
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Lend pool supply props
|
|
@@ -150,7 +150,8 @@ export function SolanaLendCancelRedemption({
|
|
|
150
150
|
/>
|
|
151
151
|
)}
|
|
152
152
|
{step === WIDGET_STEP.Error && (
|
|
153
|
-
<
|
|
153
|
+
<SolanaErrorModal
|
|
154
|
+
chainId={poolInfo.chainId}
|
|
154
155
|
title={title}
|
|
155
156
|
errorReason='Sorry there was an error'
|
|
156
157
|
errorMessage={errorMessage}
|
|
@@ -7,11 +7,11 @@ import { useAppSelector } from '../../../hooks/useRedux'
|
|
|
7
7
|
import { setStep } from '../../../store/widgets.reducers'
|
|
8
8
|
import { selectWidgetState } from '../../../store/widgets.selectors'
|
|
9
9
|
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
10
|
-
import { ErrorModal } from '../../ErrorModal'
|
|
11
10
|
import { WidgetWrapper } from '../../WidgetWrapper'
|
|
12
11
|
import { Transfer } from './2-Transfer'
|
|
13
12
|
import { Success } from './3-Success'
|
|
14
13
|
import { ApproveAllowance } from './1-ApproveAllowance'
|
|
14
|
+
import { SolanaErrorModal } from '../../SolanaErrorModal'
|
|
15
15
|
|
|
16
16
|
/**
|
|
17
17
|
* Lend pool supply props
|
|
@@ -64,7 +64,8 @@ export function SolanaEnableAutoRedemption({
|
|
|
64
64
|
/>
|
|
65
65
|
)}
|
|
66
66
|
{step === WIDGET_STEP.Error && (
|
|
67
|
-
<
|
|
67
|
+
<SolanaErrorModal
|
|
68
|
+
chainId={poolInfo.chainId}
|
|
68
69
|
title='Auto-Redemption'
|
|
69
70
|
errorReason='Sorry there was an error'
|
|
70
71
|
errorMessage={errorMessage}
|
|
@@ -16,7 +16,6 @@ import { useAppSelector } from '../../../hooks/useRedux'
|
|
|
16
16
|
import { setStep } from '../../../store/widgets.reducers'
|
|
17
17
|
import { selectWidgetState } from '../../../store/widgets.selectors'
|
|
18
18
|
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
19
|
-
import { ErrorModal } from '../../ErrorModal'
|
|
20
19
|
import { PointsEarned } from '../../PointsEarned'
|
|
21
20
|
import { WidgetWrapper } from '../../WidgetWrapper'
|
|
22
21
|
import { Evaluation } from './1-Evaluation'
|
|
@@ -26,6 +25,7 @@ import { ChooseAmount } from './4-ChooseAmount'
|
|
|
26
25
|
import { ApproveAllowance } from './5-ApproveAllowance'
|
|
27
26
|
import { Transfer } from './6-Transfer'
|
|
28
27
|
import { Success } from './7-Success'
|
|
28
|
+
import { SolanaErrorModal } from '../../SolanaErrorModal'
|
|
29
29
|
|
|
30
30
|
export interface Campaign {
|
|
31
31
|
id: string
|
|
@@ -182,7 +182,8 @@ export function SolanaLendSupply({
|
|
|
182
182
|
<PointsEarned lpConfig={poolState} handleAction={handleClose} />
|
|
183
183
|
)}
|
|
184
184
|
{step === WIDGET_STEP.Error && (
|
|
185
|
-
<
|
|
185
|
+
<SolanaErrorModal
|
|
186
|
+
chainId={poolInfo.chainId}
|
|
186
187
|
title='Supply'
|
|
187
188
|
errorReason='Sorry there was an error'
|
|
188
189
|
errorMessage={errorMessage}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import { getSolanaExplorerUrl, SolanaChainEnum } from '@huma-finance/shared'
|
|
4
|
+
import { useAppSelector } from '../hooks/useRedux'
|
|
5
|
+
import { ErrorModal } from './ErrorModal'
|
|
6
|
+
import { selectWidgetState } from '../store/widgets.selectors'
|
|
7
|
+
|
|
8
|
+
type Props = {
|
|
9
|
+
chainId: SolanaChainEnum
|
|
10
|
+
title: string
|
|
11
|
+
errorReason?: string
|
|
12
|
+
errorMessage?: string
|
|
13
|
+
handleOk: () => void
|
|
14
|
+
okText?: string
|
|
15
|
+
shouldResetState?: boolean
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function SolanaErrorModal({
|
|
19
|
+
chainId,
|
|
20
|
+
title,
|
|
21
|
+
errorReason,
|
|
22
|
+
errorMessage,
|
|
23
|
+
handleOk,
|
|
24
|
+
okText = 'OKAY',
|
|
25
|
+
shouldResetState = true,
|
|
26
|
+
}: Props): React.ReactElement {
|
|
27
|
+
const { solanaSignature } = useAppSelector(selectWidgetState)
|
|
28
|
+
const errorUrl = solanaSignature
|
|
29
|
+
? getSolanaExplorerUrl(chainId, solanaSignature, 'tx')
|
|
30
|
+
: undefined
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<ErrorModal
|
|
34
|
+
title={title}
|
|
35
|
+
errorReason={errorReason}
|
|
36
|
+
errorMessage={errorMessage}
|
|
37
|
+
errorUrl={errorUrl ?? undefined}
|
|
38
|
+
handleOk={handleOk}
|
|
39
|
+
okText={okText}
|
|
40
|
+
shouldResetState={shouldResetState}
|
|
41
|
+
/>
|
|
42
|
+
)
|
|
43
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { sleep, SolanaChainEnum } from '@huma-finance/shared'
|
|
2
|
-
import React, { useEffect, useState } from 'react'
|
|
2
|
+
import React, { useCallback, useEffect, useState } from 'react'
|
|
3
3
|
import {
|
|
4
4
|
buildOptimalTransactionFromConnection,
|
|
5
5
|
extractWritableAccounts,
|
|
@@ -7,10 +7,13 @@ import {
|
|
|
7
7
|
|
|
8
8
|
import { useConnection, useWallet } from '@solana/wallet-adapter-react'
|
|
9
9
|
import { Transaction } from '@solana/web3.js'
|
|
10
|
+
import { useForceRefresh } from '@huma-finance/web-shared'
|
|
11
|
+
import { Box, Button, css, Typography, useTheme } from '@mui/material'
|
|
10
12
|
import { useAppDispatch } from '../hooks/useRedux'
|
|
11
13
|
import { setError, setSolanaSignature } from '../store/widgets.reducers'
|
|
12
14
|
import { LoadingModal } from './LoadingModal'
|
|
13
15
|
import { SolanaViewOnExplorer } from './SolanaViewOnExplorer'
|
|
16
|
+
import { SorryImg } from './images'
|
|
14
17
|
|
|
15
18
|
type Props = {
|
|
16
19
|
chainId: SolanaChainEnum
|
|
@@ -23,25 +26,78 @@ export function SolanaTxSendModal({
|
|
|
23
26
|
tx,
|
|
24
27
|
handleSuccess,
|
|
25
28
|
}: Props): React.ReactElement | null {
|
|
29
|
+
const theme = useTheme()
|
|
26
30
|
const dispatch = useAppDispatch()
|
|
27
|
-
const { sendTransaction } = useWallet()
|
|
31
|
+
const { publicKey, signTransaction, sendTransaction } = useWallet()
|
|
28
32
|
const { connection } = useConnection()
|
|
29
33
|
const [signature, setSignature] = useState<string>('')
|
|
34
|
+
const [showRetryScreen, setShowRetryScreen] = useState<boolean>(false)
|
|
35
|
+
const [useHighPriority, setUseHighPriority] = useState<boolean>(false)
|
|
36
|
+
const [refreshCount, refresh] = useForceRefresh()
|
|
37
|
+
|
|
38
|
+
const styles = {
|
|
39
|
+
wrapper: css`
|
|
40
|
+
height: 438px;
|
|
41
|
+
position: relative;
|
|
42
|
+
`,
|
|
43
|
+
sorry: css`
|
|
44
|
+
${theme.cssMixins.rowHCentered};
|
|
45
|
+
margin-top: ${theme.spacing(12)};
|
|
46
|
+
margin-right: ${theme.spacing(4)};
|
|
47
|
+
& > img {
|
|
48
|
+
width: 170px;
|
|
49
|
+
}
|
|
50
|
+
`,
|
|
51
|
+
bottomButtonGroup: css`
|
|
52
|
+
width: 100%;
|
|
53
|
+
position: absolute;
|
|
54
|
+
bottom: 0;
|
|
55
|
+
display: flex;
|
|
56
|
+
flex-direction: column;
|
|
57
|
+
row-gap: ${theme.spacing(1)};
|
|
58
|
+
column-gap: ${theme.spacing(1)};
|
|
59
|
+
|
|
60
|
+
button {
|
|
61
|
+
height: 40px;
|
|
62
|
+
margin-top: ${theme.spacing(1)};
|
|
63
|
+
}
|
|
64
|
+
`,
|
|
65
|
+
content: css`
|
|
66
|
+
margin-top: ${theme.spacing(2)};
|
|
67
|
+
font-size: 16px;
|
|
68
|
+
`,
|
|
69
|
+
retryHighPriorityButton: css`
|
|
70
|
+
font-size: 16px;
|
|
71
|
+
`,
|
|
72
|
+
}
|
|
30
73
|
|
|
31
74
|
useEffect(() => {
|
|
32
75
|
async function sendTx() {
|
|
33
|
-
if (!connection || !tx) {
|
|
76
|
+
if (!connection || !tx || !publicKey || !signTransaction) {
|
|
34
77
|
return
|
|
35
78
|
}
|
|
36
79
|
|
|
37
80
|
let signatureResult = ''
|
|
38
81
|
try {
|
|
39
82
|
// Optimize transaction
|
|
40
|
-
|
|
83
|
+
// Make a copy of the tx so we can use the original tx for retries
|
|
84
|
+
const txCopy = new Transaction()
|
|
85
|
+
txCopy.instructions = [...tx.instructions]
|
|
86
|
+
const recentBlockhash = await connection.getLatestBlockhash('confirmed')
|
|
87
|
+
txCopy.recentBlockhash = recentBlockhash.blockhash
|
|
88
|
+
txCopy.lastValidBlockHeight = recentBlockhash.lastValidBlockHeight
|
|
89
|
+
txCopy.feePayer = publicKey
|
|
90
|
+
// Extract writable accounts
|
|
91
|
+
const txAccounts = extractWritableAccounts(txCopy)
|
|
92
|
+
// Add on compute unit limit + price instructions
|
|
41
93
|
const optimizedTx = await buildOptimalTransactionFromConnection(
|
|
42
|
-
|
|
43
|
-
|
|
94
|
+
txCopy,
|
|
95
|
+
txAccounts,
|
|
44
96
|
connection,
|
|
97
|
+
chainId,
|
|
98
|
+
publicKey,
|
|
99
|
+
useHighPriority ? 'High' : undefined,
|
|
100
|
+
process.env.REACT_APP_HELIUS_API_KEY,
|
|
45
101
|
)
|
|
46
102
|
signatureResult = await sendTransaction(optimizedTx, connection, {
|
|
47
103
|
preflightCommitment: 'confirmed',
|
|
@@ -54,10 +110,24 @@ export function SolanaTxSendModal({
|
|
|
54
110
|
lastValidBlockHeight: optimizedTx.lastValidBlockHeight!,
|
|
55
111
|
signature: signatureResult,
|
|
56
112
|
})
|
|
113
|
+
const txResult = await connection.getParsedTransaction(
|
|
114
|
+
signatureResult,
|
|
115
|
+
'confirmed',
|
|
116
|
+
)
|
|
117
|
+
if (txResult?.meta?.err) {
|
|
118
|
+
dispatch(
|
|
119
|
+
setError({
|
|
120
|
+
errorMessage:
|
|
121
|
+
'Your transaction was confirmed but had errors. Please check the transaction details on the explorer for more information.',
|
|
122
|
+
}),
|
|
123
|
+
)
|
|
124
|
+
return
|
|
125
|
+
}
|
|
57
126
|
handleSuccess({ signature: signatureResult })
|
|
58
127
|
} catch (error: unknown) {
|
|
59
|
-
|
|
128
|
+
console.log(error)
|
|
60
129
|
|
|
130
|
+
let signatureStatusRetries = 0
|
|
61
131
|
while (signatureStatusRetries < 5) {
|
|
62
132
|
// Attempt to load the signature status using transaction history
|
|
63
133
|
// eslint-disable-next-line no-await-in-loop
|
|
@@ -70,6 +140,15 @@ export function SolanaTxSendModal({
|
|
|
70
140
|
result?.value?.confirmationStatus === 'finalized' ||
|
|
71
141
|
result?.value?.confirmationStatus === 'confirmed'
|
|
72
142
|
) {
|
|
143
|
+
if (result?.value?.err) {
|
|
144
|
+
dispatch(
|
|
145
|
+
setError({
|
|
146
|
+
errorMessage:
|
|
147
|
+
'Your transaction was confirmed but had errors. Please check the transaction details on the explorer for more information.',
|
|
148
|
+
}),
|
|
149
|
+
)
|
|
150
|
+
return
|
|
151
|
+
}
|
|
73
152
|
handleSuccess({ signature: signatureResult })
|
|
74
153
|
return
|
|
75
154
|
}
|
|
@@ -78,11 +157,70 @@ export function SolanaTxSendModal({
|
|
|
78
157
|
}
|
|
79
158
|
|
|
80
159
|
const err = error as Error
|
|
81
|
-
|
|
160
|
+
if (err?.message?.includes('block height exceeded')) {
|
|
161
|
+
// Allow the user to retry the transaction
|
|
162
|
+
setShowRetryScreen(true)
|
|
163
|
+
} else {
|
|
164
|
+
dispatch(setError({ errorMessage: err?.message || '' }))
|
|
165
|
+
}
|
|
82
166
|
}
|
|
83
167
|
}
|
|
84
168
|
sendTx()
|
|
85
|
-
}, [
|
|
169
|
+
}, [
|
|
170
|
+
chainId,
|
|
171
|
+
connection,
|
|
172
|
+
dispatch,
|
|
173
|
+
handleSuccess,
|
|
174
|
+
publicKey,
|
|
175
|
+
sendTransaction,
|
|
176
|
+
signTransaction,
|
|
177
|
+
tx,
|
|
178
|
+
refreshCount,
|
|
179
|
+
useHighPriority,
|
|
180
|
+
])
|
|
181
|
+
|
|
182
|
+
const handleRetry = useCallback(
|
|
183
|
+
(highPriority: boolean) => {
|
|
184
|
+
console.log('handleRetry')
|
|
185
|
+
setUseHighPriority(highPriority)
|
|
186
|
+
setShowRetryScreen(false)
|
|
187
|
+
refresh()
|
|
188
|
+
},
|
|
189
|
+
[refresh],
|
|
190
|
+
)
|
|
191
|
+
|
|
192
|
+
if (showRetryScreen) {
|
|
193
|
+
return (
|
|
194
|
+
<Box css={styles.wrapper}>
|
|
195
|
+
<Box css={styles.sorry}>
|
|
196
|
+
<img src={SorryImg} alt='sorry' />
|
|
197
|
+
</Box>
|
|
198
|
+
<Typography variant='h6'>Block Height Exceeded</Typography>
|
|
199
|
+
<Box css={styles.content}>
|
|
200
|
+
Your transaction was unable to be confirmed in time. This can happen
|
|
201
|
+
when the network is congested. Please retry submitting your
|
|
202
|
+
transaction or retry with a higher priority fee.
|
|
203
|
+
</Box>
|
|
204
|
+
<Box css={styles.bottomButtonGroup}>
|
|
205
|
+
<Button
|
|
206
|
+
variant='outlined'
|
|
207
|
+
fullWidth
|
|
208
|
+
onClick={() => handleRetry(false)}
|
|
209
|
+
>
|
|
210
|
+
RETRY
|
|
211
|
+
</Button>
|
|
212
|
+
<Button
|
|
213
|
+
css={styles.retryHighPriorityButton}
|
|
214
|
+
variant='contained'
|
|
215
|
+
fullWidth
|
|
216
|
+
onClick={() => handleRetry(true)}
|
|
217
|
+
>
|
|
218
|
+
RETRY (HIGH PRIORITY)
|
|
219
|
+
</Button>
|
|
220
|
+
</Box>
|
|
221
|
+
</Box>
|
|
222
|
+
)
|
|
223
|
+
}
|
|
86
224
|
|
|
87
225
|
return (
|
|
88
226
|
<LoadingModal
|