@ensofinance/checkout-widget 0.0.12 → 0.0.14

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 (149) hide show
  1. package/dist/checkout-widget.es.js +14486 -13826
  2. package/dist/checkout-widget.es.js.map +1 -1
  3. package/dist/checkout-widget.umd.js +44 -43
  4. package/dist/checkout-widget.umd.js.map +1 -1
  5. package/dist/index.d.ts +7 -0
  6. package/orval.config.ts +40 -6
  7. package/package.json +1 -1
  8. package/src/components/BridgeFee.tsx +3 -3
  9. package/src/components/Checkout.tsx +5 -53
  10. package/src/components/ExchangeConfirmSecurity.tsx +16 -3
  11. package/src/components/QuoteParameters.tsx +84 -65
  12. package/src/components/TransactionDetailRow.tsx +6 -5
  13. package/src/components/cards/AssetCard.tsx +2 -2
  14. package/src/components/cards/OptionCard.tsx +2 -0
  15. package/src/components/steps/ExchangeFlow.tsx +414 -135
  16. package/src/components/steps/{InitialStep.tsx → FlowSelector.tsx} +76 -33
  17. package/src/components/steps/WalletFlow/WalletAmountStep.tsx +214 -0
  18. package/src/components/steps/{WalletConfirmStep.tsx → WalletFlow/WalletConfirmStep.tsx} +107 -156
  19. package/src/components/steps/WalletFlow/WalletFlow.tsx +116 -0
  20. package/src/components/steps/{QuoteStep.tsx → WalletFlow/WalletQuoteStep.tsx} +9 -58
  21. package/src/components/steps/WalletFlow/WalletTokenStep.tsx +75 -0
  22. package/src/components/ui/index.tsx +0 -3
  23. package/src/enso-api/api.ts +192 -3
  24. package/src/enso-api/custom-instance.ts +1 -0
  25. package/src/enso-api/index.ts +29 -118
  26. package/src/enso-api/model/approveActionDto.ts +17 -0
  27. package/src/enso-api/model/approveArgsDto.ts +22 -0
  28. package/src/enso-api/model/approveArgsDtoAmount.ts +16 -0
  29. package/src/enso-api/model/balanceActionDto.ts +17 -0
  30. package/src/enso-api/model/balanceArgsDto.ts +15 -0
  31. package/src/enso-api/model/borrowActionDto.ts +18 -0
  32. package/src/enso-api/model/borrowArgsDto.ts +22 -0
  33. package/src/enso-api/model/borrowArgsDtoAmountOut.ts +16 -0
  34. package/src/enso-api/model/bridgeActionDto.ts +19 -0
  35. package/src/enso-api/model/bridgeArgsDto.ts +29 -0
  36. package/src/enso-api/model/bridgeArgsDtoAmountIn.ts +16 -0
  37. package/src/enso-api/model/bridgeArgsDtoCallbackItem.ts +64 -0
  38. package/src/enso-api/model/bundleControllerBundleShortcutTransactionBodyItem.ts +69 -0
  39. package/src/enso-api/model/callActionDto.ts +18 -0
  40. package/src/enso-api/model/callArgsDto.ts +29 -0
  41. package/src/enso-api/model/callArgsDtoArgsItem.ts +17 -0
  42. package/src/enso-api/model/callArgsDtoArgsItemAnyOf.ts +12 -0
  43. package/src/enso-api/model/callArgsDtoValue.ts +16 -0
  44. package/src/enso-api/model/callOutput.ts +15 -0
  45. package/src/enso-api/model/depositActionDto.ts +18 -0
  46. package/src/enso-api/model/depositArgsDto.ts +28 -0
  47. package/src/enso-api/model/depositArgsDtoAmountIn.ts +20 -0
  48. package/src/enso-api/model/depositArgsDtoAmountInOneOfItem.ts +13 -0
  49. package/src/enso-api/model/depositArgsDtoTokenIn.ts +15 -0
  50. package/src/enso-api/model/depositArgsDtoTokenOut.ts +15 -0
  51. package/src/enso-api/model/depositCLMMActionDto.ts +18 -0
  52. package/src/enso-api/model/depositCLMMArgsDto.ts +30 -0
  53. package/src/enso-api/model/depositCLMMArgsDtoAmountInItem.ts +17 -0
  54. package/src/enso-api/model/depositCLMMArgsDtoAmountInItemAnyOf.ts +12 -0
  55. package/src/enso-api/model/ensoFeeActionDto.ts +17 -0
  56. package/src/enso-api/model/ensoFeeArgsDto.ts +20 -0
  57. package/src/enso-api/model/ensoFeeArgsDtoAmount.ts +16 -0
  58. package/src/enso-api/model/feeActionDto.ts +17 -0
  59. package/src/enso-api/model/feeArgsDto.ts +22 -0
  60. package/src/enso-api/model/feeArgsDtoAmount.ts +16 -0
  61. package/src/enso-api/model/harvestActionDto.ts +19 -0
  62. package/src/enso-api/model/harvestArgsDto.ts +17 -0
  63. package/src/enso-api/model/index.ts +115 -4
  64. package/src/enso-api/model/mergeActionDto.ts +17 -0
  65. package/src/enso-api/model/mergeArgsDto.ts +22 -0
  66. package/src/enso-api/model/mergeArgsDtoAmountInItem.ts +13 -0
  67. package/src/enso-api/model/minAmountOutActionDto.ts +17 -0
  68. package/src/enso-api/model/minAmountOutArgsDto.ts +19 -0
  69. package/src/enso-api/model/minAmountOutArgsDtoAmountOut.ts +16 -0
  70. package/src/enso-api/model/minAmountOutArgsDtoMinAmountOut.ts +16 -0
  71. package/src/enso-api/model/multiDepositActionDto.ts +18 -0
  72. package/src/enso-api/model/multiDepositArgsDto.ts +24 -0
  73. package/src/enso-api/model/multiDepositArgsDtoAmountInItem.ts +17 -0
  74. package/src/enso-api/model/multiDepositArgsDtoAmountInItemAnyOf.ts +12 -0
  75. package/src/enso-api/model/multiOutSingleDepositActionDto.ts +18 -0
  76. package/src/enso-api/model/multiOutSingleDepositArgsDto.ts +24 -0
  77. package/src/enso-api/model/multiOutSingleDepositArgsDtoAmountIn.ts +16 -0
  78. package/src/enso-api/model/multiRedeemActionDto.ts +18 -0
  79. package/src/enso-api/model/multiRedeemArgs2Dto.ts +24 -0
  80. package/src/enso-api/model/multiRedeemArgs2DtoAmountIn.ts +16 -0
  81. package/src/enso-api/model/nontokenizedControllerRouteNontokenizedShorcutTransactionParams.ts +8 -0
  82. package/src/enso-api/model/nontokenizedControllerRouteNontokenizedShorcutTransactionRoutingStrategy.ts +1 -0
  83. package/src/enso-api/model/nontokenizedRouteShortcutTransaction.ts +31 -0
  84. package/src/enso-api/model/paymasterFeeActionDto.ts +17 -0
  85. package/src/enso-api/model/paymasterFeeArgsDto.ts +18 -0
  86. package/src/enso-api/model/paymasterFeeArgsDtoAmount.ts +16 -0
  87. package/src/enso-api/model/permitTransferFromActionDto.ts +18 -0
  88. package/src/enso-api/model/permitTransferFromArgsDto.ts +29 -0
  89. package/src/enso-api/model/permitTransferFromArgsDtoAmount.ts +20 -0
  90. package/src/enso-api/model/permitTransferFromArgsDtoAmountOneOfItem.ts +13 -0
  91. package/src/enso-api/model/permitTransferFromArgsDtoToken.ts +15 -0
  92. package/src/enso-api/model/positionModel.ts +14 -0
  93. package/src/enso-api/model/redeemActionDto.ts +18 -0
  94. package/src/enso-api/model/redeemArgsDto.ts +25 -0
  95. package/src/enso-api/model/redeemArgsDtoAmountIn.ts +16 -0
  96. package/src/enso-api/model/redeemArgsDtoTokenOut.ts +15 -0
  97. package/src/enso-api/model/redeemCLMMActionDto.ts +18 -0
  98. package/src/enso-api/model/redeemCLMMArgsDto.ts +24 -0
  99. package/src/enso-api/model/redeemCLMMArgsDtoLiquidity.ts +16 -0
  100. package/src/enso-api/model/repayActionDto.ts +18 -0
  101. package/src/enso-api/model/repayArgsDto.ts +22 -0
  102. package/src/enso-api/model/repayArgsDtoAmountIn.ts +16 -0
  103. package/src/enso-api/model/routeActionDto.ts +20 -0
  104. package/src/enso-api/model/routeArgsDto.ts +38 -0
  105. package/src/enso-api/model/routeArgsDtoAmountIn.ts +16 -0
  106. package/src/enso-api/model/singleDepositActionDto.ts +18 -0
  107. package/src/enso-api/model/singleDepositArgsDto.ts +24 -0
  108. package/src/enso-api/model/singleDepositArgsDtoAmountIn.ts +16 -0
  109. package/src/enso-api/model/singleRedeemActionDto.ts +18 -0
  110. package/src/enso-api/model/singleRedeemArgs2Dto.ts +24 -0
  111. package/src/enso-api/model/singleRedeemArgs2DtoAmountIn.ts +16 -0
  112. package/src/enso-api/model/slippageActionDto.ts +17 -0
  113. package/src/enso-api/model/slippageArgsDto.ts +18 -0
  114. package/src/enso-api/model/slippageArgsDtoAmountOut.ts +16 -0
  115. package/src/enso-api/model/splitActionDto.ts +17 -0
  116. package/src/enso-api/model/splitArgsDto.ts +22 -0
  117. package/src/enso-api/model/splitArgsDtoAmountIn.ts +16 -0
  118. package/src/enso-api/model/swapActionDto.ts +18 -0
  119. package/src/enso-api/model/swapArgsDto.ts +30 -0
  120. package/src/enso-api/model/swapArgsDtoAmountIn.ts +16 -0
  121. package/src/enso-api/model/tokenizedMultiDepositActionDto.ts +18 -0
  122. package/src/enso-api/model/tokenizedMultiDepositArgsDto.ts +24 -0
  123. package/src/enso-api/model/tokenizedMultiDepositArgsDtoAmountInItem.ts +17 -0
  124. package/src/enso-api/model/tokenizedMultiDepositArgsDtoAmountInItemAnyOf.ts +14 -0
  125. package/src/enso-api/model/tokenizedMultiRedeemActionDto.ts +18 -0
  126. package/src/enso-api/model/tokenizedMultiRedeemArgsDto.ts +24 -0
  127. package/src/enso-api/model/tokenizedMultiRedeemArgsDtoAmountIn.ts +16 -0
  128. package/src/enso-api/model/tokenizedSingleDepositActionDto.ts +18 -0
  129. package/src/enso-api/model/tokenizedSingleDepositArgsDto.ts +24 -0
  130. package/src/enso-api/model/tokenizedSingleDepositArgsDtoAmountIn.ts +16 -0
  131. package/src/enso-api/model/tokenizedSingleRedeemActionDto.ts +18 -0
  132. package/src/enso-api/model/tokenizedSingleRedeemArgsDto.ts +24 -0
  133. package/src/enso-api/model/tokenizedSingleRedeemArgsDtoAmountIn.ts +16 -0
  134. package/src/enso-api/model/tokensControllerTokensLiquidityType.ts +19 -0
  135. package/src/enso-api/model/tokensControllerTokensParams.ts +6 -0
  136. package/src/enso-api/model/transferActionDto.ts +18 -0
  137. package/src/enso-api/model/transferArgsDto.ts +22 -0
  138. package/src/enso-api/model/transferArgsDtoAmount.ts +16 -0
  139. package/src/enso-api/model/transferFromActionDto.ts +18 -0
  140. package/src/enso-api/model/transferFromArgsDto.ts +24 -0
  141. package/src/enso-api/model/transferFromArgsDtoAmount.ts +16 -0
  142. package/src/index.ts +1 -0
  143. package/src/store.ts +13 -5
  144. package/src/types/index.ts +9 -3
  145. package/src/util/common.tsx +4 -1
  146. package/src/util/enso-hooks.tsx +137 -14
  147. package/src/util/wallet.tsx +2 -69
  148. package/src/components/steps/WalletAmountStep.tsx +0 -267
  149. package/src/components/steps/WalletTokenStep.tsx +0 -128
