@huma-finance/widgets 0.0.59-beta.494 → 0.0.59-beta.511
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/API.md +2 -0
- package/dist/cjs/index.cjs +967 -191
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.js +968 -193
- package/dist/index.js.map +1 -1
- package/package.json +6 -4
- package/src/components/ChooseAmountModal.tsx +2 -3
- package/src/components/ConfirmTransferModal.tsx +1 -1
- package/src/components/ErrorModal.tsx +1 -1
- package/src/components/InputAmountModal.tsx +2 -2
- package/src/components/Lend/supplyV2/2-Evaluation.tsx +31 -329
- package/src/components/Lend/supplyV2/3-ChooseAmount.tsx +58 -9
- package/src/components/Lend/supplyV2/6-Success.tsx +49 -6
- package/src/components/Lend/supplyV2/7-Notifications.tsx +22 -3
- package/src/components/Lend/supplyV2/8-PointsEarned.tsx +231 -0
- package/src/components/Lend/supplyV2/components/PersonaEvaluation.tsx +442 -0
- package/src/components/Lend/supplyV2/components/SecuritizeEvaluation.tsx +345 -0
- package/src/components/Lend/supplyV2/index.tsx +67 -5
- package/src/components/Lend/withdrawV2/1-ConfirmTransfer.tsx +1 -1
- package/src/components/SignIn.tsx +7 -2
- package/src/components/TxDoneModal.tsx +21 -2
- package/src/components/humaModal/HumaModal.tsx +1 -0
- package/src/components/humaModal/HumaModalHeader.tsx +1 -0
- package/src/components/icons/congratulations.svg +54 -0
- package/src/components/icons/huma-points.svg +15 -0
- package/src/components/icons/index.tsx +15 -0
- package/src/components/icons/ribbon.svg +9 -0
- package/src/store/widgets.reducers.ts +0 -1
- package/src/store/widgets.store.ts +1 -0
- package/src/theme/palette.ts +1 -1
|
@@ -1,10 +1,29 @@
|
|
|
1
|
-
import React from 'react'
|
|
1
|
+
import React, { useCallback } from 'react'
|
|
2
|
+
import { useDispatch } from 'react-redux'
|
|
3
|
+
|
|
4
|
+
import { Campaign } from '.'
|
|
2
5
|
import { NotifiSubscriptionModal } from '../../Notifi/NotifiSubscriptionModal'
|
|
6
|
+
import { setStep } from '../../../store/widgets.reducers'
|
|
7
|
+
import { WIDGET_STEP } from '../../../store/widgets.store'
|
|
3
8
|
|
|
4
9
|
type Props = {
|
|
10
|
+
campaign?: Campaign
|
|
5
11
|
handleAction: () => void
|
|
6
12
|
}
|
|
7
13
|
|
|
8
|
-
export function Notifications({
|
|
9
|
-
|
|
14
|
+
export function Notifications({
|
|
15
|
+
campaign,
|
|
16
|
+
handleAction,
|
|
17
|
+
}: Props): React.ReactElement {
|
|
18
|
+
const dispatch = useDispatch()
|
|
19
|
+
|
|
20
|
+
const handleUserAction = useCallback(() => {
|
|
21
|
+
if (campaign) {
|
|
22
|
+
dispatch(setStep(WIDGET_STEP.PointsEarned))
|
|
23
|
+
} else {
|
|
24
|
+
handleAction()
|
|
25
|
+
}
|
|
26
|
+
}, [campaign, dispatch, handleAction])
|
|
27
|
+
|
|
28
|
+
return <NotifiSubscriptionModal handleSuccess={handleUserAction} />
|
|
10
29
|
}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CampaignService,
|
|
3
|
+
checkIsDev,
|
|
4
|
+
formatNumber,
|
|
5
|
+
useAuthErrorHandling,
|
|
6
|
+
} from '@huma-finance/shared'
|
|
7
|
+
import { Box, css, useTheme } from '@mui/material'
|
|
8
|
+
import { useWeb3React } from '@web3-react/core'
|
|
9
|
+
import React, { useEffect, useState } from 'react'
|
|
10
|
+
import { useDispatch } from 'react-redux'
|
|
11
|
+
|
|
12
|
+
import { setError } from '../../../store/widgets.reducers'
|
|
13
|
+
import { BottomButton } from '../../BottomButton'
|
|
14
|
+
import { CongratulationsIcon, HumaPointsIcon, RibbonIcon } from '../../icons'
|
|
15
|
+
import { LoadingModal } from '../../LoadingModal'
|
|
16
|
+
import { SignIn } from '../../SignIn'
|
|
17
|
+
|
|
18
|
+
enum STATE {
|
|
19
|
+
Loading = 'Loading',
|
|
20
|
+
SignIn = 'SignIn',
|
|
21
|
+
Congrats = 'Congrats',
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const ERROR_MESSAGE =
|
|
25
|
+
'Failed to update wallet points. Be assured that your points will be added later.'
|
|
26
|
+
|
|
27
|
+
type Props = {
|
|
28
|
+
transactionHash: string
|
|
29
|
+
lpConfig: { withdrawalLockoutPeriodInDays: number }
|
|
30
|
+
pointsTestnetExperience: boolean
|
|
31
|
+
handleAction: () => void
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function PointsEarned({
|
|
35
|
+
transactionHash,
|
|
36
|
+
lpConfig,
|
|
37
|
+
pointsTestnetExperience,
|
|
38
|
+
handleAction,
|
|
39
|
+
}: Props): React.ReactElement {
|
|
40
|
+
const theme = useTheme()
|
|
41
|
+
const isDev = checkIsDev()
|
|
42
|
+
const dispatch = useDispatch()
|
|
43
|
+
const { account, chainId } = useWeb3React()
|
|
44
|
+
const [pointsAccumulated, setPointsAccumulated] = useState<
|
|
45
|
+
number | undefined
|
|
46
|
+
>()
|
|
47
|
+
const lockupMonths = Math.round(lpConfig.withdrawalLockoutPeriodInDays / 30)
|
|
48
|
+
const monthText =
|
|
49
|
+
lockupMonths > 1 ? `${lockupMonths} months` : `${lockupMonths} month`
|
|
50
|
+
|
|
51
|
+
const {
|
|
52
|
+
errorType,
|
|
53
|
+
setError: setAuthError,
|
|
54
|
+
isWalletOwnershipVerified,
|
|
55
|
+
isWalletOwnershipVerificationRequired,
|
|
56
|
+
} = useAuthErrorHandling(isDev)
|
|
57
|
+
const [walletOwnership, setWalletOwnership] = useState<boolean | undefined>()
|
|
58
|
+
const [state, setState] = useState<STATE>(STATE.Loading)
|
|
59
|
+
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
if (isWalletOwnershipVerificationRequired) {
|
|
62
|
+
setState(STATE.Loading)
|
|
63
|
+
}
|
|
64
|
+
}, [isWalletOwnershipVerificationRequired])
|
|
65
|
+
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
if (isWalletOwnershipVerified) {
|
|
68
|
+
setWalletOwnership(true)
|
|
69
|
+
}
|
|
70
|
+
}, [isWalletOwnershipVerified])
|
|
71
|
+
|
|
72
|
+
useEffect(() => {
|
|
73
|
+
const checkWalletOwnership = async () => {
|
|
74
|
+
const ownership = await CampaignService.checkWalletOwnership(
|
|
75
|
+
account!,
|
|
76
|
+
isDev,
|
|
77
|
+
pointsTestnetExperience,
|
|
78
|
+
)
|
|
79
|
+
setWalletOwnership(ownership)
|
|
80
|
+
if (!ownership) {
|
|
81
|
+
setAuthError('WalletNotSignInException')
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
checkWalletOwnership()
|
|
85
|
+
}, [account, isDev, pointsTestnetExperience, setAuthError])
|
|
86
|
+
|
|
87
|
+
useEffect(() => {
|
|
88
|
+
if (errorType === 'NotSignedIn') {
|
|
89
|
+
setState(STATE.SignIn)
|
|
90
|
+
} else if (errorType === 'UserRejected') {
|
|
91
|
+
dispatch(
|
|
92
|
+
setError({
|
|
93
|
+
errorMessage: 'User has rejected the transaction.',
|
|
94
|
+
}),
|
|
95
|
+
)
|
|
96
|
+
} else if (errorType === 'Other') {
|
|
97
|
+
dispatch(
|
|
98
|
+
setError({
|
|
99
|
+
errorMessage: ERROR_MESSAGE,
|
|
100
|
+
}),
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
}, [dispatch, errorType])
|
|
104
|
+
|
|
105
|
+
useEffect(() => {
|
|
106
|
+
const updateWalletPoints = async () => {
|
|
107
|
+
if (walletOwnership) {
|
|
108
|
+
try {
|
|
109
|
+
const result = await CampaignService.updateWalletPoints(
|
|
110
|
+
account!,
|
|
111
|
+
transactionHash,
|
|
112
|
+
chainId!,
|
|
113
|
+
isDev,
|
|
114
|
+
pointsTestnetExperience,
|
|
115
|
+
)
|
|
116
|
+
if (!result.pointsAccumulated) {
|
|
117
|
+
dispatch(
|
|
118
|
+
setError({
|
|
119
|
+
errorMessage: ERROR_MESSAGE,
|
|
120
|
+
}),
|
|
121
|
+
)
|
|
122
|
+
}
|
|
123
|
+
setPointsAccumulated(result.pointsAccumulated)
|
|
124
|
+
setState(STATE.Congrats)
|
|
125
|
+
} catch (error) {
|
|
126
|
+
dispatch(
|
|
127
|
+
setError({
|
|
128
|
+
errorMessage: ERROR_MESSAGE,
|
|
129
|
+
}),
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
updateWalletPoints()
|
|
135
|
+
}, [
|
|
136
|
+
account,
|
|
137
|
+
chainId,
|
|
138
|
+
dispatch,
|
|
139
|
+
isDev,
|
|
140
|
+
pointsTestnetExperience,
|
|
141
|
+
transactionHash,
|
|
142
|
+
walletOwnership,
|
|
143
|
+
])
|
|
144
|
+
|
|
145
|
+
const styles = {
|
|
146
|
+
wrapper: css`
|
|
147
|
+
height: 518px;
|
|
148
|
+
position: relative;
|
|
149
|
+
`,
|
|
150
|
+
congrats: css`
|
|
151
|
+
margin: ${theme.spacing(-4, -4.5, 0, -4.5)};
|
|
152
|
+
`,
|
|
153
|
+
ribbon: css`
|
|
154
|
+
position: relative;
|
|
155
|
+
${theme.cssMixins.rowHCentered};
|
|
156
|
+
font-weight: 700;
|
|
157
|
+
margin-top: ${theme.spacing(-8)};
|
|
158
|
+
color: ${theme.palette.text.primary};
|
|
159
|
+
font-size: 20px;
|
|
160
|
+
line-height: 160%;
|
|
161
|
+
letter-spacing: 0.15px;
|
|
162
|
+
`,
|
|
163
|
+
ribbonContent: css`
|
|
164
|
+
${theme.cssMixins.rowVCentered};
|
|
165
|
+
position: absolute;
|
|
166
|
+
top: ${theme.spacing(1)};
|
|
167
|
+
|
|
168
|
+
svg {
|
|
169
|
+
margin-right: ${theme.spacing(1)};
|
|
170
|
+
}
|
|
171
|
+
`,
|
|
172
|
+
entirePoints: css`
|
|
173
|
+
color: ${theme.palette.text.tertiary};
|
|
174
|
+
text-align: center;
|
|
175
|
+
font-weight: 700;
|
|
176
|
+
font-size: 20px;
|
|
177
|
+
line-height: 160%;
|
|
178
|
+
letter-spacing: 0.15px;
|
|
179
|
+
margin-top: ${theme.spacing(7)};
|
|
180
|
+
`,
|
|
181
|
+
entirePointsDetails: css`
|
|
182
|
+
color: ${theme.palette.text.tertiary};
|
|
183
|
+
text-align: center;
|
|
184
|
+
font-weight: 400;
|
|
185
|
+
font-size: 16px;
|
|
186
|
+
line-height: 150%;
|
|
187
|
+
letter-spacing: 0.15px;
|
|
188
|
+
margin-top: ${theme.spacing(4)};
|
|
189
|
+
`,
|
|
190
|
+
everyday: css`
|
|
191
|
+
font-weight: 700;
|
|
192
|
+
`,
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
if (state === STATE.SignIn) {
|
|
196
|
+
return (
|
|
197
|
+
<SignIn description='Please sign in to check the points that you earned.' />
|
|
198
|
+
)
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
if (state === STATE.Congrats) {
|
|
202
|
+
return (
|
|
203
|
+
<Box css={styles.wrapper}>
|
|
204
|
+
<Box css={styles.congrats}>
|
|
205
|
+
<CongratulationsIcon />
|
|
206
|
+
</Box>
|
|
207
|
+
<Box css={styles.ribbon}>
|
|
208
|
+
<RibbonIcon />
|
|
209
|
+
<Box css={styles.ribbonContent}>
|
|
210
|
+
<HumaPointsIcon />
|
|
211
|
+
<Box>{formatNumber(pointsAccumulated)} Points</Box>
|
|
212
|
+
</Box>
|
|
213
|
+
</Box>
|
|
214
|
+
<Box css={styles.entirePoints}>
|
|
215
|
+
<Box>Congratulations,</Box>
|
|
216
|
+
<Box>you've earned {pointsAccumulated} points</Box>
|
|
217
|
+
</Box>
|
|
218
|
+
<Box css={styles.entirePointsDetails}>
|
|
219
|
+
You'll earn points <span css={styles.everyday}>everyday</span> for{' '}
|
|
220
|
+
{monthText} straight. Plus, If you keep your investment till after{' '}
|
|
221
|
+
{monthText}, you’ll gain extra points daily.
|
|
222
|
+
</Box>
|
|
223
|
+
<BottomButton variant='contained' onClick={handleAction}>
|
|
224
|
+
GREAT
|
|
225
|
+
</BottomButton>
|
|
226
|
+
</Box>
|
|
227
|
+
)
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
return <LoadingModal title='SUPPLY' />
|
|
231
|
+
}
|
|
@@ -0,0 +1,442 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CAMPAIGN_REFERENCE_CODE,
|
|
3
|
+
CampaignService,
|
|
4
|
+
checkIsDev,
|
|
5
|
+
formatNumber,
|
|
6
|
+
IdentityServiceV2,
|
|
7
|
+
IdentityVerificationStatusV2,
|
|
8
|
+
KYCCopy,
|
|
9
|
+
PoolInfoV2,
|
|
10
|
+
TrancheType,
|
|
11
|
+
useAuthErrorHandling,
|
|
12
|
+
VerificationStatusResultV2,
|
|
13
|
+
} from '@huma-finance/shared'
|
|
14
|
+
import { Box, css, useTheme } from '@mui/material'
|
|
15
|
+
import { useWeb3React } from '@web3-react/core'
|
|
16
|
+
import { BigNumber } from 'ethers'
|
|
17
|
+
import Persona, { Client } from 'persona'
|
|
18
|
+
import React, { useCallback, useEffect, useRef, useState } from 'react'
|
|
19
|
+
|
|
20
|
+
import { Campaign } from '..'
|
|
21
|
+
import { useAppDispatch } from '../../../../hooks/useRedux'
|
|
22
|
+
import { setError, setStep } from '../../../../store/widgets.reducers'
|
|
23
|
+
import { WIDGET_STEP } from '../../../../store/widgets.store'
|
|
24
|
+
import { BottomButton } from '../../../BottomButton'
|
|
25
|
+
import { ApproveLenderImg } from '../../../images'
|
|
26
|
+
import { LoadingModal } from '../../../LoadingModal'
|
|
27
|
+
import { WrapperModal } from '../../../WrapperModal'
|
|
28
|
+
|
|
29
|
+
type LoadingType = 'verificationStatus' | 'startKYC' | 'approveLender'
|
|
30
|
+
|
|
31
|
+
const LoadingCopiesByType: {
|
|
32
|
+
[key: string]: {
|
|
33
|
+
description: string
|
|
34
|
+
}
|
|
35
|
+
} = {
|
|
36
|
+
verificationStatus: {
|
|
37
|
+
description: `Checking your verification status...`,
|
|
38
|
+
},
|
|
39
|
+
startKYC: {
|
|
40
|
+
description: `Starting KYC...`,
|
|
41
|
+
},
|
|
42
|
+
approveLender: {
|
|
43
|
+
description: `Approving as lender...`,
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
type Props = {
|
|
48
|
+
poolInfo: PoolInfoV2
|
|
49
|
+
isUniTranche: boolean
|
|
50
|
+
minDepositAmount: BigNumber
|
|
51
|
+
pointsTestnetExperience: boolean
|
|
52
|
+
campaign?: Campaign
|
|
53
|
+
changeTranche: (tranche: TrancheType) => void
|
|
54
|
+
handleClose: () => void
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function PersonaEvaluation({
|
|
58
|
+
poolInfo,
|
|
59
|
+
isUniTranche,
|
|
60
|
+
minDepositAmount: minDepositAmountBN,
|
|
61
|
+
campaign,
|
|
62
|
+
pointsTestnetExperience,
|
|
63
|
+
changeTranche,
|
|
64
|
+
handleClose,
|
|
65
|
+
}: Props): React.ReactElement | null {
|
|
66
|
+
const theme = useTheme()
|
|
67
|
+
const isDev = checkIsDev()
|
|
68
|
+
const dispatch = useAppDispatch()
|
|
69
|
+
const { account, chainId } = useWeb3React()
|
|
70
|
+
const {
|
|
71
|
+
errorType,
|
|
72
|
+
setError: setAuthError,
|
|
73
|
+
isWalletOwnershipVerified,
|
|
74
|
+
isWalletOwnershipVerificationRequired,
|
|
75
|
+
} = useAuthErrorHandling(isDev)
|
|
76
|
+
const KYCCopies = poolInfo.KYC!.Persona!
|
|
77
|
+
const [loadingType, setLoadingType] = useState<LoadingType>()
|
|
78
|
+
const [kycCopy, setKYCCopy] = useState<KYCCopy>(KYCCopies.verifyIdentity)
|
|
79
|
+
const [inquiryId, setInquiryId] = useState<string>()
|
|
80
|
+
const [sessionToken, setSessionToken] = useState<string>()
|
|
81
|
+
const [verificationStatus, setVerificationStatus] =
|
|
82
|
+
useState<VerificationStatusResultV2>()
|
|
83
|
+
const [showPersonaClient, setShowPersonaClient] = useState<boolean>(false)
|
|
84
|
+
const [campaignBasePoints, setCampaignBasePoints] = useState<number>(0)
|
|
85
|
+
const isKYCCompletedRef = useRef<boolean>(false)
|
|
86
|
+
const isActionOngoingRef = useRef<boolean>(false)
|
|
87
|
+
const isKYCResumedRef = useRef<boolean>(false)
|
|
88
|
+
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
const createNewWallet = async () => {
|
|
91
|
+
if (isWalletOwnershipVerified && campaign && account) {
|
|
92
|
+
await CampaignService.createNewWallet(
|
|
93
|
+
account,
|
|
94
|
+
localStorage.getItem(CAMPAIGN_REFERENCE_CODE) ?? undefined,
|
|
95
|
+
isDev,
|
|
96
|
+
pointsTestnetExperience,
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
createNewWallet()
|
|
101
|
+
}, [
|
|
102
|
+
account,
|
|
103
|
+
campaign,
|
|
104
|
+
isDev,
|
|
105
|
+
isWalletOwnershipVerified,
|
|
106
|
+
pointsTestnetExperience,
|
|
107
|
+
])
|
|
108
|
+
|
|
109
|
+
useEffect(() => {
|
|
110
|
+
const getBasePoints = async () => {
|
|
111
|
+
if (campaign) {
|
|
112
|
+
const estimatedPoints = await CampaignService.getEstimatedPoints(
|
|
113
|
+
campaign.campaignGroupId,
|
|
114
|
+
minDepositAmountBN.toString(),
|
|
115
|
+
isDev,
|
|
116
|
+
pointsTestnetExperience,
|
|
117
|
+
)
|
|
118
|
+
const campaignPoints = estimatedPoints.find(
|
|
119
|
+
(item) => item.campaignId === campaign.id,
|
|
120
|
+
)
|
|
121
|
+
if (campaignPoints) {
|
|
122
|
+
const { juniorTranchePoints, seniorTranchePoints } = campaignPoints
|
|
123
|
+
if (isUniTranche) {
|
|
124
|
+
setCampaignBasePoints(juniorTranchePoints ?? 0)
|
|
125
|
+
} else {
|
|
126
|
+
setCampaignBasePoints(
|
|
127
|
+
juniorTranchePoints < seniorTranchePoints
|
|
128
|
+
? juniorTranchePoints
|
|
129
|
+
: seniorTranchePoints,
|
|
130
|
+
)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
getBasePoints()
|
|
136
|
+
}, [
|
|
137
|
+
campaign,
|
|
138
|
+
isDev,
|
|
139
|
+
isUniTranche,
|
|
140
|
+
minDepositAmountBN,
|
|
141
|
+
pointsTestnetExperience,
|
|
142
|
+
])
|
|
143
|
+
|
|
144
|
+
const approveLender = useCallback(async () => {
|
|
145
|
+
try {
|
|
146
|
+
isActionOngoingRef.current = true
|
|
147
|
+
setLoadingType('approveLender')
|
|
148
|
+
await IdentityServiceV2.approveLender(
|
|
149
|
+
account!,
|
|
150
|
+
chainId!,
|
|
151
|
+
poolInfo.juniorTrancheVault,
|
|
152
|
+
isDev,
|
|
153
|
+
)
|
|
154
|
+
if (!isUniTranche) {
|
|
155
|
+
await IdentityServiceV2.approveLender(
|
|
156
|
+
account!,
|
|
157
|
+
chainId!,
|
|
158
|
+
poolInfo.seniorTrancheVault,
|
|
159
|
+
isDev,
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
if (isUniTranche) {
|
|
163
|
+
changeTranche('junior')
|
|
164
|
+
dispatch(setStep(WIDGET_STEP.ChooseAmount))
|
|
165
|
+
} else {
|
|
166
|
+
dispatch(setStep(WIDGET_STEP.ChooseTranche))
|
|
167
|
+
}
|
|
168
|
+
} finally {
|
|
169
|
+
isActionOngoingRef.current = false
|
|
170
|
+
setLoadingType(undefined)
|
|
171
|
+
}
|
|
172
|
+
}, [
|
|
173
|
+
account,
|
|
174
|
+
chainId,
|
|
175
|
+
changeTranche,
|
|
176
|
+
dispatch,
|
|
177
|
+
isDev,
|
|
178
|
+
isUniTranche,
|
|
179
|
+
poolInfo.juniorTrancheVault,
|
|
180
|
+
poolInfo.seniorTrancheVault,
|
|
181
|
+
])
|
|
182
|
+
|
|
183
|
+
const checkVerificationStatus = useCallback(async () => {
|
|
184
|
+
if (isActionOngoingRef.current || isKYCResumedRef.current) {
|
|
185
|
+
return
|
|
186
|
+
}
|
|
187
|
+
try {
|
|
188
|
+
if (account && chainId) {
|
|
189
|
+
isActionOngoingRef.current = true
|
|
190
|
+
setLoadingType('verificationStatus')
|
|
191
|
+
const verificationStatus =
|
|
192
|
+
await IdentityServiceV2.getVerificationStatusV2(
|
|
193
|
+
account,
|
|
194
|
+
chainId,
|
|
195
|
+
isDev,
|
|
196
|
+
)
|
|
197
|
+
setVerificationStatus(verificationStatus)
|
|
198
|
+
setInquiryId(verificationStatus.personaInquiryId)
|
|
199
|
+
|
|
200
|
+
switch (verificationStatus.status) {
|
|
201
|
+
case IdentityVerificationStatusV2.NOT_STARTED: {
|
|
202
|
+
const startVerificationResult =
|
|
203
|
+
await IdentityServiceV2.startVerification(account, chainId, isDev)
|
|
204
|
+
setInquiryId(startVerificationResult.personaInquiryId)
|
|
205
|
+
setKYCCopy(KYCCopies.verifyIdentity)
|
|
206
|
+
setLoadingType(undefined)
|
|
207
|
+
break
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
case IdentityVerificationStatusV2.CREATED: {
|
|
211
|
+
setKYCCopy(KYCCopies.verifyIdentity)
|
|
212
|
+
setLoadingType(undefined)
|
|
213
|
+
break
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
case IdentityVerificationStatusV2.PENDING: {
|
|
217
|
+
if (!isKYCCompletedRef.current) {
|
|
218
|
+
const resumeVerificationResult =
|
|
219
|
+
await IdentityServiceV2.resumeVerification(
|
|
220
|
+
account,
|
|
221
|
+
chainId,
|
|
222
|
+
isDev,
|
|
223
|
+
)
|
|
224
|
+
verificationStatus.status = resumeVerificationResult.status
|
|
225
|
+
setVerificationStatus(verificationStatus)
|
|
226
|
+
setSessionToken(resumeVerificationResult.sessionToken)
|
|
227
|
+
setLoadingType(undefined)
|
|
228
|
+
isKYCResumedRef.current = true
|
|
229
|
+
} else {
|
|
230
|
+
setLoadingType('verificationStatus')
|
|
231
|
+
}
|
|
232
|
+
setKYCCopy(KYCCopies.verifyIdentity)
|
|
233
|
+
break
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
case IdentityVerificationStatusV2.EXPIRED: {
|
|
237
|
+
const resumeVerificationResult =
|
|
238
|
+
await IdentityServiceV2.resumeVerification(
|
|
239
|
+
account,
|
|
240
|
+
chainId,
|
|
241
|
+
isDev,
|
|
242
|
+
)
|
|
243
|
+
verificationStatus.status = resumeVerificationResult.status
|
|
244
|
+
setVerificationStatus(verificationStatus)
|
|
245
|
+
setSessionToken(resumeVerificationResult.sessionToken)
|
|
246
|
+
setKYCCopy(KYCCopies.verifyIdentity)
|
|
247
|
+
setLoadingType(undefined)
|
|
248
|
+
isKYCResumedRef.current = true
|
|
249
|
+
break
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
case IdentityVerificationStatusV2.APPROVED: {
|
|
253
|
+
await approveLender()
|
|
254
|
+
break
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
case IdentityVerificationStatusV2.DECLINED: {
|
|
258
|
+
setKYCCopy(KYCCopies.verificationDeclined)
|
|
259
|
+
setLoadingType(undefined)
|
|
260
|
+
break
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
case IdentityVerificationStatusV2.NEEDS_REVIEW: {
|
|
264
|
+
setKYCCopy(KYCCopies.verificationNeedsReview)
|
|
265
|
+
setLoadingType(undefined)
|
|
266
|
+
break
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
default:
|
|
270
|
+
break
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
} catch (e: unknown) {
|
|
274
|
+
setAuthError(e)
|
|
275
|
+
} finally {
|
|
276
|
+
isActionOngoingRef.current = false
|
|
277
|
+
}
|
|
278
|
+
}, [KYCCopies, account, approveLender, chainId, isDev, setAuthError])
|
|
279
|
+
|
|
280
|
+
useEffect(() => {
|
|
281
|
+
checkVerificationStatus()
|
|
282
|
+
}, [checkVerificationStatus])
|
|
283
|
+
|
|
284
|
+
useEffect(() => {
|
|
285
|
+
if (isWalletOwnershipVerificationRequired && isWalletOwnershipVerified) {
|
|
286
|
+
checkVerificationStatus()
|
|
287
|
+
}
|
|
288
|
+
}, [
|
|
289
|
+
checkVerificationStatus,
|
|
290
|
+
isWalletOwnershipVerificationRequired,
|
|
291
|
+
isWalletOwnershipVerified,
|
|
292
|
+
])
|
|
293
|
+
|
|
294
|
+
useEffect(() => {
|
|
295
|
+
const interval = setInterval(() => {
|
|
296
|
+
if (
|
|
297
|
+
verificationStatus?.status &&
|
|
298
|
+
[
|
|
299
|
+
IdentityVerificationStatusV2.CREATED,
|
|
300
|
+
IdentityVerificationStatusV2.PENDING,
|
|
301
|
+
].includes(verificationStatus.status)
|
|
302
|
+
) {
|
|
303
|
+
checkVerificationStatus()
|
|
304
|
+
}
|
|
305
|
+
}, 10 * 1000)
|
|
306
|
+
// eslint-disable-next-line consistent-return
|
|
307
|
+
return () => clearInterval(interval)
|
|
308
|
+
}, [checkVerificationStatus, verificationStatus?.status])
|
|
309
|
+
|
|
310
|
+
useEffect(() => {
|
|
311
|
+
if (errorType === 'NotSignedIn') {
|
|
312
|
+
setLoadingType(undefined)
|
|
313
|
+
setKYCCopy(KYCCopies.signInRequired)
|
|
314
|
+
} else if (errorType === 'UserRejected') {
|
|
315
|
+
dispatch(
|
|
316
|
+
setError({
|
|
317
|
+
errorMessage: 'User has rejected the transaction.',
|
|
318
|
+
}),
|
|
319
|
+
)
|
|
320
|
+
} else if (errorType === 'Other') {
|
|
321
|
+
dispatch(
|
|
322
|
+
setError({
|
|
323
|
+
errorMessage: 'Something went wrong. Please try again later.',
|
|
324
|
+
}),
|
|
325
|
+
)
|
|
326
|
+
}
|
|
327
|
+
}, [KYCCopies.signInRequired, dispatch, errorType])
|
|
328
|
+
|
|
329
|
+
useEffect(() => {
|
|
330
|
+
const modalElement = document.getElementById('huma-modal')
|
|
331
|
+
if (modalElement) {
|
|
332
|
+
modalElement.style.visibility = showPersonaClient ? 'hidden' : 'visible'
|
|
333
|
+
}
|
|
334
|
+
}, [showPersonaClient])
|
|
335
|
+
|
|
336
|
+
const startKYC = async () => {
|
|
337
|
+
isActionOngoingRef.current = true
|
|
338
|
+
isKYCResumedRef.current = false
|
|
339
|
+
setLoadingType('startKYC')
|
|
340
|
+
const client: Client = new Persona.Client({
|
|
341
|
+
inquiryId,
|
|
342
|
+
sessionToken,
|
|
343
|
+
onReady: () => {
|
|
344
|
+
client.open()
|
|
345
|
+
setShowPersonaClient(true)
|
|
346
|
+
},
|
|
347
|
+
onComplete: () => {
|
|
348
|
+
isKYCCompletedRef.current = true
|
|
349
|
+
isActionOngoingRef.current = false
|
|
350
|
+
setShowPersonaClient(false)
|
|
351
|
+
checkVerificationStatus()
|
|
352
|
+
},
|
|
353
|
+
onCancel: () => {
|
|
354
|
+
isActionOngoingRef.current = false
|
|
355
|
+
setShowPersonaClient(false)
|
|
356
|
+
setLoadingType(undefined)
|
|
357
|
+
},
|
|
358
|
+
onError: () => {
|
|
359
|
+
isActionOngoingRef.current = false
|
|
360
|
+
setShowPersonaClient(false)
|
|
361
|
+
setLoadingType(undefined)
|
|
362
|
+
},
|
|
363
|
+
})
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const handleAction = () => {
|
|
367
|
+
if (verificationStatus) {
|
|
368
|
+
switch (verificationStatus.status) {
|
|
369
|
+
case IdentityVerificationStatusV2.NOT_STARTED:
|
|
370
|
+
case IdentityVerificationStatusV2.CREATED:
|
|
371
|
+
case IdentityVerificationStatusV2.PENDING:
|
|
372
|
+
case IdentityVerificationStatusV2.EXPIRED:
|
|
373
|
+
startKYC()
|
|
374
|
+
break
|
|
375
|
+
|
|
376
|
+
case IdentityVerificationStatusV2.DECLINED:
|
|
377
|
+
case IdentityVerificationStatusV2.NEEDS_REVIEW:
|
|
378
|
+
handleClose()
|
|
379
|
+
break
|
|
380
|
+
|
|
381
|
+
default:
|
|
382
|
+
break
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
const styles = {
|
|
388
|
+
iconWrapper: css`
|
|
389
|
+
${theme.cssMixins.rowCentered};
|
|
390
|
+
margin-top: ${theme.spacing(8)};
|
|
391
|
+
& > img {
|
|
392
|
+
width: 144px;
|
|
393
|
+
}
|
|
394
|
+
`,
|
|
395
|
+
description: css`
|
|
396
|
+
margin-top: ${theme.spacing(10)};
|
|
397
|
+
padding: ${theme.spacing(0, 2)};
|
|
398
|
+
font-weight: 400;
|
|
399
|
+
font-size: 16px;
|
|
400
|
+
color: ${theme.palette.text.primary};
|
|
401
|
+
`,
|
|
402
|
+
points: css`
|
|
403
|
+
color: ${theme.palette.primary.main};
|
|
404
|
+
font-weight: 700;
|
|
405
|
+
`,
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
if (!loadingType) {
|
|
409
|
+
return (
|
|
410
|
+
<WrapperModal title={kycCopy.title}>
|
|
411
|
+
<Box css={styles.iconWrapper}>
|
|
412
|
+
<img src={ApproveLenderImg} alt='approve-lender' />
|
|
413
|
+
</Box>
|
|
414
|
+
{campaign && kycCopy === KYCCopies.verifyIdentity ? (
|
|
415
|
+
<Box css={styles.description}>
|
|
416
|
+
<span>You'll be rewarded with a minimum of</span>
|
|
417
|
+
<span css={styles.points}>
|
|
418
|
+
{' '}
|
|
419
|
+
{formatNumber(campaignBasePoints)} Huma points{' '}
|
|
420
|
+
</span>
|
|
421
|
+
<span>after completing KYC and your first investment.</span>
|
|
422
|
+
</Box>
|
|
423
|
+
) : (
|
|
424
|
+
<Box css={styles.description}>{kycCopy.description}</Box>
|
|
425
|
+
)}
|
|
426
|
+
|
|
427
|
+
{Boolean(kycCopy.buttonText) && (
|
|
428
|
+
<BottomButton variant='contained' onClick={handleAction}>
|
|
429
|
+
{kycCopy.buttonText}
|
|
430
|
+
</BottomButton>
|
|
431
|
+
)}
|
|
432
|
+
</WrapperModal>
|
|
433
|
+
)
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return (
|
|
437
|
+
<LoadingModal
|
|
438
|
+
title='Lender Approval'
|
|
439
|
+
description={LoadingCopiesByType[loadingType].description}
|
|
440
|
+
/>
|
|
441
|
+
)
|
|
442
|
+
}
|