thirdweb 5.87.3 → 5.88.0-nightly-e50d77d28fd866efdfce706b73320541d260728d-20250208000322

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 (169) hide show
  1. package/dist/cjs/client/client.js +2 -1
  2. package/dist/cjs/client/client.js.map +1 -1
  3. package/dist/cjs/contract/deployment/zksync/implementations.js +3 -0
  4. package/dist/cjs/contract/deployment/zksync/implementations.js.map +1 -1
  5. package/dist/cjs/contract/deployment/zksync/zkDeployContract.js +4 -2
  6. package/dist/cjs/contract/deployment/zksync/zkDeployContract.js.map +1 -1
  7. package/dist/cjs/pay/buyWithCrypto/getQuote.js +4 -14
  8. package/dist/cjs/pay/buyWithCrypto/getQuote.js.map +1 -1
  9. package/dist/cjs/pay/buyWithCrypto/getTransfer.js +1 -13
  10. package/dist/cjs/pay/buyWithCrypto/getTransfer.js.map +1 -1
  11. package/dist/cjs/pay/buyWithFiat/getQuote.js.map +1 -1
  12. package/dist/cjs/pay/utils/commonTypes.js +2 -0
  13. package/dist/cjs/pay/utils/commonTypes.js.map +1 -1
  14. package/dist/cjs/react/core/utils/storage.js +2 -1
  15. package/dist/cjs/react/core/utils/storage.js.map +1 -1
  16. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +50 -223
  17. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
  18. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js +111 -0
  19. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js.map +1 -0
  20. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatStatusScreen.js +1 -1
  21. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatStatusScreen.js.map +1 -1
  22. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/PostOnRampSwap.js +30 -2
  23. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/PostOnRampSwap.js.map +1 -1
  24. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/Providers.js +24 -0
  25. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/Providers.js.map +1 -0
  26. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.js +2 -1
  27. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.js.map +1 -1
  28. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js +19 -16
  29. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js.map +1 -1
  30. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.js +37 -0
  31. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.js.map +1 -0
  32. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapFlow.js +1 -1
  33. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapFlow.js.map +1 -1
  34. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js +165 -0
  35. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js.map +1 -0
  36. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.js +1 -1
  37. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.js.map +1 -1
  38. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +33 -6
  39. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js.map +1 -1
  40. package/dist/cjs/react/web/ui/ConnectWallet/screens/nativeToken.js +8 -0
  41. package/dist/cjs/react/web/ui/ConnectWallet/screens/nativeToken.js.map +1 -1
  42. package/dist/cjs/react/web/utils/errors.js +16 -0
  43. package/dist/cjs/react/web/utils/errors.js.map +1 -0
  44. package/dist/cjs/version.js +1 -1
  45. package/dist/cjs/version.js.map +1 -1
  46. package/dist/cjs/wallets/smart/index.js +27 -0
  47. package/dist/cjs/wallets/smart/index.js.map +1 -1
  48. package/dist/cjs/wallets/smart/types.js.map +1 -1
  49. package/dist/esm/client/client.js +2 -1
  50. package/dist/esm/client/client.js.map +1 -1
  51. package/dist/esm/contract/deployment/zksync/implementations.js +3 -0
  52. package/dist/esm/contract/deployment/zksync/implementations.js.map +1 -1
  53. package/dist/esm/contract/deployment/zksync/zkDeployContract.js +4 -2
  54. package/dist/esm/contract/deployment/zksync/zkDeployContract.js.map +1 -1
  55. package/dist/esm/pay/buyWithCrypto/getQuote.js +4 -14
  56. package/dist/esm/pay/buyWithCrypto/getQuote.js.map +1 -1
  57. package/dist/esm/pay/buyWithCrypto/getTransfer.js +1 -13
  58. package/dist/esm/pay/buyWithCrypto/getTransfer.js.map +1 -1
  59. package/dist/esm/pay/buyWithFiat/getQuote.js.map +1 -1
  60. package/dist/esm/pay/utils/commonTypes.js +1 -1
  61. package/dist/esm/pay/utils/commonTypes.js.map +1 -1
  62. package/dist/esm/react/core/utils/storage.js +1 -0
  63. package/dist/esm/react/core/utils/storage.js.map +1 -1
  64. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +50 -223
  65. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
  66. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js +108 -0
  67. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js.map +1 -0
  68. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatStatusScreen.js +1 -1
  69. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatStatusScreen.js.map +1 -1
  70. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/PostOnRampSwap.js +30 -2
  71. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/PostOnRampSwap.js.map +1 -1
  72. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/Providers.js +21 -0
  73. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/Providers.js.map +1 -0
  74. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.js +2 -1
  75. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.js.map +1 -1
  76. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js +19 -16
  77. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js.map +1 -1
  78. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.js +34 -0
  79. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.js.map +1 -0
  80. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapFlow.js +1 -1
  81. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapFlow.js.map +1 -1
  82. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js +162 -0
  83. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js.map +1 -0
  84. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.js +1 -1
  85. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.js.map +1 -1
  86. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +33 -6
  87. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js.map +1 -1
  88. package/dist/esm/react/web/ui/ConnectWallet/screens/nativeToken.js +7 -0
  89. package/dist/esm/react/web/ui/ConnectWallet/screens/nativeToken.js.map +1 -1
  90. package/dist/esm/react/web/utils/errors.js +12 -0
  91. package/dist/esm/react/web/utils/errors.js.map +1 -0
  92. package/dist/esm/version.js +1 -1
  93. package/dist/esm/version.js.map +1 -1
  94. package/dist/esm/wallets/smart/index.js +27 -0
  95. package/dist/esm/wallets/smart/index.js.map +1 -1
  96. package/dist/esm/wallets/smart/types.js.map +1 -1
  97. package/dist/types/client/client.d.ts.map +1 -1
  98. package/dist/types/contract/deployment/zksync/implementations.d.ts.map +1 -1
  99. package/dist/types/contract/deployment/zksync/zkDeployContract.d.ts.map +1 -1
  100. package/dist/types/pay/buyWithCrypto/getQuote.d.ts +2 -2
  101. package/dist/types/pay/buyWithCrypto/getQuote.d.ts.map +1 -1
  102. package/dist/types/pay/buyWithCrypto/getTransfer.d.ts +2 -2
  103. package/dist/types/pay/buyWithCrypto/getTransfer.d.ts.map +1 -1
  104. package/dist/types/pay/buyWithFiat/getQuote.d.ts +4 -0
  105. package/dist/types/pay/buyWithFiat/getQuote.d.ts.map +1 -1
  106. package/dist/types/pay/utils/commonTypes.d.ts +2 -1
  107. package/dist/types/pay/utils/commonTypes.d.ts.map +1 -1
  108. package/dist/types/react/core/utils/storage.d.ts +1 -0
  109. package/dist/types/react/core/utils/storage.d.ts.map +1 -1
  110. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.d.ts.map +1 -1
  111. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.d.ts +25 -0
  112. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.d.ts.map +1 -0
  113. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/PostOnRampSwap.d.ts.map +1 -1
  114. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/Providers.d.ts +9 -0
  115. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/Providers.d.ts.map +1 -0
  116. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/main/types.d.ts +1 -0
  117. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/main/types.d.ts.map +1 -1
  118. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.d.ts.map +1 -1
  119. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.d.ts +1 -0
  120. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.d.ts.map +1 -1
  121. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.d.ts +11 -0
  122. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.d.ts.map +1 -0
  123. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/SwapFlow.d.ts +1 -0
  124. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/SwapFlow.d.ts.map +1 -1
  125. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.d.ts +31 -0
  126. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.d.ts.map +1 -0
  127. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.d.ts.map +1 -1
  128. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.d.ts.map +1 -1
  129. package/dist/types/react/web/ui/ConnectWallet/screens/nativeToken.d.ts +2 -0
  130. package/dist/types/react/web/ui/ConnectWallet/screens/nativeToken.d.ts.map +1 -1
  131. package/dist/types/react/web/ui/components/text.d.ts +1 -1
  132. package/dist/types/react/web/ui/components/text.d.ts.map +1 -1
  133. package/dist/types/react/web/utils/errors.d.ts +14 -0
  134. package/dist/types/react/web/utils/errors.d.ts.map +1 -0
  135. package/dist/types/version.d.ts +1 -1
  136. package/dist/types/version.d.ts.map +1 -1
  137. package/dist/types/wallets/smart/index.d.ts.map +1 -1
  138. package/dist/types/wallets/smart/types.d.ts +5 -0
  139. package/dist/types/wallets/smart/types.d.ts.map +1 -1
  140. package/package.json +2 -2
  141. package/src/client/client.test.ts +2 -2
  142. package/src/client/client.ts +2 -1
  143. package/src/contract/deployment/zksync/implementations.ts +3 -0
  144. package/src/contract/deployment/zksync/zkDeployContract.ts +5 -2
  145. package/src/pay/buyWithCrypto/getQuote.ts +6 -15
  146. package/src/pay/buyWithCrypto/getTransfer.ts +2 -14
  147. package/src/pay/buyWithFiat/getQuote.ts +5 -0
  148. package/src/pay/utils/commonTypes.ts +3 -1
  149. package/src/react/core/utils/storage.ts +1 -0
  150. package/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx +70 -556
  151. package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx +307 -0
  152. package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatStatusScreen.tsx +3 -5
  153. package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/PostOnRampSwap.tsx +33 -1
  154. package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/Providers.tsx +57 -0
  155. package/src/react/web/ui/ConnectWallet/screens/Buy/main/types.ts +1 -0
  156. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.tsx +12 -2
  157. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx +22 -19
  158. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx +51 -0
  159. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapFlow.tsx +2 -0
  160. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.tsx +353 -0
  161. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.tsx +3 -5
  162. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx +43 -6
  163. package/src/react/web/ui/ConnectWallet/screens/nativeToken.ts +8 -0
  164. package/src/react/web/ui/components/text.tsx +1 -1
  165. package/src/react/web/utils/errors.ts +22 -0
  166. package/src/version.ts +1 -1
  167. package/src/wallets/smart/index.ts +28 -0
  168. package/src/wallets/smart/smart-wallet-integration.test.ts +25 -0
  169. package/src/wallets/smart/types.ts +5 -0
