thirdweb 5.88.4 → 5.88.5-nightly-0574eac02c832c382972fd545df79c36e11796e1-20250217000342

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 (180) hide show
  1. package/dist/cjs/adapters/eip1193/to-eip1193.js +16 -0
  2. package/dist/cjs/adapters/eip1193/to-eip1193.js.map +1 -1
  3. package/dist/cjs/contract/deployment/deploy-via-autofactory.js +33 -9
  4. package/dist/cjs/contract/deployment/deploy-via-autofactory.js.map +1 -1
  5. package/dist/cjs/exports/contract.js +3 -1
  6. package/dist/cjs/exports/contract.js.map +1 -1
  7. package/dist/cjs/exports/modules.js +3 -1
  8. package/dist/cjs/exports/modules.js.map +1 -1
  9. package/dist/cjs/extensions/modules/common/installPublishedModule.js +4 -1
  10. package/dist/cjs/extensions/modules/common/installPublishedModule.js.map +1 -1
  11. package/dist/cjs/extensions/prebuilts/deploy-published.js +14 -2
  12. package/dist/cjs/extensions/prebuilts/deploy-published.js.map +1 -1
  13. package/dist/cjs/extensions/thirdweb/__generated__/IContractFactory/events/ProxyDeployedV2.js +33 -0
  14. package/dist/cjs/extensions/thirdweb/__generated__/IContractFactory/events/ProxyDeployedV2.js.map +1 -0
  15. package/dist/cjs/extensions/thirdweb/__generated__/IContractFactory/write/deployProxyByImplementationV2.js +152 -0
  16. package/dist/cjs/extensions/thirdweb/__generated__/IContractFactory/write/deployProxyByImplementationV2.js.map +1 -0
  17. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +66 -56
  18. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
  19. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/PayWIthCreditCard.js +3 -1
  20. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/PayWIthCreditCard.js.map +1 -1
  21. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.js +2 -2
  22. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.js.map +1 -1
  23. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js +13 -13
  24. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js.map +1 -1
  25. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.js +6 -0
  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 +3 -1
  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/swap/BuyTokenInput.js +2 -26
  30. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.js.map +1 -1
  31. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.js +1 -1
  32. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.js.map +1 -1
  33. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.js +6 -12
  34. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.js.map +1 -1
  35. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js +2 -2
  36. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js.map +1 -1
  37. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js +198 -0
  38. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js.map +1 -0
  39. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +3 -3
  40. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js.map +1 -1
  41. package/dist/cjs/react/web/ui/ConnectWallet/screens/SignatureScreen.js +1 -1
  42. package/dist/cjs/react/web/ui/ConnectWallet/screens/SignatureScreen.js.map +1 -1
  43. package/dist/cjs/react/web/ui/components/buttons.js +11 -0
  44. package/dist/cjs/react/web/ui/components/buttons.js.map +1 -1
  45. package/dist/cjs/react/web/ui/components/token/TokenRow.js +36 -0
  46. package/dist/cjs/react/web/ui/components/token/TokenRow.js.map +1 -0
  47. package/dist/cjs/utils/abi/normalizeFunctionParams.js +6 -2
  48. package/dist/cjs/utils/abi/normalizeFunctionParams.js.map +1 -1
  49. package/dist/cjs/utils/ens/namehash.js.map +1 -1
  50. package/dist/cjs/version.js +1 -1
  51. package/dist/cjs/version.js.map +1 -1
  52. package/dist/esm/adapters/eip1193/to-eip1193.js +16 -0
  53. package/dist/esm/adapters/eip1193/to-eip1193.js.map +1 -1
  54. package/dist/esm/contract/deployment/deploy-via-autofactory.js +33 -9
  55. package/dist/esm/contract/deployment/deploy-via-autofactory.js.map +1 -1
  56. package/dist/esm/exports/contract.js +1 -0
  57. package/dist/esm/exports/contract.js.map +1 -1
  58. package/dist/esm/exports/modules.js +1 -0
  59. package/dist/esm/exports/modules.js.map +1 -1
  60. package/dist/esm/extensions/modules/common/installPublishedModule.js +4 -1
  61. package/dist/esm/extensions/modules/common/installPublishedModule.js.map +1 -1
  62. package/dist/esm/extensions/prebuilts/deploy-published.js +14 -2
  63. package/dist/esm/extensions/prebuilts/deploy-published.js.map +1 -1
  64. package/dist/esm/extensions/thirdweb/__generated__/IContractFactory/events/ProxyDeployedV2.js +30 -0
  65. package/dist/esm/extensions/thirdweb/__generated__/IContractFactory/events/ProxyDeployedV2.js.map +1 -0
  66. package/dist/esm/extensions/thirdweb/__generated__/IContractFactory/write/deployProxyByImplementationV2.js +145 -0
  67. package/dist/esm/extensions/thirdweb/__generated__/IContractFactory/write/deployProxyByImplementationV2.js.map +1 -0
  68. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +68 -58
  69. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
  70. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/PayWIthCreditCard.js +3 -1
  71. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/PayWIthCreditCard.js.map +1 -1
  72. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.js +1 -1
  73. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.js.map +1 -1
  74. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js +13 -13
  75. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js.map +1 -1
  76. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.js +6 -0
  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 +3 -1
  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/swap/BuyTokenInput.js +3 -27
  81. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.js.map +1 -1
  82. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.js +1 -1
  83. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.js.map +1 -1
  84. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.js +6 -12
  85. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.js.map +1 -1
  86. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js +2 -2
  87. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js.map +1 -1
  88. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js +194 -0
  89. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js.map +1 -0
  90. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +1 -1
  91. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js.map +1 -1
  92. package/dist/esm/react/web/ui/ConnectWallet/screens/SignatureScreen.js +1 -1
  93. package/dist/esm/react/web/ui/ConnectWallet/screens/SignatureScreen.js.map +1 -1
  94. package/dist/esm/react/web/ui/components/buttons.js +11 -0
  95. package/dist/esm/react/web/ui/components/buttons.js.map +1 -1
  96. package/dist/esm/react/web/ui/components/token/TokenRow.js +33 -0
  97. package/dist/esm/react/web/ui/components/token/TokenRow.js.map +1 -0
  98. package/dist/esm/utils/abi/normalizeFunctionParams.js +6 -2
  99. package/dist/esm/utils/abi/normalizeFunctionParams.js.map +1 -1
  100. package/dist/esm/utils/ens/namehash.js.map +1 -1
  101. package/dist/esm/version.js +1 -1
  102. package/dist/esm/version.js.map +1 -1
  103. package/dist/types/adapters/eip1193/to-eip1193.d.ts.map +1 -1
  104. package/dist/types/contract/deployment/deploy-via-autofactory.d.ts +8 -2
  105. package/dist/types/contract/deployment/deploy-via-autofactory.d.ts.map +1 -1
  106. package/dist/types/exports/contract.d.ts +1 -0
  107. package/dist/types/exports/contract.d.ts.map +1 -1
  108. package/dist/types/exports/modules.d.ts +1 -0
  109. package/dist/types/exports/modules.d.ts.map +1 -1
  110. package/dist/types/extensions/modules/common/installPublishedModule.d.ts +1 -0
  111. package/dist/types/extensions/modules/common/installPublishedModule.d.ts.map +1 -1
  112. package/dist/types/extensions/prebuilts/deploy-published.d.ts +2 -0
  113. package/dist/types/extensions/prebuilts/deploy-published.d.ts.map +1 -1
  114. package/dist/types/extensions/thirdweb/__generated__/IContractFactory/events/ProxyDeployedV2.d.ts +70 -0
  115. package/dist/types/extensions/thirdweb/__generated__/IContractFactory/events/ProxyDeployedV2.d.ts.map +1 -0
  116. package/dist/types/extensions/thirdweb/__generated__/IContractFactory/write/deployProxyByImplementationV2.d.ts +100 -0
  117. package/dist/types/extensions/thirdweb/__generated__/IContractFactory/write/deployProxyByImplementationV2.d.ts.map +1 -0
  118. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.d.ts.map +1 -1
  119. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/PayWIthCreditCard.d.ts.map +1 -1
  120. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.d.ts.map +1 -1
  121. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.d.ts +1 -0
  122. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.d.ts.map +1 -1
  123. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.d.ts.map +1 -1
  124. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.d.ts.map +1 -1
  125. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.d.ts.map +1 -1
  126. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.d.ts +1 -0
  127. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.d.ts.map +1 -1
  128. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.d.ts.map +1 -1
  129. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/{PaymentSelectionScreen.d.ts → TokenSelectorScreen.d.ts} +19 -14
  130. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.d.ts.map +1 -0
  131. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.d.ts.map +1 -1
  132. package/dist/types/react/web/ui/components/buttons.d.ts.map +1 -1
  133. package/dist/types/react/web/ui/components/token/TokenRow.d.ts +14 -0
  134. package/dist/types/react/web/ui/components/token/TokenRow.d.ts.map +1 -0
  135. package/dist/types/utils/abi/normalizeFunctionParams.d.ts.map +1 -1
  136. package/dist/types/utils/ens/namehash.d.ts.map +1 -1
  137. package/dist/types/version.d.ts +1 -1
  138. package/dist/types/version.d.ts.map +1 -1
  139. package/package.json +1 -1
  140. package/src/adapters/eip1193/to-eip1193.ts +18 -0
  141. package/src/contract/deployment/deploy-via-autofactory.test.ts +166 -0
  142. package/src/contract/deployment/deploy-via-autofactory.ts +50 -10
  143. package/src/exports/contract.ts +1 -0
  144. package/src/exports/modules.ts +1 -0
  145. package/src/extensions/modules/common/installPublishedModule.ts +5 -0
  146. package/src/extensions/prebuilts/deploy-published.ts +18 -2
  147. package/src/extensions/thirdweb/__generated__/IContractFactory/events/ProxyDeployedV2.ts +55 -0
  148. package/src/extensions/thirdweb/__generated__/IContractFactory/write/deployProxyByImplementationV2.ts +184 -0
  149. package/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx +132 -86
  150. package/src/react/web/ui/ConnectWallet/screens/Buy/PayWIthCreditCard.tsx +6 -1
  151. package/src/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.tsx +1 -1
  152. package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx +67 -66
  153. package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/currencies.tsx +7 -0
  154. package/src/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.ts +3 -1
  155. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/BuyTokenInput.tsx +9 -75
  156. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/FiatValue.tsx +3 -1
  157. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/PayWithCrypto.tsx +13 -41
  158. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.tsx +59 -53
  159. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.tsx +437 -0
  160. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx +1 -1
  161. package/src/react/web/ui/ConnectWallet/screens/SignatureScreen.tsx +1 -1
  162. package/src/react/web/ui/components/buttons.tsx +12 -0
  163. package/src/react/web/ui/components/token/TokenRow.tsx +111 -0
  164. package/src/utils/abi/normalizeFunctionParams.test.ts +26 -1
  165. package/src/utils/abi/normalizeFunctionParams.ts +9 -4
  166. package/src/utils/ens/namehash.ts +4 -1
  167. package/src/version.ts +1 -1
  168. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.js +0 -85
  169. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.js.map +0 -1
  170. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.js +0 -142
  171. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.js.map +0 -1
  172. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.js +0 -81
  173. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.js.map +0 -1
  174. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.js +0 -139
  175. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.js.map +0 -1
  176. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.d.ts +0 -22
  177. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.d.ts.map +0 -1
  178. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.d.ts.map +0 -1
  179. package/src/react/web/ui/ConnectWallet/screens/Buy/WalletSelectorButton.tsx +0 -220
  180. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/PaymentSelectionScreen.tsx +0 -263
