@huma-finance/widgets 0.0.31 → 0.0.33

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.
Files changed (176) hide show
  1. package/.env.example +2 -2
  2. package/.eslintignore +2 -2
  3. package/.eslintrc.js +64 -64
  4. package/.prettierignore +4 -4
  5. package/.prettierrc.js +16 -16
  6. package/API.md +332 -332
  7. package/LICENSE +660 -660
  8. package/README.md +48 -48
  9. package/babel.config.js +15 -15
  10. package/config-overrides.js +9 -9
  11. package/cosmos.config.json +7 -7
  12. package/cypress/e2e/01-invoice-factoring-borrow.test.ts +62 -62
  13. package/cypress/support/e2e.ts +76 -76
  14. package/cypress/support/ethereum.ts +142 -142
  15. package/cypress/tsconfig.json +9 -9
  16. package/cypress/utils/index.ts +54 -54
  17. package/cypress.config.ts +20 -20
  18. package/dist/cjs/index.cjs +1026 -296
  19. package/dist/cjs/index.cjs.map +1 -1
  20. package/dist/index.d.ts +193 -193
  21. package/dist/index.js +1028 -299
  22. package/dist/index.js.map +1 -1
  23. package/jsdoc2md.json +20 -20
  24. package/package.json +4 -4
  25. package/public/index.html +40 -40
  26. package/public/manifest.json +25 -25
  27. package/public/robots.txt +3 -3
  28. package/rollup.config.js +81 -81
  29. package/src/components/Activity.tsx +132 -132
  30. package/src/components/ApolloWrapper.tsx +15 -15
  31. package/src/components/ApproveAllowanceModal.tsx +121 -121
  32. package/src/components/BottomButton.tsx +33 -33
  33. package/src/components/ChainNotSupportedModal.tsx +33 -33
  34. package/src/components/ChooseAmountModal.tsx +322 -322
  35. package/src/components/ConfirmTransferModal.tsx +153 -153
  36. package/src/components/CreditLine/borrow/1-Evaluation.tsx +157 -157
  37. package/src/components/CreditLine/borrow/2-ChooseAmount.tsx +68 -68
  38. package/src/components/CreditLine/borrow/3-Transfer.tsx +44 -44
  39. package/src/components/CreditLine/borrow/4-ApproveAllowance.tsx +29 -29
  40. package/src/components/CreditLine/borrow/5-Success.tsx +38 -30
  41. package/src/components/CreditLine/borrow/6-Notifications.tsx +10 -0
  42. package/src/components/CreditLine/borrow/index.tsx +136 -117
  43. package/src/components/CreditLine/payment/1-ChooseAmount.tsx +67 -67
  44. package/src/components/CreditLine/payment/2-ApproveAllowance.tsx +23 -23
  45. package/src/components/CreditLine/payment/3-Transfer.tsx +34 -34
  46. package/src/components/CreditLine/payment/4-Success.tsx +39 -39
  47. package/src/components/CreditLine/payment/index.tsx +94 -94
  48. package/src/components/ErrorModal.tsx +132 -132
  49. package/src/components/Factoring/FactoredList.tsx +143 -143
  50. package/src/components/Factoring/UpcomingList.tsx +90 -90
  51. package/src/components/Factoring/index.ts +2 -2
  52. package/src/components/HumaLoading.tsx +68 -68
  53. package/src/components/HumaSnackBar.tsx +60 -0
  54. package/src/components/HumaTable.tsx +158 -158
  55. package/src/components/InvoiceFactoring/borrow/1-Evaluation.tsx +49 -49
  56. package/src/components/InvoiceFactoring/borrow/2-ChooseAmount.tsx +88 -88
  57. package/src/components/InvoiceFactoring/borrow/3-ConfirmTransfer.tsx +37 -37
  58. package/src/components/InvoiceFactoring/borrow/4-ApproveNFT.tsx +55 -55
  59. package/src/components/InvoiceFactoring/borrow/5-Transfer.tsx +34 -34
  60. package/src/components/InvoiceFactoring/borrow/6-Success.tsx +20 -20
  61. package/src/components/InvoiceFactoring/borrow/index.tsx +94 -94
  62. package/src/components/InvoiceFactoring/payment/1-ChooseAmount.tsx +67 -67
  63. package/src/components/InvoiceFactoring/payment/2-ApproveAllowance.tsx +23 -23
  64. package/src/components/InvoiceFactoring/payment/3-Transfer.tsx +34 -34
  65. package/src/components/InvoiceFactoring/payment/4-Success.tsx +23 -23
  66. package/src/components/InvoiceFactoring/payment/index.tsx +86 -86
  67. package/src/components/Lend/supply/1-Evaluation/EvaluationEA.tsx +86 -0
  68. package/src/components/Lend/supply/1-Evaluation/EvaluationKYC.tsx +287 -0
  69. package/src/components/Lend/supply/1-Evaluation/index.tsx +31 -0
  70. package/src/components/Lend/supply/2-ChooseAmount.tsx +69 -70
  71. package/src/components/Lend/supply/3-ApproveAllowance.tsx +25 -25
  72. package/src/components/Lend/supply/{6-Transfer.tsx → 4-Transfer.tsx} +32 -32
  73. package/src/components/Lend/supply/{7-Success.tsx → 5-Success.tsx} +60 -49
  74. package/src/components/Lend/supply/6-Notifications.tsx +10 -0
  75. package/src/components/Lend/supply/index.tsx +167 -144
  76. package/src/components/Lend/withdraw/1-CheckWithdrawble.tsx +73 -73
  77. package/src/components/Lend/withdraw/2-ChooseAmount.tsx +50 -50
  78. package/src/components/Lend/withdraw/3-Transfer.tsx +32 -32
  79. package/src/components/Lend/withdraw/4-Success.tsx +49 -49
  80. package/src/components/Lend/withdraw/index.tsx +101 -101
  81. package/src/components/LoadingModal.tsx +49 -49
  82. package/src/components/Notifi/NotifiSubscriptionModal.tsx +264 -0
  83. package/src/components/StreamFactoring/borrow/1-Evaluation.tsx +55 -55
  84. package/src/components/StreamFactoring/borrow/2-ChooseAmount.tsx +127 -127
  85. package/src/components/StreamFactoring/borrow/3-ConfirmTransfer.tsx +42 -42
  86. package/src/components/StreamFactoring/borrow/4-ApproveAllowance.tsx +33 -33
  87. package/src/components/StreamFactoring/borrow/5-Permit.tsx +144 -144
  88. package/src/components/StreamFactoring/borrow/6-Transfer.tsx +37 -37
  89. package/src/components/StreamFactoring/borrow/7-Success.tsx +20 -20
  90. package/src/components/StreamFactoring/borrow/index.tsx +94 -94
  91. package/src/components/StreamFactoring/payment/ChooseAmount.tsx +54 -54
  92. package/src/components/StreamFactoring/payment/Success.tsx +23 -23
  93. package/src/components/StreamFactoring/payment/Transfer.tsx +34 -34
  94. package/src/components/StreamFactoring/payment/index.tsx +66 -66
  95. package/src/components/SuperfluidFactoring/SuperfluidFactoredList.tsx +70 -70
  96. package/src/components/SuperfluidFactoring/SuperfluidUpcomingList.tsx +167 -167
  97. package/src/components/SuperfluidFactoring/index.tsx +85 -85
  98. package/src/components/TxDoneModal.tsx +85 -83
  99. package/src/components/TxSendModal.tsx +59 -59
  100. package/src/components/ViewOnExplorer.tsx +26 -26
  101. package/src/components/WidgetWrapper.tsx +74 -74
  102. package/src/components/WrapperModal.tsx +54 -54
  103. package/src/components/buttons/TableActionButton.tsx +36 -36
  104. package/src/components/buttons/index.ts +1 -1
  105. package/src/components/humaModal/HumaModal.tsx +68 -68
  106. package/src/components/humaModal/HumaModalHeader.tsx +70 -70
  107. package/src/components/humaModal/index.tsx +2 -2
  108. package/src/components/icons/approve-lender.svg +30 -30
  109. package/src/components/icons/auto-payback.svg +40 -40
  110. package/src/components/icons/check-circle.svg +3 -3
  111. package/src/components/icons/check-green.svg +3 -3
  112. package/src/components/icons/check.svg +10 -10
  113. package/src/components/icons/donut.svg +904 -904
  114. package/src/components/icons/ellipse.svg +3 -3
  115. package/src/components/icons/huma-full.svg +22 -22
  116. package/src/components/icons/huma.svg +15 -15
  117. package/src/components/icons/index.tsx +93 -93
  118. package/src/components/icons/loader.svg +229 -229
  119. package/src/components/icons/metamask.svg +31 -31
  120. package/src/components/icons/polygon.svg +16 -16
  121. package/src/components/icons/receipt.svg +3 -3
  122. package/src/components/icons/separator.svg +3 -3
  123. package/src/components/icons/sorry.svg +31 -31
  124. package/src/components/icons/usdc.svg +5 -5
  125. package/src/components/icons/wallet-connect.svg +11 -11
  126. package/src/cosmos/CreditLineBorrow.fixture.tsx +86 -86
  127. package/src/cosmos/CreditLinePayment.fixture.tsx +50 -50
  128. package/src/cosmos/InvoiceFactoringBorrow.fixture.tsx +111 -111
  129. package/src/cosmos/InvoiceFactoringPayment.fixture.tsx +67 -67
  130. package/src/cosmos/LendSupply.fixture.tsx +75 -75
  131. package/src/cosmos/LendWithdraw.fixture.tsx +43 -43
  132. package/src/cosmos/SDKTesting.fixture.tsx +616 -616
  133. package/src/cosmos/SuperfluidFactoringBorrow.fixture.tsx +15 -15
  134. package/src/cosmos/WalletWrapper.tsx +52 -52
  135. package/src/cosmos/abis/InvoiceNFT.json +644 -644
  136. package/src/cosmos/abis/ReceivableFactoringPool.json +1529 -1529
  137. package/src/cosmos/utils/env.ts +6 -6
  138. package/src/cosmos/utils/index.ts +169 -169
  139. package/src/fonts/Recoleta/Recoleta-Black.otf +0 -0
  140. package/src/fonts/Recoleta/Recoleta-Bold.otf +0 -0
  141. package/src/fonts/Recoleta/Recoleta-Light.otf +0 -0
  142. package/src/fonts/Recoleta/Recoleta-Medium.otf +0 -0
  143. package/src/fonts/Recoleta/Recoleta-Regular.otf +0 -0
  144. package/src/fonts/Recoleta/Recoleta-RegularDEMO.otf +0 -0
  145. package/src/fonts/Recoleta/Recoleta-SemiBold.otf +0 -0
  146. package/src/fonts/Recoleta/Recoleta-Thin.otf +0 -0
  147. package/src/hooks/useEA.ts +53 -53
  148. package/src/hooks/useNotifi.ts +71 -0
  149. package/src/hooks/useRedux.ts +6 -6
  150. package/src/index.css +61 -61
  151. package/src/index.tsx +301 -301
  152. package/src/react-app-env.d.ts +1 -1
  153. package/src/reportWebVitals.ts +15 -15
  154. package/src/setupTests.ts +6 -6
  155. package/src/store/index.ts +27 -27
  156. package/src/store/widgets.reducers.ts +120 -120
  157. package/src/store/widgets.selectors.ts +3 -3
  158. package/src/store/widgets.store.ts +55 -54
  159. package/src/theme/breakpoints.ts +10 -10
  160. package/src/theme/components.ts +70 -70
  161. package/src/theme/coreThemeConstants.ts +29 -29
  162. package/src/theme/cssMixins.ts +92 -92
  163. package/src/theme/hooks/useGetSizes.ts +31 -31
  164. package/src/theme/index.ts +24 -24
  165. package/src/theme/palette.ts +150 -150
  166. package/src/theme/shape.ts +7 -7
  167. package/src/theme/theme.types.ts +80 -80
  168. package/src/theme/typography.ts +117 -117
  169. package/src/utilTypes.d.ts +31 -31
  170. package/src/utils/env.ts +10 -10
  171. package/tsconfig.build.json +7 -7
  172. package/tsconfig.json +32 -32
  173. package/webpack.cosmos.js +54 -54
  174. package/src/components/Lend/supply/1-Evaluation.tsx +0 -175
  175. package/src/components/Lend/supply/4-ConfirmTransfer.tsx +0 -104
  176. package/src/components/NotifiSubscriptionModal.tsx +0 -84
