thirdweb 5.94.2 → 5.95.0-nightly-64bd603301b3067b6a69a29f66a28dee7ffa38f5-20250416000349

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 (202) hide show
  1. package/dist/cjs/chains/utils.js +41 -0
  2. package/dist/cjs/chains/utils.js.map +1 -1
  3. package/dist/cjs/event/actions/get-events.js +65 -11
  4. package/dist/cjs/event/actions/get-events.js.map +1 -1
  5. package/dist/cjs/exports/insight.js +5 -0
  6. package/dist/cjs/exports/insight.js.map +1 -0
  7. package/dist/cjs/exports/thirdweb.js +6 -2
  8. package/dist/cjs/exports/thirdweb.js.map +1 -1
  9. package/dist/cjs/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.js +104 -0
  10. package/dist/cjs/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.js.map +1 -0
  11. package/dist/cjs/extensions/thirdweb/write/publish.js +9 -4
  12. package/dist/cjs/extensions/thirdweb/write/publish.js.map +1 -1
  13. package/dist/cjs/insight/get-events.js +54 -0
  14. package/dist/cjs/insight/get-events.js.map +1 -0
  15. package/dist/cjs/insight/get-nfts.js +45 -0
  16. package/dist/cjs/insight/get-nfts.js.map +1 -0
  17. package/dist/cjs/insight/get-tokens.js +46 -0
  18. package/dist/cjs/insight/get-tokens.js.map +1 -0
  19. package/dist/cjs/insight/get-transactions.js +45 -0
  20. package/dist/cjs/insight/get-transactions.js.map +1 -0
  21. package/dist/cjs/insight/index.js +12 -0
  22. package/dist/cjs/insight/index.js.map +1 -0
  23. package/dist/cjs/pay/buyWithCrypto/getHistory.js +2 -2
  24. package/dist/cjs/pay/buyWithCrypto/getHistory.js.map +1 -1
  25. package/dist/cjs/pay/buyWithCrypto/getStatus.js +2 -2
  26. package/dist/cjs/pay/buyWithCrypto/getStatus.js.map +1 -1
  27. package/dist/cjs/pay/buyWithFiat/getHistory.js +2 -2
  28. package/dist/cjs/pay/buyWithFiat/getHistory.js.map +1 -1
  29. package/dist/cjs/pay/buyWithFiat/getStatus.js +2 -2
  30. package/dist/cjs/pay/buyWithFiat/getStatus.js.map +1 -1
  31. package/dist/cjs/pay/getBuyHistory.js +2 -2
  32. package/dist/cjs/pay/getBuyHistory.js.map +1 -1
  33. package/dist/cjs/react/web/ui/ConnectWallet/Details.js +4 -14
  34. package/dist/cjs/react/web/ui/ConnectWallet/Details.js.map +1 -1
  35. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js +6 -2
  36. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js.map +1 -1
  37. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js +2 -2
  38. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js.map +1 -1
  39. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +3 -1
  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/SendFunds.js +3 -1
  42. package/dist/cjs/react/web/ui/ConnectWallet/screens/SendFunds.js.map +1 -1
  43. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewAssets.js +1 -1
  44. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewAssets.js.map +1 -1
  45. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewNFTs.js +74 -32
  46. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewNFTs.js.map +1 -1
  47. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewTokens.js +46 -6
  48. package/dist/cjs/react/web/ui/ConnectWallet/screens/ViewTokens.js.map +1 -1
  49. package/dist/cjs/react/web/ui/MediaRenderer/useResolvedMediaType.js +4 -1
  50. package/dist/cjs/react/web/ui/MediaRenderer/useResolvedMediaType.js.map +1 -1
  51. package/dist/cjs/rpc/fetch-rpc.js +4 -4
  52. package/dist/cjs/rpc/fetch-rpc.js.map +1 -1
  53. package/dist/cjs/transaction/actions/gasless/providers/biconomy.js +0 -1
  54. package/dist/cjs/transaction/actions/gasless/providers/biconomy.js.map +1 -1
  55. package/dist/cjs/transaction/actions/gasless/providers/openzeppelin.js +0 -1
  56. package/dist/cjs/transaction/actions/gasless/providers/openzeppelin.js.map +1 -1
  57. package/dist/cjs/transaction/transaction-store.js +11 -10
  58. package/dist/cjs/transaction/transaction-store.js.map +1 -1
  59. package/dist/cjs/utils/fetch.js +5 -4
  60. package/dist/cjs/utils/fetch.js.map +1 -1
  61. package/dist/cjs/version.js +1 -1
  62. package/dist/cjs/version.js.map +1 -1
  63. package/dist/esm/chains/utils.js +40 -0
  64. package/dist/esm/chains/utils.js.map +1 -1
  65. package/dist/esm/event/actions/get-events.js +62 -8
  66. package/dist/esm/event/actions/get-events.js.map +1 -1
  67. package/dist/esm/exports/insight.js +2 -0
  68. package/dist/esm/exports/insight.js.map +1 -0
  69. package/dist/esm/exports/thirdweb.js +4 -0
  70. package/dist/esm/exports/thirdweb.js.map +1 -1
  71. package/dist/esm/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.js +98 -0
  72. package/dist/esm/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.js.map +1 -0
  73. package/dist/esm/extensions/thirdweb/write/publish.js +9 -4
  74. package/dist/esm/extensions/thirdweb/write/publish.js.map +1 -1
  75. package/dist/esm/insight/get-events.js +51 -0
  76. package/dist/esm/insight/get-events.js.map +1 -0
  77. package/dist/esm/insight/get-nfts.js +42 -0
  78. package/dist/esm/insight/get-nfts.js.map +1 -0
  79. package/dist/esm/insight/get-tokens.js +43 -0
  80. package/dist/esm/insight/get-tokens.js.map +1 -0
  81. package/dist/esm/insight/get-transactions.js +42 -0
  82. package/dist/esm/insight/get-transactions.js.map +1 -0
  83. package/dist/esm/insight/index.js +5 -0
  84. package/dist/esm/insight/index.js.map +1 -0
  85. package/dist/esm/pay/buyWithCrypto/getHistory.js +2 -2
  86. package/dist/esm/pay/buyWithCrypto/getHistory.js.map +1 -1
  87. package/dist/esm/pay/buyWithCrypto/getStatus.js +2 -2
  88. package/dist/esm/pay/buyWithCrypto/getStatus.js.map +1 -1
  89. package/dist/esm/pay/buyWithFiat/getHistory.js +2 -2
  90. package/dist/esm/pay/buyWithFiat/getHistory.js.map +1 -1
  91. package/dist/esm/pay/buyWithFiat/getStatus.js +2 -2
  92. package/dist/esm/pay/buyWithFiat/getStatus.js.map +1 -1
  93. package/dist/esm/pay/getBuyHistory.js +2 -2
  94. package/dist/esm/pay/getBuyHistory.js.map +1 -1
  95. package/dist/esm/react/web/ui/ConnectWallet/Details.js +4 -14
  96. package/dist/esm/react/web/ui/ConnectWallet/Details.js.map +1 -1
  97. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js +6 -2
  98. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.js.map +1 -1
  99. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js +2 -2
  100. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.js.map +1 -1
  101. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js +3 -1
  102. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.js.map +1 -1
  103. package/dist/esm/react/web/ui/ConnectWallet/screens/SendFunds.js +3 -1
  104. package/dist/esm/react/web/ui/ConnectWallet/screens/SendFunds.js.map +1 -1
  105. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewAssets.js +1 -1
  106. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewAssets.js.map +1 -1
  107. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewNFTs.js +75 -33
  108. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewNFTs.js.map +1 -1
  109. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewTokens.js +46 -6
  110. package/dist/esm/react/web/ui/ConnectWallet/screens/ViewTokens.js.map +1 -1
  111. package/dist/esm/react/web/ui/MediaRenderer/useResolvedMediaType.js +4 -1
  112. package/dist/esm/react/web/ui/MediaRenderer/useResolvedMediaType.js.map +1 -1
  113. package/dist/esm/rpc/fetch-rpc.js +4 -4
  114. package/dist/esm/rpc/fetch-rpc.js.map +1 -1
  115. package/dist/esm/transaction/actions/gasless/providers/biconomy.js +0 -1
  116. package/dist/esm/transaction/actions/gasless/providers/biconomy.js.map +1 -1
  117. package/dist/esm/transaction/actions/gasless/providers/openzeppelin.js +0 -1
  118. package/dist/esm/transaction/actions/gasless/providers/openzeppelin.js.map +1 -1
  119. package/dist/esm/transaction/transaction-store.js +11 -10
  120. package/dist/esm/transaction/transaction-store.js.map +1 -1
  121. package/dist/esm/utils/fetch.js +5 -4
  122. package/dist/esm/utils/fetch.js.map +1 -1
  123. package/dist/esm/version.js +1 -1
  124. package/dist/esm/version.js.map +1 -1
  125. package/dist/types/chains/types.d.ts +7 -0
  126. package/dist/types/chains/types.d.ts.map +1 -1
  127. package/dist/types/chains/utils.d.ts +15 -1
  128. package/dist/types/chains/utils.d.ts.map +1 -1
  129. package/dist/types/event/actions/get-events.d.ts +1 -6
  130. package/dist/types/event/actions/get-events.d.ts.map +1 -1
  131. package/dist/types/exports/insight.d.ts +2 -0
  132. package/dist/types/exports/insight.d.ts.map +1 -0
  133. package/dist/types/exports/thirdweb.d.ts +4 -0
  134. package/dist/types/exports/thirdweb.d.ts.map +1 -1
  135. package/dist/types/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.d.ts +64 -0
  136. package/dist/types/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.d.ts.map +1 -0
  137. package/dist/types/extensions/thirdweb/write/publish.d.ts.map +1 -1
  138. package/dist/types/insight/get-events.d.ts +31 -0
  139. package/dist/types/insight/get-events.d.ts.map +1 -0
  140. package/dist/types/insight/get-nfts.d.ts +25 -0
  141. package/dist/types/insight/get-nfts.d.ts.map +1 -0
  142. package/dist/types/insight/get-tokens.d.ts +25 -0
  143. package/dist/types/insight/get-tokens.d.ts.map +1 -0
  144. package/dist/types/insight/get-transactions.d.ts +25 -0
  145. package/dist/types/insight/get-transactions.d.ts.map +1 -0
  146. package/dist/types/insight/index.d.ts +5 -0
  147. package/dist/types/insight/index.d.ts.map +1 -0
  148. package/dist/types/pay/buyWithCrypto/getHistory.d.ts.map +1 -1
  149. package/dist/types/pay/buyWithCrypto/getStatus.d.ts.map +1 -1
  150. package/dist/types/pay/buyWithFiat/getHistory.d.ts.map +1 -1
  151. package/dist/types/pay/buyWithFiat/getStatus.d.ts.map +1 -1
  152. package/dist/types/pay/getBuyHistory.d.ts.map +1 -1
  153. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts.map +1 -1
  154. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.d.ts.map +1 -1
  155. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.d.ts.map +1 -1
  156. package/dist/types/react/web/ui/ConnectWallet/screens/SendFunds.d.ts.map +1 -1
  157. package/dist/types/react/web/ui/ConnectWallet/screens/ViewNFTs.d.ts.map +1 -1
  158. package/dist/types/react/web/ui/ConnectWallet/screens/ViewTokens.d.ts.map +1 -1
  159. package/dist/types/react/web/ui/MediaRenderer/useResolvedMediaType.d.ts +1 -1
  160. package/dist/types/react/web/ui/MediaRenderer/useResolvedMediaType.d.ts.map +1 -1
  161. package/dist/types/rpc/fetch-rpc.d.ts.map +1 -1
  162. package/dist/types/transaction/actions/gasless/providers/biconomy.d.ts.map +1 -1
  163. package/dist/types/transaction/actions/gasless/providers/openzeppelin.d.ts.map +1 -1
  164. package/dist/types/transaction/transaction-store.d.ts.map +1 -1
  165. package/dist/types/utils/fetch.d.ts +1 -1
  166. package/dist/types/utils/fetch.d.ts.map +1 -1
  167. package/dist/types/version.d.ts +1 -1
  168. package/dist/types/version.d.ts.map +1 -1
  169. package/package.json +8 -2
  170. package/src/chains/types.ts +8 -0
  171. package/src/chains/utils.ts +61 -0
  172. package/src/event/actions/get-events.test.ts +96 -0
  173. package/src/event/actions/get-events.ts +99 -12
  174. package/src/exports/insight.ts +1 -0
  175. package/src/exports/thirdweb.ts +5 -0
  176. package/src/extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.ts +104 -0
  177. package/src/extensions/thirdweb/write/publish.ts +12 -4
  178. package/src/insight/get-events.ts +78 -0
  179. package/src/insight/get-nfts.ts +65 -0
  180. package/src/insight/get-tokens.ts +66 -0
  181. package/src/insight/get-transactions.ts +66 -0
  182. package/src/insight/index.ts +4 -0
  183. package/src/pay/buyWithCrypto/getHistory.ts +4 -2
  184. package/src/pay/buyWithCrypto/getStatus.ts +4 -2
  185. package/src/pay/buyWithFiat/getHistory.ts +4 -2
  186. package/src/pay/buyWithFiat/getStatus.ts +4 -2
  187. package/src/pay/getBuyHistory.ts +4 -2
  188. package/src/react/web/ui/ConnectWallet/Details.tsx +15 -33
  189. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/ConfirmationScreen.tsx +10 -2
  190. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/TokenSelectorScreen.tsx +2 -2
  191. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/TransferConfirmationScreen.tsx +5 -1
  192. package/src/react/web/ui/ConnectWallet/screens/SendFunds.tsx +5 -1
  193. package/src/react/web/ui/ConnectWallet/screens/ViewAssets.tsx +1 -1
  194. package/src/react/web/ui/ConnectWallet/screens/ViewNFTs.tsx +107 -55
  195. package/src/react/web/ui/ConnectWallet/screens/ViewTokens.tsx +94 -11
  196. package/src/react/web/ui/MediaRenderer/useResolvedMediaType.ts +4 -1
  197. package/src/rpc/fetch-rpc.ts +6 -4
  198. package/src/transaction/actions/gasless/providers/biconomy.ts +0 -1
  199. package/src/transaction/actions/gasless/providers/openzeppelin.ts +0 -1
  200. package/src/transaction/transaction-store.ts +11 -22
  201. package/src/utils/fetch.ts +6 -5
  202. package/src/version.ts +1 -1