@@ -42,6 +42,8 @@ export function FiatValue(
42
42
  }
43
43
 
44
44
  return cryptoToFiatQuery.data?.result ? (
45
- <Text {...props}>${formatNumber(cryptoToFiatQuery.data.result, 2)}</Text>
45
+ <Text {...props}>
46
+ ${formatNumber(cryptoToFiatQuery.data.result, 2).toFixed(2)}
47
+ </Text>
46
48
  ) : null;
47
49
  }
@@ -1,6 +1,5 @@
1
1
  import type { Chain } from "../../../../../../../chains/types.js";
2
2
  import type { ThirdwebClient } from "../../../../../../../client/client.js";
3
- import { formatNumber } from "../../../../../../../utils/formatNumber.js";
4
3
  import type { Account } from "../../../../../../../wallets/interfaces/wallet.js";
5
4
  import { useCustomTheme } from "../../../../../../core/design-system/CustomThemeProvider.js";
6
5
  import {
@@ -8,17 +7,16 @@ import {
8
7
  radius,
9
8
  spacing,
10
9
  } from "../../../../../../core/design-system/index.js";
11
- import { useChainName } from "../../../../../../core/hooks/others/useChainQuery.js";
12
10
  import { useWalletBalance } from "../../../../../../core/hooks/others/useWalletBalance.js";
13
11
  import type { TokenInfo } from "../../../../../../core/utils/defaultTokens.js";
14
12
  import { Skeleton } from "../../../../components/Skeleton.js";
15
13
  import { Container } from "../../../../components/basic.js";
16
14
  import { Text } from "../../../../components/text.js";
15
+ import { TokenRow } from "../../../../components/token/TokenRow.js";
17
16
  import { TokenSymbol } from "../../../../components/token/TokenSymbol.js";
18
17
  import { formatTokenBalance } from "../../formatTokenBalance.js";
19
18
  import { type NativeToken, isNativeToken } from "../../nativeToken.js";
20
- import { PayTokenIcon } from "../PayTokenIcon.js";
21
- import { WalletRow } from "../WalletSelectorButton.js";
19
+ import { WalletRow } from "./TokenSelectorScreen.js";
22
20
 
23
21
  /**
24
22
  * Shows an amount "value" and renders the selected token and chain
@@ -35,9 +33,9 @@ export function PayWithCryptoQuoteInfo(props: {
35
33
  freezeChainAndTokenSelection?: boolean;
36
34
  payerAccount: Account;
37
35
  swapRequired: boolean;
36
+ onSelectToken: () => void;
38
37
  }) {
39
38
  const theme = useCustomTheme();
40
- const { name } = useChainName(props.chain);
41
39
  const balanceQuery = useWalletBalance({
42
40
  address: props.payerAccount.address,
43
41
  chain: props.chain,
@@ -88,44 +86,18 @@ export function PayWithCryptoQuoteInfo(props: {
88
86
  )}
89
87
  </Container>
90
88
  {/* Quoted price */}
