thirdweb 5.52.0-nightly-3a32b11a80cb28f22575219ab8f80e703793ec10-20240906000338 → 5.53.0-nightly-7dd2869e240522a467c73f0017f080ee118c5bf0-20240908000435

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 (151) hide show
  1. package/dist/cjs/exports/react.js +4 -1
  2. package/dist/cjs/exports/react.js.map +1 -1
  3. package/dist/cjs/exports/social.js +6 -0
  4. package/dist/cjs/exports/social.js.map +1 -0
  5. package/dist/cjs/exports/wallets/smart.js +2 -1
  6. package/dist/cjs/exports/wallets/smart.js.map +1 -1
  7. package/dist/cjs/react/core/hooks/transaction/useSendTransaction.js.map +1 -1
  8. package/dist/cjs/react/core/providers/thirdweb-provider.js +2 -0
  9. package/dist/cjs/react/core/providers/thirdweb-provider.js.map +1 -1
  10. package/dist/cjs/react/core/social/useSocialProfiles.js +37 -0
  11. package/dist/cjs/react/core/social/useSocialProfiles.js.map +1 -0
  12. package/dist/cjs/react/core/utils/structuralSharing.js +54 -0
  13. package/dist/cjs/react/core/utils/structuralSharing.js.map +1 -0
  14. package/dist/cjs/react/core/utils/wallet.js +24 -0
  15. package/dist/cjs/react/core/utils/wallet.js.map +1 -1
  16. package/dist/cjs/react/native/ui/components/WalletImage.js +3 -3
  17. package/dist/cjs/react/native/ui/components/WalletImage.js.map +1 -1
  18. package/dist/cjs/react/native/ui/connect/ConnectedButton.js +3 -3
  19. package/dist/cjs/react/native/ui/connect/ConnectedButton.js.map +1 -1
  20. package/dist/cjs/react/native/ui/connect/ConnectedModal.js +2 -2
  21. package/dist/cjs/react/native/ui/connect/ConnectedModal.js.map +1 -1
  22. package/dist/cjs/react/web/ui/ConnectWallet/ConnectButton.js +0 -3
  23. package/dist/cjs/react/web/ui/ConnectWallet/ConnectButton.js.map +1 -1
  24. package/dist/cjs/react/web/ui/ConnectWallet/Details.js +9 -6
  25. package/dist/cjs/react/web/ui/ConnectWallet/Details.js.map +1 -1
  26. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +4 -1
  27. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
  28. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js +2 -1
  29. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js.map +1 -1
  30. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/useSwapSupportedChains.js +4 -4
  31. package/dist/cjs/react/web/ui/ConnectWallet/screens/Buy/swap/useSwapSupportedChains.js.map +1 -1
  32. package/dist/cjs/social/profiles.js +38 -0
  33. package/dist/cjs/social/profiles.js.map +1 -0
  34. package/dist/cjs/social/types.js +3 -0
  35. package/dist/cjs/social/types.js.map +1 -0
  36. package/dist/cjs/utils/domains.js +3 -0
  37. package/dist/cjs/utils/domains.js.map +1 -1
  38. package/dist/cjs/utils/function-id.js +3 -5
  39. package/dist/cjs/utils/function-id.js.map +1 -1
  40. package/dist/cjs/utils/ipfs.js +19 -10
  41. package/dist/cjs/utils/ipfs.js.map +1 -1
  42. package/dist/cjs/version.js +1 -1
  43. package/dist/cjs/wallets/smart/lib/userop.js +80 -1
  44. package/dist/cjs/wallets/smart/lib/userop.js.map +1 -1
  45. package/dist/esm/exports/react.js +2 -0
  46. package/dist/esm/exports/react.js.map +1 -1
  47. package/dist/esm/exports/social.js +3 -0
  48. package/dist/esm/exports/social.js.map +1 -0
  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/react/core/hooks/transaction/useSendTransaction.js.map +1 -1
  52. package/dist/esm/react/core/providers/thirdweb-provider.js +2 -0
  53. package/dist/esm/react/core/providers/thirdweb-provider.js.map +1 -1
  54. package/dist/esm/react/core/social/useSocialProfiles.js +34 -0
  55. package/dist/esm/react/core/social/useSocialProfiles.js.map +1 -0
  56. package/dist/esm/react/core/utils/structuralSharing.js +50 -0
  57. package/dist/esm/react/core/utils/structuralSharing.js.map +1 -0
  58. package/dist/esm/react/core/utils/wallet.js +24 -0
  59. package/dist/esm/react/core/utils/wallet.js.map +1 -1
  60. package/dist/esm/react/native/ui/components/WalletImage.js +3 -3
  61. package/dist/esm/react/native/ui/components/WalletImage.js.map +1 -1
  62. package/dist/esm/react/native/ui/connect/ConnectedButton.js +3 -3
  63. package/dist/esm/react/native/ui/connect/ConnectedButton.js.map +1 -1
  64. package/dist/esm/react/native/ui/connect/ConnectedModal.js +2 -2
  65. package/dist/esm/react/native/ui/connect/ConnectedModal.js.map +1 -1
  66. package/dist/esm/react/web/ui/ConnectWallet/ConnectButton.js +0 -3
  67. package/dist/esm/react/web/ui/ConnectWallet/ConnectButton.js.map +1 -1
  68. package/dist/esm/react/web/ui/ConnectWallet/Details.js +9 -6
  69. package/dist/esm/react/web/ui/ConnectWallet/Details.js.map +1 -1
  70. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js +4 -1
  71. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.js.map +1 -1
  72. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js +2 -1
  73. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.js.map +1 -1
  74. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/useSwapSupportedChains.js +4 -4
  75. package/dist/esm/react/web/ui/ConnectWallet/screens/Buy/swap/useSwapSupportedChains.js.map +1 -1
  76. package/dist/esm/social/profiles.js +35 -0
  77. package/dist/esm/social/profiles.js.map +1 -0
  78. package/dist/esm/social/types.js +2 -0
  79. package/dist/esm/social/types.js.map +1 -0
  80. package/dist/esm/utils/domains.js +3 -0
  81. package/dist/esm/utils/domains.js.map +1 -1
  82. package/dist/esm/utils/function-id.js +3 -5
  83. package/dist/esm/utils/function-id.js.map +1 -1
  84. package/dist/esm/utils/ipfs.js +19 -10
  85. package/dist/esm/utils/ipfs.js.map +1 -1
  86. package/dist/esm/version.js +1 -1
  87. package/dist/esm/wallets/smart/lib/userop.js +81 -3
  88. package/dist/esm/wallets/smart/lib/userop.js.map +1 -1
  89. package/dist/types/exports/react.d.ts +1 -0
  90. package/dist/types/exports/react.d.ts.map +1 -1
  91. package/dist/types/exports/social.d.ts +3 -0
  92. package/dist/types/exports/social.d.ts.map +1 -0
  93. package/dist/types/exports/wallets/smart.d.ts +1 -1
  94. package/dist/types/exports/wallets/smart.d.ts.map +1 -1
  95. package/dist/types/react/core/hooks/connection/ConnectButtonProps.d.ts +1 -0
  96. package/dist/types/react/core/hooks/connection/ConnectButtonProps.d.ts.map +1 -1
  97. package/dist/types/react/core/hooks/transaction/useSendTransaction.d.ts +3 -1
  98. package/dist/types/react/core/hooks/transaction/useSendTransaction.d.ts.map +1 -1
  99. package/dist/types/react/core/providers/thirdweb-provider.d.ts.map +1 -1
  100. package/dist/types/react/core/social/useSocialProfiles.d.ts +23 -0
  101. package/dist/types/react/core/social/useSocialProfiles.d.ts.map +1 -0
  102. package/dist/types/react/core/utils/structuralSharing.d.ts +4 -0
  103. package/dist/types/react/core/utils/structuralSharing.d.ts.map +1 -0
  104. package/dist/types/react/core/utils/wallet.d.ts +3 -0
  105. package/dist/types/react/core/utils/wallet.d.ts.map +1 -1
  106. package/dist/types/react/native/ui/components/WalletImage.d.ts +1 -1
  107. package/dist/types/react/native/ui/components/WalletImage.d.ts.map +1 -1
  108. package/dist/types/react/native/ui/connect/ConnectedButton.d.ts.map +1 -1
  109. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts +18 -3
  110. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts.map +1 -1
  111. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.d.ts.map +1 -1
  112. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.d.ts.map +1 -1
  113. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/useSwapSupportedChains.d.ts +2 -2
  114. package/dist/types/react/web/ui/ConnectWallet/screens/Buy/swap/useSwapSupportedChains.d.ts.map +1 -1
  115. package/dist/types/social/profiles.d.ts +24 -0
  116. package/dist/types/social/profiles.d.ts.map +1 -0
  117. package/dist/types/social/types.d.ts +41 -0
  118. package/dist/types/social/types.d.ts.map +1 -0
  119. package/dist/types/utils/domains.d.ts +6 -0
  120. package/dist/types/utils/domains.d.ts.map +1 -1
  121. package/dist/types/utils/function-id.d.ts.map +1 -1
  122. package/dist/types/utils/ipfs.d.ts.map +1 -1
  123. package/dist/types/version.d.ts +1 -1
  124. package/dist/types/wallets/smart/lib/userop.d.ts +25 -1
  125. package/dist/types/wallets/smart/lib/userop.d.ts.map +1 -1
  126. package/package.json +1 -1
  127. package/src/exports/react.ts +3 -0
  128. package/src/exports/social.ts +2 -0
  129. package/src/exports/wallets/smart.ts +1 -0
  130. package/src/react/core/hooks/connection/ConnectButtonProps.ts +1 -0
  131. package/src/react/core/hooks/transaction/useSendTransaction.ts +5 -1
  132. package/src/react/core/providers/thirdweb-provider.tsx +2 -0
  133. package/src/react/core/social/useSocialProfiles.ts +40 -0
  134. package/src/react/core/utils/structuralSharing.ts +53 -0
  135. package/src/react/core/utils/wallet.ts +27 -0
  136. package/src/react/native/ui/components/WalletImage.tsx +4 -4
  137. package/src/react/native/ui/connect/ConnectedButton.tsx +8 -14
  138. package/src/react/native/ui/connect/ConnectedModal.tsx +8 -14
  139. package/src/react/web/ui/ConnectWallet/ConnectButton.tsx +0 -3
  140. package/src/react/web/ui/ConnectWallet/Details.tsx +40 -23
  141. package/src/react/web/ui/ConnectWallet/screens/Buy/BuyScreen.tsx +7 -1
  142. package/src/react/web/ui/ConnectWallet/screens/Buy/main/useUISelectionStates.ts +2 -1
  143. package/src/react/web/ui/ConnectWallet/screens/Buy/swap/useSwapSupportedChains.ts +9 -3
  144. package/src/social/profiles.ts +46 -0
  145. package/src/social/types.ts +43 -0
  146. package/src/utils/domains.ts +8 -0
  147. package/src/utils/function-id.ts +3 -5
  148. package/src/utils/ipfs.test.ts +57 -1
  149. package/src/utils/ipfs.ts +22 -14
  150. package/src/version.ts +1 -1
  151. package/src/wallets/smart/lib/userop.ts +98 -2
