thirdweb 5.94.1 → 5.95.0-nightly-4c1f384a635054a8cfaaa487e3ba7ada63b221ec-20250415110008

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 (166) hide show
  1. package/dist/cjs/exports/insight.js +5 -0
  2. package/dist/cjs/exports/insight.js.map +1 -0
  3. package/dist/cjs/exports/thirdweb.js +6 -2
  4. package/dist/cjs/exports/thirdweb.js.map +1 -1
  5. package/dist/cjs/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.js +104 -0
  6. package/dist/cjs/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.js.map +1 -0
  7. package/dist/cjs/extensions/thirdweb/write/publish.js +9 -4
  8. package/dist/cjs/extensions/thirdweb/write/publish.js.map +1 -1
  9. package/dist/cjs/insight/get-nfts.js +45 -0
  10. package/dist/cjs/insight/get-nfts.js.map +1 -0
  11. package/dist/cjs/insight/get-tokens.js +46 -0
  12. package/dist/cjs/insight/get-tokens.js.map +1 -0
  13. package/dist/cjs/insight/get-transactions.js +44 -0
  14. package/dist/cjs/insight/get-transactions.js.map +1 -0
  15. package/dist/cjs/insight/index.js +10 -0
  16. package/dist/cjs/insight/index.js.map +1 -0
  17. package/dist/cjs/react/web/ui/ConnectWallet/Details.js +4 -14
  18. package/dist/cjs/react/web/ui/ConnectWallet/Details.js.map +1 -1
  19. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/Stepper.js +2 -2
  20. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/Stepper.js.map +1 -1
  21. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.js +1 -1
  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 +2 -2
  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/swap/ConfirmationScreen.js +31 -3
  26. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js.map +1 -1
  27. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.js +12 -0
  28. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.js.map +1 -0
  29. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js +1 -1
  30. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js.map +1 -1
  31. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js +4 -4
  32. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js.map +1 -1
  33. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +31 -3
  34. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js.map +1 -1
  35. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewAssets.js +1 -1
  36. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewAssets.js.map +1 -1
  37. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewNFTs.js +74 -32
  38. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewNFTs.js.map +1 -1
  39. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewTokens.js +46 -6
  40. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewTokens.js.map +1 -1
  41. package/dist/cjs/react/web/ui/MediaRenderer/useResolvedMediaType.js +4 -1
  42. package/dist/cjs/react/web/ui/MediaRenderer/useResolvedMediaType.js.map +1 -1
  43. package/dist/cjs/react/web/utils/errors.js +5 -4
  44. package/dist/cjs/react/web/utils/errors.js.map +1 -1
  45. package/dist/cjs/transaction/transaction-store.js +11 -10
  46. package/dist/cjs/transaction/transaction-store.js.map +1 -1
  47. package/dist/cjs/utils/fetch.js +5 -4
  48. package/dist/cjs/utils/fetch.js.map +1 -1
  49. package/dist/cjs/version.js +1 -1
  50. package/dist/cjs/version.js.map +1 -1
  51. package/dist/cjs/wallets/injected/index.js +15 -0
  52. package/dist/cjs/wallets/injected/index.js.map +1 -1
  53. package/dist/esm/exports/insight.js +2 -0
  54. package/dist/esm/exports/insight.js.map +1 -0
  55. package/dist/esm/exports/thirdweb.js +4 -0
  56. package/dist/esm/exports/thirdweb.js.map +1 -1
  57. package/dist/esm/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.js +98 -0
  58. package/dist/esm/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.js.map +1 -0
  59. package/dist/esm/extensions/thirdweb/write/publish.js +9 -4
  60. package/dist/esm/extensions/thirdweb/write/publish.js.map +1 -1
  61. package/dist/esm/insight/get-nfts.js +42 -0
  62. package/dist/esm/insight/get-nfts.js.map +1 -0
  63. package/dist/esm/insight/get-tokens.js +43 -0
  64. package/dist/esm/insight/get-tokens.js.map +1 -0
  65. package/dist/esm/insight/get-transactions.js +41 -0
  66. package/dist/esm/insight/get-transactions.js.map +1 -0
  67. package/dist/esm/insight/index.js +4 -0
  68. package/dist/esm/insight/index.js.map +1 -0
  69. package/dist/esm/react/web/ui/ConnectWallet/Details.js +4 -14
  70. package/dist/esm/react/web/ui/ConnectWallet/Details.js.map +1 -1
  71. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/Stepper.js +2 -2
  72. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/Stepper.js.map +1 -1
  73. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.js +1 -1
  74. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.js.map +1 -1
  75. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js +3 -3
  76. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.js.map +1 -1
  77. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js +32 -4
  78. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js.map +1 -1
  79. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.js +9 -0
  80. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.js.map +1 -0
  81. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js +2 -2
  82. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.js.map +1 -1
  83. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js +4 -4
  84. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js.map +1 -1
  85. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +32 -4
  86. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js.map +1 -1
  87. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewAssets.js +1 -1
  88. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewAssets.js.map +1 -1
  89. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewNFTs.js +75 -33
  90. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewNFTs.js.map +1 -1
  91. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewTokens.js +46 -6
  92. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewTokens.js.map +1 -1
  93. package/dist/esm/react/web/ui/MediaRenderer/useResolvedMediaType.js +4 -1
  94. package/dist/esm/react/web/ui/MediaRenderer/useResolvedMediaType.js.map +1 -1
  95. package/dist/esm/react/web/utils/errors.js +5 -3
  96. package/dist/esm/react/web/utils/errors.js.map +1 -1
  97. package/dist/esm/transaction/transaction-store.js +11 -10
  98. package/dist/esm/transaction/transaction-store.js.map +1 -1
  99. package/dist/esm/utils/fetch.js +5 -4
  100. package/dist/esm/utils/fetch.js.map +1 -1
  101. package/dist/esm/version.js +1 -1
  102. package/dist/esm/version.js.map +1 -1
  103. package/dist/esm/wallets/injected/index.js +15 -0
  104. package/dist/esm/wallets/injected/index.js.map +1 -1
  105. package/dist/types/exports/insight.d.ts +2 -0
  106. package/dist/types/exports/insight.d.ts.map +1 -0
  107. package/dist/types/exports/thirdweb.d.ts +4 -0
  108. package/dist/types/exports/thirdweb.d.ts.map +1 -1
  109. package/dist/types/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.d.ts +64 -0
  110. package/dist/types/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.d.ts.map +1 -0
  111. package/dist/types/extensions/thirdweb/write/publish.d.ts.map +1 -1
  112. package/dist/types/insight/get-nfts.d.ts +25 -0
  113. package/dist/types/insight/get-nfts.d.ts.map +1 -0
  114. package/dist/types/insight/get-tokens.d.ts +25 -0
  115. package/dist/types/insight/get-tokens.d.ts.map +1 -0
  116. package/dist/types/insight/get-transactions.d.ts +25 -0
  117. package/dist/types/insight/get-transactions.d.ts.map +1 -0
  118. package/dist/types/insight/index.d.ts +4 -0
  119. package/dist/types/insight/index.d.ts.map +1 -0
  120. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts.map +1 -1
  121. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.d.ts.map +1 -1
  122. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.d.ts.map +1 -1
  123. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.d.ts.map +1 -1
  124. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.d.ts +5 -0
  125. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.d.ts.map +1 -0
  126. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.d.ts.map +1 -1
  127. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.d.ts.map +1 -1
  128. package/dist/types/react/web/ui/ConnectWallet/screens/ViewNFTs.d.ts.map +1 -1
  129. package/dist/types/react/web/ui/ConnectWallet/screens/ViewTokens.d.ts.map +1 -1
  130. package/dist/types/react/web/ui/MediaRenderer/useResolvedMediaType.d.ts +1 -1
  131. package/dist/types/react/web/ui/MediaRenderer/useResolvedMediaType.d.ts.map +1 -1
  132. package/dist/types/react/web/utils/errors.d.ts +2 -2
  133. package/dist/types/react/web/utils/errors.d.ts.map +1 -1
  134. package/dist/types/transaction/transaction-store.d.ts.map +1 -1
  135. package/dist/types/utils/fetch.d.ts +1 -1
  136. package/dist/types/utils/fetch.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/dist/types/wallets/injected/index.d.ts.map +1 -1
  140. package/package.json +8 -2
  141. package/src/exports/insight.ts +1 -0
  142. package/src/exports/thirdweb.ts +5 -0
  143. package/src/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.ts +104 -0
  144. package/src/extensions/thirdweb/write/publish.ts +12 -4
  145. package/src/insight/get-nfts.ts +62 -0
  146. package/src/insight/get-tokens.ts +63 -0
  147. package/src/insight/get-transactions.ts +66 -0
  148. package/src/insight/index.ts +3 -0
  149. package/src/react/web/ui/ConnectWallet/Details.tsx +15 -33
  150. package/src/react/web/ui/ConnectWallet/screens/Buy/Stepper.tsx +2 -2
  151. package/src/react/web/ui/ConnectWallet/screens/Buy/TransactionModeScreen.tsx +8 -3
  152. package/src/react/web/ui/ConnectWallet/screens/Buy/fiat/FiatScreenContent.tsx +10 -8
  153. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx +41 -11
  154. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/ErrorText.tsx +23 -0
  155. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/SwapScreenContent.tsx +13 -8
  156. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.tsx +4 -4
  157. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx +43 -9
  158. package/src/react/web/ui/ConnectWallet/screens/ViewAssets.tsx +1 -1
  159. package/src/react/web/ui/ConnectWallet/screens/ViewNFTs.tsx +107 -55
  160. package/src/react/web/ui/ConnectWallet/screens/ViewTokens.tsx +94 -11
  161. package/src/react/web/ui/MediaRenderer/useResolvedMediaType.ts +4 -1
  162. package/src/react/web/utils/errors.ts +11 -4
  163. package/src/transaction/transaction-store.ts +11 -22
  164. package/src/utils/fetch.ts +6 -5
  165. package/src/version.ts +1 -1
  166. package/src/wallets/injected/index.ts +16 -0
