@lifi/widget 3.8.0-beta.2 → 3.8.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/CHANGELOG.md +24 -0
- package/dist/esm/components/GasMessage/GasRefuelMessage.js +2 -2
- package/dist/esm/components/GasMessage/GasRefuelMessage.js.map +1 -1
- package/dist/esm/components/Search/SearchInput.d.ts +2 -1
- package/dist/esm/components/Search/SearchInput.js +3 -3
- package/dist/esm/components/Search/SearchInput.js.map +1 -1
- package/dist/esm/components/Token/Token.js +7 -3
- package/dist/esm/components/Token/Token.js.map +1 -1
- package/dist/esm/components/TransactionDetails.js +8 -6
- package/dist/esm/components/TransactionDetails.js.map +1 -1
- package/dist/esm/config/version.d.ts +1 -1
- package/dist/esm/config/version.js +1 -1
- package/dist/esm/config/version.js.map +1 -1
- package/dist/esm/hooks/useLanguages.js +2 -2
- package/dist/esm/hooks/useLanguages.js.map +1 -1
- package/dist/esm/hooks/useSettingMonitor.js +3 -2
- package/dist/esm/hooks/useSettingMonitor.js.map +1 -1
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/pages/SelectEnabledToolsPage.js +3 -6
- package/dist/esm/pages/SelectEnabledToolsPage.js.map +1 -1
- package/dist/esm/pages/SettingsPage/GasPriceSettings.js +2 -2
- package/dist/esm/pages/SettingsPage/GasPriceSettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/RoutePrioritySettings.js +2 -2
- package/dist/esm/pages/SettingsPage/RoutePrioritySettings.js.map +1 -1
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.js +16 -10
- package/dist/esm/pages/SettingsPage/SlippageSettings/SlippageSettings.js.map +1 -1
- package/dist/esm/providers/WidgetProvider/WidgetProvider.js +3 -2
- package/dist/esm/providers/WidgetProvider/WidgetProvider.js.map +1 -1
- package/dist/esm/stores/form/types.d.ts +1 -1
- package/dist/esm/stores/form/useFieldActions.d.ts +10 -2
- package/dist/esm/stores/form/useFieldActions.js +39 -1
- package/dist/esm/stores/form/useFieldActions.js.map +1 -1
- package/dist/esm/stores/settings/types.d.ts +5 -2
- package/dist/esm/stores/settings/types.js.map +1 -1
- package/dist/esm/stores/settings/useAppearance.js +3 -2
- package/dist/esm/stores/settings/useAppearance.js.map +1 -1
- package/dist/esm/stores/settings/useSettingsActions.d.ts +9 -0
- package/dist/esm/stores/settings/useSettingsActions.js +77 -0
- package/dist/esm/stores/settings/useSettingsActions.js.map +1 -0
- package/dist/esm/stores/settings/useSettingsStore.d.ts +0 -2
- package/dist/esm/stores/settings/useSettingsStore.js +4 -26
- package/dist/esm/stores/settings/useSettingsStore.js.map +1 -1
- package/dist/esm/stores/settings/utils/getStateValues.d.ts +2 -0
- package/dist/esm/stores/settings/utils/getStateValues.js +15 -0
- package/dist/esm/stores/settings/utils/getStateValues.js.map +1 -0
- package/dist/esm/types/events.d.ts +21 -4
- package/dist/esm/types/events.js +2 -0
- package/dist/esm/types/events.js.map +1 -1
- package/dist/esm/utils/deepEqual.d.ts +2 -0
- package/dist/esm/utils/deepEqual.js +52 -0
- package/dist/esm/utils/deepEqual.js.map +1 -0
- package/dist/esm/utils/format.d.ts +1 -1
- package/dist/esm/utils/format.js +3 -3
- package/dist/esm/utils/getPriceImpact.d.ts +9 -0
- package/dist/esm/utils/getPriceImpact.js +10 -0
- package/dist/esm/utils/getPriceImpact.js.map +1 -0
- package/package.json +5 -5
- package/src/components/GasMessage/GasRefuelMessage.tsx +3 -2
- package/src/components/Search/SearchInput.tsx +4 -1
- package/src/components/Token/Token.tsx +7 -8
- package/src/components/TransactionDetails.tsx +8 -17
- package/src/config/version.ts +1 -1
- package/src/hooks/useLanguages.ts +2 -2
- package/src/hooks/useSettingMonitor.ts +2 -2
- package/src/index.ts +1 -0
- package/src/pages/SelectEnabledToolsPage.tsx +6 -10
- package/src/pages/SettingsPage/GasPriceSettings.tsx +2 -2
- package/src/pages/SettingsPage/RoutePrioritySettings.tsx +2 -2
- package/src/pages/SettingsPage/SlippageSettings/SlippageSettings.tsx +31 -21
- package/src/providers/WidgetProvider/WidgetProvider.tsx +5 -3
- package/src/stores/form/types.ts +1 -1
- package/src/stores/form/useFieldActions.ts +73 -2
- package/src/stores/settings/types.ts +7 -2
- package/src/stores/settings/useAppearance.ts +3 -5
- package/src/stores/settings/useSettingsActions.ts +152 -0
- package/src/stores/settings/useSettingsStore.ts +4 -34
- package/src/stores/settings/utils/getStateValues.ts +16 -0
- package/src/types/events.ts +24 -3
- package/src/utils/deepEqual.ts +62 -0
- package/src/utils/format.ts +3 -3
- package/src/utils/getPriceImpact.ts +26 -0
|
@@ -12,7 +12,8 @@ import { formatUnits } from 'viem'
|
|
|
12
12
|
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
13
13
|
import { isRouteDone } from '../stores/routes/utils.js'
|
|
14
14
|
import { getAccumulatedFeeCostsBreakdown } from '../utils/fees.js'
|
|
15
|
-
import { formatTokenAmount
|
|
15
|
+
import { formatTokenAmount } from '../utils/format.js'
|
|
16
|
+
import { getPriceImpact } from '../utils/getPriceImpact.js'
|
|
16
17
|
import { Card } from './Card/Card.js'
|
|
17
18
|
import { CardIconButton } from './Card/CardIconButton.js'
|
|
18
19
|
import { FeeBreakdownTooltip } from './FeeBreakdownTooltip.js'
|
|
@@ -37,22 +38,12 @@ export const TransactionDetails: React.FC<TransactionDetailsProps> = ({
|
|
|
37
38
|
const { gasCosts, feeCosts, gasCostUSD, feeCostUSD, combinedFeesUSD } =
|
|
38
39
|
getAccumulatedFeeCostsBreakdown(route)
|
|
39
40
|
|
|
40
|
-
const
|
|
41
|
-
BigInt(route.fromAmount),
|
|
42
|
-
route.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
route.fromToken.priceUSD
|
|
47
|
-
)
|
|
48
|
-
const toTokenAmount = formatTokenAmount(
|
|
49
|
-
BigInt(route.toAmount),
|
|
50
|
-
route.toToken.decimals
|
|
51
|
-
)
|
|
52
|
-
const toTokenPrice =
|
|
53
|
-
formatTokenPrice(toTokenAmount, route.toToken.priceUSD) || 0.01
|
|
54
|
-
|
|
55
|
-
const priceImpact = toTokenPrice / fromTokenPrice - 1
|
|
41
|
+
const priceImpact = getPriceImpact({
|
|
42
|
+
fromAmount: BigInt(route.fromAmount),
|
|
43
|
+
toAmount: BigInt(route.toAmount),
|
|
44
|
+
fromToken: route.fromToken,
|
|
45
|
+
toToken: route.toToken,
|
|
46
|
+
})
|
|
56
47
|
|
|
57
48
|
const feeCollectionStep = route.steps[0].includedSteps.find(
|
|
58
49
|
(includedStep) => includedStep.tool === 'feeCollection'
|
package/src/config/version.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const name = '@lifi/widget'
|
|
2
|
-
export const version = '3.8.
|
|
2
|
+
export const version = '3.8.1'
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { useTranslation } from 'react-i18next'
|
|
2
2
|
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
3
3
|
import { useSettings } from '../stores/settings/useSettings.js'
|
|
4
|
-
import {
|
|
4
|
+
import { useSettingsActions } from '../stores/settings/useSettingsActions.js'
|
|
5
5
|
|
|
6
6
|
export const useLanguages = () => {
|
|
7
7
|
const { t, i18n } = useTranslation()
|
|
8
8
|
const { languages } = useWidgetConfig()
|
|
9
9
|
const { language } = useSettings(['language'])
|
|
10
|
-
const setValue =
|
|
10
|
+
const { setValue } = useSettingsActions()
|
|
11
11
|
|
|
12
12
|
const sortedLanguages = Object.keys(i18n.store.data).sort()
|
|
13
13
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { shallow } from 'zustand/shallow'
|
|
2
2
|
import { useWidgetConfig } from '../providers/WidgetProvider/WidgetProvider.js'
|
|
3
|
+
import { useSettingsActions } from '../stores/settings/useSettingsActions.js'
|
|
3
4
|
import {
|
|
4
5
|
defaultConfigurableSettings,
|
|
5
|
-
setDefaultSettings,
|
|
6
6
|
useSettingsStore,
|
|
7
7
|
} from '../stores/settings/useSettingsStore.js'
|
|
8
8
|
import { useTools } from './useTools.js'
|
|
@@ -25,8 +25,8 @@ export const useSettingMonitor = () => {
|
|
|
25
25
|
shallow
|
|
26
26
|
)
|
|
27
27
|
const { tools } = useTools()
|
|
28
|
-
const resetSettings = useSettingsStore((state) => state.reset)
|
|
29
28
|
const config = useWidgetConfig()
|
|
29
|
+
const { setDefaultSettings, resetSettings } = useSettingsActions()
|
|
30
30
|
|
|
31
31
|
const isSlippageChanged = config.slippage
|
|
32
32
|
? Number(slippage) !== config.slippage * 100
|
package/src/index.ts
CHANGED
|
@@ -27,6 +27,7 @@ import { useDefaultElementId } from '../hooks/useDefaultElementId.js'
|
|
|
27
27
|
import { useHeader } from '../hooks/useHeader.js'
|
|
28
28
|
import { useScrollableContainer } from '../hooks/useScrollableContainer.js'
|
|
29
29
|
import { useTools } from '../hooks/useTools.js'
|
|
30
|
+
import { useSettingsActions } from '../stores/settings/useSettingsActions.js'
|
|
30
31
|
import { useSettingsStore } from '../stores/settings/useSettingsStore.js'
|
|
31
32
|
|
|
32
33
|
interface SelectAllCheckboxProps {
|
|
@@ -76,16 +77,11 @@ export const SelectEnabledToolsPage: React.FC<{
|
|
|
76
77
|
}> = ({ type }) => {
|
|
77
78
|
const typeKey = type.toLowerCase() as 'bridges' | 'exchanges'
|
|
78
79
|
const { tools } = useTools()
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
state.setToolValue,
|
|
85
|
-
state.toggleToolKeys,
|
|
86
|
-
],
|
|
87
|
-
shallow
|
|
88
|
-
)
|
|
80
|
+
const { setToolValue, toggleToolKeys } = useSettingsActions()
|
|
81
|
+
const [enabledTools, disabledTools] = useSettingsStore(
|
|
82
|
+
(state) => [state[`_enabled${type}`], state[`disabled${type}`]],
|
|
83
|
+
shallow
|
|
84
|
+
)
|
|
89
85
|
|
|
90
86
|
const { t } = useTranslation()
|
|
91
87
|
const elementId = useDefaultElementId()
|
|
@@ -3,13 +3,13 @@ import { useTranslation } from 'react-i18next'
|
|
|
3
3
|
import { CardTabs, Tab } from '../../components/Tabs/Tabs.style.js'
|
|
4
4
|
import { useSettingMonitor } from '../../hooks/useSettingMonitor.js'
|
|
5
5
|
import { useSettings } from '../../stores/settings/useSettings.js'
|
|
6
|
-
import {
|
|
6
|
+
import { useSettingsActions } from '../../stores/settings/useSettingsActions.js'
|
|
7
7
|
import { BadgedValue } from './SettingsCard/BadgedValue.js'
|
|
8
8
|
import { SettingCardExpandable } from './SettingsCard/SettingCardExpandable.js'
|
|
9
9
|
|
|
10
10
|
export const GasPriceSettings: React.FC = () => {
|
|
11
11
|
const { t } = useTranslation()
|
|
12
|
-
const setValue =
|
|
12
|
+
const { setValue } = useSettingsActions()
|
|
13
13
|
const { isGasPriceChanged } = useSettingMonitor()
|
|
14
14
|
const { gasPrice } = useSettings(['gasPrice'])
|
|
15
15
|
|
|
@@ -4,7 +4,7 @@ import { useTranslation } from 'react-i18next'
|
|
|
4
4
|
import { CardTabs, Tab } from '../../components/Tabs/Tabs.style.js'
|
|
5
5
|
import { useSettingMonitor } from '../../hooks/useSettingMonitor.js'
|
|
6
6
|
import { useSettings } from '../../stores/settings/useSettings.js'
|
|
7
|
-
import {
|
|
7
|
+
import { useSettingsActions } from '../../stores/settings/useSettingsActions.js'
|
|
8
8
|
import { BadgedValue } from './SettingsCard/BadgedValue.js'
|
|
9
9
|
import { SettingCardExpandable } from './SettingsCard/SettingCardExpandable.js'
|
|
10
10
|
|
|
@@ -12,7 +12,7 @@ const Priorities: Order[] = ['CHEAPEST', 'FASTEST']
|
|
|
12
12
|
|
|
13
13
|
export const RoutePrioritySettings: React.FC = () => {
|
|
14
14
|
const { t } = useTranslation()
|
|
15
|
-
const setValue =
|
|
15
|
+
const { setValue } = useSettingsActions()
|
|
16
16
|
const { isRoutePriorityChanged } = useSettingMonitor()
|
|
17
17
|
const { routePriority } = useSettings(['routePriority'])
|
|
18
18
|
const currentRoutePriority = routePriority ?? ''
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import { Percent, WarningRounded } from '@mui/icons-material'
|
|
2
|
-
import { Box, Typography } from '@mui/material'
|
|
2
|
+
import { Box, Typography, debounce } from '@mui/material'
|
|
3
3
|
import type { ChangeEventHandler, FocusEventHandler } from 'react'
|
|
4
|
-
import { useRef, useState } from 'react'
|
|
4
|
+
import { useCallback, useMemo, useRef, useState } from 'react'
|
|
5
5
|
import { useTranslation } from 'react-i18next'
|
|
6
6
|
import { useSettingMonitor } from '../../../hooks/useSettingMonitor.js'
|
|
7
7
|
import { useSettings } from '../../../stores/settings/useSettings.js'
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
useSettingsStore,
|
|
11
|
-
} from '../../../stores/settings/useSettingsStore.js'
|
|
8
|
+
import { useSettingsActions } from '../../../stores/settings/useSettingsActions.js'
|
|
9
|
+
import { defaultSlippage } from '../../../stores/settings/useSettingsStore.js'
|
|
12
10
|
import { formatSlippage } from '../../../utils/format.js'
|
|
13
11
|
import { BadgedValue } from '../SettingsCard/BadgedValue.js'
|
|
14
12
|
import { SettingCardExpandable } from '../SettingsCard/SettingCardExpandable.js'
|
|
@@ -24,36 +22,48 @@ export const SlippageSettings: React.FC = () => {
|
|
|
24
22
|
const { isSlippageOutsideRecommendedLimits, isSlippageChanged } =
|
|
25
23
|
useSettingMonitor()
|
|
26
24
|
const { slippage } = useSettings(['slippage'])
|
|
27
|
-
const setValue =
|
|
25
|
+
const { setValue } = useSettingsActions()
|
|
28
26
|
const defaultValue = useRef(slippage)
|
|
29
27
|
const [focused, setFocused] = useState<'input' | 'button'>()
|
|
30
28
|
|
|
29
|
+
const customInputValue =
|
|
30
|
+
!slippage || slippage === defaultSlippage ? '' : slippage
|
|
31
|
+
|
|
32
|
+
const [inputValue, setInputValue] = useState(customInputValue)
|
|
33
|
+
|
|
31
34
|
const handleDefaultClick = () => {
|
|
32
35
|
setValue('slippage', formatSlippage(defaultSlippage, defaultValue.current))
|
|
33
36
|
}
|
|
34
37
|
|
|
35
|
-
const
|
|
36
|
-
const { value } = event.target
|
|
38
|
+
const debouncedSetValue = useMemo(() => debounce(setValue, 500), [setValue])
|
|
37
39
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
const handleInputUpdate: ChangeEventHandler<HTMLInputElement> = useCallback(
|
|
41
|
+
(event) => {
|
|
42
|
+
const { value } = event.target
|
|
43
|
+
|
|
44
|
+
setInputValue(formatSlippage(value, defaultValue.current, true))
|
|
45
|
+
|
|
46
|
+
debouncedSetValue(
|
|
47
|
+
'slippage',
|
|
48
|
+
formatSlippage(value || defaultSlippage, defaultValue.current, true)
|
|
49
|
+
)
|
|
50
|
+
},
|
|
51
|
+
[debouncedSetValue]
|
|
52
|
+
)
|
|
43
53
|
|
|
44
54
|
const handleInputBlur: FocusEventHandler<HTMLInputElement> = (event) => {
|
|
45
55
|
setFocused(undefined)
|
|
46
56
|
|
|
47
57
|
const { value } = event.target
|
|
48
58
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
const formattedValue = formatSlippage(
|
|
60
|
+
value || defaultSlippage,
|
|
61
|
+
defaultValue.current
|
|
52
62
|
)
|
|
53
|
-
|
|
63
|
+
setInputValue(formattedValue === defaultSlippage ? '' : formattedValue)
|
|
54
64
|
|
|
55
|
-
|
|
56
|
-
|
|
65
|
+
setValue('slippage', formattedValue)
|
|
66
|
+
}
|
|
57
67
|
|
|
58
68
|
const badgeColor = isSlippageOutsideRecommendedLimits
|
|
59
69
|
? 'warning'
|
|
@@ -98,7 +108,7 @@ export const SlippageSettings: React.FC = () => {
|
|
|
98
108
|
setFocused('input')
|
|
99
109
|
}}
|
|
100
110
|
onBlur={handleInputBlur}
|
|
101
|
-
value={
|
|
111
|
+
value={inputValue}
|
|
102
112
|
autoComplete="off"
|
|
103
113
|
/>
|
|
104
114
|
</SettingsFieldSet>
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SDKConfig } from '@lifi/sdk'
|
|
2
|
+
import { config, createConfig } from '@lifi/sdk'
|
|
2
3
|
import { createContext, useContext, useId, useMemo } from 'react'
|
|
3
4
|
import { version } from '../../config/version.js'
|
|
4
|
-
import {
|
|
5
|
+
import { useSettingsActions } from '../../stores/settings/useSettingsActions.js'
|
|
5
6
|
import type { WidgetContextProps, WidgetProviderProps } from './types.js'
|
|
6
7
|
|
|
7
8
|
const initialContext: WidgetContextProps = {
|
|
@@ -20,6 +21,7 @@ export const WidgetProvider: React.FC<
|
|
|
20
21
|
React.PropsWithChildren<WidgetProviderProps>
|
|
21
22
|
> = ({ children, config: widgetConfig }) => {
|
|
22
23
|
const elementId = useId()
|
|
24
|
+
const { setDefaultSettings } = useSettingsActions()
|
|
23
25
|
|
|
24
26
|
if (!widgetConfig?.integrator) {
|
|
25
27
|
throw new Error('Required property "integrator" is missing.')
|
|
@@ -69,7 +71,7 @@ export const WidgetProvider: React.FC<
|
|
|
69
71
|
integrator: widgetConfig.integrator,
|
|
70
72
|
}
|
|
71
73
|
}
|
|
72
|
-
}, [elementId, widgetConfig])
|
|
74
|
+
}, [elementId, widgetConfig, setDefaultSettings])
|
|
73
75
|
return (
|
|
74
76
|
<WidgetContext.Provider value={value}>{children}</WidgetContext.Provider>
|
|
75
77
|
)
|
package/src/stores/form/types.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
|
+
import { useCallback } from 'react'
|
|
1
2
|
import { shallow } from 'zustand/shallow'
|
|
2
|
-
import
|
|
3
|
+
import { useWidgetEvents } from '../../hooks/useWidgetEvents.js'
|
|
4
|
+
import type { FormFieldChanged } from '../../types/events.js'
|
|
5
|
+
import { WidgetEvent } from '../../types/events.js'
|
|
6
|
+
import type {
|
|
7
|
+
DefaultValues,
|
|
8
|
+
FormActions,
|
|
9
|
+
FormFieldNames,
|
|
10
|
+
GenericFormValue,
|
|
11
|
+
SetOptions,
|
|
12
|
+
} from './types.js'
|
|
3
13
|
import { useFormStore } from './useFormStore.js'
|
|
4
14
|
|
|
5
15
|
export const useFieldActions = () => {
|
|
16
|
+
const emitter = useWidgetEvents()
|
|
6
17
|
const actions = useFormStore<FormActions>(
|
|
7
18
|
(store) => ({
|
|
8
19
|
getFieldValues: store.getFieldValues,
|
|
@@ -16,5 +27,65 @@ export const useFieldActions = () => {
|
|
|
16
27
|
shallow
|
|
17
28
|
)
|
|
18
29
|
|
|
19
|
-
|
|
30
|
+
const setFieldValueWithEmittedEvents = useCallback(
|
|
31
|
+
(
|
|
32
|
+
fieldName: FormFieldNames,
|
|
33
|
+
newValue: GenericFormValue,
|
|
34
|
+
options?: SetOptions
|
|
35
|
+
) => {
|
|
36
|
+
const oldValue = actions.getFieldValues(fieldName)[0]
|
|
37
|
+
|
|
38
|
+
actions.setFieldValue(fieldName, newValue, options)
|
|
39
|
+
|
|
40
|
+
if (newValue !== oldValue) {
|
|
41
|
+
emitter.emit(WidgetEvent.FormFieldChanged, {
|
|
42
|
+
fieldName,
|
|
43
|
+
newValue,
|
|
44
|
+
oldValue,
|
|
45
|
+
} as FormFieldChanged)
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
[actions, emitter]
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
const setUserAndDefaultValuesWithEmittedEvents = useCallback(
|
|
52
|
+
(formValues: Partial<DefaultValues>) => {
|
|
53
|
+
const formValuesKeys = Object.keys(formValues) as FormFieldNames[]
|
|
54
|
+
|
|
55
|
+
const changedValues = formValuesKeys.reduce(
|
|
56
|
+
(accum, fieldName) => {
|
|
57
|
+
const oldValue = actions.getFieldValues(fieldName)[0]
|
|
58
|
+
const newValue = formValues[fieldName]
|
|
59
|
+
|
|
60
|
+
if (newValue !== oldValue) {
|
|
61
|
+
accum.push({ fieldName, newValue, oldValue })
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
return accum
|
|
65
|
+
},
|
|
66
|
+
[] as {
|
|
67
|
+
fieldName: FormFieldNames
|
|
68
|
+
newValue: GenericFormValue
|
|
69
|
+
oldValue: GenericFormValue
|
|
70
|
+
}[]
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
actions.setUserAndDefaultValues(formValues)
|
|
74
|
+
|
|
75
|
+
changedValues.forEach(({ fieldName, newValue, oldValue }) => {
|
|
76
|
+
emitter.emit(WidgetEvent.FormFieldChanged, {
|
|
77
|
+
fieldName,
|
|
78
|
+
newValue,
|
|
79
|
+
oldValue,
|
|
80
|
+
} as FormFieldChanged)
|
|
81
|
+
})
|
|
82
|
+
},
|
|
83
|
+
[actions, emitter]
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
...actions,
|
|
88
|
+
setFieldValue: setFieldValueWithEmittedEvents,
|
|
89
|
+
setUserAndDefaultValues: setUserAndDefaultValuesWithEmittedEvents,
|
|
90
|
+
}
|
|
20
91
|
}
|
|
@@ -9,6 +9,8 @@ export type ValueSetter<S> = <K extends keyof S>(
|
|
|
9
9
|
value: S[Extract<K, string>]
|
|
10
10
|
) => void
|
|
11
11
|
|
|
12
|
+
export type ValueGetter<S> = <K extends keyof S>(key: K) => S[K]
|
|
13
|
+
|
|
12
14
|
export type ValuesSetter<S> = <K extends keyof S>(
|
|
13
15
|
values: Record<K, S[Extract<K, string>]>
|
|
14
16
|
) => void
|
|
@@ -31,9 +33,10 @@ export interface SettingsProps {
|
|
|
31
33
|
_enabledExchanges: Record<string, boolean>
|
|
32
34
|
}
|
|
33
35
|
|
|
34
|
-
export interface
|
|
36
|
+
export interface SettingsActions {
|
|
35
37
|
setValue: ValueSetter<SettingsProps>
|
|
36
|
-
|
|
38
|
+
getValue: ValueGetter<SettingsProps>
|
|
39
|
+
getSettings: () => SettingsProps
|
|
37
40
|
initializeTools(
|
|
38
41
|
toolType: SettingsToolType,
|
|
39
42
|
tools: string[],
|
|
@@ -44,6 +47,8 @@ export interface SettingsState extends SettingsProps {
|
|
|
44
47
|
reset(bridges: string[], exchanges: string[]): void
|
|
45
48
|
}
|
|
46
49
|
|
|
50
|
+
export type SettingsState = SettingsProps & SettingsActions
|
|
51
|
+
|
|
47
52
|
export interface SendToWalletState {
|
|
48
53
|
showSendToWallet: boolean
|
|
49
54
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { useSettingsActions } from '../../stores/settings/useSettingsActions.js'
|
|
2
2
|
import type { Appearance } from '../../types/widget.js'
|
|
3
3
|
import { useSettingsStore } from './useSettingsStore.js'
|
|
4
4
|
|
|
@@ -6,10 +6,8 @@ export const useAppearance = (): [
|
|
|
6
6
|
Appearance,
|
|
7
7
|
(appearance: Appearance) => void,
|
|
8
8
|
] => {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
shallow
|
|
12
|
-
)
|
|
9
|
+
const { setValue } = useSettingsActions()
|
|
10
|
+
const appearance = useSettingsStore((state) => state.appearance)
|
|
13
11
|
const setAppearance = (appearance: Appearance) => {
|
|
14
12
|
setValue('appearance', appearance)
|
|
15
13
|
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { useCallback } from 'react'
|
|
2
|
+
import { shallow } from 'zustand/shallow'
|
|
3
|
+
import type { widgetEvents } from '../../hooks/useWidgetEvents.js'
|
|
4
|
+
import { useWidgetEvents } from '../../hooks/useWidgetEvents.js'
|
|
5
|
+
import { WidgetEvent } from '../../types/events.js'
|
|
6
|
+
import type { WidgetConfig } from '../../types/widget.js'
|
|
7
|
+
import { deepEqual } from '../../utils/deepEqual.js'
|
|
8
|
+
import type {
|
|
9
|
+
SettingsActions,
|
|
10
|
+
SettingsProps,
|
|
11
|
+
SettingsToolType,
|
|
12
|
+
ValueSetter,
|
|
13
|
+
} from './types.js'
|
|
14
|
+
import {
|
|
15
|
+
defaultConfigurableSettings,
|
|
16
|
+
useSettingsStore,
|
|
17
|
+
} from './useSettingsStore.js'
|
|
18
|
+
|
|
19
|
+
const emitEventOnChange = <T extends (...args: any[]) => any>(
|
|
20
|
+
emitter: typeof widgetEvents,
|
|
21
|
+
actions: Omit<SettingsActions, 'initializeTools'>,
|
|
22
|
+
settingFunction: T,
|
|
23
|
+
...args: Parameters<T>
|
|
24
|
+
) => {
|
|
25
|
+
const oldSettings = actions.getSettings()
|
|
26
|
+
|
|
27
|
+
settingFunction(...args)
|
|
28
|
+
|
|
29
|
+
const newSettings = actions.getSettings()
|
|
30
|
+
|
|
31
|
+
if (!deepEqual(oldSettings, newSettings)) {
|
|
32
|
+
;(Object.keys(oldSettings) as (keyof SettingsProps)[]).forEach(
|
|
33
|
+
(toolKey) => {
|
|
34
|
+
if (!deepEqual(oldSettings[toolKey], newSettings[toolKey])) {
|
|
35
|
+
emitter.emit(WidgetEvent.SettingUpdated, {
|
|
36
|
+
setting: toolKey,
|
|
37
|
+
newValue: newSettings[toolKey],
|
|
38
|
+
oldValue: oldSettings[toolKey],
|
|
39
|
+
newSettings: newSettings,
|
|
40
|
+
oldSettings: oldSettings,
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export const useSettingsActions = () => {
|
|
49
|
+
const emitter = useWidgetEvents()
|
|
50
|
+
const actions = useSettingsStore(
|
|
51
|
+
(state) => ({
|
|
52
|
+
setValue: state.setValue,
|
|
53
|
+
getValue: state.getValue,
|
|
54
|
+
getSettings: state.getSettings,
|
|
55
|
+
reset: state.reset,
|
|
56
|
+
setToolValue: state.setToolValue,
|
|
57
|
+
toggleToolKeys: state.toggleToolKeys,
|
|
58
|
+
}),
|
|
59
|
+
shallow
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
const setValueWithEmittedEvent = useCallback<ValueSetter<SettingsProps>>(
|
|
63
|
+
(value, newValue) => {
|
|
64
|
+
const setting = value as keyof SettingsProps
|
|
65
|
+
emitEventOnChange(emitter, actions, actions.setValue, setting, newValue)
|
|
66
|
+
},
|
|
67
|
+
[emitter, actions]
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
const setDefaultSettingsWithEmittedEvents = useCallback(
|
|
71
|
+
(config?: WidgetConfig) => {
|
|
72
|
+
const slippage = actions.getValue('slippage')
|
|
73
|
+
const routePriority = actions.getValue('routePriority')
|
|
74
|
+
const gasPrice = actions.getValue('gasPrice')
|
|
75
|
+
|
|
76
|
+
const defaultSlippage =
|
|
77
|
+
(config?.slippage || config?.sdkConfig?.routeOptions?.slippage || 0) *
|
|
78
|
+
100
|
|
79
|
+
const defaultRoutePriority =
|
|
80
|
+
config?.routePriority || config?.sdkConfig?.routeOptions?.order
|
|
81
|
+
|
|
82
|
+
defaultConfigurableSettings.slippage = (
|
|
83
|
+
defaultSlippage || defaultConfigurableSettings.slippage
|
|
84
|
+
)?.toString()
|
|
85
|
+
|
|
86
|
+
defaultConfigurableSettings.routePriority =
|
|
87
|
+
defaultRoutePriority || defaultConfigurableSettings.routePriority
|
|
88
|
+
|
|
89
|
+
if (!slippage) {
|
|
90
|
+
setValueWithEmittedEvent(
|
|
91
|
+
'slippage',
|
|
92
|
+
defaultConfigurableSettings.slippage
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
if (!routePriority) {
|
|
96
|
+
setValueWithEmittedEvent(
|
|
97
|
+
'routePriority',
|
|
98
|
+
defaultConfigurableSettings.routePriority
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
if (!gasPrice) {
|
|
102
|
+
setValueWithEmittedEvent(
|
|
103
|
+
'gasPrice',
|
|
104
|
+
defaultConfigurableSettings.gasPrice
|
|
105
|
+
)
|
|
106
|
+
}
|
|
107
|
+
},
|
|
108
|
+
[actions, setValueWithEmittedEvent]
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
const resetWithEmittedEvents = useCallback(
|
|
112
|
+
(bridges: string[], exchanges: string[]) => {
|
|
113
|
+
emitEventOnChange(emitter, actions, actions.reset, bridges, exchanges)
|
|
114
|
+
},
|
|
115
|
+
[emitter, actions]
|
|
116
|
+
)
|
|
117
|
+
|
|
118
|
+
const setToolValueWithEmittedEvents = useCallback(
|
|
119
|
+
(toolType: SettingsToolType, tool: string, value: boolean) => {
|
|
120
|
+
emitEventOnChange(
|
|
121
|
+
emitter,
|
|
122
|
+
actions,
|
|
123
|
+
actions.setToolValue,
|
|
124
|
+
toolType,
|
|
125
|
+
tool,
|
|
126
|
+
value
|
|
127
|
+
)
|
|
128
|
+
},
|
|
129
|
+
[emitter, actions]
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
const toggleToolKeysWithEmittedEvents = useCallback(
|
|
133
|
+
(toolType: SettingsToolType, toolKeys: string[]) => {
|
|
134
|
+
emitEventOnChange(
|
|
135
|
+
emitter,
|
|
136
|
+
actions,
|
|
137
|
+
actions.toggleToolKeys,
|
|
138
|
+
toolType,
|
|
139
|
+
toolKeys
|
|
140
|
+
)
|
|
141
|
+
},
|
|
142
|
+
[emitter, actions]
|
|
143
|
+
)
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
setValue: setValueWithEmittedEvent,
|
|
147
|
+
setDefaultSettings: setDefaultSettingsWithEmittedEvents,
|
|
148
|
+
resetSettings: resetWithEmittedEvents,
|
|
149
|
+
setToolValue: setToolValueWithEmittedEvents,
|
|
150
|
+
toggleToolKeys: toggleToolKeysWithEmittedEvents,
|
|
151
|
+
}
|
|
152
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import type { StateCreator } from 'zustand'
|
|
2
2
|
import { persist } from 'zustand/middleware'
|
|
3
3
|
import { createWithEqualityFn } from 'zustand/traditional'
|
|
4
|
-
import type { WidgetConfig } from '../../types/widget.js'
|
|
5
4
|
import type { SettingsProps, SettingsState } from './types.js'
|
|
6
5
|
import { SettingsToolTypes } from './types.js'
|
|
6
|
+
import { getStateValues } from './utils/getStateValues.js'
|
|
7
7
|
|
|
8
8
|
export const defaultSlippage = '0.5'
|
|
9
9
|
|
|
@@ -36,16 +36,8 @@ export const useSettingsStore = createWithEqualityFn<SettingsState>(
|
|
|
36
36
|
set(() => ({
|
|
37
37
|
[key]: value,
|
|
38
38
|
})),
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
const updatedState: SettingsProps = { ...state }
|
|
42
|
-
for (const key in values) {
|
|
43
|
-
if (Object.hasOwn(state, key)) {
|
|
44
|
-
updatedState[key] = values[key]
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
return updatedState
|
|
48
|
-
}),
|
|
39
|
+
getSettings: () => getStateValues(get()),
|
|
40
|
+
getValue: (key) => get()[key],
|
|
49
41
|
initializeTools: (toolType, tools, reset) => {
|
|
50
42
|
if (!tools.length) {
|
|
51
43
|
return
|
|
@@ -141,6 +133,7 @@ export const useSettingsStore = createWithEqualityFn<SettingsState>(
|
|
|
141
133
|
}))
|
|
142
134
|
get().initializeTools('Bridges', bridges, true)
|
|
143
135
|
get().initializeTools('Exchanges', exchanges, true)
|
|
136
|
+
return { ...get() }
|
|
144
137
|
},
|
|
145
138
|
}),
|
|
146
139
|
{
|
|
@@ -187,26 +180,3 @@ export const useSettingsStore = createWithEqualityFn<SettingsState>(
|
|
|
187
180
|
) as StateCreator<SettingsState, [], [], SettingsState>,
|
|
188
181
|
Object.is
|
|
189
182
|
)
|
|
190
|
-
|
|
191
|
-
export const setDefaultSettings = (config?: WidgetConfig) => {
|
|
192
|
-
const { slippage, routePriority, setValue, gasPrice } =
|
|
193
|
-
useSettingsStore.getState()
|
|
194
|
-
const defaultSlippage =
|
|
195
|
-
(config?.slippage || config?.sdkConfig?.routeOptions?.slippage || 0) * 100
|
|
196
|
-
const defaultRoutePriority =
|
|
197
|
-
config?.routePriority || config?.sdkConfig?.routeOptions?.order
|
|
198
|
-
defaultConfigurableSettings.slippage = (
|
|
199
|
-
defaultSlippage || defaultConfigurableSettings.slippage
|
|
200
|
-
)?.toString()
|
|
201
|
-
defaultConfigurableSettings.routePriority =
|
|
202
|
-
defaultRoutePriority || defaultConfigurableSettings.routePriority
|
|
203
|
-
if (!slippage) {
|
|
204
|
-
setValue('slippage', defaultConfigurableSettings.slippage)
|
|
205
|
-
}
|
|
206
|
-
if (!routePriority) {
|
|
207
|
-
setValue('routePriority', defaultConfigurableSettings.routePriority)
|
|
208
|
-
}
|
|
209
|
-
if (!gasPrice) {
|
|
210
|
-
setValue('gasPrice', defaultConfigurableSettings.gasPrice)
|
|
211
|
-
}
|
|
212
|
-
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { SettingsProps, SettingsState } from '../types.js'
|
|
2
|
+
|
|
3
|
+
export const getStateValues = (state: SettingsState): SettingsProps => ({
|
|
4
|
+
appearance: state.appearance,
|
|
5
|
+
gasPrice: state.gasPrice,
|
|
6
|
+
language: state.language,
|
|
7
|
+
routePriority: state.routePriority,
|
|
8
|
+
enabledAutoRefuel: state.enabledAutoRefuel,
|
|
9
|
+
slippage: state.slippage,
|
|
10
|
+
disabledBridges: [...state.disabledBridges],
|
|
11
|
+
enabledBridges: [...state.enabledBridges],
|
|
12
|
+
_enabledBridges: { ...state._enabledBridges },
|
|
13
|
+
disabledExchanges: [...state.disabledExchanges],
|
|
14
|
+
enabledExchanges: [...state.enabledExchanges],
|
|
15
|
+
_enabledExchanges: { ...state._enabledExchanges },
|
|
16
|
+
})
|