@lifi/widget 1.11.4 → 1.13.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/AppDrawer.style.d.ts +1 -1
- package/AppDrawer.style.js +6 -2
- package/AppProvider.d.ts +4 -0
- package/AppProvider.js +5 -2
- package/components/Header/Header.js +1 -0
- package/components/Initializer.js +1 -1
- package/components/NotFound.js +2 -1
- package/components/PoweredBy/PoweredBy.js +3 -2
- package/components/ReverseTokensButton/ReverseTokensButton.style.d.ts +1 -1
- package/components/Step/CircularProgress.d.ts +0 -1
- package/components/Step/Step.js +4 -1
- package/components/Step/StepProcess.style.d.ts +1 -1
- package/components/StepActions/StepActions.js +4 -2
- package/components/SwapButton/ButtonTooltip.d.ts +0 -1
- package/components/SwapButton/SwapButton.js +7 -4
- package/components/SwapButton/SwapButton.style.d.ts +1 -1
- package/components/SwapInput/FormPriceHelperText.js +2 -2
- package/components/SwapInput/SwapInput.style.d.ts +1 -1
- package/components/SwapInput/SwapInputAdornment.d.ts +0 -1
- package/components/SwapInput/SwapInputAdornment.js +2 -2
- package/components/SwapInput/SwapInputAdornment.style.d.ts +1 -1
- package/components/SwapRouteCard/SwapRouteCard.style.js +4 -1
- package/components/TokenAvatar/TokenAvatar.js +3 -2
- package/components/TokenList/TokenList.js +25 -42
- package/components/TokenList/TokenList.style.d.ts +2 -2
- package/components/TokenList/TokenList.style.js +5 -2
- package/components/TokenList/TokenListItem.d.ts +2 -2
- package/components/TokenList/TokenListItem.js +7 -10
- package/components/TokenList/TokenNotFound.d.ts +2 -0
- package/components/TokenList/TokenNotFound.js +15 -0
- package/components/TokenList/VirtualizedTokenList.d.ts +3 -0
- package/components/TokenList/VirtualizedTokenList.js +53 -0
- package/components/TokenList/types.d.ts +16 -1
- package/config/lifi.d.ts +1 -1
- package/config/lifi.js +2 -8
- package/config/sentry.d.ts +1 -1
- package/config/sentry.js +33 -18
- package/config/theme.js +14 -11
- package/config/version.d.ts +1 -1
- package/config/version.js +1 -1
- package/hooks/index.d.ts +3 -0
- package/hooks/index.js +3 -0
- package/hooks/useFeaturedTokens.d.ts +1 -0
- package/hooks/useFeaturedTokens.js +6 -0
- package/hooks/useGasSufficiency.js +11 -4
- package/hooks/useRouteExecution.js +31 -17
- package/hooks/useSwapRoutes.js +2 -2
- package/hooks/useToken.d.ts +2 -1
- package/hooks/useToken.js +2 -1
- package/hooks/useTokenBalance.d.ts +2 -4
- package/hooks/useTokenBalance.js +11 -42
- package/hooks/useTokenBalances.d.ts +6 -3
- package/hooks/useTokenBalances.js +46 -22
- package/hooks/useTokenSearch.d.ts +7 -0
- package/hooks/useTokenSearch.js +37 -0
- package/hooks/useTokens.d.ts +2 -1
- package/hooks/useTokens.js +12 -4
- package/i18n/en/translation.json +5 -2
- package/i18n/index.d.ts +3 -0
- package/package.json +14 -15
- package/pages/MainPage/SwapRoutes.style.d.ts +1 -1
- package/pages/SelectTokenPage/ChainSelect.d.ts +0 -1
- package/pages/SelectTokenPage/ChainSelect.js +8 -5
- package/pages/SelectTokenPage/SearchTokenInput.d.ts +0 -1
- package/pages/SelectTokenPage/SearchTokenInput.js +2 -2
- package/pages/SelectWalletPage/SelectWalletPage.d.ts +0 -1
- package/pages/SelectWalletPage/SelectWalletPage.style.d.ts +2 -2
- package/pages/SettingsPage/AdvancedPreferences.d.ts +0 -1
- package/pages/SettingsPage/ColorSchemeButtonGroup.style.d.ts +1 -1
- package/pages/SettingsPage/GasPriceSelect.d.ts +0 -1
- package/pages/SettingsPage/SettingsPage.d.ts +0 -1
- package/pages/SettingsPage/SlippageInput.d.ts +0 -1
- package/pages/SwapHistoryPage/SwapHistoryPage.js +19 -3
- package/pages/SwapPage/StatusBottomSheet.js +2 -2
- package/pages/SwapRoutesPage/SwapRoutesPage.style.d.ts +1 -1
- package/providers/SwapFormProvider/SwapFormProvider.d.ts +1 -1
- package/providers/SwapFormProvider/SwapFormProvider.js +22 -5
- package/providers/SwapFormProvider/types.d.ts +2 -3
- package/providers/SwapFormProvider/types.js +1 -2
- package/providers/WalletProvider/WalletProvider.d.ts +11 -1
- package/providers/WalletProvider/WalletProvider.js +24 -33
- package/providers/WidgetProvider/WidgetProvider.js +24 -12
- package/stores/route/types.d.ts +1 -0
- package/stores/route/useRouteStore.js +3 -12
- package/types/index.d.ts +1 -0
- package/types/index.js +1 -0
- package/types/token.d.ts +4 -0
- package/types/token.js +1 -0
- package/types/widget.d.ts +4 -3
- package/utils/colors.d.ts +1 -0
- package/utils/colors.js +5 -0
- package/components/TokenList/utils.d.ts +0 -15
- package/components/TokenList/utils.js +0 -10
package/config/lifi.js
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
import LIFI from '@lifi/sdk';
|
|
2
|
-
const
|
|
3
|
-
// apiUrl: env.LIFI_API_URL,
|
|
4
|
-
// defaultRouteOptions: {
|
|
5
|
-
// integrator: 'li.fi',
|
|
6
|
-
// },
|
|
7
|
-
};
|
|
8
|
-
export const LiFi = new LIFI(defaultConfig);
|
|
2
|
+
export const LiFi = new LIFI();
|
|
9
3
|
export const updateLiFiConfig = (configUpdate) => {
|
|
10
|
-
LiFi.setConfig(
|
|
4
|
+
LiFi.setConfig(configUpdate);
|
|
11
5
|
};
|
package/config/sentry.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const initSentry: (enabled?: boolean) => void
|
|
1
|
+
export declare const initSentry: (enabled?: boolean) => Promise<void>;
|
package/config/sentry.js
CHANGED
|
@@ -1,20 +1,35 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
integrations: [
|
|
9
|
-
new BrowserTracing(),
|
|
10
|
-
new CaptureConsole({
|
|
11
|
-
levels: ['error'],
|
|
12
|
-
}),
|
|
13
|
-
],
|
|
14
|
-
sampleRate: 1,
|
|
15
|
-
tracesSampleRate: 0.2,
|
|
16
|
-
enabled,
|
|
17
|
-
environment: process.env.NODE_ENV,
|
|
18
|
-
release: version,
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
8
|
});
|
|
20
9
|
};
|
|
10
|
+
import { version } from './version';
|
|
11
|
+
let sentryLoaded = false;
|
|
12
|
+
export const initSentry = (enabled) => __awaiter(void 0, void 0, void 0, function* () {
|
|
13
|
+
if (enabled || sentryLoaded) {
|
|
14
|
+
const [Sentry, { CaptureConsole }, { BrowserTracing }] = yield Promise.all([
|
|
15
|
+
import('@sentry/react'),
|
|
16
|
+
import('@sentry/integrations'),
|
|
17
|
+
import('@sentry/tracing'),
|
|
18
|
+
]);
|
|
19
|
+
Sentry.init({
|
|
20
|
+
dsn: 'https://bc1312161bf948db9b9c82618035ec22@o1302189.ingest.sentry.io/6539228',
|
|
21
|
+
integrations: [
|
|
22
|
+
new BrowserTracing(),
|
|
23
|
+
new CaptureConsole({
|
|
24
|
+
levels: ['error'],
|
|
25
|
+
}),
|
|
26
|
+
],
|
|
27
|
+
sampleRate: 1,
|
|
28
|
+
tracesSampleRate: 0.2,
|
|
29
|
+
enabled,
|
|
30
|
+
environment: process.env.NODE_ENV,
|
|
31
|
+
release: version,
|
|
32
|
+
});
|
|
33
|
+
sentryLoaded = true;
|
|
34
|
+
}
|
|
35
|
+
});
|
package/config/theme.js
CHANGED
|
@@ -31,12 +31,15 @@ const shape = {
|
|
|
31
31
|
};
|
|
32
32
|
export const createTheme = (mode, theme = {}) => {
|
|
33
33
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v;
|
|
34
|
+
const primaryMainColor = (_c = (_b = (_a = theme.palette) === null || _a === void 0 ? void 0 : _a.primary) === null || _b === void 0 ? void 0 : _b.main) !== null && _c !== void 0 ? _c : palette.primary.main;
|
|
35
|
+
const primaryLightColor = lighten((_f = (_e = (_d = theme.palette) === null || _d === void 0 ? void 0 : _d.primary) === null || _e === void 0 ? void 0 : _e.main) !== null && _f !== void 0 ? _f : palette.primary.main, 0.5);
|
|
36
|
+
const primaryDarkColor = darken((_j = (_h = (_g = theme.palette) === null || _g === void 0 ? void 0 : _g.primary) === null || _h === void 0 ? void 0 : _h.main) !== null && _j !== void 0 ? _j : palette.primary.main, 0.2);
|
|
34
37
|
return createMuiTheme({
|
|
35
38
|
typography: Object.assign({ fontFamily: 'Inter var, Inter, sans-serif' }, theme.typography),
|
|
36
39
|
palette: Object.assign(Object.assign(Object.assign({ mode }, palette), { primary: {
|
|
37
|
-
main:
|
|
38
|
-
light:
|
|
39
|
-
dark:
|
|
40
|
+
main: primaryMainColor,
|
|
41
|
+
light: primaryLightColor,
|
|
42
|
+
dark: primaryDarkColor,
|
|
40
43
|
}, secondary: {
|
|
41
44
|
main: (_m = (_l = (_k = theme.palette) === null || _k === void 0 ? void 0 : _k.secondary) === null || _l === void 0 ? void 0 : _l.main) !== null && _m !== void 0 ? _m : palette.secondary.main,
|
|
42
45
|
light: lighten((_q = (_p = (_o = theme.palette) === null || _o === void 0 ? void 0 : _o.secondary) === null || _p === void 0 ? void 0 : _p.main) !== null && _q !== void 0 ? _q : palette.secondary.main, 0.5),
|
|
@@ -85,18 +88,18 @@ export const createTheme = (mode, theme = {}) => {
|
|
|
85
88
|
styleOverrides: Object.assign(Object.assign({}, (mode === 'dark'
|
|
86
89
|
? {
|
|
87
90
|
outlined: {
|
|
88
|
-
color:
|
|
89
|
-
borderColor:
|
|
91
|
+
color: primaryLightColor,
|
|
92
|
+
borderColor: primaryLightColor,
|
|
90
93
|
'&:hover': {
|
|
91
|
-
backgroundColor: alpha(
|
|
92
|
-
borderColor:
|
|
94
|
+
backgroundColor: alpha(primaryLightColor, 0.08),
|
|
95
|
+
borderColor: primaryLightColor,
|
|
93
96
|
},
|
|
94
97
|
},
|
|
95
98
|
text: {
|
|
96
|
-
color:
|
|
99
|
+
color: primaryLightColor,
|
|
97
100
|
'&:hover': {
|
|
98
|
-
backgroundColor: alpha(
|
|
99
|
-
borderColor:
|
|
101
|
+
backgroundColor: alpha(primaryLightColor, 0.08),
|
|
102
|
+
borderColor: primaryLightColor,
|
|
100
103
|
},
|
|
101
104
|
},
|
|
102
105
|
}
|
|
@@ -117,7 +120,7 @@ export const createTheme = (mode, theme = {}) => {
|
|
|
117
120
|
},
|
|
118
121
|
}, contained: {
|
|
119
122
|
'&:hover': {
|
|
120
|
-
color: getContrastRatio(
|
|
123
|
+
color: getContrastRatio(dark.text.primary, primaryMainColor) >= 3
|
|
121
124
|
? dark.text.primary
|
|
122
125
|
: light.text.primary,
|
|
123
126
|
},
|
package/config/version.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export declare const name = "@lifi/widget";
|
|
2
|
-
export declare const version = "1.
|
|
2
|
+
export declare const version = "1.13.0";
|
package/config/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export const name = '@lifi/widget';
|
|
2
|
-
export const version = '1.
|
|
2
|
+
export const version = '1.13.0';
|
package/hooks/index.d.ts
CHANGED
|
@@ -2,7 +2,9 @@ export * from './useChain';
|
|
|
2
2
|
export * from './useChains';
|
|
3
3
|
export * from './useContentHeight';
|
|
4
4
|
export * from './useDebouncedWatch';
|
|
5
|
+
export * from './useFeaturedTokens';
|
|
5
6
|
export * from './useGasSufficiency';
|
|
7
|
+
export * from './useInitializer';
|
|
6
8
|
export * from './useRouteExecution';
|
|
7
9
|
export * from './useScrollableContainer';
|
|
8
10
|
export * from './useSwapRoutes';
|
|
@@ -11,4 +13,5 @@ export * from './useToken';
|
|
|
11
13
|
export * from './useTokenBalance';
|
|
12
14
|
export * from './useTokenBalances';
|
|
13
15
|
export * from './useTokens';
|
|
16
|
+
export * from './useTokenSearch';
|
|
14
17
|
export * from './useTools';
|
package/hooks/index.js
CHANGED
|
@@ -2,7 +2,9 @@ export * from './useChain';
|
|
|
2
2
|
export * from './useChains';
|
|
3
3
|
export * from './useContentHeight';
|
|
4
4
|
export * from './useDebouncedWatch';
|
|
5
|
+
export * from './useFeaturedTokens';
|
|
5
6
|
export * from './useGasSufficiency';
|
|
7
|
+
export * from './useInitializer';
|
|
6
8
|
export * from './useRouteExecution';
|
|
7
9
|
export * from './useScrollableContainer';
|
|
8
10
|
export * from './useSwapRoutes';
|
|
@@ -11,4 +13,5 @@ export * from './useToken';
|
|
|
11
13
|
export * from './useTokenBalance';
|
|
12
14
|
export * from './useTokenBalances';
|
|
13
15
|
export * from './useTokens';
|
|
16
|
+
export * from './useTokenSearch';
|
|
14
17
|
export * from './useTools';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useFeaturedTokens: (selectedChainId: number) => import("@lifi/types").Token[] | undefined;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { useWidgetConfig } from '../providers/WidgetProvider';
|
|
3
|
+
export const useFeaturedTokens = (selectedChainId) => {
|
|
4
|
+
const { featuredTokens } = useWidgetConfig();
|
|
5
|
+
return useMemo(() => featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.filter((token) => token.chainId === selectedChainId), [featuredTokens, selectedChainId]);
|
|
6
|
+
};
|
|
@@ -15,12 +15,16 @@ export const useGasSufficiency = (route) => {
|
|
|
15
15
|
],
|
|
16
16
|
});
|
|
17
17
|
const fromAmount = useDebouncedWatch(SwapFormKey.FromAmount, 250);
|
|
18
|
-
const { tokens: fromChainTokenBalances } = useTokenBalances(fromChainId);
|
|
19
|
-
const { tokens: toChainTokenBalances } = useTokenBalances(toChainId);
|
|
20
18
|
const { getChainById } = useChains();
|
|
19
|
+
const { tokensWithBalance: fromChainTokenBalances } = useTokenBalances(fromChainId);
|
|
20
|
+
const { tokensWithBalance: toChainTokenBalances } = useTokenBalances(toChainId);
|
|
21
21
|
const insufficientGas = useMemo(() => {
|
|
22
22
|
var _a;
|
|
23
|
-
if (!account.isActive ||
|
|
23
|
+
if (!account.isActive ||
|
|
24
|
+
!route ||
|
|
25
|
+
!fromAmount ||
|
|
26
|
+
!fromChainTokenBalances ||
|
|
27
|
+
!toChainTokenBalances) {
|
|
24
28
|
return [];
|
|
25
29
|
}
|
|
26
30
|
const tokenBalancesByChain = {
|
|
@@ -78,7 +82,10 @@ export const useGasSufficiency = (route) => {
|
|
|
78
82
|
]);
|
|
79
83
|
const insufficientFunds = useMemo(() => {
|
|
80
84
|
var _a, _b;
|
|
81
|
-
if (!account.isActive ||
|
|
85
|
+
if (!account.isActive ||
|
|
86
|
+
!fromToken ||
|
|
87
|
+
!fromAmount ||
|
|
88
|
+
!fromChainTokenBalances) {
|
|
82
89
|
return false;
|
|
83
90
|
}
|
|
84
91
|
const balance = Big((_b = (_a = fromChainTokenBalances === null || fromChainTokenBalances === void 0 ? void 0 : fromChainTokenBalances.find((t) => t.address === fromToken)) === null || _a === void 0 ? void 0 : _a.amount) !== null && _b !== void 0 ? _b : 0);
|
|
@@ -20,21 +20,23 @@ export const useRouteExecution = (routeId) => {
|
|
|
20
20
|
const routeExecution = useRouteStore((state) => state.routes[routeId]);
|
|
21
21
|
const [updateRoute, restartRoute, deleteRoute] = useRouteStore((state) => [state.updateRoute, state.restartRoute, state.deleteRoute], shallow);
|
|
22
22
|
const updateCallback = (updatedRoute) => {
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
const clonedUpdatedRoute = deepClone(updatedRoute);
|
|
24
|
+
console.log('Route updated.', clonedUpdatedRoute);
|
|
25
|
+
updateRoute(clonedUpdatedRoute);
|
|
25
26
|
};
|
|
26
|
-
const switchChainHook =
|
|
27
|
+
const switchChainHook = (requiredChainId) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
28
|
if (!account.isActive || !account.signer) {
|
|
28
29
|
return account.signer;
|
|
29
30
|
}
|
|
30
|
-
|
|
31
|
+
const currentChainId = yield account.signer.getChainId();
|
|
32
|
+
if (currentChainId !== requiredChainId) {
|
|
31
33
|
const switched = yield switchChain(requiredChainId);
|
|
32
34
|
if (!switched) {
|
|
33
35
|
throw new Error('Chain was not switched.');
|
|
34
36
|
}
|
|
35
37
|
}
|
|
36
38
|
return account.signer;
|
|
37
|
-
})
|
|
39
|
+
});
|
|
38
40
|
const executeRouteMutation = useMutation(() => {
|
|
39
41
|
if (!account.signer) {
|
|
40
42
|
throw Error('Account signer not found.');
|
|
@@ -112,26 +114,29 @@ export const useRouteExecution = (routeId) => {
|
|
|
112
114
|
deleteRoute(routeId);
|
|
113
115
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
114
116
|
}, [routeId]);
|
|
117
|
+
// Resume route execution after page reload
|
|
115
118
|
useEffect(() => {
|
|
116
|
-
//
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
const alreadyStarted = routeExecution === null || routeExecution === void 0 ? void 0 : routeExecution.route.steps.some((step) => step.execution);
|
|
120
|
-
if (!isDone &&
|
|
121
|
-
!isFailed &&
|
|
122
|
-
alreadyStarted &&
|
|
123
|
-
account.signer &&
|
|
119
|
+
// Check if route is eligible for automatic resuming
|
|
120
|
+
if (isActiveRoute(routeExecution === null || routeExecution === void 0 ? void 0 : routeExecution.route) &&
|
|
121
|
+
account.isActive &&
|
|
124
122
|
!resumedAfterMount.current) {
|
|
125
123
|
resumedAfterMount.current = true;
|
|
126
124
|
resumeRoute();
|
|
127
125
|
}
|
|
126
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
127
|
+
}, [account.isActive]);
|
|
128
|
+
useEffect(() => {
|
|
128
129
|
return () => {
|
|
129
|
-
|
|
130
|
-
|
|
130
|
+
var _a;
|
|
131
|
+
const route = (_a = useRouteStore.getState().routes[routeId]) === null || _a === void 0 ? void 0 : _a.route;
|
|
132
|
+
if (!route || !isActiveRoute(route)) {
|
|
133
|
+
return;
|
|
131
134
|
}
|
|
135
|
+
LiFi.moveExecutionToBackground(route);
|
|
136
|
+
console.log('Move route execution to background.', routeId);
|
|
137
|
+
resumedAfterMount.current = false;
|
|
132
138
|
};
|
|
133
|
-
|
|
134
|
-
}, [account.signer]);
|
|
139
|
+
}, [routeId]);
|
|
135
140
|
return {
|
|
136
141
|
executeRoute,
|
|
137
142
|
restartRoute: restartRouteMutation,
|
|
@@ -140,3 +145,12 @@ export const useRouteExecution = (routeId) => {
|
|
|
140
145
|
status: routeExecution === null || routeExecution === void 0 ? void 0 : routeExecution.status,
|
|
141
146
|
};
|
|
142
147
|
};
|
|
148
|
+
const isActiveRoute = (route) => {
|
|
149
|
+
if (!route) {
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
const allDone = route.steps.every((step) => { var _a; return ((_a = step.execution) === null || _a === void 0 ? void 0 : _a.status) === 'DONE'; });
|
|
153
|
+
const isFailed = route.steps.some((step) => { var _a; return ((_a = step.execution) === null || _a === void 0 ? void 0 : _a.status) === 'FAILED'; });
|
|
154
|
+
const alreadyStarted = route.steps.some((step) => step.execution);
|
|
155
|
+
return !allDone && !isFailed && alreadyStarted;
|
|
156
|
+
};
|
package/hooks/useSwapRoutes.js
CHANGED
|
@@ -40,7 +40,7 @@ export const useSwapRoutes = () => {
|
|
|
40
40
|
// Boolean(account.address) &&
|
|
41
41
|
!isNaN(fromChainId) &&
|
|
42
42
|
!isNaN(toChainId) &&
|
|
43
|
-
Boolean(
|
|
43
|
+
Boolean(token === null || token === void 0 ? void 0 : token.address) &&
|
|
44
44
|
Boolean(toTokenAddress) &&
|
|
45
45
|
!isNaN(fromTokenAmount) &&
|
|
46
46
|
Number(fromTokenAmount) > 0 &&
|
|
@@ -49,7 +49,7 @@ export const useSwapRoutes = () => {
|
|
|
49
49
|
'routes',
|
|
50
50
|
account.address,
|
|
51
51
|
fromChainId,
|
|
52
|
-
|
|
52
|
+
token === null || token === void 0 ? void 0 : token.address,
|
|
53
53
|
fromTokenAmount,
|
|
54
54
|
toChainId,
|
|
55
55
|
toTokenAddress,
|
package/hooks/useToken.d.ts
CHANGED
package/hooks/useToken.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { TokenAmount } from '@lifi/sdk';
|
|
2
1
|
export declare const useTokenBalance: (chainId: number, tokenAddress: string) => {
|
|
3
|
-
token:
|
|
2
|
+
token: import("..").Token | undefined;
|
|
4
3
|
isLoading: boolean;
|
|
5
|
-
|
|
6
|
-
refetchBalance: (chainId?: number, tokenAddress?: string) => Promise<void>;
|
|
4
|
+
refetch: <TPageData>(options?: (import("@tanstack/query-core").RefetchOptions & import("@tanstack/query-core").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/query-core").QueryObserverResult<import("..").Token[] | undefined, unknown>>;
|
|
7
5
|
};
|
package/hooks/useTokenBalance.js
CHANGED
|
@@ -1,46 +1,15 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
-
});
|
|
9
|
-
};
|
|
10
|
-
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
11
|
-
import { useCallback } from 'react';
|
|
12
|
-
import { LiFi } from '../config/lifi';
|
|
13
|
-
import { useWallet } from '../providers/WalletProvider';
|
|
14
|
-
import { formatTokenAmount } from '../utils';
|
|
15
|
-
import { useToken } from './useToken';
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import { useTokenBalances } from './useTokenBalances';
|
|
16
3
|
export const useTokenBalance = (chainId, tokenAddress) => {
|
|
17
|
-
const {
|
|
18
|
-
const
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
const tokenBalance = yield LiFi.getTokenBalance(address, token);
|
|
25
|
-
return Object.assign(Object.assign(Object.assign({}, token), tokenBalance), { amount: formatTokenAmount(tokenBalance === null || tokenBalance === void 0 ? void 0 : tokenBalance.amount) });
|
|
26
|
-
}), {
|
|
27
|
-
enabled: Boolean(account.address) && Boolean(token),
|
|
28
|
-
refetchIntervalInBackground: true,
|
|
29
|
-
refetchInterval: 30000,
|
|
30
|
-
staleTime: 30000,
|
|
31
|
-
cacheTime: 30000,
|
|
32
|
-
});
|
|
33
|
-
const refetchBalance = useCallback((chainId, tokenAddress) => __awaiter(void 0, void 0, void 0, function* () {
|
|
34
|
-
if (!chainId && !tokenAddress) {
|
|
35
|
-
refetch();
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
yield queryClient.invalidateQueries(['token', account.address, chainId, tokenAddress], { type: 'all', exact: true });
|
|
39
|
-
}), [account.address, queryClient, refetch]);
|
|
4
|
+
const { tokens, tokensWithBalance, isBalanceLoading, refetch } = useTokenBalances(chainId);
|
|
5
|
+
const token = useMemo(() => {
|
|
6
|
+
var _a;
|
|
7
|
+
const token = (_a = (tokensWithBalance !== null && tokensWithBalance !== void 0 ? tokensWithBalance : tokens)) === null || _a === void 0 ? void 0 : _a.find((token) => token.address === tokenAddress && token.chainId === chainId);
|
|
8
|
+
return token;
|
|
9
|
+
}, [chainId, tokenAddress, tokens, tokensWithBalance]);
|
|
40
10
|
return {
|
|
41
|
-
token
|
|
42
|
-
isLoading,
|
|
43
|
-
|
|
44
|
-
refetchBalance,
|
|
11
|
+
token,
|
|
12
|
+
isLoading: isBalanceLoading,
|
|
13
|
+
refetch,
|
|
45
14
|
};
|
|
46
15
|
};
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Token } from '../types';
|
|
2
2
|
export declare const useTokenBalances: (selectedChainId: number) => {
|
|
3
|
-
tokens:
|
|
3
|
+
tokens: Token[] | undefined;
|
|
4
|
+
tokensWithBalance: Token[] | undefined;
|
|
5
|
+
featuredTokens: import("@lifi/types").Token[] | undefined;
|
|
4
6
|
isLoading: boolean;
|
|
5
7
|
isBalanceLoading: boolean;
|
|
6
|
-
|
|
8
|
+
isBalanceFetched: boolean;
|
|
9
|
+
refetch: <TPageData>(options?: (import("@tanstack/react-query").RefetchOptions & import("@tanstack/react-query").RefetchQueryFilters<TPageData>) | undefined) => Promise<import("@tanstack/react-query").QueryObserverResult<Token[] | undefined, unknown>>;
|
|
7
10
|
};
|
|
@@ -7,46 +7,70 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
7
7
|
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
8
|
});
|
|
9
9
|
};
|
|
10
|
+
/* eslint-disable consistent-return */
|
|
10
11
|
import { useQuery } from '@tanstack/react-query';
|
|
12
|
+
import { useState } from 'react';
|
|
11
13
|
import { LiFi } from '../config/lifi';
|
|
12
14
|
import { useWallet } from '../providers/WalletProvider';
|
|
13
15
|
import { formatTokenAmount } from '../utils';
|
|
14
|
-
import {
|
|
16
|
+
import { useFeaturedTokens } from './useFeaturedTokens';
|
|
15
17
|
import { useTokens } from './useTokens';
|
|
18
|
+
const defaultRefetchInterval = 60000;
|
|
19
|
+
const minRefetchInterval = 1000;
|
|
16
20
|
export const useTokenBalances = (selectedChainId) => {
|
|
17
21
|
const { account } = useWallet();
|
|
18
|
-
const
|
|
22
|
+
const featuredTokens = useFeaturedTokens(selectedChainId);
|
|
19
23
|
const { tokens, isLoading } = useTokens(selectedChainId);
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
+
const [refetchInterval, setRefetchInterval] = useState(defaultRefetchInterval);
|
|
25
|
+
const isBalanceLoadingEnabled = Boolean(account.address) && Boolean(tokens === null || tokens === void 0 ? void 0 : tokens.length);
|
|
26
|
+
const { data: tokensWithBalance, isLoading: isBalanceLoading, isFetched: isBalanceFetched, refetch, } = useQuery(['token-balances', account.address, selectedChainId, tokens === null || tokens === void 0 ? void 0 : tokens.length], ({ queryKey: [, accountAddress] }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
27
|
+
if (!accountAddress || !tokens) {
|
|
28
|
+
return;
|
|
24
29
|
}
|
|
25
|
-
const tokenBalances = yield LiFi.getTokenBalances(
|
|
26
|
-
|
|
30
|
+
const tokenBalances = yield LiFi.getTokenBalances(accountAddress, tokens);
|
|
31
|
+
if (!(tokenBalances === null || tokenBalances === void 0 ? void 0 : tokenBalances.length)) {
|
|
32
|
+
// Sometimes RPCs (e.g. Arbitrum) don't return balances on first call
|
|
33
|
+
// TODO: fix and remove backplane
|
|
34
|
+
setRefetchInterval((interval) => interval === defaultRefetchInterval
|
|
35
|
+
? minRefetchInterval
|
|
36
|
+
: interval * 2);
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
const featuredTokenAddresses = new Set(featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.map((token) => token.address));
|
|
40
|
+
const sortFn = (a, b) => {
|
|
41
|
+
var _a, _b, _c, _d;
|
|
42
|
+
return parseFloat((_a = b.amount) !== null && _a !== void 0 ? _a : '0') * parseFloat((_b = b.priceUSD) !== null && _b !== void 0 ? _b : '0') -
|
|
43
|
+
parseFloat((_c = a.amount) !== null && _c !== void 0 ? _c : '0') * parseFloat((_d = a.priceUSD) !== null && _d !== void 0 ? _d : '0');
|
|
44
|
+
};
|
|
45
|
+
const formattedTokens = (tokenBalances.length === 0 ? tokens : tokenBalances).map((token) => {
|
|
27
46
|
token.amount = formatTokenAmount(token.amount);
|
|
28
47
|
return token;
|
|
29
48
|
});
|
|
30
|
-
|
|
31
|
-
...
|
|
32
|
-
.filter((token) => token.amount !== '0')
|
|
33
|
-
.sort(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
49
|
+
const result = [
|
|
50
|
+
...formattedTokens
|
|
51
|
+
.filter((token) => token.amount !== '0' && featuredTokenAddresses.has(token.address))
|
|
52
|
+
.sort(sortFn),
|
|
53
|
+
...formattedTokens.filter((token) => token.amount === '0' && featuredTokenAddresses.has(token.address)),
|
|
54
|
+
...formattedTokens
|
|
55
|
+
.filter((token) => token.amount !== '0' &&
|
|
56
|
+
!featuredTokenAddresses.has(token.address))
|
|
57
|
+
.sort(sortFn),
|
|
58
|
+
...formattedTokens.filter((token) => token.amount === '0' && !featuredTokenAddresses.has(token.address)),
|
|
39
59
|
];
|
|
60
|
+
return result;
|
|
40
61
|
}), {
|
|
41
62
|
enabled: isBalanceLoadingEnabled,
|
|
42
63
|
refetchIntervalInBackground: true,
|
|
43
|
-
refetchInterval
|
|
44
|
-
staleTime:
|
|
64
|
+
refetchInterval,
|
|
65
|
+
staleTime: refetchInterval,
|
|
45
66
|
});
|
|
46
67
|
return {
|
|
47
|
-
tokens
|
|
48
|
-
|
|
68
|
+
tokens,
|
|
69
|
+
tokensWithBalance,
|
|
70
|
+
featuredTokens,
|
|
71
|
+
isLoading,
|
|
49
72
|
isBalanceLoading: isBalanceLoading && isBalanceLoadingEnabled,
|
|
50
|
-
|
|
73
|
+
isBalanceFetched,
|
|
74
|
+
refetch,
|
|
51
75
|
};
|
|
52
76
|
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
2
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
3
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
4
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
5
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
6
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
7
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
8
|
+
});
|
|
9
|
+
};
|
|
10
|
+
import { useQuery, useQueryClient } from '@tanstack/react-query';
|
|
11
|
+
import { LiFi } from '../config/lifi';
|
|
12
|
+
export const useTokenSearch = (token, chainId, enabled) => {
|
|
13
|
+
const queryClient = useQueryClient();
|
|
14
|
+
const { data, isLoading, isFetching, isFetched } = useQuery(['token-search', chainId, token], ({ queryKey: [, chainId, token], signal }) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
|
+
const data = yield LiFi.getToken(chainId, token, {
|
|
16
|
+
signal,
|
|
17
|
+
});
|
|
18
|
+
if (data) {
|
|
19
|
+
queryClient.setQueriesData(['tokens', chainId], (tokens) => {
|
|
20
|
+
if (!(tokens === null || tokens === void 0 ? void 0 : tokens.some((token) => token.address === data.address))) {
|
|
21
|
+
tokens === null || tokens === void 0 ? void 0 : tokens.push(data);
|
|
22
|
+
}
|
|
23
|
+
return tokens;
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
return data;
|
|
27
|
+
}), {
|
|
28
|
+
enabled,
|
|
29
|
+
retry: false,
|
|
30
|
+
});
|
|
31
|
+
return {
|
|
32
|
+
token: data,
|
|
33
|
+
isLoading,
|
|
34
|
+
isFetching,
|
|
35
|
+
isFetched,
|
|
36
|
+
};
|
|
37
|
+
};
|
package/hooks/useTokens.d.ts
CHANGED
package/hooks/useTokens.js
CHANGED
|
@@ -9,12 +9,20 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
9
9
|
};
|
|
10
10
|
import { useQuery } from '@tanstack/react-query';
|
|
11
11
|
import { LiFi } from '../config/lifi';
|
|
12
|
+
import { useFeaturedTokens } from './useFeaturedTokens';
|
|
12
13
|
export const useTokens = (selectedChainId) => {
|
|
13
|
-
const
|
|
14
|
-
|
|
14
|
+
const featuredTokens = useFeaturedTokens(selectedChainId);
|
|
15
|
+
const { data: tokens, isLoading, isFetching, } = useQuery(['tokens', selectedChainId, featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.length], () => __awaiter(void 0, void 0, void 0, function* () {
|
|
16
|
+
var _a, _b, _c;
|
|
15
17
|
const data = yield LiFi.getTokens({ chains: [selectedChainId] });
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
const featuredTokenAddresses = new Set(featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.map((token) => token.address));
|
|
19
|
+
return [
|
|
20
|
+
...((_a = featuredTokens === null || featuredTokens === void 0 ? void 0 : featuredTokens.map((token) => {
|
|
21
|
+
token.featured = true;
|
|
22
|
+
return token;
|
|
23
|
+
})) !== null && _a !== void 0 ? _a : []),
|
|
24
|
+
...((_c = (_b = data.tokens) === null || _b === void 0 ? void 0 : _b[selectedChainId].filter((token) => !featuredTokenAddresses.has(token.address))) !== null && _c !== void 0 ? _c : []),
|
|
25
|
+
];
|
|
18
26
|
}));
|
|
19
27
|
return {
|
|
20
28
|
tokens,
|
package/i18n/en/translation.json
CHANGED
|
@@ -50,6 +50,8 @@
|
|
|
50
50
|
"selectChain": "Chain",
|
|
51
51
|
"selectToken": "Token",
|
|
52
52
|
"selectChainAndToken": "Select chain and token",
|
|
53
|
+
"featuredTokens": "Featured tokens",
|
|
54
|
+
"otherTokens": "Other tokens",
|
|
53
55
|
"inProgress": "In progress",
|
|
54
56
|
"couldntFindTokens": "We couldn't find tokens on this chain or you don't have any.",
|
|
55
57
|
"stepSwap": "Swap",
|
|
@@ -90,7 +92,8 @@
|
|
|
90
92
|
"warning": {
|
|
91
93
|
"title": {
|
|
92
94
|
"insufficientGas": "Insufficient gas",
|
|
93
|
-
"deleteSwap": "Delete this swap?"
|
|
95
|
+
"deleteSwap": "Delete this swap?",
|
|
96
|
+
"deleteSwapHistory": "Delete swap history?"
|
|
94
97
|
},
|
|
95
98
|
"message": {
|
|
96
99
|
"insufficientFunds": "You don't have enough funds to execute the swap.",
|
|
@@ -164,7 +167,7 @@
|
|
|
164
167
|
},
|
|
165
168
|
"tooltip": {
|
|
166
169
|
"notFound": {
|
|
167
|
-
"title": "
|
|
170
|
+
"title": "404",
|
|
168
171
|
"text": "We couldn't find this page."
|
|
169
172
|
},
|
|
170
173
|
"progressToNextUpdate": "Displayed data will auto-refresh after {{value}} seconds. Click this circle to update manually."
|