91
- <Container
92
- flex="row"
93
- gap="sm"
89
+ <TokenRow
90
+ token={props.token}
91
+ chain={props.chain}
92
+ client={props.client}
93
+ isLoading={props.isLoading}
94
+ value={props.value}
95
+ onSelectToken={props.onSelectToken}
94
96
  style={{
95
- paddingInline: spacing.sm,
96
- paddingBlock: spacing.sm,
97
- minWidth: "50%",
98
- justifyContent: "flex-start",
99
- minHeight: "64px",
97
+ border: "none",
98
+ borderRadius: 0,
100
99
  }}
101
- >
102
- <PayTokenIcon
103
- token={props.token}
104
- chain={props.chain}
105
- size="md"
106
- client={props.client}
107
- />
108
- <Container flex="column" gap="3xs">
109
- {props.isLoading ? (
110
- <Skeleton width="120px" height={fontSize.md} color="borderColor" />
111
- ) : (
112
- <Container flex="row" gap="xxs" center="y" color="primaryText">
113
- <Text
114
- size="md"
115
- color={props.value ? "primaryText" : "secondaryText"}
116
- >
117
- {formatNumber(Number(props.value), 6) || ""}
118
- </Text>
119
- <TokenSymbol token={props.token} chain={props.chain} size="sm" />
120
- </Container>
121
- )}
122
- {name ? (
123
- <Text size="xs">{name}</Text>
124
- ) : (
125
- <Skeleton width="90px" height={fontSize.xs} />
126
- )}
127
- </Container>
128
- </Container>
100
+ />
129
101
  </Container>