@@ -1,49 +1,49 @@
1
- import { useWeb3React } from '@web3-react/core'
2
- import {
3
- decodeLogs,
4
- downScale,
5
- formatMoney,
6
- PoolInfoType,
7
- sendTxAtom,
8
- } from '@huma-finance/shared'
9
- import transferAbi from '@huma-finance/shared/dist/abis/Transfer.json'
10
- import { useAtom } from 'jotai'
11
- import React, { useEffect, useState } from 'react'
12
-
13
- import { TxDoneModal } from '../../TxDoneModal'
14
-
15
- type Props = {
16
- poolInfo: PoolInfoType
17
- handleAction: () => void
18
- }
19
-
20
- export function Success({ poolInfo, handleAction }: Props): React.ReactElement {
21
- const { account } = useWeb3React()
22
- const { poolUnderlyingToken } = poolInfo
23
- const [{ txReceipt }] = useAtom(sendTxAtom)
24
- const { symbol, decimals, address } = poolUnderlyingToken
25
- const [withdrawAmount, setWithdrawAmount] = useState<string | undefined>()
26
-
27
- useEffect(() => {
28
- if (txReceipt) {
29
- const events = decodeLogs(txReceipt.logs, transferAbi)
30
- if (events) {
31
- events.forEach((event) => {
32
- const { from, to, value } = event.args
33
- if (
34
- from.toLowerCase() === poolInfo.pool.toLowerCase() &&
35
- to.toLowerCase() === account?.toLowerCase()
36
- ) {
37
- setWithdrawAmount(downScale(value.toString(), decimals))
38
- }
39
- })
40
- }
41
- }
42
- }, [account, address, decimals, poolInfo.pool, txReceipt])
43
-
44
- const content = [
45
- `You successfully withdrawn ${formatMoney(withdrawAmount)} ${symbol}.`,
46
- ]
47
-
48
- return <TxDoneModal handleAction={handleAction} content={content} />
49
- }
1
+ import { useWeb3React } from '@web3-react/core'
2
+ import {
3
+ decodeLogs,
4
+ downScale,
5
+ formatMoney,
6
+ PoolInfoType,
7
+ sendTxAtom,
8
+ } from '@huma-finance/shared'
9
+ import transferAbi from '@huma-finance/shared/dist/abis/Transfer.json'
10
+ import { useAtom } from 'jotai'
11
+ import React, { useEffect, useState } from 'react'
12
+
13
+ import { TxDoneModal } from '../../TxDoneModal'
14
+
15
+ type Props = {
16
+ poolInfo: PoolInfoType
17
+ handleAction: () => void
18
+ }
19
+
20
+ export function Success({ poolInfo, handleAction }: Props): React.ReactElement {
21
+ const { account } = useWeb3React()
22
+ const { poolUnderlyingToken } = poolInfo
23
+ const [{ txReceipt }] = useAtom(sendTxAtom)
24
+ const { symbol, decimals, address } = poolUnderlyingToken
25
+ const [withdrawAmount, setWithdrawAmount] = useState<string | undefined>()
26
+
27
+ useEffect(() => {
28
+ if (txReceipt) {
29
+ const events = decodeLogs(txReceipt.logs, transferAbi)
30
+ if (events) {
31
+ events.forEach((event) => {
32
+ const { from, to, value } = event.args
33
+ if (
34
+ from.toLowerCase() === poolInfo.pool.toLowerCase() &&
35
+ to.toLowerCase() === account?.toLowerCase()
36
+ ) {
37
+ setWithdrawAmount(downScale(value.toString(), decimals))
38
+ }
39
+ })
40
+ }
41
+ }
42
+ }, [account, address, decimals, poolInfo.pool, txReceipt])
43
+
44
+ const content = [
45
+ `You successfully withdrawn ${formatMoney(withdrawAmount)} ${symbol}.`,
46
+ ]
47
+
48
+ return <TxDoneModal handleAction={handleAction} content={content} />
49
+ }
@@ -1,101 +1,101 @@
1
- import { useWeb3React } from '@web3-react/core'
2
- import {
3
- POOL_NAME,
4
- POOL_TYPE,
5
- useLenderPosition,
6
- usePoolInfo,
7
- } from '@huma-finance/shared'
8
- import React, { useCallback, useEffect } from 'react'
9
- import { useDispatch } from 'react-redux'
10
-
11
- import { useAppSelector } from '../../../hooks/useRedux'
12
- import { setStep } from '../../../store/widgets.reducers'
13
- import { selectWidgetState } from '../../../store/widgets.selectors'
14
- import { WIDGET_STEP } from '../../../store/widgets.store'
15
- import { ErrorModal } from '../../ErrorModal'
16
- import { WidgetWrapper } from '../../WidgetWrapper'
17
- import { CheckWithdrawable } from './1-CheckWithdrawble'
18
- import { ChooseAmount } from './2-ChooseAmount'
19
- import { Transfer } from './3-Transfer'
20
- import { Success } from './4-Success'
21
-
22
- /**
23
- * Lend pool withdraw props
24
- * @typedef {Object} LendWithdrawProps
25
- * @property {POOL_NAME} poolName The name of the pool.
26
- * @property {POOL_TYPE} poolType The type of the pool.
27
- * @property {function():void} handleClose Function to notify to close the widget modal when user clicks the 'x' close button.
28
- * @property {function((number|undefined)):void|undefined} handleSuccess Optional function to notify that the lending pool withdraw action is successful.
29
- */
30
- export type LendWithdrawProps = {
31
- poolName: keyof typeof POOL_NAME
32
- poolType: keyof typeof POOL_TYPE
33
- handleClose: () => void
34
- handleSuccess?: (blockNumber?: number) => void
35
- }
36
-
37
- export function LendWithdraw({
38
- poolName: poolNameStr,
39
- poolType: poolTypeStr,
40
- handleClose,
41
- handleSuccess,
42
- }: LendWithdrawProps): React.ReactElement | null {
43
- const dispatch = useDispatch()
44
- const { account } = useWeb3React()
45
- const poolName = POOL_NAME[poolNameStr]
46
- const poolType = POOL_TYPE[poolTypeStr]
47
- const poolInfo = usePoolInfo(poolName, poolType)
48
- const { step, errorMessage } = useAppSelector(selectWidgetState)
49
- const [lenderPosition, refreshLenderPosition] = useLenderPosition(
50
- poolName,
51
- poolType,
52
- account,
53
- )
54
-
55
- useEffect(() => {
56
- if (!step && lenderPosition) {
57
- dispatch(setStep(WIDGET_STEP.CheckWithdrawable))
58
- }
59
- }, [dispatch, lenderPosition, step])
60
-
61
- const handleWithdrawSuccess = useCallback(
62
- (blockNumber: number) => {
63
- refreshLenderPosition()
64
- if (handleSuccess) {
65
- handleSuccess(blockNumber)
66
- }
67
- },
68
- [handleSuccess, refreshLenderPosition],
69
- )
70
-
71
- if (!poolInfo) {
72
- return null
73
- }
74
-
75
- return (
76
- <WidgetWrapper
77
- isOpen
78
- handleClose={handleClose}
79
- handleSuccess={handleWithdrawSuccess}
80
- >
81
- {(!step || step === WIDGET_STEP.CheckWithdrawable) && (
82
- <CheckWithdrawable poolInfo={poolInfo} handleClose={handleClose} />
83
- )}
84
- {step === WIDGET_STEP.ChooseAmount && (
85
- <ChooseAmount poolInfo={poolInfo} lenderPosition={lenderPosition!} />
86
- )}
87
- {step === WIDGET_STEP.Transfer && <Transfer poolInfo={poolInfo} />}
88
- {step === WIDGET_STEP.Done && (
89
- <Success poolInfo={poolInfo} handleAction={handleClose} />
90
- )}
91
- {step === WIDGET_STEP.Error && (
92
- <ErrorModal
93
- title='Withdraw'
94
- errorReason='Sorry there was an error'
95
- errorMessage={errorMessage}
96
- handleOk={handleClose}
97
- />
98
- )}
99
- </WidgetWrapper>
100
- )
101
- }
1
+ import { useWeb3React } from '@web3-react/core'
2
+ import {
3
+ POOL_NAME,
4
+ POOL_TYPE,
5
+ useLenderPosition,
6
+ usePoolInfo,
7
+ } from '@huma-finance/shared'
8
+ import React, { useCallback, useEffect } from 'react'
9
+ import { useDispatch } from 'react-redux'
10
+
11
+ import { useAppSelector } from '../../../hooks/useRedux'
12
+ import { setStep } from '../../../store/widgets.reducers'
13
+ import { selectWidgetState } from '../../../store/widgets.selectors'
14
+ import { WIDGET_STEP } from '../../../store/widgets.store'
15
+ import { ErrorModal } from '../../ErrorModal'
16
+ import { WidgetWrapper } from '../../WidgetWrapper'
17
+ import { CheckWithdrawable } from './1-CheckWithdrawble'
18
+ import { ChooseAmount } from './2-ChooseAmount'
19
+ import { Transfer } from './3-Transfer'
20
+ import { Success } from './4-Success'
21
+
22
+ /**
23
+ * Lend pool withdraw props
24
+ * @typedef {Object} LendWithdrawProps
25
+ * @property {POOL_NAME} poolName The name of the pool.
26
+ * @property {POOL_TYPE} poolType The type of the pool.
27
+ * @property {function():void} handleClose Function to notify to close the widget modal when user clicks the 'x' close button.
28
+ * @property {function((number|undefined)):void|undefined} handleSuccess Optional function to notify that the lending pool withdraw action is successful.
29
+ */
30
+ export type LendWithdrawProps = {
31
+ poolName: keyof typeof POOL_NAME
32
+ poolType: keyof typeof POOL_TYPE
33
+ handleClose: () => void
34
+ handleSuccess?: (blockNumber?: number) => void
35
+ }
36
+
37
+ export function LendWithdraw({
38
+ poolName: poolNameStr,
39
+ poolType: poolTypeStr,
40
+ handleClose,
41
+ handleSuccess,
42
+ }: LendWithdrawProps): React.ReactElement | null {
43
+ const dispatch = useDispatch()
44
+ const { account } = useWeb3React()
45
+ const poolName = POOL_NAME[poolNameStr]
46
+ const poolType = POOL_TYPE[poolTypeStr]
47
+ const poolInfo = usePoolInfo(poolName, poolType)
48
+ const { step, errorMessage } = useAppSelector(selectWidgetState)
49
+ const [lenderPosition, refreshLenderPosition] = useLenderPosition(
50
+ poolName,
51
+ poolType,
52
+ account,
53
+ )
54
+
55
+ useEffect(() => {
56
+ if (!step && lenderPosition) {
57
+ dispatch(setStep(WIDGET_STEP.CheckWithdrawable))
58
+ }
59
+ }, [dispatch, lenderPosition, step])
60
+
61
+ const handleWithdrawSuccess = useCallback(
62
+ (blockNumber: number) => {
63
+ refreshLenderPosition()
64
+ if (handleSuccess) {
65
+ handleSuccess(blockNumber)
66
+ }
67
+ },
68
+ [handleSuccess, refreshLenderPosition],
69
+ )
70
+
71
+ if (!poolInfo) {
72
+ return null
73
+ }
74
+
75
+ return (
76
+ <WidgetWrapper
77
+ isOpen
78
+ handleClose={handleClose}
79
+ handleSuccess={handleWithdrawSuccess}
80
+ >
81
+ {(!step || step === WIDGET_STEP.CheckWithdrawable) && (
82
+ <CheckWithdrawable poolInfo={poolInfo} handleClose={handleClose} />
83
+ )}
84
+ {step === WIDGET_STEP.ChooseAmount && (
85
+ <ChooseAmount poolInfo={poolInfo} lenderPosition={lenderPosition!} />
86
+ )}
87
+ {step === WIDGET_STEP.Transfer && <Transfer poolInfo={poolInfo} />}
88
+ {step === WIDGET_STEP.Done && (
89
+ <Success poolInfo={poolInfo} handleAction={handleClose} />
90
+ )}
91
+ {step === WIDGET_STEP.Error && (
92
+ <ErrorModal
93
+ title='Withdraw'
94
+ errorReason='Sorry there was an error'
95
+ errorMessage={errorMessage}
96
+ handleOk={handleClose}
97
+ />
98
+ )}
99
+ </WidgetWrapper>
100
+ )
101
+ }
@@ -1,49 +1,49 @@
1
- import { Box, css, useTheme } from '@mui/material'
2
- import React from 'react'
3
- import { HumaLoading } from './HumaLoading'
4
-
5
- import { WrapperModal } from './WrapperModal'
6
-
7
- type Props = {
8
- title: string
9
- description?: string
10
- hideLoader?: boolean
11
- children?: React.ReactNode
12
- }
13
-
14
- export function LoadingModal({
15
- title,
16
- description,
17
- hideLoader = false,
18
- children,
19
- }: Props): React.ReactElement {
20
- const theme = useTheme()
21
-
22
- const styles = {
23
- loader: css`
24
- width: 100%;
25
- ${theme.cssMixins.rowHCentered};
26
- position: absolute;
27
- top: 50%;
28
- transform: translateY(-50%);
29
- `,
30
- bottom: css`
31
- & .MuiButtonBase-root {
32
- width: 100%;
33
- position: absolute;
34
- bottom: 0;
35
- }
36
- `,
37
- }
38
-
39
- return (
40
- <WrapperModal title={title} subTitle={description}>
41
- {!hideLoader && (
42
- <Box css={styles.loader}>
43
- <HumaLoading />
44
- </Box>
45
- )}
46
- <Box css={styles.bottom}>{children}</Box>
47
- </WrapperModal>
48
- )
49
- }
1
+ import { Box, css, useTheme } from '@mui/material'
2
+ import React from 'react'
3
+ import { HumaLoading } from './HumaLoading'
4
+
5
+ import { WrapperModal } from './WrapperModal'
6
+
7
+ type Props = {
8
+ title: string
9
+ description?: string
10
+ hideLoader?: boolean
11
+ children?: React.ReactNode
12
+ }
13
+
14
+ export function LoadingModal({
15
+ title,
16
+ description,
17
+ hideLoader = false,
18
+ children,
19
+ }: Props): React.ReactElement {
20
+ const theme = useTheme()
21
+
22
+ const styles = {
23
+ loader: css`
24
+ width: 100%;
25
+ ${theme.cssMixins.rowHCentered};
26
+ position: absolute;
27
+ top: 50%;
28
+ transform: translateY(-50%);
29
+ `,
30
+ bottom: css`
31
+ & .MuiButtonBase-root {
32
+ width: 100%;
33
+ position: absolute;
34
+ bottom: 0;
35
+ }
36
+ `,
37
+ }
38
+
39
+ return (
40
+ <WrapperModal title={title} subTitle={description}>
41
+ {!hideLoader && (
42
+ <Box css={styles.loader}>
43
+ <HumaLoading />
44
+ </Box>
45
+ )}
46
+ <Box css={styles.bottom}>{children}</Box>
47
+ </WrapperModal>
48
+ )
49
+ }
@@ -0,0 +1,264 @@
1
+ import React, { useCallback, useEffect, useState } from 'react'
2
+ import { useWeb3React } from '@web3-react/core'
3
+ import {
4
+ NotifiFrontendClient,
5
+ newFrontendClient,
6
+ Uint8SignMessageFunction,
7
+ SignMessageParams,
8
+ CardConfigItemV1,
9
+ DirectPushEventTypeItem,
10
+ EventTypeItem,
11
+ BroadcastEventTypeItem,
12
+ } from '@notifi-network/notifi-frontend-client'
13
+ import { getBlockchainConfigFromChain, txAtom } from '@huma-finance/shared'
14
+ import { ethers } from 'ethers'
15
+ import {
16
+ Box,
17
+ Input,
18
+ InputAdornment,
19
+ Typography,
20
+ css,
21
+ useTheme,
22
+ } from '@mui/material'
23
+ import Email from '@mui/icons-material/Email'
24
+ import { useResetAtom } from 'jotai/utils'
25
+
26
+ import { WrapperModal } from '../WrapperModal'
27
+ import { envUtil } from '../../utils/env'
28
+ import { BottomButton } from '../BottomButton'
29
+ import { LoadingModal } from '../LoadingModal'
30
+ import { CheckIcon } from '../icons'
31
+ import { resetState } from '../../store/widgets.reducers'
32
+ import { useAppDispatch } from '../../hooks/useRedux'
33
+
34
+ type Props = {
35
+ handleSuccess: () => void
36
+ }
37
+
38
+ function getIdFromEventType(eventType: EventTypeItem): string {
39
+ if (eventType.type === 'directPush') {
40
+ const directPushEventType = eventType as DirectPushEventTypeItem
41
+ return (
42
+ directPushEventType.directPushId as {
43
+ value: string
44
+ }
45
+ ).value
46
+ }
47
+ if (eventType.type === 'broadcast') {
48
+ const broadcastEventType = eventType as BroadcastEventTypeItem
49
+ return (
50
+ broadcastEventType.broadcastId as {
51
+ value: string
52
+ }
53
+ ).value
54
+ }
55
+
56
+ return ''
57
+ }
58
+
59
+ async function fetchEventTypes(
60
+ notifiClient: NotifiFrontendClient,
61
+ ): Promise<(EventTypeItem & { enabled: boolean })[]> {
62
+ const subscribedAlerts = await notifiClient.getAlerts()
63
+
64
+ const subscriptionConfig = (await notifiClient.fetchSubscriptionCard({
65
+ id: process.env.REACT_APP_NOTIFI_CONFIG_ID ?? '',
66
+ type: 'SUBSCRIPTION_CARD',
67
+ })) as CardConfigItemV1
68
+
69
+ const eventTypes = subscriptionConfig?.eventTypes?.map(
70
+ (eventType): EventTypeItem & { enabled: boolean } => {
71
+ const eventTypeId = getIdFromEventType(eventType)
72
+ let enabled = false
73
+ // Check whether the user is subscribed to the event
74
+ const subscribedAlert = subscribedAlerts?.find(
75
+ (alert) => alert.filterOptions.indexOf(eventTypeId) >= 0,
76
+ )
77
+
78
+ if (subscribedAlert) {
79
+ enabled = true
80
+ }
81
+
82
+ return {
83
+ ...eventType,
84
+ enabled,
85
+ }
86
+ },
87
+ )
88
+
89
+ return eventTypes
90
+ }
91
+
92
+ export function NotifiSubscriptionModal({
93
+ handleSuccess,
94
+ }: Props): React.ReactElement {
95
+ const theme = useTheme()
96
+ const reset = useResetAtom(txAtom)
97
+ const dispatch = useAppDispatch()
98
+ const { account, chainId, provider } = useWeb3React()
99
+ const [notifiClient, setNotifiClient] = useState<NotifiFrontendClient>()
100
+ const [showSuccessScreen, setShowSuccessScreen] = useState<boolean>(false)
101
+ const [isLoading, setIsLoading] = useState<boolean>(false)
102
+ const [emailAddress, setEmailAddress] = useState<string>()
103
+ const [emailValid, setEmailValid] = useState<boolean>()
104
+
105
+ useEffect(() => {
106
+ const initializeClient = async () => {
107
+ if (account != null && chainId != null) {
108
+ const client = newFrontendClient({
109
+ account: { publicKey: account },
110
+ tenantId: 'humadapp',
111
+ env: envUtil.checkIsDev() ? 'Development' : 'Production',
112
+ walletBlockchain: getBlockchainConfigFromChain(chainId),
113
+ })
114
+
115
+ await client.initialize()
116
+
117
+ setNotifiClient(client)
118
+ }
119
+ }
120
+
121
+ initializeClient()
122
+ }, [account, chainId])
123
+
124
+ const signMessage: Uint8SignMessageFunction = async (
125
+ message: Uint8Array,
126
+ ): Promise<Uint8Array> => {
127
+ const signer = provider!.getSigner()
128
+ const signature = await signer.signMessage(Buffer.from(message))
129
+ return ethers.utils.arrayify(signature)
130
+ }
131
+
132
+ const handleEmailAddressChange = (
133
+ event: React.ChangeEvent<HTMLInputElement>,
134
+ ) => {
135
+ const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
136
+ setEmailValid(emailRegex.test(event.target.value ?? ''))
137
+ setEmailAddress(event.target.value)
138
+ }
139
+
140
+ const logInAndSubscribe = async (): Promise<void> => {
141
+ if (notifiClient != null && chainId != null) {
142
+ setIsLoading(true)
143
+
144
+ // Ask user to sign a message to authenticate
145
+ try {
146
+ await notifiClient.logIn({
147
+ walletBlockchain: getBlockchainConfigFromChain(chainId),
148
+ signMessage,
149
+ } as SignMessageParams)
150
+ } catch (e) {
151
+ setIsLoading(false)
152
+ return
153
+ }
154
+
155
+ // Fetch all event types
156
+ const fetchedEventTypes = await fetchEventTypes(notifiClient)
157
+
158
+ // Authorize this email address for this wallet
159
+ await notifiClient.ensureTargetGroup({
160
+ name: 'Default',
161
+ emailAddress: emailAddress!,
162
+ })
163
+
164
+ // Intentionally running this in serial because the Notifi ensureAlert can't handle
165
+ // multiple calls. Notified their team to fix this.
166
+ // eslint-disable-next-line no-restricted-syntax
167
+ for (const eventType of fetchedEventTypes) {
168
+ // eslint-disable-next-line no-await-in-loop
169
+ await notifiClient.ensureAlert({
170
+ eventType,
171
+ inputs: {},
172
+ })
173
+ }
174
+
175
+ setShowSuccessScreen(true)
176
+ setIsLoading(false)
177
+ }
178
+ }
179
+
180
+ const handleCloseModal = useCallback(() => {
181
+ reset()
182
+ dispatch(resetState())
183
+ handleSuccess()
184
+ }, [dispatch, handleSuccess, reset])
185
+
186
+ const styles = {
187
+ disclaimer: css`
188
+ ${theme.cssMixins.rowCentered};
189
+ font-family: 'Uni-Neue-Regular';
190
+ font-size: 16px;
191
+ color: #a8a1b2;
192
+ margin-top: 48px;
193
+ `,
194
+ inputField: css`
195
+ width: 90%;
196
+ font-size: 16px;
197
+ `,
198
+ inputWrapper: css`
199
+ width: 100%;
200
+ `,
201
+ header: css`
202
+ ${theme.cssMixins.rowHCentered};
203
+ margin-top: -5px;
204
+ `,
205
+ check: css`
206
+ width: 100%;
207
+ ${theme.cssMixins.rowHCentered};
208
+ margin-top: 82px;
209
+ `,
210
+ }
211
+
212
+ if (isLoading) {
213
+ return <LoadingModal title='Notifications' />
214
+ }
215
+
216
+ if (showSuccessScreen) {
217
+ return (
218
+ <WrapperModal
219
+ title='Success'
220
+ subTitle='You successfully connected your email'
221
+ >
222
+ <Box css={styles.check}>
223
+ <CheckIcon />
224
+ </Box>
225
+ <BottomButton variant='contained' onClick={handleCloseModal}>
226
+ DONE
227
+ </BottomButton>
228
+ </WrapperModal>
229
+ )
230
+ }
231
+
232
+ return (
233
+ <WrapperModal title='Connect Your Email'>
234
+ <Typography variant='body2' margin='12px 0'>
235
+ Connect your wallet to receive important emails about your account
236
+ </Typography>
237
+ <Box css={styles.inputWrapper}>
238
+ <Input
239
+ css={styles.inputField}
240
+ type='email'
241
+ value={emailAddress}
242
+ onChange={handleEmailAddressChange}
243
+ placeholder='youremail@example.com'
244
+ startAdornment={
245
+ <InputAdornment position='start'>
246
+ <Email />
247
+ </InputAdornment>
248
+ }
249
+ />
250
+ </Box>
251
+ <Box css={styles.disclaimer}>
252
+ You can adjust these settings at any time by clicking the alert icon in
253
+ the header
254
+ </Box>
255
+ <BottomButton
256
+ variant='contained'
257
+ onClick={logInAndSubscribe}
258
+ disabled={!emailValid || isLoading}
259
+ >
260
+ CONNECT WALLET
261
+ </BottomButton>
262
+ </WrapperModal>
263
+ )
264
+ }