@@ -3,24 +3,19 @@ import { useCallback, useMemo, useState } from "react";
3
3
  import type { Chain } from "../../../../../../chains/types.js";
4
4
  import type { ThirdwebClient } from "../../../../../../client/client.js";
5
5
  import { NATIVE_TOKEN_ADDRESS } from "../../../../../../constants/addresses.js";
6
- import type { GetBuyWithCryptoQuoteParams } from "../../../../../../pay/buyWithCrypto/getQuote.js";
7
6
  import type { BuyWithCryptoStatus } from "../../../../../../pay/buyWithCrypto/getStatus.js";
8
7
  import type { BuyWithFiatStatus } from "../../../../../../pay/buyWithFiat/getStatus.js";
9
- import { isSwapRequiredPostOnramp } from "../../../../../../pay/buyWithFiat/isSwapRequiredPostOnramp.js";
10
- import { formatNumber } from "../../../../../../utils/formatNumber.js";
11
8
  import type { Account } from "../../../../../../wallets/interfaces/wallet.js";
12
9
  import type { WalletId } from "../../../../../../wallets/wallet-types.js";
13
10
  import {
14
11
  type Theme,
12
+ fontSize,
15
13
  spacing,
16
14
  } from "../../../../../core/design-system/index.js";
17
15
  import type {
18
16
  FundWalletOptions,
19
17
  PayUIOptions,
20
18
  } from "../../../../../core/hooks/connection/ConnectButtonProps.js";
