thirdweb 5.48.1 → 5.48.2

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 (184) hide show
  1. package/dist/cjs/exports/pay.js +3 -1
  2. package/dist/cjs/exports/pay.js.map +1 -1
  3. package/dist/cjs/exports/thirdweb.js +3 -1
  4. package/dist/cjs/exports/thirdweb.js.map +1 -1
  5. package/dist/cjs/pay/buyWithCrypto/commonTypes.js +3 -0
  6. package/dist/cjs/pay/buyWithCrypto/commonTypes.js.map +1 -0
  7. package/dist/cjs/pay/buyWithCrypto/getQuote.js.map +1 -1
  8. package/dist/cjs/pay/buyWithCrypto/getTransfer.js +95 -0
  9. package/dist/cjs/pay/buyWithCrypto/getTransfer.js.map +1 -0
  10. package/dist/cjs/pay/utils/definitions.js +7 -1
  11. package/dist/cjs/pay/utils/definitions.js.map +1 -1
  12. package/dist/cjs/react/core/hooks/transaction/useSendTransaction.js.map +1 -1
  13. package/dist/cjs/react/native/ui/connect/ConnectedButton.js +5 -1
  14. package/dist/cjs/react/native/ui/connect/ConnectedButton.js.map +1 -1
  15. package/dist/cjs/react/native/ui/connect/ConnectedModal.js +2 -1
  16. package/dist/cjs/react/native/ui/connect/ConnectedModal.js.map +1 -1
  17. package/dist/cjs/react/native/ui/connect/TokenListScreen.js +5 -1
  18. package/dist/cjs/react/native/ui/connect/TokenListScreen.js.map +1 -1
  19. package/dist/cjs/react/web/ui/ConnectWallet/Details.js +28 -22
  20. package/dist/cjs/react/web/ui/ConnectWallet/Details.js.map +1 -1
  21. package/dist/cjs/react/web/ui/ConnectWallet/icons/currencies/JPYIcon.js +9 -0
  22. package/dist/cjs/react/web/ui/ConnectWallet/icons/currencies/JPYIcon.js.map +1 -0
  23. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +5 -1
  24. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
  25. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.js +9 -3
  26. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.js.map +1 -1
  27. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js +34 -2
  28. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js.map +1 -1
  29. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/pay-transactions/SwapDetailsScreen.js +8 -0
  30. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/pay-transactions/SwapDetailsScreen.js.map +1 -1
  31. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.js +1 -1
  32. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.js.map +1 -1
  33. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +118 -0
  34. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js.map +1 -0
  35. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferFlow.js +7 -76
  36. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferFlow.js.map +1 -1
  37. package/dist/cjs/react/web/ui/ConnectWallet/screens/formatTokenBalance.js +2 -1
  38. package/dist/cjs/react/web/ui/ConnectWallet/screens/formatTokenBalance.js.map +1 -1
  39. package/dist/cjs/stories/ConnectButton.stories.js +28 -0
  40. package/dist/cjs/stories/ConnectButton.stories.js.map +1 -0
  41. package/dist/cjs/stories/PayEmbed.stories.js +38 -0
  42. package/dist/cjs/stories/PayEmbed.stories.js.map +1 -0
  43. package/dist/cjs/stories/utils.js +27 -0
  44. package/dist/cjs/stories/utils.js.map +1 -0
  45. package/dist/cjs/transaction/actions/send-transaction.js.map +1 -1
  46. package/dist/cjs/utils/signatures/sign-message.js +13 -19
  47. package/dist/cjs/utils/signatures/sign-message.js.map +1 -1
  48. package/dist/cjs/version.js +1 -1
  49. package/dist/cjs/wallets/in-app/core/wallet/index.js +4 -1
  50. package/dist/cjs/wallets/in-app/core/wallet/index.js.map +1 -1
  51. package/dist/esm/exports/pay.js +2 -0
  52. package/dist/esm/exports/pay.js.map +1 -1
  53. package/dist/esm/exports/thirdweb.js +2 -0
  54. package/dist/esm/exports/thirdweb.js.map +1 -1
  55. package/dist/esm/pay/buyWithCrypto/commonTypes.js +2 -0
  56. package/dist/esm/pay/buyWithCrypto/commonTypes.js.map +1 -0
  57. package/dist/esm/pay/buyWithCrypto/getQuote.js +1 -1
  58. package/dist/esm/pay/buyWithCrypto/getQuote.js.map +1 -1
  59. package/dist/esm/pay/buyWithCrypto/getTransfer.js +92 -0
  60. package/dist/esm/pay/buyWithCrypto/getTransfer.js.map +1 -0
  61. package/dist/esm/pay/utils/definitions.js +5 -0
  62. package/dist/esm/pay/utils/definitions.js.map +1 -1
  63. package/dist/esm/react/core/hooks/transaction/useSendTransaction.js.map +1 -1
  64. package/dist/esm/react/native/ui/connect/ConnectedButton.js +5 -1
  65. package/dist/esm/react/native/ui/connect/ConnectedButton.js.map +1 -1
  66. package/dist/esm/react/native/ui/connect/ConnectedModal.js +2 -1
  67. package/dist/esm/react/native/ui/connect/ConnectedModal.js.map +1 -1
  68. package/dist/esm/react/native/ui/connect/TokenListScreen.js +5 -1
  69. package/dist/esm/react/native/ui/connect/TokenListScreen.js.map +1 -1
  70. package/dist/esm/react/web/ui/ConnectWallet/Details.js +28 -22
  71. package/dist/esm/react/web/ui/ConnectWallet/Details.js.map +1 -1
  72. package/dist/esm/react/web/ui/ConnectWallet/icons/currencies/JPYIcon.js +5 -0
  73. package/dist/esm/react/web/ui/ConnectWallet/icons/currencies/JPYIcon.js.map +1 -0
  74. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +5 -1
  75. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
  76. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.js +8 -2
  77. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.js.map +1 -1
  78. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js +35 -3
  79. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js.map +1 -1
  80. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/pay-transactions/SwapDetailsScreen.js +8 -0
  81. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/pay-transactions/SwapDetailsScreen.js.map +1 -1
  82. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.js +1 -1
  83. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.js.map +1 -1
  84. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +115 -0
  85. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js.map +1 -0
  86. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferFlow.js +8 -77
  87. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferFlow.js.map +1 -1
  88. package/dist/esm/react/web/ui/ConnectWallet/screens/formatTokenBalance.js +2 -1
  89. package/dist/esm/react/web/ui/ConnectWallet/screens/formatTokenBalance.js.map +1 -1
  90. package/dist/esm/stories/ConnectButton.stories.js +25 -0
  91. package/dist/esm/stories/ConnectButton.stories.js.map +1 -0
  92. package/dist/esm/stories/PayEmbed.stories.js +35 -0
  93. package/dist/esm/stories/PayEmbed.stories.js.map +1 -0
  94. package/dist/esm/stories/utils.js +24 -0
  95. package/dist/esm/stories/utils.js.map +1 -0
  96. package/dist/esm/transaction/actions/send-transaction.js.map +1 -1
  97. package/dist/esm/utils/signatures/sign-message.js +13 -19
  98. package/dist/esm/utils/signatures/sign-message.js.map +1 -1
  99. package/dist/esm/version.js +1 -1
  100. package/dist/esm/wallets/in-app/core/wallet/index.js +4 -1
  101. package/dist/esm/wallets/in-app/core/wallet/index.js.map +1 -1
  102. package/dist/types/exports/pay.d.ts +3 -1
  103. package/dist/types/exports/pay.d.ts.map +1 -1
  104. package/dist/types/exports/thirdweb.d.ts +3 -1
  105. package/dist/types/exports/thirdweb.d.ts.map +1 -1
  106. package/dist/types/pay/buyWithCrypto/commonTypes.d.ts +36 -0
  107. package/dist/types/pay/buyWithCrypto/commonTypes.d.ts.map +1 -0
  108. package/dist/types/pay/buyWithCrypto/getQuote.d.ts +1 -24
  109. package/dist/types/pay/buyWithCrypto/getQuote.d.ts.map +1 -1
  110. package/dist/types/pay/buyWithCrypto/getStatus.d.ts +1 -1
  111. package/dist/types/pay/buyWithCrypto/getStatus.d.ts.map +1 -1
  112. package/dist/types/pay/buyWithCrypto/getTransfer.d.ts +85 -0
  113. package/dist/types/pay/buyWithCrypto/getTransfer.d.ts.map +1 -0
  114. package/dist/types/pay/buyWithFiat/getQuote.d.ts +1 -1
  115. package/dist/types/pay/buyWithFiat/getQuote.d.ts.map +1 -1
  116. package/dist/types/pay/utils/definitions.d.ts +5 -0
  117. package/dist/types/pay/utils/definitions.d.ts.map +1 -1
  118. package/dist/types/react/core/hooks/connection/ConnectButtonProps.d.ts +15 -0
  119. package/dist/types/react/core/hooks/connection/ConnectButtonProps.d.ts.map +1 -1
  120. package/dist/types/react/core/hooks/transaction/useSendTransaction.d.ts +3 -0
  121. package/dist/types/react/core/hooks/transaction/useSendTransaction.d.ts.map +1 -1
  122. package/dist/types/react/native/ui/connect/ConnectedButton.d.ts.map +1 -1
  123. package/dist/types/react/native/ui/connect/ConnectedModal.d.ts.map +1 -1
  124. package/dist/types/react/native/ui/connect/TokenListScreen.d.ts.map +1 -1
  125. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts +6 -0
  126. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts.map +1 -1
  127. package/dist/types/react/web/ui/ConnectWallet/icons/currencies/JPYIcon.d.ts +3 -0
  128. package/dist/types/react/web/ui/ConnectWallet/icons/currencies/JPYIcon.d.ts.map +1 -0
  129. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.d.ts +2 -2
  130. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.d.ts.map +1 -1
  131. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.d.ts +3 -2
  132. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.d.ts.map +1 -1
  133. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/pay-transactions/SwapDetailsScreen.d.ts.map +1 -1
  134. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.d.ts +1 -1
  135. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.d.ts.map +1 -1
  136. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.d.ts +20 -0
  137. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.d.ts.map +1 -0
  138. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/TransferFlow.d.ts +5 -1
  139. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/TransferFlow.d.ts.map +1 -1
  140. package/dist/types/react/web/ui/ConnectWallet/screens/formatTokenBalance.d.ts.map +1 -1
  141. package/dist/types/stories/ConnectButton.stories.d.ts +18 -0
  142. package/dist/types/stories/ConnectButton.stories.d.ts.map +1 -0
  143. package/dist/types/stories/PayEmbed.stories.d.ts +19 -0
  144. package/dist/types/stories/PayEmbed.stories.d.ts.map +1 -0
  145. package/dist/types/stories/utils.d.ts +5 -0
  146. package/dist/types/stories/utils.d.ts.map +1 -0
  147. package/dist/types/transaction/actions/send-transaction.d.ts +12 -2
  148. package/dist/types/transaction/actions/send-transaction.d.ts.map +1 -1
  149. package/dist/types/utils/signatures/sign-message.d.ts +26 -3
  150. package/dist/types/utils/signatures/sign-message.d.ts.map +1 -1
  151. package/dist/types/version.d.ts +1 -1
  152. package/dist/types/wallets/in-app/core/wallet/index.d.ts.map +1 -1
  153. package/package.json +15 -2
  154. package/src/exports/pay.ts +11 -2
  155. package/src/exports/thirdweb.ts +11 -2
  156. package/src/pay/buyWithCrypto/commonTypes.ts +40 -0
  157. package/src/pay/buyWithCrypto/getQuote.ts +8 -42
  158. package/src/pay/buyWithCrypto/getStatus.ts +1 -1
  159. package/src/pay/buyWithCrypto/getTransfer.ts +185 -0
  160. package/src/pay/buyWithFiat/getQuote.ts +1 -1
  161. package/src/pay/utils/definitions.ts +7 -0
  162. package/src/react/core/hooks/connection/ConnectButtonProps.ts +16 -0
  163. package/src/react/core/hooks/transaction/useSendTransaction.ts +3 -0
  164. package/src/react/native/ui/connect/ConnectedButton.tsx +6 -1
  165. package/src/react/native/ui/connect/ConnectedModal.tsx +2 -1
  166. package/src/react/native/ui/connect/TokenListScreen.tsx +6 -1
  167. package/src/react/web/ui/ConnectWallet/Details.tsx +93 -77
  168. package/src/react/web/ui/ConnectWallet/icons/currencies/JPYIcon.tsx +21 -0
  169. package/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx +8 -1
  170. package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.tsx +9 -3
  171. package/src/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.ts +47 -3
  172. package/src/react/web/ui/ConnectWallet/screens/Buy/pay-transactions/SwapDetailsScreen.tsx +26 -0
  173. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapStatusScreen.tsx +3 -3
  174. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx +284 -0
  175. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferFlow.tsx +29 -220
  176. package/src/react/web/ui/ConnectWallet/screens/formatTokenBalance.ts +3 -1
  177. package/src/stories/ConnectButton.stories.ts +31 -0
  178. package/src/stories/PayEmbed.stories.ts +42 -0
  179. package/src/stories/utils.tsx +29 -0
  180. package/src/transaction/actions/send-transaction.ts +12 -3
  181. package/src/utils/signatures/sign-message.test.ts +78 -50
  182. package/src/utils/signatures/sign-message.ts +44 -9
  183. package/src/version.ts +1 -1
  184. package/src/wallets/in-app/core/wallet/index.ts +2 -0
