@rango-dev/widget-embedded 0.30.1-next.1 → 0.30.1-next.11
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/ConfirmWalletsModal/ConfirmWallets.styles.d.ts +1 -653
- package/dist/components/ConfirmWalletsModal/ConfirmWallets.styles.d.ts.map +1 -1
- package/dist/components/ConfirmWalletsModal/ConfirmWalletsModal.d.ts.map +1 -1
- package/dist/components/ConfirmWalletsModal/WalletList.d.ts.map +1 -1
- package/dist/components/CustomDestination/CustomDestination.d.ts +4 -0
- package/dist/components/CustomDestination/CustomDestination.d.ts.map +1 -0
- package/dist/components/CustomDestination/CustomDestination.styles.d.ts +495 -0
- package/dist/components/CustomDestination/CustomDestination.styles.d.ts.map +1 -0
- package/dist/components/CustomDestination/CustomDestination.types.d.ts +7 -0
- package/dist/components/CustomDestination/CustomDestination.types.d.ts.map +1 -0
- package/dist/components/Quote/Quote.styles.d.ts +3 -3
- package/dist/components/RefreshModal/RefreshModal.styles.d.ts +3 -3
- package/dist/components/SwapDetailsModal/SwapDetailsModal.WalletState.d.ts.map +1 -1
- package/dist/containers/Wallets/Wallets.d.ts.map +1 -1
- package/dist/hooks/usePrepareBlockchainList/usePrepareBlockchainList.helpers.d.ts +2 -2
- package/dist/hooks/useTheme.d.ts.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +4 -4
- package/dist/pages/Home.d.ts.map +1 -1
- package/dist/pages/WalletsPage.d.ts.map +1 -1
- package/dist/services/cacheService.d.ts +21 -0
- package/dist/services/cacheService.d.ts.map +1 -0
- package/dist/store/notification.d.ts.map +1 -1
- package/dist/store/slices/config.d.ts +2 -1
- package/dist/store/slices/config.d.ts.map +1 -1
- package/dist/store/slices/data.d.ts +2 -1
- package/dist/store/slices/data.d.ts.map +1 -1
- package/dist/store/utils/data.d.ts +20 -0
- package/dist/store/utils/data.d.ts.map +1 -0
- package/dist/store/utils/data.test.d.ts +2 -0
- package/dist/store/utils/data.test.d.ts.map +1 -0
- package/dist/store/utils/index.d.ts +2 -0
- package/dist/store/utils/index.d.ts.map +1 -0
- package/dist/test-utils/fixtures.d.ts +1 -0
- package/dist/test-utils/fixtures.d.ts.map +1 -1
- package/dist/types/config.d.ts +5 -0
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/event.d.ts +21 -15
- package/dist/types/event.d.ts.map +1 -1
- package/dist/types/notification.d.ts +1 -0
- package/dist/types/notification.d.ts.map +1 -1
- package/dist/types/wallets.d.ts +1 -1
- package/dist/types/wallets.d.ts.map +1 -1
- package/dist/utils/events.d.ts +8 -0
- package/dist/utils/events.d.ts.map +1 -0
- package/dist/utils/settings.d.ts +1 -1
- package/dist/utils/swap.d.ts +1 -1
- package/dist/utils/swap.d.ts.map +1 -1
- package/dist/widget-embedded.build.json +1 -1
- package/package.json +10 -10
- package/src/components/ConfirmWalletsModal/ConfirmWallets.styles.ts +1 -49
- package/src/components/ConfirmWalletsModal/ConfirmWalletsModal.tsx +59 -178
- package/src/components/ConfirmWalletsModal/WalletList.tsx +16 -4
- package/src/components/CustomDestination/CustomDestination.styles.ts +45 -0
- package/src/components/CustomDestination/CustomDestination.tsx +148 -0
- package/src/components/CustomDestination/CustomDestination.types.ts +7 -0
- package/src/components/SwapDetailsModal/SwapDetailsModal.WalletState.tsx +28 -13
- package/src/containers/Wallets/Wallets.tsx +7 -2
- package/src/hooks/useTheme.ts +11 -5
- package/src/index.ts +4 -0
- package/src/pages/Home.tsx +6 -3
- package/src/pages/WalletsPage.tsx +25 -11
- package/src/services/cacheService.ts +35 -0
- package/src/store/notification.ts +13 -1
- package/src/store/slices/config.ts +39 -1
- package/src/store/slices/data.test.ts +84 -0
- package/src/store/slices/data.ts +44 -24
- package/src/store/utils/data.test.ts +175 -0
- package/src/store/utils/data.ts +117 -0
- package/src/store/utils/index.ts +1 -0
- package/src/test-utils/fixtures.ts +14 -7
- package/src/types/config.ts +3 -1
- package/src/types/event.ts +32 -16
- package/src/types/notification.ts +1 -0
- package/src/types/wallets.ts +1 -1
- package/src/utils/events.ts +27 -0
- package/src/utils/swap.ts +4 -4
|
@@ -68,6 +68,33 @@ export const WalletStateContent = (props: WalletStateContentProps) => {
|
|
|
68
68
|
}
|
|
69
69
|
};
|
|
70
70
|
|
|
71
|
+
const handleWalletItemClick = () => {
|
|
72
|
+
if (!!walletType && !!walletInfo) {
|
|
73
|
+
if (!!walletInfo.namespaces?.length) {
|
|
74
|
+
if (walletInfo.namespaces.length > 1) {
|
|
75
|
+
setNamespacesModalState({
|
|
76
|
+
open: true,
|
|
77
|
+
providerType: walletType,
|
|
78
|
+
providerImage: walletInfo.img,
|
|
79
|
+
availableNamespaces: walletInfo.namespaces,
|
|
80
|
+
singleNamespace: walletInfo.singleNamespace,
|
|
81
|
+
});
|
|
82
|
+
} else if (walletInfo.needsDerivationPath) {
|
|
83
|
+
setDerivationPathModalState({
|
|
84
|
+
open: true,
|
|
85
|
+
providerType: walletType,
|
|
86
|
+
providerImage: walletInfo.img,
|
|
87
|
+
namespace: walletInfo.namespaces[0],
|
|
88
|
+
});
|
|
89
|
+
} else {
|
|
90
|
+
connect(walletType).catch((error) => debug(error));
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
connect(walletType).catch((error) => debug(error));
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
|
|
71
98
|
const handleConfirmNamespaces = (selectedNamespaces: Namespace[]) => {
|
|
72
99
|
if (
|
|
73
100
|
!!walletInfo?.needsDerivationPath &&
|
|
@@ -117,19 +144,7 @@ export const WalletStateContent = (props: WalletStateContentProps) => {
|
|
|
117
144
|
link={walletInfo.installLink}
|
|
118
145
|
disabled={walletButtonDisabled}
|
|
119
146
|
// TODO we need to show an error modal when user reject the connection
|
|
120
|
-
onClick={
|
|
121
|
-
if (walletInfo.namespaces) {
|
|
122
|
-
setNamespacesModalState({
|
|
123
|
-
open: true,
|
|
124
|
-
providerType: walletType,
|
|
125
|
-
providerImage: walletInfo.img,
|
|
126
|
-
availableNamespaces: walletInfo.namespaces,
|
|
127
|
-
singleNamespace: walletInfo.singleNamespace,
|
|
128
|
-
});
|
|
129
|
-
} else {
|
|
130
|
-
connect(walletType).catch((error) => debug(error));
|
|
131
|
-
}
|
|
132
|
-
}}
|
|
147
|
+
onClick={handleWalletItemClick}
|
|
133
148
|
/>
|
|
134
149
|
</WalletContainer>
|
|
135
150
|
)}
|
|
@@ -31,7 +31,12 @@ export const WidgetContext = createContext<WidgetContextInterface>({
|
|
|
31
31
|
});
|
|
32
32
|
|
|
33
33
|
function Main(props: PropsWithChildren<PropTypes>) {
|
|
34
|
-
const {
|
|
34
|
+
const {
|
|
35
|
+
updateConfig,
|
|
36
|
+
updateSettings,
|
|
37
|
+
fetch: fetchMeta,
|
|
38
|
+
fetchStatus,
|
|
39
|
+
} = useAppStore();
|
|
35
40
|
const blockchains = useAppStore().blockchains();
|
|
36
41
|
const { findToken } = useAppStore();
|
|
37
42
|
const config = useAppStore().config;
|
|
@@ -61,7 +66,7 @@ function Main(props: PropsWithChildren<PropTypes>) {
|
|
|
61
66
|
dappConfig: props.config,
|
|
62
67
|
};
|
|
63
68
|
}
|
|
64
|
-
}, [props.config]);
|
|
69
|
+
}, [props.config, fetchStatus]);
|
|
65
70
|
|
|
66
71
|
const evmBasedChainNames = blockchains
|
|
67
72
|
.filter(isEvmBlockchain)
|
package/src/hooks/useTheme.ts
CHANGED
|
@@ -15,6 +15,13 @@ import {
|
|
|
15
15
|
} from '../utils/configs';
|
|
16
16
|
import { customizedThemeTokens } from '../utils/ui';
|
|
17
17
|
|
|
18
|
+
function doesWindowPreferDarkColorScheme() {
|
|
19
|
+
return (
|
|
20
|
+
window.matchMedia &&
|
|
21
|
+
window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
|
|
18
25
|
export function useTheme(props: WidgetTheme) {
|
|
19
26
|
const {
|
|
20
27
|
colors,
|
|
@@ -23,7 +30,9 @@ export function useTheme(props: WidgetTheme) {
|
|
|
23
30
|
secondaryBorderRadius = DEFAULT_SECONDARY_RADIUS,
|
|
24
31
|
} = props;
|
|
25
32
|
|
|
26
|
-
const [OSTheme, setOSTheme] = useState(
|
|
33
|
+
const [OSTheme, setOSTheme] = useState(
|
|
34
|
+
doesWindowPreferDarkColorScheme() ? 'dark' : 'light'
|
|
35
|
+
);
|
|
27
36
|
|
|
28
37
|
const { theme } = useAppStore();
|
|
29
38
|
|
|
@@ -64,10 +73,7 @@ export function useTheme(props: WidgetTheme) {
|
|
|
64
73
|
}
|
|
65
74
|
};
|
|
66
75
|
|
|
67
|
-
if (
|
|
68
|
-
window.matchMedia &&
|
|
69
|
-
window.matchMedia('(prefers-color-scheme: dark)').matches
|
|
70
|
-
) {
|
|
76
|
+
if (doesWindowPreferDarkColorScheme()) {
|
|
71
77
|
setOSTheme('dark');
|
|
72
78
|
}
|
|
73
79
|
|
package/src/index.ts
CHANGED
|
@@ -4,6 +4,7 @@ import type {
|
|
|
4
4
|
BlockchainAndTokenConfig,
|
|
5
5
|
QuoteEventData,
|
|
6
6
|
Tokens,
|
|
7
|
+
UiEventData,
|
|
7
8
|
WalletEventData,
|
|
8
9
|
WalletInfoWithExtra,
|
|
9
10
|
WidgetColors,
|
|
@@ -71,6 +72,7 @@ import { widgetEventEmitter } from './services/eventEmitter';
|
|
|
71
72
|
import {
|
|
72
73
|
WidgetEvents as MainEvents,
|
|
73
74
|
QuoteEventTypes,
|
|
75
|
+
UiEventTypes,
|
|
74
76
|
WalletEventTypes,
|
|
75
77
|
WidgetEvents,
|
|
76
78
|
} from './types';
|
|
@@ -108,6 +110,7 @@ export type {
|
|
|
108
110
|
WidgetVariant,
|
|
109
111
|
WalletEventData,
|
|
110
112
|
QuoteEventData,
|
|
113
|
+
UiEventData,
|
|
111
114
|
WalletInfoWithExtra,
|
|
112
115
|
};
|
|
113
116
|
export {
|
|
@@ -133,6 +136,7 @@ export {
|
|
|
133
136
|
MainEvents,
|
|
134
137
|
QuoteEventTypes,
|
|
135
138
|
WalletEventTypes,
|
|
139
|
+
UiEventTypes,
|
|
136
140
|
RouteEventType,
|
|
137
141
|
StepEventType,
|
|
138
142
|
StepExecutionEventStatus,
|
package/src/pages/Home.tsx
CHANGED
|
@@ -19,7 +19,9 @@ import { useAppStore } from '../store/AppStore';
|
|
|
19
19
|
import { useQuoteStore } from '../store/quote';
|
|
20
20
|
import { useUiStore } from '../store/ui';
|
|
21
21
|
import { useWalletsStore } from '../store/wallets';
|
|
22
|
+
import { UiEventTypes } from '../types';
|
|
22
23
|
import { isVariantExpandable } from '../utils/configs';
|
|
24
|
+
import { emitPreventableEvent } from '../utils/events';
|
|
23
25
|
import { getSwapButtonState, isTokensIdentical } from '../utils/swap';
|
|
24
26
|
|
|
25
27
|
const MainContainer = styled('div', {
|
|
@@ -115,14 +117,12 @@ export function Home() {
|
|
|
115
117
|
navigate(route);
|
|
116
118
|
}
|
|
117
119
|
};
|
|
118
|
-
|
|
119
120
|
const onClickOnQuote = (quote: SelectedQuote) => {
|
|
120
121
|
if (selectedQuote?.requestId !== quote.requestId) {
|
|
121
122
|
setShowQuoteWarningModal(false);
|
|
122
123
|
setSelectedQuote(quote);
|
|
123
124
|
}
|
|
124
125
|
};
|
|
125
|
-
|
|
126
126
|
return (
|
|
127
127
|
<MainContainer>
|
|
128
128
|
<Layout
|
|
@@ -138,7 +138,10 @@ export function Home() {
|
|
|
138
138
|
fullWidth
|
|
139
139
|
onClick={() => {
|
|
140
140
|
if (swapButtonState.action === 'connect-wallet') {
|
|
141
|
-
|
|
141
|
+
emitPreventableEvent(
|
|
142
|
+
{ type: UiEventTypes.CLICK_CONNECT_WALLET },
|
|
143
|
+
() => onHandleNavigation(navigationRoutes.wallets)
|
|
144
|
+
);
|
|
142
145
|
} else if (swapButtonState.action === 'confirm-warning') {
|
|
143
146
|
setShowQuoteWarningModal(true);
|
|
144
147
|
} else {
|
|
@@ -126,21 +126,35 @@ export function WalletsPage() {
|
|
|
126
126
|
|
|
127
127
|
const filteredWallets = filterWalletsByCategory(list, blockchainCategory);
|
|
128
128
|
|
|
129
|
-
const handleWalletItemClick = (
|
|
129
|
+
const handleWalletItemClick = (wallet: WalletInfoWithExtra) => {
|
|
130
130
|
if (isSingleWalletActive(list, config.multiWallets)) {
|
|
131
131
|
return;
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
if (
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
134
|
+
if (
|
|
135
|
+
!!wallet.namespaces?.length &&
|
|
136
|
+
wallet.state === WalletState.DISCONNECTED
|
|
137
|
+
) {
|
|
138
|
+
if (wallet.namespaces.length > 1) {
|
|
139
|
+
setNamespacesModalState({
|
|
140
|
+
open: true,
|
|
141
|
+
providerType: wallet.type,
|
|
142
|
+
providerImage: wallet.image,
|
|
143
|
+
availableNamespaces: wallet.namespaces,
|
|
144
|
+
singleNamespace: wallet.singleNamespace,
|
|
145
|
+
});
|
|
146
|
+
} else if (wallet.needsDerivationPath) {
|
|
147
|
+
setDerivationPathModalState({
|
|
148
|
+
open: true,
|
|
149
|
+
providerType: wallet.type,
|
|
150
|
+
providerImage: wallet.image,
|
|
151
|
+
namespace: wallet.namespaces[0],
|
|
152
|
+
});
|
|
153
|
+
} else {
|
|
154
|
+
void handleClick(wallet.type);
|
|
155
|
+
}
|
|
142
156
|
} else {
|
|
143
|
-
void handleClick(type);
|
|
157
|
+
void handleClick(wallet.type);
|
|
144
158
|
}
|
|
145
159
|
};
|
|
146
160
|
|
|
@@ -208,7 +222,7 @@ export function WalletsPage() {
|
|
|
208
222
|
key={key}
|
|
209
223
|
{...wallet}
|
|
210
224
|
container={getContainer()}
|
|
211
|
-
onClick={(
|
|
225
|
+
onClick={() => handleWalletItemClick(wallet)}
|
|
212
226
|
isLoading={fetchMetaStatus === 'loading'}
|
|
213
227
|
disabled={!isActiveTab}
|
|
214
228
|
/>
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { Token } from 'rango-sdk';
|
|
2
|
+
|
|
3
|
+
interface CacheServiceInterface<V> {
|
|
4
|
+
get<K extends keyof V>(key: K): V[K] | undefined;
|
|
5
|
+
set<K extends keyof V>(key: K, value: V[K]): void;
|
|
6
|
+
remove<K extends keyof V>(key: K): void;
|
|
7
|
+
clear(): void;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
class CacheService<T> implements CacheServiceInterface<T> {
|
|
11
|
+
#cache: Map<string, T[keyof T]> = new Map();
|
|
12
|
+
|
|
13
|
+
get<K extends keyof T>(key: K): T[K] | undefined {
|
|
14
|
+
return this.#cache.get(key as string) as T[K];
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
set<K extends keyof T>(key: K, value: T[K]): void {
|
|
18
|
+
this.#cache.set(key as string, value);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
remove<K extends keyof T>(key: K): void {
|
|
22
|
+
this.#cache.delete(key as string);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
clear(): void {
|
|
26
|
+
this.#cache.clear();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export type CachedEntries = {
|
|
31
|
+
supportedSourceTokens: Token[];
|
|
32
|
+
supportedDestinationTokens: Token[];
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
export const cacheService = new CacheService<CachedEntries>();
|
|
@@ -36,6 +36,7 @@ export const useNotificationStore = createSelectors(
|
|
|
36
36
|
creationTime: Date.now(),
|
|
37
37
|
requestId: route.requestId,
|
|
38
38
|
route: {
|
|
39
|
+
creationTime: parseInt(route.creationTime),
|
|
39
40
|
from: {
|
|
40
41
|
blockchain: fromStep.fromBlockchain,
|
|
41
42
|
address: fromStep.fromSymbolAddress,
|
|
@@ -67,7 +68,18 @@ export const useNotificationStore = createSelectors(
|
|
|
67
68
|
getNotifications: () => {
|
|
68
69
|
const { isSynced, notifications } = get();
|
|
69
70
|
return isSynced
|
|
70
|
-
? notifications.sort((a, b) =>
|
|
71
|
+
? notifications.sort((a, b) => {
|
|
72
|
+
if (a.route.creationTime && !b.route.creationTime) {
|
|
73
|
+
return -1;
|
|
74
|
+
}
|
|
75
|
+
if (!a.route.creationTime && b.route.creationTime) {
|
|
76
|
+
return 1;
|
|
77
|
+
}
|
|
78
|
+
if (!a.route.creationTime && !b.route.creationTime) {
|
|
79
|
+
return b.creationTime - a.creationTime;
|
|
80
|
+
}
|
|
81
|
+
return b.route.creationTime - a.route.creationTime;
|
|
82
|
+
})
|
|
71
83
|
: [];
|
|
72
84
|
},
|
|
73
85
|
syncNotifications: (swaps) => {
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import type { DataSlice } from './data';
|
|
1
2
|
import type { SettingsSlice } from './settings';
|
|
2
3
|
import type { WidgetConfig } from '../../types';
|
|
3
4
|
import type { StateCreatorWithInitialData } from '../app';
|
|
4
5
|
|
|
6
|
+
import { cacheService } from '../../services/cacheService';
|
|
7
|
+
import { matchTokensFromConfigWithMeta } from '../utils';
|
|
8
|
+
|
|
5
9
|
export const DEFAULT_CONFIG: WidgetConfig = {
|
|
6
10
|
apiKey: '',
|
|
7
11
|
title: undefined,
|
|
@@ -54,7 +58,7 @@ export interface ConfigSlice {
|
|
|
54
58
|
|
|
55
59
|
export const createConfigSlice: StateCreatorWithInitialData<
|
|
56
60
|
WidgetConfig,
|
|
57
|
-
ConfigSlice & SettingsSlice,
|
|
61
|
+
ConfigSlice & SettingsSlice & DataSlice,
|
|
58
62
|
ConfigSlice
|
|
59
63
|
> = (initialData, set, get) => {
|
|
60
64
|
return {
|
|
@@ -87,6 +91,40 @@ export const createConfigSlice: StateCreatorWithInitialData<
|
|
|
87
91
|
// Actions
|
|
88
92
|
updateConfig: (nextConfig: WidgetConfig) => {
|
|
89
93
|
const currentConfig = get().config;
|
|
94
|
+
const {
|
|
95
|
+
_tokensMapByTokenHash: tokensMapByTokenHash,
|
|
96
|
+
_tokensMapByBlockchainName: tokensMapByBlockchainName,
|
|
97
|
+
} = get();
|
|
98
|
+
|
|
99
|
+
const supportedSourceTokens = matchTokensFromConfigWithMeta({
|
|
100
|
+
type: 'source',
|
|
101
|
+
config: {
|
|
102
|
+
blockchains: nextConfig.from?.blockchains,
|
|
103
|
+
tokens: nextConfig.from?.tokens,
|
|
104
|
+
},
|
|
105
|
+
meta: {
|
|
106
|
+
tokensMapByBlockchainName,
|
|
107
|
+
tokensMapByTokenHash,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
const supportedDestinationTokens = matchTokensFromConfigWithMeta({
|
|
112
|
+
type: 'destination',
|
|
113
|
+
config: {
|
|
114
|
+
blockchains: nextConfig.to?.blockchains,
|
|
115
|
+
tokens: nextConfig.to?.tokens,
|
|
116
|
+
},
|
|
117
|
+
meta: {
|
|
118
|
+
tokensMapByBlockchainName,
|
|
119
|
+
tokensMapByTokenHash,
|
|
120
|
+
},
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
cacheService.set('supportedSourceTokens', supportedSourceTokens);
|
|
124
|
+
cacheService.set(
|
|
125
|
+
'supportedDestinationTokens',
|
|
126
|
+
supportedDestinationTokens
|
|
127
|
+
);
|
|
90
128
|
|
|
91
129
|
set({
|
|
92
130
|
config: {
|
|
@@ -3,6 +3,7 @@ import type { EvmBlockchainMeta, Token } from 'rango-sdk';
|
|
|
3
3
|
|
|
4
4
|
import { assert, beforeEach, describe, expect, test } from 'vitest';
|
|
5
5
|
|
|
6
|
+
import { cacheService } from '../../services/cacheService';
|
|
6
7
|
import {
|
|
7
8
|
createEvmBlockchain,
|
|
8
9
|
createInitialAppStore,
|
|
@@ -17,6 +18,7 @@ let customTokens: [Token, Token, Token];
|
|
|
17
18
|
let rangoBlockchain: EvmBlockchainMeta;
|
|
18
19
|
|
|
19
20
|
beforeEach(() => {
|
|
21
|
+
cacheService.clear();
|
|
20
22
|
rangoBlockchain = createEvmBlockchain();
|
|
21
23
|
|
|
22
24
|
customTokens = [
|
|
@@ -52,6 +54,10 @@ beforeEach(() => {
|
|
|
52
54
|
customTokens.forEach((token) => {
|
|
53
55
|
const tokenHash = createTokenHash(token);
|
|
54
56
|
initData._tokensMapByTokenHash.set(tokenHash, token);
|
|
57
|
+
if (!initData._tokensMapByBlockchainName[token.blockchain]) {
|
|
58
|
+
initData._tokensMapByBlockchainName[token.blockchain] = [];
|
|
59
|
+
}
|
|
60
|
+
initData._tokensMapByBlockchainName[token.blockchain].push(tokenHash);
|
|
55
61
|
});
|
|
56
62
|
|
|
57
63
|
const appStore = createAppStore();
|
|
@@ -351,3 +357,81 @@ describe('search in tokens', () => {
|
|
|
351
357
|
expect(secondResult).toBe('RNG');
|
|
352
358
|
});
|
|
353
359
|
});
|
|
360
|
+
|
|
361
|
+
describe('supported tokens from config', () => {
|
|
362
|
+
test('Should ensure tokens include only tokens from the config', () => {
|
|
363
|
+
const rangoToken = customTokens[0];
|
|
364
|
+
const djangoToken = customTokens[1];
|
|
365
|
+
|
|
366
|
+
const configTokens = [rangoToken, djangoToken];
|
|
367
|
+
|
|
368
|
+
appStoreState = updateAppStoreConfig(appStoreState, {
|
|
369
|
+
from: {
|
|
370
|
+
tokens: configTokens,
|
|
371
|
+
},
|
|
372
|
+
to: { tokens: configTokens },
|
|
373
|
+
});
|
|
374
|
+
|
|
375
|
+
let sourceTokens = appStoreState.tokens({
|
|
376
|
+
type: 'source',
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
let destinationTokens = appStoreState.tokens({
|
|
380
|
+
type: 'destination',
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
expect(configTokens).toMatchObject(sourceTokens);
|
|
384
|
+
expect(configTokens).toMatchObject(destinationTokens);
|
|
385
|
+
|
|
386
|
+
appStoreState = updateAppStoreConfig(appStoreState, {
|
|
387
|
+
from: {
|
|
388
|
+
blockchains: [rangoBlockchain.name],
|
|
389
|
+
tokens: {
|
|
390
|
+
[rangoBlockchain.name]: {
|
|
391
|
+
tokens: configTokens,
|
|
392
|
+
isExcluded: false,
|
|
393
|
+
},
|
|
394
|
+
},
|
|
395
|
+
},
|
|
396
|
+
to: {
|
|
397
|
+
blockchains: [rangoBlockchain.name],
|
|
398
|
+
tokens: {
|
|
399
|
+
[rangoBlockchain.name]: {
|
|
400
|
+
tokens: configTokens,
|
|
401
|
+
isExcluded: false,
|
|
402
|
+
},
|
|
403
|
+
},
|
|
404
|
+
},
|
|
405
|
+
});
|
|
406
|
+
|
|
407
|
+
sourceTokens = appStoreState.tokens({
|
|
408
|
+
type: 'source',
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
destinationTokens = appStoreState.tokens({
|
|
412
|
+
type: 'destination',
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
expect(sourceTokens).toMatchObject(sourceTokens);
|
|
416
|
+
expect(configTokens).toMatchObject(destinationTokens);
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
test('Check tokens calculation is caching', () => {
|
|
420
|
+
const rangoToken = customTokens[0];
|
|
421
|
+
const djangoToken = customTokens[1];
|
|
422
|
+
|
|
423
|
+
appStoreState = updateAppStoreConfig(appStoreState, {
|
|
424
|
+
from: {
|
|
425
|
+
tokens: [rangoToken, djangoToken],
|
|
426
|
+
},
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
expect(cacheService.get('supportedSourceTokens')?.length ?? 0).toBe(0);
|
|
430
|
+
|
|
431
|
+
appStoreState.tokens({
|
|
432
|
+
type: 'source',
|
|
433
|
+
});
|
|
434
|
+
|
|
435
|
+
expect(cacheService.get('supportedSourceTokens')?.length ?? 0).toBe(2);
|
|
436
|
+
});
|
|
437
|
+
});
|
package/src/store/slices/data.ts
CHANGED
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
// We keep all the received data from server in this slice
|
|
2
2
|
|
|
3
3
|
import type { ConfigSlice } from './config';
|
|
4
|
-
import type {
|
|
4
|
+
import type { CachedEntries } from '../../services/cacheService';
|
|
5
|
+
import type { Balance, Blockchain, TokenHash } from '../../types';
|
|
5
6
|
import type { Asset, BlockchainMeta, SwapperMeta, Token } from 'rango-sdk';
|
|
6
7
|
import type { StateCreator } from 'zustand';
|
|
7
8
|
|
|
9
|
+
import { cacheService } from '../../services/cacheService';
|
|
8
10
|
import { httpService as sdk } from '../../services/httpService';
|
|
9
11
|
import { compareWithSearchFor, containsText } from '../../utils/common';
|
|
10
|
-
import { isTokenExcludedInConfig } from '../../utils/configs';
|
|
11
12
|
import { createTokenHash, isTokenNative } from '../../utils/meta';
|
|
12
13
|
import { sortLiquiditySourcesByGroupTitle } from '../../utils/settings';
|
|
13
14
|
import { areTokensEqual, compareTokenBalance } from '../../utils/wallets';
|
|
15
|
+
import { matchTokensFromConfigWithMeta } from '../utils';
|
|
14
16
|
|
|
15
17
|
type BlockchainOptions = {
|
|
16
18
|
type?: 'source' | 'destination';
|
|
@@ -30,6 +32,7 @@ export type FetchStatus = 'loading' | 'success' | 'failed';
|
|
|
30
32
|
export interface DataSlice {
|
|
31
33
|
_blockchainsMapByName: Map<string, BlockchainMeta>;
|
|
32
34
|
_tokensMapByTokenHash: Map<TokenHash, Token>;
|
|
35
|
+
_tokensMapByBlockchainName: Record<Blockchain, TokenHash[]>;
|
|
33
36
|
_popularTokens: Token[];
|
|
34
37
|
_swappers: SwapperMeta[];
|
|
35
38
|
fetchStatus: FetchStatus;
|
|
@@ -48,8 +51,9 @@ export const createDataSlice: StateCreator<
|
|
|
48
51
|
DataSlice
|
|
49
52
|
> = (set, get) => ({
|
|
50
53
|
// State
|
|
51
|
-
_blockchainsMapByName: new Map
|
|
52
|
-
_tokensMapByTokenHash: new Map
|
|
54
|
+
_blockchainsMapByName: new Map(),
|
|
55
|
+
_tokensMapByTokenHash: new Map(),
|
|
56
|
+
_tokensMapByBlockchainName: {},
|
|
53
57
|
_popularTokens: [],
|
|
54
58
|
_swappers: [],
|
|
55
59
|
fetchStatus: 'loading',
|
|
@@ -84,31 +88,41 @@ export const createDataSlice: StateCreator<
|
|
|
84
88
|
return list;
|
|
85
89
|
},
|
|
86
90
|
tokens: (options) => {
|
|
87
|
-
const
|
|
88
|
-
const tokensFromState = Array.from(
|
|
91
|
+
const { _tokensMapByTokenHash, _tokensMapByBlockchainName, config } = get();
|
|
92
|
+
const tokensFromState = Array.from(_tokensMapByTokenHash.values());
|
|
89
93
|
const blockchainsMapByName = get()._blockchainsMapByName;
|
|
90
|
-
|
|
91
|
-
if (!options || !options?.type) {
|
|
94
|
+
if (!options || !options.type) {
|
|
92
95
|
return tokensFromState;
|
|
93
96
|
}
|
|
94
97
|
|
|
95
|
-
const
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
98
|
+
const configType = options.type === 'source' ? 'from' : 'to';
|
|
99
|
+
const cacheKey: keyof CachedEntries =
|
|
100
|
+
options.type === 'source'
|
|
101
|
+
? 'supportedSourceTokens'
|
|
102
|
+
: 'supportedDestinationTokens';
|
|
103
|
+
|
|
104
|
+
let supportedTokens = cacheService.get(cacheKey);
|
|
105
|
+
if (!supportedTokens) {
|
|
106
|
+
supportedTokens = matchTokensFromConfigWithMeta({
|
|
107
|
+
type: options.type,
|
|
108
|
+
config: {
|
|
109
|
+
blockchains: config[configType]?.blockchains,
|
|
110
|
+
tokens: config[configType]?.tokens,
|
|
111
|
+
},
|
|
112
|
+
meta: {
|
|
113
|
+
tokensMapByTokenHash: _tokensMapByTokenHash,
|
|
114
|
+
tokensMapByBlockchainName: _tokensMapByBlockchainName,
|
|
115
|
+
},
|
|
116
|
+
});
|
|
117
|
+
cacheService.set(cacheKey, supportedTokens);
|
|
118
|
+
}
|
|
119
|
+
|
|
99
120
|
const blockchains = get().blockchains({
|
|
100
121
|
type: options.type,
|
|
101
122
|
});
|
|
102
123
|
|
|
103
|
-
const list =
|
|
124
|
+
const list = supportedTokens
|
|
104
125
|
.filter((token) => {
|
|
105
|
-
if (
|
|
106
|
-
supportedTokensConfig &&
|
|
107
|
-
isTokenExcludedInConfig(token, supportedTokensConfig)
|
|
108
|
-
) {
|
|
109
|
-
return false;
|
|
110
|
-
}
|
|
111
|
-
|
|
112
126
|
// If a specific blockchain has passed, we only keep that blockchain's tokens.
|
|
113
127
|
if (!!options.blockchain && token.blockchain !== options.blockchain) {
|
|
114
128
|
return false;
|
|
@@ -261,17 +275,18 @@ export const createDataSlice: StateCreator<
|
|
|
261
275
|
const response = await sdk().getAllMetadata({
|
|
262
276
|
enableCentralizedSwappers,
|
|
263
277
|
});
|
|
264
|
-
|
|
265
278
|
set({ fetchStatus: 'success' });
|
|
266
279
|
const blockchainsMapByName: Map<string, BlockchainMeta> = new Map<
|
|
267
280
|
string,
|
|
268
281
|
BlockchainMeta
|
|
269
282
|
>();
|
|
270
283
|
|
|
271
|
-
const
|
|
284
|
+
const tokensMapByTokenHash: Map<TokenHash, Token> = new Map<
|
|
272
285
|
TokenHash,
|
|
273
286
|
Token
|
|
274
287
|
>();
|
|
288
|
+
const tokensMapByBlockchainName: DataSlice['_tokensMapByBlockchainName'] =
|
|
289
|
+
{};
|
|
275
290
|
const tokens: Token[] = [];
|
|
276
291
|
const popularTokens: Token[] = response.popularTokens;
|
|
277
292
|
const swappers: SwapperMeta[] = response.swappers;
|
|
@@ -299,12 +314,17 @@ export const createDataSlice: StateCreator<
|
|
|
299
314
|
|
|
300
315
|
tokens.forEach((token) => {
|
|
301
316
|
const tokenHash = createTokenHash(token);
|
|
302
|
-
|
|
317
|
+
if (!tokensMapByBlockchainName[token.blockchain]) {
|
|
318
|
+
tokensMapByBlockchainName[token.blockchain] = [];
|
|
319
|
+
}
|
|
320
|
+
tokensMapByTokenHash.set(tokenHash, token);
|
|
321
|
+
tokensMapByBlockchainName[token.blockchain].push(tokenHash);
|
|
303
322
|
});
|
|
304
323
|
|
|
305
324
|
set({
|
|
306
325
|
_blockchainsMapByName: blockchainsMapByName,
|
|
307
|
-
_tokensMapByTokenHash:
|
|
326
|
+
_tokensMapByTokenHash: tokensMapByTokenHash,
|
|
327
|
+
_tokensMapByBlockchainName: tokensMapByBlockchainName,
|
|
308
328
|
_popularTokens: popularTokens,
|
|
309
329
|
_swappers: swappers,
|
|
310
330
|
});
|