@@ -7,6 +7,7 @@ import type {
7
7
  Chain,
8
8
  ChainMetadata,
9
9
  ChainOptions,
10
+ ChainService,
10
11
  LegacyChain,
11
12
  } from "./types.js";
12
13
 
@@ -321,6 +322,66 @@ export function getChainMetadata(chain: Chain): Promise<ChainMetadata> {
321
322
  );
322
323
  }
323
324
 
325
+ type FetchChainServiceResponse =
326
+ | {
327
+ data: {
328
+ services: ChainService[];
329
+ };
330
+ error?: never;
331
+ }
332
+ | {
333
+ data?: never;
334
+ error: unknown;
335
+ };
336
+
337
+ /**
338
+ * Retrieves a list of services available on a given chain
339
+ * @param chain - The chain object containing the chain ID.
340
+ * @returns A Promise that resolves to chain services.
341
+ * @throws If there is an error fetching the chain services.
342
+ * @example
343
+ * ```ts
344
+ * const chain = defineChain({ id: 1 });
345
+ * const chainServices = await getChainServices(chain);
346
+ * console.log(chainServices);
347
+ * ```
348
+ * @chain
349
+ */
350
+ export function getChainServices(chain: Chain): Promise<ChainService[]> {
351
+ const chainId = chain.id;
352
+ return withCache(
353
+ async () => {
354
+ try {
355
+ const res = await fetch(
356
+ `https://api.thirdweb.com/v1/chains/${chainId}/services`,
357
+ );
358
+ if (!res.ok) {
359
+ res.body?.cancel();
360
+ throw new Error(`Failed to fetch services for chainId ${chainId}`);
361
+ }
362
+
363
+ const response = (await res.json()) as FetchChainServiceResponse;
364
+ if (response.error) {
365
+ throw new Error(`Failed to fetch services for chainId ${chainId}`);
366
+ }
367
+ if (!response.data) {
368
+ throw new Error(`Failed to fetch services for chainId ${chainId}`);
369
+ }
370
+
371
+ const services = response.data.services;
372
+
373
+ return services;
374
+ } catch {
375
+ throw new Error(`Failed to fetch services for chainId ${chainId}`);
376
+ }
377
+ },
378
+ {
379
+ cacheKey: `chain:${chainId}:services`,
380
+ cacheTime: 24 * 60 * 60 * 1000, // 1 day
381
+ },
382
+ );
383
+ }
384
+
324
385
  /**
325
386
  * Convert `ApiChain` to `Chain` object
326
387
  * @internal
@@ -15,6 +15,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
15
15
  const events = await getContractEvents({
16
16
  contract: USDT_CONTRACT,
17
17
  fromBlock: FORK_BLOCK_NUMBER - 10n,
18
+ useIndexer: false,
18
19
  });
19
20
  expect(events.length).toBe(261);
20
21
  });
@@ -35,6 +36,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
35
36
  const events = await getContractEvents({
36
37
  contract: USDT_CONTRACT,
37
38
  blockRange: 10n,
39
+ useIndexer: false,
38
40
  });
39
41
  expect(events.length).toBe(241);
40
42
 
@@ -42,6 +44,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
42
44
  contract: USDT_CONTRACT,
43
45
  fromBlock: FORK_BLOCK_NUMBER - 9n, // 1 less than range as fromBlock and toBlock are inclusive
44
46
  toBlock: FORK_BLOCK_NUMBER,
47
+ useIndexer: false,
45
48
  });
46
49
  expect(explicitEvents.length).toEqual(events.length);
47
50
  });
@@ -51,6 +54,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
51
54
  contract: USDT_CONTRACT,
52
55
  fromBlock: FORK_BLOCK_NUMBER - 49n,
53
56
  blockRange: 20n,
57
+ useIndexer: false,
54
58
  });
55
59
  expect(eventsFromBlock.length).toBe(412);
56
60
 
@@ -58,6 +62,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
58
62
  contract: USDT_CONTRACT,
59
63
  toBlock: FORK_BLOCK_NUMBER - 30n,
60
64
  blockRange: 20n,
65
+ useIndexer: false,
61
66
  });
62
67
  expect(eventsToBlock.length).toBe(eventsFromBlock.length);
63
68
 
@@ -65,6 +70,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
65
70
  contract: USDT_CONTRACT,
66
71
  fromBlock: FORK_BLOCK_NUMBER - 49n,
67
72
  toBlock: FORK_BLOCK_NUMBER - 30n,
73
+ useIndexer: false,
68
74
  });
69
75
  expect(explicitEvents.length).toEqual(eventsFromBlock.length);
70
76
  });
@@ -73,6 +79,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
73
79
  const events = await getContractEvents({
74
80
  contract: USDT_CONTRACT,
75
81
  fromBlock: FORK_BLOCK_NUMBER - 100n,
82
+ useIndexer: false,
76
83
  events: [
77
84
  prepareEvent({
78
85
  signature: "event Burn(address indexed burner, uint256 amount)",
@@ -86,6 +93,8 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
86
93
  const events = await getContractEvents({
87
94
  contract: USDT_CONTRACT,
88
95
  fromBlock: FORK_BLOCK_NUMBER - 10n,
96
+ toBlock: FORK_BLOCK_NUMBER,
97
+ useIndexer: false,
89
98
  events: [
90
99
  prepareEvent({
91
100
  signature: "event Burn(address indexed burner, uint256 amount)",
@@ -126,6 +135,8 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
126
135
  const events = await getContractEvents({
127
136
  contract: DOODLES_CONTRACT,
128
137
  fromBlock: FORK_BLOCK_NUMBER - 1000n,
138
+ toBlock: FORK_BLOCK_NUMBER,
139
+ useIndexer: false,
129
140
  events: [transferEvent()],
130
141
  });
131
142
  expect(events.length).toBe(38);
@@ -135,6 +146,8 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
135
146
  const events = await getContractEvents({
136
147
  contract: DOODLES_CONTRACT,
137
148
  fromBlock: FORK_BLOCK_NUMBER - 1000n,
149
+ toBlock: FORK_BLOCK_NUMBER,
150
+ useIndexer: false,
138
151
  events: [
139
152
  transferEvent({
140
153
  from: "0xB81965DdFdDA3923f292a47A1be83ba3A36B5133",
@@ -143,4 +156,87 @@ describe.runIf(process.env.TW_SECRET_KEY)("getEvents", () => {
143
156
  });
144
157
  expect(events.length).toBe(2);
145
158
  });
159
+
160
+ // insight tests
161
+
162
+ it("should get events for blockHash using indexer", async () => {
163
+ const BLOCK_HASH =
164
+ "0xb0ad5ee7b4912b50e5a2d7993796944653a4c0632c57740fe4a7a1c61e426324";
165
+ const events = await getContractEvents({
166
+ contract: USDT_CONTRACT,
167
+ blockHash: BLOCK_HASH,
168
+ useIndexer: true,
169
+ });
170
+
171
+ expect(events.length).toBe(14);
172
+ });
173
+
174
+ it("should get individual events with extension no filter using indexer", async () => {
175
+ const events = await getContractEvents({
176
+ contract: DOODLES_CONTRACT,
177
+ fromBlock: FORK_BLOCK_NUMBER - 1000n,
178
+ toBlock: FORK_BLOCK_NUMBER,
179
+ events: [transferEvent()],
180
+ useIndexer: true,
181
+ });
182
+ expect(events.length).toBe(38);
183
+ });
184
+
185
+ it("should get events for signature using indexer", async () => {
186
+ const events = await getContractEvents({
187
+ contract: DOODLES_CONTRACT,
188
+ fromBlock: FORK_BLOCK_NUMBER - 1000n,
189
+ toBlock: FORK_BLOCK_NUMBER,
190
+ events: [
191
+ transferEvent({
192
+ from: "0xB81965DdFdDA3923f292a47A1be83ba3A36B5133",
193
+ }),
194
+ ],
195
+ useIndexer: true,
196
+ });
197
+
198
+ expect(events.length).toBe(2);
199
+ });
200
+
201
+ it("should get specified events using indexer", async () => {
202
+ const events = await getContractEvents({
203
+ contract: USDT_CONTRACT,
204
+ fromBlock: FORK_BLOCK_NUMBER - 10n,
205
+ toBlock: FORK_BLOCK_NUMBER,
206
+ useIndexer: true,
207
+ events: [
208
+ prepareEvent({
209
+ signature: "event Burn(address indexed burner, uint256 amount)",
210
+ }),
211
+ prepareEvent({
212
+ signature: {
213
+ anonymous: false,
214
+ inputs: [
215
+ {
216
+ indexed: true,
217
+ internalType: "address",
218
+ name: "owner",
219
+ type: "address",
220
+ },
221
+ {
222
+ indexed: true,
223
+ internalType: "address",
224
+ name: "spender",
225
+ type: "address",
226
+ },
227
+ {
228
+ indexed: false,
229
+ internalType: "uint256",
230
+ name: "value",
231
+ type: "uint256",
232
+ },
233
+ ],
234
+ name: "Approval",
235
+ type: "event",
236
+ },
237
+ }),
238
+ ],
239
+ });
240
+ expect(events.length).toMatchInlineSnapshot("9");
241
+ });
146
242
  });
@@ -1,18 +1,14 @@
1
- /**
2
- * 1. blockTime + contract (with abi) + no events -> logs with types and parsing *if* contract has abi defined
3
- * 2. blockTime + contract (no abi) + no events -> logs with NO types but *with* parsing
4
- * 3. blockTime + no contract + events -> logs with types and parsing (across all "addresses") (no contract filter)
5
- * 4. blockTime + contract + events -> logs with types and parsing (filtered by contract address + event topics)
6
- */
7
-
8
1
  import type {
9
2
  Abi,
10
3
  AbiEvent,
11
4
  ExtractAbiEvent,
12
5
  ExtractAbiEventNames,
13
6
  } from "abitype";
