@lifi/widget 3.6.0-alpha.5 → 3.6.1
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/App.tsx +3 -3
- package/AppProvider.tsx +2 -1
- package/CHANGELOG.md +23 -0
- package/_esm/App.d.ts +1 -1
- package/_esm/App.js +3 -3
- package/_esm/App.js.map +1 -1
- package/_esm/AppProvider.js +2 -2
- package/_esm/AppProvider.js.map +1 -1
- package/_esm/components/Card/InputCard.d.ts +1 -1
- package/_esm/components/ChainSelect/useChainSelect.js +1 -5
- package/_esm/components/ChainSelect/useChainSelect.js.map +1 -1
- package/_esm/components/FeeBreakdownTooltip.js +1 -4
- package/_esm/components/FeeBreakdownTooltip.js.map +1 -1
- package/_esm/components/Header/EVMDisconnectIconButton.js +4 -5
- package/_esm/components/Header/EVMDisconnectIconButton.js.map +1 -1
- package/_esm/components/Header/Header.style.d.ts +0 -3
- package/_esm/components/Header/Header.style.js +0 -5
- package/_esm/components/Header/Header.style.js.map +1 -1
- package/_esm/components/Header/WalletMenu.js +6 -5
- package/_esm/components/Header/WalletMenu.js.map +1 -1
- package/_esm/components/Header/WalletMenu.style.js +1 -5
- package/_esm/components/Header/WalletMenu.style.js.map +1 -1
- package/_esm/components/SendToWallet/SendToWalletButton.js +16 -6
- package/_esm/components/SendToWallet/SendToWalletButton.js.map +1 -1
- package/_esm/components/SendToWallet/SendToWalletExpandButton.js +8 -6
- package/_esm/components/SendToWallet/SendToWalletExpandButton.js.map +1 -1
- package/_esm/components/Skeleton/WidgetSkeleton.style.d.ts +1 -1
- package/_esm/components/Step/StepProcess.js +9 -1
- package/_esm/components/Step/StepProcess.js.map +1 -1
- package/_esm/components/TokenList/TokenListItem.js +5 -11
- package/_esm/components/TokenList/TokenListItem.js.map +1 -1
- package/_esm/components/TokenList/VirtualizedTokenList.js +1 -1
- package/_esm/components/TokenList/VirtualizedTokenList.js.map +1 -1
- package/_esm/components/TokenList/types.d.ts +2 -2
- package/_esm/components/TokenRate/TokenRate.js +2 -2
- package/_esm/components/TokenRate/TokenRate.js.map +1 -1
- package/_esm/components/TransactionDetails.js +2 -1
- package/_esm/components/TransactionDetails.js.map +1 -1
- package/_esm/config/version.d.ts +1 -1
- package/_esm/config/version.js +1 -1
- package/_esm/config/version.js.map +1 -1
- package/_esm/hooks/useAccount.d.ts +15 -15
- package/_esm/hooks/useAccount.js +13 -50
- package/_esm/hooks/useAccount.js.map +1 -1
- package/_esm/hooks/useAvailableChains.d.ts +1 -2
- package/_esm/hooks/useAvailableChains.js +8 -9
- package/_esm/hooks/useAvailableChains.js.map +1 -1
- package/_esm/hooks/useChains.d.ts +3 -4
- package/_esm/hooks/useChains.js +3 -5
- package/_esm/hooks/useChains.js.map +1 -1
- package/_esm/hooks/useExplorer.d.ts +10 -1
- package/_esm/hooks/useExplorer.js +4 -1
- package/_esm/hooks/useExplorer.js.map +1 -1
- package/_esm/hooks/useGasSufficiency.js +2 -2
- package/_esm/hooks/useGasSufficiency.js.map +1 -1
- package/_esm/hooks/useHeaderHeight.js +8 -1
- package/_esm/hooks/useHeaderHeight.js.map +1 -1
- package/_esm/hooks/useTokens.js +1 -1
- package/_esm/hooks/useTokens.js.map +1 -1
- package/_esm/hooks/useWallets.d.ts +1 -1
- package/_esm/hooks/useWallets.js +15 -36
- package/_esm/hooks/useWallets.js.map +1 -1
- package/_esm/i18n/en.json +1 -1
- package/_esm/pages/SelectWalletPage/EVMListItemButton.d.ts +2 -1
- package/_esm/pages/SelectWalletPage/EVMListItemButton.js +14 -15
- package/_esm/pages/SelectWalletPage/EVMListItemButton.js.map +1 -1
- package/_esm/pages/SelectWalletPage/SVMListItemButton.js +0 -3
- package/_esm/pages/SelectWalletPage/SVMListItemButton.js.map +1 -1
- package/_esm/pages/SelectWalletPage/SelectWalletPage.js +3 -3
- package/_esm/pages/SelectWalletPage/SelectWalletPage.js.map +1 -1
- package/_esm/pages/SendToWallet/SendToWalletPage.style.d.ts +1 -1
- package/_esm/pages/TransactionDetailsPage/TransferIdCard.js +1 -1
- package/_esm/pages/TransactionDetailsPage/TransferIdCard.js.map +1 -1
- package/_esm/pages/TransactionPage/StatusBottomSheet.js +3 -2
- package/_esm/pages/TransactionPage/StatusBottomSheet.js.map +1 -1
- package/_esm/providers/I18nProvider/types.d.ts +2 -2
- package/_esm/providers/WalletProvider/SDKProviders.js +7 -15
- package/_esm/providers/WalletProvider/SDKProviders.js.map +1 -1
- package/_esm/providers/WalletProvider/WalletProvider.js +1 -2
- package/_esm/providers/WalletProvider/WalletProvider.js.map +1 -1
- package/_esm/providers/WalletProvider/useHasExternalWalletProvider.d.ts +1 -1
- package/_esm/providers/WalletProvider/useHasExternalWalletProvider.js +3 -8
- package/_esm/providers/WalletProvider/useHasExternalWalletProvider.js.map +1 -1
- package/_esm/providers/WidgetProvider/WidgetProvider.js +1 -31
- package/_esm/providers/WidgetProvider/WidgetProvider.js.map +1 -1
- package/_esm/stores/StoreProvider.js +2 -2
- package/_esm/stores/StoreProvider.js.map +1 -1
- package/_esm/stores/form/FormStore.d.ts +6 -1
- package/_esm/stores/form/FormStore.js +69 -18
- package/_esm/stores/form/FormStore.js.map +1 -1
- package/_esm/stores/form/FormUpdater.d.ts +1 -1
- package/_esm/stores/form/FormUpdater.js +36 -18
- package/_esm/stores/form/FormUpdater.js.map +1 -1
- package/_esm/stores/form/URLSearchParamsBuilder.js +44 -4
- package/_esm/stores/form/URLSearchParamsBuilder.js.map +1 -1
- package/_esm/stores/form/createFormStore.js +9 -0
- package/_esm/stores/form/createFormStore.js.map +1 -1
- package/_esm/stores/form/types.d.ts +13 -10
- package/_esm/stores/form/types.js.map +1 -1
- package/_esm/stores/form/useFieldActions.js +1 -0
- package/_esm/stores/form/useFieldActions.js.map +1 -1
- package/_esm/stores/form/useFormRef.d.ts +3 -0
- package/_esm/stores/form/useFormRef.js +51 -0
- package/_esm/stores/form/useFormRef.js.map +1 -0
- package/_esm/stores/form/useTouchedFields.d.ts +6 -6
- package/_esm/stores/settings/types.d.ts +0 -2
- package/_esm/stores/settings/useSendToWalletStore.d.ts +0 -1
- package/_esm/stores/settings/useSendToWalletStore.js +0 -7
- package/_esm/stores/settings/useSendToWalletStore.js.map +1 -1
- package/_esm/themes/createTheme.js +1 -2
- package/_esm/themes/createTheme.js.map +1 -1
- package/_esm/types/widget.d.ts +29 -4
- package/_esm/types/widget.js.map +1 -1
- package/_esm/utils/chainType.js +3 -2
- package/_esm/utils/chainType.js.map +1 -1
- package/_esm/utils/fees.js +5 -9
- package/_esm/utils/fees.js.map +1 -1
- package/_esm/utils/format.js +1 -1
- package/_esm/utils/format.js.map +1 -1
- package/_esm/utils/svm.d.ts +1 -0
- package/_esm/utils/svm.js +11 -0
- package/_esm/utils/svm.js.map +1 -0
- package/components/ChainSelect/useChainSelect.ts +1 -10
- package/components/FeeBreakdownTooltip.tsx +1 -4
- package/components/Header/EVMDisconnectIconButton.tsx +5 -5
- package/components/Header/Header.style.ts +0 -6
- package/components/Header/WalletMenu.style.tsx +1 -5
- package/components/Header/WalletMenu.tsx +5 -6
- package/components/SendToWallet/SendToWalletButton.tsx +23 -13
- package/components/SendToWallet/SendToWalletExpandButton.tsx +10 -10
- package/components/Step/StepProcess.tsx +12 -2
- package/components/TokenList/TokenListItem.tsx +7 -15
- package/components/TokenList/VirtualizedTokenList.tsx +1 -1
- package/components/TokenList/types.ts +2 -2
- package/components/TokenRate/TokenRate.tsx +2 -2
- package/components/TransactionDetails.tsx +4 -1
- package/config/version.ts +1 -1
- package/hooks/useAccount.ts +35 -82
- package/hooks/useAvailableChains.ts +10 -9
- package/hooks/useChains.ts +3 -6
- package/hooks/useExplorer.ts +19 -2
- package/hooks/useGasSufficiency.ts +2 -4
- package/hooks/useHeaderHeight.ts +8 -1
- package/hooks/useTokens.ts +1 -2
- package/hooks/useWallets.ts +20 -41
- package/i18n/en.json +1 -1
- package/package.json +8 -8
- package/pages/SelectWalletPage/EVMListItemButton.tsx +19 -15
- package/pages/SelectWalletPage/SVMListItemButton.tsx +0 -3
- package/pages/SelectWalletPage/SelectWalletPage.tsx +4 -9
- package/pages/TransactionDetailsPage/TransferIdCard.tsx +1 -1
- package/pages/TransactionPage/StatusBottomSheet.tsx +5 -0
- package/providers/I18nProvider/types.ts +2 -2
- package/providers/WalletProvider/SDKProviders.tsx +7 -25
- package/providers/WalletProvider/WalletProvider.tsx +2 -5
- package/providers/WalletProvider/useHasExternalWalletProvider.ts +5 -11
- package/providers/WidgetProvider/WidgetProvider.tsx +1 -39
- package/stores/StoreProvider.tsx +5 -4
- package/stores/form/FormStore.tsx +100 -20
- package/stores/form/FormUpdater.tsx +52 -22
- package/stores/form/URLSearchParamsBuilder.tsx +55 -5
- package/stores/form/createFormStore.ts +9 -0
- package/stores/form/types.ts +14 -10
- package/stores/form/useFieldActions.ts +1 -0
- package/stores/form/useFormRef.ts +69 -0
- package/stores/settings/types.ts +0 -2
- package/stores/settings/useSendToWalletStore.ts +0 -8
- package/themes/createTheme.ts +1 -3
- package/types/widget.ts +46 -3
- package/utils/chainType.ts +3 -2
- package/utils/fees.ts +13 -15
- package/utils/format.ts +1 -1
- package/utils/svm.ts +10 -0
- package/_esm/components/Header/UTXODisconnectIconButton.d.ts +0 -4
- package/_esm/components/Header/UTXODisconnectIconButton.js +0 -13
- package/_esm/components/Header/UTXODisconnectIconButton.js.map +0 -1
- package/_esm/pages/SelectWalletPage/UTXOListItemButton.d.ts +0 -8
- package/_esm/pages/SelectWalletPage/UTXOListItemButton.js +0 -39
- package/_esm/pages/SelectWalletPage/UTXOListItemButton.js.map +0 -1
- package/_esm/providers/WalletProvider/UTXOBaseProvider.d.ts +0 -2
- package/_esm/providers/WalletProvider/UTXOBaseProvider.js +0 -17
- package/_esm/providers/WalletProvider/UTXOBaseProvider.js.map +0 -1
- package/_esm/providers/WalletProvider/UTXOExternalContext.d.ts +0 -1
- package/_esm/providers/WalletProvider/UTXOExternalContext.js +0 -3
- package/_esm/providers/WalletProvider/UTXOExternalContext.js.map +0 -1
- package/_esm/providers/WalletProvider/UTXOProvider.d.ts +0 -3
- package/_esm/providers/WalletProvider/UTXOProvider.js +0 -18
- package/_esm/providers/WalletProvider/UTXOProvider.js.map +0 -1
- package/components/Header/UTXODisconnectIconButton.tsx +0 -24
- package/pages/SelectWalletPage/UTXOListItemButton.tsx +0 -70
- package/providers/WalletProvider/UTXOBaseProvider.tsx +0 -28
- package/providers/WalletProvider/UTXOExternalContext.ts +0 -3
- package/providers/WalletProvider/UTXOProvider.tsx +0 -26
|
@@ -1,63 +1,143 @@
|
|
|
1
1
|
import type { PropsWithChildren } from 'react';
|
|
2
2
|
import { useMemo, useRef } from 'react';
|
|
3
3
|
import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js';
|
|
4
|
+
import type { FormRef, ToAddress } from '../../types/widget.js';
|
|
4
5
|
import { HiddenUI } from '../../types/widget.js';
|
|
5
6
|
import { FormStoreContext } from './FormStoreContext.js';
|
|
6
7
|
import { FormUpdater } from './FormUpdater.js';
|
|
7
8
|
import { createFormStore, formDefaultValues } from './createFormStore.js';
|
|
8
|
-
import type { FormStoreStore } from './types.js';
|
|
9
|
+
import type { DefaultValues, FormStoreStore } from './types.js';
|
|
10
|
+
import { useFormRef } from './useFormRef.js';
|
|
9
11
|
|
|
10
|
-
|
|
12
|
+
// decorates and initialise the form date for use in the form store
|
|
13
|
+
const initialiseDefaultValues = (
|
|
14
|
+
defaultValues: Partial<DefaultValues>,
|
|
15
|
+
fromAmount?: number | string,
|
|
16
|
+
toAmount?: number | string,
|
|
17
|
+
toAddress?: ToAddress,
|
|
18
|
+
hiddenToAddress?: boolean,
|
|
19
|
+
) => ({
|
|
20
|
+
...formDefaultValues,
|
|
21
|
+
...defaultValues,
|
|
22
|
+
fromAmount:
|
|
23
|
+
(typeof fromAmount === 'number' ? fromAmount?.toPrecision() : fromAmount) ||
|
|
24
|
+
formDefaultValues.fromAmount,
|
|
25
|
+
toAmount:
|
|
26
|
+
(typeof toAmount === 'number' ? toAmount?.toPrecision() : toAmount) ||
|
|
27
|
+
formDefaultValues.toAmount,
|
|
28
|
+
// Prevent setting address when the field is hidden
|
|
29
|
+
toAddress: hiddenToAddress
|
|
30
|
+
? formDefaultValues.toAddress
|
|
31
|
+
: toAddress?.address || formDefaultValues.toAddress,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
interface FormStoreProviderProps extends PropsWithChildren {
|
|
35
|
+
formRef?: FormRef;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const FormStoreProvider: React.FC<FormStoreProviderProps> = ({
|
|
11
39
|
children,
|
|
40
|
+
formRef,
|
|
12
41
|
}) => {
|
|
42
|
+
const widgetConfig = useWidgetConfig();
|
|
43
|
+
|
|
13
44
|
const {
|
|
14
45
|
fromChain,
|
|
15
46
|
fromToken,
|
|
16
|
-
fromAmount,
|
|
17
47
|
toChain,
|
|
18
48
|
toToken,
|
|
49
|
+
fromAmount,
|
|
50
|
+
toAmount,
|
|
19
51
|
toAddress,
|
|
20
52
|
hiddenUI,
|
|
21
|
-
|
|
53
|
+
formUpdateKey,
|
|
54
|
+
} = widgetConfig;
|
|
55
|
+
|
|
22
56
|
const storeRef = useRef<FormStoreStore>();
|
|
23
57
|
|
|
24
58
|
const hiddenToAddress = hiddenUI?.includes(HiddenUI.ToAddress);
|
|
25
59
|
|
|
26
|
-
const
|
|
60
|
+
const configHasFromChain = widgetConfig.hasOwnProperty('fromChain');
|
|
61
|
+
const configHasFromToken = widgetConfig.hasOwnProperty('fromToken');
|
|
62
|
+
const configHasFromAmount = widgetConfig.hasOwnProperty('fromAmount');
|
|
63
|
+
const configHasToAmount = widgetConfig.hasOwnProperty('toAmount');
|
|
64
|
+
const configHasToAddress = widgetConfig.hasOwnProperty('toAddress');
|
|
65
|
+
const configHasToChain = widgetConfig.hasOwnProperty('toChain');
|
|
66
|
+
const configHasToToken = widgetConfig.hasOwnProperty('toToken');
|
|
67
|
+
|
|
68
|
+
// We use the presence/absence of a property to decide if the form values in state need to be updated
|
|
69
|
+
// We only build and set a property on the memoized form values here if they are included in the
|
|
70
|
+
// config - undefined is considered a valid value that will reset that form field
|
|
71
|
+
const reactiveFormValues = useMemo(
|
|
27
72
|
() => ({
|
|
28
|
-
...
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
?
|
|
40
|
-
|
|
73
|
+
...(configHasFromChain ? { fromChain } : undefined),
|
|
74
|
+
...(configHasFromToken ? { fromToken } : undefined),
|
|
75
|
+
...(configHasFromAmount
|
|
76
|
+
? {
|
|
77
|
+
fromAmount:
|
|
78
|
+
(typeof fromAmount === 'number'
|
|
79
|
+
? fromAmount?.toPrecision()
|
|
80
|
+
: fromAmount) || formDefaultValues.fromAmount,
|
|
81
|
+
}
|
|
82
|
+
: undefined),
|
|
83
|
+
...(configHasFromAmount
|
|
84
|
+
? {
|
|
85
|
+
toAmount:
|
|
86
|
+
(typeof toAmount === 'number'
|
|
87
|
+
? toAmount?.toPrecision()
|
|
88
|
+
: toAmount) || formDefaultValues.toAmount,
|
|
89
|
+
}
|
|
90
|
+
: undefined),
|
|
91
|
+
...(configHasToChain ? { toChain } : undefined),
|
|
92
|
+
...(configHasToToken ? { toToken } : undefined),
|
|
93
|
+
...(configHasToAddress
|
|
94
|
+
? {
|
|
95
|
+
toAddress: hiddenToAddress
|
|
96
|
+
? formDefaultValues.toAddress
|
|
97
|
+
: toAddress?.address || formDefaultValues.toAddress,
|
|
98
|
+
}
|
|
99
|
+
: undefined),
|
|
41
100
|
}),
|
|
101
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
42
102
|
[
|
|
43
103
|
fromAmount,
|
|
104
|
+
toAmount,
|
|
44
105
|
fromChain,
|
|
45
106
|
fromToken,
|
|
46
107
|
hiddenToAddress,
|
|
47
108
|
toAddress,
|
|
48
109
|
toChain,
|
|
49
110
|
toToken,
|
|
111
|
+
// formUpdateKey should be a randomly assigned unique key. It can be used to force updates for the form field values
|
|
112
|
+
formUpdateKey,
|
|
113
|
+
configHasFromChain,
|
|
114
|
+
configHasFromToken,
|
|
115
|
+
configHasFromAmount,
|
|
116
|
+
configHasToAmount,
|
|
117
|
+
configHasToAddress,
|
|
118
|
+
configHasToChain,
|
|
119
|
+
configHasToToken,
|
|
50
120
|
],
|
|
51
121
|
);
|
|
52
122
|
|
|
53
123
|
if (!storeRef.current) {
|
|
54
|
-
storeRef.current = createFormStore(
|
|
124
|
+
storeRef.current = createFormStore(
|
|
125
|
+
initialiseDefaultValues(
|
|
126
|
+
reactiveFormValues,
|
|
127
|
+
fromAmount,
|
|
128
|
+
toAmount,
|
|
129
|
+
toAddress,
|
|
130
|
+
hiddenToAddress,
|
|
131
|
+
),
|
|
132
|
+
);
|
|
55
133
|
}
|
|
56
134
|
|
|
135
|
+
useFormRef(storeRef.current, formRef);
|
|
136
|
+
|
|
57
137
|
return (
|
|
58
138
|
<FormStoreContext.Provider value={storeRef.current}>
|
|
59
139
|
{children}
|
|
60
|
-
<FormUpdater
|
|
140
|
+
<FormUpdater reactiveFormValues={reactiveFormValues} />
|
|
61
141
|
</FormStoreContext.Provider>
|
|
62
142
|
);
|
|
63
143
|
};
|
|
@@ -1,21 +1,30 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
-
import { useEffect
|
|
2
|
+
import { useEffect } from 'react';
|
|
3
3
|
import { useAccount } from '../../hooks/useAccount.js';
|
|
4
4
|
import { useChains } from '../../hooks/useChains.js';
|
|
5
5
|
import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js';
|
|
6
|
-
import
|
|
6
|
+
import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js';
|
|
7
|
+
import { formDefaultValues } from '../../stores/form/createFormStore.js';
|
|
8
|
+
import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js';
|
|
9
|
+
import type { DefaultValues } from './types.js';
|
|
7
10
|
import { useFieldActions } from './useFieldActions.js';
|
|
8
11
|
|
|
9
12
|
export const FormUpdater: React.FC<{
|
|
10
|
-
|
|
11
|
-
}> = ({
|
|
12
|
-
const { fromChain, toChain } = useWidgetConfig();
|
|
13
|
+
reactiveFormValues: Partial<DefaultValues>;
|
|
14
|
+
}> = ({ reactiveFormValues }) => {
|
|
15
|
+
const { fromChain, toChain, toAddress } = useWidgetConfig();
|
|
13
16
|
const { account } = useAccount();
|
|
14
17
|
const { chains } = useChains();
|
|
15
|
-
const {
|
|
16
|
-
|
|
17
|
-
const previousDefaultValues = useRef(defaultValues);
|
|
18
|
+
const { setSendToWallet } = useSendToWalletActions();
|
|
19
|
+
const { setSelectedBookmark } = useBookmarkActions();
|
|
18
20
|
|
|
21
|
+
const {
|
|
22
|
+
isTouched,
|
|
23
|
+
resetField,
|
|
24
|
+
setFieldValue,
|
|
25
|
+
getFieldValues,
|
|
26
|
+
setUserAndDefaultValues,
|
|
27
|
+
} = useFieldActions();
|
|
19
28
|
// Set wallet chain as default if no chains are provided by config and if they were not changed during widget usage
|
|
20
29
|
useEffect(() => {
|
|
21
30
|
const chainAllowed =
|
|
@@ -50,21 +59,42 @@ export const FormUpdater: React.FC<{
|
|
|
50
59
|
// Makes widget config options reactive to changes
|
|
51
60
|
// should update userValues when defaultValues updates and includes additional logic for chains
|
|
52
61
|
useEffect(() => {
|
|
53
|
-
(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
resetField(key, { defaultValue: value });
|
|
63
|
-
}
|
|
64
|
-
});
|
|
65
|
-
previousDefaultValues.current = defaultValues;
|
|
62
|
+
if (reactiveFormValues.toAddress) {
|
|
63
|
+
setSendToWallet(true);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
setSelectedBookmark(toAddress);
|
|
67
|
+
|
|
68
|
+
setUserAndDefaultValues(
|
|
69
|
+
accountForChainId(reactiveFormValues, account.chainId),
|
|
70
|
+
);
|
|
66
71
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
67
|
-
}, [
|
|
72
|
+
}, [
|
|
73
|
+
toAddress,
|
|
74
|
+
reactiveFormValues,
|
|
75
|
+
getFieldValues,
|
|
76
|
+
resetField,
|
|
77
|
+
setFieldValue,
|
|
78
|
+
setUserAndDefaultValues,
|
|
79
|
+
setSendToWallet,
|
|
80
|
+
setSelectedBookmark,
|
|
81
|
+
]);
|
|
68
82
|
|
|
69
83
|
return null;
|
|
70
84
|
};
|
|
85
|
+
|
|
86
|
+
const accountForChainId = (
|
|
87
|
+
defaultValues: Partial<DefaultValues>,
|
|
88
|
+
chainId?: number,
|
|
89
|
+
) => {
|
|
90
|
+
const result: Partial<DefaultValues> = { ...defaultValues };
|
|
91
|
+
for (const key in result) {
|
|
92
|
+
const k = key as keyof DefaultValues;
|
|
93
|
+
if (result[k] === formDefaultValues[k]) {
|
|
94
|
+
if ((k === 'fromChain' || k === 'toChain') && chainId) {
|
|
95
|
+
result[k] = chainId;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return result;
|
|
100
|
+
};
|
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import { useEffect } from 'react';
|
|
2
2
|
import { useLocation } from 'react-router-dom';
|
|
3
|
-
import
|
|
3
|
+
import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js';
|
|
4
|
+
import { formatInputAmount } from '../../utils/format.js';
|
|
5
|
+
import type { DefaultValues, FormFieldNames } from '../form/types.js';
|
|
6
|
+
import { useFieldActions } from '../form/useFieldActions.js';
|
|
4
7
|
import { useFieldValues } from '../form/useFieldValues.js';
|
|
5
8
|
import { useTouchedFields } from '../form/useTouchedFields.js';
|
|
6
9
|
|
|
@@ -13,24 +16,71 @@ const formValueKeys: FormFieldNames[] = [
|
|
|
13
16
|
'toToken',
|
|
14
17
|
];
|
|
15
18
|
|
|
19
|
+
const getDefaultValuesFromQueryString = (): Partial<DefaultValues> => {
|
|
20
|
+
const searchParams = Object.fromEntries(
|
|
21
|
+
new URLSearchParams(window?.location.search),
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
// Prevent using fromToken/toToken params if chain is not selected
|
|
25
|
+
['from', 'to'].forEach((key) => {
|
|
26
|
+
if (searchParams[`${key}Token`] && !searchParams[`${key}Chain`]) {
|
|
27
|
+
delete searchParams[`${key}Token`];
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
return {
|
|
32
|
+
...(Number.isFinite(parseInt(searchParams.fromChain, 10))
|
|
33
|
+
? { fromChain: parseInt(searchParams.fromChain, 10) }
|
|
34
|
+
: {}),
|
|
35
|
+
...(Number.isFinite(parseInt(searchParams.toChain, 10))
|
|
36
|
+
? { toChain: parseInt(searchParams.toChain, 10) }
|
|
37
|
+
: {}),
|
|
38
|
+
...(searchParams.fromToken ? { fromToken: searchParams.fromToken } : {}),
|
|
39
|
+
...(searchParams.toToken ? { toToken: searchParams.toToken } : {}),
|
|
40
|
+
...(Number.isFinite(parseFloat(searchParams.fromAmount))
|
|
41
|
+
? { fromAmount: formatInputAmount(searchParams.fromAmount) }
|
|
42
|
+
: {}),
|
|
43
|
+
...(searchParams.toAddress ? { toAddress: searchParams.toAddress } : {}),
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
16
47
|
export const URLSearchParamsBuilder = () => {
|
|
17
48
|
const { pathname } = useLocation();
|
|
18
49
|
const touchedFields = useTouchedFields();
|
|
19
50
|
const values = useFieldValues(...formValueKeys);
|
|
51
|
+
const { setSendToWallet } = useSendToWalletActions();
|
|
52
|
+
|
|
53
|
+
// Using these methods as trying to use the touchedFields and values above
|
|
54
|
+
// often has a lag that can effect the widgets initialisation sequence
|
|
55
|
+
// and accidentally cause values to be wiped from the query string
|
|
56
|
+
const { getFieldValues, isTouched, setUserAndDefaultValues } =
|
|
57
|
+
useFieldActions();
|
|
58
|
+
|
|
59
|
+
useEffect(() => {
|
|
60
|
+
// get the initial values from the querysting
|
|
61
|
+
const formValues = getDefaultValuesFromQueryString();
|
|
62
|
+
|
|
63
|
+
if (formValues.toAddress) {
|
|
64
|
+
setSendToWallet(true);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
setUserAndDefaultValues(formValues);
|
|
68
|
+
}, [setUserAndDefaultValues, setSendToWallet]);
|
|
20
69
|
|
|
21
70
|
useEffect(() => {
|
|
71
|
+
// set the values on the querysting
|
|
22
72
|
const url = new URL(window.location as any);
|
|
23
73
|
formValueKeys.forEach((key, index) => {
|
|
24
|
-
const value =
|
|
25
|
-
if (
|
|
74
|
+
const value = getFieldValues(key)[0];
|
|
75
|
+
if (isTouched(key) && value) {
|
|
26
76
|
url.searchParams.set(key, value.toString());
|
|
27
|
-
} else if (url.searchParams.has(key) && !
|
|
77
|
+
} else if (url.searchParams.has(key) && !value) {
|
|
28
78
|
url.searchParams.delete(key);
|
|
29
79
|
}
|
|
30
80
|
});
|
|
31
81
|
url.searchParams.sort();
|
|
32
82
|
window.history.replaceState(window.history.state, '', url);
|
|
33
|
-
}, [pathname, touchedFields, values]);
|
|
83
|
+
}, [pathname, touchedFields, values, isTouched, getFieldValues]);
|
|
34
84
|
|
|
35
85
|
return null;
|
|
36
86
|
};
|
|
@@ -94,6 +94,15 @@ export const createFormStore = (defaultValues?: DefaultValues) =>
|
|
|
94
94
|
),
|
|
95
95
|
}));
|
|
96
96
|
},
|
|
97
|
+
setUserAndDefaultValues: (formValues) => {
|
|
98
|
+
const currentUserValues = get().userValues;
|
|
99
|
+
(Object.keys(formValues) as FormFieldNames[]).forEach((key) => {
|
|
100
|
+
if (formValues[key] !== currentUserValues[key]?.value) {
|
|
101
|
+
get().resetField(key, { defaultValue: formValues[key] });
|
|
102
|
+
get().setFieldValue(key, formValues[key], { isTouched: true });
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
},
|
|
97
106
|
isTouched: (fieldName: FormFieldNames) =>
|
|
98
107
|
!!get().userValues[fieldName]?.isTouched,
|
|
99
108
|
setAsTouched: (fieldName: FormFieldNames) => {
|
package/stores/form/types.ts
CHANGED
|
@@ -2,15 +2,18 @@ import type { ContractCall } from '@lifi/sdk';
|
|
|
2
2
|
import type { StoreApi } from 'zustand';
|
|
3
3
|
import type { UseBoundStoreWithEqualityFn } from 'zustand/traditional';
|
|
4
4
|
|
|
5
|
-
export interface
|
|
6
|
-
contractCalls?: ContractCall[];
|
|
7
|
-
fromAmount: string;
|
|
5
|
+
export interface DefaultFieldValues {
|
|
8
6
|
fromChain?: number;
|
|
9
7
|
fromToken?: string;
|
|
10
|
-
toAddress?: string;
|
|
11
|
-
toAmount: string;
|
|
12
8
|
toChain?: number;
|
|
13
9
|
toToken?: string;
|
|
10
|
+
toAddress?: string;
|
|
11
|
+
fromAmount: string;
|
|
12
|
+
toAmount: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface DefaultValues extends DefaultFieldValues {
|
|
16
|
+
contractCalls?: ContractCall[];
|
|
14
17
|
tokenSearchFilter: string;
|
|
15
18
|
}
|
|
16
19
|
|
|
@@ -32,17 +35,17 @@ export type FormFieldArray<T extends FormFieldNames[]> = {
|
|
|
32
35
|
[K in keyof T]: ExtractValueType<FormValues[T[K]]>;
|
|
33
36
|
};
|
|
34
37
|
|
|
35
|
-
export type TouchedFields = { [
|
|
38
|
+
export type TouchedFields = { [key in FormFieldNames]?: boolean };
|
|
36
39
|
|
|
37
40
|
type ValidationFn = (value: any) => Promise<boolean | string>;
|
|
38
41
|
export interface ValidationProps {
|
|
39
42
|
isValid: boolean;
|
|
40
43
|
isValidating: boolean;
|
|
41
44
|
errors: {
|
|
42
|
-
[
|
|
45
|
+
[key in FormFieldNames]?: string;
|
|
43
46
|
};
|
|
44
47
|
validation: {
|
|
45
|
-
[
|
|
48
|
+
[key in FormFieldNames]?: ValidationFn;
|
|
46
49
|
};
|
|
47
50
|
}
|
|
48
51
|
|
|
@@ -58,7 +61,7 @@ export interface ValidationActions {
|
|
|
58
61
|
export interface FormProps {
|
|
59
62
|
defaultValues: FormValues;
|
|
60
63
|
userValues: FormValues;
|
|
61
|
-
touchedFields: { [
|
|
64
|
+
touchedFields: { [key in FormFieldNames]?: boolean };
|
|
62
65
|
}
|
|
63
66
|
|
|
64
67
|
interface ResetOptions {
|
|
@@ -67,6 +70,7 @@ interface ResetOptions {
|
|
|
67
70
|
|
|
68
71
|
export interface FormActions {
|
|
69
72
|
setDefaultValues: (formValues: DefaultValues) => void;
|
|
73
|
+
setUserAndDefaultValues: (formValues: Partial<DefaultValues>) => void;
|
|
70
74
|
isTouched: (fieldName: FormFieldNames) => boolean;
|
|
71
75
|
setAsTouched: (fieldName: FormFieldNames) => void;
|
|
72
76
|
resetField: (fieldName: FormFieldNames, resetOptions?: ResetOptions) => void;
|
|
@@ -89,7 +93,7 @@ export type FormStoreStore = UseBoundStoreWithEqualityFn<
|
|
|
89
93
|
StoreApi<FormValuesState>
|
|
90
94
|
>;
|
|
91
95
|
|
|
92
|
-
interface SetOptions {
|
|
96
|
+
export interface SetOptions {
|
|
93
97
|
isDirty?: boolean;
|
|
94
98
|
isTouched?: boolean;
|
|
95
99
|
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { useImperativeHandle } from 'react';
|
|
2
|
+
import { useWidgetConfig } from '../../providers/WidgetProvider/WidgetProvider.js';
|
|
3
|
+
import { useBookmarkActions } from '../../stores/bookmarks/useBookmarkActions.js';
|
|
4
|
+
import { formDefaultValues } from '../../stores/form/createFormStore.js';
|
|
5
|
+
import { useSendToWalletActions } from '../../stores/settings/useSendToWalletStore.js';
|
|
6
|
+
import type { FormRef } from '../../types/widget.js';
|
|
7
|
+
import { HiddenUI } from '../../types/widget.js';
|
|
8
|
+
import type { FormStoreStore, GenericFormValue } from './types.js';
|
|
9
|
+
|
|
10
|
+
export const useFormRef = (formStore: FormStoreStore, formRef?: FormRef) => {
|
|
11
|
+
const { setSendToWallet } = useSendToWalletActions();
|
|
12
|
+
const { setSelectedBookmark } = useBookmarkActions();
|
|
13
|
+
const { hiddenUI } = useWidgetConfig();
|
|
14
|
+
|
|
15
|
+
useImperativeHandle(formRef, () => {
|
|
16
|
+
const sanitizeValue: {
|
|
17
|
+
[key: string]: (value: any) => GenericFormValue;
|
|
18
|
+
} = {
|
|
19
|
+
fromAmount: (value) =>
|
|
20
|
+
(typeof value === 'number' ? value?.toPrecision() : value) ||
|
|
21
|
+
formDefaultValues.fromAmount,
|
|
22
|
+
toAmount: (value) =>
|
|
23
|
+
(typeof value === 'number' ? value?.toPrecision() : value) ||
|
|
24
|
+
formDefaultValues.toAmount,
|
|
25
|
+
toAddress: (value) => {
|
|
26
|
+
if (hiddenUI?.includes(HiddenUI.ToAddress)) {
|
|
27
|
+
return formDefaultValues.toAddress;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const isToAddressObj = typeof value !== 'string';
|
|
31
|
+
|
|
32
|
+
const address =
|
|
33
|
+
(isToAddressObj ? value?.address : value) ||
|
|
34
|
+
formDefaultValues.toAddress;
|
|
35
|
+
|
|
36
|
+
// sets the send to wallet button state to be open
|
|
37
|
+
// if there is an address to display
|
|
38
|
+
if (address) {
|
|
39
|
+
setSendToWallet(address);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// we can assume that the toAddress has been passed as ToAddress object
|
|
43
|
+
// and display it accordingly - this ensures that if a name is included
|
|
44
|
+
// that it is displayed in the Send To Wallet form field correctly
|
|
45
|
+
if (isToAddressObj) {
|
|
46
|
+
setSelectedBookmark(value);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return address;
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
setFieldValue: (fieldName, value, options) => {
|
|
55
|
+
const sanitizedValue = (
|
|
56
|
+
sanitizeValue[fieldName] ? sanitizeValue[fieldName](value) : value
|
|
57
|
+
) as GenericFormValue;
|
|
58
|
+
|
|
59
|
+
const fieldValueOptions = options?.setUrlSearchParam
|
|
60
|
+
? { isTouched: options?.setUrlSearchParam }
|
|
61
|
+
: undefined;
|
|
62
|
+
|
|
63
|
+
formStore
|
|
64
|
+
.getState()
|
|
65
|
+
.setFieldValue(fieldName, sanitizedValue, fieldValueOptions);
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}, [formStore, hiddenUI, setSendToWallet, setSelectedBookmark]);
|
|
69
|
+
};
|
package/stores/settings/types.ts
CHANGED
|
@@ -46,11 +46,9 @@ export interface SettingsState extends SettingsProps {
|
|
|
46
46
|
|
|
47
47
|
export interface SendToWalletState {
|
|
48
48
|
showSendToWallet: boolean;
|
|
49
|
-
showSendToWalletDirty: boolean;
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
export interface SendToWalletStore extends SendToWalletState {
|
|
53
|
-
toggleSendToWallet(): void;
|
|
54
52
|
setSendToWallet(value: boolean): void;
|
|
55
53
|
}
|
|
56
54
|
|
|
@@ -5,16 +5,9 @@ import type { SendToWalletStore } from './types.js';
|
|
|
5
5
|
export const useSendToWalletStore = createWithEqualityFn<SendToWalletStore>(
|
|
6
6
|
(set) => ({
|
|
7
7
|
showSendToWallet: false,
|
|
8
|
-
showSendToWalletDirty: false,
|
|
9
|
-
toggleSendToWallet: () =>
|
|
10
|
-
set((state) => ({
|
|
11
|
-
showSendToWallet: !state.showSendToWallet,
|
|
12
|
-
showSendToWalletDirty: true,
|
|
13
|
-
})),
|
|
14
8
|
setSendToWallet: (value) =>
|
|
15
9
|
set({
|
|
16
10
|
showSendToWallet: value,
|
|
17
|
-
showSendToWalletDirty: true,
|
|
18
11
|
}),
|
|
19
12
|
}),
|
|
20
13
|
Object.is,
|
|
@@ -23,7 +16,6 @@ export const useSendToWalletStore = createWithEqualityFn<SendToWalletStore>(
|
|
|
23
16
|
export const useSendToWalletActions = () => {
|
|
24
17
|
const actions = useSendToWalletStore(
|
|
25
18
|
(store) => ({
|
|
26
|
-
toggleSendToWallet: store.toggleSendToWallet,
|
|
27
19
|
setSendToWallet: store.setSendToWallet,
|
|
28
20
|
}),
|
|
29
21
|
shallow,
|
package/themes/createTheme.ts
CHANGED
|
@@ -63,7 +63,7 @@ export const createTheme = (
|
|
|
63
63
|
const borderRadiusSecondary =
|
|
64
64
|
widgetTheme.shape?.borderRadiusSecondary ?? shape.borderRadiusSecondary;
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
return createMuiTheme({
|
|
67
67
|
container: widgetTheme.container,
|
|
68
68
|
header: widgetTheme.header,
|
|
69
69
|
navigation: {
|
|
@@ -409,6 +409,4 @@ export const createTheme = (
|
|
|
409
409
|
},
|
|
410
410
|
},
|
|
411
411
|
});
|
|
412
|
-
|
|
413
|
-
return theme;
|
|
414
412
|
};
|
package/types/widget.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
ChainType,
|
|
4
4
|
ContractCall,
|
|
5
5
|
Order,
|
|
6
|
+
RouteExtended,
|
|
6
7
|
RouteOptions,
|
|
7
8
|
SDKConfig,
|
|
8
9
|
StaticToken,
|
|
@@ -21,11 +22,18 @@ import type {
|
|
|
21
22
|
MetaMaskParameters,
|
|
22
23
|
WalletConnectParameters,
|
|
23
24
|
} from '@wagmi/connectors';
|
|
24
|
-
import type {
|
|
25
|
+
import type {
|
|
26
|
+
CSSProperties,
|
|
27
|
+
FC,
|
|
28
|
+
MutableRefObject,
|
|
29
|
+
ReactNode,
|
|
30
|
+
RefObject,
|
|
31
|
+
} from 'react';
|
|
25
32
|
import type {
|
|
26
33
|
LanguageKey,
|
|
27
34
|
LanguageResources,
|
|
28
35
|
} from '../providers/I18nProvider/types.js';
|
|
36
|
+
import type { DefaultFieldValues } from '../stores/form/types.js';
|
|
29
37
|
|
|
30
38
|
export type WidgetVariant = 'compact' | 'wide' | 'drawer';
|
|
31
39
|
export type WidgetSubvariant = 'default' | 'split' | 'custom' | 'refuel';
|
|
@@ -143,6 +151,10 @@ export interface WidgetFeeConfig {
|
|
|
143
151
|
* @returns A promise that resolves to the calculated fee as a number (e.g., 0.03 represents a 3% fee)
|
|
144
152
|
*/
|
|
145
153
|
calculateFee?(params: CalculateFeeParams): Promise<number | undefined>;
|
|
154
|
+
/**
|
|
155
|
+
* @internal
|
|
156
|
+
*/
|
|
157
|
+
_vcComponent: FC<{ route: RouteExtended }>;
|
|
146
158
|
}
|
|
147
159
|
|
|
148
160
|
export interface ToAddress {
|
|
@@ -182,6 +194,7 @@ export interface WidgetConfig {
|
|
|
182
194
|
toAddresses?: ToAddress[];
|
|
183
195
|
fromAmount?: number | string;
|
|
184
196
|
toAmount?: number | string;
|
|
197
|
+
formUpdateKey?: string;
|
|
185
198
|
|
|
186
199
|
contractCalls?: ContractCall[];
|
|
187
200
|
contractComponent?: ReactNode;
|
|
@@ -228,7 +241,36 @@ export interface WidgetConfig {
|
|
|
228
241
|
Partial<Record<'internal', string[]>>;
|
|
229
242
|
}
|
|
230
243
|
|
|
231
|
-
export interface
|
|
244
|
+
export interface FormFieldOptions {
|
|
245
|
+
setUrlSearchParam: boolean;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export interface FieldValues
|
|
249
|
+
extends Omit<DefaultFieldValues, 'fromAmount' | 'toAmount' | 'toAddress'> {
|
|
250
|
+
fromAmount?: number | string;
|
|
251
|
+
toAmount?: number | string;
|
|
252
|
+
toAddress?: ToAddress | string;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export type FieldNames = keyof FieldValues;
|
|
256
|
+
|
|
257
|
+
export type SetFieldValueFunction = <K extends FieldNames>(
|
|
258
|
+
key: K,
|
|
259
|
+
value: FieldValues[K],
|
|
260
|
+
options?: FormFieldOptions,
|
|
261
|
+
) => void;
|
|
262
|
+
|
|
263
|
+
export type FormState = {
|
|
264
|
+
setFieldValue: SetFieldValueFunction;
|
|
265
|
+
};
|
|
266
|
+
|
|
267
|
+
export type FormRef = MutableRefObject<FormState | null>;
|
|
268
|
+
|
|
269
|
+
export interface FormRefProps {
|
|
270
|
+
formRef?: FormRef;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export interface WidgetConfigProps extends FormRefProps {
|
|
232
274
|
config: WidgetConfig;
|
|
233
275
|
}
|
|
234
276
|
|
|
@@ -238,7 +280,8 @@ export interface WidgetConfigPartialProps {
|
|
|
238
280
|
|
|
239
281
|
export type WidgetProps = WidgetDrawerProps &
|
|
240
282
|
WidgetConfig &
|
|
241
|
-
WidgetConfigPartialProps
|
|
283
|
+
WidgetConfigPartialProps &
|
|
284
|
+
FormRefProps;
|
|
242
285
|
|
|
243
286
|
export interface WidgetDrawerProps extends WidgetConfigPartialProps {
|
|
244
287
|
elementRef?: RefObject<HTMLDivElement>;
|
package/utils/chainType.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { ChainId, ChainType
|
|
1
|
+
import { ChainId, ChainType } from '@lifi/sdk';
|
|
2
2
|
import { isAddress as isEVMAddress } from 'viem';
|
|
3
|
+
import { isSVMAddress } from './svm.js';
|
|
3
4
|
|
|
4
5
|
const chainTypeAddressValidation = {
|
|
5
6
|
[ChainType.EVM]: isEVMAddress,
|
|
6
7
|
[ChainType.SVM]: isSVMAddress,
|
|
7
|
-
[ChainType.UTXO]:
|
|
8
|
+
[ChainType.UTXO]: () => false,
|
|
8
9
|
};
|
|
9
10
|
|
|
10
11
|
export const getChainTypeFromAddress = (
|