21
- import { useWalletBalance } from "../../../../../core/hooks/others/useWalletBalance.js";
22
- import { useBuyWithCryptoQuote } from "../../../../../core/hooks/pay/useBuyWithCryptoQuote.js";
23
- import { useBuyWithFiatQuote } from "../../../../../core/hooks/pay/useBuyWithFiatQuote.js";
24
19
  import { useActiveAccount } from "../../../../../core/hooks/wallets/useActiveAccount.js";
25
20
  import { invalidateWalletBalance } from "../../../../../core/providers/invalidateWalletBalance.js";
26
21
  import type { SupportedTokens } from "../../../../../core/utils/defaultTokens.js";
@@ -28,16 +23,10 @@ import { ErrorState } from "../../../../wallets/shared/ErrorState.js";
28
23
  import { LoadingScreen } from "../../../../wallets/shared/LoadingScreen.js";
29
24
  import type { PayEmbedConnectOptions } from "../../../PayEmbed.js";
30
25
  import { ChainName } from "../../../components/ChainName.js";
31
- import {
32
- Drawer,
33
- DrawerOverlay,
34
- useDrawer,
35
- } from "../../../components/Drawer.js";
36
26
  import { Spacer } from "../../../components/Spacer.js";
37
- import { Spinner } from "../../../components/Spinner.js";
38
- import { SwitchNetworkButton } from "../../../components/SwitchNetwork.js";
39
27
  import { Container, Line, ModalHeader } from "../../../components/basic.js";
40
28
  import { Button } from "../../../components/buttons.js";
29
+ import { Input } from "../../../components/formElements.js";
41
30
  import { Text } from "../../../components/text.js";
42
31
  import { TokenSymbol } from "../../../components/token/TokenSymbol.js";
43
32
  import { ConnectButton } from "../../ConnectButton.js";
@@ -47,13 +36,11 @@ import { TokenSelector } from "../TokenSelector.js";
47
36
  import { WalletSwitcherConnectionScreen } from "../WalletSwitcherConnectionScreen.js";
48
37
  import { type ERC20OrNativeToken, isNativeToken } from "../nativeToken.js";
49
38
  import { DirectPaymentModeScreen } from "./DirectPaymentModeScreen.js";
50
- import { EstimatedTimeAndFees } from "./EstimatedTimeAndFees.js";
51
39
  import { PayTokenIcon } from "./PayTokenIcon.js";
52
- import { PayWithCreditCard } from "./PayWIthCreditCard.js";
53
40
  import { TransactionModeScreen } from "./TransactionModeScreen.js";
54
41
  import { CurrencySelection } from "./fiat/CurrencySelection.js";
55
42
  import { FiatFlow } from "./fiat/FiatFlow.js";
56
- import type { CurrencyMeta } from "./fiat/currencies.js";
43
+ import { FiatScreenContent } from "./fiat/FiatScreenContent.js";
57
44
  import type { SelectedScreen } from "./main/types.js";