7
+ import { type Log, formatLog } from "viem";
8
+ import { getChainServices } from "../../chains/utils.js";
14
9
  import { resolveContractAbi } from "../../contract/actions/resolve-abi.js";
15
10
  import type { ThirdwebContract } from "../../contract/contract.js";
11
+ import { getContractEvents as getContractEventsInsight } from "../../insight/get-events.js";
16
12
  import { eth_blockNumber } from "../../rpc/actions/eth_blockNumber.js";
17
13
  import {
18
14
  type GetLogsBlockParams,
@@ -21,6 +17,7 @@ import {
21
17
  } from "../../rpc/actions/eth_getLogs.js";
22
18
  import { getRpcClient } from "../../rpc/rpc.js";
23
19
  import { getAddress } from "../../utils/address.js";
20
+ import { type Hex, numberToHex } from "../../utils/encoding/hex.js";
24
21
  import type { Prettify } from "../../utils/type-utils.js";
25
22
  import { type PreparedEvent, prepareEvent } from "../prepare-event.js";
26
23
  import { isAbiEvent } from "../utils.js";
@@ -34,6 +31,7 @@ export type GetContractEventsOptionsDirect<
34
31
  contract: ThirdwebContract<abi>;
35
32
  events?: abiEvents;
36
33
  strict?: TStrict;
34
+ useIndexer?: boolean;
37
35
  };
