thirdweb 5.95.0-nightly-64bd603301b3067b6a69a29f66a28dee7ffa38f5-20250416000349 → 5.95.0-nightly-e7b01108037ebef07fba95f888be1905c8fab5df-20250417000348

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 (196) hide show
  1. package/dist/cjs/chains/utils.js +2 -4
  2. package/dist/cjs/chains/utils.js.map +1 -1
  3. package/dist/cjs/event/actions/get-events.js +4 -10
  4. package/dist/cjs/event/actions/get-events.js.map +1 -1
  5. package/dist/cjs/extensions/erc1155/read/getNFT.js +2 -0
  6. package/dist/cjs/extensions/erc1155/read/getNFT.js.map +1 -1
  7. package/dist/cjs/extensions/erc20/read/getBalance.js +2 -0
  8. package/dist/cjs/extensions/erc20/read/getBalance.js.map +1 -1
  9. package/dist/cjs/extensions/erc721/read/getNFT.js +42 -0
  10. package/dist/cjs/extensions/erc721/read/getNFT.js.map +1 -1
  11. package/dist/cjs/extensions/erc721/read/getNFTs.js +44 -17
  12. package/dist/cjs/extensions/erc721/read/getNFTs.js.map +1 -1
  13. package/dist/cjs/extensions/erc721/read/getOwnedNFTs.js +46 -0
  14. package/dist/cjs/extensions/erc721/read/getOwnedNFTs.js.map +1 -1
  15. package/dist/cjs/extensions/marketplace/direct-listings/utils.js +7 -4
  16. package/dist/cjs/extensions/marketplace/direct-listings/utils.js.map +1 -1
  17. package/dist/cjs/extensions/marketplace/english-auctions/utils.js +9 -4
  18. package/dist/cjs/extensions/marketplace/english-auctions/utils.js.map +1 -1
  19. package/dist/cjs/extensions/marketplace/offers/utils.js +7 -4
  20. package/dist/cjs/extensions/marketplace/offers/utils.js.map +1 -1
  21. package/dist/cjs/insight/common.js +18 -0
  22. package/dist/cjs/insight/common.js.map +1 -0
  23. package/dist/cjs/insight/get-events.js +12 -9
  24. package/dist/cjs/insight/get-events.js.map +1 -1
  25. package/dist/cjs/insight/get-nfts.js +158 -16
  26. package/dist/cjs/insight/get-nfts.js.map +1 -1
  27. package/dist/cjs/insight/get-tokens.js +34 -14
  28. package/dist/cjs/insight/get-tokens.js.map +1 -1
  29. package/dist/cjs/insight/get-transactions.js +17 -12
  30. package/dist/cjs/insight/get-transactions.js.map +1 -1
  31. package/dist/cjs/insight/index.js +3 -1
  32. package/dist/cjs/insight/index.js.map +1 -1
  33. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewNFTs.js +6 -43
  34. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewNFTs.js.map +1 -1
  35. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewTokens.js +3 -9
  36. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewTokens.js.map +1 -1
  37. package/dist/cjs/react/web/ui/components/TokenIcon.js +3 -1
  38. package/dist/cjs/react/web/ui/components/TokenIcon.js.map +1 -1
  39. package/dist/cjs/react/web/ui/prebuilt/NFT/utils.js +7 -2
  40. package/dist/cjs/react/web/ui/prebuilt/NFT/utils.js.map +1 -1
  41. package/dist/cjs/social/profiles.js +3 -8
  42. package/dist/cjs/social/profiles.js.map +1 -1
  43. package/dist/cjs/storage/download.js +2 -2
  44. package/dist/cjs/storage/download.js.map +1 -1
  45. package/dist/cjs/storage/unpin.js +2 -2
  46. package/dist/cjs/storage/unpin.js.map +1 -1
  47. package/dist/cjs/storage/upload/web-node.js +0 -1
  48. package/dist/cjs/storage/upload/web-node.js.map +1 -1
  49. package/dist/cjs/utils/nft/parseNft.js +4 -0
  50. package/dist/cjs/utils/nft/parseNft.js.map +1 -1
  51. package/dist/cjs/utils/signatures/resolve-signature.js +0 -2
  52. package/dist/cjs/utils/signatures/resolve-signature.js.map +1 -1
  53. package/dist/cjs/version.js +1 -1
  54. package/dist/cjs/wallets/smart/lib/calls.js +2 -2
  55. package/dist/cjs/wallets/smart/lib/calls.js.map +1 -1
  56. package/dist/cjs/wallets/utils/getWalletBalance.js +3 -0
  57. package/dist/cjs/wallets/utils/getWalletBalance.js.map +1 -1
  58. package/dist/esm/chains/utils.js +2 -4
  59. package/dist/esm/chains/utils.js.map +1 -1
  60. package/dist/esm/event/actions/get-events.js +1 -7
  61. package/dist/esm/event/actions/get-events.js.map +1 -1
  62. package/dist/esm/extensions/erc1155/read/getNFT.js +2 -0
  63. package/dist/esm/extensions/erc1155/read/getNFT.js.map +1 -1
  64. package/dist/esm/extensions/erc20/read/getBalance.js +2 -0
  65. package/dist/esm/extensions/erc20/read/getBalance.js.map +1 -1
  66. package/dist/esm/extensions/erc721/read/getNFT.js +42 -0
  67. package/dist/esm/extensions/erc721/read/getNFT.js.map +1 -1
  68. package/dist/esm/extensions/erc721/read/getNFTs.js +44 -17
  69. package/dist/esm/extensions/erc721/read/getNFTs.js.map +1 -1
  70. package/dist/esm/extensions/erc721/read/getOwnedNFTs.js +46 -0
  71. package/dist/esm/extensions/erc721/read/getOwnedNFTs.js.map +1 -1
  72. package/dist/esm/extensions/marketplace/direct-listings/utils.js +7 -4
  73. package/dist/esm/extensions/marketplace/direct-listings/utils.js.map +1 -1
  74. package/dist/esm/extensions/marketplace/english-auctions/utils.js +9 -4
  75. package/dist/esm/extensions/marketplace/english-auctions/utils.js.map +1 -1
  76. package/dist/esm/extensions/marketplace/offers/utils.js +7 -4
  77. package/dist/esm/extensions/marketplace/offers/utils.js.map +1 -1
  78. package/dist/esm/insight/common.js +15 -0
  79. package/dist/esm/insight/common.js.map +1 -0
  80. package/dist/esm/insight/get-events.js +8 -5
  81. package/dist/esm/insight/get-events.js.map +1 -1
  82. package/dist/esm/insight/get-nfts.js +153 -13
  83. package/dist/esm/insight/get-nfts.js.map +1 -1
  84. package/dist/esm/insight/get-tokens.js +30 -10
  85. package/dist/esm/insight/get-tokens.js.map +1 -1
  86. package/dist/esm/insight/get-transactions.js +13 -8
  87. package/dist/esm/insight/get-transactions.js.map +1 -1
  88. package/dist/esm/insight/index.js +1 -1
  89. package/dist/esm/insight/index.js.map +1 -1
  90. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewNFTs.js +6 -43
  91. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewNFTs.js.map +1 -1
  92. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewTokens.js +3 -9
  93. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewTokens.js.map +1 -1
  94. package/dist/esm/react/web/ui/components/TokenIcon.js +3 -1
  95. package/dist/esm/react/web/ui/components/TokenIcon.js.map +1 -1
  96. package/dist/esm/react/web/ui/prebuilt/NFT/utils.js +7 -2
  97. package/dist/esm/react/web/ui/prebuilt/NFT/utils.js.map +1 -1
  98. package/dist/esm/social/profiles.js +3 -8
  99. package/dist/esm/social/profiles.js.map +1 -1
  100. package/dist/esm/storage/download.js +2 -2
  101. package/dist/esm/storage/download.js.map +1 -1
  102. package/dist/esm/storage/unpin.js +2 -2
  103. package/dist/esm/storage/unpin.js.map +1 -1
  104. package/dist/esm/storage/upload/web-node.js +0 -1
  105. package/dist/esm/storage/upload/web-node.js.map +1 -1
  106. package/dist/esm/utils/nft/parseNft.js +4 -0
  107. package/dist/esm/utils/nft/parseNft.js.map +1 -1
  108. package/dist/esm/utils/signatures/resolve-signature.js +0 -2
  109. package/dist/esm/utils/signatures/resolve-signature.js.map +1 -1
  110. package/dist/esm/version.js +1 -1
  111. package/dist/esm/wallets/smart/lib/calls.js +2 -2
  112. package/dist/esm/wallets/smart/lib/calls.js.map +1 -1
  113. package/dist/esm/wallets/utils/getWalletBalance.js +3 -0
  114. package/dist/esm/wallets/utils/getWalletBalance.js.map +1 -1
  115. package/dist/types/chains/utils.d.ts.map +1 -1
  116. package/dist/types/event/actions/get-events.d.ts.map +1 -1
  117. package/dist/types/extensions/erc1155/read/getNFT.d.ts.map +1 -1
  118. package/dist/types/extensions/erc20/read/getBalance.d.ts +2 -0
  119. package/dist/types/extensions/erc20/read/getBalance.d.ts.map +1 -1
  120. package/dist/types/extensions/erc721/read/getNFT.d.ts +5 -0
  121. package/dist/types/extensions/erc721/read/getNFT.d.ts.map +1 -1
  122. package/dist/types/extensions/erc721/read/getNFTs.d.ts +5 -0
  123. package/dist/types/extensions/erc721/read/getNFTs.d.ts.map +1 -1
  124. package/dist/types/extensions/erc721/read/getOwnedNFTs.d.ts +3 -1
  125. package/dist/types/extensions/erc721/read/getOwnedNFTs.d.ts.map +1 -1
  126. package/dist/types/extensions/marketplace/direct-listings/utils.d.ts.map +1 -1
  127. package/dist/types/extensions/marketplace/english-auctions/utils.d.ts.map +1 -1
  128. package/dist/types/extensions/marketplace/offers/utils.d.ts.map +1 -1
  129. package/dist/types/insight/common.d.ts +3 -0
  130. package/dist/types/insight/common.d.ts.map +1 -0
  131. package/dist/types/insight/get-events.d.ts +2 -2
  132. package/dist/types/insight/get-events.d.ts.map +1 -1
  133. package/dist/types/insight/get-nfts.d.ts +52 -4
  134. package/dist/types/insight/get-nfts.d.ts.map +1 -1
  135. package/dist/types/insight/get-tokens.d.ts +3 -3
  136. package/dist/types/insight/get-tokens.d.ts.map +1 -1
  137. package/dist/types/insight/get-transactions.d.ts +1 -1
  138. package/dist/types/insight/get-transactions.d.ts.map +1 -1
  139. package/dist/types/insight/index.d.ts +2 -2
  140. package/dist/types/insight/index.d.ts.map +1 -1
  141. package/dist/types/react/core/utils/wallet.d.ts +1 -1
  142. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/main/useBuyTxStates.d.ts +1 -1
  143. package/dist/types/react/web/ui/ConnectWallet/screens/ViewNFTs.d.ts.map +1 -1
  144. package/dist/types/react/web/ui/ConnectWallet/screens/ViewTokens.d.ts.map +1 -1
  145. package/dist/types/react/web/ui/components/TokenIcon.d.ts.map +1 -1
  146. package/dist/types/react/web/ui/prebuilt/NFT/utils.d.ts.map +1 -1
  147. package/dist/types/social/profiles.d.ts.map +1 -1
  148. package/dist/types/storage/download.d.ts.map +1 -1
  149. package/dist/types/storage/unpin.d.ts.map +1 -1
  150. package/dist/types/storage/upload/web-node.d.ts.map +1 -1
  151. package/dist/types/utils/nft/parseNft.d.ts +8 -0
  152. package/dist/types/utils/nft/parseNft.d.ts.map +1 -1
  153. package/dist/types/utils/signatures/resolve-signature.d.ts.map +1 -1
  154. package/dist/types/version.d.ts +1 -1
  155. package/dist/types/wallets/utils/getWalletBalance.d.ts +2 -7
  156. package/dist/types/wallets/utils/getWalletBalance.d.ts.map +1 -1
  157. package/package.json +4 -4
  158. package/src/chains/utils.ts +6 -4
  159. package/src/event/actions/get-events.ts +1 -13
  160. package/src/extensions/erc1155/read/getNFT.test.ts +2 -0
  161. package/src/extensions/erc1155/read/getNFT.ts +2 -0
  162. package/src/extensions/erc20/drop20.test.ts +48 -132
  163. package/src/extensions/erc20/read/getBalance.test.ts +5 -9
  164. package/src/extensions/erc20/read/getBalance.ts +4 -0
  165. package/src/extensions/erc721/read/getNFT.test.ts +108 -0
  166. package/src/extensions/erc721/read/getNFT.ts +55 -1
  167. package/src/extensions/erc721/read/getNFTs.test.ts +219 -13
  168. package/src/extensions/erc721/read/getNFTs.ts +59 -20
  169. package/src/extensions/erc721/read/getOwnedNFTs.test.ts +27 -2
  170. package/src/extensions/erc721/read/getOwnedNFTs.ts +61 -1
  171. package/src/extensions/erc721/token721.test.ts +2 -0
  172. package/src/extensions/marketplace/direct-listings/direct-listings.test.ts +2 -18
  173. package/src/extensions/marketplace/direct-listings/utils.ts +7 -4
  174. package/src/extensions/marketplace/english-auctions/utils.ts +9 -4
  175. package/src/extensions/marketplace/offers/utils.ts +7 -4
  176. package/src/insight/common.ts +24 -0
  177. package/src/insight/get-events.ts +23 -9
  178. package/src/insight/get-nfts.ts +251 -20
  179. package/src/insight/get-tokens.ts +51 -23
  180. package/src/insight/get-transactions.ts +26 -16
  181. package/src/insight/index.ts +6 -2
  182. package/src/react/web/ui/ConnectWallet/screens/ViewNFTs.tsx +43 -68
  183. package/src/react/web/ui/ConnectWallet/screens/ViewTokens.tsx +4 -14
  184. package/src/react/web/ui/components/TokenIcon.tsx +12 -3
  185. package/src/react/web/ui/prebuilt/NFT/utils.test.ts +2 -64
  186. package/src/react/web/ui/prebuilt/NFT/utils.ts +7 -2
  187. package/src/social/profiles.ts +5 -9
  188. package/src/storage/download.ts +4 -2
  189. package/src/storage/unpin.ts +4 -2
  190. package/src/storage/upload/web-node.ts +0 -1
  191. package/src/utils/nft/parseNft.test.ts +8 -0
  192. package/src/utils/nft/parseNft.ts +12 -0
  193. package/src/utils/signatures/resolve-signature.ts +0 -2
  194. package/src/version.ts +1 -1
  195. package/src/wallets/smart/lib/calls.ts +2 -2
  196. package/src/wallets/utils/getWalletBalance.ts +5 -7