58
45
  import {
59
46
  type PaymentMethods,
@@ -64,20 +51,16 @@ import {
64
51
  useFromTokenSelectionStates,
65
52
  useToTokenSelectionStates,
66
53
  } from "./main/useUISelectionStates.js";
67
- import { openOnrampPopup } from "./openOnRamppopup.js";
68
54
  import { BuyTokenInput } from "./swap/BuyTokenInput.js";
69
- import { FiatFees, SwapFees } from "./swap/Fees.js";
70
- import { PayWithCryptoQuoteInfo } from "./swap/PayWithCrypto.js";
71
55
  import { PaymentSelectionScreen } from "./swap/PaymentSelectionScreen.js";
72
56
  import { SwapFlow } from "./swap/SwapFlow.js";
57
+ import { SwapScreenContent } from "./swap/SwapScreenContent.js";
73
58
  import { TransferFlow } from "./swap/TransferFlow.js";
74
- import { addPendingTx } from "./swap/pendingSwapTx.js";
75
59
  import {
76
60
  type SupportedChainAndTokens,
77
61
  useBuySupportedDestinations,
78
62
  useBuySupportedSources,
79
63
  } from "./swap/useSwapSupportedChains.js";
80
- import type { PayerInfo } from "./types.js";
81
64
  import { usePayerSetup } from "./usePayerSetup.js";
82
65
 
83
66
  export type BuyScreenProps = {
@@ -322,6 +305,7 @@ function BuyScreenContent(props: BuyScreenContentProps) {
322
305
  });
323
306
  }}
324
307
  onSuccess={onSwapSuccess}
308
+ approvalAmount={screen.approvalAmount}
325
309
  />
326
310
  );
327
311
  }