38
36
 
39
37
  export type GetContractEventsOptions<
@@ -49,6 +47,10 @@ export type GetContractEventsResult<
49
47
  TStrict extends boolean,
50
48
  > = ParseEventLogsResult<abiEvents, TStrict>;
51
49
 
50
+ type GetLogsParamsExtra = {
51
+ signature?: string;
52
+ } & GetLogsParams;
53
+
52
54
  /**
53
55
  * Retrieves events from a contract based on the provided options.
54
56
  * @param options - The options for retrieving events.
@@ -106,7 +108,13 @@ export async function getContractEvents<
106
108
  >(
107
109
  options: GetContractEventsOptions<abi, abiEvents, TStrict>,
108
110
  ): Promise<GetContractEventsResult<abiEvents, TStrict>> {
109
- const { contract, events, blockRange, ...restParams } = options;
111
+ const {
112
+ contract,
113
+ events,
114
+ blockRange,
115
+ useIndexer = true,
116
+ ...restParams
117
+ } = options;
110
118
 
111
119
  const rpcRequest = getRpcClient(contract);
112
120
 
@@ -164,7 +172,7 @@ export async function getContractEvents<
164
172
  }
165
173
  }
166
174
 
167
- const logsParams: GetLogsParams[] =
175
+ const logsParams: GetLogsParamsExtra[] =
168
176
  events && events.length > 0
169
177
  ? // if we have events passed in then we use those
170
178
  events.map((e) => ({
@@ -175,9 +183,33 @@ export async function getContractEvents<
175
183
  : // otherwise we want "all" events (aka not pass any topics at all)
176
184
  [{ ...restParams, address: getAddress(contract.address) }];
177
185
 
178
- const logs = await Promise.all(
179
- logsParams.map((ethLogParams) => eth_getLogs(rpcRequest, ethLogParams)),
180
- );
186
+ let logs: Log[][] = [];
187
+
188
+ // try fetching from insight if available
189
+ if (useIndexer) {
190
+ try {
191
+ logs = await Promise.all(
192
+ logsParams.map((p) =>
193
+ getLogsFromInsight({
194
+ params: p,
195
+ contract,
196
+ }),
197
+ ),
198
+ );
199
+ } catch (e) {
200
+ console.warn("Error fetching from insight", e);
201
+ // fetch from rpc
202
+ logs = await Promise.all(
203
+ logsParams.map((ethLogParams) => eth_getLogs(rpcRequest, ethLogParams)),
204
+ );
205
+ }
206
+ } else {
207
+ // fetch from rpc
208
+ logs = await Promise.all(
209
+ logsParams.map((ethLogParams) => eth_getLogs(rpcRequest, ethLogParams)),
210
+ );
211
+ }
212
+
181
213
  const flattenLogs = logs
182
214
  .flat()
183
215
  .sort((a, b) => Number((a.blockNumber ?? 0n) - (b.blockNumber ?? 0n)));
@@ -186,3 +218,58 @@ export async function getContractEvents<
186
218
  events: resolvedEvents,
187
219
  });
188
220
  }
221
+
222
+ async function getLogsFromInsight(options: {
223
+ params: GetLogsParamsExtra;
224
+ contract: ThirdwebContract<Abi>;
225
+ }): Promise<Log[]> {
226
+ const { params, contract } = options;
227
+
228
+ const chainServices = await getChainServices(contract.chain);
229
+ const insightEnabled = chainServices.some(
230
+ (c) => c.service === "insight" && c.enabled,
231
+ );
232
+
233
+ if (!insightEnabled) {
234
+ throw new Error(
235
+ `Insight is not available for chainId ${contract.chain.id}`,
236
+ );
237
+ }
238
+
239
+ const fromBlock =
240
+ typeof params.fromBlock === "bigint" ? Number(params.fromBlock) : undefined;
241
+
242
+ const toBlock =
243
+ typeof params.toBlock === "bigint" ? Number(params.toBlock) : undefined;
244
+
245
+ const r = await getContractEventsInsight({
246
+ client: contract.client,
247
+ chains: [contract.chain],
248
+ contractAddress: contract.address,
249
+ queryOptions: {
250
+ limit: 500,
251
+ filter_block_hash: params.blockHash,
252
+ filter_block_number_gte: fromBlock,
253
+ filter_block_number_lte: toBlock,
254
+ filter_topic_0: params.topics?.[0] as Hex | undefined,
255
+ filter_topic_1: params.topics?.[1] as Hex | undefined,
256
+ filter_topic_2: params.topics?.[2] as Hex | undefined,
257
+ filter_topic_3: params.topics?.[3] as Hex | undefined,
258
+ },
259
+ });
260
+
261
+ const cleanedEventData = r.map((tx) => ({
262
+ chainId: tx.chain_id,
263
+ blockNumber: numberToHex(Number(tx.block_number)),
264
+ blockHash: tx.block_hash as Hex,
265
+ blockTimestamp: tx.block_timestamp,
266
+ transactionHash: tx.transaction_hash as Hex,
267
+ transactionIndex: numberToHex(tx.transaction_index),
268
+ logIndex: numberToHex(tx.log_index),
269
+ address: tx.address,
270
+ data: tx.data as Hex,
271
+ topics: tx.topics as [`0x${string}`, ...`0x${string}`[]] | [] | undefined,
272
+ }));
273
+
274
+ return cleanedEventData.map((e) => formatLog(e));
275
+ }
@@ -0,0 +1 @@
1
+ export * from "../insight/index.js";
@@ -76,6 +76,11 @@ export {
76
76
  */