@@ -0,0 +1,24 @@
1
+ import type { Chain } from "../chains/types.js";
2
+ import { getChainServices } from "../chains/utils.js";
3
+
4
+ export async function assertInsightEnabled(chains: Chain[]) {
5
+ const chainData = await Promise.all(
6
+ chains.map((chain) =>
7
+ getChainServices(chain).then((services) => ({
8
+ chain,
9
+ enabled: services.some((c) => c.service === "insight" && c.enabled),
10
+ })),
11
+ ),
12
+ );
13
+
14
+ const insightEnabled = chainData.every((c) => c.enabled);
15
+
16
+ if (!insightEnabled) {
17
+ throw new Error(
18
+ `Insight is not available for chains ${chainData
19
+ .filter((c) => !c.enabled)
20
+ .map((c) => c.chain.id)
21
+ .join(", ")}`,
22
+ );
23
+ }
24
+ }
@@ -1,15 +1,11 @@
1
- import {
2
- type GetV1EventsByContractAddressData,
3
- type GetV1EventsByContractAddressResponse,
4
- getV1EventsByContractAddress,
1
+ import type {
2
+ GetV1EventsByContractAddressData,
3
+ GetV1EventsByContractAddressResponse,
5
4
  } from "@thirdweb-dev/insight";
6
5
  import type { AbiEvent } from "ox/AbiEvent";
7
- import { stringify } from "viem";
8
6
  import type { Chain } from "../chains/types.js";
9
7
  import type { ThirdwebClient } from "../client/client.js";
10
8
  import type { PreparedEvent } from "../event/prepare-event.js";
11
- import { getThirdwebDomains } from "../utils/domains.js";
12
- import { getClientFetch } from "../utils/fetch.js";
13
9
 
14
10
  export type ContractEvent = NonNullable<
15
11
  GetV1EventsByContractAddressResponse["data"]
@@ -37,11 +33,30 @@ export async function getContractEvents(options: {
37
33
  contractAddress: string;
38
34
  event?: PreparedEvent<AbiEvent>;
39
35
  decodeLogs?: boolean;
40
- queryOptions?: GetV1EventsByContractAddressData["query"];
36
+ queryOptions?: Omit<
37
+ GetV1EventsByContractAddressData["query"],
38
+ "chain" | "decode"
39
+ >;
41
40
  }): Promise<ContractEvent[]> {
41
+ const [
42
+ { getV1EventsByContractAddress },
43
+ { getThirdwebDomains },
44
+ { getClientFetch },
45
+ { assertInsightEnabled },
46
+ { stringify },
47
+ ] = await Promise.all([
48
+ import("@thirdweb-dev/insight"),
49
+ import("../utils/domains.js"),
50
+ import("../utils/fetch.js"),
51
+ import("./common.js"),
52
+ import("../utils/json.js"),
53
+ ]);
54
+
42
55
  const { client, chains, contractAddress, event, queryOptions, decodeLogs } =
43
56
  options;
44
57
 
58
+ await assertInsightEnabled(chains);
59
+
45
60
  const defaultQueryOptions: GetV1EventsByContractAddressData["query"] = {
46
61
  chain: chains.map((chain) => chain.id),
47
62
  limit: 100,
@@ -62,7 +77,6 @@ export async function getContractEvents(options: {
62
77
  contractAddress,
63
78
  },
64
79
  query: {
65
- chain: chains.map((chain) => chain.id),
66
80
  ...defaultQueryOptions,
67
81
  ...queryOptions,
68
82
  },
@@ -1,15 +1,16 @@
1
- import {
2
- type GetV1NftsBalanceByOwnerAddressData,
3
- type GetV1NftsBalanceByOwnerAddressResponse,
4
- getV1NftsBalanceByOwnerAddress,
1
+ import type {
2
+ GetV1NftsByContractAddressByTokenIdData,
3
+ GetV1NftsByContractAddressData,
4
+ GetV1NftsByContractAddressResponse,
5
+ GetV1NftsData,
6
+ GetV1NftsResponse,
5
7
  } from "@thirdweb-dev/insight";
6
- import { stringify } from "viem";
7
8
  import type { Chain } from "../chains/types.js";
8
9
  import type { ThirdwebClient } from "../client/client.js";
9
- import { getThirdwebDomains } from "../utils/domains.js";
10
- import { getClientFetch } from "../utils/fetch.js";
10
+ import type { NFT } from "../utils/nft/parseNft.js";
11
11
 
12
- export type OwnedNFT = GetV1NftsBalanceByOwnerAddressResponse["data"][number];
12
+ type OwnedNFT = GetV1NftsResponse["data"][number];
13
+ type ContractNFT = GetV1NftsByContractAddressResponse["data"][number];
13
14
 
14
15
  /**
15
16
  * Get NFTs owned by an address
@@ -29,28 +30,199 @@ export async function getOwnedNFTs(args: {
29
30
  client: ThirdwebClient;
30
31
  chains: Chain[];
31
32
  ownerAddress: string;
32
- queryOptions?: GetV1NftsBalanceByOwnerAddressData["query"];
33
- }): Promise<OwnedNFT[]> {
33
+ includeMetadata?: boolean;
34
+ queryOptions?: Omit<GetV1NftsData["query"], "owner_address" | "chain">;
35
+ }): Promise<(NFT & { quantityOwned: bigint })[]> {
36
+ const [
37
+ { getV1Nfts },
38
+ { getThirdwebDomains },
39
+ { getClientFetch },
40
+ { assertInsightEnabled },
41
+ { stringify },
42
+ ] = await Promise.all([
43
+ import("@thirdweb-dev/insight"),
44
+ import("../utils/domains.js"),
45
+ import("../utils/fetch.js"),
46
+ import("./common.js"),
47
+ import("viem"),
48
+ ]);
49
+
50
+ // TODO (insight): add support for contract address filters
51
+ const { client, chains, ownerAddress, queryOptions } = args;
52
+
53
+ await assertInsightEnabled(chains);
54
+
55
+ const defaultQueryOptions: GetV1NftsData["query"] = {
56
+ chain: chains.map((chain) => chain.id),
57
+ // metadata: includeMetadata ? "true" : "false", TODO (insight): add support for this
58
+ limit: 50,
59
+ owner_address: ownerAddress,
60
+ };
61
+
62
+ const result = await getV1Nfts({
63
+ baseUrl: `https://${getThirdwebDomains().insight}`,
64
+ fetch: getClientFetch(client),
65
+ query: {
66
+ ...defaultQueryOptions,
67
+ ...queryOptions,
68
+ },
69
+ });
70
+
71
+ if (result.error) {
72
+ throw new Error(
73
+ `${result.response.status} ${result.response.statusText} - ${result.error ? stringify(result.error) : "Unknown error"}`,
74
+ );
75
+ }
76
+
77
+ const transformedNfts = await transformNFTModel(
78
+ result.data?.data ?? [],
79
+ ownerAddress,
80
+ );
81
+ return transformedNfts.map((nft) => ({
82
+ ...nft,
83
+ quantityOwned: nft.quantityOwned ?? 1n,
84
+ }));
85
+ }
86
+
87
+ /**
88
+ * Get all NFTs from a contract
89
+ * @example
90
+ * ```ts
91
+ * import { Insight } from "thirdweb";
92
+ *
93
+ * const nfts = await Insight.getContractNFTs({
94
+ * client,
95
+ * chains: [sepolia],
96
+ * contractAddress: "0x1234567890123456789012345678901234567890",
97
+ * });
98
+ * ```
99
+ * @insight
100
+ */
101
+ export async function getContractNFTs(args: {
102
+ client: ThirdwebClient;
103
+ chains: Chain[];
104
+ contractAddress: string;
105
+ includeMetadata?: boolean;
106
+ includeOwners?: boolean;
107
+ queryOptions?: Omit<GetV1NftsByContractAddressData["query"], "chain">;
108
+ }): Promise<NFT[]> {
109
+ const [
110
+ { getV1NftsByContractAddress },
111
+ { getThirdwebDomains },
112
+ { getClientFetch },
113
+ { assertInsightEnabled },
114
+ { stringify },
115
+ ] = await Promise.all([
116
+ import("@thirdweb-dev/insight"),
117
+ import("../utils/domains.js"),
118
+ import("../utils/fetch.js"),
119
+ import("./common.js"),
120
+ import("../utils/json.js"),
121
+ ]);
122
+
34
123
  const {
35
124
  client,
36
125
  chains,
37
- ownerAddress,
38
- queryOptions = {
39
- chain: chains.map((chain) => chain.id),
40
- metadata: "true",
41
- limit: 100,
42
- page: 1,
126
+ contractAddress,
127
+ includeOwners = true,
128
+ queryOptions,
129
+ } = args;
130
+
131
+ const defaultQueryOptions: GetV1NftsByContractAddressData["query"] = {
132
+ chain: chains.map((chain) => chain.id),
133
+ // metadata: includeMetadata ? "true" : "false", TODO (insight): add support for this
134
+ limit: 50,
135
+ include_owners:
136
+ includeOwners === true ? ("true" as const) : ("false" as const),
137
+ };
138
+
139
+ await assertInsightEnabled(chains);
140
+
141
+ const result = await getV1NftsByContractAddress({
142
+ baseUrl: `https://${getThirdwebDomains().insight}`,
143
+ fetch: getClientFetch(client),
144
+ path: {
145
+ contract_address: contractAddress,
146
+ },
147
+ query: {
148
+ ...defaultQueryOptions,
149
+ ...queryOptions,
43
150
  },
151
+ });
152
+
153
+ if (result.error) {
154
+ throw new Error(
155
+ `${result.response.status} ${result.response.statusText} - ${result.error ? stringify(result.error) : "Unknown error"}`,
156
+ );
157
+ }
158
+
159
+ return transformNFTModel(result.data?.data ?? []);
160
+ }
161
+
162
+ /**
163
+ * Get NFT metadata by contract address and token id
164
+ * @example
165
+ * ```ts
166
+ * import { Insight } from "thirdweb";
167
+ *
168
+ * const nft = await Insight.getNFT({
169
+ * client,
170
+ * chain: sepolia,
171
+ * contractAddress: "0x1234567890123456789012345678901234567890",
172
+ * tokenId: 1n,
173
+ * });
174
+ * ```
175
+ * @insight
176
+ */
177
+ export async function getNFT(args: {
178
+ client: ThirdwebClient;
179
+ chain: Chain;
180
+ contractAddress: string;
181
+ tokenId: bigint | number | string;
182
+ includeOwners?: boolean;
183
+ queryOptions?: GetV1NftsByContractAddressByTokenIdData["query"];
184
+ }): Promise<NFT | undefined> {
185
+ const [
186
+ { getV1NftsByContractAddressByTokenId },
187
+ { getThirdwebDomains },
188
+ { getClientFetch },
189
+ { assertInsightEnabled },
190
+ { stringify },
191
+ ] = await Promise.all([
192
+ import("@thirdweb-dev/insight"),
193
+ import("../utils/domains.js"),
194
+ import("../utils/fetch.js"),
195
+ import("./common.js"),
196
+ import("../utils/json.js"),
197
+ ]);
198
+
199
+ const {
200
+ client,
201
+ chain,
202
+ contractAddress,
203
+ tokenId,
204
+ includeOwners = true,
205
+ queryOptions,
44
206
  } = args;
45
207
 
46
- const result = await getV1NftsBalanceByOwnerAddress({
208
+ await assertInsightEnabled([chain]);
209
+
210
+ const defaultQueryOptions: GetV1NftsByContractAddressByTokenIdData["query"] =
211
+ {
212
+ chain: chain.id,
213
+ include_owners:
214
+ includeOwners === true ? ("true" as const) : ("false" as const),
215
+ };
216
+
217
+ const result = await getV1NftsByContractAddressByTokenId({
47
218
  baseUrl: `https://${getThirdwebDomains().insight}`,
48
219
  fetch: getClientFetch(client),
49
220
  path: {
50
- ownerAddress: ownerAddress,
221
+ contract_address: contractAddress,
222
+ token_id: tokenId.toString(),
51
223
  },
52
224
  query: {
53
- chain: chains.map((chain) => chain.id),
225
+ ...defaultQueryOptions,
54
226
  ...queryOptions,
55
227
  },
56
228
  });
@@ -61,5 +233,64 @@ export async function getOwnedNFTs(args: {
61
233
  );
62
234
  }
63
235
 
64
- return result.data?.data ?? [];
236
+ const transformedNfts = await transformNFTModel(result.data?.data ?? []);
237
+ return transformedNfts?.[0];
238
+ }
239
+
240
+ async function transformNFTModel(
241
+ nfts: (ContractNFT | OwnedNFT)[],
242
+ ownerAddress?: string,
243
+ ): Promise<(NFT & { quantityOwned?: bigint })[]> {
244
+ const { parseNFT } = await import("../utils/nft/parseNft.js");
245
+
246
+ return nfts.map((nft) => {
247
+ let parsedNft: NFT;
248
+ const {
249
+ contract,
250
+ extra_metadata,
251
+ collection,
252
+ metadata_url,
253
+ chain_id,
254
+ token_id,
255
+ status,
256
+ balance,
257
+ token_type,
258
+ ...rest
259
+ } = nft;
260
+ const metadata = {
261
+ uri: nft.metadata_url ?? "",
262
+ image: nft.image_url,
263
+ attributes: nft.extra_metadata?.attributes ?? undefined,
264
+ ...rest,
265
+ };
266
+
267
+ const owner_addresses = ownerAddress
268
+ ? [ownerAddress]
269
+ : "owner_addresses" in nft
270
+ ? nft.owner_addresses
271
+ : undefined;
272
+
273
+ if (contract?.type === "erc1155") {
274
+ parsedNft = parseNFT(metadata, {
275
+ tokenId: BigInt(token_id),
276
+ tokenUri: metadata_url ?? "",
277
+ type: "ERC1155",
278
+ owner: owner_addresses?.[0],
279
+ tokenAddress: contract?.address ?? "",
280
+ chainId: contract?.chain_id ?? 0,
281
+ supply: balance ? BigInt(balance) : 0n, // TODO (insight): this is wrong, needs to be added in the API
282
+ });
283
+ } else {
284
+ parsedNft = parseNFT(metadata, {
285
+ tokenId: BigInt(token_id),
286
+ type: "ERC721",
287
+ owner: owner_addresses?.[0],
288
+ tokenUri: metadata_url ?? "",
289
+ tokenAddress: contract?.address ?? "",
290
+ chainId: contract?.chain_id ?? 0,
291
+ });
292
+ }
293
+
294
+ return parsedNft;
295
+ });
65
296
  }
@@ -1,15 +1,12 @@
1
- import {
2
- type GetV1TokensErc20ByOwnerAddressData,
3
- type GetV1TokensErc20ByOwnerAddressResponse,
4
- getV1TokensErc20ByOwnerAddress,
1
+ import type {
2
+ GetV1TokensErc20ByOwnerAddressData,
3
+ GetV1TokensErc20ByOwnerAddressResponse,
5
4
  } from "@thirdweb-dev/insight";
6
- import { stringify } from "viem";
7
5
  import type { Chain } from "../chains/types.js";
8
6
  import type { ThirdwebClient } from "../client/client.js";
9
- import { getThirdwebDomains } from "../utils/domains.js";
10
- import { getClientFetch } from "../utils/fetch.js";
7
+ import type { GetWalletBalanceResult } from "../wallets/utils/getWalletBalance.js";
11
8
 
12
- export type OwnedToken = GetV1TokensErc20ByOwnerAddressResponse["data"][number];
9
+ type OwnedToken = GetV1TokensErc20ByOwnerAddressResponse["data"][number];
13
10
 
14
11
  /**
15
12
  * Get ERC20 tokens owned by an address
@@ -30,19 +27,31 @@ export async function getOwnedTokens(args: {
30
27
  chains: Chain[];
31
28
  ownerAddress: string;
32
29
  queryOptions?: GetV1TokensErc20ByOwnerAddressData["query"];
33
- }): Promise<OwnedToken[]> {
34
- const {
35
- client,
36
- chains,
37
- ownerAddress,
38
- queryOptions = {
39
- chain: chains.map((chain) => chain.id),
40
- include_spam: "false",
41
- metadata: "true",
42
- limit: 100,
43
- page: 1,
44
- },
45
- } = args;
30
+ }): Promise<GetWalletBalanceResult[]> {
31
+ const [
32
+ { getV1TokensErc20ByOwnerAddress },
33
+ { getThirdwebDomains },
34
+ { getClientFetch },
35
+ { assertInsightEnabled },
36
+ { stringify },
37
+ ] = await Promise.all([
38
+ import("@thirdweb-dev/insight"),
39
+ import("../utils/domains.js"),
40
+ import("../utils/fetch.js"),
41
+ import("./common.js"),
42
+ import("../utils/json.js"),
43
+ ]);
44
+
45
+ const { client, chains, ownerAddress, queryOptions } = args;
46
+
47
+ await assertInsightEnabled(chains);
48
+
49
+ const defaultQueryOptions: GetV1TokensErc20ByOwnerAddressData["query"] = {
50
+ chain: chains.map((chain) => chain.id),
51
+ include_spam: "false",
52
+ metadata: "true",
53
+ limit: 50,
54
+ };
46
55
 
47
56
  const result = await getV1TokensErc20ByOwnerAddress({
48
57
  baseUrl: `https://${getThirdwebDomains().insight}`,
@@ -51,7 +60,7 @@ export async function getOwnedTokens(args: {
51
60
  ownerAddress: ownerAddress,
52
61
  },
53
62
  query: {
54
- chain: chains.map((chain) => chain.id),
63
+ ...defaultQueryOptions,
55
64
  ...queryOptions,
56
65
  },
57
66
  });
@@ -62,5 +71,24 @@ export async function getOwnedTokens(args: {
62
71
  );
63
72
  }
64
73
 
65
- return result.data?.data ?? [];
74
+ return transformOwnedToken(result.data?.data ?? []);
75
+ }
76
+
77
+ async function transformOwnedToken(
78
+ token: OwnedToken[],
79
+ ): Promise<GetWalletBalanceResult[]> {
80
+ const { toTokens } = await import("../utils/units.js");
81
+ return token.map((t) => {
82
+ const decimals = t.decimals ?? 18;
83
+ const value = BigInt(t.balance);
84
+ return {
85
+ value,
86
+ displayValue: toTokens(value, decimals),
87
+ tokenAddress: t.token_address,
88
+ chainId: t.chain_id,
89
+ decimals,
90
+ symbol: t.symbol ?? "",
91
+ name: t.name ?? "",
92
+ };
93
+ });
66
94
  }
@@ -1,13 +1,9 @@
1
- import {
2
- type GetV1WalletsByWalletAddressTransactionsData,
3
- type GetV1WalletsByWalletAddressTransactionsResponse,
4
- getV1WalletsByWalletAddressTransactions,
1
+ import type {
2
+ GetV1WalletsByWalletAddressTransactionsData,
3
+ GetV1WalletsByWalletAddressTransactionsResponse,
5
4
  } from "@thirdweb-dev/insight";
6
- import { stringify } from "viem";
7
5
  import type { Chain } from "../chains/types.js";
8
6
  import type { ThirdwebClient } from "../client/client.js";
9
- import { getThirdwebDomains } from "../utils/domains.js";
10
- import { getClientFetch } from "../utils/fetch.js";
11
7
 
12
8
  export type Transaction = NonNullable<
13
9
  GetV1WalletsByWalletAddressTransactionsResponse["data"]
@@ -33,24 +29,38 @@ export async function getTransactions(args: {
33
29
  chains: Chain[];
34
30
  queryOptions?: GetV1WalletsByWalletAddressTransactionsData["query"];
35
31
  }): Promise<Transaction[]> {
32
+ const [
33
+ { getV1WalletsByWalletAddressTransactions },
34
+ { getThirdwebDomains },
35
+ { getClientFetch },
36
+ { assertInsightEnabled },
37
+ { stringify },
38
+ ] = await Promise.all([
39
+ import("@thirdweb-dev/insight"),
40
+ import("../utils/domains.js"),
41
+ import("../utils/fetch.js"),
42
+ import("./common.js"),
43
+ import("../utils/json.js"),
44
+ ]);
45
+
46
+ await assertInsightEnabled(args.chains);
36
47
  const threeMonthsAgoInSeconds = Math.floor(
37
48
  (Date.now() - 3 * 30 * 24 * 60 * 60 * 1000) / 1000,
38
49
  );
39
- const {
40
- client,
41
- walletAddress,
42
- chains,
43
- queryOptions = {
50
+ const { client, walletAddress, chains, queryOptions } = args;
51
+
52
+ const defaultQueryOptions: GetV1WalletsByWalletAddressTransactionsData["query"] =
53
+ {
54
+ chain: chains.map((chain) => chain.id),
44
55
  filter_block_timestamp_gte: threeMonthsAgoInSeconds,
45
56
  limit: 100,
46
- page: 1,
47
- },
48
- } = args;
57
+ };
58
+
49
59
  const result = await getV1WalletsByWalletAddressTransactions({
50
60
  baseUrl: `https://${getThirdwebDomains().insight}`,
51
61
  fetch: getClientFetch(client),
52
62
  query: {
53
- chain: chains.map((chain) => chain.id),
63
+ ...defaultQueryOptions,
54
64
  ...queryOptions,
55
65
  },
56
66
  path: {
@@ -1,4 +1,8 @@
1
- export { getOwnedNFTs, type OwnedNFT } from "./get-nfts.js";
2
- export { getOwnedTokens, type OwnedToken } from "./get-tokens.js";
1
+ export {
2
+ getContractNFTs,
3
+ getOwnedNFTs,
4
+ getNFT,
5
+ } from "./get-nfts.js";
6
+ export { getOwnedTokens } from "./get-tokens.js";
3
7
  export { getTransactions, type Transaction } from "./get-transactions.js";
4
8
  export { getContractEvents, type ContractEvent } from "./get-events.js";
@@ -130,53 +130,12 @@ export function ViewNFTsContent(props: {
130
130
  });
131
131
 
132
132
  return result
133
- .filter((nft) => !!nft.name && !!nft.image_url)
133
+ .filter((nft) => !!nft.metadata.name && !!nft.metadata.image)
134
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
- };
155
-
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
135
  return {
176
- chain: getCachedChain(nft.chain_id),
177
- address: nft.token_address as Address,
178
- quantityOwned: BigInt(nft.balance),
179
- ...parsedNft,
136
+ chain: getCachedChain(nft.chainId),
137
+ address: nft.tokenAddress as Address,
138
+ ...nft,
180
139
  };
181
140
  });
182
141
  },
@@ -197,29 +156,45 @@ export function ViewNFTsContent(props: {
197
156
 
198
157
  return (
199
158
  <>
200
- <Container
201
- style={{
202
- display: "grid",
203
- gridTemplateColumns: "1fr 1fr",
204
- gap: "12px",
205
- }}
206
- >
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}
219
- />
220
- ))
221
- )}
222
- </Container>
159
+ {nftQuery.error ? (
160
+ <Container center="both" py="lg">
161
+ <Text size="sm" color="secondaryText" center>
162
+ Error loading NFTs
163
+ </Text>
164
+ </Container>
165
+ ) : nftQuery.data?.length === 0 && !nftQuery.isLoading ? (
166
+ <Container center="both" py="lg">
167
+ <Text size="sm" color="secondaryText" center>
168
+ No NFTs found on this chain
169
+ </Text>
170
+ </Container>
171
+ ) : (
172
+ <Container
173
+ style={{
174
+ display: "grid",
175
+ gridTemplateColumns: "1fr 1fr",
176
+ gap: "12px",
177
+ }}
178
+ >
179
+ {nftQuery.isLoading || !filteredNFTs ? (
180
+ <>
181
+ <Skeleton height="150px" width="150px" />
182
+ <Skeleton height="150px" width="150px" />
183
+ <Skeleton height="150px" width="150px" />
184
+ </>
185
+ ) : (
186
+ filteredNFTs.map((nft) => (
187
+ <NftCard
188
+ key={`${nft.chain.id}:${nft.address}:${nft.id}`}
189
+ {...nft}
190
+ client={props.client}
191
+ chain={nft.chain}
192
+ theme={props.theme}
193
+ />
194
+ ))
195
+ )}
196
+ </Container>
197
+ )}
223
198
  <Spacer y="lg" />
224
199
  </>
225
200
  );