@@ -536,6 +520,7 @@ function BuyScreenContent(props: BuyScreenContentProps) {
536
520
  selectedChain={toChain}
537
521
  selectedToken={toToken}
538
522
  tokenAmount={tokenAmount}
523
+ setTokenAmount={setTokenAmount}
539
524
  client={client}
540
525
  onBack={() => {
541
526
  if (
@@ -663,8 +648,17 @@ function SelectedTokenInfo(props: {
663
648
  selectedToken: ERC20OrNativeToken;
664
649
  selectedChain: Chain;
665
650
  tokenAmount: string;
651
+ setTokenAmount: (amount: string) => void;
666
652
  client: ThirdwebClient;
667
653
  }) {
654
+ const getWidth = () => {
655
+ let chars = props.tokenAmount.replace(".", "").length;
656
+ const hasDot = props.tokenAmount.includes(".");
657
+ if (hasDot) {
658
+ chars += 0.3;
659
+ }
660
+ return `calc(${`${Math.max(1, chars)}ch + 2px`})`;
661
+ };
668
662
  return (
669
663
  <div>
670
664
  <Container
@@ -676,9 +670,59 @@ function SelectedTokenInfo(props: {
676
670
  }}
677
671
  >
678
672
  <Container flex="row" gap="xs" center="y">
679
- <Text color="primaryText" data-testid="tokenAmount" size="xl">
680
- {formatNumber(Number(props.tokenAmount), 6)}
681
- </Text>
673
+ <Input
674
+ variant="outline"
675
+ pattern="^[0-9]*[.,]?[0-9]*$"
676
+ inputMode="decimal"
677
+ tabIndex={-1}
678
+ placeholder="0"
679
+ type="text"
680
+ data-placeholder={props.tokenAmount === ""}
681
+ value={props.tokenAmount || "0"}
682
+ disabled={false} // TODO: add disabled freeze amount
683
+ onClick={(e) => {
684
+ // put cursor at the end of the input
685
+ if (props.tokenAmount === "") {
686
+ e.currentTarget.setSelectionRange(
687
+ e.currentTarget.value.length,
688
+ e.currentTarget.value.length,
689
+ );
690
+ }
691
+ }}
692
+ onChange={(e) => {
693
+ let value = e.target.value;
694
+
695
+ if (value.startsWith(".")) {
696
+ value = `0${value}`;
697
+ }
698
+
699
+ if (value.length > 10) {
700
+ return;
701
+ }
702
+
703
+ const numValue = Number(value);
704
+ if (Number.isNaN(numValue)) {
705
+ return;
706
+ }
707
+
708
+ if (value.startsWith("0") && !value.startsWith("0.")) {
709
+ props.setTokenAmount(value.slice(1));
710
+ } else {
711
+ props.setTokenAmount(value);
712
+ }
713
+ }}
714
+ style={{
715
+ border: "none",
716
+ fontSize: fontSize.lg,
717
+ boxShadow: "none",
718
+ borderRadius: "0",
719
+ padding: "0",
720
+ paddingBlock: "2px",
721
+ fontWeight: 600,
722
+ textAlign: "left",
723
+ width: getWidth(),
724
+ }}
725
+ />
682
726
 
683
727
  <Container flex="row" gap="xxs" center="y">
684
728
  <TokenSymbol
@@ -866,6 +910,7 @@ function TokenSelectedLayout(props: {
866
910
  title: string;
867
911
  children: React.ReactNode;
868
912
  tokenAmount: string;
913
+ setTokenAmount: (amount: string) => void;
869
914
  selectedToken: ERC20OrNativeToken;
870
915
  selectedChain: Chain;
871
916
  client: ThirdwebClient;
@@ -888,6 +933,7 @@ function TokenSelectedLayout(props: {
888
933
  selectedToken={props.selectedToken}
889
934
  selectedChain={props.selectedChain}
890
935
  tokenAmount={props.tokenAmount}
936
+ setTokenAmount={props.setTokenAmount}
891
937
  client={props.client}
892
938
  />
893
939
 
@@ -904,538 +950,6 @@ function TokenSelectedLayout(props: {
904
950
  );
905
951
  }
906
952
 
907
- function SwapScreenContent(props: {
908
- setScreen: (screen: SelectedScreen) => void;
909
- tokenAmount: string;
910
- toToken: ERC20OrNativeToken;
911
- toChain: Chain;
912
- fromChain: Chain;
913
- fromToken: ERC20OrNativeToken;
914
- showFromTokenSelector: () => void;
915
- payer: PayerInfo;
916
- client: ThirdwebClient;
917
- payOptions: PayUIOptions;
918
- isEmbed: boolean;
919
- onDone: () => void;
920
- connectOptions: PayEmbedConnectOptions | undefined;
921
- connectLocale: ConnectLocale;
922
- setPayer: (payer: PayerInfo) => void;
923
- activeAccount: Account;
924
- setTokenAmount: (amount: string) => void;
925
- setHasEditedAmount: (hasEdited: boolean) => void;
926
- disableTokenSelection: boolean;
927
- }) {
928
- const {
929
- setScreen,
930
- payer,
931
- client,
932
- toChain,
933
- tokenAmount,
934
- toToken,
935
- fromChain,
936
- fromToken,
937
- payOptions,
938
- disableTokenSelection,
939
- } = props;
940
-
941
- const defaultRecipientAddress = (
942
- props.payOptions as Extract<PayUIOptions, { mode: "direct_payment" }>
943
- )?.paymentInfo?.sellerAddress;
944
- const receiverAddress =
945
- defaultRecipientAddress || props.activeAccount.address;
946
- const { drawerRef, drawerOverlayRef, isOpen, setIsOpen } = useDrawer();
947
- const [drawerScreen, setDrawerScreen] = useState<
948
- "fees" | "receiver" | "payer"
949
- >("fees");
950
-
951
- const fromTokenBalanceQuery = useWalletBalance({
952
- address: payer.account.address,
953
- chain: fromChain,
954
- tokenAddress: isNativeToken(fromToken) ? undefined : fromToken.address,
955
- client,
956
- });
957
-
958
- const fromTokenId = isNativeToken(fromToken)
959
- ? NATIVE_TOKEN_ADDRESS
960
- : fromToken.address.toLowerCase();
961
- const toTokenId = isNativeToken(toToken)
962
- ? NATIVE_TOKEN_ADDRESS
963
- : toToken.address.toLowerCase();
964
- const swapRequired =
965
- !!tokenAmount &&
966
- !(fromChain.id === toChain.id && fromTokenId === toTokenId);
967
- const quoteParams: GetBuyWithCryptoQuoteParams | undefined = swapRequired
968
- ? {
969
- // wallets
970
- fromAddress: payer.account.address,
971
- toAddress: receiverAddress,
972
- // from
973
- fromChainId: fromChain.id,
974
- fromTokenAddress: isNativeToken(fromToken)
975
- ? NATIVE_TOKEN_ADDRESS
976
- : fromToken.address,
977
- // to
978
- toChainId: toChain.id,
979
- toTokenAddress: isNativeToken(toToken)
980
- ? NATIVE_TOKEN_ADDRESS
981
- : toToken.address,
982
- toAmount: tokenAmount,
983
- client,
984
- purchaseData: payOptions.purchaseData,
985
- }
986
- : undefined;
987
-
988
- const quoteQuery = useBuyWithCryptoQuote(quoteParams, {
989
- // refetch every 30 seconds
990
- staleTime: 30 * 1000,
991
- refetchInterval: 30 * 1000,
992
- gcTime: 30 * 1000,
993
- });
994
-
995
- const sourceTokenAmount = swapRequired
996
- ? quoteQuery.data?.swapDetails.fromAmount
997
- : tokenAmount;
998
-
999
- const isNotEnoughBalance =
1000
- !!sourceTokenAmount &&
1001
- !!fromTokenBalanceQuery.data &&
1002
- Number(fromTokenBalanceQuery.data.displayValue) < Number(sourceTokenAmount);
1003
-
1004
- const disableContinue =
1005
- (swapRequired && !quoteQuery.data) || isNotEnoughBalance;
1006
- const switchChainRequired =
1007
- props.payer.wallet.getChain()?.id !== fromChain.id;
1008
-
1009
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
1010
- function getErrorMessage(err: any) {
1011
- type AmountTooLowError = {
1012
- code: "MINIMUM_PURCHASE_AMOUNT";
1013
- data: {
1014
- minimumAmountUSDCents: number;
1015
- requestedAmountUSDCents: number;
1016
- minimumAmountWei: string;
1017
- minimumAmountEth: string;
1018
- };
1019
- };
1020
-
1021
- const defaultMessage = "Unable to get price quote";
1022
- try {
1023
- if (err.error.code === "MINIMUM_PURCHASE_AMOUNT") {
1024
- const obj = err.error as AmountTooLowError;
1025
- const minAmountToken = obj.data.minimumAmountEth;
1026
- return {
1027
- minAmount: formatNumber(Number(minAmountToken), 6),
1028
- };
1029
- }
1030
- } catch {}
1031
-
1032
- return {
1033
- msg: [defaultMessage],
1034
- };
1035
- }
1036
-
1037
- const errorMsg =
1038
- !quoteQuery.isLoading && quoteQuery.error
1039
- ? getErrorMessage(quoteQuery.error)
1040
- : undefined;
1041
-
1042
- function showSwapFlow() {
1043
- if (
1044
- (props.payOptions.mode === "direct_payment" ||
1045
- props.payOptions.mode === "fund_wallet") &&
1046
- !isNotEnoughBalance &&
1047
- !swapRequired
1048
- ) {
1049
- // same currency, just direct transfer
1050
- setScreen({
1051
- id: "transfer-flow",
1052
- });
1053
- } else if (
1054
- props.payOptions.mode === "transaction" &&
1055
- !isNotEnoughBalance &&
1056
- !swapRequired
1057
- ) {
1058
- if (payer.account.address !== receiverAddress) {
1059
- // needs transfer from another wallet before executing the transaction
1060
- setScreen({
1061
- id: "transfer-flow",
1062
- });
1063
- } else {
1064
- // has enough balance to just do the transaction directly
1065
- props.onDone();
1066
- }
1067
-
1068
- return;
1069
- }
1070
-
1071
- if (!quoteQuery.data) {
1072
- return;
1073
- }
1074
-
1075
- setScreen({
1076
- id: "swap-flow",
1077
- quote: quoteQuery.data,
1078
- });
1079
- }
1080
-
1081
- function showFees() {
1082
- if (!quoteQuery.data) {
1083
- return;
1084
- }
1085
-
1086
- setIsOpen(true);
1087
- setDrawerScreen("fees");
1088
- }
1089
-
1090
- return (
1091
- <Container flex="column" gap="md" animate="fadein">
1092
- {isOpen && (
1093
- <>
1094
- <DrawerOverlay ref={drawerOverlayRef} />
1095
- <Drawer ref={drawerRef} close={() => setIsOpen(false)}>
1096
- {drawerScreen === "fees" && quoteQuery.data && (
1097
- <div>
1098
- <Text size="lg" color="primaryText">
1099
- Fees
1100
- </Text>
1101
- <Spacer y="lg" />
1102
- <SwapFees quote={quoteQuery.data} />
1103
- </div>
1104
- )}
1105
- </Drawer>
1106
- </>
1107
- )}
1108
-
1109
- {/* Quote info */}
1110
- <div>
1111
- <PayWithCryptoQuoteInfo
1112
- value={sourceTokenAmount || ""}
1113
- chain={fromChain}
1114
- token={fromToken}
1115
- isLoading={quoteQuery.isLoading && !sourceTokenAmount}
1116
- client={client}
1117
- freezeChainAndTokenSelection={disableTokenSelection}
1118
- payerAccount={props.payer.account}
1119
- swapRequired={swapRequired}
1120
- />
1121
- {swapRequired && (
1122
- <EstimatedTimeAndFees
1123
- quoteIsLoading={quoteQuery.isLoading}
1124
- estimatedSeconds={
1125
- quoteQuery.data?.swapDetails.estimated.durationSeconds
1126
- }
1127
- onViewFees={showFees}
1128
- />
1129
- )}
1130
- <Spacer y="md" />
1131
- </div>
1132
-
1133
- {/* Error message */}
1134
- {errorMsg && (
1135
- <div>
1136
- {errorMsg.minAmount && (
1137
- <Text color="danger" size="sm" center multiline>
1138
- Minimum amount is {errorMsg.minAmount}{" "}
1139
- <TokenSymbol
1140
- token={toToken}
1141
- chain={toChain}
1142
- size="sm"
1143
- inline
1144
- color="danger"
1145
- />
1146
- </Text>
1147
- )}
1148
-
1149
- {errorMsg.msg?.map((msg) => (
1150
- <Text color="danger" size="sm" center multiline key={msg}>
1151
- {msg}
1152
- </Text>
1153
- ))}
1154
- </div>
1155
- )}
1156
-
1157
- {!errorMsg && isNotEnoughBalance && (
1158
- <div>
1159
- <Text color="danger" size="sm" center multiline>
1160
- Not enough funds.
1161
- </Text>
1162
- <Text color="danger" size="sm" center multiline>
1163
- Try a different wallet or token.
1164
- </Text>
1165
- </div>
1166
- )}
1167
-
1168
- {/* Button */}
1169
- {errorMsg?.minAmount ? (
1170
- <Button
1171
- variant="accent"
1172
- fullWidth
1173
- onClick={() => {
1174
- props.setTokenAmount(String(errorMsg.minAmount));
1175
- props.setHasEditedAmount(true);
1176
- }}
1177
- >
1178
- Set Minimum
1179
- </Button>
1180
- ) : switchChainRequired &&
1181
- !quoteQuery.isLoading &&
1182
- !isNotEnoughBalance &&
1183
- !quoteQuery.error ? (
1184
- <SwitchNetworkButton
1185
- variant="accent"
1186
- fullWidth
1187
- switchChain={async () => {
1188
- await props.payer.wallet.switchChain(fromChain);
1189
- }}
1190
- />
1191
- ) : (
1192
- <Button
1193
- variant={disableContinue ? "outline" : "accent"}
1194
- fullWidth
1195
- data-disabled={disableContinue}
1196
- disabled={disableContinue}
1197
- onClick={async () => {
1198
- if (!disableContinue) {
1199
- showSwapFlow();
1200
- }
1201
- }}
1202
- gap="xs"
1203
- >
1204
- {quoteQuery.isLoading ? (
1205
- <>
1206
- Getting price quote
1207
- <Spinner size="sm" color="accentText" />
1208
- </>
1209
- ) : (
1210
- "Continue"
1211
- )}
1212
- </Button>
1213
- )}
1214
- </Container>
1215
- );
1216
- }
1217
-
1218
- function FiatScreenContent(props: {
1219
- setScreen: (screen: SelectedScreen) => void;
1220
- tokenAmount: string;
1221
- toToken: ERC20OrNativeToken;
1222
- toChain: Chain;
1223
- selectedCurrency: CurrencyMeta;
1224
- showCurrencySelector: () => void;
1225
- payOptions: PayUIOptions;
1226
- theme: "light" | "dark" | Theme;
1227
- client: ThirdwebClient;
1228
- onDone: () => void;
1229
- isEmbed: boolean;
1230
- payer: PayerInfo;
1231
- setTokenAmount: (amount: string) => void;
1232
- setHasEditedAmount: (hasEdited: boolean) => void;
1233
- }) {
1234
- const {
1235
- toToken,
1236
- tokenAmount,
1237
- payer,
1238
- client,
1239
- setScreen,
1240
- toChain,
1241
- showCurrencySelector,
1242
- selectedCurrency,
1243
- } = props;
1244
- const defaultRecipientAddress = (
1245
- props.payOptions as Extract<PayUIOptions, { mode: "direct_payment" }>
1246
- )?.paymentInfo?.sellerAddress;
1247
- const receiverAddress =
1248
- defaultRecipientAddress || props.payer.account.address;
1249
- const { drawerRef, drawerOverlayRef, isOpen, setIsOpen } = useDrawer();
1250
- const [drawerScreen, setDrawerScreen] = useState<"fees">("fees");
1251
-
1252
- const buyWithFiatOptions = props.payOptions.buyWithFiat;
1253
-
1254
- const fiatQuoteQuery = useBuyWithFiatQuote(
1255
- buyWithFiatOptions !== false && tokenAmount
1256
- ? {
1257
- fromCurrencySymbol: selectedCurrency.shorthand,
1258
- toChainId: toChain.id,
1259
- toAddress: receiverAddress,
1260
- toTokenAddress: isNativeToken(toToken)
1261
- ? NATIVE_TOKEN_ADDRESS
1262
- : toToken.address,
1263
- toAmount: tokenAmount,
1264
- client,
1265
- isTestMode: buyWithFiatOptions?.testMode,
1266
- purchaseData: props.payOptions.purchaseData,
1267
- fromAddress: payer.account.address,
1268
- preferredProvider: buyWithFiatOptions?.preferredProvider,
1269
- }
1270
- : undefined,
1271
- );
1272
-
1273
- function handleSubmit() {
1274
- if (!fiatQuoteQuery.data) {
1275
- return;
1276
- }
1277
-
1278
- const hasTwoSteps = isSwapRequiredPostOnramp(fiatQuoteQuery.data);
1279
- let openedWindow: Window | null = null;
1280
-
1281
- if (!hasTwoSteps) {
1282
- openedWindow = openOnrampPopup(
1283
- fiatQuoteQuery.data.onRampLink,
1284
- typeof props.theme === "string" ? props.theme : props.theme.type,
1285
- );
1286
-
1287
- addPendingTx({
1288
- type: "fiat",
1289
- intentId: fiatQuoteQuery.data.intentId,
1290
- });
1291
- }
1292
-
1293
- setScreen({
1294
- id: "fiat-flow",
1295
- quote: fiatQuoteQuery.data,
1296
- openedWindow,
1297
- });
1298
- }
1299
-
1300
- function showFees() {
1301
- if (!fiatQuoteQuery.data) {
1302
- return;
1303
- }
1304
-
1305
- setDrawerScreen("fees");
1306
- setIsOpen(true);
1307
- }
1308
-
1309
- // biome-ignore lint/suspicious/noExplicitAny: <explanation>
1310
- function getErrorMessage(err: any) {
1311
- type AmountTooLowError = {
1312
- code: "MINIMUM_PURCHASE_AMOUNT";
1313
- data: {
1314
- minimumAmountUSDCents: number;
1315
- requestedAmountUSDCents: number;
1316
- minimumAmountWei: string;
1317
- minimumAmountEth: string;
1318
- };
1319
- };
1320
-
1321
- const defaultMessage = "Unable to get price quote";
1322
- try {
1323
- if (err.error.code === "MINIMUM_PURCHASE_AMOUNT") {
1324
- const obj = err.error as AmountTooLowError;
1325
- const minAmountToken = obj.data.minimumAmountEth;
1326
- return {
1327
- minAmount: formatNumber(Number(minAmountToken), 6),
1328
- };
1329
- }
1330
- } catch {}
1331
-
1332
- return {
1333
- msg: [defaultMessage],
1334
- };
1335
- }
1336
-
1337
- const disableSubmit = !fiatQuoteQuery.data;
1338
-
1339
- const errorMsg =
1340
- !fiatQuoteQuery.isLoading && fiatQuoteQuery.error
1341
- ? getErrorMessage(fiatQuoteQuery.error)
1342
- : undefined;
1343
-
1344
- return (
1345
- <Container flex="column" gap="md" animate="fadein">
1346
- {isOpen && (
1347
- <>
1348
- <DrawerOverlay ref={drawerOverlayRef} />
1349
- <Drawer ref={drawerRef} close={() => setIsOpen(false)}>
1350
- {drawerScreen === "fees" && fiatQuoteQuery.data && (
1351
- <div>
1352
- <Text size="lg" color="primaryText">
1353
- Fees
1354
- </Text>
1355
-
1356
- <Spacer y="lg" />
1357
- <FiatFees quote={fiatQuoteQuery.data} />
1358
- </div>
1359
- )}
1360
- </Drawer>
1361
- </>
1362
- )}
1363
-
1364
- <div>
1365
- <PayWithCreditCard
1366
- isLoading={fiatQuoteQuery.isLoading}
1367
- value={fiatQuoteQuery.data?.fromCurrencyWithFees.amount}
1368
- client={client}
1369
- currency={selectedCurrency}
1370
- onSelectCurrency={showCurrencySelector}
1371
- />
1372
- {/* Estimated time + View fees button */}
1373
- <EstimatedTimeAndFees
1374
- quoteIsLoading={fiatQuoteQuery.isLoading}
1375
- estimatedSeconds={fiatQuoteQuery.data?.estimatedDurationSeconds}
1376
- onViewFees={showFees}
1377
- />
1378
- <Spacer y="md" />
1379
- </div>
1380
-
1381
- {/* Error message */}
1382
- {errorMsg && (
1383
- <div>
1384
- {errorMsg.minAmount && (
1385
- <Text color="danger" size="sm" center multiline>
1386
- Minimum amount is {errorMsg.minAmount}{" "}
1387
- <TokenSymbol
1388
- token={toToken}
1389
- chain={toChain}
1390
- size="sm"
1391
- inline
1392
- color="danger"
1393
- />
1394
- </Text>
1395
- )}
1396
-
1397
- {errorMsg.msg?.map((msg) => (
1398
- <Text color="danger" size="sm" center multiline key={msg}>
1399
- {msg}
1400
- </Text>
1401
- ))}
1402
- </div>
1403
- )}
1404
-
1405
- {errorMsg?.minAmount ? (
1406
- <Button
1407
- variant="accent"
1408
- fullWidth
1409
- onClick={() => {
1410
- props.setTokenAmount(String(errorMsg.minAmount));
1411
- props.setHasEditedAmount(true);
1412
- }}
1413
- >
1414
- Set Minimum
1415
- </Button>
1416
- ) : (
1417
- <Button
1418
- variant={disableSubmit ? "outline" : "accent"}
1419
- data-disabled={disableSubmit}
1420
- disabled={disableSubmit}
1421
- fullWidth
1422
- onClick={handleSubmit}
1423
- gap="xs"
1424
- >
1425
- {fiatQuoteQuery.isLoading ? (
1426
- <>
1427
- Getting price quote
1428
- <Spinner size="sm" color="accentText" />
1429
- </>
1430
- ) : (
1431
- "Continue"
1432
- )}
1433
- </Button>
1434
- )}
1435
- </Container>
1436
- );
1437
- }
1438
-
1439
953
  function createSupportedTokens(
1440
954
  data: SupportedChainAndTokens,
1441
955
  payOptions: PayUIOptions,