77
77
  export * as Bridge from "../bridge/index.js";
78
78
 
79
+ /**
80
+ * INSIGHT
81
+ */
82
+ export * as Insight from "../insight/index.js";
83
+
79
84
  /**
80
85
  * WALLETS
81
86
  */
@@ -0,0 +1,104 @@
1
+ import { readContract } from "../../../../../transaction/read-contract.js";
2
+ import type { BaseTransactionOptions } from "../../../../../transaction/types.js";
3
+
4
+ import { decodeAbiParameters } from "viem";
5
+ import type { Hex } from "../../../../../utils/encoding/hex.js";
6
+ import { detectMethod } from "../../../../../utils/bytecode/detectExtension.js";
7
+
8
+ export const FN_SELECTOR = "0x4a00cc48" as const;
9
+ const FN_INPUTS = [] as const;
10
+ const FN_OUTPUTS = [
11
+ {
12
+ type: "tuple[]",
13
+ components: [
14
+ {
15
+ type: "tuple",
16
+ name: "metadata",
17
+ components: [
18
+ {
19
+ type: "string",
20
+ name: "name",
21
+ },
22
+ {
23
+ type: "string",
24
+ name: "metadataURI",
25
+ },
26
+ {
27
+ type: "address",
28
+ name: "implementation",
29
+ },
30
+ ],
31
+ },
32
+ {
33
+ type: "tuple[]",
34
+ name: "functions",
35
+ components: [
36
+ {
37
+ type: "bytes4",
38
+ name: "functionSelector",
39
+ },
40
+ {
41
+ type: "string",
42
+ name: "functionSignature",
43
+ },
44
+ ],
45
+ },
46
+ ],
47
+ },
48
+ ] as const;
49
+
50
+ /**
51
+ * Checks if the `getAllExtensions` method is supported by the given contract.
52
+ * @param availableSelectors An array of 4byte function selectors of the contract. You can get this in various ways, such as using "whatsabi" or if you have the ABI of the contract available you can use it to generate the selectors.
53
+ * @returns A boolean indicating if the `getAllExtensions` method is supported.
54
+ * @extension DYNAMIC-CONTRACTS
55
+ * @example
56
+ * ```ts
57
+ * import { isGetAllExtensionsSupported } from "thirdweb/extensions/dynamic-contracts";
58
+ * const supported = isGetAllExtensionsSupported(["0x..."]);
59
+ * ```
60
+ */
61
+ export function isGetAllExtensionsSupported(availableSelectors: string[]) {
62
+ return detectMethod({
63
+ availableSelectors,
64
+ method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
65
+ });
66
+ }
67
+
68
+ /**
69
+ * Decodes the result of the getAllExtensions function call.
70
+ * @param result - The hexadecimal result to decode.
71
+ * @returns The decoded result as per the FN_OUTPUTS definition.
72
+ * @extension DYNAMIC-CONTRACTS
73
+ * @example
74
+ * ```ts
75
+ * import { decodeGetAllExtensionsResult } from "thirdweb/extensions/dynamic-contracts";
76
+ * const result = decodeGetAllExtensionsResultResult("...");
77
+ * ```
78
+ */
79
+ export function decodeGetAllExtensionsResult(result: Hex) {
80
+ return decodeAbiParameters(FN_OUTPUTS, result)[0];
81
+ }
82
+
83
+ /**
84
+ * Calls the "getAllExtensions" function on the contract.
85
+ * @param options - The options for the getAllExtensions function.
86
+ * @returns The parsed result of the function call.
87
+ * @extension DYNAMIC-CONTRACTS
88
+ * @example
89
+ * ```ts
90
+ * import { getAllExtensions } from "thirdweb/extensions/dynamic-contracts";
91
+ *
92
+ * const result = await getAllExtensions({
93
+ * contract,
94
+ * });
95
+ *
96
+ * ```
97
+ */
98
+ export async function getAllExtensions(options: BaseTransactionOptions) {
99
+ return readContract({
100
+ contract: options.contract,
101
+ method: [FN_SELECTOR, FN_INPUTS, FN_OUTPUTS] as const,
102
+ params: [],
103
+ });
104
+ }
@@ -5,6 +5,7 @@ import type { ThirdwebClient } from "../../../client/client.js";
5
5
  import { ZERO_ADDRESS } from "../../../constants/addresses.js";
