@rango-dev/widget-embedded 0.37.0 → 0.37.1-next.1

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 (157) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/QueueManager.d.ts.map +1 -1
  3. package/dist/components/ConfirmWalletsModal/ConfirmWalletsModal.d.ts.map +1 -1
  4. package/dist/components/ConfirmWalletsModal/WalletList.d.ts.map +1 -1
  5. package/dist/components/Layout/Layout.d.ts.map +1 -1
  6. package/dist/components/Quote/Quote.d.ts.map +1 -1
  7. package/dist/components/Quote/Quote.styles.d.ts +1 -1
  8. package/dist/components/Quote/Quote.types.d.ts +2 -0
  9. package/dist/components/Quote/Quote.types.d.ts.map +1 -1
  10. package/dist/components/Quote/QuoteCostDetails.d.ts.map +1 -1
  11. package/dist/components/Quote/QuoteCostDetails.styles.d.ts.map +1 -1
  12. package/dist/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.d.ts.map +1 -1
  13. package/dist/components/Quotes/Quotes.d.ts.map +1 -1
  14. package/dist/components/RefreshModal/RefreshModal.styles.d.ts +1 -1
  15. package/dist/components/SwapDetails/SwapDetails.d.ts.map +1 -1
  16. package/dist/components/SwapDetailsAlerts/SwapDetailsAlerts.types.d.ts +1 -1
  17. package/dist/components/SwapDetailsAlerts/SwapDetailsAlerts.types.d.ts.map +1 -1
  18. package/dist/components/SwapDetailsModal/SwapDetailsCompleteModal.d.ts.map +1 -1
  19. package/dist/components/TokenList/TokenList.d.ts.map +1 -1
  20. package/dist/components/WalletStatefulConnect/DerivationPath.helpers.d.ts +2 -1
  21. package/dist/components/WalletStatefulConnect/DerivationPath.helpers.d.ts.map +1 -1
  22. package/dist/components/WalletStatefulConnect/Namespaces.d.ts.map +1 -1
  23. package/dist/components/WalletStatefulConnect/Namespaces.types.d.ts +1 -1
  24. package/dist/components/WalletStatefulConnect/Namespaces.types.d.ts.map +1 -1
  25. package/dist/constants/quote.d.ts +10 -0
  26. package/dist/constants/quote.d.ts.map +1 -1
  27. package/dist/containers/ExpandedQuotes/ExpandedQuotes.styles.d.ts.map +1 -1
  28. package/dist/containers/Inputs/Inputs.d.ts.map +1 -1
  29. package/dist/containers/QuoteInfo/QuoteInfo.d.ts.map +1 -1
  30. package/dist/containers/Wallets/Wallets.d.ts.map +1 -1
  31. package/dist/containers/WidgetInfo/WidgetInfo.d.ts.map +1 -1
  32. package/dist/containers/WidgetInfo/WidgetInfo.helpers.d.ts +1 -1
  33. package/dist/containers/WidgetInfo/WidgetInfo.types.d.ts +3 -3
  34. package/dist/containers/WidgetInfo/WidgetInfo.types.d.ts.map +1 -1
  35. package/dist/hooks/useConfirmSwap/useConfirmSwap.d.ts.map +1 -1
  36. package/dist/hooks/useConfirmSwap/useConfirmSwap.helpers.d.ts +6 -4
  37. package/dist/hooks/useConfirmSwap/useConfirmSwap.helpers.d.ts.map +1 -1
  38. package/dist/hooks/useFetchApiConfig.d.ts.map +1 -1
  39. package/dist/hooks/useFetchCustomToken.d.ts.map +1 -1
  40. package/dist/hooks/useStatefulConnect/useStatefulConnect.d.ts +2 -1
  41. package/dist/hooks/useStatefulConnect/useStatefulConnect.d.ts.map +1 -1
  42. package/dist/hooks/useStatefulConnect/useStatefulConnect.types.d.ts +3 -5
  43. package/dist/hooks/useStatefulConnect/useStatefulConnect.types.d.ts.map +1 -1
  44. package/dist/hooks/useSubscribeToWidgetEvents/useSubscribeToWidgetEvents.d.ts.map +1 -1
  45. package/dist/hooks/useSwapInput.d.ts.map +1 -1
  46. package/dist/hooks/useWalletList.d.ts.map +1 -1
  47. package/dist/hooks/useWalletProviders/useWalletProviders.d.ts +2 -3
  48. package/dist/hooks/useWalletProviders/useWalletProviders.d.ts.map +1 -1
  49. package/dist/index.d.ts +1 -1
  50. package/dist/index.d.ts.map +1 -1
  51. package/dist/index.js +2 -2
  52. package/dist/index.js.map +4 -4
  53. package/dist/pages/ConfirmSwapPage.d.ts.map +1 -1
  54. package/dist/pages/Home.d.ts.map +1 -1
  55. package/dist/pages/SelectSwapItemsPage.d.ts.map +1 -1
  56. package/dist/store/app.d.ts +2 -4
  57. package/dist/store/app.d.ts.map +1 -1
  58. package/dist/store/quote.d.ts.map +1 -1
  59. package/dist/store/slices/config.d.ts +4 -0
  60. package/dist/store/slices/config.d.ts.map +1 -1
  61. package/dist/store/slices/data.d.ts.map +1 -1
  62. package/dist/store/slices/types.d.ts +6 -0
  63. package/dist/store/slices/types.d.ts.map +1 -0
  64. package/dist/store/slices/wallets.d.ts +80 -0
  65. package/dist/store/slices/wallets.d.ts.map +1 -0
  66. package/dist/store/ui.d.ts +4 -0
  67. package/dist/store/ui.d.ts.map +1 -1
  68. package/dist/store/utils/wallets.d.ts +17 -0
  69. package/dist/store/utils/wallets.d.ts.map +1 -0
  70. package/dist/types/config.d.ts +6 -3
  71. package/dist/types/config.d.ts.map +1 -1
  72. package/dist/types/quote.d.ts +8 -17
  73. package/dist/types/quote.d.ts.map +1 -1
  74. package/dist/types/wallets.d.ts +3 -7
  75. package/dist/types/wallets.d.ts.map +1 -1
  76. package/dist/utils/providers.d.ts +8 -9
  77. package/dist/utils/providers.d.ts.map +1 -1
  78. package/dist/utils/quote.d.ts +5 -6
  79. package/dist/utils/quote.d.ts.map +1 -1
  80. package/dist/utils/settings.d.ts +1 -0
  81. package/dist/utils/settings.d.ts.map +1 -1
  82. package/dist/utils/swap.d.ts +5 -5
  83. package/dist/utils/swap.d.ts.map +1 -1
  84. package/dist/utils/wallets.d.ts +12 -14
  85. package/dist/utils/wallets.d.ts.map +1 -1
  86. package/dist/widget-embedded.build.json +1 -1
  87. package/package.json +9 -9
  88. package/src/QueueManager.tsx +17 -11
  89. package/src/components/ConfirmWalletsModal/ConfirmWalletsModal.tsx +5 -24
  90. package/src/components/ConfirmWalletsModal/WalletList.tsx +10 -7
  91. package/src/components/Layout/Layout.tsx +1 -3
  92. package/src/components/Quote/Quote.tsx +22 -3
  93. package/src/components/Quote/Quote.types.ts +2 -0
  94. package/src/components/Quote/QuoteCostDetails.styles.ts +0 -1
  95. package/src/components/Quote/QuoteCostDetails.tsx +23 -4
  96. package/src/components/QuoteWarningsAndErrors/QuoteWarningsAndErrors.helpers.ts +42 -22
  97. package/src/components/Quotes/Quotes.tsx +2 -3
  98. package/src/components/StatefulConnectModal/StatefulConnectModal.tsx +1 -1
  99. package/src/components/SwapDetails/SwapDetails.tsx +14 -6
  100. package/src/components/SwapDetailsAlerts/SwapDetailsAlerts.types.ts +1 -1
  101. package/src/components/SwapDetailsModal/SwapDetailsCompleteModal.tsx +26 -13
  102. package/src/components/TokenList/TokenList.tsx +4 -27
  103. package/src/components/WalletStatefulConnect/DerivationPath.helpers.ts +2 -1
  104. package/src/components/WalletStatefulConnect/Namespaces.tsx +31 -38
  105. package/src/components/WalletStatefulConnect/Namespaces.types.tsx +1 -1
  106. package/src/constants/quote.ts +25 -0
  107. package/src/containers/ExpandedQuotes/ExpandedQuotes.styles.ts +1 -0
  108. package/src/containers/ExpandedQuotes/ExpandedQuotes.tsx +1 -1
  109. package/src/containers/Inputs/Inputs.tsx +20 -7
  110. package/src/containers/QuoteInfo/QuoteInfo.tsx +3 -9
  111. package/src/containers/Wallets/Wallets.tsx +82 -16
  112. package/src/containers/WidgetInfo/WidgetInfo.helpers.ts +2 -2
  113. package/src/containers/WidgetInfo/WidgetInfo.tsx +10 -8
  114. package/src/containers/WidgetInfo/WidgetInfo.types.ts +3 -3
  115. package/src/hooks/useConfirmSwap/useConfirmSwap.helpers.ts +29 -66
  116. package/src/hooks/useConfirmSwap/useConfirmSwap.ts +10 -15
  117. package/src/hooks/useFetchApiConfig.ts +5 -1
  118. package/src/hooks/useFetchCustomToken.ts +5 -0
  119. package/src/hooks/useStatefulConnect/useStatefulConnect.ts +50 -17
  120. package/src/hooks/useStatefulConnect/useStatefulConnect.types.ts +3 -5
  121. package/src/hooks/useSubscribeToWidgetEvents/useSubscribeToWidgetEvents.ts +7 -6
  122. package/src/hooks/useSwapInput.ts +3 -11
  123. package/src/hooks/useWalletList.ts +6 -8
  124. package/src/hooks/useWalletProviders/useWalletProviders.ts +8 -12
  125. package/src/index.ts +1 -1
  126. package/src/pages/ConfirmSwapPage.tsx +7 -15
  127. package/src/pages/Home.tsx +5 -3
  128. package/src/pages/SelectSwapItemsPage.tsx +1 -2
  129. package/src/store/app.ts +4 -4
  130. package/src/store/quote.ts +3 -13
  131. package/src/store/slices/config.ts +76 -0
  132. package/src/store/slices/data.test.ts +23 -1
  133. package/src/store/slices/data.ts +3 -2
  134. package/src/store/slices/types.ts +9 -0
  135. package/src/store/slices/wallets.ts +577 -0
  136. package/src/store/ui.ts +6 -0
  137. package/src/store/utils/wallets.ts +111 -0
  138. package/src/types/config.ts +7 -3
  139. package/src/types/quote.ts +10 -24
  140. package/src/types/wallets.ts +3 -7
  141. package/src/utils/providers.ts +88 -36
  142. package/src/utils/quote.ts +57 -45
  143. package/src/utils/settings.ts +4 -0
  144. package/src/utils/swap.ts +56 -37
  145. package/src/utils/wallets.ts +76 -141
  146. package/dist/constants/warnings.d.ts +0 -3
  147. package/dist/constants/warnings.d.ts.map +0 -1
  148. package/dist/hooks/useObserveBalanceChanges/index.d.ts +0 -2
  149. package/dist/hooks/useObserveBalanceChanges/index.d.ts.map +0 -1
  150. package/dist/hooks/useObserveBalanceChanges/useObserveBalanceChanges.d.ts +0 -4
  151. package/dist/hooks/useObserveBalanceChanges/useObserveBalanceChanges.d.ts.map +0 -1
  152. package/dist/store/wallets.d.ts +0 -66
  153. package/dist/store/wallets.d.ts.map +0 -1
  154. package/src/constants/warnings.ts +0 -26
  155. package/src/hooks/useObserveBalanceChanges/index.ts +0 -1
  156. package/src/hooks/useObserveBalanceChanges/useObserveBalanceChanges.ts +0 -68
  157. package/src/store/wallets.ts +0 -268
