@rango-dev/widget-embedded 0.1.10-next.69

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.
Files changed (47) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/package.json +29 -0
  3. package/public/index.html +11 -0
  4. package/readme.md +2 -0
  5. package/src/App.tsx +78 -0
  6. package/src/app.css +28 -0
  7. package/src/components/AppRouter.tsx +15 -0
  8. package/src/components/AppRoutes.tsx +32 -0
  9. package/src/components/BottomLogo.tsx +44 -0
  10. package/src/components/Footer.tsx +8 -0
  11. package/src/components/Header.tsx +25 -0
  12. package/src/components/HeaderButtons.tsx +34 -0
  13. package/src/components/Layout.tsx +55 -0
  14. package/src/components/SwitchFromAndTo.tsx +30 -0
  15. package/src/components/TokenInfo.tsx +218 -0
  16. package/src/components/UpdateUrl.tsx +85 -0
  17. package/src/constants/errors.ts +3 -0
  18. package/src/constants/navigationRoutes.ts +14 -0
  19. package/src/constants/numbers.ts +3 -0
  20. package/src/constants/searchParams.ts +7 -0
  21. package/src/globalStyles.ts +16 -0
  22. package/src/hooks/useBestRoute.ts +70 -0
  23. package/src/hooks/useConfirmSwap.ts +234 -0
  24. package/src/hooks/useTheme.ts +37 -0
  25. package/src/index.tsx +12 -0
  26. package/src/mockData/pendingSwap.ts +607 -0
  27. package/src/pages/ConfirmSwapPage.tsx +24 -0
  28. package/src/pages/ConfirmWalletsPage.tsx +51 -0
  29. package/src/pages/HistoryPage.tsx +793 -0
  30. package/src/pages/Home.tsx +176 -0
  31. package/src/pages/LiquiditySourcesPage.tsx +49 -0
  32. package/src/pages/SelectChainPage.tsx +62 -0
  33. package/src/pages/SelectTokenPage.tsx +84 -0
  34. package/src/pages/SettingsPage.tsx +60 -0
  35. package/src/pages/SwapDetailsPage.tsx +9 -0
  36. package/src/pages/WalletsPage.tsx +61 -0
  37. package/src/services/httpService.ts +3 -0
  38. package/src/store/bestRoute.ts +82 -0
  39. package/src/store/meta.ts +35 -0
  40. package/src/store/selectors.ts +19 -0
  41. package/src/store/settings.ts +72 -0
  42. package/src/store/wallets.ts +144 -0
  43. package/src/utils/common.ts +3 -0
  44. package/src/utils/numbers.ts +94 -0
  45. package/src/utils/routing.ts +108 -0
  46. package/src/utils/swap.ts +155 -0
  47. package/src/utils/wallets.ts +345 -0