6
6
  import { getContract } from "../../../contract/contract.js";
7
7
  import { CONTRACT_PUBLISHER_ADDRESS } from "../../../contract/deployment/publisher.js";
8
+ import { isGetAllExtensionsSupported } from "../../../extensions/dynamic-contracts/__generated__/IExtensionManager/read/getAllExtensions.js";
8
9
  import { download } from "../../../storage/download.js";
9
10
  import { upload } from "../../../storage/upload.js";
10
11
  import type { BaseTransactionOptions } from "../../../transaction/types.js";
@@ -79,8 +80,14 @@ export function publishContract(
79
80
  compositeAbi: options.metadata.compositeAbi,
80
81
  constructorParams: options.metadata.constructorParams,
81
82
  implConstructorParams: options.metadata.implConstructorParams,
82
- defaultExtensions: options.metadata.defaultExtensions,
83
- defaultModules: options.metadata.defaultModules,
83
+ defaultExtensions:
84
+ routerType === "dynamic"
85
+ ? options.metadata.defaultExtensions
86
+ : undefined,
87
+ defaultModules:
88
+ routerType === "modular"
89
+ ? options.metadata.defaultModules
90
+ : undefined,
84
91
  deployType: options.metadata.deployType,
85
92
  description: options.metadata.description,
86
93
  displayName: options.metadata.displayName,
@@ -131,6 +138,7 @@ function getRouterType(abi: Abi) {
131
138
  .filter((f) => f.type === "function")
132
139
  .map((f) => toFunctionSelector(f));
133
140
  const isModule = isGetInstalledModulesSupported(fnSelectors);
134
- // TODO add dynamic detection
135
- return isModule ? "modular" : "none";
141
+ const isDynamic = isGetAllExtensionsSupported(fnSelectors);
142
+
143
+ return isModule ? "modular" : isDynamic ? "dynamic" : "none";
136
144
  }
@@ -0,0 +1,78 @@
1
+ import {
2
+ type GetV1EventsByContractAddressData,
3
+ type GetV1EventsByContractAddressResponse,
4
+ getV1EventsByContractAddress,
5
+ } from "@thirdweb-dev/insight";
6
+ import type { AbiEvent } from "ox/AbiEvent";
7
+ import { stringify } from "viem";
8
+ import type { Chain } from "../chains/types.js";
9
+ import type { ThirdwebClient } from "../client/client.js";
10
+ import type { PreparedEvent } from "../event/prepare-event.js";
11
+ import { getThirdwebDomains } from "../utils/domains.js";
12
+ import { getClientFetch } from "../utils/fetch.js";
13
+
14
+ export type ContractEvent = NonNullable<
15
+ GetV1EventsByContractAddressResponse["data"]
16
+ >[number];
17
+
18
+ /**
19
+ * Get contract events
20
+ * @example
21
+ * ```ts
22
+ * import { Insight } from "thirdweb";
23
+ *
24
+ * const events = await Insight.getContractEvents({
25
+ * client,
26
+ * chains: [sepolia],
27
+ * contractAddress: "0x1234567890123456789012345678901234567890",
28
+ * event: transferEvent(),
29
+ * decodeLogs: true,
30
+ * });
31
+ * ```
32
+ * @insight
33
+ */
34
+ export async function getContractEvents(options: {
35
+ client: ThirdwebClient;
36
+ chains: Chain[];
37
+ contractAddress: string;
38
+ event?: PreparedEvent<AbiEvent>;
39
+ decodeLogs?: boolean;
40
+ queryOptions?: GetV1EventsByContractAddressData["query"];
41
+ }): Promise<ContractEvent[]> {
42
+ const { client, chains, contractAddress, event, queryOptions, decodeLogs } =
43
+ options;
44
+
45
+ const defaultQueryOptions: GetV1EventsByContractAddressData["query"] = {
46
+ chain: chains.map((chain) => chain.id),
47
+ limit: 100,
48
+ decode: decodeLogs,
49
+ };
50
+
51
+ if (event) {
52
+ defaultQueryOptions.filter_topic_0 = event.topics[0];
53
+ defaultQueryOptions.filter_topic_1 = event.topics[1];
54
+ defaultQueryOptions.filter_topic_2 = event.topics[2];
55
+ defaultQueryOptions.filter_topic_3 = event.topics[3];
56
+ }
57
+
58
+ const result = await getV1EventsByContractAddress({
59
+ baseUrl: `https://${getThirdwebDomains().insight}`,
60
+ fetch: getClientFetch(client),
61
+ path: {
62
+ contractAddress,
63
+ },
64
+ query: {
65
+ chain: chains.map((chain) => chain.id),
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
+ return result.data?.data ?? [];
78
+ }