@rango-dev/widget-embedded 0.31.1-next.2 → 0.32.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AppRoutes.d.ts.map +1 -1
- package/dist/components/BlockchainList/BlockchainList.d.ts.map +1 -1
- package/dist/components/BlockchainList/BlockchainList.styles.d.ts +4 -1
- package/dist/components/BlockchainList/BlockchainList.styles.d.ts.map +1 -1
- package/dist/components/BlockchainList/BlockchainList.types.d.ts +1 -0
- package/dist/components/BlockchainList/BlockchainList.types.d.ts.map +1 -1
- package/dist/components/BlockchainSelectorButton/BlockchainSelectorButton.d.ts +4 -0
- package/dist/components/BlockchainSelectorButton/BlockchainSelectorButton.d.ts.map +1 -0
- package/dist/components/BlockchainSelectorButton/BlockchainSelectorButton.styles.d.ts +483 -0
- package/dist/components/BlockchainSelectorButton/BlockchainSelectorButton.styles.d.ts.map +1 -0
- package/dist/components/BlockchainSelectorButton/BlockchainSelectorButton.types.d.ts +12 -0
- package/dist/components/BlockchainSelectorButton/BlockchainSelectorButton.types.d.ts.map +1 -0
- package/dist/components/BlockchainSelectorButton/index.d.ts +2 -0
- package/dist/components/BlockchainSelectorButton/index.d.ts.map +1 -0
- package/dist/components/BlockchainsSection/BlockchainsSection.styles.d.ts +1 -0
- package/dist/components/BlockchainsSection/BlockchainsSection.styles.d.ts.map +1 -1
- package/dist/components/ConfirmWalletsModal/ConfirmWallets.styles.d.ts +11 -0
- package/dist/components/ConfirmWalletsModal/ConfirmWallets.styles.d.ts.map +1 -1
- package/dist/components/ConfirmWalletsModal/WalletList.styles.d.ts +3 -0
- package/dist/components/ConfirmWalletsModal/WalletList.styles.d.ts.map +1 -1
- package/dist/components/CustomCollapsible/CustomCollapsible.styles.d.ts +4 -0
- package/dist/components/CustomCollapsible/CustomCollapsible.styles.d.ts.map +1 -1
- package/dist/components/CustomDestination/CustomDestination.d.ts.map +1 -1
- package/dist/components/CustomDestination/CustomDestination.styles.d.ts +5 -2
- package/dist/components/CustomDestination/CustomDestination.styles.d.ts.map +1 -1
- package/dist/components/CustomTokenModal/CustomTokenModal.d.ts +4 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.d.ts.map +1 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.helpers.d.ts +3 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.helpers.d.ts.map +1 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.styles.d.ts +323 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.styles.d.ts.map +1 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.types.d.ts +9 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.types.d.ts.map +1 -0
- package/dist/components/CustomTokenModal/index.d.ts +2 -0
- package/dist/components/CustomTokenModal/index.d.ts.map +1 -0
- package/dist/components/FilterSelector/FilterSelector.style.d.ts +6 -0
- package/dist/components/FilterSelector/FilterSelector.style.d.ts.map +1 -1
- package/dist/components/HeaderButtons/HeaderButtons.styles.d.ts +8 -0
- package/dist/components/HeaderButtons/HeaderButtons.styles.d.ts.map +1 -1
- package/dist/components/HistoryGroupedList/HistoryGroupedList.styles.d.ts +6 -0
- package/dist/components/HistoryGroupedList/HistoryGroupedList.styles.d.ts.map +1 -1
- package/dist/components/Layout/Layout.styles.d.ts +4 -0
- package/dist/components/Layout/Layout.styles.d.ts.map +1 -1
- package/dist/components/Layout/PageContainer.d.ts +1 -0
- package/dist/components/Layout/PageContainer.d.ts.map +1 -1
- package/dist/components/Layout/ScrollableArea.d.ts +1 -0
- package/dist/components/Layout/ScrollableArea.d.ts.map +1 -1
- package/dist/components/LoadingLiquiditySourceList/LoadingLiquiditySourceList.styles.d.ts +1 -0
- package/dist/components/LoadingLiquiditySourceList/LoadingLiquiditySourceList.styles.d.ts.map +1 -1
- package/dist/components/LoadingSwapDetails/LoadingSwapDetails.styles.d.ts +14 -0
- package/dist/components/LoadingSwapDetails/LoadingSwapDetails.styles.d.ts.map +1 -1
- package/dist/components/NoResult/NoResult.styles.d.ts +4 -0
- package/dist/components/NoResult/NoResult.styles.d.ts.map +1 -1
- package/dist/components/Quote/Quote.styles.d.ts +22 -1
- package/dist/components/Quote/Quote.styles.d.ts.map +1 -1
- package/dist/components/Quote/QuoteCostDetails.styles.d.ts +5 -0
- package/dist/components/Quote/QuoteCostDetails.styles.d.ts.map +1 -1
- package/dist/components/Quote/QuoteSummary.styles.d.ts +2 -0
- package/dist/components/Quote/QuoteSummary.styles.d.ts.map +1 -1
- package/dist/components/QuoteSkeleton/QuoteSkeleton.styles.d.ts +4 -0
- package/dist/components/QuoteSkeleton/QuoteSkeleton.styles.d.ts.map +1 -1
- package/dist/components/QuoteSkeleton/QuoteSummarySkeleton.styles.d.ts +10 -0
- package/dist/components/QuoteSkeleton/QuoteSummarySkeleton.styles.d.ts.map +1 -1
- package/dist/components/QuoteSkeleton/StepSkeleton.styles.d.ts +5 -0
- package/dist/components/QuoteSkeleton/StepSkeleton.styles.d.ts.map +1 -1
- package/dist/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.styles.d.ts +4 -0
- package/dist/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.styles.d.ts.map +1 -1
- package/dist/components/Quotes/Quotes.styles.d.ts +3 -0
- package/dist/components/Quotes/Quotes.styles.d.ts.map +1 -1
- package/dist/components/RefreshModal/RefreshModal.styles.d.ts +2 -1
- package/dist/components/RefreshModal/RefreshModal.styles.d.ts.map +1 -1
- package/dist/components/SearchInput/SearchInput.styles.d.ts +1 -0
- package/dist/components/SearchInput/SearchInput.styles.d.ts.map +1 -1
- package/dist/components/SettingsContainer/SettingsContainer.style.d.ts +3 -0
- package/dist/components/SettingsContainer/SettingsContainer.style.d.ts.map +1 -1
- package/dist/components/Slippage/Slippage.styles.d.ts +5 -0
- package/dist/components/Slippage/Slippage.styles.d.ts.map +1 -1
- package/dist/components/SwapDetails/SwapDetails.styles.d.ts +15 -0
- package/dist/components/SwapDetails/SwapDetails.styles.d.ts.map +1 -1
- package/dist/components/SwapDetailsAlerts/SwapDetailsAlerts.styles.d.ts +3 -0
- package/dist/components/SwapDetailsAlerts/SwapDetailsAlerts.styles.d.ts.map +1 -1
- package/dist/components/SwapDetailsModal/SwapDetailsModal.styles.d.ts +2 -0
- package/dist/components/SwapDetailsModal/SwapDetailsModal.styles.d.ts.map +1 -1
- package/dist/components/SwitchFromAndTo/SwitchFromAndTo.styles.d.ts +2 -0
- package/dist/components/SwitchFromAndTo/SwitchFromAndTo.styles.d.ts.map +1 -1
- package/dist/components/TokenList/TokenList.d.ts.map +1 -1
- package/dist/components/TokenList/TokenList.styles.d.ts +18 -0
- package/dist/components/TokenList/TokenList.styles.d.ts.map +1 -1
- package/dist/components/TokenList/TokenList.types.d.ts +5 -2
- package/dist/components/TokenList/TokenList.types.d.ts.map +1 -1
- package/dist/components/WalletDerivationPathModal/WalletDerivationPathModal.styles.d.ts +2 -0
- package/dist/components/WalletDerivationPathModal/WalletDerivationPathModal.styles.d.ts.map +1 -1
- package/dist/components/WalletModal/WalletModalContent.styles.d.ts +4 -0
- package/dist/components/WalletModal/WalletModalContent.styles.d.ts.map +1 -1
- package/dist/components/WalletNamespacesModal/WalletNamespacesModal.styles.d.ts +1 -0
- package/dist/components/WalletNamespacesModal/WalletNamespacesModal.styles.d.ts.map +1 -1
- package/dist/constants/customTokens.d.ts +2 -0
- package/dist/constants/customTokens.d.ts.map +1 -0
- package/dist/constants/navigationRoutes.d.ts +2 -0
- package/dist/constants/navigationRoutes.d.ts.map +1 -1
- package/dist/constants/searchParams.d.ts +1 -0
- package/dist/constants/searchParams.d.ts.map +1 -1
- package/dist/containers/App/App.styles.d.ts +1 -0
- package/dist/containers/App/App.styles.d.ts.map +1 -1
- package/dist/containers/ExpandedQuotes/ExpandedQuotes.styles.d.ts +2 -0
- package/dist/containers/ExpandedQuotes/ExpandedQuotes.styles.d.ts.map +1 -1
- package/dist/containers/Inputs/Inputs.styles.d.ts +2 -0
- package/dist/containers/Inputs/Inputs.styles.d.ts.map +1 -1
- package/dist/containers/QuoteInfo/QuoteInfo.styles.d.ts +3 -0
- package/dist/containers/QuoteInfo/QuoteInfo.styles.d.ts.map +1 -1
- package/dist/containers/Settings/Lists.d.ts.map +1 -1
- package/dist/hooks/useFetchCustomToken.d.ts +16 -0
- package/dist/hooks/useFetchCustomToken.d.ts.map +1 -0
- package/dist/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.d.ts +2 -2
- package/dist/hooks/useSwapInput.d.ts.map +1 -1
- package/dist/hooks/useSyncUrlAndStore/useSyncUrlAndStore.d.ts.map +1 -1
- package/dist/hooks/useTheme.d.ts +1 -0
- package/dist/hooks/useTheme.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +4 -4
- package/dist/pages/AddCustomTokenPage.d.ts +3 -0
- package/dist/pages/AddCustomTokenPage.d.ts.map +1 -0
- package/dist/pages/CustomTokensPage.d.ts +3 -0
- package/dist/pages/CustomTokensPage.d.ts.map +1 -0
- package/dist/pages/SelectBlockchainPage.d.ts +2 -1
- package/dist/pages/SelectBlockchainPage.d.ts.map +1 -1
- package/dist/store/AppStore.d.ts +2 -0
- package/dist/store/AppStore.d.ts.map +1 -1
- package/dist/store/app.d.ts +2 -0
- package/dist/store/app.d.ts.map +1 -1
- package/dist/store/quote.d.ts.map +1 -1
- package/dist/store/slices/data.d.ts +4 -3
- package/dist/store/slices/data.d.ts.map +1 -1
- package/dist/store/slices/settings.d.ts +7 -2
- package/dist/store/slices/settings.d.ts.map +1 -1
- package/dist/store/utils/data.d.ts +4 -1
- package/dist/store/utils/data.d.ts.map +1 -1
- package/dist/types/config.d.ts +3 -1
- package/dist/types/config.d.ts.map +1 -1
- package/dist/utils/meta.d.ts +1 -0
- package/dist/utils/meta.d.ts.map +1 -1
- package/dist/utils/quote.d.ts +1 -0
- package/dist/utils/quote.d.ts.map +1 -1
- package/dist/utils/settings.d.ts +3 -2
- package/dist/utils/settings.d.ts.map +1 -1
- package/dist/utils/swap.d.ts.map +1 -1
- package/dist/widget-embedded.build.json +1 -1
- package/package.json +4 -4
- package/src/components/AppRoutes.tsx +30 -0
- package/src/components/BlockchainList/BlockchainList.styles.ts +3 -1
- package/src/components/BlockchainList/BlockchainList.tsx +26 -17
- package/src/components/BlockchainList/BlockchainList.types.ts +1 -0
- package/src/components/BlockchainSelectorButton/BlockchainSelectorButton.styles.ts +49 -0
- package/src/components/BlockchainSelectorButton/BlockchainSelectorButton.tsx +47 -0
- package/src/components/BlockchainSelectorButton/BlockchainSelectorButton.types.ts +11 -0
- package/src/components/BlockchainSelectorButton/index.ts +1 -0
- package/src/components/CustomDestination/CustomDestination.tsx +5 -3
- package/src/components/CustomTokenModal/CustomTokenModal.helpers.ts +19 -0
- package/src/components/CustomTokenModal/CustomTokenModal.styles.ts +57 -0
- package/src/components/CustomTokenModal/CustomTokenModal.tsx +92 -0
- package/src/components/CustomTokenModal/CustomTokenModal.types.ts +9 -0
- package/src/components/CustomTokenModal/index.ts +1 -0
- package/src/components/TokenList/TokenList.styles.ts +1 -0
- package/src/components/TokenList/TokenList.tsx +76 -51
- package/src/components/TokenList/TokenList.types.ts +5 -2
- package/src/constants/customTokens.ts +6 -0
- package/src/constants/navigationRoutes.ts +2 -0
- package/src/constants/searchParams.ts +3 -0
- package/src/containers/Settings/Lists.tsx +25 -1
- package/src/hooks/useFetchCustomToken.ts +114 -0
- package/src/hooks/useSwapInput.ts +8 -3
- package/src/hooks/useSyncUrlAndStore/useSyncUrlAndStore.ts +6 -1
- package/src/hooks/useTheme.ts +5 -1
- package/src/pages/AddCustomTokenPage.tsx +210 -0
- package/src/pages/CustomTokensPage.tsx +184 -0
- package/src/pages/HistoryPage.tsx +2 -2
- package/src/pages/LiquiditySourcePage.tsx +2 -2
- package/src/pages/SelectBlockchainPage.tsx +15 -8
- package/src/pages/SelectSwapItemsPage.tsx +1 -1
- package/src/store/app.ts +1 -0
- package/src/store/quote.ts +12 -2
- package/src/store/slices/data.ts +61 -8
- package/src/store/slices/settings.ts +35 -2
- package/src/store/utils/data.ts +26 -1
- package/src/store/wallets.ts +1 -1
- package/src/types/config.ts +4 -1
- package/src/utils/meta.ts +12 -1
- package/src/utils/quote.ts +16 -3
- package/src/utils/settings.ts +13 -1
- package/src/utils/swap.ts +7 -7
- package/dist/components/ConfirmWalletsModal/ConfirmWallets.helpers.d.ts +0 -3
- package/dist/components/ConfirmWalletsModal/ConfirmWallets.helpers.d.ts.map +0 -1
- package/src/components/ConfirmWalletsModal/ConfirmWallets.helpers.ts +0 -10
|
@@ -4,6 +4,8 @@ export const navigationRoutes = {
|
|
|
4
4
|
toSwap: 'to-swap',
|
|
5
5
|
blockchains: 'blockchains',
|
|
6
6
|
settings: 'settings',
|
|
7
|
+
customTokens: 'custom-tokens',
|
|
8
|
+
addCustomTokens: 'add-custom-tokens',
|
|
7
9
|
liquiditySources: 'liquidity-sources',
|
|
8
10
|
bridges: 'bridges',
|
|
9
11
|
exchanges: 'exchanges',
|
|
@@ -5,6 +5,9 @@ export enum SearchParams {
|
|
|
5
5
|
TO_TOKEN = 'toToken',
|
|
6
6
|
FROM_AMOUNT = 'fromAmount',
|
|
7
7
|
AUTO_CONNECT = 'autoConnect',
|
|
8
|
+
|
|
9
|
+
// This is for custom tokens
|
|
10
|
+
BLOCKCHAIN = 'blockchain',
|
|
8
11
|
/*
|
|
9
12
|
* dApps can transmit liquidity sources as a search parameter,
|
|
10
13
|
* and these take precedence over widget configurations
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
styled,
|
|
21
21
|
Switch,
|
|
22
22
|
Tabs,
|
|
23
|
+
TargetIcon,
|
|
23
24
|
Tooltip,
|
|
24
25
|
Typography,
|
|
25
26
|
} from '@rango-dev/ui';
|
|
@@ -97,9 +98,11 @@ export function SettingsLists() {
|
|
|
97
98
|
const {
|
|
98
99
|
config: { features },
|
|
99
100
|
} = useAppStore();
|
|
101
|
+
const customTokens = useAppStore().customTokens();
|
|
100
102
|
const isThemeHidden = isFeatureHidden('theme', features);
|
|
101
103
|
const isLiquidityHidden = isFeatureHidden('liquiditySource', features);
|
|
102
104
|
const isLanguageHidden = isFeatureHidden('language', features);
|
|
105
|
+
const isCustomTokensHidden = isFeatureHidden('customTokens', features);
|
|
103
106
|
|
|
104
107
|
const infiniteApprove = useAppStore().infiniteApprove;
|
|
105
108
|
const toggleInfiniteApprove = useAppStore().toggleInfiniteApprove;
|
|
@@ -185,6 +188,25 @@ export function SettingsLists() {
|
|
|
185
188
|
onClick: () => navigate(navigationRoutes.exchanges),
|
|
186
189
|
};
|
|
187
190
|
|
|
191
|
+
const customTokensItem = {
|
|
192
|
+
id: 'custom-tokens-item',
|
|
193
|
+
title: (
|
|
194
|
+
<Typography variant="title" size="xmedium">
|
|
195
|
+
{i18n.t('Custom Tokens')}
|
|
196
|
+
</Typography>
|
|
197
|
+
),
|
|
198
|
+
end: (
|
|
199
|
+
<>
|
|
200
|
+
<Typography variant="body" size="medium">
|
|
201
|
+
{`${customTokens.length}`}
|
|
202
|
+
</Typography>
|
|
203
|
+
<Divider direction="horizontal" size={8} />
|
|
204
|
+
<ChevronRightIcon color="black" />
|
|
205
|
+
</>
|
|
206
|
+
),
|
|
207
|
+
start: <TargetIcon color="gray" size={16} />,
|
|
208
|
+
onClick: () => navigate(navigationRoutes.customTokens),
|
|
209
|
+
};
|
|
188
210
|
const languageItem = {
|
|
189
211
|
id: 'language-item',
|
|
190
212
|
title: (
|
|
@@ -261,7 +283,9 @@ export function SettingsLists() {
|
|
|
261
283
|
const settingItems: ListPropTypes['items'] = isLiquidityHidden
|
|
262
284
|
? []
|
|
263
285
|
: [bridgeItem, exchangeItem];
|
|
264
|
-
|
|
286
|
+
if (!isCustomTokensHidden) {
|
|
287
|
+
settingItems.push(customTokensItem);
|
|
288
|
+
}
|
|
265
289
|
if (!isLanguageHidden) {
|
|
266
290
|
settingItems.push(languageItem);
|
|
267
291
|
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import type { Token } from 'rango-sdk';
|
|
2
|
+
|
|
3
|
+
import { i18n } from '@lingui/core';
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
|
|
6
|
+
import { useAppStore } from '../store/AppStore';
|
|
7
|
+
import { getConfig } from '../utils/configs';
|
|
8
|
+
|
|
9
|
+
type ErrorType = {
|
|
10
|
+
title: string;
|
|
11
|
+
message: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
interface UseFetchCustomToken {
|
|
15
|
+
fetchCustomToken: ({
|
|
16
|
+
blockchain,
|
|
17
|
+
tokenAddress,
|
|
18
|
+
}: {
|
|
19
|
+
blockchain: string;
|
|
20
|
+
tokenAddress: string;
|
|
21
|
+
}) => Promise<Token>;
|
|
22
|
+
loading: boolean;
|
|
23
|
+
error?: ErrorType;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function useFetchCustomToken(): UseFetchCustomToken {
|
|
27
|
+
const [loading, setLoading] = useState(false);
|
|
28
|
+
const [error, setError] = useState<undefined | ErrorType>(undefined);
|
|
29
|
+
const { findToken } = useAppStore();
|
|
30
|
+
const customTokens = useAppStore().customTokens();
|
|
31
|
+
|
|
32
|
+
function produceErrorMessage(
|
|
33
|
+
type: 'duplicated' | 'not-found' | 'token-exist',
|
|
34
|
+
blockchain?: string
|
|
35
|
+
) {
|
|
36
|
+
switch (type) {
|
|
37
|
+
case 'duplicated':
|
|
38
|
+
return {
|
|
39
|
+
title: i18n.t('Duplicate Token'),
|
|
40
|
+
message: i18n.t(
|
|
41
|
+
'The address you entered is duplicate, please enter a new address.'
|
|
42
|
+
),
|
|
43
|
+
};
|
|
44
|
+
case 'token-exist':
|
|
45
|
+
return {
|
|
46
|
+
title: i18n.t('Token Already Exists'),
|
|
47
|
+
message: i18n.t(
|
|
48
|
+
`There's no need to add this token again because it already exists and is supported by us.`
|
|
49
|
+
),
|
|
50
|
+
};
|
|
51
|
+
case 'not-found':
|
|
52
|
+
return {
|
|
53
|
+
title: i18n.t('Token Not Found'),
|
|
54
|
+
message: i18n.t(
|
|
55
|
+
`Sorry, no token was found on ${blockchain} blockchain with the provided address. please make sure you have entered the right token address.`
|
|
56
|
+
),
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const fetchCustomToken: UseFetchCustomToken['fetchCustomToken'] = async ({
|
|
62
|
+
blockchain,
|
|
63
|
+
tokenAddress,
|
|
64
|
+
}) => {
|
|
65
|
+
setLoading(true);
|
|
66
|
+
try {
|
|
67
|
+
// Check for duplicate token in customTokens
|
|
68
|
+
const isDuplicate = customTokens.some(
|
|
69
|
+
(token) => token.address?.toLowerCase() === tokenAddress.toLowerCase()
|
|
70
|
+
);
|
|
71
|
+
if (isDuplicate) {
|
|
72
|
+
const errorMessage = produceErrorMessage('duplicated');
|
|
73
|
+
setError(errorMessage);
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const res = await fetch(
|
|
78
|
+
`${getConfig('BASE_URL')}/meta/token?apiKey=${getConfig(
|
|
79
|
+
'API_KEY'
|
|
80
|
+
)}&blockchain=${blockchain}&address=${tokenAddress}`
|
|
81
|
+
);
|
|
82
|
+
const contentType = res.headers.get('content-type');
|
|
83
|
+
const response =
|
|
84
|
+
contentType &&
|
|
85
|
+
contentType.includes('application/json') &&
|
|
86
|
+
(await res.json());
|
|
87
|
+
if (!response || response.error) {
|
|
88
|
+
const errorMessage = produceErrorMessage('not-found', blockchain);
|
|
89
|
+
setError(errorMessage);
|
|
90
|
+
return undefined;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Check if token is already in the system
|
|
94
|
+
const isTokenFound = findToken({
|
|
95
|
+
blockchain: response.blockchain,
|
|
96
|
+
address: response.address,
|
|
97
|
+
symbol: response.symbol,
|
|
98
|
+
});
|
|
99
|
+
if (isTokenFound) {
|
|
100
|
+
const errorMessage = produceErrorMessage('token-exist');
|
|
101
|
+
setError(errorMessage);
|
|
102
|
+
return undefined;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return response;
|
|
106
|
+
} catch (error: any) {
|
|
107
|
+
setError(undefined);
|
|
108
|
+
throw new Error(error.message);
|
|
109
|
+
} finally {
|
|
110
|
+
setLoading(false);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
return { fetchCustomToken, loading, error };
|
|
114
|
+
}
|
|
@@ -11,6 +11,8 @@ import { isPositiveNumber } from '../utils/numbers';
|
|
|
11
11
|
import {
|
|
12
12
|
generateQuoteWarnings,
|
|
13
13
|
getDefaultQuote,
|
|
14
|
+
getQuoteFromTokenUsdPrice,
|
|
15
|
+
getQuoteToTokenUsdPrice,
|
|
14
16
|
sortQuotesBy,
|
|
15
17
|
} from '../utils/quote';
|
|
16
18
|
import { isFeatureEnabled } from '../utils/settings';
|
|
@@ -146,12 +148,15 @@ export function useSwapInput({
|
|
|
146
148
|
requestId: quote?.requestId || '',
|
|
147
149
|
swaps: quote?.swaps,
|
|
148
150
|
});
|
|
149
|
-
|
|
151
|
+
const outputUsdValue =
|
|
152
|
+
getQuoteToTokenUsdPrice(quote) || toToken?.usdPrice;
|
|
153
|
+
const inputUsdValue =
|
|
154
|
+
getQuoteFromTokenUsdPrice(quote) || fromToken?.usdPrice;
|
|
150
155
|
const quoteWarning =
|
|
151
156
|
quote &&
|
|
152
157
|
generateQuoteWarnings(quote, {
|
|
153
|
-
fromToken,
|
|
154
|
-
toToken,
|
|
158
|
+
fromToken: { ...fromToken, usdPrice: inputUsdValue },
|
|
159
|
+
toToken: { ...toToken, usdPrice: outputUsdValue },
|
|
155
160
|
userSlippage,
|
|
156
161
|
findToken,
|
|
157
162
|
});
|
|
@@ -54,6 +54,8 @@ export function useSyncUrlAndStore() {
|
|
|
54
54
|
const clientUrl = searchParams.get(SearchParams.CLIENT_URL);
|
|
55
55
|
const liquiditySources = searchParams.get(SearchParams.LIQUIDITY_SOURCES);
|
|
56
56
|
|
|
57
|
+
const blockchain = searchParams.get(SearchParams.BLOCKCHAIN);
|
|
58
|
+
|
|
57
59
|
return {
|
|
58
60
|
fromAmount,
|
|
59
61
|
fromBlockchain,
|
|
@@ -64,6 +66,7 @@ export function useSyncUrlAndStore() {
|
|
|
64
66
|
clientUrl,
|
|
65
67
|
liquiditySources,
|
|
66
68
|
utmQueryParams,
|
|
69
|
+
blockchain,
|
|
67
70
|
};
|
|
68
71
|
};
|
|
69
72
|
|
|
@@ -79,7 +82,8 @@ export function useSyncUrlAndStore() {
|
|
|
79
82
|
};
|
|
80
83
|
|
|
81
84
|
useEffect(() => {
|
|
82
|
-
const { autoConnect, clientUrl, utmQueryParams } =
|
|
85
|
+
const { autoConnect, clientUrl, utmQueryParams, blockchain } =
|
|
86
|
+
getUrlSearchParams();
|
|
83
87
|
if (isInRouterContext && fetchMetaStatus === 'success') {
|
|
84
88
|
updateUrlSearchParams({
|
|
85
89
|
[SearchParams.FROM_BLOCKCHAIN]: fromBlockchain?.name,
|
|
@@ -89,6 +93,7 @@ export function useSyncUrlAndStore() {
|
|
|
89
93
|
[SearchParams.FROM_AMOUNT]: inputAmount,
|
|
90
94
|
[SearchParams.AUTO_CONNECT]: autoConnect ?? undefined,
|
|
91
95
|
[SearchParams.CLIENT_URL]: clientUrl ?? undefined,
|
|
96
|
+
[SearchParams.BLOCKCHAIN]: blockchain ?? undefined,
|
|
92
97
|
[SearchParams.LIQUIDITY_SOURCES]: campaignMode
|
|
93
98
|
? liquiditySourcesParamsRef.current
|
|
94
99
|
: undefined,
|
package/src/hooks/useTheme.ts
CHANGED
|
@@ -93,8 +93,12 @@ export function useTheme(props: WidgetTheme) {
|
|
|
93
93
|
if (theme === 'auto') {
|
|
94
94
|
return OSTheme === 'dark' ? darkClassNames : lightClassNames;
|
|
95
95
|
}
|
|
96
|
+
|
|
96
97
|
return theme === 'dark' ? darkClassNames : lightClassNames;
|
|
97
98
|
};
|
|
98
99
|
|
|
99
|
-
return {
|
|
100
|
+
return {
|
|
101
|
+
activeTheme: getActiveTheme,
|
|
102
|
+
mode: theme === 'auto' ? OSTheme : theme,
|
|
103
|
+
};
|
|
100
104
|
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
import { i18n } from '@lingui/core';
|
|
2
|
+
import {
|
|
3
|
+
Alert,
|
|
4
|
+
Button,
|
|
5
|
+
darkTheme,
|
|
6
|
+
Divider,
|
|
7
|
+
DoneIcon,
|
|
8
|
+
MessageBox,
|
|
9
|
+
styled,
|
|
10
|
+
TextField,
|
|
11
|
+
Typography,
|
|
12
|
+
} from '@rango-dev/ui';
|
|
13
|
+
import { type Token } from 'rango-sdk';
|
|
14
|
+
import React, { useEffect, useState } from 'react';
|
|
15
|
+
import { useNavigate, useSearchParams } from 'react-router-dom';
|
|
16
|
+
|
|
17
|
+
import { BlockchainSelectorButton } from '../components/BlockchainSelectorButton';
|
|
18
|
+
import { WatermarkedModal } from '../components/common/WatermarkedModal';
|
|
19
|
+
import { CustomTokenModal } from '../components/CustomTokenModal';
|
|
20
|
+
import { Layout, PageContainer } from '../components/Layout';
|
|
21
|
+
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
22
|
+
import { SearchParams } from '../constants/searchParams';
|
|
23
|
+
import { useFetchCustomToken } from '../hooks/useFetchCustomToken';
|
|
24
|
+
import { useNavigateBack } from '../hooks/useNavigateBack';
|
|
25
|
+
import { useAppStore } from '../store/AppStore';
|
|
26
|
+
import { getContainer } from '../utils/common';
|
|
27
|
+
import { findBlockchain, isValidTokenAddress } from '../utils/meta';
|
|
28
|
+
|
|
29
|
+
const Content = styled('div', {
|
|
30
|
+
display: 'flex',
|
|
31
|
+
justifyContent: 'space-between',
|
|
32
|
+
flexDirection: 'column',
|
|
33
|
+
flex: 1,
|
|
34
|
+
'& ._text-field': {
|
|
35
|
+
padding: '$4 $10',
|
|
36
|
+
backgroundColor: '$neutral300',
|
|
37
|
+
[`.${darkTheme} &`]: {
|
|
38
|
+
backgroundColor: '$neutral400',
|
|
39
|
+
},
|
|
40
|
+
borderRadius: '$sm',
|
|
41
|
+
height: '$40',
|
|
42
|
+
},
|
|
43
|
+
});
|
|
44
|
+
const CUSTOM_TOKEN_REFRESH_DELAY = 1000;
|
|
45
|
+
|
|
46
|
+
export function AddCustomTokenPage() {
|
|
47
|
+
const navigate = useNavigate();
|
|
48
|
+
const [searchParams] = useSearchParams();
|
|
49
|
+
const navigateBack = useNavigateBack();
|
|
50
|
+
const { setCustomToken } = useAppStore();
|
|
51
|
+
const blockchains = useAppStore().blockchains();
|
|
52
|
+
|
|
53
|
+
const blockchainName = searchParams.get(SearchParams.BLOCKCHAIN) || '';
|
|
54
|
+
const blockchain = findBlockchain(blockchainName, blockchains);
|
|
55
|
+
const [address, setAddress] = useState('');
|
|
56
|
+
const [isOpenErrorModal, setIsOpenErrorModal] = useState<boolean>(false);
|
|
57
|
+
const [token, setToken] = useState<Token>();
|
|
58
|
+
const { fetchCustomToken, loading, error } = useFetchCustomToken();
|
|
59
|
+
const [networkError, setNetworkError] = useState('');
|
|
60
|
+
const isValidAddress =
|
|
61
|
+
!!blockchain && isValidTokenAddress(blockchain, address);
|
|
62
|
+
const isImportDisabled = !blockchain || !address || !isValidAddress;
|
|
63
|
+
|
|
64
|
+
const getCustomToken = async () => {
|
|
65
|
+
if (blockchain) {
|
|
66
|
+
try {
|
|
67
|
+
const res = await fetchCustomToken({
|
|
68
|
+
blockchain: blockchainName,
|
|
69
|
+
tokenAddress: address,
|
|
70
|
+
});
|
|
71
|
+
setNetworkError('');
|
|
72
|
+
if (!!res) {
|
|
73
|
+
setToken(res);
|
|
74
|
+
}
|
|
75
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
76
|
+
} catch (error: any) {
|
|
77
|
+
if (error.message === 'Failed to fetch') {
|
|
78
|
+
setNetworkError(i18n.t('Network Error'));
|
|
79
|
+
setIsOpenErrorModal(true);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const closeErrorModal = () => {
|
|
86
|
+
if (!!error) {
|
|
87
|
+
setAddress('');
|
|
88
|
+
}
|
|
89
|
+
setIsOpenErrorModal(false);
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
const handleErrorModalButtonClick = async () => {
|
|
93
|
+
if (!!networkError) {
|
|
94
|
+
setTimeout(async () => {
|
|
95
|
+
await getCustomToken();
|
|
96
|
+
}, CUSTOM_TOKEN_REFRESH_DELAY);
|
|
97
|
+
}
|
|
98
|
+
closeErrorModal();
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
if (!!error) {
|
|
103
|
+
setIsOpenErrorModal(true);
|
|
104
|
+
}
|
|
105
|
+
}, [error]);
|
|
106
|
+
return (
|
|
107
|
+
<Layout
|
|
108
|
+
header={{
|
|
109
|
+
title: i18n.t('Add Custom Token'),
|
|
110
|
+
}}>
|
|
111
|
+
<PageContainer>
|
|
112
|
+
<Content>
|
|
113
|
+
<div>
|
|
114
|
+
<BlockchainSelectorButton
|
|
115
|
+
onClick={() =>
|
|
116
|
+
navigate(navigationRoutes.blockchains, { replace: true })
|
|
117
|
+
}
|
|
118
|
+
hasLogo={!!blockchain?.logo}
|
|
119
|
+
value={
|
|
120
|
+
!!blockchain
|
|
121
|
+
? {
|
|
122
|
+
name: blockchain.displayName,
|
|
123
|
+
logo: blockchain.logo,
|
|
124
|
+
}
|
|
125
|
+
: undefined
|
|
126
|
+
}
|
|
127
|
+
title={i18n.t('Select chain')}
|
|
128
|
+
placeholder={i18n.t('Select chain')}
|
|
129
|
+
/>
|
|
130
|
+
<Divider size={'24'} />
|
|
131
|
+
<Typography size="large" variant="label">
|
|
132
|
+
{i18n.t('Enter Address')}
|
|
133
|
+
</Typography>
|
|
134
|
+
<Divider size={10} />
|
|
135
|
+
<TextField
|
|
136
|
+
fullWidth
|
|
137
|
+
disabled={!blockchain}
|
|
138
|
+
variant="contained"
|
|
139
|
+
placeholder={i18n.t('Enter token address')}
|
|
140
|
+
size="large"
|
|
141
|
+
value={address}
|
|
142
|
+
suffix={
|
|
143
|
+
!!address &&
|
|
144
|
+
isValidAddress && <DoneIcon color="success" size={12} />
|
|
145
|
+
}
|
|
146
|
+
onChange={(e) => setAddress(e.target.value)}
|
|
147
|
+
/>
|
|
148
|
+
{!isValidAddress && !!address && (
|
|
149
|
+
<>
|
|
150
|
+
<Divider size={4} />
|
|
151
|
+
<Alert type="error" variant="alarm" title="Invalid Address" />
|
|
152
|
+
</>
|
|
153
|
+
)}
|
|
154
|
+
</div>
|
|
155
|
+
|
|
156
|
+
<Button
|
|
157
|
+
disabled={isImportDisabled}
|
|
158
|
+
type="primary"
|
|
159
|
+
variant="contained"
|
|
160
|
+
loading={loading}
|
|
161
|
+
size="large"
|
|
162
|
+
onClick={getCustomToken}>
|
|
163
|
+
{i18n.t('Import')}
|
|
164
|
+
</Button>
|
|
165
|
+
</Content>
|
|
166
|
+
<WatermarkedModal
|
|
167
|
+
open={isOpenErrorModal}
|
|
168
|
+
dismissible
|
|
169
|
+
onClose={closeErrorModal}
|
|
170
|
+
container={getContainer()}>
|
|
171
|
+
<MessageBox
|
|
172
|
+
title={error?.title || networkError}
|
|
173
|
+
type="error"
|
|
174
|
+
description={
|
|
175
|
+
error?.message || i18n.t('Failed Network, Please retry.')
|
|
176
|
+
}>
|
|
177
|
+
<Divider size={40} />
|
|
178
|
+
<Divider size={10} />
|
|
179
|
+
|
|
180
|
+
<Button
|
|
181
|
+
variant="contained"
|
|
182
|
+
size="large"
|
|
183
|
+
type="primary"
|
|
184
|
+
fullWidth
|
|
185
|
+
onClick={handleErrorModalButtonClick}>
|
|
186
|
+
{networkError
|
|
187
|
+
? i18n.t('Retry')
|
|
188
|
+
: i18n.t('Add another custom token')}
|
|
189
|
+
</Button>
|
|
190
|
+
</MessageBox>
|
|
191
|
+
</WatermarkedModal>
|
|
192
|
+
{blockchain && token && (
|
|
193
|
+
<CustomTokenModal
|
|
194
|
+
blockchain={blockchain}
|
|
195
|
+
token={token}
|
|
196
|
+
onSubmitClick={() => {
|
|
197
|
+
if (token) {
|
|
198
|
+
setCustomToken(token);
|
|
199
|
+
setToken(undefined);
|
|
200
|
+
navigateBack();
|
|
201
|
+
}
|
|
202
|
+
}}
|
|
203
|
+
onClose={() => setToken(undefined)}
|
|
204
|
+
open={!!blockchain && !!token}
|
|
205
|
+
/>
|
|
206
|
+
)}
|
|
207
|
+
</PageContainer>
|
|
208
|
+
</Layout>
|
|
209
|
+
);
|
|
210
|
+
}
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import type { Token } from 'rango-sdk';
|
|
2
|
+
|
|
3
|
+
import { i18n } from '@lingui/core';
|
|
4
|
+
import {
|
|
5
|
+
Button,
|
|
6
|
+
CustomTokensZeroStateDarkIcon,
|
|
7
|
+
CustomTokensZeroStateIcon,
|
|
8
|
+
DeleteIcon,
|
|
9
|
+
Divider,
|
|
10
|
+
IconButton,
|
|
11
|
+
MessageBox,
|
|
12
|
+
NotFound,
|
|
13
|
+
styled,
|
|
14
|
+
} from '@rango-dev/ui';
|
|
15
|
+
import React, { useState } from 'react';
|
|
16
|
+
import { useNavigate } from 'react-router-dom';
|
|
17
|
+
|
|
18
|
+
import { WatermarkedModal } from '../components/common/WatermarkedModal';
|
|
19
|
+
import { Layout, PageContainer } from '../components/Layout';
|
|
20
|
+
import { SearchInput } from '../components/SearchInput';
|
|
21
|
+
import { TokenList } from '../components/TokenList';
|
|
22
|
+
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
23
|
+
import { useTheme } from '../hooks/useTheme';
|
|
24
|
+
import { useAppStore } from '../store/AppStore';
|
|
25
|
+
import { useQuoteStore } from '../store/quote';
|
|
26
|
+
import { containsText, getContainer } from '../utils/common';
|
|
27
|
+
import { createTokenHash } from '../utils/meta';
|
|
28
|
+
|
|
29
|
+
const Content = styled('div', {
|
|
30
|
+
display: 'flex',
|
|
31
|
+
justifyContent: 'space-between',
|
|
32
|
+
flexDirection: 'column',
|
|
33
|
+
flex: 1,
|
|
34
|
+
});
|
|
35
|
+
const NotFoundContent = styled('div', {
|
|
36
|
+
display: 'flex',
|
|
37
|
+
flexDirection: 'column',
|
|
38
|
+
alignItems: 'center',
|
|
39
|
+
justifyContent: 'center',
|
|
40
|
+
flex: '0.75',
|
|
41
|
+
});
|
|
42
|
+
const DeleteIconButton = styled(IconButton, {
|
|
43
|
+
'&:hover': {
|
|
44
|
+
'& svg': {
|
|
45
|
+
color: '$secondary550',
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
export function CustomTokensPage() {
|
|
50
|
+
const [searchedFor, setSearchedFor] = useState<string>('');
|
|
51
|
+
const { deleteCustomToken } = useAppStore();
|
|
52
|
+
const customTokens = useAppStore().customTokens();
|
|
53
|
+
const { fromToken, toToken, setFromToken, setToToken } = useQuoteStore();
|
|
54
|
+
const { mode } = useTheme({});
|
|
55
|
+
const navigate = useNavigate();
|
|
56
|
+
const [isDeleteModalOpen, setIsDeleteModalOpen] = useState<boolean>(false);
|
|
57
|
+
const [selectedToken, setSelectedToken] = useState<Token>();
|
|
58
|
+
const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
59
|
+
const value = event.target.value;
|
|
60
|
+
setSearchedFor(value);
|
|
61
|
+
};
|
|
62
|
+
const isDarkTheme = mode === 'dark';
|
|
63
|
+
|
|
64
|
+
const customTokensResults = customTokens.filter(
|
|
65
|
+
(token) =>
|
|
66
|
+
containsText(token.symbol, searchedFor) ||
|
|
67
|
+
containsText(token.address || '', searchedFor) ||
|
|
68
|
+
containsText(token.name || '', searchedFor)
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
const handleDeleteCustomToken = () => {
|
|
72
|
+
if (selectedToken) {
|
|
73
|
+
const toTokenHash = toToken ? createTokenHash(toToken) : null;
|
|
74
|
+
const fromTokenHash = fromToken ? createTokenHash(fromToken) : null;
|
|
75
|
+
const selectedTokenHash = createTokenHash(selectedToken);
|
|
76
|
+
|
|
77
|
+
if (toTokenHash === selectedTokenHash) {
|
|
78
|
+
setToToken({ token: null });
|
|
79
|
+
} else if (fromTokenHash === selectedTokenHash) {
|
|
80
|
+
setFromToken({ token: null });
|
|
81
|
+
}
|
|
82
|
+
deleteCustomToken(selectedToken);
|
|
83
|
+
}
|
|
84
|
+
setIsDeleteModalOpen(false);
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
return (
|
|
88
|
+
<Layout
|
|
89
|
+
header={{
|
|
90
|
+
title: i18n.t('Custom Tokens'),
|
|
91
|
+
}}>
|
|
92
|
+
<PageContainer>
|
|
93
|
+
<Content>
|
|
94
|
+
{!!customTokens.length ? (
|
|
95
|
+
<>
|
|
96
|
+
<SearchInput
|
|
97
|
+
value={searchedFor}
|
|
98
|
+
setValue={setSearchedFor}
|
|
99
|
+
fullWidth
|
|
100
|
+
color="light"
|
|
101
|
+
variant="contained"
|
|
102
|
+
placeholder={i18n.t('Search Token')}
|
|
103
|
+
onChange={handleSearch}
|
|
104
|
+
/>
|
|
105
|
+
<Divider size={16} />
|
|
106
|
+
<TokenList
|
|
107
|
+
list={customTokensResults}
|
|
108
|
+
type="custom-token"
|
|
109
|
+
searchedFor={searchedFor}
|
|
110
|
+
showTitle={false}
|
|
111
|
+
action={(token) => (
|
|
112
|
+
<DeleteIconButton
|
|
113
|
+
variant="ghost"
|
|
114
|
+
onClick={() => {
|
|
115
|
+
setIsDeleteModalOpen(true);
|
|
116
|
+
setSelectedToken(token);
|
|
117
|
+
}}>
|
|
118
|
+
<DeleteIcon size={12} color="gray" />
|
|
119
|
+
</DeleteIconButton>
|
|
120
|
+
)}
|
|
121
|
+
/>
|
|
122
|
+
</>
|
|
123
|
+
) : (
|
|
124
|
+
<NotFoundContent>
|
|
125
|
+
<NotFound
|
|
126
|
+
icon={
|
|
127
|
+
isDarkTheme ? (
|
|
128
|
+
<CustomTokensZeroStateDarkIcon size={200} />
|
|
129
|
+
) : (
|
|
130
|
+
<CustomTokensZeroStateIcon size={200} />
|
|
131
|
+
)
|
|
132
|
+
}
|
|
133
|
+
title={i18n.t('No custom tokens')}
|
|
134
|
+
description={i18n.t(
|
|
135
|
+
'press the button to add your custom token'
|
|
136
|
+
)}
|
|
137
|
+
/>
|
|
138
|
+
</NotFoundContent>
|
|
139
|
+
)}
|
|
140
|
+
<Divider size={20} />
|
|
141
|
+
|
|
142
|
+
<Button
|
|
143
|
+
type="primary"
|
|
144
|
+
variant="contained"
|
|
145
|
+
size="large"
|
|
146
|
+
onClick={() => navigate(navigationRoutes.addCustomTokens)}>
|
|
147
|
+
{i18n.t('Add Custom Token')}
|
|
148
|
+
</Button>
|
|
149
|
+
</Content>
|
|
150
|
+
<WatermarkedModal
|
|
151
|
+
open={isDeleteModalOpen}
|
|
152
|
+
dismissible
|
|
153
|
+
onClose={() => setIsDeleteModalOpen(false)}
|
|
154
|
+
container={getContainer()}>
|
|
155
|
+
<MessageBox
|
|
156
|
+
title={i18n.t('Delete Custom Token')}
|
|
157
|
+
type="error"
|
|
158
|
+
description={i18n.t('Are you sure you want to Delete this Token?')}>
|
|
159
|
+
<Divider size={40} />
|
|
160
|
+
<Divider size={10} />
|
|
161
|
+
|
|
162
|
+
<Button
|
|
163
|
+
fullWidth
|
|
164
|
+
variant="contained"
|
|
165
|
+
type="primary"
|
|
166
|
+
size="large"
|
|
167
|
+
onClick={handleDeleteCustomToken}>
|
|
168
|
+
{i18n.t('Yes, Delete it')}
|
|
169
|
+
</Button>
|
|
170
|
+
<Divider size={12} />
|
|
171
|
+
<Button
|
|
172
|
+
fullWidth
|
|
173
|
+
variant="outlined"
|
|
174
|
+
type="primary"
|
|
175
|
+
size="large"
|
|
176
|
+
onClick={() => setIsDeleteModalOpen(false)}>
|
|
177
|
+
{i18n.t('No, Continue')}
|
|
178
|
+
</Button>
|
|
179
|
+
</MessageBox>
|
|
180
|
+
</WatermarkedModal>
|
|
181
|
+
</PageContainer>
|
|
182
|
+
</Layout>
|
|
183
|
+
);
|
|
184
|
+
}
|
|
@@ -87,7 +87,7 @@ export function HistoryPage() {
|
|
|
87
87
|
const loading = !state.loadedFromPersistor;
|
|
88
88
|
const [filterBy, setFilterBy] = useState('');
|
|
89
89
|
const [openClearModal, setOpenClearModal] = useState(false);
|
|
90
|
-
const
|
|
90
|
+
const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
91
91
|
const value = event.target.value;
|
|
92
92
|
setSearchedFor(value);
|
|
93
93
|
};
|
|
@@ -159,7 +159,7 @@ export function HistoryPage() {
|
|
|
159
159
|
variant="contained"
|
|
160
160
|
placeholder={i18n.t('Search Transaction')}
|
|
161
161
|
autoFocus
|
|
162
|
-
onChange={
|
|
162
|
+
onChange={handleSearch}
|
|
163
163
|
style={{ height: 36 }}
|
|
164
164
|
value={searchedFor}
|
|
165
165
|
/>
|