@@ -1,5 +1,4 @@
1
- import { useQueries } from "@tanstack/react-query";
2
- import { useMemo } from "react";
1
+ import { useQuery } from "@tanstack/react-query";
3
2
  import type { Chain } from "../../../../../chains/types.js";
4
3
  import { getCachedChain } from "../../../../../chains/utils.js";
5
4
  import type { ThirdwebClient } from "../../../../../client/client.js";
@@ -8,6 +7,9 @@ import { getOwnedNFTs as getErc721OwnedNFTs } from "../../../../../extensions/er
8
7
  import { isERC721 } from "../../../../../extensions/erc721/read/isERC721.js";
9
8
  import { getOwnedNFTs as getErc1155OwnedNFTs } from "../../../../../extensions/erc1155/read/getOwnedNFTs.js";
10
9
  import { isERC1155 } from "../../../../../extensions/erc1155/read/isERC1155.js";
10
+ import { getOwnedNFTs } from "../../../../../insight/get-nfts.js";
11
+ import type { Address } from "../../../../../utils/address.js";
12
+ import type { NFT } from "../../../../../utils/nft/parseNft.js";
11
13
  import type { Theme } from "../../../../core/design-system/index.js";
12
14
  import { useActiveAccount } from "../../../../core/hooks/wallets/useActiveAccount.js";