@@ -0,0 +1,111 @@
1
+ import type { Balance } from '../../types';
2
+ import type { AppStoreState } from '../app';
3
+ import type {
4
+ AggregatedBalanceState,
5
+ AssetKey,
6
+ BalanceKey,
7
+ BalanceState,
8
+ } from '../slices/wallets';
9
+ import type { Asset, WalletDetail } from 'rango-types';
10
+
11
+ import BigNumber from 'bignumber.js';
12
+
13
+ import { ZERO } from '../../constants/numbers';
14
+
15
+ /**
16
+ * Note: We need to use `symbol` as well since native coins and cosmos blockchains don't have `address`
17
+ * output format: BlockchainId-TokenAddress-TokenSymbol
18
+ */
19
+ export function createAssetKey(asset: Asset): AssetKey {
20
+ return `${asset.blockchain}-${asset.address}-${asset.symbol}`;
21
+ }
22
+
23
+ /**
24
+ * output format: BlockchainId-TokenAddress-TokenSymbol-WalletAddress
25
+ */
26
+ export function createBalanceKey(
27
+ accountAddress: string,
28
+ asset: Asset
29
+ ): BalanceKey {
30
+ const assetKey = createAssetKey(asset);
31
+ return `${assetKey}-${accountAddress}`;
32
+ }
33
+
34
+ export function extractAssetFromBalanceKey(key: BalanceKey): Asset {
35
+ const [assetChain, assetAddress, assetSymbol] = key.split('-');
36
+
37
+ // null will be serialized to 'null', we need to make it back to a null type
38
+ const address = assetAddress === 'null' ? null : assetAddress;
39
+ return {
40
+ address,
41
+ blockchain: assetChain,
42
+ symbol: assetSymbol,
43
+ };
44
+ }
45
+
46
+ export function createBalanceStateForNewAccount(
47
+ account: WalletDetail,
48
+ store: () => AppStoreState
49
+ ): BalanceState {
50
+ const state: BalanceState = {};
51
+
52
+ account.balances?.forEach((accountBalance) => {
53
+ const key = createBalanceKey(account.address, accountBalance.asset);
54
+ const amount = accountBalance.amount.amount;
55
+ const decimals = accountBalance.amount.decimals;
56
+
57
+ const usdPrice = store().findToken(accountBalance.asset)?.usdPrice;
58
+ const usdValue = usdPrice
59
+ ? new BigNumber(usdPrice ?? ZERO).multipliedBy(amount).toString()
60
+ : '';
61
+
62
+ const balance: Balance = {
63
+ amount,
64
+ decimals,
65
+ usdValue,
66
+ };
67
+
68
+ state[key] = balance;
69
+ });
70
+
71
+ return state;
72
+ }
73
+
74
+ export function updateAggregatedBalanceStateForNewAccount(
75
+ aggregatedBalances: AggregatedBalanceState,
76
+ balanceState: BalanceState
77
+ ) {
78
+ for (const balanceKey in balanceState) {
79
+ const asset = extractAssetFromBalanceKey(balanceKey as BalanceKey);
80
+ const assetKey = createAssetKey(asset);
81
+
82
+ if (!aggregatedBalances[assetKey]) {
83
+ aggregatedBalances[assetKey] = [];
84
+ }
85
+
86
+ if (!aggregatedBalances[assetKey].includes(balanceKey as BalanceKey)) {
87
+ aggregatedBalances[assetKey] = [
88
+ ...aggregatedBalances[assetKey],
89
+ balanceKey as BalanceKey,
90
+ ];
91
+ }
92
+ }
93
+
94
+ return aggregatedBalances;
95
+ }
96
+
97
+ export function removeBalanceFromAggregatedBalance(
98
+ aggregatedBalances: AggregatedBalanceState,
99
+ balanceKey: BalanceKey
100
+ ) {
101
+ const asset = extractAssetFromBalanceKey(balanceKey);
102
+ const assetKey = createAssetKey(asset);
103
+
104
+ if (aggregatedBalances[assetKey]) {
105
+ aggregatedBalances[assetKey] = aggregatedBalances[assetKey].filter(
106
+ (aggregatedBalance) => aggregatedBalance !== balanceKey
107
+ );
108
+ }
109
+
110
+ return aggregatedBalances;
111
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Language, theme } from '@rango-dev/ui';
2
- import type { ProviderInterface } from '@rango-dev/wallets-react';
2
+ import type { LegacyProviderInterface } from '@rango-dev/wallets-core/dist/legacy/mod';
3
3
  import type { WalletType } from '@rango-dev/wallets-shared';