@@ -0,0 +1,46 @@
1
+ import type { ThirdwebClient } from "../client/client.js";
2
+ import { getThirdwebBaseUrl } from "../utils/domains.js";
3
+ import { getClientFetch } from "../utils/fetch.js";
4
+ import type { SocialProfiles } from "./types.js";
5
+
6
+ /**
7
+ * Fetches the wallet's available social profiles.
8
+ * @param args - The arguments to use when fetching the social profiles.
9
+ * @param args.address - The wallet address to fetch the social profiles for.
10
+ * @param args.client - The Thirdweb client.
11
+ * @returns A promise resolving to the retrieved social profiles for different protocols. If a profile is not available for a protocol, the value will be `null`.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import { getProfiles } from "thirdweb/social";
16
+ * const profiles = await getProfiles({
17
+ * address: "0x...",
18
+ * client,
19
+ * });
20
+ * ```
21
+ * @beta
22
+ */
23
+ export async function getSocialProfiles(args: {
24
+ address: string;
25
+ client: ThirdwebClient;
26
+ }): Promise<SocialProfiles> {
27
+ const { address, client } = args;
28
+
29
+ const clientFetch = getClientFetch(client);
30
+ const response = await clientFetch(
31
+ `${getThirdwebBaseUrl("social")}/v1/profiles/${address}`,
32
+ );
33
+
34
+ if (response.status !== 200) {
35
+ try {
36
+ const errorBody = await response.json();
37
+ throw new Error(`Failed to fetch profile: ${errorBody.message}`);
38
+ } catch {
39
+ throw new Error(
40
+ `Failed to fetch profile: ${response.status}\n${await response.text()}`,
41
+ );
42
+ }
43
+ }
44
+
45
+ return (await response.json()).data as SocialProfiles;
46
+ }
@@ -0,0 +1,43 @@
1
+ export type FarcasterProfile = {
2
+ fid?: number;
3
+ bio?: string;
4
+ pfp?: string;
5
+ display?: string;
6
+ username?: string;
7
+ custodyAddress?: string;
8
+ addresses?: string[];
9
+ };
10
+
11
+ export type LensProfile = {
12
+ name?: string;
13
+ bio?: string;
14
+ picture?: string;
15
+ coverPicture?: string;
16
+ };
17
+
18
+ export type EnsProfile = {
19
+ name?: string;
20
+ address?: string;
21
+ avatar?: string;
22
+ display?: string;
23
+ description?: string;
24
+ keywords?: string[];
25
+ email?: string;
26
+ mail?: string;
27
+ notice?: string;
28
+ location?: string;
29
+ phone?: string;
30
+ url?: string;
31
+ twitter?: string;
32
+ github?: string;
33
+ discord?: string;
34
+ telegram?: string;
35
+ };
36
+
37
+ export type SocialProfiles = {
38
+ type: "farcaster" | "lens" | "ens";
39
+ name?: string;
40
+ avatar?: string;
41
+ bio?: string;
42
+ metadata?: FarcasterProfile | LensProfile | EnsProfile;
43
+ }[];
@@ -4,6 +4,11 @@ type DomainOverrides = {
4
4
  * @default "rpc.thirdweb.com"
5
5
  */
6
6
  rpc?: string;
7
+ /**
8
+ * The base URL for the social service.
9
+ * @default "social.thirdweb.com"
10
+ */
11
+ social?: string;
7
12
  /**
8
13
  * The base URL for the in-app wallet service
9
14
  * @default "embedded-wallet.thirdweb.com"
@@ -28,6 +33,7 @@ type DomainOverrides = {
28
33
 
29
34
  export const DEFAULT_RPC_URL = "rpc.thirdweb.com";
30
35
  const DEFAULT_IN_APP_WALLET_URL = "embedded-wallet.thirdweb.com";
36
+ const DEFAULT_SOCIAL_URL = "social.thirdweb.com";
31
37
  const DEFAULT_PAY_URL = "pay.thirdweb.com";
32
38
  const DEFAULT_STORAGE_URL = "storage.thirdweb.com";
33
39
  const DEFAULT_BUNDLER_URL = "bundler.thirdweb.com";
@@ -35,6 +41,7 @@ const DEFAULT_BUNDLER_URL = "bundler.thirdweb.com";
35
41
  let domains: { [k in keyof DomainOverrides]-?: string } = {
36
42
  rpc: DEFAULT_RPC_URL,
37
43
  inAppWallet: DEFAULT_IN_APP_WALLET_URL,
44
+ social: DEFAULT_SOCIAL_URL,
38
45
  pay: DEFAULT_PAY_URL,
39
46
  storage: DEFAULT_STORAGE_URL,
40
47
  bundler: DEFAULT_BUNDLER_URL,
@@ -47,6 +54,7 @@ export const setThirdwebDomains = (DomainOverrides: DomainOverrides) => {
47
54
  domains = {
48
55
  rpc: DomainOverrides.rpc ?? DEFAULT_RPC_URL,
49
56
  inAppWallet: DomainOverrides.inAppWallet ?? DEFAULT_IN_APP_WALLET_URL,
57
+ social: DomainOverrides.social ?? DEFAULT_SOCIAL_URL,
50
58
  pay: DomainOverrides.pay ?? DEFAULT_PAY_URL,
51
59
  storage: DomainOverrides.storage ?? DEFAULT_STORAGE_URL,
52
60
  bundler: DomainOverrides.bundler ?? DEFAULT_BUNDLER_URL,
@@ -1,11 +1,9 @@
1
- import { sha256 } from "@noble/hashes/sha256";
2
- import { uint8ArrayToHex } from "./encoding/hex.js";
1
+ import { randomBytesHex } from "./random.js";
3
2
 
4
3
  // biome-ignore lint/suspicious/noExplicitAny: the whoel point here is to accept anything
5
4
  type AnyFunction = (...args: any[]) => any;
6
5
 
7
- // WeakMap should be fine, if we de-reference the function, it should be garbage collected
8
- const functionIdCache = new WeakMap<AnyFunction, string>();
6
+ const functionIdCache = new Map<AnyFunction, string>();
9
7
 
10
8
  /**
11
9
  * Retrieves the unique identifier for a given function.
@@ -20,7 +18,7 @@ export function getFunctionId(fn: AnyFunction) {
20
18
  // biome-ignore lint/style/noNonNullAssertion: the `has` above ensures that this will always be set
21
19
  return functionIdCache.get(fn)!;
22
20
  }
23
- const id = uint8ArrayToHex(sha256(fn.toString()));
21
+ const id = randomBytesHex();
24
22
  functionIdCache.set(fn, id);
25
23
  return id;
26
24
  }
@@ -1,6 +1,10 @@
1
1
  import { describe, expect, it } from "vitest";
2
2
  import { createThirdwebClient } from "../client/client.js";
3
- import { findIPFSCidFromUri, resolveScheme } from "./ipfs.js";
3
+ import {
4
+ findIPFSCidFromUri,
5
+ getBaseUriFromBatch,
6
+ resolveScheme,
7
+ } from "./ipfs.js";
4
8
 
5
9
  describe("resolveScheme", () => {
6
10
  it("should resolve ipfs scheme when not passing a gateway override", () => {
@@ -70,3 +74,55 @@ describe("resolveScheme", () => {
70
74
  expect(findIPFSCidFromUri(uri)).toBe(cid);
71
75
  });
72
76
  });
77
+
78
+ describe("getBaseUriFromBatch", () => {
79
+ it("should return the base uri", () => {
80
+ const batchOfUris = ["ipfs://Qm.../0", "ipfs://Qm.../1", "ipfs://Qm.../2"];
81
+ const baseUri = getBaseUriFromBatch(batchOfUris);
82
+ expect(baseUri).toMatchInlineSnapshot(`"ipfs://Qm.../"`);
83
+ });
84
+ it("should throw if the batch is empty", () => {
85
+ expect(() => getBaseUriFromBatch([])).toThrowErrorMatchingInlineSnapshot(
86
+ "[Error: Batch of URIs is empty]",
87
+ );
88
+ });
89
+
90
+ it("should throw if an element of the array does not have the same base", () => {
91
+ const batchOfUris = ["ipfs://Qm.../0", "ipfs://Qm.../1", "ipfs://Qm2.../2"];
92
+ expect(() =>
93
+ getBaseUriFromBatch(batchOfUris),
94
+ ).toThrowErrorMatchingInlineSnapshot(
95
+ "[Error: All URIs in the batch must have the same base URI]",
96
+ );
97
+ });
98
+
99
+ it("should work with a custom domain", () => {
100
+ const batchOfUris = [
101
+ "https://example.com/0",
102
+ "https://example.com/1",
103
+ "https://example.com/2",
104
+ ];
105
+ const baseUri = getBaseUriFromBatch(batchOfUris);
106
+ expect(baseUri).toMatchInlineSnapshot(`"https://example.com/"`);
107
+ });
108
+
109
+ it("should work with a custom domain and path", () => {
110
+ const batchOfUris = [
111
+ "https://example.com/path/0",
112
+ "https://example.com/path/1",
113
+ "https://example.com/path/2",
114
+ ];
115
+ const baseUri = getBaseUriFromBatch(batchOfUris);
116
+ expect(baseUri).toMatchInlineSnapshot(`"https://example.com/path/"`);
117
+ });
118
+
119
+ it("should work with a custom domain and path with trailing slash", () => {
120
+ const batchOfUris = [
121
+ "https://example.com/path/0/",
122
+ "https://example.com/path/1/",
123
+ "https://example.com/path/2/",
124
+ ];
125
+ const baseUri = getBaseUriFromBatch(batchOfUris);
126
+ expect(baseUri).toMatchInlineSnapshot(`"https://example.com/path/"`);
127
+ });
128
+ });
package/src/utils/ipfs.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import type { ThirdwebClient } from "../client/client.js";
2
-
3
2
  import type { FileOrBufferOrString } from "../storage/upload/types.js";
4
3
 
5
4
  export type ResolveSchemeOptions = {
@@ -109,23 +108,32 @@ export async function uploadOrExtractURIs<
109
108
  * @internal
110
109
  */
111
110
  export function getBaseUriFromBatch(uris: string[]): string {
112
- const urisWithSlashes = uris.map((uri) => new URL(uri));
113
- const baseUri = urisWithSlashes[0];
114
- for (let i = 0; i < urisWithSlashes.length; i++) {
115
- const uri = urisWithSlashes[i];
116
- if (baseUri?.host !== uri?.host) {
117
- throw new Error(
118
- `Can only create batches with the same base URI for every entry in the batch. Expected '${baseUri}' but got '${uri}'`,
119
- );
111
+ const [base, ...rest] = uris.map((uri) => {
112
+ // remove query parameters
113
+ // biome-ignore lint/style/noParameterAssign: lemme do my stuff
114
+ [uri] = uri.split("?") as [string];
115
+ // remove fragments
116
+ // biome-ignore lint/style/noParameterAssign: lemme do my stuff
117
+ [uri] = uri.split("#") as [string];
118
+
119
+ // if the URI ends with a `/`, remove it
120
+ if (uri.endsWith("/")) {
121
+ // biome-ignore lint/style/noParameterAssign: lemme do my stuff
122
+ uri = uri.slice(0, -1);
120
123
  }
121
- }
122
124
 
123
- if (!baseUri) {
124
- throw new Error("No base URI found in the batch");
125
+ // remove the last part of the URI & add the trailing `/`
126
+ return `${uri.split("/").slice(0, -1).join("/")}/`;
127
+ });
128
+
129
+ if (!base) {
130
+ throw new Error("Batch of URIs is empty");
125
131
  }
126
132
 
127
- // Ensure that baseUri ends with trailing slash
128
- return `${baseUri.protocol}//${baseUri.host}/`;
133
+ if (rest.some((uri) => uri !== base)) {
134
+ throw new Error("All URIs in the batch must have the same base URI");
135
+ }
136
+ return base;
129
137
  }
130
138
 
131
139
  function isUriList<T extends FileOrBufferOrString | Record<string, unknown>>(
package/src/version.ts CHANGED
@@ -1 +1 @@
1
- export const version = "5.52.0-nightly-3a32b11a80cb28f22575219ab8f80e703793ec10-20240906000338";
1
+ export const version = "5.53.0-nightly-7dd2869e240522a467c73f0017f080ee118c5bf0-20240908000435";
@@ -10,6 +10,7 @@ import { getUserOpHash as getUserOpHashV06 } from "../../../extensions/erc4337/_
10
10
  import { getUserOpHash as getUserOpHashV07 } from "../../../extensions/erc4337/__generated__/IEntryPoint_v07/read/getUserOpHash.js";
11
11
  import { getDefaultGasOverrides } from "../../../gas/fee-data.js";
12
12
  import { encode } from "../../../transaction/actions/encode.js";
13
+ import { toSerializableTransaction } from "../../../transaction/actions/to-serializable-transaction.js";
13
14
  import type { PreparedTransaction } from "../../../transaction/prepare-transaction.js";
14
15
  import type { TransactionReceipt } from "../../../transaction/types.js";
15
16
  import { isContractDeployed } from "../../../utils/bytecode/is-contract-deployed.js";
@@ -30,11 +31,17 @@ import {
30
31
  getUserOpGasFees,
31
32
  getUserOpReceipt,
32
33
  } from "./bundler.js";
33
- import { prepareCreateAccount } from "./calls.js";
34
+ import {
35
+ predictAddress,
36
+ prepareBatchExecute,
37
+ prepareCreateAccount,
38
+ prepareExecute,
39
+ } from "./calls.js";
34
40
  import {
35
41
  DUMMY_SIGNATURE,
36
42
  ENTRYPOINT_ADDRESS_v0_6,
37
43
  ENTRYPOINT_ADDRESS_v0_7,
44
+ getDefaultAccountFactory,
38
45
  getDefaultBundlerUrl,
39
46
  getEntryPointVersion,
40
47
  } from "./constants.js";
@@ -486,9 +493,10 @@ async function populateUserOp_v0_6(args: {
486
493
  * ```ts
487
494
  * import { signUserOp } from "thirdweb/wallets/smart";
488
495
  *
489
- * const userOp = createUnsignedUserOp(...);
496
+ * const userOp = await createUnsignedUserOp(...);
490
497
  *
491
498
  * const signedUserOp = await signUserOp({
499
+ * client,
492
500
  * userOp,
493
501
  * chain,
494
502
  * adminAccount,
@@ -592,3 +600,91 @@ async function getAccountNonce(options: {
592
600
  sender: accountContract.address,
593
601
  });
594
602
  }
603
+
604
+ /**
605
+ * Create and sign a user operation.
606
+ * @param options - The options for creating and signing the user operation
607
+ * @returns - The signed user operation
608
+ * @example
609
+ * ```ts
610
+ * import { createAndSignUserOp } from "thirdweb/wallets/smart";
611
+ *
612
+ * const userOp = await createAndSignUserOp({
613
+ * client,
614
+ * adminAccount,
615
+ * smartWalletOptions,
616
+ * transactions,
617
+ * });
618
+ * ```
619
+ * @walletUtils
620
+ */
621
+ export async function createAndSignUserOp(options: {
622
+ transactions: PreparedTransaction[];
623
+ adminAccount: Account;
624
+ client: ThirdwebClient;
625
+ smartWalletOptions: SmartWalletOptions;
626
+ }) {
627
+ const config = options.smartWalletOptions;
628
+ const factoryContract = getContract({
629
+ address:
630
+ config.factoryAddress ||
631
+ getDefaultAccountFactory(config.overrides?.entrypointAddress),
632
+ chain: config.chain,
633
+ client: options.client,
634
+ });
635
+ const accountAddress = await predictAddress({
636
+ factoryContract,
637
+ adminAddress: options.adminAccount.address,
638
+ predictAddressOverride: config.overrides?.predictAddress,
639
+ accountSalt: config.overrides?.accountSalt,
640
+ accountAddress: config.overrides?.accountAddress,
641
+ });
642
+ const accountContract = getContract({
643
+ address: accountAddress,
644
+ chain: config.chain,
645
+ client: options.client,
646
+ });
647
+
648
+ let executeTx: PreparedTransaction;
649
+ if (options.transactions.length === 1) {
650
+ const tx = options.transactions[0] as PreparedTransaction;
651
+ const serializedTx = await toSerializableTransaction({
652
+ transaction: tx,
653
+ });
654
+ executeTx = prepareExecute({
655
+ accountContract,
656
+ transaction: serializedTx,
657
+ executeOverride: config.overrides?.execute,
658
+ });
659
+ } else {
660
+ const serializedTxs = await Promise.all(
661
+ options.transactions.map((tx) =>
662
+ toSerializableTransaction({
663
+ transaction: tx,
664
+ }),
665
+ ),
666
+ );
667
+ executeTx = prepareBatchExecute({
668
+ accountContract,
669
+ transactions: serializedTxs,
670
+ executeBatchOverride: config.overrides?.executeBatch,
671
+ });
672
+ }
673
+
674
+ const unsignedUserOp = await createUnsignedUserOp({
675
+ transaction: executeTx,
676
+ factoryContract,
677
+ accountContract,
678
+ adminAddress: options.adminAccount.address,
679
+ sponsorGas: "sponsorGas" in config ? config.sponsorGas : config.gasless,
680
+ overrides: config.overrides,
681
+ });
682
+ const signedUserOp = await signUserOp({
683
+ client: options.client,
684
+ chain: config.chain,
685
+ adminAccount: options.adminAccount,
686
+ entrypointAddress: config.overrides?.entrypointAddress,
687
+ userOp: unsignedUserOp,
688
+ });
689
+ return signedUserOp;
690
+ }