@@ -1,13 +1,77 @@
1
- import { useAccount, useWalletClient } from "wagmi";
1
+ import { useAccount, useWalletClient, useReadContract } from "wagmi";
2
2
  import { useCapabilities, useSendCalls } from "wagmi/experimental";
3
- import { Address } from "viem";
3
+ import { Address, parseAbiItem } from "viem";
4
4
  import { useCallback, useMemo } from "react";
5
- import { useEnsoToken, useEnsoPrice, useEnsoData } from "@/enso-api/api";
5
+ import {
6
+ useEnsoToken,
7
+ useEnsoPrice,
8
+ useTokenizedRouteData,
9
+ useSmartAccountBalance,
10
+ useIsNontokenized,
11
+ useNontokenizedRouteData,
12
+ } from "@/enso-api/api";
6
13
  import { getWalletDisplayName, getWalletIcon } from "@/util/wallet";
7
14
  import { formatUSD, normalizeValue } from "@/util";
8
15
  import { useAppStore } from "@/store";
9
16
  import { VITALIK_ADDRESS } from "./constants";
10
17
 
18
+ export function getERC4337CloneFactory(chainId: ChainIds): AddressArg {
19
+ return "0x1a59347d28f64091079fa04a2cbd03da63dff154";
20
+ }
21
+
22
+ const GET_SMART_ADDRESS = parseAbiItem(
23
+ "function getAddress(address) external view returns (address)",
24
+ );
25
+
26
+ export const useSmartAccountAddress = (
27
+ ownerAddress?: Address,
28
+ chainId?: number,
29
+ ) => {
30
+ const factoryAddress = getERC4337CloneFactory(chainId);
31
+
32
+ const {
33
+ data: smartAccountAddress,
34
+ isLoading,
35
+ error,
36
+ } = useReadContract({
37
+ address: factoryAddress as Address,
38
+ abi: [GET_SMART_ADDRESS],
39
+ functionName: "getAddress",
40
+ args: ownerAddress ? [ownerAddress] : undefined,
41
+ chainId,
42
+ query: {
43
+ enabled: !!(factoryAddress && ownerAddress && chainId),
44
+ },
45
+ });
46
+
47
+ return {
48
+ smartAccountAddress: smartAccountAddress as Address | undefined,
49
+ isLoading,
50
+ };
51
+ };
52
+
53
+ export const useSmartAccountBalances = (chainId: number = 1) => {
54
+ const { address } = useAccount();
55
+
56
+ // Get smart account address for the given chain
57
+ const { smartAccountAddress, isLoading: isLoadingSmartAccount } =
58
+ useSmartAccountAddress(address, chainId);
59
+
60
+ // Get balances from smart account
61
+ const {
62
+ holdingsList,
63
+ total,
64
+ isLoading: isLoadingBalances,
65
+ } = useSmartAccountBalance(smartAccountAddress);
66
+
67
+ return {
68
+ smartAccountAddress,
69
+ holdingsList,
70
+ total,
71
+ isLoading: isLoadingSmartAccount || isLoadingBalances,
72
+ };
73
+ };
74
+
11
75
  export const useAppDetails = () => {
12
76
  const { address = VITALIK_ADDRESS } = useAccount();
13
77
  const amountIn = useAppStore((state) => state.amountIn);
@@ -16,7 +80,9 @@ export const useAppDetails = () => {
16
80
  const slippage = useAppStore((state) => state.slippage);
17
81
  const chainIdIn = useAppStore((state) => state.chainIdIn);
18
82
  const chainIdOut = useAppStore((state) => state.chainIdOut);
19
- const isCheckout = useAppStore((state) => state.isCheckout);
83
+ const selectedIntegration = useAppStore(
84
+ (state) => state.selectedIntegration,
85
+ );
20
86
 
21
87
  const {
22
88
  data: [tokenInData],
@@ -27,6 +93,42 @@ export const useAppDetails = () => {
27
93
  const { data: tokenInPrice } = useEnsoPrice(chainIdIn, tokenIn);
28
94
  const { data: tokenOutPrice } = useEnsoPrice(chainIdOut, tokenOut);
29
95
 
96
+ const { isNontokenized, nontokenizedData } = useIsNontokenized(
97
+ tokenOut,
98
+ chainIdOut,
99
+ );
100
+
101
+ // Use underlying tokens if target is nontokenized, otherwise use tokenOutData
102
+ const effectiveTokenOutData = useMemo(() => {
103
+ if (isNontokenized && nontokenizedData?.underlyingTokens) {
104
+ // Map underlying tokens to Token format with logoURI
105
+ const underlyingTokens = nontokenizedData.underlyingTokens.map(
106
+ (token) => ({
107
+ ...token,
108
+ logoURI: token.logosUri?.[0],
109
+ }),
110
+ );
111
+
112
+ // Return first underlying token as primary, with all underlyingTokens available
113
+ return {
114
+ ...underlyingTokens[0],
115
+ underlyingTokens,
116
+ protocol: nontokenizedData.protocol,
117
+ name:
118
+ nontokenizedData.protocol + " " + underlyingTokens[0].name,
119
+ isNontokenized: true,
120
+ };
121
+ }
122
+
123
+ return tokenOutData;
124
+ }, [isNontokenized, nontokenizedData, tokenOutData]);
125
+
126
+ const nontokenizedPrice = useEnsoPrice(
127
+ chainIdOut,
128
+ effectiveTokenOutData?.address,
129
+ );
130
+ const effectivePrice = isNontokenized ? nontokenizedPrice : tokenOutPrice;
131
+
30
132
  return {
31
133
  chainIdIn,
32
134
  chainIdOut,
@@ -39,7 +141,10 @@ export const useAppDetails = () => {
39
141
  tokenOutPrice,
40
142
  tokenIn,
41
143
  tokenOut,
42
- isCheckout,
144
+ selectedIntegration,
145
+ effectiveTokenOutData,
146
+ effectivePrice,
147
+ isNontokenized,
43
148
  };
44
149
  };
45
150
 
@@ -59,7 +164,7 @@ export const useSendTxns = ({
59
164
  // const useFallback = !atomicOkay; // one-line policy; tweak to taste
60
165
  const wallet = useWalletClient();
61
166
 
62
- console.log(caps, atomicOkay);
167
+ console.log(caps, atomicOkay, wallet.data);
63
168
 
64
169
  const sendTxns = useCallback(
65
170
  async (
@@ -147,16 +252,12 @@ export const useRouteData = () => {
147
252
  tokenInPrice,
148
253
  tokenIn,
149
254
  tokenOut,
150
- isCheckout,
255
+ selectedIntegration,
256
+ isNontokenized,
151
257
  } = useAppDetails();
152
258
 
153
- const {
154
- data: routeData,
155
- isLoading,
156
- error,
157
- isFetched,
158
- } = useEnsoData({
159
- routingStrategy: isCheckout ? "checkout" : "router",
259
+ const standardRoute = useTokenizedRouteData({
260
+ routingStrategy: selectedIntegration?.type ? "checkout" : "router",
160
261
  fromAddress: address,
161
262
  receiver: address,
162
263
  spender: address,
@@ -166,8 +267,30 @@ export const useRouteData = () => {
166
267
  slippage,
167
268
  chainId: chainIdIn,
168
269
  outChainId: chainIdOut,
270
+ enabled: !isNontokenized,
169
271
  });
170
272
 
273
+ const nontokenizedRoute = useNontokenizedRouteData({
274
+ routingStrategy: selectedIntegration?.type ? "checkout" : "router",
275
+ fromAddress: address,
276
+ receiver: address,
277
+ spender: address,
278
+ amountIn,
279
+ tokenIn,
280
+ positionOut: tokenOut,
281
+ slippage,
282
+ chainId: chainIdIn,
283
+ outChainId: chainIdOut,
284
+ enabled: isNontokenized,
285
+ });
286
+
287
+ const {
288
+ data: routeData,
289
+ isLoading,
290
+ error,
291
+ isFetched,
292
+ } = isNontokenized ? nontokenizedRoute : standardRoute;
293
+
171
294
  const usdAmountIn = useMemo(
172
295
  () =>
173
296
  formatUSD(
@@ -1,25 +1,11 @@
1
- import {
2
- ReactElement,
3
- ReactNode,
4
- useCallback,
5
- useEffect,
6
- useState,
7
- } from "react";
8
- import {
9
- useAccount,
10
- useBalance,
11
- useReadContract,
12
- useSendTransaction,
13
- UseSimulateContractParameters,
14
- } from "wagmi";
1
+ import { ReactElement, useCallback, useEffect, useState } from "react";
2
+ import { useAccount, useBalance, useReadContract } from "wagmi";
15
3
  import { Address, isAddress, erc20Abi } from "viem";
16
4
  import { WalletIcon } from "lucide-react";
17
5
  import { useQueryClient } from "@tanstack/react-query";
18
- import { RouteData } from "@ensofinance/sdk";
19
6
  import { usePriorityChainId } from "./common";
20
7
  import { ETH_ADDRESS, SupportedChainId } from "@/util/constants";
21
8
  import { compareCaseInsensitive } from "@/util/index";
22
- import { toaster } from "@/components/ui/toaster";
23
9
 
24
10
  import metamaskIcon from "@/assets/metamask.png";
25
11
  import rabbyIcon from "@/assets/rabby.png";
@@ -139,40 +125,6 @@ export const useAllowance = (token: Address, spender: Address) => {
139
125
  };
140
126
  };
141
127
 
142
- export const useExtendedSendTransaction = ({
143
- title,
144
- args,
145
- onSuccess,
146
- crosschain,
147
- }: {
148
- title: string;
149
- args: UseSimulateContractParameters;
150
- onSuccess?: (hash: string) => void;
151
- crosschain?: boolean;
152
- }) => {
153
- const sendTransaction = useSendTransaction();
154
-
155
- const send = useCallback(() => {
156
- sendTransaction.sendTransaction(args, {
157
- onError: (error) => {
158
- toaster.create({
159
- title: "Error",
160
- // @ts-ignore
161
- description: error?.cause?.shortMessage || error.message,
162
- type: "error",
163
- });
164
- console.error(error);
165
- },
166
- onSuccess,
167
- });
168
- }, [sendTransaction, args, onSuccess]);
169
-
170
- return {
171
- ...sendTransaction,
172
- send,
173
- };
174
- };
175
-
176
128
  export const useIsApproveNeeded = (
177
129
  tokenIn: Address,
178
130
  target: Address = "0xF75584eF6673aD213a685a1B58Cc0330B8eA22Cf",
@@ -193,25 +145,6 @@ export const useIsApproveNeeded = (
193
145
  };
194
146
  };
195
147
 
196
- export const useSendEnsoTransaction = ({
197
- args,
198
- title,
199
- crosschain,
200
- onSuccess,
201
- }: {
202
- args: RouteData["tx"];
203
- title: string;
204
- crosschain?: boolean;
205
- onSuccess?: (hash: string) => void;
206
- }) => {
207
- return useExtendedSendTransaction({
208
- title,
209
- args,
210
- crosschain,
211
- onSuccess,
212
- });
213
- };
214
-
215
148
  /**
216
149
  * Get the appropriate wallet icon based on the connector name
217
150
  * @param connectorName - The name of the wallet connector
@@ -1,267 +0,0 @@
1
- import { Box, Icon, Text } from "@chakra-ui/react";
2
- import { HeaderWrapper, HeaderTitle, BodyWrapper } from "../ui/styled";
3
- import { ChevronLeft, X, ArrowDownUpIcon } from "lucide-react";
4
- import { useContext, useState, useEffect, useMemo } from "react";
5
- import { Address } from "viem";
6
- import Modal from "../modal";
7
- import { CheckoutContext } from "../Checkout";
8
- import { Button, IconButton, Tab, Input } from "../ui";
9
- import CurrencySwapDisplay from "../CurrencySwapDisplay";
10
- import { useEnsoPrice, useEnsoToken } from "@/enso-api/api";
11
- import { useAppStore } from "@/store";
12
- import {
13
- normalizeValue,
14
- denormalizeValue,
15
- formatNumber,
16
- formatUSD,
17
- } from "@/util";
18
- import { useTokenBalance } from "@/util/wallet";
19
-
20
- type InputMode = "usd" | "token";
21
-
22
- const percentageOptions = [
23
- { label: "25%", value: 25 },
24
- { label: "50%", value: 50 },
25
- { label: "75%", value: 75 },
26
- { label: "Max", value: 100 },
27
- ];
28
-
29
- const WalletAmountStep = ({ nextStep }: { nextStep?: string }) => {
30
- const { handleClose, setStep } = useContext(CheckoutContext);
31
- const [usdValue, setUsdValue] = useState<string>("10.10");
32
- // const [tokenAmount, setTokenAmount] = useState<string>("");
33
- const [inputMode, setInputMode] = useState<InputMode>("usd");
34
-
35
- const tokenIn = useAppStore((state) => state.tokenIn);
36
- const tokenOut = useAppStore((state) => state.tokenOut);
37
- const chainIdOut = useAppStore((state) => state.chainIdOut);
38
- const chainIdIn = useAppStore((state) => state.chainIdIn);
39
- const setAmountIn = useAppStore((state) => state.setAmountIn);
40
- const amountIn = useAppStore((state) => state.amountIn);
41
- const [initialLoad, setInitialLoad] = useState(true);
42
-
43
- const {
44
- data: [tokenDetails],
45
- } = useEnsoToken(tokenIn, chainIdIn);
46
- const {
47
- data: [tokenOutDetails],
48
- } = useEnsoToken(tokenOut, chainIdOut);
49
- const { data: priceData } = useEnsoPrice(chainIdIn, tokenIn);
50
-
51
- const tokenValue = useMemo(() => {
52
- return normalizeValue(amountIn, tokenDetails?.decimals);
53
- }, [amountIn, tokenDetails?.decimals]);
54
-
55
- const balanceIn = useTokenBalance(tokenIn as Address, chainIdIn);
56
-
57
- // Handle percentage selection
58
- const handlePercentageSelect = (percent: number) => {
59
- if (!balanceIn || !priceData || !tokenDetails?.decimals) {
60
- setUsdValue("0.00");
61
- return;
62
- }
63
-
64
- const amountToSet = (
65
- (BigInt(balanceIn) * BigInt(percent)) /
66
- BigInt(100)
67
- ).toString();
68
-
69
- setAmountIn(amountToSet);
70
- setUsdValue(
71
- (
72
- +normalizeValue(amountToSet, tokenDetails?.decimals) * priceData
73
- ).toFixed(2),
74
- );
75
- };
76
-
77
- useEffect(() => {
78
- if (initialLoad && priceData && tokenDetails && +balanceIn > 0) {
79
- setInitialLoad(false);
80
- handlePercentageSelect(100);
81
- }
82
- }, [balanceIn, initialLoad, priceData, tokenDetails, balanceIn]);
83
-
84
- // Handle input change based on current mode
85
- const handleInputChange = (value: string) => {
86
- if (inputMode === "usd") {
87
- const cleanUsd = value.replace("$", "");
88
- // Clean the input from usd sign
89
- console.log(cleanUsd, priceData, tokenDetails?.decimals);
90
- setUsdValue(cleanUsd);
91
- setAmountIn(
92
- denormalizeValue(
93
- (parseFloat(cleanUsd) / priceData).toString(),
94
- tokenDetails?.decimals,
95
- ),
96
- );
97
- } else {
98
- setAmountIn(denormalizeValue(value, tokenDetails?.decimals));
99
- setUsdValue((parseFloat(value) * priceData).toFixed(2));
100
- }
101
- };
102
-
103
- // Toggle between USD and token input modes
104
- const handleToggleMode = () => {
105
- setInputMode(inputMode === "usd" ? "token" : "usd");
106
- };
107
-
108
- // Get input placeholder and display value
109
- const getInputDisplay = () => {
110
- const formattedValue = formatNumber(tokenValue);
111
- const safeUsdValue = parseFloat(usdValue) > 0 ? usdValue : 0;
112
-
113
- if (inputMode === "usd") {
114
- return {
115
- placeholder: "$10.00",
116
- displayValue: safeUsdValue ? `$${safeUsdValue}` : "",
117
- equivalentValue: tokenValue
118
- ? `${formattedValue} ${tokenDetails?.symbol}`
119
- : "—",
120
- };
121
- }
122
-
123
- return {
124
- placeholder: "0.00",
125
- displayValue: formattedValue,
126
- equivalentValue: formatUSD(safeUsdValue),
127
- };
128
- };
129
-
130
- const { placeholder, displayValue, equivalentValue } = getInputDisplay();
131
- const notEnoughBalance = +balanceIn < +amountIn;
132
-
133
- return (
134
- <>
135
- <Modal.Header>
136
- <HeaderWrapper>
137
- <IconButton
138
- minWidth={"16px"}
139
- minHeight={"16px"}
140
- maxWidth={"16px"}
141
- onClick={() => setStep("selectToken")}
142
- >
143
- <Icon
144
- as={ChevronLeft}
145
- color="gray"
146
- width={"16px"}
147
- height={"16px"}
148
- />
149
- </IconButton>
150
-
151
- <Box display="flex" flexDirection="column" gap={"4px"}>
152
- <HeaderTitle>Deposit</HeaderTitle>
153
- </Box>
154
-
155
- {handleClose && (
156
- <IconButton
157
- onClick={handleClose}
158
- width={"40px"}
159
- marginLeft={"auto"}
160
- >
161
- <Icon
162
- as={X}
163
- color="gray"
164
- width={"16px"}
165
- height={"16px"}
166
- />
167
- </IconButton>
168
- )}
169
- </HeaderWrapper>
170
- </Modal.Header>
171
-
172
- <Modal.Body>
173
- <BodyWrapper>
174
- <Box display={"flex"} flexDirection={"column"} gap={"8px"}>
175
- <Box
176
- display={"flex"}
177
- flexDirection={"column"}
178
- gap={"8px"}
179
- alignItems={"center"}
180
- padding={"25.5px"}
181
- >
182
- {/* Main Input */}
183
- <Input
184
- inputMode="decimal"
185
- marginY={"8px"}
186
- variant={"text"}
187
- placeholder={placeholder}
188
- value={displayValue}
189
- onChange={(e) =>
190
- handleInputChange(e.target.value)
191
- }
192
- />
193
-
194
- {/* Toggle Button and Equivalent Display */}
195
- <Box
196
- display={"flex"}
197
- gap={"3"}
198
- alignItems={"center"}
199
- onClick={handleToggleMode}
200
- _hover={{ background: "bg.subtle" }}
201
- cursor={"pointer"}
202
- borderRadius={"lg"}
203
- px={"3"}
204
- >
205
- <IconButton
206
- minWidth={"24px"}
207
- minHeight={"24px"}
208
- maxWidth={"24px"}
209
- background={"transparent"}
210
- >
211
- <Icon
212
- as={ArrowDownUpIcon}
213
- color="gray"
214
- width={"16px"}
215
- height={"16px"}
216
- />
217
- </IconButton>
218
-
219
- {/* Small equivalent value display */}
220
- <Text fontSize="sm" color="fg.muted">
221
- {equivalentValue}
222
- </Text>
223
- </Box>
224
- </Box>
225
- <Box
226
- display={"flex"}
227
- gap={"4px"}
228
- justifyContent={"center"}
229
- paddingBottom={"35px"}
230
- >
231
- {percentageOptions.map((option) => (
232
- <Tab
233
- key={option.label}
234
- onClick={() =>
235
- handlePercentageSelect(option.value)
236
- }
237
- >
238
- {option.label}
239
- </Tab>
240
- ))}
241
- </Box>
242
- </Box>
243
-
244
- <CurrencySwapDisplay
245
- tokenOut={tokenOutDetails}
246
- tokenIn={tokenDetails}
247
- chainIdIn={chainIdIn}
248
- chainIdOut={chainIdOut}
249
- />
250
-
251
- <Button
252
- onClick={() =>
253
- notEnoughBalance
254
- ? undefined
255
- : setStep(nextStep ?? "quote")
256
- }
257
- disabled={notEnoughBalance}
258
- >
259
- Continue
260
- </Button>
261
- </BodyWrapper>
262
- </Modal.Body>
263
- </>
264
- );
265
- };
266
-
267
- export default WalletAmountStep;
@@ -1,128 +0,0 @@
1
- import { Box, Icon, Skeleton } from "@chakra-ui/react";
2
- import {
3
- HeaderWrapper,
4
- HeaderTitle,
5
- HeaderDescription,
6
- ListWrapper,
7
- BodyWrapper,
8
- } from "../ui/styled";
9
- import { ChevronLeft, X } from "lucide-react";
10
- import { useContext, useEffect } from "react";
11
- import Modal from "../modal";
12
- import { CheckoutContext } from "../Checkout";
13
- import { Button, IconButton } from "../ui";
14
- import { AssetCard } from "../cards";
15
- import { useAppStore } from "@/store";
16
- import { useWalletBalance } from "@/enso-api/api";
17
- import { formatNumber, formatUSD, normalizeValue } from "@/util";
18
-
19
- const SelectTokenStep = () => {
20
- const { handleClose, setFlow, setStep } = useContext(CheckoutContext);
21
- const setIsCheckout = useAppStore((state) => state.setIsCheckout);
22
- const setTokenIn = useAppStore((state) => state.setTokenIn);
23
- const tokenIn = useAppStore((state) => state.tokenIn);
24
- const setChainIdIn = useAppStore((state) => state.setChainIdIn);
25
- const chainIdIn = useAppStore((state) => state.chainIdIn);
26
- const { holdingsList, total, isLoading } = useWalletBalance();
27
-
28
- useEffect(() => {
29
- setIsCheckout(false);
30
- }, []);
31
-
32
- return (
33
- <>
34
- <Modal.Header>
35
- <HeaderWrapper>
36
- <IconButton
37
- minWidth={"16px"}
38
- minHeight={"16px"}
39
- maxWidth={"16px"}
40
- onClick={() => {
41
- setFlow("");
42
- setStep("");
43
- }}
44
- >
45
- <Icon
46
- as={ChevronLeft}
47
- color="gray"
48
- width={"16px"}
49
- height={"16px"}
50
- />
51
- </IconButton>
52
- <Box display="flex" flexDirection="column" gap={"4px"}>
53
- <HeaderTitle>Deposit</HeaderTitle>
54
- <HeaderDescription>
55
- Balance: {formatUSD(total)}
56
- </HeaderDescription>
57
- </Box>
58
- {handleClose && (
59
- <IconButton
60
- onClick={handleClose}
61
- width={"40px"}
62
- marginLeft={"auto"}
63
- >
64
- <Icon
65
- as={X}
66
- color="gray"
67
- width={"16px"}
68
- height={"16px"}
69
- />
70
- </IconButton>
71
- )}
72
- </HeaderWrapper>
73
- </Modal.Header>
74
-
75
- <Modal.Body>
76
- <BodyWrapper>
77
- <Box overflowY={"scroll"} maxH={"400px"}>
78
- <ListWrapper>
79
- {isLoading
80
- ? Array.from({ length: 10 }).map((_, index) => (
81
- <Skeleton
82
- key={index}
83
- height="40px"
84
- width="300px"
85
- />
86
- ))
87
- : holdingsList?.map((asset) => (
88
- <AssetCard
89
- key={`${asset.token}-${asset.chainId}`}
90
- chainId={asset.chainId}
91
- icon={asset.logoUri}
92
- title={asset.name}
93
- balance={`${formatNumber(
94
- normalizeValue(
95
- asset.amount,
96
- asset.decimals,
97
- ),
98
- )} ${asset.symbol}`}
99
- usdBalance={formatUSD(asset.total)}
100
- tag={""}
101
- loading={false}
102
- selected={
103
- asset.token === tokenIn &&
104
- asset.chainId === chainIdIn
105
- }
106
- onClick={() => {
107
- setTokenIn(asset.token);
108
- setChainIdIn(asset.chainId);
109
- }}
110
- />
111
- ))}
112
- </ListWrapper>
113
- </Box>
114
- <Button
115
- onClick={() => {
116
- setStep("selectAmount");
117
- }}
118
- disabled={!tokenIn}
119
- >
120
- Continue
121
- </Button>
122
- </BodyWrapper>
123
- </Modal.Body>
124
- </>
125
- );
126
- };
127
-
128
- export default SelectTokenStep;