@@ -8,7 +8,11 @@ import type {
8
8
  import { useActiveWalletChain } from "../../../../../../core/hooks/wallets/useActiveWalletChain.js";
9
9
  import { useDebouncedValue } from "../../../../hooks/useDebouncedValue.js";
10
10
  import { type ERC20OrNativeToken, NATIVE_TOKEN } from "../../nativeToken.js";
11
- import { defaultSelectedCurrency } from "../fiat/currencies.js";
11
+ import {
12
+ type CurrencyMeta,
13
+ currencies,
14
+ usdCurrency,
15
+ } from "../fiat/currencies.js";
12
16
  import type { SupportedChainAndTokens } from "../swap/useSwapSupportedChains.js";
13
17
 
14
18
  // handle states for token and chain selection
@@ -71,10 +75,17 @@ export function useUISelectionStates(options: {
71
75
  );
72
76
 
73
77
  // --------------------------------------------------------------------------
78
+ const devSpecifiedDefaultCurrency =
79
+ payOptions.buyWithFiat !== false
80
+ ? payOptions.buyWithFiat?.prefillSource?.currency
81
+ : undefined;
82
+
83
+ const defaultSelectedCurrencyShorthand =
84
+ devSpecifiedDefaultCurrency || getDefaultCurrencyBasedOnLocation();
74
85
 
75
- // stripe only supports USD, so not using a state right now
76
86
  const [selectedCurrency, setSelectedCurrency] = useState(
77
- defaultSelectedCurrency,
87
+ currencies.find((x) => x.shorthand === defaultSelectedCurrencyShorthand) ||
88
+ usdCurrency,
78
89
  );
79
90
 
80
91
  return {
@@ -95,3 +106,36 @@ export function useUISelectionStates(options: {
95
106
  setSelectedCurrency,
96
107
  };
97
108
  }
109
+
110
+ function getDefaultCurrencyBasedOnLocation(): CurrencyMeta["shorthand"] {
111
+ // if Intl is not supported - browser throws
112
+ try {
113
+ const timeZone = Intl.DateTimeFormat()
114
+ .resolvedOptions()
115
+ .timeZone.toLowerCase();
116
+
117
+ // Europe/London -> GBP
118
+ if (timeZone.includes("london")) {
119
+ return "GBP";
120
+ }
121
+
122
+ // Europe/* -> EUR
123
+ if (timeZone.includes("europe")) {
124
+ return "EUR";
125
+ }
126
+
127
+ // Japan
128
+ if (timeZone.includes("japan")) {
129
+ return "JPY";
130
+ }
131
+
132
+ // canada
133
+ if (timeZone.includes("canada")) {
134
+ return "CAD";
135
+ }
136
+
137
+ return "USD";
138
+ } catch {
139
+ return "USD";
140
+ }
141
+ }
@@ -100,7 +100,9 @@ export function SwapTxDetailsTable(
100
100
  ) {
101
101
  let uiData: SwapTxDetailsData;
102
102
  let showStatusRow = true;
103
+ let isTransfer = false;
103
104
  if (props.type === "status") {
105
+ isTransfer = props.status.swapType === "TRANSFER";
104
106
  const status = props.status;
105
107
  if (props.hideStatusRow) {
106
108
  showStatusRow = false;
@@ -189,6 +191,30 @@ export function SwapTxDetailsTable(
189
191
  </>
190
192
  );
191
193
 
194
+ if (isTransfer) {
195
+ return (
196
+ <div>
197
+ {/* source chain Tx hash link */}
198
+ {fromChainExplorers.explorers?.[0]?.url && sourceTxHash && (
199
+ <ButtonLink
200
+ fullWidth
201
+ variant="outline"
202
+ href={`${fromChainExplorers.explorers[0].url}/tx/${sourceTxHash}`}
203
+ target="_blank"
204
+ gap="xs"
205
+ style={{
206
+ fontSize: fontSize.sm,
207
+ padding: spacing.sm,
208
+ }}
209
+ >
210
+ View on {fromChainName.name} Explorer
211
+ <ExternalLinkIcon width={iconSize.sm} height={iconSize.sm} />
212
+ </ButtonLink>
213
+ )}
214
+ </div>
215
+ );
216
+ }
217
+
192
218
  return (
193
219
  <div>
194
220
  {isPartialSuccess && gotToken ? (
@@ -26,7 +26,7 @@ export function SwapStatusScreen(props: {
26
26
  onDone: () => void;
27
27
  transactionMode: boolean;
28
28
  isEmbed: boolean;
29
- quote: BuyWithCryptoQuote;
29
+ quote: BuyWithCryptoQuote | undefined;
30
30
  onSuccess: ((status: BuyWithCryptoStatus) => void) | undefined;
31
31
  }) {
32
32
  const { onSuccess } = props;
@@ -82,13 +82,13 @@ export function SwapStatusScreen(props: {
82
82
  hideStatusRow={true}
83
83
  client={props.client}
84
84
  />
85
- ) : (
85
+ ) : props.quote ? (
86
86
  <SwapTxDetailsTable
87
87
  type="quote"
88
88
  quote={props.quote}
89
89
  client={props.client}
90
90
  />
91
- );
91
+ ) : null;
92
92
 
93
93
  return (
94
94
  <Container animate="fadein">
@@ -0,0 +1,284 @@
1
+ import { CheckCircledIcon, CrossCircledIcon } from "@radix-ui/react-icons";
2
+ import { useState } from "react";
3
+ import type { Chain } from "../../../../../../../chains/types.js";
4
+ import type { ThirdwebClient } from "../../../../../../../client/client.js";
5
+ import { NATIVE_TOKEN_ADDRESS } from "../../../../../../../constants/addresses.js";
6
+ import { getContract } from "../../../../../../../contract/contract.js";
7
+ import { transfer } from "../../../../../../../extensions/erc20/write/transfer.js";
8
+ import { getBuyWithCryptoTransfer } from "../../../../../../../pay/buyWithCrypto/getTransfer.js";
9
+ import { sendAndConfirmTransaction } from "../../../../../../../transaction/actions/send-and-confirm-transaction.js";
10
+ import { sendTransaction } from "../../../../../../../transaction/actions/send-transaction.js";
11
+ import { prepareTransaction } from "../../../../../../../transaction/prepare-transaction.js";
12
+ import { toWei } from "../../../../../../../utils/units.js";
13
+ import { iconSize } from "../../../../../../core/design-system/index.js";
14
+ import { useChainSymbol } from "../../../../../../core/hooks/others/useChainQuery.js";
15
+ import { Spacer } from "../../../../components/Spacer.js";
16
+ import { Spinner } from "../../../../components/Spinner.js";
17
+ import { StepBar } from "../../../../components/StepBar.js";
18
+ import { SwitchNetworkButton } from "../../../../components/SwitchNetwork.js";
19
+ import { Container, Line, ModalHeader } from "../../../../components/basic.js";
20
+ import { Button } from "../../../../components/buttons.js";
21
+ import { Text } from "../../../../components/text.js";
22
+ import { type ERC20OrNativeToken, isNativeToken } from "../../nativeToken.js";
23
+ import { Step } from "../Stepper.js";
24
+ import { WalletRow } from "../WalletSelectorButton.js";
25
+ import { TokenInfoRow } from "../pay-transactions/TokenInfoRow.js";
26
+ import type { PayerInfo } from "../types.js";
27
+ import { ConnectorLine } from "./ConfirmationScreen.js";
28
+
29
+ type TrasnferConfirmationScreenProps = {
30
+ title: string;
31
+ onBack?: () => void;
32
+ setTransactionHash: (txHash: string) => void;
33
+ payer: PayerInfo;
34
+ receiverAddress: string;
35
+ client: ThirdwebClient;
36
+ onDone: () => void;
37
+ chain: Chain;
38
+ token: ERC20OrNativeToken;
39
+ tokenAmount: string;
40
+ transactionMode?: boolean;
41
+ };
42
+
43
+ export function TransferConfirmationScreen(
44
+ props: TrasnferConfirmationScreenProps,
45
+ ) {
46
+ const {
47
+ title,
48
+ onBack,
49
+ receiverAddress,
50
+ client,
51
+ payer,
52
+ onDone,
53
+ chain,
54
+ token,
55
+ tokenAmount,
56
+ transactionMode,
57
+ setTransactionHash,
58
+ } = props;
59
+ const [step, setStep] = useState<"approve" | "transfer" | "execute">(
60
+ "transfer",
61
+ );
62
+ const [status, setStatus] = useState<"idle" | "pending" | "error" | "done">(
63
+ "idle",
64
+ );
65
+ const { symbol } = useChainSymbol(chain);
66
+
67
+ return (
68
+ <Container p="lg">
69
+ <ModalHeader title={title} onBack={onBack} />
70
+ <Spacer y="xl" />
71
+
72
+ {transactionMode && (
73
+ <>
74
+ <StepBar steps={2} currentStep={step === "transfer" ? 1 : 2} />
75
+ <Spacer y="sm" />
76
+ <Text size="sm">
77
+ {step === "transfer"
78
+ ? "Step 1 of 2 - Transfer funds"
79
+ : "Step 2 of 2 - Finalize transaction"}
80
+ </Text>
81
+ <Spacer y="xl" />
82
+ </>
83
+ )}
84
+
85
+ {/* Sender Address */}
86
+ <Container
87
+ flex="row"
88
+ center="y"
89
+ style={{
90
+ justifyContent: "space-between",
91
+ }}
92
+ >
93
+ <Text size="sm">From</Text>
94
+ <WalletRow address={payer.account.address} client={client} />
95
+ </Container>
96
+
97
+ <Spacer y="md" />
98
+ <Line />
99
+ <Spacer y="md" />
100
+
101
+ {/* Receiver Address */}
102
+ <Container
103
+ flex="row"
104
+ center="y"
105
+ style={{
106
+ justifyContent: "space-between",
107
+ }}
108
+ >
109
+ <Text size="sm">To</Text>
110
+ <WalletRow address={receiverAddress} client={client} />
111
+ </Container>
112
+
113
+ <Spacer y="md" />
114
+ <Line />
115
+ <Spacer y="md" />
116
+
117
+ {/* Token Info */}
118
+ <TokenInfoRow
119
+ chainId={chain.id}
120
+ client={client}
121
+ label={"Amount"}
122
+ tokenAmount={tokenAmount}
123
+ tokenSymbol={isNativeToken(token) ? symbol || "" : token.symbol}
124
+ tokenAddress={
125
+ isNativeToken(token) ? NATIVE_TOKEN_ADDRESS : token.address
126
+ }
127
+ />
128
+
129
+ <Spacer y="lg" />
130
+
131
+ {transactionMode && (
132
+ <>
133
+ <Spacer y="sm" />
134
+ <Container
135
+ gap="sm"
136
+ flex="row"
137
+ style={{
138
+ justifyContent: "space-between",
139
+ }}
140
+ center="y"
141
+ color="accentText"
142
+ >
143
+ <Step
144
+ isDone={step === "execute"}
145
+ isActive={step === "transfer"}
146
+ label={step === "transfer" ? "Transfer" : "Done"}
147
+ />
148
+ <ConnectorLine />
149
+ <Step
150
+ isDone={false}
151
+ label="Finalize"
152
+ isActive={step === "execute"}
153
+ />
154
+ </Container>
155
+ <Spacer y="lg" />
156
+ </>
157
+ )}
158
+
159
+ {status === "error" && (
160
+ <>
161
+ <Container flex="row" gap="xs" center="both" color="danger">
162
+ <CrossCircledIcon width={iconSize.sm} height={iconSize.sm} />
163
+ <Text color="danger" size="sm">
164
+ {step === "transfer" ? "Failed to Transfer" : "Failed to Execute"}
165
+ </Text>
166
+ </Container>
167
+ <Spacer y="md" />
168
+ </>
169
+ )}
170
+
171
+ {!transactionMode && step === "execute" && status === "done" && (
172
+ <>
173
+ <Container flex="row" gap="xs" center="both" color="success">
174
+ <CheckCircledIcon width={iconSize.sm} height={iconSize.sm} />
175
+ <Text color="success" size="sm">
176
+ {"Payment completed"}
177
+ </Text>
178
+ </Container>
179
+ <Spacer y="md" />
180
+ </>
181
+ )}
182
+
183
+ {/* Execute */}
184
+ {payer.chain.id !== chain.id ? (
185
+ <SwitchNetworkButton
186
+ fullWidth
187
+ variant="accent"
188
+ switchChain={async () => {
189
+ await props.payer.wallet.switchChain(chain);
190
+ }}
191
+ />
192
+ ) : (
193
+ <Button
194
+ variant="accent"
195
+ fullWidth
196
+ disabled={status === "pending"}
197
+ onClick={async () => {
198
+ if (step === "execute") {
199
+ onDone();
200
+ return;
201
+ }
202
+
203
+ try {
204
+ setStatus("pending");
205
+
206
+ // TRANSACTION MODE = transfer funds to another one of your wallets before executing the tx
207
+ if (transactionMode) {
208
+ const transaction = isNativeToken(token)
209
+ ? prepareTransaction({
210
+ client,
211
+ chain,
212
+ to: receiverAddress,
213
+ value: toWei(tokenAmount),
214
+ })
215
+ : transfer({
216
+ contract: getContract({
217
+ address: token.address,
218
+ chain: chain,
219
+ client: client,
220
+ }),
221
+ to: receiverAddress,
222
+ amount: tokenAmount,
223
+ });
224
+ await sendAndConfirmTransaction({
225
+ account: props.payer.account,
226
+ transaction,
227
+ });
228
+ // switch to execute step
229
+ setStep("execute");
230
+ setStatus("idle");
231
+ } else {
232
+ const transferResponse = await getBuyWithCryptoTransfer({
233
+ client,
234
+ fromAddress: payer.account.address,
235
+ toAddress: receiverAddress,
236
+ chainId: chain.id,
237
+ tokenAddress: isNativeToken(token)
238
+ ? NATIVE_TOKEN_ADDRESS
239
+ : token.address,
240
+ amount: tokenAmount,
241
+ purchaseData: undefined, // TODO (pay): add purchase data
242
+ });
243
+
244
+ console.log("transferResponse", transferResponse);
245
+ if (transferResponse.approval) {
246
+ setStep("approve");
247
+ // approve the transfer
248
+ await sendAndConfirmTransaction({
249
+ account: props.payer.account,
250
+ transaction: transferResponse.approval,
251
+ });
252
+ }
253
+
254
+ setStep("transfer");
255
+ // execute the transfer
256
+ const transaction = transferResponse.transactionRequest;
257
+ const tx = await sendTransaction({
258
+ account: props.payer.account,
259
+ transaction,
260
+ });
261
+ // switches to the status polling screen
262
+ setTransactionHash(tx.transactionHash);
263
+ setStatus("idle");
264
+ }
265
+ } catch (e) {
266
+ console.error(e);
267
+ setStatus("error");
268
+ }
269
+ }}
270
+ gap="xs"
271
+ >
272
+ {step === "execute" && (status === "done" ? "Done" : "Continue")}
273
+ {step === "transfer" &&
274
+ (status === "pending" ? "Confirming" : "Confirm")}
275
+ {step === "approve" &&
276
+ (status === "pending" ? "Approving" : "Approve")}
277
+ {status === "pending" && (
278
+ <Spinner size="sm" color="accentButtonText" />
279
+ )}
280
+ </Button>
281
+ )}
282
+ </Container>
283
+ );
284
+ }
@@ -1,28 +1,11 @@
1
- import { CheckCircledIcon, CrossCircledIcon } from "@radix-ui/react-icons";
2
1
  import { useState } from "react";
3
2
  import type { Chain } from "../../../../../../../chains/types.js";
4
3
  import type { ThirdwebClient } from "../../../../../../../client/client.js";
5
- import { NATIVE_TOKEN_ADDRESS } from "../../../../../../../constants/addresses.js";
6
- import { getContract } from "../../../../../../../contract/contract.js";
7
- import { transfer } from "../../../../../../../extensions/erc20/write/transfer.js";
8
- import { sendAndConfirmTransaction } from "../../../../../../../transaction/actions/send-and-confirm-transaction.js";
9
- import { prepareTransaction } from "../../../../../../../transaction/prepare-transaction.js";
10
- import { toWei } from "../../../../../../../utils/units.js";
11
- import { iconSize } from "../../../../../../core/design-system/index.js";
12
- import { useChainSymbol } from "../../../../../../core/hooks/others/useChainQuery.js";
13
- import { Spacer } from "../../../../components/Spacer.js";
14
- import { Spinner } from "../../../../components/Spinner.js";
15
- import { StepBar } from "../../../../components/StepBar.js";
16
- import { SwitchNetworkButton } from "../../../../components/SwitchNetwork.js";
17
- import { Container, Line, ModalHeader } from "../../../../components/basic.js";
18
- import { Button } from "../../../../components/buttons.js";
19
- import { Text } from "../../../../components/text.js";
20
- import { type ERC20OrNativeToken, isNativeToken } from "../../nativeToken.js";
21
- import { Step } from "../Stepper.js";
22
- import { WalletRow } from "../WalletSelectorButton.js";
23
- import { TokenInfoRow } from "../pay-transactions/TokenInfoRow.js";
4
+ import type { BuyWithCryptoStatus } from "../../../../../../../pay/buyWithCrypto/getStatus.js";
5
+ import type { ERC20OrNativeToken } from "../../nativeToken.js";
24
6
  import type { PayerInfo } from "../types.js";
25
- import { ConnectorLine } from "./ConfirmationScreen.js";
7
+ import { SwapStatusScreen } from "./SwapStatusScreen.js";
8
+ import { TransferConfirmationScreen } from "./TransferConfirmationScreen.js";
26
9
 
27
10
  type TrasnferFlowProps = {
28
11
  title: string;
@@ -31,6 +14,9 @@ type TrasnferFlowProps = {
31
14
  receiverAddress: string;
32
15
  client: ThirdwebClient;
33
16
  onDone: () => void;
17
+ onTryAgain: () => void;
18
+ isEmbed: boolean;
19
+ onSuccess: ((status: BuyWithCryptoStatus) => void) | undefined;
34
20
  chain: Chain;
35
21
  token: ERC20OrNativeToken;
36
22
  tokenAmount: string;
@@ -38,206 +24,29 @@ type TrasnferFlowProps = {
38
24
  };
39
25
 
40
26
  export function TransferFlow(props: TrasnferFlowProps) {
41
- const {
42
- title,
43
- onBack,
44
- receiverAddress,
45
- client,
46
- payer,
47
- onDone,
48
- chain,
49
- token,
50
- tokenAmount,
51
- transactionMode,
52
- } = props;
53
- const [step, setStep] = useState<"transfer" | "execute">("transfer");
54
- const [status, setStatus] = useState<"idle" | "pending" | "error" | "done">(
55
- "idle",
56
- );
57
- const { symbol } = useChainSymbol(chain);
58
-
59
- return (
60
- <Container p="lg">
61
- <ModalHeader title={title} onBack={onBack} />
62
- <Spacer y="xl" />
63
-
64
- {transactionMode && (
65
- <>
66
- <StepBar steps={2} currentStep={step === "transfer" ? 1 : 2} />
67
- <Spacer y="sm" />
68
- <Text size="sm">
69
- {step === "transfer"
70
- ? "Step 1 of 2 - Transfer funds"
71
- : "Step 2 of 2 - Finalize transaction"}
72
- </Text>
73
- <Spacer y="xl" />
74
- </>
75
- )}
76
-
77
- {/* Sender Address */}
78
- <Container
79
- flex="row"
80
- center="y"
81
- style={{
82
- justifyContent: "space-between",
83
- }}
84
- >
85
- <Text size="sm">From</Text>
86
- <WalletRow address={payer.account.address} client={client} />
87
- </Container>
88
-
89
- <Spacer y="md" />
90
- <Line />
91
- <Spacer y="md" />
92
-
93
- {/* Receiver Address */}
94
- <Container
95
- flex="row"
96
- center="y"
97
- style={{
98
- justifyContent: "space-between",
99
- }}
100
- >
101
- <Text size="sm">To</Text>
102
- <WalletRow address={receiverAddress} client={client} />
103
- </Container>
104
-
105
- <Spacer y="md" />
106
- <Line />
107
- <Spacer y="md" />
108
-
109
- {/* Token Info */}
110
- <TokenInfoRow
111
- chainId={chain.id}
112
- client={client}
113
- label={"Amount"}
114
- tokenAmount={tokenAmount}
115
- tokenSymbol={isNativeToken(token) ? symbol || "" : token.symbol}
116
- tokenAddress={
117
- isNativeToken(token) ? NATIVE_TOKEN_ADDRESS : token.address
118
- }
27
+ const [transferTxHash, setTransferTxHash] = useState<string | undefined>();
28
+
29
+ if (transferTxHash) {
30
+ return (
31
+ <SwapStatusScreen
32
+ title={props.title}
33
+ onBack={props.onBack}
34
+ onTryAgain={props.onTryAgain}
35
+ swapTxHash={transferTxHash}
36
+ client={props.client}
37
+ onDone={props.onDone}
38
+ transactionMode={false}
39
+ isEmbed={props.isEmbed}
40
+ quote={undefined}
41
+ onSuccess={props.onSuccess}
119
42
  />
43
+ );
44
+ }
120
45
 
121
- <Spacer y="lg" />
122
-
123
- {transactionMode && (
124
- <>
125
- <Spacer y="sm" />
126
- <Container
127
- gap="sm"
128
- flex="row"
129
- style={{
130
- justifyContent: "space-between",
131
- }}
132
- center="y"
133
- color="accentText"
134
- >
135
- <Step
136
- isDone={step === "execute"}
137
- isActive={step === "transfer"}
138
- label={step === "transfer" ? "Transfer" : "Done"}
139
- />
140
- <ConnectorLine />
141
- <Step
142
- isDone={false}
143
- label="Finalize"
144
- isActive={step === "execute"}
145
- />
146
- </Container>
147
- <Spacer y="lg" />
148
- </>
149
- )}
150
-
151
- {status === "error" && (
152
- <>
153
- <Container flex="row" gap="xs" center="both" color="danger">
154
- <CrossCircledIcon width={iconSize.sm} height={iconSize.sm} />
155
- <Text color="danger" size="sm">
156
- {step === "transfer" ? "Failed to Transfer" : "Failed to Execute"}
157
- </Text>
158
- </Container>
159
- <Spacer y="md" />
160
- </>
161
- )}
162
-
163
- {!transactionMode && step === "execute" && status === "done" && (
164
- <>
165
- <Container flex="row" gap="xs" center="both" color="success">
166
- <CheckCircledIcon width={iconSize.sm} height={iconSize.sm} />
167
- <Text color="success" size="sm">
168
- {"Payment completed"}
169
- </Text>
170
- </Container>
171
- <Spacer y="md" />
172
- </>
173
- )}
174
-
175
- {/* Execute */}
176
- {payer.chain.id !== chain.id ? (
177
- <SwitchNetworkButton
178
- fullWidth
179
- variant="accent"
180
- switchChain={async () => {
181
- await props.payer.wallet.switchChain(chain);
182
- }}
183
- />
184
- ) : (
185
- <Button
186
- variant="accent"
187
- fullWidth
188
- disabled={status === "pending"}
189
- onClick={async () => {
190
- if (step === "execute") {
191
- onDone();
192
- return;
193
- }
194
-
195
- try {
196
- setStatus("pending");
197
-
198
- const transaction = isNativeToken(token)
199
- ? prepareTransaction({
200
- client,
201
- chain,
202
- to: receiverAddress,
203
- value: toWei(tokenAmount),
204
- })
205
- : transfer({
206
- contract: getContract({
207
- address: token.address,
208
- chain: chain,
209
- client: client,
210
- }),
211
- to: receiverAddress,
212
- amount: tokenAmount,
213
- });
214
-
215
- await sendAndConfirmTransaction({
216
- account: props.payer.account,
217
- transaction,
218
- });
219
-
220
- setStep("execute");
221
- if (transactionMode) {
222
- setStatus("idle");
223
- } else {
224
- setStatus("done");
225
- }
226
- } catch (e) {
227
- console.error(e);
228
- setStatus("error");
229
- }
230
- }}
231
- gap="xs"
232
- >
233
- {step === "execute" && (status === "done" ? "Done" : "Continue")}
234
- {step === "transfer" &&
235
- (status === "pending" ? "Confirming" : "Confirm")}
236
- {status === "pending" && (
237
- <Spinner size="sm" color="accentButtonText" />
238
- )}
239
- </Button>
240
- )}
241
- </Container>
46
+ return (
47
+ <TransferConfirmationScreen
48
+ {...props}
49
+ setTransactionHash={setTransferTxHash}
50
+ />
242
51
  );
243
52
  }