thirdweb 5.89.0 → 5.90.0

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 (174) hide show
  1. package/dist/cjs/adapters/ethers5.js +2 -0
  2. package/dist/cjs/adapters/ethers5.js.map +1 -1
  3. package/dist/cjs/chains/constants.js +17 -2
  4. package/dist/cjs/chains/constants.js.map +1 -1
  5. package/dist/cjs/contract/actions/resolve-abi.js +9 -11
  6. package/dist/cjs/contract/actions/resolve-abi.js.map +1 -1
  7. package/dist/cjs/exports/extensions/erc721.js +4 -2
  8. package/dist/cjs/exports/extensions/erc721.js.map +1 -1
  9. package/dist/cjs/exports/wallets/smart.js +2 -1
  10. package/dist/cjs/exports/wallets/smart.js.map +1 -1
  11. package/dist/cjs/extensions/erc721/read/getNFT.js +30 -7
  12. package/dist/cjs/extensions/erc721/read/getNFT.js.map +1 -1
  13. package/dist/cjs/extensions/erc721/read/getNFTs.js.map +1 -1
  14. package/dist/cjs/gas/fee-data.js +22 -15
  15. package/dist/cjs/gas/fee-data.js.map +1 -1
  16. package/dist/cjs/storage/download.js +16 -0
  17. package/dist/cjs/storage/download.js.map +1 -1
  18. package/dist/cjs/storage/mock.js +46 -0
  19. package/dist/cjs/storage/mock.js.map +1 -0
  20. package/dist/cjs/storage/upload/web-node.js +6 -1
  21. package/dist/cjs/storage/upload/web-node.js.map +1 -1
  22. package/dist/cjs/transaction/actions/estimate-gas-cost.js +1 -1
  23. package/dist/cjs/transaction/actions/estimate-gas-cost.js.map +1 -1
  24. package/dist/cjs/transaction/actions/to-serializable-transaction.js +3 -1
  25. package/dist/cjs/transaction/actions/to-serializable-transaction.js.map +1 -1
  26. package/dist/cjs/transaction/prepare-transaction.js +8 -0
  27. package/dist/cjs/transaction/prepare-transaction.js.map +1 -1
  28. package/dist/cjs/utils/process.js +4 -1
  29. package/dist/cjs/utils/process.js.map +1 -1
  30. package/dist/cjs/version.js +1 -1
  31. package/dist/cjs/wallets/manager/index.js +1 -1
  32. package/dist/cjs/wallets/manager/index.js.map +1 -1
  33. package/dist/cjs/wallets/smart/index.js +1 -0
  34. package/dist/cjs/wallets/smart/index.js.map +1 -1
  35. package/dist/cjs/wallets/smart/lib/bundler.js +75 -0
  36. package/dist/cjs/wallets/smart/lib/bundler.js.map +1 -1
  37. package/dist/cjs/wallets/smart/lib/calls.js +13 -7
  38. package/dist/cjs/wallets/smart/lib/calls.js.map +1 -1
  39. package/dist/cjs/wallets/smart/lib/userop.js +42 -17
  40. package/dist/cjs/wallets/smart/lib/userop.js.map +1 -1
  41. package/dist/esm/adapters/ethers5.js +2 -0
  42. package/dist/esm/adapters/ethers5.js.map +1 -1
  43. package/dist/esm/chains/constants.js +17 -2
  44. package/dist/esm/chains/constants.js.map +1 -1
  45. package/dist/esm/contract/actions/resolve-abi.js +9 -11
  46. package/dist/esm/contract/actions/resolve-abi.js.map +1 -1
  47. package/dist/esm/exports/extensions/erc721.js +1 -0
  48. package/dist/esm/exports/extensions/erc721.js.map +1 -1
  49. package/dist/esm/exports/wallets/smart.js +1 -1
  50. package/dist/esm/exports/wallets/smart.js.map +1 -1
  51. package/dist/esm/extensions/erc721/read/getNFT.js +30 -7
  52. package/dist/esm/extensions/erc721/read/getNFT.js.map +1 -1
  53. package/dist/esm/extensions/erc721/read/getNFTs.js.map +1 -1
  54. package/dist/esm/gas/fee-data.js +22 -15
  55. package/dist/esm/gas/fee-data.js.map +1 -1
  56. package/dist/esm/storage/download.js +16 -0
  57. package/dist/esm/storage/download.js.map +1 -1
  58. package/dist/esm/storage/mock.js +42 -0
  59. package/dist/esm/storage/mock.js.map +1 -0
  60. package/dist/esm/storage/upload/web-node.js +6 -1
  61. package/dist/esm/storage/upload/web-node.js.map +1 -1
  62. package/dist/esm/transaction/actions/estimate-gas-cost.js +1 -1
  63. package/dist/esm/transaction/actions/estimate-gas-cost.js.map +1 -1
  64. package/dist/esm/transaction/actions/to-serializable-transaction.js +3 -1
  65. package/dist/esm/transaction/actions/to-serializable-transaction.js.map +1 -1
  66. package/dist/esm/transaction/prepare-transaction.js +7 -0
  67. package/dist/esm/transaction/prepare-transaction.js.map +1 -1
  68. package/dist/esm/utils/process.js +3 -0
  69. package/dist/esm/utils/process.js.map +1 -1
  70. package/dist/esm/version.js +1 -1
  71. package/dist/esm/wallets/manager/index.js +1 -1
  72. package/dist/esm/wallets/manager/index.js.map +1 -1
  73. package/dist/esm/wallets/smart/index.js +1 -1
  74. package/dist/esm/wallets/smart/index.js.map +1 -1
  75. package/dist/esm/wallets/smart/lib/bundler.js +74 -0
  76. package/dist/esm/wallets/smart/lib/bundler.js.map +1 -1
  77. package/dist/esm/wallets/smart/lib/calls.js +13 -7
  78. package/dist/esm/wallets/smart/lib/calls.js.map +1 -1
  79. package/dist/esm/wallets/smart/lib/userop.js +41 -17
  80. package/dist/esm/wallets/smart/lib/userop.js.map +1 -1
  81. package/dist/types/adapters/ethers5.d.ts.map +1 -1
  82. package/dist/types/chains/constants.d.ts +1 -1
  83. package/dist/types/chains/constants.d.ts.map +1 -1
  84. package/dist/types/chains/types.d.ts +2 -0
  85. package/dist/types/chains/types.d.ts.map +1 -1
  86. package/dist/types/contract/actions/resolve-abi.d.ts.map +1 -1
  87. package/dist/types/exports/extensions/erc721.d.ts +1 -0
  88. package/dist/types/exports/extensions/erc721.d.ts.map +1 -1
  89. package/dist/types/exports/wallets/smart.d.ts +1 -1
  90. package/dist/types/exports/wallets/smart.d.ts.map +1 -1
  91. package/dist/types/extensions/erc721/read/getNFT.d.ts +19 -0
  92. package/dist/types/extensions/erc721/read/getNFT.d.ts.map +1 -1
  93. package/dist/types/extensions/erc721/read/getNFTs.d.ts +7 -0
  94. package/dist/types/extensions/erc721/read/getNFTs.d.ts.map +1 -1
  95. package/dist/types/gas/fee-data.d.ts +6 -5
  96. package/dist/types/gas/fee-data.d.ts.map +1 -1
  97. package/dist/types/storage/download.d.ts.map +1 -1
  98. package/dist/types/storage/mock.d.ts +11 -0
  99. package/dist/types/storage/mock.d.ts.map +1 -0
  100. package/dist/types/storage/upload/web-node.d.ts.map +1 -1
  101. package/dist/types/transaction/actions/to-serializable-transaction.d.ts +2 -0
  102. package/dist/types/transaction/actions/to-serializable-transaction.d.ts.map +1 -1
  103. package/dist/types/transaction/prepare-transaction.d.ts +3 -0
  104. package/dist/types/transaction/prepare-transaction.d.ts.map +1 -1
  105. package/dist/types/utils/process.d.ts +1 -0
  106. package/dist/types/utils/process.d.ts.map +1 -1
  107. package/dist/types/version.d.ts +1 -1
  108. package/dist/types/wallets/manager/index.d.ts +1 -1
  109. package/dist/types/wallets/manager/index.d.ts.map +1 -1
  110. package/dist/types/wallets/smart/index.d.ts +2 -0
  111. package/dist/types/wallets/smart/index.d.ts.map +1 -1
  112. package/dist/types/wallets/smart/lib/bundler.d.ts +30 -1
  113. package/dist/types/wallets/smart/lib/bundler.d.ts.map +1 -1
  114. package/dist/types/wallets/smart/lib/calls.d.ts.map +1 -1
  115. package/dist/types/wallets/smart/lib/userop.d.ts +10 -0
  116. package/dist/types/wallets/smart/lib/userop.d.ts.map +1 -1
  117. package/package.json +33 -33
  118. package/src/adapters/ethers5.ts +5 -1
  119. package/src/adapters/viem-legacy.test.ts +1 -1
  120. package/src/chains/constants.ts +17 -2
  121. package/src/chains/types.ts +3 -0
  122. package/src/contract/actions/resolve-abi.test.ts +3 -3
  123. package/src/contract/actions/resolve-abi.ts +27 -25
  124. package/src/exports/extensions/erc721.ts +1 -0
  125. package/src/exports/wallets/smart.ts +1 -0
  126. package/src/extensions/erc1155/customDrop1155.test.ts +3 -14
  127. package/src/extensions/erc1155/drop1155.test.ts +3 -14
  128. package/src/extensions/erc1155/token1155.test.ts +16 -109
  129. package/src/extensions/erc20/read/getCurrencyMetadata.test.ts +1 -1
  130. package/src/extensions/erc721/customDrop721.test.ts +3 -13
  131. package/src/extensions/erc721/drop721.test.ts +3 -13
  132. package/src/extensions/erc721/read/getNFT.ts +37 -7
  133. package/src/extensions/erc721/read/getNFTs.test.ts +1 -1
  134. package/src/extensions/erc721/read/getNFTs.ts +7 -0
  135. package/src/extensions/erc721/read/getOwnedTokenIds.test.ts +1 -1
  136. package/src/extensions/lens/read/resolveAddress.test.ts +1 -1
  137. package/src/extensions/prebuilts/deploy-vote.test.ts +1 -1
  138. package/src/extensions/unstoppable-domains/read/resolveAddress.test.ts +1 -1
  139. package/src/extensions/unstoppable-domains/read/resolveName.test.ts +1 -1
  140. package/src/gas/fee-data.ts +32 -19
  141. package/src/pay/convert/cryptoToFiat.test.ts +4 -4
  142. package/src/pay/convert/fiatToCrypto.test.ts +4 -4
  143. package/src/react/core/hooks/wallets/useConnect.test.tsx +3 -3
  144. package/src/react/web/ui/prebuilt/Account/balance.test.tsx +7 -13
  145. package/src/react/web/ui/prebuilt/Chain/icon.test.tsx +1 -1
  146. package/src/react/web/ui/prebuilt/NFT/description.test.tsx +1 -1
  147. package/src/react/web/ui/prebuilt/NFT/media.test.tsx +1 -1
  148. package/src/react/web/ui/prebuilt/NFT/name.test.tsx +1 -1
  149. package/src/react/web/ui/prebuilt/NFT/utils.test.ts +1 -1
  150. package/src/react/web/ui/prebuilt/Token/name.test.tsx +1 -1
  151. package/src/react/web/ui/prebuilt/Token/symbol.test.tsx +1 -1
  152. package/src/react/web/ui/prebuilt/Wallet/icon.test.tsx +1 -1
  153. package/src/react/web/ui/prebuilt/Wallet/name.test.tsx +1 -1
  154. package/src/react/web/ui/prebuilt/thirdweb/ClaimButton/ClaimButton.test.tsx +1 -1
  155. package/src/storage/download.test.ts +1 -1
  156. package/src/storage/download.ts +17 -0
  157. package/src/storage/mock.ts +52 -0
  158. package/src/storage/upload/web-node.test.ts +2 -1
  159. package/src/storage/upload/web-node.ts +8 -1
  160. package/src/transaction/actions/encode.test.ts +1 -1
  161. package/src/transaction/actions/estimate-gas-cost.ts +1 -1
  162. package/src/transaction/actions/to-serializable-transaction.ts +46 -35
  163. package/src/transaction/prepare-transaction.ts +11 -0
  164. package/src/utils/nft/fetch-token-metadata.test.ts +1 -1
  165. package/src/utils/process.ts +4 -0
  166. package/src/version.ts +1 -1
  167. package/src/wallets/manager/index.ts +6 -2
  168. package/src/wallets/smart/index.ts +1 -1
  169. package/src/wallets/smart/lib/bundler.ts +95 -0
  170. package/src/wallets/smart/lib/calls.ts +18 -9
  171. package/src/wallets/smart/lib/userop.ts +53 -18
  172. package/src/wallets/smart/smart-wallet-integration-v07.test.ts +23 -16
  173. package/src/wallets/smart/smart-wallet-integration.test.ts +21 -1
  174. package/src/wallets/smart/smart-wallet-modular.test.ts +1 -1
