@0xsquid/react-hooks 1.0.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.
Files changed (108) hide show
  1. package/.babelrc +7 -0
  2. package/.eslintignore +1 -0
  3. package/.eslintrc.json +44 -0
  4. package/dist/index.js +6 -0
  5. package/jest.config.ts +28 -0
  6. package/package.json +124 -0
  7. package/scripts/copyAssets.js +27 -0
  8. package/scripts/removeBuildTestFolder.js +28 -0
  9. package/scripts/replacePaths.js +37 -0
  10. package/src/assets/images/icons/wallets/binance.svg +4 -0
  11. package/src/assets/images/icons/wallets/bitget.svg +43 -0
  12. package/src/assets/images/icons/wallets/bitkeep.svg +9 -0
  13. package/src/assets/images/icons/wallets/blockchaindotcom.svg +11 -0
  14. package/src/assets/images/icons/wallets/brave.svg +18 -0
  15. package/src/assets/images/icons/wallets/c98.svg +3 -0
  16. package/src/assets/images/icons/wallets/coinbase.svg +5 -0
  17. package/src/assets/images/icons/wallets/cosmostation.svg +9 -0
  18. package/src/assets/images/icons/wallets/defiConnect.svg +25 -0
  19. package/src/assets/images/icons/wallets/exodus.svg +33 -0
  20. package/src/assets/images/icons/wallets/fetchai.svg +1 -0
  21. package/src/assets/images/icons/wallets/index.ts +43 -0
  22. package/src/assets/images/icons/wallets/keplr.svg +9 -0
  23. package/src/assets/images/icons/wallets/leap.svg +35 -0
  24. package/src/assets/images/icons/wallets/metamask.svg +48 -0
  25. package/src/assets/images/icons/wallets/okx.svg +1 -0
  26. package/src/assets/images/icons/wallets/rabby.svg +1 -0
  27. package/src/assets/images/icons/wallets/trustwallet.svg +11 -0
  28. package/src/assets/images/icons/wallets/walletConnect.svg +11 -0
  29. package/src/assets/images/icons/wallets/wallet_icon.svg +1 -0
  30. package/src/assets/images/icons/wallets/xdefi.svg +9 -0
  31. package/src/assets/images/icons/wallets/zerion.svg +11 -0
  32. package/src/connectors/ExodusConnector.ts +6 -0
  33. package/src/connectors/LedgerLiveConnector.ts +226 -0
  34. package/src/contracts/typechain/ERC20.d.ts +441 -0
  35. package/src/contracts/typechain/factories/ERC20__factory.d.ts +56 -0
  36. package/src/contracts/typechain/factories/ERC20__factory.ts +340 -0
  37. package/src/core/constants.ts +549 -0
  38. package/src/core/externalLinks.ts +26 -0
  39. package/src/core/index.ts +1 -0
  40. package/src/core/multicall3.ts +22 -0
  41. package/src/core/numbers.ts +44 -0
  42. package/src/core/providers/CosmosProvider.tsx +55 -0
  43. package/src/core/queries/queries-keys.ts +156 -0
  44. package/src/core/queries/react-query-config.ts +13 -0
  45. package/src/core/types/components.ts +16 -0
  46. package/src/core/types/config.ts +52 -0
  47. package/src/core/types/dex.ts +31 -0
  48. package/src/core/types/error.ts +52 -0
  49. package/src/core/types/event.ts +16 -0
  50. package/src/core/types/route.ts +21 -0
  51. package/src/core/types/swap.ts +8 -0
  52. package/src/core/types/tokens.ts +30 -0
  53. package/src/core/types/transaction.ts +84 -0
  54. package/src/core/types/types.ts +37 -0
  55. package/src/core/types/wallet.ts +83 -0
  56. package/src/hooks/chains/useSquidChains.ts +66 -0
  57. package/src/hooks/cosmos/useCosmos.ts +279 -0
  58. package/src/hooks/cosmos/useCosmosForChain.ts +33 -0
  59. package/src/hooks/index.ts +32 -0
  60. package/src/hooks/navigation/useKeyboardNavigation.ts +88 -0
  61. package/src/hooks/store/useSquidStore.ts +80 -0
  62. package/src/hooks/swap/useSwap.ts +359 -0
  63. package/src/hooks/tokens/useAllTokensWithBalance.ts +157 -0
  64. package/src/hooks/tokens/useBalance.ts +180 -0
  65. package/src/hooks/tokens/useMultiChainBalance.ts +59 -0
  66. package/src/hooks/tokens/usePrices.ts +52 -0
  67. package/src/hooks/tokens/useSingleTokenPrice.ts +45 -0
  68. package/src/hooks/tokens/useSquidTokens.ts +48 -0
  69. package/src/hooks/tokens/useTokensWithBalance.ts +169 -0
  70. package/src/hooks/transaction/useEstimate.ts +397 -0
  71. package/src/hooks/transaction/useEstimatePriceImpact.ts +39 -0
  72. package/src/hooks/transaction/useExecuteTransaction.ts +440 -0
  73. package/src/hooks/transaction/useExpress.ts +46 -0
  74. package/src/hooks/transaction/useGetRoute.ts +145 -0
  75. package/src/hooks/transaction/useSingleTransaction.ts +155 -0
  76. package/src/hooks/transaction/useTransaction.ts +734 -0
  77. package/src/hooks/user/useUserParams.ts +63 -0
  78. package/src/hooks/wallet/useAddToken.ts +53 -0
  79. package/src/hooks/wallet/useAutoConnect.ts +56 -0
  80. package/src/hooks/wallet/useGnosisContext.ts +84 -0
  81. package/src/hooks/wallet/useIntegratorContext.ts +44 -0
  82. package/src/hooks/wallet/useMultiChainWallet.ts +146 -0
  83. package/src/hooks/wallet/useWallet.ts +86 -0
  84. package/src/hooks/webapp-router/useSquidRouter.ts +42 -0
  85. package/src/index.ts +5 -0
  86. package/src/provider/index.tsx +105 -0
  87. package/src/react-app-env.d.ts +2 -0
  88. package/src/services/external/analyticsService.ts +46 -0
  89. package/src/services/external/coingeckoService.ts +35 -0
  90. package/src/services/external/rpcService.ts +196 -0
  91. package/src/services/external/secretService.ts +178 -0
  92. package/src/services/index.ts +1 -0
  93. package/src/services/internal/apiService.ts +6 -0
  94. package/src/services/internal/assetsService.ts +84 -0
  95. package/src/services/internal/configService.ts +261 -0
  96. package/src/services/internal/errorService.ts +124 -0
  97. package/src/services/internal/eventService.ts +93 -0
  98. package/src/services/internal/priceService.ts +10 -0
  99. package/src/services/internal/transactionService.ts +255 -0
  100. package/src/services/internal/transactionStatusService.ts +293 -0
  101. package/src/services/internal/walletService.ts +158 -0
  102. package/src/tests/assetsService.test.ts +176 -0
  103. package/src/tests/configService.test.ts +486 -0
  104. package/src/tests/fetchSquidData.ts +43 -0
  105. package/src/tests/jest-svg-transform.ts +19 -0
  106. package/src/tests/sample.json +0 -0
  107. package/src/tests/walletService.test.ts +178 -0
  108. package/tsconfig.json +30 -0
