@rango-dev/widget-embedded 0.1.10-next.100
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/App.d.ts +9 -0
- package/dist/App.d.ts.map +1 -0
- package/dist/QueueManager.d.ts +4 -0
- package/dist/QueueManager.d.ts.map +1 -0
- package/dist/components/AppRouter.d.ts +9 -0
- package/dist/components/AppRouter.d.ts.map +1 -0
- package/dist/components/AppRoutes.d.ts +8 -0
- package/dist/components/AppRoutes.d.ts.map +1 -0
- package/dist/components/BottomLogo.d.ts +3 -0
- package/dist/components/BottomLogo.d.ts.map +1 -0
- package/dist/components/ChangeSlippageButton.d.ts +3 -0
- package/dist/components/ChangeSlippageButton.d.ts.map +1 -0
- package/dist/components/ConfirmSwapErrors.d.ts +4 -0
- package/dist/components/ConfirmSwapErrors.d.ts.map +1 -0
- package/dist/components/ConfirmSwapWarnings.d.ts +4 -0
- package/dist/components/ConfirmSwapWarnings.d.ts.map +1 -0
- package/dist/components/Footer.d.ts +2 -0
- package/dist/components/Footer.d.ts.map +1 -0
- package/dist/components/Header.d.ts +10 -0
- package/dist/components/Header.d.ts.map +1 -0
- package/dist/components/HeaderButtons.d.ts +4 -0
- package/dist/components/HeaderButtons.d.ts.map +1 -0
- package/dist/components/Layout.d.ts +7 -0
- package/dist/components/Layout.d.ts.map +1 -0
- package/dist/components/RoutesOverview.d.ts +10 -0
- package/dist/components/RoutesOverview.d.ts.map +1 -0
- package/dist/components/SwitchFromAndTo.d.ts +4 -0
- package/dist/components/SwitchFromAndTo.d.ts.map +1 -0
- package/dist/components/TokenInfo.d.ts +18 -0
- package/dist/components/TokenInfo.d.ts.map +1 -0
- package/dist/components/TokenPreview.d.ts +20 -0
- package/dist/components/TokenPreview.d.ts.map +1 -0
- package/dist/components/UpdateUrl.d.ts +2 -0
- package/dist/components/UpdateUrl.d.ts.map +1 -0
- package/dist/components/warnings/BalanceWarnings.d.ts +7 -0
- package/dist/components/warnings/BalanceWarnings.d.ts.map +1 -0
- package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts +7 -0
- package/dist/components/warnings/ConfirmSwapExtraMessages.d.ts.map +1 -0
- package/dist/components/warnings/HighSlippageWarning.d.ts +7 -0
- package/dist/components/warnings/HighSlippageWarning.d.ts.map +1 -0
- package/dist/components/warnings/MinRequiredSlippage.d.ts +7 -0
- package/dist/components/warnings/MinRequiredSlippage.d.ts.map +1 -0
- package/dist/constants/errors.d.ts +4 -0
- package/dist/constants/errors.d.ts.map +1 -0
- package/dist/constants/navigationRoutes.d.ts +15 -0
- package/dist/constants/navigationRoutes.d.ts.map +1 -0
- package/dist/constants/numbers.d.ts +3 -0
- package/dist/constants/numbers.d.ts.map +1 -0
- package/dist/constants/searchParams.d.ts +8 -0
- package/dist/constants/searchParams.d.ts.map +1 -0
- package/dist/constants/swapSettings.d.ts +6 -0
- package/dist/constants/swapSettings.d.ts.map +1 -0
- package/dist/globalStyles.d.ts +3 -0
- package/dist/globalStyles.d.ts.map +1 -0
- package/dist/hooks/useConfirmSwap.d.ts +11 -0
- package/dist/hooks/useConfirmSwap.d.ts.map +1 -0
- package/dist/hooks/useCopyToClipboard.d.ts +2 -0
- package/dist/hooks/useCopyToClipboard.d.ts.map +1 -0
- package/dist/hooks/useNavigateBack.d.ts +4 -0
- package/dist/hooks/useNavigateBack.d.ts.map +1 -0
- package/dist/hooks/usePrevious.d.ts +2 -0
- package/dist/hooks/usePrevious.d.ts.map +1 -0
- package/dist/hooks/useSelectLanguage.d.ts +5 -0
- package/dist/hooks/useSelectLanguage.d.ts.map +1 -0
- package/dist/hooks/useTheme.d.ts +8 -0
- package/dist/hooks/useTheme.d.ts.map +1 -0
- package/dist/i18n.d.ts +3 -0
- package/dist/i18n.d.ts.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/lib.d.ts +8 -0
- package/dist/lib.d.ts.map +1 -0
- package/dist/mockData/pendingSwap.d.ts +2 -0
- package/dist/mockData/pendingSwap.d.ts.map +1 -0
- package/dist/pages/ConfirmSwapPage.d.ts +3 -0
- package/dist/pages/ConfirmSwapPage.d.ts.map +1 -0
- package/dist/pages/ConfirmWalletsPage.d.ts +3 -0
- package/dist/pages/ConfirmWalletsPage.d.ts.map +1 -0
- package/dist/pages/HistoryPage.d.ts +3 -0
- package/dist/pages/HistoryPage.d.ts.map +1 -0
- package/dist/pages/Home.d.ts +9 -0
- package/dist/pages/Home.d.ts.map +1 -0
- package/dist/pages/LiquiditySourcesPage.d.ts +8 -0
- package/dist/pages/LiquiditySourcesPage.d.ts.map +1 -0
- package/dist/pages/SelectChainPage.d.ts +9 -0
- package/dist/pages/SelectChainPage.d.ts.map +1 -0
- package/dist/pages/SelectTokenPage.d.ts +15 -0
- package/dist/pages/SelectTokenPage.d.ts.map +1 -0
- package/dist/pages/SettingsPage.d.ts +8 -0
- package/dist/pages/SettingsPage.d.ts.map +1 -0
- package/dist/pages/SwapDetailsPage.d.ts +3 -0
- package/dist/pages/SwapDetailsPage.d.ts.map +1 -0
- package/dist/pages/WalletsPage.d.ts +9 -0
- package/dist/pages/WalletsPage.d.ts.map +1 -0
- package/dist/services/httpService.d.ts +3 -0
- package/dist/services/httpService.d.ts.map +1 -0
- package/dist/store/bestRoute.d.ts +28 -0
- package/dist/store/bestRoute.d.ts.map +1 -0
- package/dist/store/meta.d.ts +9 -0
- package/dist/store/meta.d.ts.map +1 -0
- package/dist/store/selectors.d.ts +11 -0
- package/dist/store/selectors.d.ts.map +1 -0
- package/dist/store/settings.d.ts +17 -0
- package/dist/store/settings.d.ts.map +1 -0
- package/dist/store/ui.d.ts +2 -0
- package/dist/store/ui.d.ts.map +1 -0
- package/dist/store/wallets.d.ts +28 -0
- package/dist/store/wallets.d.ts.map +1 -0
- package/dist/types/config.d.ts +40 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/routing.d.ts +45 -0
- package/dist/types/routing.d.ts.map +1 -0
- package/dist/types/swap.d.ts +11 -0
- package/dist/types/swap.d.ts.map +1 -0
- package/dist/utils/common.d.ts +4 -0
- package/dist/utils/common.d.ts.map +1 -0
- package/dist/utils/numbers.d.ts +14 -0
- package/dist/utils/numbers.d.ts.map +1 -0
- package/dist/utils/queue.d.ts +4 -0
- package/dist/utils/queue.d.ts.map +1 -0
- package/dist/utils/routing.d.ts +18 -0
- package/dist/utils/routing.d.ts.map +1 -0
- package/dist/utils/swap.d.ts +45 -0
- package/dist/utils/swap.d.ts.map +1 -0
- package/dist/utils/wallets.d.ts +29 -0
- package/dist/utils/wallets.d.ts.map +1 -0
- package/dist/widget-embedded.cjs.development.js +3101 -0
- package/dist/widget-embedded.cjs.development.js.map +1 -0
- package/dist/widget-embedded.cjs.production.min.js +3101 -0
- package/dist/widget-embedded.cjs.production.min.js.map +1 -0
- package/dist/widget-embedded.esm.js +3092 -0
- package/dist/widget-embedded.esm.js.map +1 -0
- package/package.json +55 -0
- package/readme.md +2 -0
- package/src/App.tsx +91 -0
- package/src/QueueManager.tsx +94 -0
- package/src/app.css +27 -0
- package/src/components/AppRouter.tsx +60 -0
- package/src/components/AppRoutes.tsx +105 -0
- package/src/components/BottomLogo.tsx +47 -0
- package/src/components/ChangeSlippageButton.tsx +19 -0
- package/src/components/ConfirmSwapErrors.tsx +38 -0
- package/src/components/ConfirmSwapWarnings.tsx +35 -0
- package/src/components/Footer.tsx +8 -0
- package/src/components/Header.tsx +37 -0
- package/src/components/HeaderButtons.tsx +47 -0
- package/src/components/Layout.tsx +96 -0
- package/src/components/RoutesOverview.tsx +60 -0
- package/src/components/SwitchFromAndTo.tsx +30 -0
- package/src/components/TokenInfo.tsx +311 -0
- package/src/components/TokenPreview.tsx +175 -0
- package/src/components/UpdateUrl.tsx +162 -0
- package/src/components/warnings/BalanceWarnings.tsx +39 -0
- package/src/components/warnings/ConfirmSwapExtraMessages.tsx +20 -0
- package/src/components/warnings/HighSlippageWarning.tsx +18 -0
- package/src/components/warnings/MinRequiredSlippage.tsx +18 -0
- package/src/constants/errors.ts +3 -0
- package/src/constants/navigationRoutes.ts +14 -0
- package/src/constants/numbers.ts +3 -0
- package/src/constants/searchParams.ts +7 -0
- package/src/constants/swapSettings.ts +9 -0
- package/src/globalStyles.ts +26 -0
- package/src/hooks/useConfirmSwap.ts +260 -0
- package/src/hooks/useCopyToClipboard.ts +23 -0
- package/src/hooks/useNavigateBack.ts +40 -0
- package/src/hooks/usePrevious.ts +13 -0
- package/src/hooks/useSelectLanguage.ts +15 -0
- package/src/hooks/useTheme.ts +127 -0
- package/src/i18n.js +30 -0
- package/src/index.tsx +14 -0
- package/src/languages/en.json +14 -0
- package/src/languages/tr.json +11 -0
- package/src/lib.tsx +119 -0
- package/src/mockData/pendingSwap.ts +607 -0
- package/src/pages/ConfirmSwapPage.tsx +72 -0
- package/src/pages/ConfirmWalletsPage.tsx +127 -0
- package/src/pages/HistoryPage.tsx +29 -0
- package/src/pages/Home.tsx +228 -0
- package/src/pages/LiquiditySourcesPage.tsx +64 -0
- package/src/pages/SelectChainPage.tsx +42 -0
- package/src/pages/SelectTokenPage.tsx +64 -0
- package/src/pages/SettingsPage.tsx +98 -0
- package/src/pages/SwapDetailsPage.tsx +38 -0
- package/src/pages/WalletsPage.tsx +119 -0
- package/src/services/httpService.ts +5 -0
- package/src/store/bestRoute.ts +245 -0
- package/src/store/meta.ts +35 -0
- package/src/store/selectors.ts +19 -0
- package/src/store/settings.ts +84 -0
- package/src/store/ui.ts +21 -0
- package/src/store/wallets.ts +190 -0
- package/src/types/config.ts +44 -0
- package/src/types/index.ts +3 -0
- package/src/types/routing.ts +60 -0
- package/src/types/swap.ts +13 -0
- package/src/utils/common.ts +35 -0
- package/src/utils/numbers.ts +133 -0
- package/src/utils/queue.ts +24 -0
- package/src/utils/routing.ts +150 -0
- package/src/utils/swap.ts +552 -0
- package/src/utils/wallets.ts +481 -0
|
@@ -0,0 +1,552 @@
|
|
|
1
|
+
import { PendingSwap } from '@rango-dev/ui/dist/containers/History/types';
|
|
2
|
+
import {
|
|
3
|
+
WalletTypeAndAddress,
|
|
4
|
+
SwapSavedSettings,
|
|
5
|
+
} from '@rango-dev/ui/dist/types/swaps';
|
|
6
|
+
import BigNumber from 'bignumber.js';
|
|
7
|
+
import {
|
|
8
|
+
BestRouteRequest,
|
|
9
|
+
BestRouteResponse,
|
|
10
|
+
RecommendedSlippage,
|
|
11
|
+
SwapResult,
|
|
12
|
+
MetaResponse,
|
|
13
|
+
Token,
|
|
14
|
+
} from 'rango-sdk';
|
|
15
|
+
import { Account } from '../store/wallets';
|
|
16
|
+
import { ZERO } from '../constants/numbers';
|
|
17
|
+
import { numberToString } from './numbers';
|
|
18
|
+
import { WalletType } from '@rango-dev/wallets-shared';
|
|
19
|
+
import { getRequiredBalanceOfWallet } from './routing';
|
|
20
|
+
import { getRequiredChains, SelectedWallet } from './wallets';
|
|
21
|
+
import { LoadingStatus } from '../store/meta';
|
|
22
|
+
import { SwapButtonState } from '../types';
|
|
23
|
+
|
|
24
|
+
export function getOutputRatio(
|
|
25
|
+
inputUsdValue: BigNumber,
|
|
26
|
+
outputUsdValue: BigNumber
|
|
27
|
+
) {
|
|
28
|
+
if (inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) return 0;
|
|
29
|
+
return outputUsdValue.div(inputUsdValue).minus(1).multipliedBy(100);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function outputRatioHasWarning(
|
|
33
|
+
inputUsdValue: BigNumber,
|
|
34
|
+
outputRatio: BigNumber | 0
|
|
35
|
+
) {
|
|
36
|
+
return (
|
|
37
|
+
(parseInt(outputRatio.toFixed(2) || '0') <= -10 &&
|
|
38
|
+
inputUsdValue.gte(new BigNumber(400))) ||
|
|
39
|
+
(parseInt(outputRatio.toFixed(2) || '0') <= -5 &&
|
|
40
|
+
inputUsdValue.gte(new BigNumber(1000)))
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function hasLimitError(bestRoute: BestRouteResponse | null): boolean {
|
|
45
|
+
return (
|
|
46
|
+
(bestRoute?.result?.swaps || []).filter((swap) => {
|
|
47
|
+
const minimum = !!swap.fromAmountMinValue
|
|
48
|
+
? new BigNumber(swap.fromAmountMinValue)
|
|
49
|
+
: null;
|
|
50
|
+
const maximum = !!swap.fromAmountMaxValue
|
|
51
|
+
? new BigNumber(swap.fromAmountMaxValue)
|
|
52
|
+
: null;
|
|
53
|
+
const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
|
|
54
|
+
if (isExclusive) {
|
|
55
|
+
return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);
|
|
56
|
+
} else {
|
|
57
|
+
return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);
|
|
58
|
+
}
|
|
59
|
+
}).length > 0
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function LimitErrorMessage(bestRoute: BestRouteResponse | null): {
|
|
64
|
+
swap: SwapResult | null;
|
|
65
|
+
fromAmountRangeError: string;
|
|
66
|
+
recommendation: string;
|
|
67
|
+
} {
|
|
68
|
+
if (!bestRoute)
|
|
69
|
+
return { swap: null, fromAmountRangeError: '', recommendation: '' };
|
|
70
|
+
const swap = (bestRoute?.result?.swaps || []).filter((swap) => {
|
|
71
|
+
const minimum = !!swap.fromAmountMinValue
|
|
72
|
+
? new BigNumber(swap.fromAmountMinValue)
|
|
73
|
+
: null;
|
|
74
|
+
const maximum = !!swap.fromAmountMaxValue
|
|
75
|
+
? new BigNumber(swap.fromAmountMaxValue)
|
|
76
|
+
: null;
|
|
77
|
+
const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
|
|
78
|
+
if (isExclusive) {
|
|
79
|
+
return minimum?.gte(swap.fromAmount) || maximum?.lte(swap.fromAmount);
|
|
80
|
+
} else {
|
|
81
|
+
return minimum?.gt(swap.fromAmount) || maximum?.lt(swap.fromAmount);
|
|
82
|
+
}
|
|
83
|
+
})[0];
|
|
84
|
+
if (!swap)
|
|
85
|
+
return { swap: null, fromAmountRangeError: '', recommendation: '' };
|
|
86
|
+
const minimum = !!swap.fromAmountMinValue
|
|
87
|
+
? new BigNumber(swap.fromAmountMinValue)
|
|
88
|
+
: null;
|
|
89
|
+
const maximum = !!swap.fromAmountMaxValue
|
|
90
|
+
? new BigNumber(swap.fromAmountMaxValue)
|
|
91
|
+
: null;
|
|
92
|
+
const isExclusive = swap.fromAmountRestrictionType === 'EXCLUSIVE';
|
|
93
|
+
|
|
94
|
+
let fromAmountRangeError = '';
|
|
95
|
+
let recommendation = '';
|
|
96
|
+
if (!isExclusive && !!minimum && minimum.gt(swap.fromAmount)) {
|
|
97
|
+
fromAmountRangeError = `Required: >= ${numberToString(minimum)} ${
|
|
98
|
+
swap.from.symbol
|
|
99
|
+
}`;
|
|
100
|
+
recommendation = 'Increase your swap amount';
|
|
101
|
+
} else if (isExclusive && !!minimum && minimum.gte(swap.fromAmount)) {
|
|
102
|
+
fromAmountRangeError = `Required: > ${numberToString(minimum)} ${
|
|
103
|
+
swap.from.symbol
|
|
104
|
+
}`;
|
|
105
|
+
recommendation = 'Increase your swap amount';
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (!isExclusive && !!maximum && maximum.lt(swap.fromAmount)) {
|
|
109
|
+
fromAmountRangeError = `Required: <= ${numberToString(maximum)} ${
|
|
110
|
+
swap.from.symbol
|
|
111
|
+
}`;
|
|
112
|
+
recommendation = 'Decrease your swap amount';
|
|
113
|
+
} else if (isExclusive && !!maximum && maximum.lte(swap.fromAmount)) {
|
|
114
|
+
fromAmountRangeError = `Required: < ${numberToString(maximum)} ${
|
|
115
|
+
swap.from.symbol
|
|
116
|
+
}`;
|
|
117
|
+
recommendation = 'Decrease your swap amount';
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return { swap, fromAmountRangeError, recommendation };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function getSwapButtonState(
|
|
124
|
+
loadingMetaStatus: LoadingStatus,
|
|
125
|
+
accounts: Account[],
|
|
126
|
+
loading: boolean,
|
|
127
|
+
bestRoute: BestRouteResponse | null,
|
|
128
|
+
hasLimitError: boolean,
|
|
129
|
+
highValueLoss: boolean,
|
|
130
|
+
priceImpactCanNotBeComputed: boolean,
|
|
131
|
+
needsToWarnEthOnPath: boolean,
|
|
132
|
+
inputIsZero: boolean
|
|
133
|
+
): SwapButtonState {
|
|
134
|
+
if (loadingMetaStatus !== 'success')
|
|
135
|
+
return { title: 'Connect Wallet', disabled: true };
|
|
136
|
+
if (accounts.length == 0) return { title: 'Connect Wallet', disabled: false };
|
|
137
|
+
if (loading) return { title: 'Finding Best Route...', disabled: true };
|
|
138
|
+
else if (inputIsZero) return { title: 'Enter an amount', disabled: true };
|
|
139
|
+
else if (!bestRoute) return { title: 'Swap', disabled: true };
|
|
140
|
+
else if (hasLimitError) return { title: 'Limit Error', disabled: true };
|
|
141
|
+
else if (highValueLoss)
|
|
142
|
+
return { title: 'Price impact is too high!', disabled: true };
|
|
143
|
+
else if (priceImpactCanNotBeComputed)
|
|
144
|
+
return {
|
|
145
|
+
title: 'USD price is unknown, price impact might be high!',
|
|
146
|
+
disabled: false,
|
|
147
|
+
hasWarning: true,
|
|
148
|
+
};
|
|
149
|
+
else if (needsToWarnEthOnPath)
|
|
150
|
+
return {
|
|
151
|
+
title: 'The route goes through Ethereum. Continue?',
|
|
152
|
+
disabled: false,
|
|
153
|
+
hasWarning: true,
|
|
154
|
+
};
|
|
155
|
+
else return { title: 'Swap', disabled: false };
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export function canComputePriceImpact(
|
|
159
|
+
bestRoute: BestRouteResponse | null,
|
|
160
|
+
inputAmount: string,
|
|
161
|
+
inputUsdValue: BigNumber,
|
|
162
|
+
outputUsdValue: BigNumber
|
|
163
|
+
) {
|
|
164
|
+
return !(
|
|
165
|
+
(inputUsdValue.lte(ZERO) || outputUsdValue.lte(ZERO)) &&
|
|
166
|
+
!!bestRoute?.result &&
|
|
167
|
+
!!inputAmount &&
|
|
168
|
+
inputAmount !== '0' &&
|
|
169
|
+
parseFloat(inputAmount || '0') !== 0 &&
|
|
170
|
+
!!bestRoute.result
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
export function calculatePendingSwap(
|
|
175
|
+
inputAmount: string,
|
|
176
|
+
bestRoute: BestRouteResponse,
|
|
177
|
+
wallets: { [p: string]: WalletTypeAndAddress },
|
|
178
|
+
settings: Omit<SwapSavedSettings, 'disabledSwappersIds'>,
|
|
179
|
+
validateBalanceOrFee: boolean,
|
|
180
|
+
meta: MetaResponse
|
|
181
|
+
): PendingSwap {
|
|
182
|
+
const simulationResult = bestRoute.result;
|
|
183
|
+
if (!simulationResult) throw Error('Simulation result should not be null');
|
|
184
|
+
|
|
185
|
+
return {
|
|
186
|
+
creationTime: new Date().getTime().toString(),
|
|
187
|
+
finishTime: null,
|
|
188
|
+
requestId: bestRoute.requestId || '',
|
|
189
|
+
inputAmount: inputAmount,
|
|
190
|
+
wallets,
|
|
191
|
+
status: 'running',
|
|
192
|
+
isPaused: false,
|
|
193
|
+
extraMessage: null,
|
|
194
|
+
extraMessageSeverity: null,
|
|
195
|
+
extraMessageDetail: null,
|
|
196
|
+
extraMessageErrorCode: null,
|
|
197
|
+
networkStatusExtraMessage: null,
|
|
198
|
+
networkStatusExtraMessageDetail: null,
|
|
199
|
+
lastNotificationTime: null,
|
|
200
|
+
//@ts-ignore
|
|
201
|
+
settings: settings,
|
|
202
|
+
simulationResult: simulationResult,
|
|
203
|
+
validateBalanceOrFee,
|
|
204
|
+
steps:
|
|
205
|
+
bestRoute.result?.swaps?.map((swap, index) => {
|
|
206
|
+
const swapper = meta.swappers.find(
|
|
207
|
+
(swapper) => swapper.id === swap.swapperId
|
|
208
|
+
);
|
|
209
|
+
const swapperType = swapper?.types[0];
|
|
210
|
+
const fromBlockchain = meta.blockchains.find(
|
|
211
|
+
(blockchain) => blockchain.name === swap.from.blockchain
|
|
212
|
+
);
|
|
213
|
+
const toBlockchain = meta.blockchains.find(
|
|
214
|
+
(blockchain) => blockchain.name === swap.to.blockchain
|
|
215
|
+
);
|
|
216
|
+
return {
|
|
217
|
+
id: index + 1,
|
|
218
|
+
fromBlockchain: swap.from.blockchain,
|
|
219
|
+
fromSymbol: swap.from.symbol,
|
|
220
|
+
fromSymbolAddress: swap.from.address,
|
|
221
|
+
fromDecimals: swap.from.decimals,
|
|
222
|
+
fromAmountPrecision: swap.fromAmountPrecision,
|
|
223
|
+
fromAmountMinValue: swap.fromAmountMinValue,
|
|
224
|
+
fromAmountMaxValue: swap.fromAmountMaxValue,
|
|
225
|
+
toBlockchain: swap.to.blockchain,
|
|
226
|
+
fromLogo: swap.from.logo,
|
|
227
|
+
toSymbol: swap.to.symbol,
|
|
228
|
+
toSymbolAddress: swap.to.address,
|
|
229
|
+
toDecimals: swap.to.decimals,
|
|
230
|
+
toLogo: swap.to.logo,
|
|
231
|
+
startTransactionTime: new Date().getTime(),
|
|
232
|
+
swapperId: swap.swapperId,
|
|
233
|
+
feeInUsd: numberToString(getUsdFeeOfStep(swap, meta.tokens), null, 2),
|
|
234
|
+
expectedOutputAmountHumanReadable: swap.toAmount,
|
|
235
|
+
outputAmount: '',
|
|
236
|
+
status: 'created',
|
|
237
|
+
networkStatus: null,
|
|
238
|
+
executedTransactionId: null,
|
|
239
|
+
externalTransactionId: null,
|
|
240
|
+
explorerUrl: null,
|
|
241
|
+
trackingCode: null,
|
|
242
|
+
cosmosTransaction: null,
|
|
243
|
+
solanaTransaction: null,
|
|
244
|
+
starknetTransaction: null,
|
|
245
|
+
starknetApprovalTransaction: null,
|
|
246
|
+
tronTransaction: null,
|
|
247
|
+
tronApprovalTransaction: null,
|
|
248
|
+
evmTransaction: null,
|
|
249
|
+
evmApprovalTransaction: null,
|
|
250
|
+
transferTransaction: null,
|
|
251
|
+
diagnosisUrl: null,
|
|
252
|
+
internalSteps: null,
|
|
253
|
+
fromBlockchainLogo: fromBlockchain?.logo || '',
|
|
254
|
+
toBlockchainLogo: toBlockchain?.logo || '',
|
|
255
|
+
swapperLogo: swapper?.logo || '',
|
|
256
|
+
swapperType: swapperType || '',
|
|
257
|
+
};
|
|
258
|
+
}) || [],
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export function requiredWallets(route: BestRouteResponse | null) {
|
|
263
|
+
const wallets: string[] = [];
|
|
264
|
+
|
|
265
|
+
route?.result?.swaps.forEach((swap) => {
|
|
266
|
+
const currentStepFromBlockchain = swap.from.blockchain;
|
|
267
|
+
const currentStepToBlockchain = swap.to.blockchain;
|
|
268
|
+
let lastAddedWallet = wallets[wallets.length - 1];
|
|
269
|
+
if (currentStepFromBlockchain != lastAddedWallet)
|
|
270
|
+
wallets.push(currentStepFromBlockchain);
|
|
271
|
+
lastAddedWallet = wallets[wallets.length - 1];
|
|
272
|
+
if (currentStepToBlockchain != lastAddedWallet)
|
|
273
|
+
wallets.push(currentStepToBlockchain);
|
|
274
|
+
});
|
|
275
|
+
return wallets;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
export const getUsdPrice = (
|
|
279
|
+
blockchain: string,
|
|
280
|
+
symbol: string,
|
|
281
|
+
address: string | null,
|
|
282
|
+
allTokens: Token[]
|
|
283
|
+
): number | null => {
|
|
284
|
+
const token = allTokens?.find(
|
|
285
|
+
(t) =>
|
|
286
|
+
t.blockchain === blockchain &&
|
|
287
|
+
t.symbol?.toUpperCase() === symbol?.toUpperCase() &&
|
|
288
|
+
t.address === address
|
|
289
|
+
);
|
|
290
|
+
return token?.usdPrice || null;
|
|
291
|
+
};
|
|
292
|
+
|
|
293
|
+
export function getUsdFeeOfStep(
|
|
294
|
+
step: SwapResult,
|
|
295
|
+
allTokens: Token[]
|
|
296
|
+
): BigNumber {
|
|
297
|
+
let totalFeeInUsd = ZERO;
|
|
298
|
+
for (let i = 0; i < step.fee.length; i++) {
|
|
299
|
+
const fee = step.fee[i];
|
|
300
|
+
if (fee.expenseType === 'DECREASE_FROM_OUTPUT') continue;
|
|
301
|
+
|
|
302
|
+
const unitPrice = getUsdPrice(
|
|
303
|
+
fee.asset.blockchain,
|
|
304
|
+
fee.asset.symbol,
|
|
305
|
+
fee.asset.address,
|
|
306
|
+
allTokens
|
|
307
|
+
);
|
|
308
|
+
totalFeeInUsd = totalFeeInUsd.plus(
|
|
309
|
+
new BigNumber(fee.amount).multipliedBy(unitPrice || 0)
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
return totalFeeInUsd;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
export function getTotalFeeInUsd(
|
|
317
|
+
bestRoute: BestRouteResponse | null,
|
|
318
|
+
allTokens: Token[]
|
|
319
|
+
): BigNumber | null {
|
|
320
|
+
return (
|
|
321
|
+
bestRoute?.result?.swaps.reduce(
|
|
322
|
+
(totalFee: BigNumber, step) =>
|
|
323
|
+
totalFee.plus(getUsdFeeOfStep(step, allTokens)),
|
|
324
|
+
ZERO
|
|
325
|
+
) || null
|
|
326
|
+
);
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
export function hasHighFee(totalFeeInUsd: BigNumber | null) {
|
|
330
|
+
if (!totalFeeInUsd) return false;
|
|
331
|
+
return !totalFeeInUsd.lt(new BigNumber(30));
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function hasSlippageError(
|
|
335
|
+
slippages: (RecommendedSlippage | null)[] | undefined
|
|
336
|
+
) {
|
|
337
|
+
return (slippages?.filter((s) => !!s?.error)?.length || 0) > 0;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
export function getMinRequiredSlippage(
|
|
341
|
+
route: BestRouteResponse
|
|
342
|
+
): number | null {
|
|
343
|
+
const slippages = route.result?.swaps.map(
|
|
344
|
+
(slippage) => slippage.recommendedSlippage
|
|
345
|
+
);
|
|
346
|
+
return (
|
|
347
|
+
slippages
|
|
348
|
+
?.map((s) => parseFloat(s?.slippage || '0'))
|
|
349
|
+
?.filter((s) => s > 0)
|
|
350
|
+
?.sort((a, b) => b - a)
|
|
351
|
+
?.find(() => true) || null
|
|
352
|
+
);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
export function hasProperSlippage(
|
|
356
|
+
userSlippage: string,
|
|
357
|
+
minRequiredSlippage: number | null
|
|
358
|
+
) {
|
|
359
|
+
if (!minRequiredSlippage) return true;
|
|
360
|
+
//@ts-ignore
|
|
361
|
+
return parseFloat(userSlippage) >= parseFloat(minRequiredSlippage);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
export function hasEnoughBalance(
|
|
365
|
+
route: BestRouteResponse,
|
|
366
|
+
selectedWallets: SelectedWallet[]
|
|
367
|
+
) {
|
|
368
|
+
const fee = route.validationStatus;
|
|
369
|
+
|
|
370
|
+
if (fee === null || fee.length === 0) return true;
|
|
371
|
+
|
|
372
|
+
for (const wallet of selectedWallets) {
|
|
373
|
+
const requiredAssets = getRequiredBalanceOfWallet(wallet, fee);
|
|
374
|
+
if (!requiredAssets) continue;
|
|
375
|
+
|
|
376
|
+
const enoughBalanceInWallet = requiredAssets
|
|
377
|
+
.map((asset) => asset.ok)
|
|
378
|
+
.reduce((previous, current) => previous && current);
|
|
379
|
+
if (!enoughBalanceInWallet) return false;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
return true;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
export function hasEnoughBalanceAndProperSlippage(
|
|
386
|
+
route: BestRouteResponse,
|
|
387
|
+
selectedWallets: SelectedWallet[],
|
|
388
|
+
userSlippage: string,
|
|
389
|
+
minRequiredSlippage: number | null
|
|
390
|
+
): boolean {
|
|
391
|
+
return (
|
|
392
|
+
hasEnoughBalance(route, selectedWallets) &&
|
|
393
|
+
hasProperSlippage(userSlippage, minRequiredSlippage)
|
|
394
|
+
);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export function createBestRouteRequestBody(
|
|
398
|
+
fromToken: Token,
|
|
399
|
+
toToken: Token,
|
|
400
|
+
inputAmount: string,
|
|
401
|
+
wallets: Account[],
|
|
402
|
+
selectedWallets: SelectedWallet[],
|
|
403
|
+
disabledLiquiditySources: string[],
|
|
404
|
+
slippage: number,
|
|
405
|
+
checkPrerequisites: boolean
|
|
406
|
+
): BestRouteRequest {
|
|
407
|
+
const selectedWalletsMap = selectedWallets.reduce(
|
|
408
|
+
(
|
|
409
|
+
selectedWalletsMap: BestRouteRequest['selectedWallets'],
|
|
410
|
+
selectedWallet
|
|
411
|
+
) => (
|
|
412
|
+
(selectedWalletsMap[selectedWallet.chain] = selectedWallet.address),
|
|
413
|
+
selectedWalletsMap
|
|
414
|
+
),
|
|
415
|
+
{}
|
|
416
|
+
);
|
|
417
|
+
|
|
418
|
+
const connectedWallets: BestRouteRequest['connectedWallets'] = [];
|
|
419
|
+
|
|
420
|
+
wallets.forEach((wallet) => {
|
|
421
|
+
const chainAndAccounts = connectedWallets.find(
|
|
422
|
+
(connectedWallet) => connectedWallet.blockchain === wallet.chain
|
|
423
|
+
);
|
|
424
|
+
if (!!chainAndAccounts) chainAndAccounts.addresses.push(wallet.address);
|
|
425
|
+
else
|
|
426
|
+
connectedWallets.push({
|
|
427
|
+
blockchain: wallet.chain,
|
|
428
|
+
addresses: [wallet.address],
|
|
429
|
+
});
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
const requestBody: BestRouteRequest = {
|
|
433
|
+
amount: inputAmount.toString(),
|
|
434
|
+
checkPrerequisites,
|
|
435
|
+
from: {
|
|
436
|
+
address: fromToken.address,
|
|
437
|
+
blockchain: fromToken.blockchain,
|
|
438
|
+
symbol: fromToken.symbol,
|
|
439
|
+
},
|
|
440
|
+
to: {
|
|
441
|
+
address: toToken.address,
|
|
442
|
+
blockchain: toToken.blockchain,
|
|
443
|
+
symbol: toToken.symbol,
|
|
444
|
+
},
|
|
445
|
+
connectedWallets,
|
|
446
|
+
selectedWallets: selectedWalletsMap,
|
|
447
|
+
swapperGroups: disabledLiquiditySources,
|
|
448
|
+
swappersGroupsExclude: true,
|
|
449
|
+
//@ts-ignore
|
|
450
|
+
slippage: slippage.toString(),
|
|
451
|
+
};
|
|
452
|
+
|
|
453
|
+
return requestBody;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
export function getWalletsForNewSwap(selectedWallets: SelectedWallet[]) {
|
|
457
|
+
const wallets = selectedWallets.reduce(
|
|
458
|
+
(
|
|
459
|
+
selectedWalletsMap: {
|
|
460
|
+
[p: string]: { address: string; walletType: WalletType };
|
|
461
|
+
},
|
|
462
|
+
selectedWallet
|
|
463
|
+
) => (
|
|
464
|
+
(selectedWalletsMap[selectedWallet.chain] = {
|
|
465
|
+
address: selectedWallet.address,
|
|
466
|
+
walletType: selectedWallet.walletType,
|
|
467
|
+
}),
|
|
468
|
+
selectedWalletsMap
|
|
469
|
+
),
|
|
470
|
+
{}
|
|
471
|
+
);
|
|
472
|
+
|
|
473
|
+
return wallets;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
export function getRouteOutputAmount(route: BestRouteResponse | null) {
|
|
477
|
+
return route?.result?.outputAmount || null;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
export function getPercentageChange(
|
|
481
|
+
oldValue: string | number | null,
|
|
482
|
+
newValue: string | number | null
|
|
483
|
+
) {
|
|
484
|
+
if (!oldValue || !newValue) return null;
|
|
485
|
+
return new BigNumber(newValue)
|
|
486
|
+
.div(new BigNumber(oldValue))
|
|
487
|
+
.minus(1)
|
|
488
|
+
.multipliedBy(100);
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
export function isOutputAmountChangedALot(
|
|
492
|
+
oldRoute: BestRouteResponse,
|
|
493
|
+
newRoute: BestRouteResponse
|
|
494
|
+
) {
|
|
495
|
+
const oldOutputAmount = getRouteOutputAmount(oldRoute);
|
|
496
|
+
const newOutputAmount = getRouteOutputAmount(newRoute);
|
|
497
|
+
if (!oldOutputAmount || !newOutputAmount) return false;
|
|
498
|
+
const percentageChange = getPercentageChange(
|
|
499
|
+
oldOutputAmount,
|
|
500
|
+
newOutputAmount
|
|
501
|
+
);
|
|
502
|
+
if (!percentageChange) return true;
|
|
503
|
+
|
|
504
|
+
return percentageChange.toNumber() <= -1;
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export function getBalanceWarnings(
|
|
508
|
+
route: BestRouteResponse,
|
|
509
|
+
selectedWallets: SelectedWallet[]
|
|
510
|
+
) {
|
|
511
|
+
const fee = route.validationStatus;
|
|
512
|
+
const requiredWallets = getRequiredChains(route);
|
|
513
|
+
const walletsSortedByRequiredWallets = selectedWallets.sort(
|
|
514
|
+
(selectedWallet1, selectedWallet2) =>
|
|
515
|
+
requiredWallets.indexOf(selectedWallet1.chain) -
|
|
516
|
+
requiredWallets.indexOf(selectedWallet2.chain)
|
|
517
|
+
);
|
|
518
|
+
return walletsSortedByRequiredWallets
|
|
519
|
+
.flatMap((wallet) => getRequiredBalanceOfWallet(wallet, fee) || [])
|
|
520
|
+
.filter((asset) => !asset.ok)
|
|
521
|
+
.map((asset) => {
|
|
522
|
+
const symbol = asset.asset.symbol;
|
|
523
|
+
const currentAmount = numberToString(
|
|
524
|
+
new BigNumber(asset.currentAmount.amount).shiftedBy(
|
|
525
|
+
-asset.currentAmount.decimals
|
|
526
|
+
),
|
|
527
|
+
8
|
|
528
|
+
);
|
|
529
|
+
const requiredAmount = numberToString(
|
|
530
|
+
new BigNumber(asset.requiredAmount.amount).shiftedBy(
|
|
531
|
+
-asset.requiredAmount.decimals
|
|
532
|
+
),
|
|
533
|
+
8
|
|
534
|
+
);
|
|
535
|
+
let reason = '';
|
|
536
|
+
if (asset.reason === 'FEE') reason = ' for network fee';
|
|
537
|
+
if (asset.reason === 'INPUT_ASSET') reason = ' for swap';
|
|
538
|
+
if (asset.reason === 'FEE_AND_INPUT_ASSET')
|
|
539
|
+
reason = ' for input and network fee';
|
|
540
|
+
const warningMessage = `Needs ≈ ${requiredAmount} ${symbol}${reason}, but you have ${currentAmount} ${symbol} in your ${asset.asset.blockchain} wallet.`;
|
|
541
|
+
return warningMessage;
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
export function calcOutputUsdValue(
|
|
546
|
+
outputAmount?: string,
|
|
547
|
+
tokenPrice?: number | null
|
|
548
|
+
) {
|
|
549
|
+
const amount = !!outputAmount ? new BigNumber(outputAmount) : ZERO;
|
|
550
|
+
|
|
551
|
+
return amount.multipliedBy(tokenPrice || 0);
|
|
552
|
+
}
|