@rango-dev/widget-embedded 0.40.2-next.8 → 0.41.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/CustomTokenModal/CustomTokenModal.constants.d.ts +2 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.constants.d.ts.map +1 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.d.ts.map +1 -1
- package/dist/components/CustomTokenModal/CustomTokenModal.types.d.ts +1 -0
- package/dist/components/CustomTokenModal/CustomTokenModal.types.d.ts.map +1 -1
- package/dist/components/ImportCustomToken/ImportCustomToken.d.ts +4 -0
- package/dist/components/ImportCustomToken/ImportCustomToken.d.ts.map +1 -0
- package/dist/components/ImportCustomToken/ImportCustomToken.types.d.ts +15 -0
- package/dist/components/ImportCustomToken/ImportCustomToken.types.d.ts.map +1 -0
- package/dist/components/ImportCustomToken/index.d.ts +2 -0
- package/dist/components/ImportCustomToken/index.d.ts.map +1 -0
- package/dist/components/Quote/Quote.styles.d.ts +2 -2
- package/dist/components/SearchInput/SearchInput.d.ts.map +1 -1
- package/dist/components/SearchInput/SearchInput.types.d.ts +4 -2
- package/dist/components/SearchInput/SearchInput.types.d.ts.map +1 -1
- package/dist/components/SwapDetailsModal/SwapDetailsModal.types.d.ts +2 -2
- package/dist/components/SwapDetailsModal/SwapDetailsModal.types.d.ts.map +1 -1
- package/dist/components/TokenList/TokenList.d.ts.map +1 -1
- package/dist/components/TokenList/TokenList.styles.d.ts +323 -1
- package/dist/components/TokenList/TokenList.styles.d.ts.map +1 -1
- package/dist/components/TokenList/TokenList.types.d.ts +6 -1
- package/dist/components/TokenList/TokenList.types.d.ts.map +1 -1
- package/dist/constants/customTokens.d.ts +1 -0
- package/dist/constants/customTokens.d.ts.map +1 -1
- package/dist/containers/Inputs/Inputs.d.ts.map +1 -1
- package/dist/hooks/useFetchCustomToken.d.ts +8 -4
- package/dist/hooks/useFetchCustomToken.d.ts.map +1 -1
- package/dist/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.d.ts +2 -2
- package/dist/hooks/useSearchCustomTokens/index.d.ts +2 -0
- package/dist/hooks/useSearchCustomTokens/index.d.ts.map +1 -0
- package/dist/hooks/useSearchCustomTokens/types.d.ts +9 -0
- package/dist/hooks/useSearchCustomTokens/types.d.ts.map +1 -0
- package/dist/hooks/useSearchCustomTokens/useSearchCustomTokens.constants.d.ts +2 -0
- package/dist/hooks/useSearchCustomTokens/useSearchCustomTokens.constants.d.ts.map +1 -0
- package/dist/hooks/useSearchCustomTokens/useSearchCustomTokens.d.ts +3 -0
- package/dist/hooks/useSearchCustomTokens/useSearchCustomTokens.d.ts.map +1 -0
- package/dist/hooks/useSyncStoresWithConfig.d.ts.map +1 -1
- package/dist/hooks/useSyncUrlAndStore/useSyncUrlAndStore.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +4 -4
- package/dist/pages/AddCustomTokenPage.d.ts.map +1 -1
- package/dist/pages/CustomTokensPage.d.ts.map +1 -1
- package/dist/pages/SelectSwapItemPage/SelectSwapItemPage.constants.d.ts +3 -0
- package/dist/pages/SelectSwapItemPage/SelectSwapItemPage.constants.d.ts.map +1 -0
- package/dist/pages/SelectSwapItemPage/SelectSwapItemPage.helpers.d.ts +4 -0
- package/dist/pages/SelectSwapItemPage/SelectSwapItemPage.helpers.d.ts.map +1 -0
- package/dist/pages/SelectSwapItemPage/SelectSwapItemsPage.d.ts.map +1 -0
- package/dist/pages/SelectSwapItemPage/index.d.ts +2 -0
- package/dist/pages/SelectSwapItemPage/index.d.ts.map +1 -0
- package/dist/store/app.d.ts +1 -1
- package/dist/store/app.d.ts.map +1 -1
- package/dist/store/quote.d.ts +9 -6
- package/dist/store/quote.d.ts.map +1 -1
- package/dist/store/slices/settings.d.ts +4 -2
- package/dist/store/slices/settings.d.ts.map +1 -1
- package/dist/store/slices/wallets.d.ts +5 -1
- package/dist/store/slices/wallets.d.ts.map +1 -1
- package/dist/store/utils/wallets.d.ts +2 -1
- package/dist/store/utils/wallets.d.ts.map +1 -1
- package/dist/utils/quote.d.ts +1 -1
- package/dist/utils/quote.d.ts.map +1 -1
- package/dist/utils/settings.d.ts +1 -1
- package/dist/widget-embedded.build.json +1 -1
- package/package.json +12 -12
- package/src/components/AppRoutes.tsx +1 -1
- package/src/components/CustomTokenModal/CustomTokenModal.constants.ts +2 -0
- package/src/components/CustomTokenModal/CustomTokenModal.tsx +26 -5
- package/src/components/CustomTokenModal/CustomTokenModal.types.ts +1 -0
- package/src/components/ImportCustomToken/ImportCustomToken.tsx +121 -0
- package/src/components/ImportCustomToken/ImportCustomToken.types.ts +18 -0
- package/src/components/ImportCustomToken/index.ts +1 -0
- package/src/components/NotificationContent/NotificationContent.tsx +2 -2
- package/src/components/Quote/QuoteTrigger.tsx +5 -5
- package/src/components/QuoteSkeleton/QuoteSummarySkeleton.tsx +2 -2
- package/src/components/QuoteSkeleton/StepSkeleton.tsx +2 -2
- package/src/components/SearchInput/SearchInput.tsx +13 -10
- package/src/components/SearchInput/SearchInput.types.ts +4 -2
- package/src/components/SwapDetailsModal/SwapDetailsModal.types.ts +2 -2
- package/src/components/TokenList/TokenList.styles.ts +40 -0
- package/src/components/TokenList/TokenList.tsx +134 -22
- package/src/components/TokenList/TokenList.types.ts +5 -1
- package/src/constants/customTokens.ts +3 -0
- package/src/containers/Inputs/Inputs.tsx +6 -4
- package/src/hooks/useFetchCustomToken.ts +39 -16
- package/src/hooks/useSearchCustomTokens/index.ts +1 -0
- package/src/hooks/useSearchCustomTokens/types.ts +9 -0
- package/src/hooks/useSearchCustomTokens/useSearchCustomTokens.constants.ts +1 -0
- package/src/hooks/useSearchCustomTokens/useSearchCustomTokens.ts +81 -0
- package/src/hooks/useSyncStoresWithConfig.ts +2 -3
- package/src/hooks/useSyncUrlAndStore/useSyncUrlAndStore.ts +1 -3
- package/src/pages/AddCustomTokenPage.tsx +24 -94
- package/src/pages/CustomTokensPage.tsx +1 -0
- package/src/pages/SelectSwapItemPage/SelectSwapItemPage.constants.ts +2 -0
- package/src/pages/SelectSwapItemPage/SelectSwapItemPage.helpers.ts +51 -0
- package/src/pages/{SelectSwapItemsPage.tsx → SelectSwapItemPage/SelectSwapItemsPage.tsx} +54 -13
- package/src/pages/SelectSwapItemPage/index.ts +1 -0
- package/src/store/app.ts +12 -1
- package/src/store/quote.ts +6 -3
- package/src/store/slices/settings.ts +11 -4
- package/src/store/slices/wallets.ts +105 -2
- package/src/store/utils/wallets.ts +31 -2
- package/src/utils/quote.ts +1 -1
- package/dist/pages/SelectSwapItemsPage.d.ts.map +0 -1
- /package/dist/pages/{SelectSwapItemsPage.d.ts → SelectSwapItemPage/SelectSwapItemsPage.d.ts} +0 -0
|
@@ -5,25 +5,21 @@ import {
|
|
|
5
5
|
darkTheme,
|
|
6
6
|
Divider,
|
|
7
7
|
DoneIcon,
|
|
8
|
-
MessageBox,
|
|
9
8
|
styled,
|
|
10
9
|
TextField,
|
|
11
10
|
Typography,
|
|
12
11
|
} from '@rango-dev/ui';
|
|
13
|
-
import {
|
|
14
|
-
import React, { useEffect, useState } from 'react';
|
|
12
|
+
import React, { useState } from 'react';
|
|
15
13
|
import { useNavigate, useSearchParams } from 'react-router-dom';
|
|
16
14
|
|
|
17
15
|
import { BlockchainSelectorButton } from '../components/BlockchainSelectorButton';
|
|
18
|
-
import {
|
|
19
|
-
import { CustomTokenModal } from '../components/CustomTokenModal';
|
|
16
|
+
import { ImportCustomToken } from '../components/ImportCustomToken';
|
|
20
17
|
import { Layout, PageContainer } from '../components/Layout';
|
|
21
18
|
import { navigationRoutes } from '../constants/navigationRoutes';
|
|
22
19
|
import { SearchParams } from '../constants/searchParams';
|
|
23
20
|
import { useFetchCustomToken } from '../hooks/useFetchCustomToken';
|
|
24
21
|
import { useNavigateBack } from '../hooks/useNavigateBack';
|
|
25
22
|
import { useAppStore } from '../store/AppStore';
|
|
26
|
-
import { getContainer } from '../utils/common';
|
|
27
23
|
import { findBlockchain, isValidTokenAddress } from '../utils/meta';
|
|
28
24
|
|
|
29
25
|
const Content = styled('div', {
|
|
@@ -41,68 +37,31 @@ const Content = styled('div', {
|
|
|
41
37
|
height: '$40',
|
|
42
38
|
},
|
|
43
39
|
});
|
|
44
|
-
const CUSTOM_TOKEN_REFRESH_DELAY = 1000;
|
|
45
40
|
|
|
46
41
|
export function AddCustomTokenPage() {
|
|
47
42
|
const navigate = useNavigate();
|
|
48
43
|
const [searchParams] = useSearchParams();
|
|
49
44
|
const navigateBack = useNavigateBack();
|
|
50
|
-
const { setCustomToken } = useAppStore();
|
|
51
45
|
const blockchains = useAppStore().blockchains();
|
|
52
46
|
|
|
53
47
|
const blockchainName = searchParams.get(SearchParams.BLOCKCHAIN) || '';
|
|
54
48
|
const blockchain = findBlockchain(blockchainName, blockchains);
|
|
55
49
|
const [address, setAddress] = useState('');
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
const { fetchCustomToken, loading, error } = useFetchCustomToken();
|
|
59
|
-
const [networkError, setNetworkError] = useState('');
|
|
50
|
+
const { fetchCustomToken, token, loading, error, resetState } =
|
|
51
|
+
useFetchCustomToken();
|
|
60
52
|
const isValidAddress =
|
|
61
53
|
!!blockchain && isValidTokenAddress(blockchain, address);
|
|
62
54
|
const isImportDisabled = !blockchain || !address || !isValidAddress;
|
|
63
55
|
|
|
64
|
-
const getCustomToken =
|
|
56
|
+
const getCustomToken = () => {
|
|
65
57
|
if (blockchain) {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
}
|
|
58
|
+
void fetchCustomToken({
|
|
59
|
+
blockchain: blockchainName,
|
|
60
|
+
tokenAddress: address,
|
|
61
|
+
});
|
|
82
62
|
}
|
|
83
63
|
};
|
|
84
64
|
|
|
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
65
|
return (
|
|
107
66
|
<Layout
|
|
108
67
|
header={{
|
|
@@ -164,50 +123,21 @@ export function AddCustomTokenPage() {
|
|
|
164
123
|
{i18n.t('Import')}
|
|
165
124
|
</Button>
|
|
166
125
|
</Content>
|
|
167
|
-
<
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
type
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
id={`widget-add-custom-token-${
|
|
183
|
-
networkError ? 'retry' : 'add-another'
|
|
184
|
-
}-btn`}
|
|
185
|
-
variant="contained"
|
|
186
|
-
size="large"
|
|
187
|
-
type="primary"
|
|
188
|
-
fullWidth
|
|
189
|
-
onClick={handleErrorModalButtonClick}>
|
|
190
|
-
{networkError
|
|
191
|
-
? i18n.t('Retry')
|
|
192
|
-
: i18n.t('Add another custom token')}
|
|
193
|
-
</Button>
|
|
194
|
-
</MessageBox>
|
|
195
|
-
</WatermarkedModal>
|
|
196
|
-
{blockchain && token && (
|
|
197
|
-
<CustomTokenModal
|
|
198
|
-
blockchain={blockchain}
|
|
199
|
-
token={token}
|
|
200
|
-
onSubmitClick={() => {
|
|
201
|
-
if (token) {
|
|
202
|
-
setCustomToken(token);
|
|
203
|
-
setToken(undefined);
|
|
204
|
-
navigateBack();
|
|
205
|
-
}
|
|
206
|
-
}}
|
|
207
|
-
onClose={() => setToken(undefined)}
|
|
208
|
-
open={!!blockchain && !!token}
|
|
209
|
-
/>
|
|
210
|
-
)}
|
|
126
|
+
<ImportCustomToken
|
|
127
|
+
token={token}
|
|
128
|
+
blockchain={blockchain ?? undefined}
|
|
129
|
+
address={address}
|
|
130
|
+
error={error ?? undefined}
|
|
131
|
+
fetchCustomToken={fetchCustomToken}
|
|
132
|
+
onCloseErrorModal={() => {
|
|
133
|
+
if (error?.type !== 'network-error') {
|
|
134
|
+
setAddress('');
|
|
135
|
+
}
|
|
136
|
+
}}
|
|
137
|
+
onImport={navigateBack}
|
|
138
|
+
onExitErrorModal={resetState}
|
|
139
|
+
onExitImportModal={resetState}
|
|
140
|
+
/>
|
|
211
141
|
</PageContainer>
|
|
212
142
|
</Layout>
|
|
213
143
|
);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { TokenList } from '../../components/TokenList';
|
|
2
|
+
import type { Token } from 'rango-sdk';
|
|
3
|
+
import type { ComponentProps } from 'react';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
MAX_TOKENS_BEFORE_FETCH,
|
|
7
|
+
MIN_SEARCH_LENGTH,
|
|
8
|
+
} from './SelectSwapItemPage.constants';
|
|
9
|
+
|
|
10
|
+
export function shouldSearchForCustomTokens(
|
|
11
|
+
metaSearchResultTokens: Token[],
|
|
12
|
+
query: string,
|
|
13
|
+
blockchain?: string
|
|
14
|
+
) {
|
|
15
|
+
if (
|
|
16
|
+
blockchain &&
|
|
17
|
+
metaSearchResultTokens.length === 1 &&
|
|
18
|
+
metaSearchResultTokens[0].address === query
|
|
19
|
+
) {
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
return (
|
|
23
|
+
metaSearchResultTokens.length < MAX_TOKENS_BEFORE_FETCH &&
|
|
24
|
+
query.trim().length >= MIN_SEARCH_LENGTH
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function prepareTokensList(
|
|
29
|
+
tokens: Token[],
|
|
30
|
+
customTokens: Token[],
|
|
31
|
+
query: string,
|
|
32
|
+
loading: boolean,
|
|
33
|
+
blockchain?: string
|
|
34
|
+
) {
|
|
35
|
+
let modifiedList: ComponentProps<typeof TokenList>['list'] = [...tokens];
|
|
36
|
+
|
|
37
|
+
if (shouldSearchForCustomTokens(tokens, query, blockchain)) {
|
|
38
|
+
modifiedList = loading
|
|
39
|
+
? [...modifiedList, 'skeleton', 'skeleton', 'skeleton']
|
|
40
|
+
: [
|
|
41
|
+
...modifiedList,
|
|
42
|
+
...customTokens.map((customToken) => ({
|
|
43
|
+
...customToken,
|
|
44
|
+
customToken: true,
|
|
45
|
+
warning: true,
|
|
46
|
+
})),
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return modifiedList;
|
|
51
|
+
}
|
|
@@ -1,18 +1,24 @@
|
|
|
1
1
|
import type { BlockchainMeta, Token } from 'rango-sdk';
|
|
2
2
|
|
|
3
3
|
import { i18n } from '@lingui/core';
|
|
4
|
-
import { Divider } from '@rango-dev/ui';
|
|
5
|
-
import React, { useState } from 'react';
|
|
4
|
+
import { Divider, Spinner } from '@rango-dev/ui';
|
|
5
|
+
import React, { useEffect, useState } from 'react';
|
|
6
6
|
import { useNavigate } from 'react-router-dom';
|
|
7
7
|
|
|
8
|
-
import { BlockchainsSection } from '
|
|
9
|
-
import { Layout, PageContainer } from '
|
|
10
|
-
import { SearchInput } from '
|
|
11
|
-
import { TokenList } from '
|
|
12
|
-
import { navigationRoutes } from '
|
|
13
|
-
import { useNavigateBack } from '
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
8
|
+
import { BlockchainsSection } from '../../components/BlockchainsSection';
|
|
9
|
+
import { Layout, PageContainer } from '../../components/Layout';
|
|
10
|
+
import { SearchInput } from '../../components/SearchInput';
|
|
11
|
+
import { TokenList } from '../../components/TokenList';
|
|
12
|
+
import { navigationRoutes } from '../../constants/navigationRoutes';
|
|
13
|
+
import { useNavigateBack } from '../../hooks/useNavigateBack';
|
|
14
|
+
import { useSearchCustomTokens } from '../../hooks/useSearchCustomTokens';
|
|
15
|
+
import { useAppStore } from '../../store/AppStore';
|
|
16
|
+
import { useQuoteStore } from '../../store/quote';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
prepareTokensList,
|
|
20
|
+
shouldSearchForCustomTokens,
|
|
21
|
+
} from './SelectSwapItemPage.helpers';
|
|
16
22
|
|
|
17
23
|
interface PropTypes {
|
|
18
24
|
type: 'source' | 'destination';
|
|
@@ -31,6 +37,12 @@ export function SelectSwapItemsPage(props: PropTypes) {
|
|
|
31
37
|
setToBlockchain,
|
|
32
38
|
} = useQuoteStore();
|
|
33
39
|
const { getBalanceFor } = useAppStore();
|
|
40
|
+
const {
|
|
41
|
+
fetch,
|
|
42
|
+
loading,
|
|
43
|
+
tokens: customTokens,
|
|
44
|
+
cancel,
|
|
45
|
+
} = useSearchCustomTokens();
|
|
34
46
|
const [searchedFor, setSearchedFor] = useState<string>('');
|
|
35
47
|
|
|
36
48
|
const selectedBlockchain = type === 'source' ? fromBlockchain : toBlockchain;
|
|
@@ -47,6 +59,14 @@ export function SelectSwapItemsPage(props: PropTypes) {
|
|
|
47
59
|
getBalanceFor: getBalanceFor,
|
|
48
60
|
});
|
|
49
61
|
|
|
62
|
+
const modifiedTokens = prepareTokensList(
|
|
63
|
+
tokens,
|
|
64
|
+
customTokens,
|
|
65
|
+
searchedFor,
|
|
66
|
+
loading,
|
|
67
|
+
selectedBlockchain?.name
|
|
68
|
+
);
|
|
69
|
+
|
|
50
70
|
const updateBlockchain = (blockchain: BlockchainMeta) => {
|
|
51
71
|
if (type === 'source') {
|
|
52
72
|
setFromBlockchain(blockchain);
|
|
@@ -57,9 +77,9 @@ export function SelectSwapItemsPage(props: PropTypes) {
|
|
|
57
77
|
|
|
58
78
|
const updateToken = (token: Token) => {
|
|
59
79
|
if (type === 'source') {
|
|
60
|
-
setFromToken({ token, meta: { blockchains
|
|
80
|
+
setFromToken({ token, meta: { blockchains } });
|
|
61
81
|
} else {
|
|
62
|
-
setToToken({ token, meta: { blockchains
|
|
82
|
+
setToToken({ token, meta: { blockchains } });
|
|
63
83
|
}
|
|
64
84
|
};
|
|
65
85
|
const types = {
|
|
@@ -67,6 +87,18 @@ export function SelectSwapItemsPage(props: PropTypes) {
|
|
|
67
87
|
destination: i18n.t('Destination'),
|
|
68
88
|
};
|
|
69
89
|
|
|
90
|
+
useEffect(() => {
|
|
91
|
+
if (
|
|
92
|
+
shouldSearchForCustomTokens(tokens, searchedFor, selectedBlockchain?.name)
|
|
93
|
+
) {
|
|
94
|
+
fetch(searchedFor, selectedBlockchain?.name ?? undefined);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return () => {
|
|
98
|
+
cancel();
|
|
99
|
+
};
|
|
100
|
+
}, [tokens.length, searchedFor, selectedBlockchain?.name]);
|
|
101
|
+
|
|
70
102
|
return (
|
|
71
103
|
<Layout
|
|
72
104
|
header={{
|
|
@@ -92,10 +124,19 @@ export function SelectSwapItemsPage(props: PropTypes) {
|
|
|
92
124
|
size="large"
|
|
93
125
|
setValue={() => setSearchedFor('')}
|
|
94
126
|
onChange={(event) => setSearchedFor(event.target.value)}
|
|
127
|
+
suffix={
|
|
128
|
+
shouldSearchForCustomTokens(
|
|
129
|
+
tokens,
|
|
130
|
+
searchedFor,
|
|
131
|
+
selectedBlockchain?.name
|
|
132
|
+
) && loading ? (
|
|
133
|
+
<Spinner size={12} color="secondary" />
|
|
134
|
+
) : undefined
|
|
135
|
+
}
|
|
95
136
|
/>
|
|
96
137
|
<Divider size={16} />
|
|
97
138
|
<TokenList
|
|
98
|
-
list={
|
|
139
|
+
list={modifiedTokens}
|
|
99
140
|
selectedBlockchain={selectedBlockchainName}
|
|
100
141
|
searchedFor={searchedFor}
|
|
101
142
|
type={type}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { SelectSwapItemsPage } from './SelectSwapItemsPage';
|
package/src/store/app.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { AppStoreState } from './slices/types';
|
|
2
1
|
import type { WidgetConfig } from '../types';
|
|
2
|
+
import type { AppStoreState } from './slices/types';
|
|
3
3
|
import type { StateCreator } from 'zustand';
|
|
4
4
|
|
|
5
5
|
import { create } from 'zustand';
|
|
@@ -48,6 +48,17 @@ export function createAppStore(initialData?: WidgetConfig) {
|
|
|
48
48
|
disabledLiquiditySources: state.disabledLiquiditySources,
|
|
49
49
|
};
|
|
50
50
|
},
|
|
51
|
+
version: 1,
|
|
52
|
+
migrate: (persistedState, version) => {
|
|
53
|
+
const state = persistedState as AppStoreState;
|
|
54
|
+
if (version === 0) {
|
|
55
|
+
state._customTokens = state._customTokens.map((token) => ({
|
|
56
|
+
...token,
|
|
57
|
+
warning: true,
|
|
58
|
+
}));
|
|
59
|
+
}
|
|
60
|
+
return state;
|
|
61
|
+
},
|
|
51
62
|
}
|
|
52
63
|
)
|
|
53
64
|
);
|
package/src/store/quote.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { TokenData } from '../components/TokenList/TokenList.types';
|
|
1
2
|
import type {
|
|
2
3
|
BlockchainMeta,
|
|
3
4
|
MetaResponse,
|
|
@@ -35,7 +36,9 @@ export const getUsdValue = (
|
|
|
35
36
|
|
|
36
37
|
export type Meta = Pick<MetaResponse, 'blockchains' | 'tokens'>;
|
|
37
38
|
|
|
38
|
-
export type SetTokenParams =
|
|
39
|
+
export type SetTokenParams =
|
|
40
|
+
| { token: TokenData; meta: { blockchains: BlockchainMeta[] } }
|
|
41
|
+
| { token: null };
|
|
39
42
|
|
|
40
43
|
type SomeQuoteState = {
|
|
41
44
|
quotes: MultiRouteResponse | null;
|
|
@@ -58,9 +61,9 @@ export interface QuoteState {
|
|
|
58
61
|
inputUsdValue: BigNumber | null;
|
|
59
62
|
outputAmount: BigNumber | null;
|
|
60
63
|
outputUsdValue: BigNumber | null;
|
|
61
|
-
fromToken:
|
|
64
|
+
fromToken: TokenData | null;
|
|
62
65
|
sortStrategy: PreferenceType;
|
|
63
|
-
toToken:
|
|
66
|
+
toToken: TokenData | null;
|
|
64
67
|
quoteWalletsConfirmed: boolean;
|
|
65
68
|
selectedWallets: Wallet[];
|
|
66
69
|
quoteWarningsConfirmed: boolean;
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { ConfigSlice } from './config';
|
|
2
2
|
import type { DataSlice } from './data';
|
|
3
|
+
import type { WalletsSlice } from './wallets';
|
|
4
|
+
import type { TokenData } from '../../components/TokenList/TokenList.types';
|
|
3
5
|
import type { WidgetConfig } from '../../types';
|
|
4
6
|
import type { SwapperMeta, Token } from 'rango-sdk';
|
|
5
7
|
import type { StateCreator } from 'zustand';
|
|
@@ -46,13 +48,13 @@ export interface SettingsSlice {
|
|
|
46
48
|
) => void;
|
|
47
49
|
addPreferredBlockchain: (blockchain: string) => void;
|
|
48
50
|
updateSettings: (config: WidgetConfig) => void;
|
|
49
|
-
setCustomToken: (token:
|
|
51
|
+
setCustomToken: (token: TokenData) => void;
|
|
50
52
|
deleteCustomToken: (token: Token) => void;
|
|
51
53
|
customTokens: () => Token[];
|
|
52
54
|
}
|
|
53
55
|
|
|
54
56
|
export const createSettingsSlice: StateCreator<
|
|
55
|
-
SettingsSlice & DataSlice & ConfigSlice,
|
|
57
|
+
SettingsSlice & DataSlice & ConfigSlice & WalletsSlice,
|
|
56
58
|
[],
|
|
57
59
|
[],
|
|
58
60
|
SettingsSlice
|
|
@@ -186,10 +188,15 @@ export const createSettingsSlice: StateCreator<
|
|
|
186
188
|
}),
|
|
187
189
|
});
|
|
188
190
|
},
|
|
189
|
-
setCustomToken: (token) =>
|
|
191
|
+
setCustomToken: (token) => {
|
|
192
|
+
void get().fetchCustomTokensBalance({
|
|
193
|
+
tokens: [token],
|
|
194
|
+
connectedWallets: get().connectedWallets,
|
|
195
|
+
});
|
|
190
196
|
set((state) => ({
|
|
191
197
|
_customTokens: [token, ...state._customTokens],
|
|
192
|
-
}))
|
|
198
|
+
}));
|
|
199
|
+
},
|
|
193
200
|
deleteCustomToken: (token) =>
|
|
194
201
|
set((state) => ({
|
|
195
202
|
_customTokens: state._customTokens.filter(
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AppStoreState } from './types';
|
|
2
2
|
import type { Namespace } from '@rango-dev/wallets-core/namespaces/common';
|
|
3
|
-
import type { Token, WalletDetail } from 'rango-sdk';
|
|
3
|
+
import type { Asset, Token, WalletDetail } from 'rango-sdk';
|
|
4
4
|
|
|
5
5
|
import BigNumber from 'bignumber.js';
|
|
6
6
|
|
|
@@ -24,6 +24,7 @@ import {
|
|
|
24
24
|
extractAssetFromBalanceKey,
|
|
25
25
|
removeBalanceFromAggregatedBalance,
|
|
26
26
|
updateAggregatedBalanceStateForNewAccount,
|
|
27
|
+
updateBalancesWithNewPrices,
|
|
27
28
|
} from '../utils/wallets';
|
|
28
29
|
|
|
29
30
|
type WalletAddress = string;
|
|
@@ -124,6 +125,10 @@ export interface WalletsSlice {
|
|
|
124
125
|
accounts: Wallet[],
|
|
125
126
|
options?: { retryOnFailedBalances?: boolean }
|
|
126
127
|
) => Promise<void>;
|
|
128
|
+
fetchCustomTokensBalance: (params: {
|
|
129
|
+
tokens: Asset[];
|
|
130
|
+
connectedWallets: Wallet[];
|
|
131
|
+
}) => Promise<void>;
|
|
127
132
|
getBalanceFor: (token: Token) => Balance | null;
|
|
128
133
|
getBalances: () => BalanceState;
|
|
129
134
|
getBalancesForWalletAddress: (address: string) => BalanceState;
|
|
@@ -295,6 +300,98 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
|
|
|
295
300
|
});
|
|
296
301
|
}
|
|
297
302
|
},
|
|
303
|
+
fetchCustomTokensBalance: async (params) => {
|
|
304
|
+
const { tokens, connectedWallets } = params;
|
|
305
|
+
|
|
306
|
+
const tokensByBlockchain = tokens.reduce<{ [key: string]: Asset[] }>(
|
|
307
|
+
(acc, asset) => {
|
|
308
|
+
(acc[asset.blockchain] ||= []).push(asset);
|
|
309
|
+
return acc;
|
|
310
|
+
},
|
|
311
|
+
{}
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
const addedWallets = new Set<string>();
|
|
315
|
+
|
|
316
|
+
const tokensByWalletAddress = connectedWallets.reduce<{
|
|
317
|
+
[key: string]: Asset[];
|
|
318
|
+
}>((acc, wallet) => {
|
|
319
|
+
const key = `${wallet.address}-${wallet.chain}`;
|
|
320
|
+
if (addedWallets.has(key)) {
|
|
321
|
+
return acc;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
addedWallets.add(key);
|
|
325
|
+
if (tokensByBlockchain[wallet.chain]) {
|
|
326
|
+
if (!acc[wallet.address]) {
|
|
327
|
+
acc[wallet.address] = [];
|
|
328
|
+
}
|
|
329
|
+
acc[wallet.address].push(...tokensByBlockchain[wallet.chain]);
|
|
330
|
+
}
|
|
331
|
+
return acc;
|
|
332
|
+
}, {});
|
|
333
|
+
|
|
334
|
+
Object.entries(tokensByWalletAddress).forEach(
|
|
335
|
+
async ([walletAddress, tokens]) => {
|
|
336
|
+
try {
|
|
337
|
+
const { balances } = await httpService().getMultipleTokenBalance({
|
|
338
|
+
assets: tokens.map(({ symbol, address, blockchain }) => ({
|
|
339
|
+
symbol,
|
|
340
|
+
address,
|
|
341
|
+
blockchain,
|
|
342
|
+
})),
|
|
343
|
+
walletAddress,
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
if (balances) {
|
|
347
|
+
let nextBalances: BalanceState = get()._balances;
|
|
348
|
+
let nextAggregatedBalances: AggregatedBalanceState =
|
|
349
|
+
get()._aggregatedBalances;
|
|
350
|
+
|
|
351
|
+
balances.forEach((balance) => {
|
|
352
|
+
if (parseFloat(balance.amount.amount) === 0) {
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
const WalletDetail = {
|
|
357
|
+
blockChain: balance.asset.blockchain,
|
|
358
|
+
balances: [balance],
|
|
359
|
+
address: walletAddress,
|
|
360
|
+
};
|
|
361
|
+
|
|
362
|
+
updateBalancesWithNewPrices(WalletDetail, nextBalances, get);
|
|
363
|
+
|
|
364
|
+
const balancesForWallet = createBalanceStateForNewAccount(
|
|
365
|
+
WalletDetail,
|
|
366
|
+
get
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
nextAggregatedBalances =
|
|
370
|
+
updateAggregatedBalanceStateForNewAccount(
|
|
371
|
+
nextAggregatedBalances,
|
|
372
|
+
balancesForWallet
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
nextBalances = {
|
|
376
|
+
...nextBalances,
|
|
377
|
+
...balancesForWallet,
|
|
378
|
+
};
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
set((state) => ({
|
|
382
|
+
_balances: {
|
|
383
|
+
...state._balances,
|
|
384
|
+
...nextBalances,
|
|
385
|
+
},
|
|
386
|
+
_aggregatedBalances: nextAggregatedBalances,
|
|
387
|
+
}));
|
|
388
|
+
}
|
|
389
|
+
} catch (error) {
|
|
390
|
+
console.error(error);
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
);
|
|
394
|
+
},
|
|
298
395
|
setWalletsAsSelected: (wallets) => {
|
|
299
396
|
const nextConnectedWalletsWithUpdatedSelectedStatus =
|
|
300
397
|
get().connectedWallets.map((connectedWallet) => {
|
|
@@ -332,6 +429,10 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
|
|
|
332
429
|
get().addConnectedWallet(accounts, namespace);
|
|
333
430
|
|
|
334
431
|
void get().fetchBalances(accounts);
|
|
432
|
+
void get().fetchCustomTokensBalance({
|
|
433
|
+
tokens: get().customTokens(),
|
|
434
|
+
connectedWallets: accounts,
|
|
435
|
+
});
|
|
335
436
|
},
|
|
336
437
|
removeBalancesForWallet: (walletType, options) => {
|
|
337
438
|
let walletsNeedsToBeRemoved = get().connectedWallets.filter(
|
|
@@ -562,7 +663,7 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
|
|
|
562
663
|
}
|
|
563
664
|
}
|
|
564
665
|
|
|
565
|
-
let nextBalances: BalanceState =
|
|
666
|
+
let nextBalances: BalanceState = get()._balances;
|
|
566
667
|
let nextAggregatedBalances: AggregatedBalanceState =
|
|
567
668
|
get()._aggregatedBalances;
|
|
568
669
|
walletsDetails.forEach((wallet) => {
|
|
@@ -570,6 +671,8 @@ export const createWalletsSlice = keepLastUpdated<AppStoreState, WalletsSlice>(
|
|
|
570
671
|
return;
|
|
571
672
|
}
|
|
572
673
|
|
|
674
|
+
updateBalancesWithNewPrices(wallet, nextBalances, get);
|
|
675
|
+
|
|
573
676
|
// Remove old balances for current wallet and blockchain
|
|
574
677
|
get().removeBalancesForWallet(walletType, {
|
|
575
678
|
chains: [wallet.blockChain],
|
|
@@ -44,8 +44,36 @@ export function extractAssetFromBalanceKey(key: BalanceKey): Asset {
|
|
|
44
44
|
};
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
export function updateBalancesWithNewPrices(
|
|
48
|
+
wallet: Omit<WalletDetail, 'failed' | 'explorerUrl'>,
|
|
49
|
+
balanceState: BalanceState,
|
|
50
|
+
store: () => AppStoreState
|
|
51
|
+
): BalanceState {
|
|
52
|
+
wallet.balances?.forEach((balance) => {
|
|
53
|
+
const usdPrice =
|
|
54
|
+
balance.price ?? store().findToken(balance.asset)?.usdPrice;
|
|
55
|
+
const balancesToUpdate =
|
|
56
|
+
store()._aggregatedBalances[createAssetKey(balance.asset)];
|
|
57
|
+
|
|
58
|
+
balancesToUpdate?.forEach((balanceKey) => {
|
|
59
|
+
if (balanceState[balanceKey]) {
|
|
60
|
+
balanceState[balanceKey] = {
|
|
61
|
+
...balanceState[balanceKey],
|
|
62
|
+
usdValue: usdPrice
|
|
63
|
+
? new BigNumber(usdPrice ?? ZERO)
|
|
64
|
+
.multipliedBy(balanceState[balanceKey].amount)
|
|
65
|
+
.toString()
|
|
66
|
+
: '',
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
return balanceState;
|
|
73
|
+
}
|
|
74
|
+
|
|
47
75
|
export function createBalanceStateForNewAccount(
|
|
48
|
-
account: WalletDetail,
|
|
76
|
+
account: Omit<WalletDetail, 'failed' | 'explorerUrl'>,
|
|
49
77
|
store: () => AppStoreState
|
|
50
78
|
): BalanceState {
|
|
51
79
|
const state: BalanceState = {};
|
|
@@ -55,7 +83,8 @@ export function createBalanceStateForNewAccount(
|
|
|
55
83
|
const amount = accountBalance.amount.amount;
|
|
56
84
|
const decimals = accountBalance.amount.decimals;
|
|
57
85
|
|
|
58
|
-
const usdPrice =
|
|
86
|
+
const usdPrice =
|
|
87
|
+
accountBalance.price ?? store().findToken(accountBalance.asset)?.usdPrice;
|
|
59
88
|
const usdValue = usdPrice
|
|
60
89
|
? new BigNumber(usdPrice ?? ZERO).multipliedBy(amount).toString()
|
|
61
90
|
: '';
|
package/src/utils/quote.ts
CHANGED
|
@@ -293,7 +293,7 @@ export function getPriceImpact(
|
|
|
293
293
|
|
|
294
294
|
export const getUniqueBlockchains = (steps: Step[]) => {
|
|
295
295
|
const set = new Set();
|
|
296
|
-
const result: { displayName: string; image
|
|
296
|
+
const result: { displayName: string; image?: string }[] = [];
|
|
297
297
|
steps.forEach((step) => {
|
|
298
298
|
if (!set.has(step.from.chain.displayName)) {
|
|
299
299
|
set.add(step.from.chain.displayName);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"SelectSwapItemsPage.d.ts","sourceRoot":"","sources":["../../src/pages/SelectSwapItemsPage.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAmB,MAAM,OAAO,CAAC;AAYxC,UAAU,SAAS;IACjB,IAAI,EAAE,QAAQ,GAAG,aAAa,CAAC;CAChC;AAED,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,SAAS,qBAiGnD"}
|
/package/dist/pages/{SelectSwapItemsPage.d.ts → SelectSwapItemPage/SelectSwapItemsPage.d.ts}
RENAMED
|
File without changes
|