@@ -0,0 +1,397 @@
1
+ import { gasRefundMultiplier } from "@/core/constants";
2
+ import { formatUnitsRounded } from "@/core/numbers";
3
+ import { useSquidStore } from "@/hooks/store/useSquidStore";
4
+ import { useNativeTokenBalanceFromChain } from "@/hooks/tokens/useBalance";
5
+ import { useSingleTokenPrice } from "@/hooks/tokens/useSingleTokenPrice";
6
+ import { useSquidTokens } from "@/hooks/tokens/useSquidTokens";
7
+ import type { Estimate, FeeCost, GasCost } from "@0xsquid/squid-types";
8
+ import { ChainType } from "@0xsquid/squid-types";
9
+ import { BigNumber, constants } from "ethers";
10
+ import { formatUnits } from "ethers/lib/utils";
11
+ import { useMemo } from "react";
12
+ import { useSquidChains } from "../chains/useSquidChains";
13
+ import { useMultiChainBalance } from "../tokens/useMultiChainBalance";
14
+ import { useGetRoute } from "./useGetRoute";
15
+
16
+ export const useEstimate = ({
17
+ squidRoute,
18
+ }: {
19
+ squidRoute: ReturnType<typeof useGetRoute>;
20
+ }) => {
21
+ const { config } = useSquidStore();
22
+ const { balance: nativeTokenBalanceFromChain } =
23
+ useNativeTokenBalanceFromChain();
24
+ const { tokens } = useSquidTokens();
25
+ const { chains } = useSquidChains();
26
+
27
+ const [fromChain, toChain] = useMemo(() => {
28
+ return [
29
+ chains.find((c) => c.chainId === squidRoute.data?.params.fromChain),
30
+ chains.find((c) => c.chainId === squidRoute.data?.params.toChain),
31
+ ];
32
+ }, [
33
+ chains,
34
+ squidRoute.data?.params.fromChain,
35
+ squidRoute.data?.params.toChain,
36
+ ]);
37
+
38
+ const fromToken = useMemo(
39
+ () => tokens.find((t) => t.address === squidRoute.data?.params.fromToken),
40
+ [tokens, squidRoute.data?.params.fromToken]
41
+ );
42
+
43
+ const balanceFormatted =
44
+ useMultiChainBalance({
45
+ chain: fromChain,
46
+ token: fromToken,
47
+ userAddress: squidRoute.data?.params.fromAddress ?? "",
48
+ enabled: !!squidRoute.data,
49
+ }).balance ?? "0";
50
+
51
+ const fromAmount = useMemo(
52
+ () => squidRoute.data?.estimate?.fromAmount ?? undefined,
53
+ [squidRoute.data?.estimate?.fromAmount]
54
+ );
55
+
56
+ const fromAmountFormatted = useMemo(
57
+ () => (fromAmount ? formatUnits(fromAmount, fromToken?.decimals) : ""),
58
+ [fromAmount, fromToken?.decimals]
59
+ );
60
+
61
+ const sourceChainNativeToken = useMemo(() => {
62
+ return tokens.find(
63
+ (t) =>
64
+ t.symbol === fromChain?.nativeCurrency.symbol &&
65
+ t.chainId == fromChain?.chainId
66
+ );
67
+ }, [tokens, fromChain]);
68
+
69
+ const destChainNativeToken = useMemo(() => {
70
+ return tokens.find(
71
+ (t) =>
72
+ t.symbol === toChain?.nativeCurrency.symbol &&
73
+ t.chainId == toChain?.chainId
74
+ );
75
+ }, [tokens, toChain]);
76
+
77
+ const toAmountUSD = useMemo(
78
+ () => squidRoute.data?.estimate?.toAmountUSD ?? undefined,
79
+ [squidRoute.data?.estimate?.toAmountUSD]
80
+ );
81
+
82
+ const toAmountUSDFloat = useMemo(
83
+ () => (toAmountUSD ? parseFloat(toAmountUSD.replace(/,/g, "")) : 0),
84
+ [toAmountUSD]
85
+ );
86
+
87
+ const exchangeRate = useMemo(
88
+ () => squidRoute.data?.estimate.exchangeRate ?? "0",
89
+ [squidRoute.data?.estimate.exchangeRate]
90
+ );
91
+
92
+ const toAmountMin = useMemo(() => {
93
+ return formatUnits(
94
+ squidRoute.data?.estimate.toAmountMin ?? "0",
95
+ squidRoute.data?.estimate.toToken.decimals
96
+ );
97
+ }, [
98
+ squidRoute.data?.estimate.toAmountMin,
99
+ squidRoute.data?.estimate.toToken.decimals,
100
+ ]);
101
+
102
+ const toAmount = useMemo(() => {
103
+ const formattedAmount = formatUnitsRounded(
104
+ squidRoute.data?.estimate.toAmount ?? "0",
105
+ squidRoute.data?.estimate.toToken.decimals,
106
+ 14
107
+ );
108
+ return formattedAmount === "0.0" ? "0" : formattedAmount;
109
+ }, [
110
+ squidRoute.data?.estimate.toAmount,
111
+ squidRoute.data?.estimate.toToken.decimals,
112
+ ]);
113
+
114
+ /**
115
+ * At the moment we're only taking the first item
116
+ * of fees array, but keeping the possibility to display multiple fees
117
+ */
118
+ const crossChainGasFee = useMemo((): FeeCost | undefined => {
119
+ const estimate = squidRoute.data?.estimate as Estimate;
120
+ return estimate?.feeCosts.length > 0 ? estimate?.feeCosts[0] : undefined;
121
+ }, [squidRoute.data?.estimate]);
122
+
123
+ const allFeeCosts = useMemo((): FeeCost[] => {
124
+ const estimate = squidRoute.data?.estimate as Estimate;
125
+ return estimate?.feeCosts ?? [];
126
+ }, [squidRoute.data?.estimate]);
127
+
128
+ const allGasCosts = useMemo((): GasCost[] => {
129
+ const estimate = squidRoute.data?.estimate as Estimate;
130
+ return estimate?.gasCosts ?? [];
131
+ }, [squidRoute.data?.estimate]);
132
+
133
+ const firstGasCost = useMemo(
134
+ (): GasCost | undefined =>
135
+ allGasCosts.length > 0 ? allGasCosts[0] : undefined,
136
+ [allGasCosts]
137
+ );
138
+
139
+ const firstFeeCost = useMemo(
140
+ (): FeeCost | undefined =>
141
+ allFeeCosts.length > 0 ? allFeeCosts[0] : undefined,
142
+ [allFeeCosts]
143
+ );
144
+
145
+ const integratorFeeCost = useMemo(
146
+ (): FeeCost | undefined =>
147
+ allFeeCosts.length > 0 && config.collectFees
148
+ ? // TODO: This is a hack to get the integrator fee, not mapped in squid types yet
149
+ allFeeCosts.find((f) => (f.name as any) === "Integrator Fee")
150
+ : undefined,
151
+ [allFeeCosts, config]
152
+ );
153
+
154
+ const { getUSDValue } = useSingleTokenPrice(firstFeeCost?.token);
155
+
156
+ const expressFeeCost = useMemo(
157
+ (): FeeCost | undefined =>
158
+ allFeeCosts.length > 0
159
+ ? allFeeCosts.find((f) => f.name === "Express Fee")
160
+ : undefined,
161
+ [allFeeCosts]
162
+ );
163
+
164
+ const expectedGasRefundCost = useMemo(
165
+ () =>
166
+ BigNumber.from(firstFeeCost?.amount ?? "0")
167
+ .mul(
168
+ // When source is Cosmos we don't refund any gas
169
+ fromChain?.chainType === ChainType.COSMOS ? 0 : gasRefundMultiplier
170
+ )
171
+ .div(100),
172
+ [firstFeeCost?.amount]
173
+ );
174
+
175
+ const sameTokenBetweenFees = useMemo(
176
+ () =>
177
+ firstFeeCost?.token.address === firstGasCost?.token.address &&
178
+ firstFeeCost?.token.chainId === firstGasCost?.token.chainId,
179
+ [
180
+ firstFeeCost?.token.address,
181
+ firstFeeCost?.token.chainId,
182
+ firstGasCost?.token.address,
183
+ firstGasCost?.token.chainId,
184
+ ]
185
+ );
186
+
187
+ // From token is the same as the native chain token
188
+ // TODO: This only works for EVM chains
189
+ const isFromTokenNative = useMemo(() => {
190
+ if (fromToken === undefined || fromChain?.chainId === undefined) {
191
+ return false;
192
+ }
193
+ return fromToken.symbol === fromChain.nativeCurrency.symbol;
194
+ }, [fromToken, fromChain]);
195
+
196
+ const totalNativeFees = useMemo(() => {
197
+ const expressBn = BigNumber.from(expressFeeCost?.amount ?? constants.Zero);
198
+ if (sameTokenBetweenFees) {
199
+ return BigNumber.from(firstFeeCost?.amount ?? constants.Zero)
200
+ .add(BigNumber.from(firstGasCost?.amount ?? constants.Zero))
201
+ .add(expressBn);
202
+ }
203
+
204
+ return BigNumber.from(firstGasCost?.amount ?? constants.Zero).add(
205
+ expressBn
206
+ );
207
+ }, [
208
+ firstFeeCost?.amount,
209
+ firstGasCost?.amount,
210
+ sameTokenBetweenFees,
211
+ expressFeeCost?.amount,
212
+ ]);
213
+
214
+ const totalFeesInNativeTokenPlusRatio = useMemo(() => {
215
+ return totalNativeFees.mul(105).div(100);
216
+ }, [totalNativeFees]);
217
+
218
+ const totalWithRefundEstimate = useMemo(() => {
219
+ const firstFee = {
220
+ BN: BigNumber.from(firstFeeCost?.amount ?? "0"),
221
+ token: firstFeeCost?.token,
222
+ };
223
+
224
+ const expressFee = {
225
+ BN: BigNumber.from(expressFeeCost?.amount ?? "0"),
226
+ token: expressFeeCost?.token,
227
+ };
228
+
229
+ // Big number amount
230
+ const totalBnbAmount = firstFee.BN.add(expressFee.BN).sub(
231
+ expectedGasRefundCost
232
+ );
233
+
234
+ const totalAmount = formatUnits(
235
+ totalBnbAmount,
236
+ firstFee.token?.decimals ?? 18
237
+ );
238
+
239
+ // USD values
240
+ const formattedRefundCost = formatUnits(
241
+ expectedGasRefundCost,
242
+ firstFeeCost?.token.decimals
243
+ );
244
+ const formattedRefundCostUSD = getUSDValue(formattedRefundCost);
245
+ const totalAmountUSD =
246
+ +(firstFeeCost?.amountUsd ?? 0) +
247
+ +(expressFeeCost?.amountUsd ?? 0) -
248
+ +(formattedRefundCostUSD ?? 0);
249
+
250
+ return {
251
+ totalAmount,
252
+ totalAmountUSD,
253
+ feeToken: firstFeeCost?.token,
254
+ };
255
+ }, [
256
+ expectedGasRefundCost,
257
+ expressFeeCost?.amount,
258
+ expressFeeCost?.amountUsd,
259
+ expressFeeCost?.token,
260
+ firstFeeCost?.amount,
261
+ firstFeeCost?.amountUsd,
262
+ firstFeeCost?.token,
263
+ getUSDValue,
264
+ ]);
265
+
266
+ /**
267
+ * Two cases:
268
+ * 1. If the source token is the same as the native token, check if the balance of native token is less than the (source amount) + (native gas)
269
+ * 2. If the source token is different from the native token, check if the balance of native token is less than (native gas)
270
+ */
271
+ const fromBalanceEnoughToSwap = useMemo(() => {
272
+ if (squidRoute.isLoading) return true;
273
+
274
+ const fromAmountWei = BigNumber.from(fromAmount ?? constants.Zero);
275
+ const fromBalance = nativeTokenBalanceFromChain.data ?? constants.Zero;
276
+
277
+ if (isFromTokenNative) {
278
+ const fromPlusGas = fromAmountWei.add(totalFeesInNativeTokenPlusRatio);
279
+ if (fromPlusGas.lte(fromBalance)) {
280
+ return true;
281
+ }
282
+ } else if (totalFeesInNativeTokenPlusRatio.lte(fromBalance)) {
283
+ return true;
284
+ }
285
+
286
+ return false;
287
+ }, [
288
+ nativeTokenBalanceFromChain.data,
289
+ fromAmount,
290
+ isFromTokenNative,
291
+ squidRoute.isLoading,
292
+ totalFeesInNativeTokenPlusRatio,
293
+ ]);
294
+
295
+ /**
296
+ * In the case where the source token is the same as the native token,
297
+ * we need to advise the user to change the source amount to be less than the balance of native token minus the gas cost
298
+ */
299
+ const minAmountValueWarnMsg = useMemo(() => {
300
+ if (!isFromTokenNative) {
301
+ return undefined;
302
+ }
303
+
304
+ const fromBalance = nativeTokenBalanceFromChain.data ?? constants.Zero;
305
+
306
+ const minAmount = fromBalance.sub(totalFeesInNativeTokenPlusRatio);
307
+
308
+ if (minAmount.gt(constants.Zero)) {
309
+ const parsedMinAmount = formatUnits(
310
+ minAmount,
311
+ sourceChainNativeToken?.decimals ?? 18
312
+ );
313
+
314
+ return parsedMinAmount;
315
+ }
316
+ return "0";
317
+ }, [
318
+ nativeTokenBalanceFromChain.data,
319
+ isFromTokenNative,
320
+ sourceChainNativeToken?.decimals,
321
+ totalFeesInNativeTokenPlusRatio,
322
+ ]);
323
+
324
+ const proposedGasDestinationAmount = useMemo(() => {
325
+ // Get native token of chain
326
+ const nativeToken = toChain?.nativeCurrency.symbol;
327
+ let gasDestinationAmount = 0;
328
+ switch (nativeToken) {
329
+ case "GLMR":
330
+ gasDestinationAmount = 5.289;
331
+ break;
332
+ case "ETH":
333
+ gasDestinationAmount = 0.0009;
334
+ break;
335
+ case "AVAX":
336
+ gasDestinationAmount = 0.115;
337
+ break;
338
+ case "BNB":
339
+ gasDestinationAmount = 0.00425;
340
+ break;
341
+ case "FTM":
342
+ gasDestinationAmount = 4.45;
343
+ break;
344
+ case "CELO":
345
+ gasDestinationAmount = 3.052;
346
+ break;
347
+ case "KAVA":
348
+ gasDestinationAmount = 2.339;
349
+ break;
350
+ case "MATIC":
351
+ gasDestinationAmount = 1.795;
352
+ break;
353
+ default:
354
+ gasDestinationAmount = 0;
355
+ break;
356
+ }
357
+ return { value: gasDestinationAmount, currency: nativeToken };
358
+ }, [toChain?.nativeCurrency.symbol]);
359
+
360
+ const enoughBalanceToSwap = useMemo(
361
+ () => +balanceFormatted >= 0 && +balanceFormatted > +fromAmountFormatted,
362
+ [balanceFormatted, fromAmountFormatted]
363
+ );
364
+
365
+ return {
366
+ allFeeCosts,
367
+ allGasCosts,
368
+ crossChainGasFee,
369
+ exchangeRate,
370
+ toAmountMin,
371
+ toAmount,
372
+ fromToken,
373
+ toAmountUSD,
374
+ toAmountUSDFloat,
375
+ isFetching: squidRoute.isLoading,
376
+ squidRouteError: squidRoute.error,
377
+ fromAmount,
378
+ fromAmountFormatted,
379
+ estimatedRouteDuration: squidRoute.data?.estimate?.estimatedRouteDuration,
380
+ minAmountValueWarnMsg,
381
+ fromBalanceEnoughToSwap,
382
+ isFromTokenNative,
383
+ firstFeeCost,
384
+ firstGasCost,
385
+ sameTokenBetweenFees,
386
+ totalFeesInNativeTokenPlusRatio,
387
+ totalNativeFees,
388
+ sourceChainNativeToken,
389
+ expressFeeCost,
390
+ proposedGasDestinationAmount,
391
+ expectedGasRefundCost,
392
+ totalWithRefundEstimate,
393
+ destChainNativeToken,
394
+ integratorFeeCost,
395
+ enoughBalanceToSwap,
396
+ };
397
+ };
@@ -0,0 +1,39 @@
1
+ import { useSquidStore } from "@/hooks/store/useSquidStore";
2
+ import { useGetRoute } from "@/hooks/transaction/useGetRoute";
3
+ import { useMemo } from "react";
4
+
5
+ export const useEstimatePriceImpact = ({
6
+ squidRoute,
7
+ }: {
8
+ squidRoute: ReturnType<typeof useGetRoute>;
9
+ }) => {
10
+ const { config } = useSquidStore();
11
+
12
+ const priceImpact = useMemo(
13
+ () => squidRoute.data?.estimate?.aggregatePriceImpact ?? undefined,
14
+ [squidRoute.data?.estimate]
15
+ );
16
+
17
+ const priceImpactStatus = useMemo(() => {
18
+ if (config.priceImpactWarnings !== undefined && priceImpact !== undefined) {
19
+ if (
20
+ +priceImpact >= config.priceImpactWarnings.warning &&
21
+ +priceImpact < config.priceImpactWarnings.critical
22
+ ) {
23
+ return "warning";
24
+ }
25
+ if (+priceImpact >= config.priceImpactWarnings.critical) {
26
+ return "critical";
27
+ }
28
+ if (+priceImpact < config.priceImpactWarnings.warning) {
29
+ return "normal";
30
+ }
31
+ }
32
+ return undefined;
33
+ }, [config.priceImpactWarnings, priceImpact]);
34
+
35
+ return {
36
+ priceImpact,
37
+ priceImpactStatus,
38
+ };
39
+ };