@@ -53,7 +53,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("Pay: fiatToCrypto", () => {
53
53
  });
54
54
 
55
55
  it("should throw error for testnet chain (because testnets are not supported", async () => {
56
- await expect(() =>
56
+ await expect(
57
57
  convertFiatToCrypto({
58
58
  chain: sepolia,
59
59
  to: NATIVE_TOKEN_ADDRESS,
@@ -67,7 +67,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("Pay: fiatToCrypto", () => {
67
67
  });
68
68
 
69
69
  it("should throw error if `to` is set to an invalid EVM address", async () => {
70
- await expect(() =>
70
+ await expect(
71
71
  convertFiatToCrypto({
72
72
  chain: ethereum,
73
73
  to: "haha",
@@ -81,7 +81,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("Pay: fiatToCrypto", () => {
81
81
  });
82
82
 
83
83
  it("should throw error if `to` is set to a wallet address", async () => {
84
- await expect(() =>
84
+ await expect(
85
85
  convertFiatToCrypto({
86
86
  chain: base,
87
87
  to: TEST_ACCOUNT_A.address,
@@ -100,7 +100,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("Pay: fiatToCrypto", () => {
100
100
  status: 400,
101
101
  statusText: "Bad Request",
102
102
  });
103
- await expect(() =>
103
+ await expect(
104
104
  convertFiatToCrypto({
105
105
  chain: ethereum,
106
106
  to: NATIVE_TOKEN_ADDRESS,
@@ -48,7 +48,7 @@ describe("useAddConnectedWallet", () => {
48
48
  },
49
49
  );
50
50
  const { result } = renderHook(() => useConnect(), { wrapper });
51
- expect(statusResult.current).toEqual("disconnected");
51
+ expect(statusResult.current).toEqual("unknown");
52
52
  await result.current.connect(async () => wallet);
53
53
  expect(statusResult.current).toEqual("connected");
54
54
 
@@ -67,7 +67,7 @@ describe("useAddConnectedWallet", () => {
67
67
  },
68
68
  );
69
69
  const { result } = renderHook(() => useConnect(), { wrapper });
70
- expect(statusResult.current).toEqual("disconnected");
70
+ expect(statusResult.current).toEqual("unknown");
71
71
  await result.current.connect(async () => wallet);
72
72
  expect(statusResult.current).toEqual("connected");
73
73
 
@@ -85,7 +85,7 @@ describe("useAddConnectedWallet", () => {
85
85
  wrapper,
86
86
  },
87
87
  );
88
- expect(statusResult.current).toEqual("disconnected");
88
+ expect(statusResult.current).toEqual("unknown");
89
89
  const { result } = renderHook(() => useConnect(), { wrapper });
90
90
  await result.current.connect(async () => {
91
91
  throw new Error("test");
@@ -72,14 +72,8 @@ describe.runIf(process.env.TW_SECRET_KEY)("AccountBalance component", () => {
72
72
  expect(result.symbol).toBe("$");
73
73
  });
74
74
 
75
- it("`loadAccountBalance` should throw if `chain` is not passed", async () => {
76
- await expect(() =>
77
- loadAccountBalance({ client: TEST_CLIENT, address: VITALIK_WALLET }),
78
- ).rejects.toThrowError("chain is required");
79
- });
80
-
81
75
  it("`loadAccountBalance` should throw if `tokenAddress` is mistakenly passed as native token", async () => {
82
- await expect(() =>
76
+ await expect(
83
77
  loadAccountBalance({
84
78
  client: TEST_CLIENT,
85
79
  address: VITALIK_WALLET,
@@ -92,7 +86,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("AccountBalance component", () => {
92
86
  });
93
87
 
94
88
  it("`loadAccountBalance` should throw if `address` is not a valid evm address", async () => {
95
- await expect(() =>
89
+ await expect(
96
90
  loadAccountBalance({
97
91
  client: TEST_CLIENT,
98
92
  // biome-ignore lint/suspicious/noExplicitAny: for the test
@@ -103,7 +97,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("AccountBalance component", () => {
103
97
  });
104
98
 
105
99
  it("`loadAccountBalance` should throw if `tokenAddress` is passed but is not a valid evm address", async () => {
106
- await expect(() =>
100
+ await expect(
107
101
  loadAccountBalance({
108
102
  client: TEST_CLIENT,
109
103
  address: VITALIK_WALLET,
@@ -133,7 +127,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("AccountBalance component", () => {
133
127
  });
134
128
 
135
129
  it("`loadAccountBalance` should throw if failed to load tokenBalance (native token)", async () => {
136
- await expect(() =>
130
+ await expect(
137
131
  loadAccountBalance({
138
132
  client: TEST_CLIENT,
139
133
  address: VITALIK_WALLET,
@@ -145,7 +139,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("AccountBalance component", () => {
145
139
  });
146
140
 
147
141
  it("`loadAccountBalance` should throw if failed to load tokenBalance (erc20 token)", async () => {
148
- await expect(() =>
142
+ await expect(
149
143
  loadAccountBalance({
150
144
  client: TEST_CLIENT,
151
145
  address: VITALIK_WALLET,
@@ -158,7 +152,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("AccountBalance component", () => {
158
152
  });
159
153
 
160
154
  it("if fetching fiat value then it should throw if failed to resolve (native token)", async () => {
161
- await expect(() =>
155
+ await expect(
162
156
  loadAccountBalance({
163
157
  client: TEST_CLIENT,
164
158
  address: VITALIK_WALLET,
@@ -171,7 +165,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("AccountBalance component", () => {
171
165
  });
172
166
 
173
167
  it("if fetching fiat value then it should throw if failed to resolve (erc20 token)", async () => {
174
- await expect(() =>
168
+ await expect(
175
169
  loadAccountBalance({
176
170
  client: TEST_CLIENT,
177
171
  address: VITALIK_WALLET,
@@ -76,7 +76,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("ChainIcon", () => {
76
76
  });
77
77
 
78
78
  it("fetchChainIcon should throw error if failed to resolve chain icon", async () => {
79
- await expect(() =>
79
+ await expect(
80
80
  fetchChainIcon({ chain: defineChain(-1), client }),
81
81
  ).rejects.toThrowError("Failed to resolve icon for chain");
82
82
  });
@@ -53,7 +53,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("NFTDescription", () => {
53
53
  });
54
54
 
55
55
  it("fetchNftDescription should throw error if failed to resolve nft info", async () => {
56
- await expect(() =>
56
+ await expect(
57
57
  fetchNftDescription({
58
58
  contract: UNISWAPV3_FACTORY_CONTRACT,
59
59
  tokenId: 0n,
@@ -70,7 +70,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("NFTMedia", () => {
70
70
  });
71
71
 
72
72
  it("fetchNftMedia should throw error if failed to resolve nft info", async () => {
73
- await expect(() =>
73
+ await expect(
74
74
  fetchNftMedia({
75
75
  contract: UNISWAPV3_FACTORY_CONTRACT,
76
76
  tokenId: 0n,
@@ -54,7 +54,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("NFTName", () => {
54
54
  });
55
55
 
56
56
  it("fetchNftName should throw error if failed to resolve nft info", async () => {
57
- await expect(() =>
57
+ await expect(
58
58
  fetchNftName({
59
59
  contract: UNISWAPV3_FACTORY_CONTRACT,
60
60
  tokenId: 0n,
@@ -86,7 +86,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("getNFTInfo", () => {
86
86
  });
87
87
 
88
88
  it("should throw error if failed to load nft info", async () => {
89
- await expect(() =>
89
+ await expect(
90
90
  getNFTInfo({ contract: UNISWAPV3_FACTORY_CONTRACT, tokenId: 0n }),
91
91
  ).rejects.toThrowError("Failed to load NFT metadata");
92
92
  });
@@ -73,7 +73,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("TokenName component", () => {
73
73
  });
74
74
 
75
75
  it("fetchTokenName should throw in the end where all fallback solutions failed to resolve to any name", async () => {
76
- await expect(() =>
76
+ await expect(
77
77
  fetchTokenName({
78
78
  address: UNISWAPV3_FACTORY_CONTRACT.address,
79
79
  client,
@@ -73,7 +73,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("TokenSymbol component", () => {
73
73
  });
74
74
 
75
75
  it("fetchTokenSymbol should throw in the end where all fallback solutions failed to resolve to any symbol", async () => {
76
- await expect(() =>
76
+ await expect(
77
77
  fetchTokenSymbol({
78
78
  address: UNISWAPV3_FACTORY_CONTRACT.address,
79
79
  client,
@@ -11,7 +11,7 @@ describe("WalletIcon", () => {
11
11
  });
12
12
 
13
13
  it("should throw error if WalletId is not supported", async () => {
14
- await expect(() =>
14
+ await expect(
15
15
  // @ts-ignore For test
16
16
  fetchWalletImage({ id: "__undefined__" }),
17
17
  ).rejects.toThrowError("Wallet with id __undefined__ not found");
@@ -16,7 +16,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("WalletName", () => {
16
16
 
17
17
  it("fetchWalletName should throw error if failed to get name", async () => {
18
18
  // @ts-ignore for test
19
- await expect(() => fetchWalletName({ id: "test___" })).rejects.toThrowError(
19
+ await expect(fetchWalletName({ id: "test___" })).rejects.toThrowError(
20
20
  "Wallet with id test___ not found",
21
21
  );
22
22
  });
@@ -113,7 +113,7 @@ describe.runIf(process.env.TW_SECRET_KEY)("ClaimButton", () => {
113
113
  },
114
114
  });
115
115
  const contract = getContract({ address, chain, client });
116
- await expect(() =>
116
+ await expect(
117
117
  getERC20ClaimTo({
118
118
  contract,
119
119
  account,
@@ -7,7 +7,7 @@ import { download } from "./download.js";
7
7
 
8
8
  const server = setupServer(...storageHandlers);
9
9
 
10
- describe("download", () => {
10
+ describe.skip("download", () => {
11
11
  beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
12
12
  afterAll(() => server.close());
13
13
  afterEach(() => server.resetHandlers());
@@ -1,6 +1,8 @@
1
1
  import { getClientFetch } from "../utils/fetch.js";
2
2
  import { type ResolveSchemeOptions, resolveScheme } from "../utils/ipfs.js";
3
+ import { IS_TEST } from "../utils/process.js";
3
4
  import type { Prettify } from "../utils/type-utils.js";
5
+ import { getFromMockStorage } from "./mock.js";
4
6
 
5
7
  export type DownloadOptions = Prettify<
6
8
  ResolveSchemeOptions & {
@@ -64,6 +66,21 @@ export type DownloadOptions = Prettify<
64
66
  * @storage
65
67
  */
66
68
  export async function download(options: DownloadOptions) {
69
+ if (IS_TEST) {
70
+ const hash = options.uri.split("://")[1];
71
+ if (!hash) {
72
+ throw new Error("Invalid hash");
73
+ }
74
+ const data = getFromMockStorage(hash);
75
+ if (data) {
76
+ return {
77
+ ok: true,
78
+ status: 200,
79
+ json: () => Promise.resolve(data),
80
+ } as Response;
81
+ }
82
+ }
83
+
67
84
  let url: string;
68
85
  if (options.uri.startsWith("ar://")) {
69
86
  const { resolveArweaveScheme } = await import("../utils/arweave.js");
@@ -0,0 +1,52 @@
1
+ import { randomBytesHex } from "../utils/random.js";
2
+
3
+ const mockStorage = new Map<string, unknown>();
4
+
5
+ /**
6
+ * Extracts file contents from FormData and stores it as JSON
7
+ * @returns The storage key with filename if present
8
+ */
9
+ export async function addToMockStorage(value: FormData): Promise<string[]> {
10
+ const key = randomBytesHex();
11
+
12
+ // Get the first file from FormData
13
+ const files = value.getAll("file") as File[];
14
+ if (!files) {
15
+ throw new Error("No file found in FormData");
16
+ }
17
+
18
+ // Read file contents
19
+ return Promise.all(
20
+ files.map(async (file) => {
21
+ const text = await file.text();
22
+ let data: unknown;
23
+
24
+ try {
25
+ // Parse the contents as JSON
26
+ data = JSON.parse(text);
27
+ } catch {
28
+ throw new Error("File contents must be valid JSON");
29
+ }
30
+
31
+ // If file has a name, return key/filename format
32
+ const filename =
33
+ "name" in file && file.name ? file.name.replace("files/", "") : "";
34
+
35
+ // console.log("mockStorage upload", key, data, filename);
36
+
37
+ const hash = `${key}${filename ? `/${filename}` : ""}`;
38
+ mockStorage.set(hash, data);
39
+ return `ipfs://${hash}`;
40
+ }),
41
+ );
42
+ }
43
+
44
+ /**
45
+ * Retrieves parsed JSON data from storage
46
+ * @returns The parsed data object or undefined if not found
47
+ */
48
+ export function getFromMockStorage(key: string): unknown {
49
+ const data = mockStorage.get(key);
50
+ // console.log("mockStorage get", key, data);
51
+ return data;
52
+ }
@@ -8,7 +8,8 @@ import { uploadBatch } from "./web-node.js";
8
8
 
9
9
  const server = setupServer(...storageHandlers);
10
10
 
11
- describe("uploadBatch", () => {
11
+ // skip this test for now, will need to be manually run
12
+ describe.skip("uploadBatch", () => {
12
13
  beforeAll(() => server.listen({ onUnhandledRequest: "error" }));
13
14
  afterAll(() => server.close());
14
15
  afterEach(() => server.resetHandlers());
@@ -1,6 +1,8 @@
1
1
  import type { ThirdwebClient } from "../../client/client.js";
2
2
  import { getThirdwebDomains } from "../../utils/domains.js";
3
3
  import { getClientFetch } from "../../utils/fetch.js";
4
+ import { IS_TEST } from "../../utils/process.js";
5
+ import { addToMockStorage } from "../mock.js";
4
6
  import type { UploadOptions, UploadableFile } from "./types.js";
5
7
 
6
8
  export async function uploadBatch<const TFiles extends UploadableFile[]>(
@@ -9,6 +11,10 @@ export async function uploadBatch<const TFiles extends UploadableFile[]>(
9
11
  fileNames: string[],
10
12
  options?: UploadOptions<TFiles>,
11
13
  ) {
14
+ if (IS_TEST) {
15
+ return addToMockStorage(form);
16
+ }
17
+
12
18
  const headers: HeadersInit = {};
13
19
 
14
20
  const res = await getClientFetch(client)(
@@ -17,7 +23,8 @@ export async function uploadBatch<const TFiles extends UploadableFile[]>(
17
23
  method: "POST",
18
24
  headers,
19
25
  body: form,
20
- requestTimeoutMs: client.config?.storage?.fetch?.requestTimeoutMs,
26
+ requestTimeoutMs:
27
+ client.config?.storage?.fetch?.requestTimeoutMs || 120000,
21
28
  },
22
29
  );
23
30
 
@@ -203,7 +203,7 @@ describe("transaction: encode", () => {
203
203
  // @ts-ignore Intentionally for the test purpose
204
204
  extraCallData: "I'm a cat",
205
205
  });
206
- await expect(() => getExtraCallDataFromTx(tx)).rejects.toThrowError(
206
+ await expect(getExtraCallDataFromTx(tx)).rejects.toThrowError(
207
207
  "Invalid extra calldata - must be a hex string",
208
208
  );
209
209
  });
@@ -44,7 +44,7 @@ export async function estimateGasCost(
44
44
  );
45
45
  }
46
46
  let l1Fee: bigint;
47
- if (isOpStackChain(transaction.chain)) {
47
+ if (await isOpStackChain(transaction.chain)) {
48
48
  const { estimateL1Fee } = await import("../../gas/estimate-l1-fee.js");
49
49
  l1Fee = await estimateL1Fee({
50
50
  transaction,
@@ -75,42 +75,52 @@ export async function toSerializableTransaction(
75
75
  const rpcRequest = getRpcClient(options.transaction);
76
76
  const chainId = options.transaction.chain.id;
77
77
  const from = options.from;
78
- let [data, nonce, gas, feeData, to, accessList, value, authorizationList] =
79
- await Promise.all([
80
- encode(options.transaction),
81
- (async () => {
82
- // if the user has specified a nonce, use that
83
- const resolvedNonce = await resolvePromisedValue(
84
- options.transaction.nonce,
85
- );
86
- if (resolvedNonce !== undefined) {
87
- return resolvedNonce;
88
- }
78
+ let [
79
+ data,
80
+ nonce,
81
+ gas,
82
+ feeData,
83
+ to,
84
+ accessList,
85
+ value,
86
+ authorizationList,
87
+ type,
88
+ ] = await Promise.all([
89
+ encode(options.transaction),
90
+ (async () => {
91
+ // if the user has specified a nonce, use that
92
+ const resolvedNonce = await resolvePromisedValue(
93
+ options.transaction.nonce,
94
+ );
95
+ if (resolvedNonce !== undefined) {
96
+ return resolvedNonce;
97
+ }
89
98
 
90
- return from // otherwise get the next nonce (import the method to do so)
91
- ? await import("../../rpc/actions/eth_getTransactionCount.js").then(
92
- ({ eth_getTransactionCount }) =>
93
- eth_getTransactionCount(rpcRequest, {
94
- address:
95
- typeof from === "string"
96
- ? getAddress(from)
97
- : getAddress(from.address),
98
- blockTag: "pending",
99
- }),
100
- )
101
- : undefined;
102
- })(),
103
- // takes the same options as the sendTransaction function thankfully!
104
- estimateGas({
105
- ...options,
106
- from: options.from,
107
- }),
108
- getGasOverridesForTransaction(options.transaction),
109
- resolvePromisedValue(options.transaction.to),
110
- resolvePromisedValue(options.transaction.accessList),
111
- resolvePromisedValue(options.transaction.value),
112
- resolvePromisedValue(options.transaction.authorizationList),
113
- ]);
99
+ return from // otherwise get the next nonce (import the method to do so)
100
+ ? await import("../../rpc/actions/eth_getTransactionCount.js").then(
101
+ ({ eth_getTransactionCount }) =>
102
+ eth_getTransactionCount(rpcRequest, {
103
+ address:
104
+ typeof from === "string"
105
+ ? getAddress(from)
106
+ : getAddress(from.address),
107
+ blockTag: "pending",
108
+ }),
109
+ )
110
+ : undefined;
111
+ })(),
112
+ // takes the same options as the sendTransaction function thankfully!
113
+ estimateGas({
114
+ ...options,
115
+ from: options.from,
116
+ }),
117
+ getGasOverridesForTransaction(options.transaction),
118
+ resolvePromisedValue(options.transaction.to),
119
+ resolvePromisedValue(options.transaction.accessList),
120
+ resolvePromisedValue(options.transaction.value),
121
+ resolvePromisedValue(options.transaction.authorizationList),
122
+ resolvePromisedValue(options.transaction.type),
123
+ ]);
114
124
 
115
125
  const extraGas = await resolvePromisedValue(options.transaction.extraGas);
116
126
  if (extraGas) {
@@ -126,6 +136,7 @@ export async function toSerializableTransaction(
126
136
  accessList,
127
137
  value,
128
138
  authorizationList,
139
+ type,
129
140
  ...feeData,
130
141
  } satisfies SerializableTransaction;
131
142
  }
@@ -17,6 +17,7 @@ export type StaticPrepareTransactionOptions = {
17
17
  maxFeePerGas?: bigint | undefined;
18
18
  maxPriorityFeePerGas?: bigint | undefined;
19
19
  maxFeePerBlobGas?: bigint | undefined;
20
+ type?: undefined | TransactionType;
20
21
  nonce?: number | undefined;
21
22
  extraGas?: bigint | undefined;
22
23
  // eip7702
@@ -34,6 +35,16 @@ export type StaticPrepareTransactionOptions = {
34
35
  };
35
36
  };
36
37
 
38
+ type TransactionType = "legacy" | "eip1559" | "eip2930" | "eip4844" | "eip7702";
39
+
40
+ export const TransactionTypeMap: Record<TransactionType, number> = {
41
+ legacy: 0,
42
+ eip1559: 1,
43
+ eip2930: 2,
44
+ eip4844: 3,
45
+ eip7702: 4,
46
+ };
47
+
37
48
  export type EIP712TransactionOptions = {
38
49
  // constant or user input
39
50
  gasPerPubdata?: bigint | undefined;
@@ -32,6 +32,6 @@ describe("fetchTokenMetadata", () => {
32
32
  tokenId: 0n,
33
33
  tokenUri: invalidBase64Json,
34
34
  };
35
- await expect(() => fetchTokenMetadata(options)).rejects.toThrowError();
35
+ await expect(fetchTokenMetadata(options)).rejects.toThrowError();
36
36
  });
37
37
  });
@@ -1,3 +1,7 @@
1
1
  export const IS_DEV =
2
2
  // biome-ignore lint/nursery/noProcessEnv: ok in this file
3
3
  process.env.NODE_ENV === "development" || process.env.NODE_ENV === "test";
4
+
5
+ export const IS_TEST =
6
+ // biome-ignore lint/nursery/noProcessEnv: ok in this file
7
+ process.env.NODE_ENV === "test";
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "5.89.0";
1
+ export const version = "5.90.0";
@@ -15,7 +15,11 @@ import type { SmartWalletOptions } from "../smart/types.js";
15
15
  import type { WalletId } from "../wallet-types.js";
16
16
 
17
17
  type WalletIdToConnectedWalletMap = Map<string, Wallet>;
18
- export type ConnectionStatus = "connected" | "disconnected" | "connecting";
18
+ export type ConnectionStatus =
19
+ | "connected"
20
+ | "disconnected"
21
+ | "connecting"
22
+ | "unknown";
19
23
 
20
24
  const CONNECTED_WALLET_IDS = "thirdweb:connected-wallet-ids";
21
25
  const LAST_ACTIVE_EOA_ID = "thirdweb:active-wallet-id";
@@ -47,7 +51,7 @@ export function createConnectionManager(storage: AsyncStorage) {
47
51
  const activeAccountStore = createStore<Account | undefined>(undefined);
48
52
  const activeWalletChainStore = createStore<Chain | undefined>(undefined);
49
53
  const activeWalletConnectionStatusStore =
50
- createStore<ConnectionStatus>("disconnected");
54
+ createStore<ConnectionStatus>("unknown");
51
55
 
52
56
  const definedChainsStore = createStore<Map<number, Chain>>(new Map());
53
57
 
@@ -556,7 +556,7 @@ async function _sendUserOp(args: {
556
556
  }
557
557
  }
558
558
 
559
- async function getEntrypointFromFactory(
559
+ export async function getEntrypointFromFactory(
560
560
  factoryAddress: string,
561
561
  client: ThirdwebClient,
562
562
  chain: Chain,