@@ -0,0 +1,345 @@
1
+ import {
2
+ isEvmAddress,
3
+ Network,
4
+ WalletInfo,
5
+ WalletState,
6
+ WalletType,
7
+ } from '@rango-dev/wallets-shared';
8
+
9
+ import { WalletInfo as ModalWalletInfo, WalletState as WalletStatus } from '@rango-dev/ui';
10
+ import { BestRouteResponse, BlockchainMeta, Token, WalletDetail } from 'rango-sdk';
11
+ import { readAccountAddress } from '@rango-dev/wallets-core';
12
+ import { SelectableWallet } from '../pages/ConfirmWalletsPage';
13
+ import { Account, Balance, TokenBalance } from '../store/wallets';
14
+ import { numberToString } from './numbers';
15
+ import BigNumber from 'bignumber.js';
16
+ import { TokenWithBalance } from '../pages/SelectTokenPage';
17
+ import { ZERO } from '../constants/numbers';
18
+
19
+ export function getStateWallet(state: WalletState): WalletStatus {
20
+ switch (true) {
21
+ case state.connected:
22
+ return WalletStatus.CONNECTED;
23
+ case state.connecting:
24
+ return WalletStatus.CONNECTING;
25
+ case !state.installed:
26
+ return WalletStatus.NOT_INSTALLED;
27
+ default:
28
+ return WalletStatus.DISCONNECTED;
29
+ }
30
+ }
31
+
32
+ export function getlistWallet(
33
+ getState: (type: WalletType) => WalletState,
34
+ getWalletInfo: (type: WalletType) => WalletInfo,
35
+ list: WalletType[],
36
+ ): ModalWalletInfo[] {
37
+ const excludedWallets = [WalletType.UNKNOWN, WalletType.TERRA_STATION, WalletType.LEAP];
38
+
39
+ return list
40
+ .filter((wallet) => !excludedWallets.includes(wallet))
41
+ .map((type) => {
42
+ const { name, img: image, installLink } = getWalletInfo(type);
43
+ const state = getStateWallet(getState(type));
44
+ return {
45
+ name,
46
+ image,
47
+ installLink,
48
+ state,
49
+ type,
50
+ };
51
+ });
52
+ }
53
+
54
+ export function walletAndSupportedChainsNames(supportedChains: BlockchainMeta[]): Network[] | null {
55
+ if (!supportedChains) return null;
56
+ let walletAndSupportedChainsNames: Network[] = [];
57
+ walletAndSupportedChainsNames = supportedChains.map(
58
+ (blockchainMeta) => blockchainMeta.name as Network,
59
+ );
60
+
61
+ return walletAndSupportedChainsNames;
62
+ }
63
+
64
+ export function prepareAccountsForWalletStore(
65
+ wallet: WalletType,
66
+ accounts: string[],
67
+ evmBasedChains: string[],
68
+ supportedChainNames: Network[] | null,
69
+ ): Account[] {
70
+ const result: Account[] = [];
71
+
72
+ function addAccount(network: Network, address: string) {
73
+ const newAccount: Account = {
74
+ address,
75
+ chain: network,
76
+ walletType: wallet,
77
+ };
78
+
79
+ result.push(newAccount);
80
+ }
81
+
82
+ const supportedChains = supportedChainNames || [];
83
+
84
+ accounts.forEach((account) => {
85
+ const { address, network } = readAccountAddress(account);
86
+
87
+ const hasLimitation = supportedChains.length > 0;
88
+ const isSupported = supportedChains.includes(network);
89
+ const isUnknown = network === Network.Unknown;
90
+ const notSupportedNetworkByWallet = hasLimitation && !isSupported && !isUnknown;
91
+
92
+ // Here we check given `network` is not supported by wallet
93
+ // And also the network is known.
94
+ if (notSupportedNetworkByWallet) return;
95
+
96
+ // In some cases we can handle unknown network by checking its address
97
+ // pattern and act on it.
98
+ // Example: showing our evm compatible netwrok when the uknown network is evem.
99
+ // Otherwise, we stop executing this function.
100
+ const isUknownAndEvmBased = network === Network.Unknown && isEvmAddress(address);
101
+ if (isUnknown && !isUknownAndEvmBased) return;
102
+
103
+ const isEvmBasedChain = evmBasedChains.includes(network);
104
+
105
+ // If it's an evm network, we will add the address to all the evm chains.
106
+ if (isEvmBasedChain || isUknownAndEvmBased) {
107
+ // all evm chains are not supported in wallets, so we are adding
108
+ // only to those that are supported by wallet.
109
+ const evmChainsSupportedByWallet = supportedChains.filter((chain) =>
110
+ evmBasedChains.includes(chain),
111
+ );
112
+
113
+ evmChainsSupportedByWallet.forEach((network) => {
114
+ // EVM addresses are not case sensetive.
115
+ // Some wallets like Binance-chain return some letters in uppercase which produces bugs in our wallet state.
116
+ addAccount(network, address.toLowerCase());
117
+ });
118
+ } else {
119
+ addAccount(network, address);
120
+ }
121
+ });
122
+
123
+ return result;
124
+ }
125
+
126
+ export function getRequiredChains(route: BestRouteResponse | null) {
127
+ const wallets: string[] = [];
128
+
129
+ route?.result?.swaps.forEach((swap) => {
130
+ const currentStepFromBlockchain = swap.from.blockchain;
131
+ const currentStepToBlockchain = swap.to.blockchain;
132
+ let lastAddedWallet = wallets[wallets.length - 1];
133
+ if (currentStepFromBlockchain != lastAddedWallet) wallets.push(currentStepFromBlockchain);
134
+ lastAddedWallet = wallets[wallets.length - 1];
135
+ if (currentStepToBlockchain != lastAddedWallet) wallets.push(currentStepToBlockchain);
136
+ });
137
+ return wallets;
138
+ }
139
+
140
+ export interface SelectedWallet extends Account {}
141
+ type Blockchain = { name: string; accounts: Balance[] };
142
+
143
+ export function getSelectableWallets(
144
+ accounts: Account[],
145
+ selectedWallets: SelectedWallet[],
146
+ getWalletInfo: (type: WalletType) => WalletInfo,
147
+ requiredChains?: string[],
148
+ ) {
149
+ const connectedWallets: SelectableWallet[] = accounts.map((account) => ({
150
+ address: account.address,
151
+ walletType: account.walletType,
152
+ chain: account.chain,
153
+ image: getWalletInfo(account.walletType).img,
154
+ selected: !!selectedWallets.find((wallet) => wallet.chain === account.chain),
155
+ }));
156
+
157
+ return requiredChains
158
+ ? connectedWallets.filter((wallet) => requiredChains.includes(wallet.chain))
159
+ : removeDuplicateWallets(connectedWallets, 'walletType');
160
+ }
161
+
162
+ const removeDuplicateWallets = (arr: SelectableWallet[], key: string): SelectableWallet[] => {
163
+ return [...new Map(arr.map((item) => [item[key], item])).values()];
164
+ };
165
+
166
+ export function getBalanceFromWallet(
167
+ balances: Balance[],
168
+ chain: string,
169
+ symbol: string,
170
+ address: string | null,
171
+ ): TokenBalance | null {
172
+ if (balances.length === 0) return null;
173
+
174
+ const selectedChainBalances = balances.filter((balance) => balance.chain === chain);
175
+ if (selectedChainBalances.length === 0) return null;
176
+
177
+ return (
178
+ selectedChainBalances
179
+ .map(
180
+ (a) =>
181
+ a.balances?.find(
182
+ (bl) =>
183
+ (address !== null && bl.address === address) ||
184
+ (address === null && bl.address === address && bl.symbol === symbol),
185
+ ) || null,
186
+ )
187
+ .filter((b) => b !== null)
188
+ .sort((a, b) => parseFloat(b?.amount || '0') - parseFloat(a?.amount || '1'))
189
+ .find(() => true) || null
190
+ );
191
+ }
192
+
193
+ export function isAccountAndBalanceMatched(account: Account, balance: Balance) {
194
+ return (
195
+ account.address === balance.address &&
196
+ account.chain === balance.chain &&
197
+ account.walletType === balance.walletType
198
+ );
199
+ }
200
+
201
+ export function makeBalanceFor(
202
+ account: Account,
203
+ retrivedBalance: WalletDetail,
204
+ tokens: Token[],
205
+ ): Balance {
206
+ const { address, blockChain: chain, explorerUrl, balances = [] } = retrivedBalance;
207
+ return {
208
+ address,
209
+ chain,
210
+ loading: false,
211
+ error: false,
212
+ explorerUrl,
213
+ walletType: account.walletType,
214
+ balances:
215
+ balances?.map((tokenBalance) => ({
216
+ chain,
217
+ symbol: tokenBalance.asset.symbol,
218
+ ticker: tokenBalance.asset.symbol,
219
+ address: tokenBalance.asset.address || null,
220
+ rawAmount: tokenBalance.amount.amount,
221
+ decimal: tokenBalance.amount.decimals,
222
+ amount: new BigNumber(tokenBalance.amount.amount)
223
+ .shiftedBy(-tokenBalance.amount.decimals)
224
+ .toFixed(),
225
+ logo: '',
226
+ usdPrice:
227
+ getUsdPrice(chain, tokenBalance.asset.symbol, tokenBalance.asset.address, tokens) || null,
228
+ })) || [],
229
+ };
230
+ }
231
+
232
+ export function resetBalanceState(balance: Balance): Balance {
233
+ return { ...balance, loading: false, error: true };
234
+ }
235
+
236
+ export const calculateWalletUsdValue = (balance: Balance[]) => {
237
+ const uniqueAccountAddresses = new Set<string | null>();
238
+ const uniqueBalane: Balance[] = balance?.reduce((acc: Balance[], current: Balance) => {
239
+ return acc.findIndex((i) => i.address === current.address && i.chain === current.chain) === -1
240
+ ? [...acc, current]
241
+ : acc;
242
+ }, []);
243
+
244
+ const modifiedWalletBlockchains = uniqueBalane?.map((chain) => {
245
+ const modifiedWalletBlockchain: Blockchain = { name: chain.chain, accounts: [] };
246
+ if (!uniqueAccountAddresses.has(chain.address)) {
247
+ uniqueAccountAddresses.add(chain.address);
248
+ }
249
+ uniqueAccountAddresses.forEach((accountAddress) => {
250
+ if (chain.address === accountAddress) modifiedWalletBlockchain.accounts.push(chain);
251
+ });
252
+ return modifiedWalletBlockchain;
253
+ });
254
+ const total = numberToString(
255
+ modifiedWalletBlockchains
256
+ ?.flatMap((b) => b.accounts)
257
+ ?.flatMap((a) => a?.balances)
258
+ ?.map((b) => new BigNumber(b?.amount || ZERO).multipliedBy(b?.usdPrice || 0))
259
+ ?.reduce((a, b) => a.plus(b), ZERO) || ZERO,
260
+ ).toString();
261
+
262
+ console.log('total');
263
+ console.log(total);
264
+
265
+ return numberWithThousandSeperator(total);
266
+ };
267
+
268
+ function numberWithThousandSeperator(number: string | number): string {
269
+ var parts = number.toString().split('.');
270
+ parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ',');
271
+ return parts.join('.');
272
+ }
273
+
274
+ export const sortedTokens = (
275
+ tokens: TokenWithBalance[],
276
+ position: 'from' | 'to',
277
+ balance: Balance[],
278
+ ): TokenWithBalance[] => {
279
+ if (!tokens) return [];
280
+ const walletSymbols = new Set(
281
+ (balance || [])
282
+ .flatMap((a) => a.balances || [])
283
+ .filter((b) => (new BigNumber(b?.rawAmount) || ZERO).gt(0))
284
+ .map((b) => `${b?.chain}.${b?.symbol}.${b?.address}`),
285
+ );
286
+ let sortedList = [
287
+ ...tokens.filter((t) => !t.address && walletSymbols.size && position === 'to'),
288
+ ...tokens
289
+ .filter(
290
+ (t) =>
291
+ !(position === 'to' && !t.address) &&
292
+ walletSymbols.has(`${t.blockchain}.${t.symbol}.${t.address}`),
293
+ )
294
+ .sort((tokenA, tokenB) => compareBalance(tokenA, tokenB, balance)),
295
+ ...tokens.filter(
296
+ (t) =>
297
+ !walletSymbols.has(`${t.blockchain}.${t.symbol}.${t.address}`) &&
298
+ !t.address &&
299
+ (!walletSymbols.size || position === 'from'),
300
+ ),
301
+ ...tokens.filter(
302
+ (t) =>
303
+ !walletSymbols.has(`${t.blockchain}.${t.symbol}.${t.address}`) &&
304
+ t.address &&
305
+ !t.isSecondaryCoin,
306
+ ),
307
+ ...tokens.filter(
308
+ (t) => !walletSymbols.has(`${t.blockchain}.${t.symbol}.${t.address}`) && t.isSecondaryCoin,
309
+ ),
310
+ ];
311
+
312
+ return sortedList;
313
+ };
314
+
315
+ const compareBalance = (
316
+ tokenA: TokenWithBalance,
317
+ tokenB: TokenWithBalance,
318
+ wallet: Balance[],
319
+ ): number => {
320
+ if (!tokenA.usdPrice || !tokenB.usdPrice) return 0;
321
+
322
+ const tokenAUsdValue = new BigNumber(
323
+ getBalanceFromWallet(wallet, tokenA.blockchain, tokenA.symbol, tokenA.address)?.amount || ZERO,
324
+ ).multipliedBy(tokenA.usdPrice);
325
+ const tokenBUsdValue = new BigNumber(
326
+ getBalanceFromWallet(wallet, tokenB.blockchain, tokenB.symbol, tokenB.address)?.amount || ZERO,
327
+ ).multipliedBy(tokenB.usdPrice);
328
+ if (tokenAUsdValue.gt(tokenBUsdValue)) return -1;
329
+ return 1;
330
+ };
331
+
332
+ export const getUsdPrice = (
333
+ blockchain: string,
334
+ symbol: string,
335
+ address: string | null,
336
+ allTokens: Token[],
337
+ ): number | null => {
338
+ const token = allTokens?.find(
339
+ (t) =>
340
+ t.blockchain === blockchain &&
341
+ t.symbol?.toUpperCase() === symbol?.toUpperCase() &&
342
+ t.address === address,
343
+ );
344
+ return token?.usdPrice || null;
345
+ };