13
15
  import { useActiveWalletChain } from "../../../../core/hooks/wallets/useActiveWalletChain.js";
@@ -16,6 +18,7 @@ import { MediaRenderer } from "../../MediaRenderer/MediaRenderer.js";
16
18
  import { Skeleton } from "../../components/Skeleton.js";
17
19
  import { Spacer } from "../../components/Spacer.js";
18
20
  import { Container, Line, ModalHeader } from "../../components/basic.js";
21
+ import { Text } from "../../components/text.js";
19
22
  import type { ConnectLocale } from "../locale/types.js";
20
23
 
21
24
  const fetchNFTs = async (
@@ -108,44 +111,90 @@ export function ViewNFTsContent(props: {
108
111
  const activeAccount = useActiveAccount();
109
112
  const activeChain = useActiveWalletChain();
110
113
 
111
- const nftList = useMemo(() => {
112
- const nfts = [];
113
- if (!props.supportedNFTs) return [];
114
- for (const chainId in props.supportedNFTs) {
115
- if (props.supportedNFTs[chainId]) {
116
- nfts.push(
117
- ...props.supportedNFTs[chainId].map((address) => ({
118
- address,
119
- chain: getCachedChain(Number.parseInt(chainId)),
120
- })),
121
- );
114
+ const nftQuery = useQuery({
115
+ queryKey: ["nfts", activeChain?.id, activeAccount?.address],
116
+ queryFn: async (): Promise<
117
+ (NFT & { chain: Chain; address: Address; quantityOwned: bigint })[]
118
+ > => {
119
+ if (!activeAccount) {
120
+ throw new Error("No active account");
122
121
  }
123
- }
124
- return nfts;
125
- }, [props.supportedNFTs]);
122
+ if (!activeChain) {
123
+ throw new Error("No active chain");
124
+ }
125
+
126
+ const result = await getOwnedNFTs({
127
+ client: props.client,
128
+ chains: [activeChain],
129
+ ownerAddress: activeAccount.address,
130
+ });
131
+
132
+ return result
133
+ .filter((nft) => !!nft.name && !!nft.image_url)
134
+ .map((nft) => {
135
+ let parsedNft: NFT;
136
+ const metadata = {
137
+ name: nft.name,
138
+ description: nft.description,
139
+ image: nft.image_url,
140
+ animation_url: nft.video_url,
141
+ external_url: nft.external_url,
142
+ background_color: nft.background_color,
143
+ uri: nft.metadata_url ?? "",
144
+ image_url: nft.image_url,
145
+ attributes: Array.isArray(nft.extra_metadata?.attributes)
146
+ ? nft.extra_metadata?.attributes?.reduce(
147
+ (acc, attr) => {
148
+ acc[attr.trait_type] = attr.value;
149
+ return acc;
150
+ },
151
+ {} as Record<string, unknown>,
152
+ )
153
+ : {},
154
+ };
126
155
 
127
- const results = useQueries({
128
- queries: nftList.map((nft) => ({
129
- queryKey: ["readContract", nft.chain.id, nft.address],
130
- queryFn: () => {
131
- if (!activeAccount) {
132
- throw new Error("No active account");
133
- }
134
- return fetchNFTs(
135
- props.client,
136
- nft.chain,
137
- nft.address,
138
- activeAccount.address,
139
- );
140
- },
141
- enabled: !!activeAccount,
142
- })),
156
+ if (nft.contract?.type === "erc1155") {
157
+ parsedNft = {
158
+ id: BigInt(nft.token_id),
159
+ type: "ERC1155",
160
+ owner: activeAccount.address,
161
+ tokenURI: nft.metadata_url ?? "",
162
+ supply: BigInt(nft.balance), // TODO: this is wrong
163
+ metadata,
164
+ };
165
+ } else {
166
+ parsedNft = {
167
+ id: BigInt(nft.token_id),
168
+ type: "ERC721",
169
+ owner: activeAccount.address,
170
+ tokenURI: nft.metadata_url ?? "",
171
+ metadata,
172
+ };
173
+ }
174
+
175
+ return {
176
+ chain: getCachedChain(nft.chain_id),
177
+ address: nft.token_address as Address,
178
+ quantityOwned: BigInt(nft.balance),
179
+ ...parsedNft,
180
+ };
181
+ });
182
+ },
183
+ enabled: !!activeChain && !!activeAccount,
143
184
  });
144
185
 
145
186
  if (!activeChain?.id || !activeAccount?.address) {
146
187
  return null;
147
188
  }
148
189
 
190
+ const filteredNFTs = props.supportedNFTs?.[activeChain.id]
191
+ ? nftQuery.data?.filter((nft) =>
192
+ props.supportedNFTs?.[activeChain.id]
193
+ ?.map((supportedNFTAddress) => supportedNFTAddress.toLowerCase())
194
+ .includes(nft.address.toLowerCase()),
195
+ )
196
+ : nftQuery.data;
197
+
149
198
  return (
150
199
  <>
151
200
  <Container
@@ -155,29 +204,21 @@ export function ViewNFTsContent(props: {
155
204
  gap: "12px",
156
205
  }}
157
206
  >
158
- {results.map((result, index) => {
159
- if (result.error) {
160
- console.error(result.error);
161
- return null;
162
- }
163
- return result.isLoading || !result.data ? (
164
- <Skeleton
165
- key={`${nftList[index]?.chain?.id}:${nftList[index]?.address}`}
166
- height="150px"
167
- width="150px"
207
+ {nftQuery.error ? (
208
+ <Text>Error loading NFTs</Text>
209
+ ) : nftQuery.isLoading || !filteredNFTs ? (
210
+ <Skeleton height="150px" width="150px" />
211
+ ) : (
212
+ filteredNFTs.map((nft) => (
213
+ <NftCard
214
+ key={`${nft.chain.id}:${nft.address}:${nft.id}`}
215
+ {...nft}
216
+ client={props.client}
217
+ chain={nft.chain}
218
+ theme={props.theme}
168
219
  />
169
- ) : (
170
- result.data.map((nft) => (
171
- <NftCard
172
- key={`${nft.chain.id}:${nft.address}:${nft.id}`}
173
- {...nft}
174
- client={props.client}
175
- chain={nft.chain}
176
- theme={props.theme}
177
- />
178
- ))
179
- );
180
- })}
220
+ ))
221
+ )}
181
222
  </Container>
182
223
  <Spacer y="lg" />
183
224
  </>
@@ -198,6 +239,7 @@ function NftCard(
198
239
  <div
199
240
  style={{
200
241
  display: "flex",
242
+ width: "150px",
201
243
  flexDirection: "column",
202
244
  gap: "4px",
203
245
  alignItems: "center",
@@ -263,7 +305,17 @@ function NftCard(
263
305
  />
264
306
  )}
265
307
  </div>
266
- <span style={{ fontWeight: 600 }}>{props.metadata.name}</span>
308
+ <Text
309
+ size="xs"
310
+ color="primaryText"
311
+ style={{
312
+ fontWeight: 600,
313
+ textAlign: "center",
314
+ maxLines: 2,
315
+ }}
316
+ >
317
+ {props.metadata.name}
318
+ </Text>
267
319
  </div>
268
320
  );
269
321
 
@@ -1,5 +1,8 @@
1
+ import { useQuery } from "@tanstack/react-query";
1
2
  import type { Chain } from "../../../../../chains/types.js";
2
3
  import type { ThirdwebClient } from "../../../../../client/client.js";
4
+ import { getOwnedTokens } from "../../../../../insight/get-tokens.js";
5
+ import { toTokens } from "../../../../../utils/units.js";
3
6
  import { fontSize } from "../../../../core/design-system/index.js";
4
7
  import { useWalletBalance } from "../../../../core/hooks/others/useWalletBalance.js";
5
8
  import { useActiveAccount } from "../../../../core/hooks/wallets/useActiveAccount.js";
@@ -38,7 +41,7 @@ export function ViewTokens(props: {
38
41
  >
39
42
  <Container p="lg">
40
43
  <ModalHeader
41
- title={props.connectLocale.viewFunds.title}
44
+ title={props.connectLocale.viewFunds.viewTokens}
42
45
  onBack={props.onBack}
43
46
  />
44
47
  </Container>
@@ -63,15 +66,49 @@ export function ViewTokensContent(props: {
63
66
  client: ThirdwebClient;
64
67
  connectLocale: ConnectLocale;
65
68
  }) {
69
+ const account = useActiveAccount();
66
70
  const activeChain = useActiveWalletChain();
67
- if (!activeChain) {
68
- return null;
69
- }
71
+
70
72
  const supportedTokens = props.supportedTokens || defaultTokens;
71
73
 
72
74
  const tokenList =
73
75
  (activeChain?.id ? supportedTokens[activeChain.id] : undefined) || [];
74
76
 
77
+ const erc20TokensQuery = useQuery({
78
+ queryKey: ["tokens", activeChain?.id, account?.address],
79
+ queryFn: async () => {
80
+ if (!activeChain) {
81
+ throw new Error("No active chain");
82
+ }
83
+
84
+ if (!account) {
85
+ throw new Error("No account");
86
+ }
87
+
88
+ const result = await getOwnedTokens({
89
+ client: props.client,
90
+ chains: [activeChain],
91
+ ownerAddress: account.address,
92
+ });
93
+
94
+ return result.filter(
95
+ (token) =>
96
+ !defaultTokens[activeChain.id]?.some(
97
+ (t) =>
98
+ t.address.toLowerCase() === token.token_address.toLowerCase(),
99
+ ),
100
+ );
101
+ },
102
+ // only fetch tokens if no explicit supported tokens are provided
103
+ enabled:
104
+ !!activeChain &&
105
+ !!account &&
106
+ (!props.supportedTokens || !props.supportedTokens[activeChain.id]),
107
+ });
108
+
109
+ if (!activeChain || !account) {
110
+ return null;
111
+ }
75
112
  return (
76
113
  <>
77
114
  <TokenInfo
@@ -90,6 +127,37 @@ export function ViewTokensContent(props: {
90
127
  />
91
128
  );
92
129
  })}
130
+
131
+ {erc20TokensQuery.isLoading && (
132
+ <Container flex="column" gap="sm" p="sm">
133
+ <Skeleton height={fontSize.md} width="100%" />
134
+ <Skeleton height={fontSize.md} width="100%" />
135
+ </Container>
136
+ )}
137
+
138
+ {erc20TokensQuery.data?.map((token) => {
139
+ return (
140
+ <TokenInfo
141
+ token={{
142
+ address: token.token_address,
143
+ name: token.name ?? "",
144
+ symbol: token.symbol ?? "",
145
+ }}
146
+ key={token.token_address}
147
+ chain={activeChain}
148
+ client={props.client}
149
+ balanceData={{
150
+ symbol: token.symbol ?? "",
151
+ name: token.name ?? "",
152
+ decimals: token.decimals ?? 18,
153
+ displayValue: toTokens(
154
+ BigInt(token.balance),
155
+ token.decimals ?? 18,
156
+ ),
157
+ }}
158
+ />
159
+ );
160
+ })}
93
161
  </>
94
162
  );
95
163
  }
@@ -98,14 +166,27 @@ function TokenInfo(props: {
98
166
  token: ERC20OrNativeToken;
99
167
  chain: Chain;
100
168
  client: ThirdwebClient;
169
+ balanceData?: {
170
+ symbol: string;
171
+ name: string;
172
+ decimals: number;
173
+ displayValue: string;
174
+ };
101
175
  }) {
102
176
  const account = useActiveAccount();
103
- const tokenBalanceQuery = useWalletBalance({
104
- address: account?.address,
105
- chain: props.chain,
106
- tokenAddress: isNativeToken(props.token) ? undefined : props.token.address,
107
- client: props.client,
108
- });
177
+ const tokenBalanceQuery = useWalletBalance(
178
+ {
179
+ address: account?.address,
180
+ chain: props.chain,
181
+ tokenAddress: isNativeToken(props.token)
182
+ ? undefined
183
+ : props.token.address,
184
+ client: props.client,
185
+ },
186
+ {
187
+ enabled: props.balanceData === undefined,
188
+ },
189
+ );
109
190
 
110
191
  const tokenName = isNativeToken(props.token)
111
192
  ? tokenBalanceQuery.data?.name
@@ -129,7 +210,9 @@ function TokenInfo(props: {
129
210
  <Skeleton height={fontSize.md} width="150px" />
130
211
  )}
131
212
 
132
- {tokenBalanceQuery.data ? (
213
+ {props.balanceData ? (
214
+ <Text size="xs"> {formatTokenBalance(props.balanceData)}</Text>
215
+ ) : tokenBalanceQuery.data ? (
133
216
  <Text size="xs"> {formatTokenBalance(tokenBalanceQuery.data)}</Text>
134
217
  ) : (
135
218
  <Skeleton height={fontSize.xs} width="100px" />
@@ -42,7 +42,10 @@ export function useResolvedMediaType(
42
42
  });
43
43
 
44
44
  return {
45
- mediaInfo: { url: resolvedUrl, mimeType: resolvedMimeType.data },
45
+ mediaInfo: {
46
+ url: resolvedUrl,
47
+ mimeType: resolvedMimeType.data || "image/", // default to image if no mime type is found
48
+ },
46
49
  isFetched: resolvedMimeType.isFetched || !!mimeType,
47
50
  };
48
51
  }
@@ -1,6 +1,7 @@
1
1
  type ApiError = {
2
2
  code: string;
3
- message?: string;
3
+ title: string;
4
+ message: string;
4
5
  data?: {
5
6
  minimumAmountUSDCents?: string;
6
7
  requestedAmountUSDCents?: string;
@@ -9,19 +10,25 @@ type ApiError = {
9
10
  };
10
11
  };
11
12
 
12
- export const defaultMessage = "Unable to get price quote";
13
13
  // biome-ignore lint/suspicious/noExplicitAny: <explanation>
14
14
  export function getErrorMessage(err: any): ApiError {
15
15
  if (typeof err.error === "object" && err.error.code) {
16
16
  if (err.error.code === "MINIMUM_PURCHASE_AMOUNT") {
17
17
  return {
18
18
  code: "MINIMUM_PURCHASE_AMOUNT",
19
- message: "Purchase amount is too low",
19
+ title: "Amount Too Low",
20
+ message:
21
+ "The requested amount is less than the minimum purchase. Try another provider or amount.",
20
22
  };
21
23
  }
22
24
  }
25
+
26
+ console.error(err);
27
+
23
28
  return {
24
29
  code: "UNABLE_TO_GET_PRICE_QUOTE",
25
- message: defaultMessage,
30
+ title: "Failed to Find Quote",
31
+ message:
32
+ "We couldn't get a quote for this token pair. Select another token or pay with a debit card.",
26
33
  };
27
34
  }
@@ -1,9 +1,8 @@
1
1
  import type { Chain } from "../chains/types.js";
2
2
  import type { ThirdwebClient } from "../client/client.js";
3
+ import { getTransactions } from "../insight/get-transactions.js";
3
4
  import { type Store, createStore } from "../reactive/store.js";
4
- import { getThirdwebDomains } from "../utils/domains.js";
5
5
  import type { Hex } from "../utils/encoding/hex.js";
6
- import { getClientFetch } from "../utils/fetch.js";
7
6
 
8
7
  export type StoredTransaction = {
9
8
  transactionHash: Hex;
@@ -76,26 +75,16 @@ export async function getPastTransactions(options: {
76
75
  const oneMonthsAgoInSeconds = Math.floor(
77
76
  (Date.now() - 1 * 30 * 24 * 60 * 60 * 1000) / 1000,
78
77
  );
79
- const url = new URL(
80
- `https://${getThirdwebDomains().insight}/v1/wallets/${walletAddress}/transactions`,
81
- );
82
- url.searchParams.set("limit", "10");
83
- url.searchParams.set("chain", chain.id.toString());
84
- url.searchParams.set(
85
- "filter_block_timestamp_gte",
86
- oneMonthsAgoInSeconds.toString(),
87
- );
88
- const clientFetch = getClientFetch(client);
89
- const result = await clientFetch(url.toString());
90
- const json = (await result.json()) as {
91
- data: {
92
- chain_id: number;
93
- hash: string;
94
- status: number;
95
- to_address: string;
96
- }[];
97
- };
98
- return json.data.map((tx) => ({
78
+ const result = await getTransactions({
79
+ client,
80
+ walletAddress,
81
+ chains: [chain],
82
+ queryOptions: {
83
+ filter_block_timestamp_gte: oneMonthsAgoInSeconds,
84
+ limit: 20,
85
+ },
86
+ });
87
+ return result.map((tx) => ({
99
88
  transactionHash: tx.hash as Hex,
100
89
  chainId: tx.chain_id,
101
90
  receipt: {
@@ -20,16 +20,17 @@ export function getClientFetch(client: ThirdwebClient, ecosystem?: Ecosystem) {
20
20
  * @internal
21
21
  */
22
22
  async function fetchWithHeaders(
23
- url: string,
23
+ url: string | Request,
24
24
  init?: Omit<RequestInit, "signal"> & { requestTimeoutMs?: number },
25
25
  ): Promise<Response> {
26
26
  const { requestTimeoutMs = DEFAULT_REQUEST_TIMEOUT, ...restInit } =
27
27
  init || {};
28
28
 
29
29
  let headers = restInit.headers ? new Headers(restInit.headers) : undefined;
30
+ const urlString = typeof url === "string" ? url : url.url;
30
31
 
31
32
  // check if we are making a request to a thirdweb service (we don't want to send any headers to non-thirdweb services)
32
- if (isThirdwebUrl(url)) {
33
+ if (isThirdwebUrl(urlString)) {
33
34
  if (!headers) {
34
35
  headers = new Headers();
35
36
  }
@@ -49,9 +50,9 @@ export function getClientFetch(client: ThirdwebClient, ecosystem?: Ecosystem) {
49
50
  // pay urls should never send the auth token, because we always want the "developer" to be the one making the request, not the "end user"
50
51
  if (
51
52
  authToken &&
52
- !isPayUrl(url) &&
53
- !isInAppWalletUrl(url) &&
54
- !isBundlerUrl(url)
53
+ !isPayUrl(urlString) &&
54
+ !isInAppWalletUrl(urlString) &&
55
+ !isBundlerUrl(urlString)
55
56
  ) {
56
57
  headers.set("authorization", `Bearer ${authToken}`);
57
58
  } else if (secretKey) {
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "5.94.1";
1
+ export const version = "5.95.0-nightly-4c1f384a635054a8cfaaa487e3ba7ada63b221ec-20250415110008";
@@ -63,6 +63,9 @@ export async function connectEip1193Wallet({
63
63
  });
64
64
  } catch (e) {
65
65
  console.error(e);
66
+ if (extractErrorMessage(e)?.toLowerCase()?.includes("rejected")) {
67
+ throw e;
68
+ }
66
69
  await new Promise((resolve) => setTimeout(resolve, 500));
67
70
  }
68
71
  attempts++;
@@ -375,3 +378,16 @@ async function switchChain(provider: EIP1193Provider, chain: Chain) {
375
378
  });
376
379
  }
377
380
  }
381
+
382
+ function extractErrorMessage(e: unknown) {
383
+ if (e instanceof Error) {
384
+ return e.message;
385
+ }
386
+ if (typeof e === "string") {
387
+ return e;
388
+ }
389
+ if (typeof e === "object" && e !== null) {
390
+ return JSON.stringify(e);
391
+ }
392
+ return String(e);
393
+ }