130
102
  );
131
103
  }
@@ -220,7 +220,7 @@ export function SwapScreenContent(props: {
220
220
  }
221
221
 
222
222
  return (
223
- <Container flex="column" gap="md" animate="fadein">
223
+ <Container flex="column" gap="lg" animate="fadein">
224
224
  {isOpen && (
225
225
  <>
226
226
  <DrawerOverlay ref={drawerOverlayRef} />
@@ -239,62 +239,60 @@ export function SwapScreenContent(props: {
239
239
  )}
240
240
 
241
241
  {/* Quote info */}
242
- <div>
243
- <PayWithCryptoQuoteInfo
244
- value={sourceTokenAmount || ""}
245
- chain={fromChain}
246
- token={fromToken}
247
- isLoading={quoteQuery.isLoading && !sourceTokenAmount}
248
- client={client}
249
- freezeChainAndTokenSelection={disableTokenSelection}
250
- payerAccount={props.payer.account}
251
- swapRequired={swapRequired}
252
- />
253
- {swapRequired && (
254
- <EstimatedTimeAndFees
255
- quoteIsLoading={quoteQuery.isLoading}
256
- estimatedSeconds={
257
- quoteQuery.data?.swapDetails.estimated.durationSeconds
258
- }
259
- onViewFees={showFees}
260
- />
261
- )}
262
- <Spacer y="md" />
263
- </div>
264
-
265
- {/* Error message */}
266
- {errorMsg && (
242
+ <Container flex="column" gap="sm">
267
243
  <div>
268
- {errorMsg.data?.minimumAmountEth ? (
269
- <Text color="danger" size="sm" center multiline>
270
- Minimum amount is{" "}
271
- {formatNumber(Number(errorMsg.data.minimumAmountEth), 6)}{" "}
272
- <TokenSymbol
273
- token={toToken}
274
- chain={toChain}
275
- size="sm"
276
- inline
277
- color="danger"
278
- />
279
- </Text>
280
- ) : (
281
- <Text color="danger" size="sm" center multiline>
282
- {errorMsg.message || defaultMessage}
283
- </Text>
244
+ <PayWithCryptoQuoteInfo
245
+ value={sourceTokenAmount || ""}
246
+ chain={fromChain}
247
+ token={fromToken}
248
+ isLoading={quoteQuery.isLoading && !sourceTokenAmount}
249
+ client={client}
250
+ freezeChainAndTokenSelection={disableTokenSelection}
251
+ payerAccount={props.payer.account}
252
+ swapRequired={swapRequired}
253
+ onSelectToken={props.showFromTokenSelector}
254
+ />
255
+ {swapRequired && (
256
+ <EstimatedTimeAndFees
257
+ quoteIsLoading={quoteQuery.isLoading}
258
+ estimatedSeconds={
259
+ quoteQuery.data?.swapDetails.estimated.durationSeconds
260
+ }
261
+ onViewFees={showFees}
262
+ />
284
263
  )}
285
264
  </div>
286
- )}
265
+ {/* Error message */}
266
+ {errorMsg && (
267
+ <div>
268
+ {errorMsg.data?.minimumAmountEth ? (
269
+ <Text color="danger" size="xs" center multiline>
270
+ Minimum amount is{" "}
271
+ {formatNumber(Number(errorMsg.data.minimumAmountEth), 6)}{" "}
272
+ <TokenSymbol
273
+ token={toToken}
274
+ chain={toChain}
275
+ size="sm"
276
+ inline
277
+ color="danger"
278
+ />
279
+ </Text>
280
+ ) : (
281
+ <Text color="danger" size="xs" center multiline>
282
+ {errorMsg.message || defaultMessage}
283
+ </Text>
284
+ )}
285
+ </div>
286
+ )}
287
287
 
288
- {!errorMsg && isNotEnoughBalance && (
289
- <div>
290
- <Text color="danger" size="sm" center multiline>
291
- Not enough funds.
292
- </Text>
293
- <Text color="danger" size="sm" center multiline>
294
- Try a different wallet or token.
295
- </Text>
296
- </div>
297
- )}
288
+ {!errorMsg && isNotEnoughBalance && (
289
+ <div>
290
+ <Text color="danger" size="xs" center multiline>
291
+ Not enough funds.
292
+ </Text>
293
+ </div>
294
+ )}
295
+ </Container>
298
296
 
299
297
  {/* Button */}
300
298
  {errorMsg?.data?.minimumAmountEth ? (
@@ -313,6 +311,14 @@ export function SwapScreenContent(props: {
313
311
  >
314
312
  Set Minimum
315
313
  </Button>
314
+ ) : isNotEnoughBalance || errorMsg ? (
315
+ <Button
316
+ variant="accent"
317
+ fullWidth
318
+ onClick={() => props.showFromTokenSelector()}
319
+ >
320
+ Select another token
321
+ </Button>
316
322
  ) : switchChainRequired &&
317
323
  !quoteQuery.isLoading &&
318
324
  !allowanceQuery.isLoading &&
@@ -0,0 +1,437 @@
1
+ import styled from "@emotion/styled";
2
+ import { useQuery } from "@tanstack/react-query";
3
+ import type { Chain } from "../../../../../../../chains/types.js";
4
+ import { getCachedChain } from "../../../../../../../chains/utils.js";
5
+ import type { ThirdwebClient } from "../../../../../../../client/client.js";
6
+ import { NATIVE_TOKEN_ADDRESS } from "../../../../../../../constants/addresses.js";
7
+ import { shortenAddress } from "../../../../../../../utils/address.js";
8
+ import type { Wallet } from "../../../../../../../wallets/interfaces/wallet.js";
9
+ import {
10
+ type GetWalletBalanceResult,
11
+ getWalletBalance,
12
+ } from "../../../../../../../wallets/utils/getWalletBalance.js";
13
+ import type { WalletId } from "../../../../../../../wallets/wallet-types.js";
14
+ import { useCustomTheme } from "../../../../../../core/design-system/CustomThemeProvider.js";
15
+ import {
16
+ type fontSize,
17
+ iconSize,
18
+ radius,
19
+ spacing,
20
+ } from "../../../../../../core/design-system/index.js";
21
+ import type { PayUIOptions } from "../../../../../../core/hooks/connection/ConnectButtonProps.js";
22
+ import {
23
+ useChainMetadata,
24
+ useChainName,
25
+ } from "../../../../../../core/hooks/others/useChainQuery.js";
26
+ import { useActiveAccount } from "../../../../../../core/hooks/wallets/useActiveAccount.js";
27
+ import { useConnectedWallets } from "../../../../../../core/hooks/wallets/useConnectedWallets.js";
28
+ import type {
29
+ SupportedTokens,
30
+ TokenInfo,
31
+ } from "../../../../../../core/utils/defaultTokens.js";
32
+ import {
33
+ useEnsAvatar,
34
+ useEnsName,
35
+ } from "../../../../../../core/utils/wallet.js";
36
+ import { LoadingScreen } from "../../../../../wallets/shared/LoadingScreen.js";
37
+ import { Img } from "../../../../components/Img.js";
38
+ import { TextDivider } from "../../../../components/TextDivider.js";
39
+ import { TokenIcon } from "../../../../components/TokenIcon.js";
40
+ import { WalletImage } from "../../../../components/WalletImage.js";
41
+ import { Container, Line, ModalHeader } from "../../../../components/basic.js";
42
+ import { Button } from "../../../../components/buttons.js";
43
+ import { Text } from "../../../../components/text.js";
44
+ import { Blobbie } from "../../../Blobbie.js";
45
+ import { OutlineWalletIcon } from "../../../icons/OutlineWalletIcon.js";
46
+ import type { ConnectLocale } from "../../../locale/types.js";
47
+ import { formatTokenBalance } from "../../formatTokenBalance.js";
48
+ import { type ERC20OrNativeToken, isNativeToken } from "../../nativeToken.js";
49
+ import { FiatValue } from "./FiatValue.js";
50
+
51
+ type TokenBalance = {
52
+ balance: GetWalletBalanceResult;
53
+ chain: Chain;
54
+ token: TokenInfo;
55
+ };
56
+
57
+ export function TokenSelectorScreen(props: {
58
+ client: ThirdwebClient;
59
+ sourceTokens: SupportedTokens | undefined;
60
+ sourceSupportedTokens: SupportedTokens | undefined;
61
+ toChain: Chain;
62
+ toToken: ERC20OrNativeToken;
63
+ fromToken: ERC20OrNativeToken;
64
+ fromChain: Chain;
65
+ tokenAmount: string;
66
+ mode: PayUIOptions["mode"];
67
+ hiddenWallets?: WalletId[];
68
+ onSelect: (wallet: Wallet, token: TokenInfo, chain: Chain) => void;
69
+ onBack: () => void;
70
+ onConnect: () => void;
71
+ modalTitle?: string;
72
+ connectLocale: ConnectLocale;
73
+ }) {
74
+ const connectedWallets = useConnectedWallets();
75
+ const activeAccount = useActiveAccount();
76
+ const chainInfo = useChainMetadata(props.toChain);
77
+ const theme = useCustomTheme();
78
+ const locale = props.connectLocale.sendFundsScreen;
79
+
80
+ const walletsAndBalances = useQuery({
81
+ queryKey: [
82
+ "wallets-and-balances",
83
+ props.sourceSupportedTokens,
84
+ props.toChain.id,
85
+ props.toToken,
86
+ props.tokenAmount,
87
+ props.mode,
88
+ activeAccount?.address,
89
+ connectedWallets.map((w) => w.getAccount()?.address),
90
+ ],
91
+ queryFn: async () => {
92
+ // in parallel, get the balances of all the wallets on each of the sourceSupportedTokens
93
+ const walletBalanceMap = new Map<Wallet, TokenBalance[]>();
94
+
95
+ const balancePromises = connectedWallets.flatMap((wallet) => {
96
+ const account = wallet.getAccount();
97
+ if (!account) return [];
98
+ walletBalanceMap.set(wallet, []);
99
+
100
+ // inject the destination token too since it can be used as well to pay/transfer
101
+ const toToken = isNativeToken(props.toToken)
102
+ ? {
103
+ address: NATIVE_TOKEN_ADDRESS,
104
+ name: chainInfo.data?.nativeCurrency.name || "",
105
+ symbol: chainInfo.data?.nativeCurrency.symbol || "",
106
+ icon: chainInfo.data?.icon?.url,
107
+ }
108
+ : props.toToken;
109
+
110
+ const tokens = {
111
+ ...props.sourceSupportedTokens,
112
+ [props.toChain.id]: [
113
+ toToken,
114
+ ...(props.sourceSupportedTokens?.[props.toChain.id] || []),
115
+ ],
116
+ };
117
+
118
+ return Object.entries(tokens).flatMap(([chainId, tokens]) => {
119
+ return tokens.map(async (token) => {
120
+ try {
121
+ const chain = getCachedChain(Number(chainId));
122
+ const balance = await getWalletBalance({
123
+ address: account.address,
124
+ chain,
125
+ tokenAddress: isNativeToken(token) ? undefined : token.address,
126
+ client: props.client,
127
+ });
128
+
129
+ // show the token if:
130
+ // - its not the destination token and balance is greater than 0
131
+ // - its the destination token and balance is greater than the token amount AND we the account is not the default account in fund_wallet mode
132
+ const shouldInclude =
133
+ token.address === toToken.address &&
134
+ chain.id === props.toChain.id
135
+ ? props.mode === "fund_wallet" &&
136
+ account.address === activeAccount?.address
137
+ ? false
138
+ : Number(balance.displayValue) > Number(props.tokenAmount)
139
+ : balance.value > 0n;
140
+
141
+ if (shouldInclude) {
142
+ const existingBalances = walletBalanceMap.get(wallet) || [];
143
+ existingBalances.push({ balance, chain, token });
144
+ existingBalances.sort((a, b) => {
145
+ if (
146
+ a.chain.id === props.toChain.id &&
147
+ a.token.address === toToken.address
148
+ )
149
+ return -1;
150
+ if (
151
+ b.chain.id === props.toChain.id &&
152
+ b.token.address === toToken.address
153
+ )
154
+ return 1;
155
+ if (a.chain.id === props.toChain.id) return -1;
156
+ if (b.chain.id === props.toChain.id) return 1;
157
+ return a.chain.id > b.chain.id ? 1 : -1;
158
+ });
159
+ }
160
+ } catch (error) {
161
+ console.error(
162
+ `Failed to fetch balance for wallet ${wallet.id} on chain ${chainId} for token ${token.symbol}:`,
163
+ error,
164
+ );
165
+ }
166
+ });
167
+ });
168
+ });
169
+
170
+ await Promise.all(balancePromises);
171
+ return walletBalanceMap;
172
+ },
173
+ enabled: !!props.sourceSupportedTokens && !!chainInfo.data,
174
+ });
175
+
176
+ if (walletsAndBalances.isLoading || !walletsAndBalances.data) {
177
+ return <LoadingScreen />;
178
+ }
179
+
180
+ const filteredWallets = Array.from(walletsAndBalances.data.entries() || [])
181
+ .filter(([w]) => !props.hiddenWallets?.includes(w.id))
182
+ .filter(([, balances]) => {
183
+ const hasEnoughBalance = balances.some((b) => b.balance.value > 0);
184
+ return hasEnoughBalance;
185
+ });
186
+
187
+ return (
188
+ <Container
189
+ animate="fadein"
190
+ style={{
191
+ minHeight: "300px",
192
+ }}
193
+ >
194
+ <Container py="md" px="lg">
195
+ <ModalHeader
196
+ onBack={props.onBack}
197
+ title={props.modalTitle || locale.selectTokenTitle}
198
+ />
199
+ </Container>
200
+
201
+ <Line />
202
+
203
+ <Container
204
+ scrollY
205
+ style={{
206
+ maxHeight: "450px",
207
+ }}
208
+ >
209
+ <Container flex="column" gap="sm" p="lg">
210
+ {filteredWallets.length === 0 && (
211
+ <Container flex="column" gap="xs" py="md">
212
+ <Text size="xs" color="secondaryText" center>
213
+ <i>
214
+ No suitable payment token found
215
+ <br />
216
+ in connected wallets
217
+ </i>
218
+ </Text>
219
+ </Container>
220
+ )}
221
+ {filteredWallets.map(([w, balances]) => {
222
+ const address = w.getAccount()?.address;
223
+ if (!address) return null;
224
+ return (
225
+ <WalletRowWithBalances
226
+ key={w.id}
227
+ wallet={w}
228
+ balances={balances}
229
+ client={props.client}
230
+ address={address}
231
+ onClick={props.onSelect}
232
+ />
233
+ );
234
+ })}
235
+ {filteredWallets.length > 0 && <TextDivider text="OR" />}
236
+ <Button
237
+ variant="secondary"
238
+ fullWidth
239
+ onClick={props.onConnect}
240
+ gap="xs"
241
+ bg="tertiaryBg"
242
+ style={{
243
+ borderRadius: radius.md,
244
+ border: `1px solid ${theme.colors.borderColor}`,
245
+ padding: spacing.sm,
246
+ }}
247
+ >
248
+ <Container
249
+ flex="row"
250
+ gap="sm"
251
+ center="y"
252
+ expand
253
+ color="secondaryIconColor"
254
+ >
255
+ <OutlineWalletIcon size={iconSize.md} />
256
+ <Text size="sm" color="primaryText">
257
+ Connect another wallet
258
+ </Text>
259
+ </Container>
260
+ </Button>
261
+ </Container>
262
+ </Container>
263
+ </Container>
264
+ );
265
+ }
266
+
267
+ function WalletRowWithBalances(props: {
268
+ client: ThirdwebClient;
269
+ address: string;
270
+ wallet: Wallet;
271
+ balances: TokenBalance[];
272
+ onClick: (wallet: Wallet, token: TokenInfo, chain: Chain) => void;
273
+ hideConnectButton?: boolean;
274
+ }) {
275
+ const displayedBalances = props.balances;
276
+
277
+ return (
278
+ <Container flex="column" gap="sm">
279
+ <Container px="sm">
280
+ <WalletRow {...props} />
281
+ </Container>
282
+ <Container flex="column" gap="sm">
283
+ {props.balances.length > 0 ? (
284
+ displayedBalances.map((b) => (
285
+ <TokenBalanceRow
286
+ client={props.client}
287
+ onClick={() => props.onClick(props.wallet, b.token, b.chain)}
288
+ key={`${b.token.address}-${b.chain.id}`}
289
+ tokenBalance={b}
290
+ wallet={props.wallet}
291
+ />
292
+ ))
293
+ ) : (
294
+ <Container style={{ padding: spacing.sm }}>
295
+ <Text size="sm" color="secondaryText">
296
+ Not enough funds
297
+ </Text>
298
+ </Container>
299
+ )}
300
+ </Container>
301
+ </Container>
302
+ );
303
+ }
304
+
305
+ function TokenBalanceRow(props: {
306
+ client: ThirdwebClient;
307
+ tokenBalance: TokenBalance;
308
+ wallet: Wallet;
309
+ onClick: (token: TokenInfo, wallet: Wallet) => void;
310
+ }) {
311
+ const { tokenBalance, wallet, onClick, client } = props;
312
+ const chainInfo = useChainName(tokenBalance.chain);
313
+ return (
314
+ <StyledButton
315
+ onClick={() => onClick(tokenBalance.token, wallet)}
316
+ variant="secondary"
317
+ >
318
+ <Container flex="row" center="y" gap="md">
319
+ <TokenIcon
320
+ token={tokenBalance.token}
321
+ chain={tokenBalance.chain}
322
+ size="md"
323
+ client={client}
324
+ />
325
+ <Container flex="column" gap="3xs">
326
+ <Text size="xs" color="primaryText">
327
+ {tokenBalance.token.symbol}
328
+ </Text>
329
+ {chainInfo && <Text size="xs">{chainInfo.name}</Text>}
330
+ </Container>
331
+ </Container>
332
+ <Container flex="row" center="y" gap="3xs" color="secondaryText">
333
+ <Container
334
+ flex="column"
335
+ color="secondaryText"
336
+ gap="3xs"
337
+ style={{
338
+ justifyContent: "flex-end",
339
+ alignItems: "flex-end",
340
+ }}
341
+ >
342
+ <Text size="xs" color="primaryText">
343
+ {formatTokenBalance(tokenBalance.balance, true, 2)}
344
+ </Text>
345
+ <FiatValue
346
+ tokenAmount={tokenBalance.balance.displayValue}
347
+ token={tokenBalance.token}
348
+ chain={tokenBalance.chain}
349
+ client={client}
350
+ size="xs"
351
+ />
352
+ </Container>
353
+ {/* <ChevronRightIcon width={iconSize.md} height={iconSize.md} /> */}
354
+ </Container>
355
+ </StyledButton>
356
+ );
357
+ }
358
+
359
+ export function WalletRow(props: {
360
+ client: ThirdwebClient;
361
+ address: string;
362
+ iconSize?: keyof typeof iconSize;
363
+ textSize?: keyof typeof fontSize;
364
+ walletId?: WalletId;
365
+ wallet?: Wallet;
366
+ }) {
367
+ const { client, address } = props;
368
+ const walletId = props.walletId;
369
+ const theme = useCustomTheme();
370
+ const ensNameQuery = useEnsName({
371
+ client,
372
+ address,
373
+ });
374
+ const addressOrENS = ensNameQuery.data || shortenAddress(address);
375
+ const ensAvatarQuery = useEnsAvatar({
376
+ client,
377
+ ensName: ensNameQuery.data,
378
+ });
379
+ return (
380
+ <Container flex="row" style={{ justifyContent: "space-between" }}>
381
+ <Container flex="row" center="y" gap="sm" color="secondaryText">
382
+ {ensAvatarQuery.data ? (
383
+ <Img
384
+ src={ensAvatarQuery.data}
385
+ width={props.iconSize ? iconSize[props.iconSize] : iconSize.md}
386
+ height={props.iconSize ? iconSize[props.iconSize] : iconSize.md}
387
+ style={{
388
+ borderRadius: radius.sm,
389
+ overflow: "hidden",
390
+ border: `1px solid ${theme.colors.borderColor}`,
391
+ }}
392
+ client={props.client}
393
+ />
394
+ ) : walletId ? (
395
+ <WalletImage
396
+ id={walletId}
397
+ size={props.iconSize || iconSize.md}
398
+ client={props.client}
399
+ />
400
+ ) : (
401
+ <Container
402
+ style={{
403
+ width: iconSize.md,
404
+ height: iconSize.md,
405
+ borderRadius: radius.sm,
406
+ overflow: "hidden",
407
+ border: `1px solid ${theme.colors.borderColor}`,
408
+ }}
409
+ >
410
+ <Blobbie address={props.address} size={Number(iconSize.md)} />
411
+ </Container>
412
+ )}
413
+
414
+ <Text size={props.textSize || "sm"} color="primaryText">
415
+ {addressOrENS || shortenAddress(props.address)}
416
+ </Text>
417
+ </Container>
418
+ </Container>
419
+ );
420
+ }
421
+
422
+ const StyledButton = /* @__PURE__ */ styled(Button)((_) => {
423
+ const theme = useCustomTheme();
424
+ return {
425
+ background: theme.colors.tertiaryBg,
426
+ justifyContent: "space-between",
427
+ flexDirection: "row",
428
+ padding: spacing.sm,
429
+ border: `1px solid ${theme.colors.borderColor}`,
430
+ gap: spacing.sm,
431
+ "&:hover": {
432
+ background: theme.colors.secondaryButtonBg,
433
+ transform: "scale(1.01)",
434
+ },
435
+ transition: "background 200ms ease, transform 150ms ease",
436
+ };
437
+ });
@@ -26,10 +26,10 @@ import { Button } from "../../../../components/buttons.js";
26
26
  import { Text } from "../../../../components/text.js";
27
27
  import { type ERC20OrNativeToken, isNativeToken } from "../../nativeToken.js";
28
28
  import { Step } from "../Stepper.js";
29
- import { WalletRow } from "../WalletSelectorButton.js";
30
29
  import { TokenInfoRow } from "../pay-transactions/TokenInfoRow.js";
31
30
  import type { PayerInfo } from "../types.js";
32
31
  import { ConnectorLine } from "./ConfirmationScreen.js";
32
+ import { WalletRow } from "./TokenSelectorScreen.js";
33
33
 
34
34
  type TransferConfirmationScreenProps = {
35
35
  title: string;