4
4
  import type { Asset } from 'rango-sdk';
5
5
 
@@ -129,6 +129,9 @@ export type SignersConfig = {
129
129
  *
130
130
  * @property {'visible' | 'hidden'} [liquiditySource]
131
131
  * - The visibility state for the liquiditySource feature. Optional property.
132
+ *
133
+ * @property {'disabled' | 'enabled'} [experimentalWallet]
134
+ * - Enable our experimental version of wallets. Default: disable on production, enabled on dev.
132
135
  */
133
136
  export type Features = Partial<
134
137
  Record<
@@ -140,7 +143,8 @@ export type Features = Partial<
140
143
  | 'customTokens',
141
144
  'visible' | 'hidden'
142
145
  >
143
- >;
146
+ > &
147
+ Partial<Record<'experimentalWallet', 'disabled' | 'enabled'>>;
144
148
 
145
149
  /**
146
150
  * `Routing`
@@ -253,7 +257,7 @@ export type WidgetConfig = {
253
257
  from?: BlockchainAndTokenConfig;
254
258
  to?: BlockchainAndTokenConfig;
255
259
  liquiditySources?: string[];
256
- wallets?: (WalletType | ProviderInterface)[];
260
+ wallets?: (WalletType | LegacyProviderInterface)[];
257
261
  multiWallets?: boolean;
258
262
  customDestination?: boolean;
259
263
  defaultCustomDestinations?: { [blockchain: string]: string };
@@ -51,29 +51,9 @@ export enum QuoteWarningType {
51
51
  UNKNOWN_PRICE,
52
52
  INSUFFICIENT_SLIPPAGE,
53
53
  HIGH_SLIPPAGE,
54
+ EXCESSIVE_OUTPUT_AMOUNT_CHANGE,
54
55
  }
55
56
 
56
- export enum QuoteUpdateType {
57
- QUOTE_UPDATED,
58
- QUOTE_SWAPPERS_UPDATED,
59
- QUOTE_COINS_UPDATED,
60
- QUOTE_AND_OUTPUT_AMOUNT_UPDATED,
61
- QUOTE_UPDATED_WITH_HIGH_VALUE_LOSS,
62
- }
63
-
64
- export type QuoteUpdateWarning =
65
- | {
66
- type: QuoteUpdateType.QUOTE_AND_OUTPUT_AMOUNT_UPDATED;
67
- newOutputAmount: string;
68
- percentageChange: string;
69
- }
70
- | {
71
- type: Exclude<
72
- QuoteUpdateType,
73
- QuoteUpdateType.QUOTE_AND_OUTPUT_AMOUNT_UPDATED
74
- >;
75
- };
76
-
77
57
  export type RecommendedSlippages = Map<number, string>;
78
58
 
79
59
  export type InsufficientSlippageWarning = {
@@ -100,15 +80,21 @@ export type UnknownPriceWarning = {
100
80
  type: QuoteWarningType.UNKNOWN_PRICE;
101
81
  };
102
82
 
83
+ export type ExcessiveOutputAmountChange = {
84
+ type: QuoteWarningType.EXCESSIVE_OUTPUT_AMOUNT_CHANGE;
85
+ usdValueChange: string;
86
+ percentageChange: string;
87
+ };
88
+
103
89
  export type QuoteWarning =
104
90
  | HighValueLossWarning
91
+ | ExcessiveOutputAmountChange
92
+ | UnknownPriceWarning
105
93
  | InsufficientSlippageWarning
106
- | HighSlippageWarning
107
- | UnknownPriceWarning;
94
+ | HighSlippageWarning;
108
95
 
109
96
  export type ConfirmSwapWarnings = {
110
97
  quote: QuoteWarning | null;
111
- quoteUpdate: QuoteUpdateWarning | null;
112
98
  balance: { messages: string[] } | null;
113
99
  };
114
100
 
@@ -1,5 +1,5 @@
1
1
  import type { WalletInfo } from '@rango-dev/ui';
2
- import type { Namespace, WalletType } from '@rango-dev/wallets-shared';
2
+ import type { WalletType } from '@rango-dev/wallets-shared';
3
3
 
4
4
  export interface Wallet {
5
5
  chain: string;
@@ -10,7 +10,7 @@ export interface Wallet {
10
10
  export type Balance = {
11
11
  amount: string;
12
12
  decimals: number;
13
- usdValue: string;
13
+ usdValue: string | null;
14
14
  };
15
15
 
16
16
  export type Blockchain = string;
@@ -24,8 +24,4 @@ export type TokensBalance = {
24
24
  [key: TokenHash]: Balance;
25
25
  };
26
26
 
27
- export type WalletInfoWithExtra = WalletInfo & {
28
- namespaces?: Namespace[];
29
- singleNamespace?: boolean;
30
- needsDerivationPath?: boolean;
31
- };
27
+ export type WalletInfoWithExtra = WalletInfo;
@@ -1,7 +1,12 @@
1
1
  import type { WidgetConfig } from '../types';
2
- import type { ProviderInterface } from '@rango-dev/wallets-react';
2
+ import type { LegacyProviderInterface } from '@rango-dev/wallets-core/legacy';
3
3
 
4
- import { allProviders } from '@rango-dev/provider-all';
4
+ import {
5
+ defineVersions,
6
+ pickVersion,
7
+ Provider,
8
+ type VersionedProviders,
9
+ } from '@rango-dev/wallets-core';
5
10
 
6
11
  export interface ProvidersOptions {
7
12
  walletConnectProjectId?: WidgetConfig['walletConnectProjectId'];
@@ -10,71 +15,118 @@ export interface ProvidersOptions {
10
15
  >['walletConnectListedDesktopWalletLink'];
11
16
  trezorManifest: WidgetConfig['trezorManifest'];
12
17
  tonConnect: WidgetConfig['tonConnect'];
18
+ experimentalWallet?: 'enabled' | 'disabled';
13
19
  }
14
20
 
15
21
  /**
16
22
  *
17
23
  * Generate a list of providers by passing a provider name (e.g. metamask) or a custom provider which implemented ProviderInterface.
18
- * @returns ProviderInterface[] a list of ProviderInterface
24
+ * @returns BothProvidersInterface[] a list of BothProvidersInterface
19
25
  *
20
26
  */
21
- export function matchAndGenerateProviders(
22
- providers: WidgetConfig['wallets'],
23
- options?: ProvidersOptions
24
- ): ProviderInterface[] {
25
- const all = allProviders({
26
- walletconnect2: {
27
- WC_PROJECT_ID: options?.walletConnectProjectId || '',
28
- DISABLE_MODAL_AND_OPEN_LINK:
29
- options?.walletConnectListedDesktopWalletLink,
30
- },
31
- selectedProviders: providers,
32
- trezor: options?.trezorManifest
33
- ? { manifest: options.trezorManifest }
34
- : undefined,
35
- tonConnect: options?.tonConnect?.manifestUrl
36
- ? { manifestUrl: options?.tonConnect.manifestUrl }
37
- : undefined,
38
- });
39
-
40
- if (providers) {
41
- const selectedProviders: ProviderInterface[] = [];
27
+ type BothProvidersInterface = LegacyProviderInterface | Provider;
28
+ export function matchAndGenerateProviders({
29
+ allProviders,
30
+ configWallets,
31
+ options,
32
+ }: {
33
+ allProviders: VersionedProviders[];
34
+ configWallets: WidgetConfig['wallets'];
35
+ options?: ProvidersOptions;
36
+ }): VersionedProviders[] {
37
+ if (configWallets) {
38
+ /*
39
+ * If `wallets` is included in widget config,
40
+ * allProviders should be filtered based on wallets list
41
+ */
42
+ const selectedProviders: VersionedProviders[] = [];
42
43
 
43
- providers.forEach((requestedProvider) => {
44
+ configWallets.forEach((requestedWallet) => {
44
45
  /*
45
46
  * There are two types of provider we get, the first one is only passing the wallet name
46
47
  * then we will match the wallet name with our providers (@rango-dev/provider-*).
47
48
  * The second way is passing a custom provider which implemented ProviderInterface.
48
49
  */
49
- if (typeof requestedProvider === 'string') {
50
- const result: ProviderInterface | undefined = all.find((provider) => {
51
- return provider.config.type === requestedProvider;
50
+ if (typeof requestedWallet === 'string') {
51
+ const result = allProviders.find((provider) => {
52
+ /*
53
+ * To find a provider in allProviders,
54
+ * a version of each provider should be picked
55
+ * and validated based on that version scheme.
56
+ * If the corresponding provider to a wallet was found in allProvider,
57
+ * it will be add to selected providers.
58
+ */
59
+ const versionedProvider = pickProviderVersionWithFallbackToLegacy(
60
+ provider,
61
+ options
62
+ );
63
+ if (versionedProvider instanceof Provider) {
64
+ return versionedProvider.id === requestedWallet;
65
+ }
66
+ return versionedProvider.config.type === requestedWallet;
52
67
  });
68
+
69
+ /*
70
+ * A provider may have multiple versions
71
+ * (e.g., 0.0, also known as legacy, and 1.0, also known as hub).
72
+ * We should ensure that all existing versions of a provider are added to selectedProviders.
73
+ */
53
74
  if (result) {
54
75
  selectedProviders.push(result);
55
76
  } else {
56
77
  console.warn(
57
- `Couldn't find ${requestedProvider} provider. Please make sure you are passing the correct name.`
78
+ // A provider name is included in config but was not found in allProviders
79
+ `Couldn't find ${requestedWallet} provider. Please make sure you are passing the correct name.`
58
80
  );
59
81
  }
60
82
  } else {
61
83
  // It's a custom provider so we directly push it to the list.
62
- selectedProviders.push(requestedProvider);
84
+ if (requestedWallet instanceof Provider) {
85
+ selectedProviders.push(
86
+ defineVersions().version('1.0.0', requestedWallet).build()
87
+ );
88
+ } else {
89
+ selectedProviders.push(
90
+ defineVersions().version('0.0.0', requestedWallet).build()
91
+ );
92
+ }
63
93
  }
64
94
  });
95
+
65
96
  return selectedProviders;
66
97
  }
67
98
 
68
- return all;
99
+ return allProviders;
100
+ }
101
+
102
+ function pickProviderVersionWithFallbackToLegacy(
103
+ provider: VersionedProviders,
104
+ options?: ProvidersOptions
105
+ ): BothProvidersInterface {
106
+ const { experimentalWallet = 'enabled' } = options || {};
107
+ const version = experimentalWallet == 'disabled' ? '0.0.0' : '1.0.0';
108
+
109
+ try {
110
+ return pickVersion(provider, version)[1];
111
+ } catch {
112
+ // Fallback to legacy version, if target version doesn't exists.
113
+ return pickVersion(provider, '0.0.0')[1];
114
+ }
69
115
  }
70
116
 
71
117
  export function configWalletsToWalletName(
72
- config: WidgetConfig['wallets'],
118
+ providers: VersionedProviders[],
73
119
  options?: ProvidersOptions
74
120
  ): string[] {
75
- const providers = matchAndGenerateProviders(config, options);
76
- const names = providers.map((provider) => {
77
- return provider.config.type;
78
- });
121
+ const names = providers
122
+ .map((provider) =>
123
+ pickProviderVersionWithFallbackToLegacy(provider, options)
124
+ )
125
+ .map((provider) => {
126
+ if (provider instanceof Provider) {
127
+ return provider.id;
128
+ }
129
+ return provider.config.type;
130
+ });
79
131
  return names;
80
132
  }
@@ -15,7 +15,6 @@ import type {
15
15
  MultiRouteSimulationResult,
16
16
  PreferenceType,
17
17
  RouteTag,
18
- Token,
19
18
  } from 'rango-sdk';
20
19
  import type { PendingSwap } from 'rango-types';
21
20
 
@@ -29,30 +28,19 @@ import { QuoteWarningType } from '../types';
29
28
 
30
29
  import { areEqual } from './common';
31
30
  import { createTokenHash, findBlockchain } from './meta';
31
+ import { numberToString } from './numbers';
32
32
  import {
33
- calcOutputUsdValue,
34
33
  checkSlippageWarnings,
35
34
  getMinRequiredSlippage,
36
35
  getPercentageChange,
37
36
  getTotalFeeInUsd,
37
+ getUsdInputFrom,
38
+ getUsdOutputFrom,
38
39
  hasHighValueLoss,
39
40
  hasProperSlippage,
41
+ isOutputAmountChangedExcessively,
40
42
  } from './swap';
41
43
 
42
- export function getQuoteToTokenUsdPrice(
43
- quote: SelectedQuote | null
44
- ): number | null | undefined {
45
- const swaps = quote?.swaps || [];
46
- return swaps[swaps.length - 1].to.usdPrice;
47
- }
48
-
49
- export function getQuoteFromTokenUsdPrice(
50
- quote: SelectedQuote | null
51
- ): number | null | undefined {
52
- const swaps = quote?.swaps || [];
53
- return swaps[0].from.usdPrice;
54
- }
55
-
56
44
  export function isNumberOfSwapsChanged(
57
45
  quoteA: SelectedQuote,
58
46
  quoteB: SelectedQuote
@@ -195,56 +183,73 @@ export function createRetryQuote(
195
183
  };
196
184
  }
197
185
 
198
- export function generateQuoteWarnings(
199
- quote: SelectedQuote,
200
- params: {
201
- fromToken: Token;
202
- toToken: Token;
203
- findToken: FindToken;
204
- userSlippage: number;
205
- }
206
- ): QuoteWarning | null {
207
- const { fromToken, toToken, findToken, userSlippage } = params;
208
- const inputUsdValue = calcOutputUsdValue(
209
- quote.requestAmount,
210
- getQuoteFromTokenUsdPrice(quote) || fromToken?.usdPrice
211
- );
212
- const outputUsdValue = calcOutputUsdValue(
213
- quote.outputAmount,
214
- getQuoteToTokenUsdPrice(quote) || toToken?.usdPrice
215
- );
216
-
217
- if (!!quote && inputUsdValue && outputUsdValue) {
186
+ export function generateQuoteWarnings(params: {
187
+ previousQuote?: SelectedQuote;
188
+ currentQuote: SelectedQuote;
189
+ findToken: FindToken;
190
+ userSlippage: number;
191
+ }): QuoteWarning | null {
192
+ const { previousQuote, currentQuote, findToken, userSlippage } = params;
193
+ const usdInput = getUsdInputFrom(currentQuote);
194
+ const usdOutput = getUsdOutputFrom(currentQuote);
195
+
196
+ if (!!currentQuote && usdInput && usdOutput) {
218
197
  const priceImpact = getPriceImpact(
219
- inputUsdValue.toString(),
220
- outputUsdValue.toString()
198
+ usdInput.toString(),
199
+ usdOutput.toString()
221
200
  );
222
201
  const highValueLoss =
223
- !!priceImpact && hasHighValueLoss(inputUsdValue, priceImpact);
202
+ !!priceImpact && hasHighValueLoss(usdInput, priceImpact);
224
203
 
225
204
  if (highValueLoss) {
226
- const totalFee = getTotalFeeInUsd(quote?.swaps, findToken);
205
+ const totalFee = getTotalFeeInUsd(currentQuote?.swaps, findToken);
227
206
  const warningLevel = getPriceImpactLevel(priceImpact);
228
207
  return {
229
208
  type: QuoteWarningType.HIGH_VALUE_LOSS,
230
- inputUsdValue,
231
- outputUsdValue,
209
+ inputUsdValue: usdInput,
210
+ outputUsdValue: usdOutput,
232
211
  priceImpact,
233
212
  totalFee,
234
213
  warningLevel,
235
214
  };
236
215
  }
237
- } else if (quote && (!inputUsdValue || !outputUsdValue)) {
216
+ }
217
+
218
+ if (
219
+ previousQuote &&
220
+ isOutputAmountChangedExcessively(previousQuote, currentQuote)
221
+ ) {
222
+ return {
223
+ type: QuoteWarningType.EXCESSIVE_OUTPUT_AMOUNT_CHANGE,
224
+ usdValueChange: numberToString(
225
+ getUsdOutputFrom(currentQuote)
226
+ ?.minus(getUsdOutputFrom(previousQuote) ?? 0)
227
+ .toString() ?? '0',
228
+ null,
229
+ 2
230
+ ),
231
+ percentageChange: numberToString(
232
+ getPriceImpact(
233
+ getUsdOutputFrom(previousQuote) ?? '1',
234
+ getUsdOutputFrom(currentQuote) ?? '1'
235
+ ),
236
+ null,
237
+ 2
238
+ ),
239
+ };
240
+ }
241
+
242
+ if (currentQuote && (!usdInput || !usdOutput)) {
238
243
  return { type: QuoteWarningType.UNKNOWN_PRICE };
239
244
  }
240
245
 
241
- const minRequiredSlippage = getMinRequiredSlippage(quote.swaps);
246
+ const minRequiredSlippage = getMinRequiredSlippage(currentQuote.swaps);
242
247
  const highSlippage = userSlippage > HIGH_SLIPPAGE;
243
248
 
244
249
  if (!hasProperSlippage(params.userSlippage.toString(), minRequiredSlippage)) {
245
250
  return {
246
251
  type: QuoteWarningType.INSUFFICIENT_SLIPPAGE,
247
- recommendedSlippages: checkSlippageWarnings(quote, userSlippage),
252
+ recommendedSlippages: checkSlippageWarnings(currentQuote, userSlippage),
248
253
  minRequiredSlippage: minRequiredSlippage,
249
254
  };
250
255
  } else if (
@@ -260,6 +265,13 @@ export function generateQuoteWarnings(
260
265
  return null;
261
266
  }
262
267
 
268
+ export function isQuoteWarningConfirmationRequired(warning: QuoteWarning) {
269
+ const WARNINGS_NOT_REQUIRING_CONFIRMATION = [
270
+ QuoteWarningType.EXCESSIVE_OUTPUT_AMOUNT_CHANGE,
271
+ ];
272
+ return !WARNINGS_NOT_REQUIRING_CONFIRMATION.includes(warning.type);
273
+ }
274
+
263
275
  export function getPriceImpact(
264
276
  inputUsdValue: BigNumber | string | null,
265
277
  outputUsdValue: BigNumber | string | null
@@ -72,6 +72,10 @@ export function isFeatureHidden(feature: keyof Features, features?: Features) {
72
72
  return features?.[feature] === 'hidden';
73
73
  }
74
74
 
75
+ export function isFeatureEnabled(feature: keyof Features, features?: Features) {
76
+ return features?.[feature] === 'enabled';
77
+ }
78
+
75
79
  export function isRoutingEnabled(item: keyof Routing, routing?: Routing) {
76
80
  return routing?.[item] === 'enabled';
77
81
  }