thirdweb 5.57.3 → 5.58.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 (176) hide show
  1. package/dist/cjs/exports/extensions/erc1155.js +3 -2
  2. package/dist/cjs/exports/extensions/erc1155.js.map +1 -1
  3. package/dist/cjs/react/core/utils/walletIcon.js +5 -1
  4. package/dist/cjs/react/core/utils/walletIcon.js.map +1 -1
  5. package/dist/cjs/react/native/ui/connect/InAppWalletUI.js +1 -0
  6. package/dist/cjs/react/native/ui/connect/InAppWalletUI.js.map +1 -1
  7. package/dist/cjs/react/native/ui/icons/svgs.js +12 -1
  8. package/dist/cjs/react/native/ui/icons/svgs.js.map +1 -1
  9. package/dist/cjs/react/web/ui/ConnectWallet/Details.js +27 -2
  10. package/dist/cjs/react/web/ui/ConnectWallet/Details.js.map +1 -1
  11. package/dist/cjs/react/web/wallets/shared/ConnectWalletSocialOptions.js +42 -21
  12. package/dist/cjs/react/web/wallets/shared/ConnectWalletSocialOptions.js.map +1 -1
  13. package/dist/cjs/react/web/wallets/shared/oauthSignIn.js +2 -1
  14. package/dist/cjs/react/web/wallets/shared/oauthSignIn.js.map +1 -1
  15. package/dist/cjs/utils/fetch.js +10 -4
  16. package/dist/cjs/utils/fetch.js.map +1 -1
  17. package/dist/cjs/version.js +1 -1
  18. package/dist/cjs/wallets/in-app/core/authentication/types.js +2 -0
  19. package/dist/cjs/wallets/in-app/core/authentication/types.js.map +1 -1
  20. package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js +2 -2
  21. package/dist/cjs/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
  22. package/dist/cjs/wallets/in-app/native/native-connector.js +1 -0
  23. package/dist/cjs/wallets/in-app/native/native-connector.js.map +1 -1
  24. package/dist/cjs/wallets/in-app/web/in-app.js +1 -0
  25. package/dist/cjs/wallets/in-app/web/in-app.js.map +1 -1
  26. package/dist/cjs/wallets/in-app/web/lib/actions/generate-wallet.enclave.js +26 -0
  27. package/dist/cjs/wallets/in-app/web/lib/actions/generate-wallet.enclave.js.map +1 -0
  28. package/dist/cjs/wallets/in-app/web/lib/actions/get-enclave-user-status.js +31 -0
  29. package/dist/cjs/wallets/in-app/web/lib/actions/get-enclave-user-status.js.map +1 -0
  30. package/dist/cjs/wallets/in-app/web/lib/actions/sign-message.enclave.js +30 -0
  31. package/dist/cjs/wallets/in-app/web/lib/actions/sign-message.enclave.js.map +1 -0
  32. package/dist/cjs/wallets/in-app/web/lib/actions/sign-transaction.enclave.js +28 -0
  33. package/dist/cjs/wallets/in-app/web/lib/actions/sign-transaction.enclave.js.map +1 -0
  34. package/dist/cjs/wallets/in-app/web/lib/actions/sign-typed-data.enclave.js +27 -0
  35. package/dist/cjs/wallets/in-app/web/lib/actions/sign-typed-data.enclave.js.map +1 -0
  36. package/dist/cjs/wallets/in-app/web/lib/auth/iframe-auth.js +42 -5
  37. package/dist/cjs/wallets/in-app/web/lib/auth/iframe-auth.js.map +1 -1
  38. package/dist/cjs/wallets/in-app/web/lib/auth/index.js +2 -2
  39. package/dist/cjs/wallets/in-app/web/lib/auth/index.js.map +1 -1
  40. package/dist/cjs/wallets/in-app/web/lib/enclave-wallet.js +195 -0
  41. package/dist/cjs/wallets/in-app/web/lib/enclave-wallet.js.map +1 -0
  42. package/dist/cjs/wallets/in-app/web/lib/get-auth-token.js +14 -0
  43. package/dist/cjs/wallets/in-app/web/lib/get-auth-token.js.map +1 -0
  44. package/dist/cjs/wallets/in-app/web/lib/{in-app-account.js → iframe-wallet.js} +8 -22
  45. package/dist/cjs/wallets/in-app/web/lib/iframe-wallet.js.map +1 -0
  46. package/dist/cjs/wallets/in-app/web/lib/web-connector.js +111 -37
  47. package/dist/cjs/wallets/in-app/web/lib/web-connector.js.map +1 -1
  48. package/dist/cjs/wallets/in-app/web/lib/web-wallet.js +3 -0
  49. package/dist/cjs/wallets/in-app/web/lib/web-wallet.js.map +1 -0
  50. package/dist/cjs/wallets/types.js +1 -0
  51. package/dist/cjs/wallets/types.js.map +1 -1
  52. package/dist/esm/exports/extensions/erc1155.js +1 -1
  53. package/dist/esm/exports/extensions/erc1155.js.map +1 -1
  54. package/dist/esm/react/core/utils/walletIcon.js +4 -0
  55. package/dist/esm/react/core/utils/walletIcon.js.map +1 -1
  56. package/dist/esm/react/native/ui/connect/InAppWalletUI.js +2 -1
  57. package/dist/esm/react/native/ui/connect/InAppWalletUI.js.map +1 -1
  58. package/dist/esm/react/native/ui/icons/svgs.js +11 -0
  59. package/dist/esm/react/native/ui/icons/svgs.js.map +1 -1
  60. package/dist/esm/react/web/ui/ConnectWallet/Details.js +27 -2
  61. package/dist/esm/react/web/ui/ConnectWallet/Details.js.map +1 -1
  62. package/dist/esm/react/web/wallets/shared/ConnectWalletSocialOptions.js +42 -21
  63. package/dist/esm/react/web/wallets/shared/ConnectWalletSocialOptions.js.map +1 -1
  64. package/dist/esm/react/web/wallets/shared/oauthSignIn.js +2 -1
  65. package/dist/esm/react/web/wallets/shared/oauthSignIn.js.map +1 -1
  66. package/dist/esm/utils/fetch.js +10 -4
  67. package/dist/esm/utils/fetch.js.map +1 -1
  68. package/dist/esm/version.js +1 -1
  69. package/dist/esm/wallets/in-app/core/authentication/types.js +2 -0
  70. package/dist/esm/wallets/in-app/core/authentication/types.js.map +1 -1
  71. package/dist/esm/wallets/in-app/core/wallet/in-app-core.js +2 -2
  72. package/dist/esm/wallets/in-app/core/wallet/in-app-core.js.map +1 -1
  73. package/dist/esm/wallets/in-app/native/native-connector.js +1 -0
  74. package/dist/esm/wallets/in-app/native/native-connector.js.map +1 -1
  75. package/dist/esm/wallets/in-app/web/in-app.js +1 -0
  76. package/dist/esm/wallets/in-app/web/in-app.js.map +1 -1
  77. package/dist/esm/wallets/in-app/web/lib/actions/generate-wallet.enclave.js +23 -0
  78. package/dist/esm/wallets/in-app/web/lib/actions/generate-wallet.enclave.js.map +1 -0
  79. package/dist/esm/wallets/in-app/web/lib/actions/get-enclave-user-status.js +28 -0
  80. package/dist/esm/wallets/in-app/web/lib/actions/get-enclave-user-status.js.map +1 -0
  81. package/dist/esm/wallets/in-app/web/lib/actions/sign-message.enclave.js +27 -0
  82. package/dist/esm/wallets/in-app/web/lib/actions/sign-message.enclave.js.map +1 -0
  83. package/dist/esm/wallets/in-app/web/lib/actions/sign-transaction.enclave.js +25 -0
  84. package/dist/esm/wallets/in-app/web/lib/actions/sign-transaction.enclave.js.map +1 -0
  85. package/dist/esm/wallets/in-app/web/lib/actions/sign-typed-data.enclave.js +24 -0
  86. package/dist/esm/wallets/in-app/web/lib/actions/sign-typed-data.enclave.js.map +1 -0
  87. package/dist/esm/wallets/in-app/web/lib/auth/iframe-auth.js +42 -5
  88. package/dist/esm/wallets/in-app/web/lib/auth/iframe-auth.js.map +1 -1
  89. package/dist/esm/wallets/in-app/web/lib/auth/index.js +2 -2
  90. package/dist/esm/wallets/in-app/web/lib/auth/index.js.map +1 -1
  91. package/dist/esm/wallets/in-app/web/lib/enclave-wallet.js +191 -0
  92. package/dist/esm/wallets/in-app/web/lib/enclave-wallet.js.map +1 -0
  93. package/dist/esm/wallets/in-app/web/lib/get-auth-token.js +11 -0
  94. package/dist/esm/wallets/in-app/web/lib/get-auth-token.js.map +1 -0
  95. package/dist/esm/wallets/in-app/web/lib/{in-app-account.js → iframe-wallet.js} +8 -22
  96. package/dist/esm/wallets/in-app/web/lib/iframe-wallet.js.map +1 -0
  97. package/dist/esm/wallets/in-app/web/lib/web-connector.js +111 -37
  98. package/dist/esm/wallets/in-app/web/lib/web-connector.js.map +1 -1
  99. package/dist/esm/wallets/in-app/web/lib/web-wallet.js +2 -0
  100. package/dist/esm/wallets/in-app/web/lib/web-wallet.js.map +1 -0
  101. package/dist/esm/wallets/types.js +1 -0
  102. package/dist/esm/wallets/types.js.map +1 -1
  103. package/dist/types/exports/extensions/erc1155.d.ts +1 -1
  104. package/dist/types/exports/extensions/erc1155.d.ts.map +1 -1
  105. package/dist/types/react/core/utils/walletIcon.d.ts +3 -1
  106. package/dist/types/react/core/utils/walletIcon.d.ts.map +1 -1
  107. package/dist/types/react/native/ui/connect/InAppWalletUI.d.ts.map +1 -1
  108. package/dist/types/react/native/ui/icons/svgs.d.ts +1 -0
  109. package/dist/types/react/native/ui/icons/svgs.d.ts.map +1 -1
  110. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts +1 -1
  111. package/dist/types/react/web/ui/ConnectWallet/Details.d.ts.map +1 -1
  112. package/dist/types/react/web/wallets/shared/ConnectWalletSocialOptions.d.ts.map +1 -1
  113. package/dist/types/react/web/wallets/shared/oauthSignIn.d.ts.map +1 -1
  114. package/dist/types/utils/fetch.d.ts.map +1 -1
  115. package/dist/types/version.d.ts +1 -1
  116. package/dist/types/wallets/in-app/core/authentication/types.d.ts +6 -2
  117. package/dist/types/wallets/in-app/core/authentication/types.d.ts.map +1 -1
  118. package/dist/types/wallets/in-app/core/wallet/in-app-core.d.ts.map +1 -1
  119. package/dist/types/wallets/in-app/native/native-connector.d.ts.map +1 -1
  120. package/dist/types/wallets/in-app/web/in-app.d.ts +1 -0
  121. package/dist/types/wallets/in-app/web/in-app.d.ts.map +1 -1
  122. package/dist/types/wallets/in-app/web/lib/actions/generate-wallet.enclave.d.ts +15 -0
  123. package/dist/types/wallets/in-app/web/lib/actions/generate-wallet.enclave.d.ts.map +1 -0
  124. package/dist/types/wallets/in-app/web/lib/actions/get-enclave-user-status.d.ts +14 -0
  125. package/dist/types/wallets/in-app/web/lib/actions/get-enclave-user-status.d.ts.map +1 -0
  126. package/dist/types/wallets/in-app/web/lib/actions/sign-message.enclave.d.ts +17 -0
  127. package/dist/types/wallets/in-app/web/lib/actions/sign-message.enclave.d.ts.map +1 -0
  128. package/dist/types/wallets/in-app/web/lib/actions/sign-transaction.enclave.d.ts +9 -0
  129. package/dist/types/wallets/in-app/web/lib/actions/sign-transaction.enclave.d.ts.map +1 -0
  130. package/dist/types/wallets/in-app/web/lib/actions/sign-typed-data.enclave.d.ts +16 -0
  131. package/dist/types/wallets/in-app/web/lib/actions/sign-typed-data.enclave.d.ts.map +1 -0
  132. package/dist/types/wallets/in-app/web/lib/auth/iframe-auth.d.ts +5 -1
  133. package/dist/types/wallets/in-app/web/lib/auth/iframe-auth.d.ts.map +1 -1
  134. package/dist/types/wallets/in-app/web/lib/enclave-wallet.d.ts +61 -0
  135. package/dist/types/wallets/in-app/web/lib/enclave-wallet.d.ts.map +1 -0
  136. package/dist/types/wallets/in-app/web/lib/get-auth-token.d.ts +4 -0
  137. package/dist/types/wallets/in-app/web/lib/get-auth-token.d.ts.map +1 -0
  138. package/dist/types/wallets/in-app/web/lib/{in-app-account.d.ts → iframe-wallet.d.ts} +5 -8
  139. package/dist/types/wallets/in-app/web/lib/iframe-wallet.d.ts.map +1 -0
  140. package/dist/types/wallets/in-app/web/lib/web-connector.d.ts +4 -2
  141. package/dist/types/wallets/in-app/web/lib/web-connector.d.ts.map +1 -1
  142. package/dist/types/wallets/in-app/web/lib/web-wallet.d.ts +15 -0
  143. package/dist/types/wallets/in-app/web/lib/web-wallet.d.ts.map +1 -0
  144. package/dist/types/wallets/types.d.ts +2 -2
  145. package/dist/types/wallets/types.d.ts.map +1 -1
  146. package/package.json +1 -1
  147. package/src/exports/extensions/erc1155.ts +1 -0
  148. package/src/extensions/prebuilts/deploy-published.test.ts +34 -1
  149. package/src/react/core/utils/walletIcon.ts +5 -0
  150. package/src/react/native/ui/connect/InAppWalletUI.tsx +2 -0
  151. package/src/react/native/ui/icons/svgs.ts +12 -0
  152. package/src/react/web/ui/ConnectWallet/Details.tsx +44 -4
  153. package/src/react/web/wallets/shared/ConnectWalletSocialOptions.tsx +82 -48
  154. package/src/react/web/wallets/shared/oauthSignIn.ts +2 -1
  155. package/src/utils/fetch.ts +11 -4
  156. package/src/version.ts +1 -1
  157. package/src/wallets/in-app/core/authentication/types.ts +6 -1
  158. package/src/wallets/in-app/core/wallet/in-app-core.ts +2 -5
  159. package/src/wallets/in-app/native/native-connector.ts +1 -0
  160. package/src/wallets/in-app/web/in-app.ts +1 -0
  161. package/src/wallets/in-app/web/lib/actions/generate-wallet.enclave.ts +44 -0
  162. package/src/wallets/in-app/web/lib/actions/get-enclave-user-status.ts +44 -0
  163. package/src/wallets/in-app/web/lib/actions/sign-message.enclave.ts +52 -0
  164. package/src/wallets/in-app/web/lib/actions/sign-transaction.enclave.ts +48 -0
  165. package/src/wallets/in-app/web/lib/actions/sign-typed-data.enclave.ts +51 -0
  166. package/src/wallets/in-app/web/lib/auth/iframe-auth.ts +45 -6
  167. package/src/wallets/in-app/web/lib/auth/index.ts +2 -2
  168. package/src/wallets/in-app/web/lib/enclave-wallet.ts +245 -0
  169. package/src/wallets/in-app/web/lib/get-auth-token.ts +17 -0
  170. package/src/wallets/in-app/web/lib/{in-app-account.ts → iframe-wallet.ts} +14 -36
  171. package/src/wallets/in-app/web/lib/web-connector.ts +125 -39
  172. package/src/wallets/in-app/web/lib/web-wallet.ts +23 -0
  173. package/src/wallets/types.ts +1 -0
  174. package/dist/cjs/wallets/in-app/web/lib/in-app-account.js.map +0 -1
  175. package/dist/esm/wallets/in-app/web/lib/in-app-account.js.map +0 -1
  176. package/dist/types/wallets/in-app/web/lib/in-app-account.d.ts.map +0 -1
@@ -17,10 +17,7 @@ import type {
17
17
  } from "../authentication/types.js";
18
18
  import type { InAppConnector } from "../interfaces/connector.js";
19
19
 
20
- const connectorCache = new WeakMap<
21
- { client: ThirdwebClient; ecosystem?: Ecosystem },
22
- InAppConnector
23
- >();
20
+ const connectorCache = new Map<string, InAppConnector>();
24
21
 
25
22
  /**
26
23
  * @internal
@@ -30,7 +27,7 @@ export async function getOrCreateInAppWalletConnector(
30
27
  connectorFactory: (client: ThirdwebClient) => Promise<InAppConnector>,
31
28
  ecosystem?: Ecosystem,
32
29
  ) {
33
- const key = { client, ecosystem };
30
+ const key = JSON.stringify({ clientId: client.clientId, ecosystem });
34
31
  if (connectorCache.has(key)) {
35
32
  return connectorCache.get(key) as InAppConnector;
36
33
  }
@@ -158,6 +158,7 @@ export class InAppNativeConnector implements InAppConnector {
158
158
  case "x":
159
159
  case "farcaster":
160
160
  case "telegram":
161
+ case "coinbase":
161
162
  case "apple": {
162
163
  const ExpoLinking = require("expo-linking");
163
164
  const redirectUrl =
@@ -15,6 +15,7 @@ import { createInAppWallet } from "../core/wallet/in-app-core.js";
15
15
  * - Apple
16
16
  * - Facebook
17
17
  * - Discord
18
+ * - Coinbase
18
19
  * - Telegram
19
20
  * - LINE
20
21
  * - X
@@ -0,0 +1,44 @@
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 { Ecosystem } from "../../types.js";
5
+
6
+ /**
7
+ * Generate a new enclave wallet using an auth token
8
+ * @internal
9
+ */
10
+ export async function generateWallet({
11
+ authToken,
12
+ client,
13
+ ecosystem,
14
+ }: {
15
+ client: ThirdwebClient;
16
+ ecosystem: Ecosystem;
17
+ authToken: string;
18
+ }) {
19
+ const clientFetch = getClientFetch(client, ecosystem);
20
+ const response = await clientFetch(
21
+ `${getThirdwebBaseUrl("inAppWallet")}/api/v1/enclave-wallet/generate`,
22
+ {
23
+ method: "POST",
24
+ headers: {
25
+ "Content-Type": "application/json",
26
+ "x-thirdweb-client-id": client.clientId,
27
+ Authorization: `Bearer embedded-wallet-token:${authToken}`,
28
+ },
29
+ },
30
+ );
31
+
32
+ if (!response.ok) {
33
+ throw new Error("Failed to generate wallet");
34
+ }
35
+
36
+ const { wallet } = (await response.json()) as {
37
+ wallet: {
38
+ address: string;
39
+ type: "enclave";
40
+ };
41
+ };
42
+
43
+ return wallet;
44
+ }
@@ -0,0 +1,44 @@
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 { UserStatus } from "../../lib/enclave-wallet.js";
5
+ import type { Ecosystem } from "../../types.js";
6
+
7
+ /**
8
+ * Gets the user's status from the backend.
9
+ *
10
+ * @internal
11
+ */
12
+ export async function getUserStatus({
13
+ authToken,
14
+ client,
15
+ ecosystem,
16
+ }: {
17
+ authToken: string;
18
+ client: ThirdwebClient;
19
+ ecosystem?: Ecosystem;
20
+ }): Promise<UserStatus | undefined> {
21
+ const clientFetch = getClientFetch(client, ecosystem);
22
+ const response = await clientFetch(
23
+ `${getThirdwebBaseUrl("inAppWallet")}/api/2024-05-05/accounts`,
24
+ {
25
+ method: "GET",
26
+ headers: {
27
+ "Content-Type": "application/json",
28
+ "x-thirdweb-client-id": client.clientId,
29
+ Authorization: `Bearer embedded-wallet-token:${authToken}`,
30
+ },
31
+ },
32
+ );
33
+
34
+ if (!response.ok) {
35
+ if (response.status === 401) {
36
+ // 401 response indicates there is no user logged in, so we return undefined
37
+ return undefined;
38
+ }
39
+ const result = await response.json();
40
+ throw new Error(`Failed to get user status: ${result.error}`);
41
+ }
42
+
43
+ return (await response.json()) as UserStatus;
44
+ }
@@ -0,0 +1,52 @@
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 { Ecosystem } from "../../types.js";
5
+ import { getAuthToken } from "../get-auth-token.js";
6
+
7
+ export async function signMessage({
8
+ client,
9
+ ecosystem,
10
+ payload: { message, isRaw },
11
+ }: {
12
+ client: ThirdwebClient;
13
+ ecosystem?: Ecosystem;
14
+ payload: {
15
+ message: string;
16
+ isRaw: boolean;
17
+ };
18
+ }) {
19
+ const clientFetch = getClientFetch(client, ecosystem);
20
+ const authToken = await getAuthToken(client, ecosystem);
21
+
22
+ const response = await clientFetch(
23
+ `${getThirdwebBaseUrl("inAppWallet")}/api/v1/enclave-wallet/sign-message`,
24
+ {
25
+ method: "POST",
26
+ headers: {
27
+ "Content-Type": "application/json",
28
+ "x-thirdweb-client-id": client.clientId,
29
+ Authorization: `Bearer embedded-wallet-token:${authToken}`,
30
+ },
31
+ body: JSON.stringify({
32
+ messagePayload: {
33
+ message,
34
+ isRaw,
35
+ },
36
+ }),
37
+ },
38
+ );
39
+
40
+ if (!response.ok) {
41
+ throw new Error("Failed to sign message");
42
+ }
43
+
44
+ const signedMessage = (await response.json()) as {
45
+ r: string;
46
+ s: string;
47
+ v: number;
48
+ signature: string;
49
+ hash: string;
50
+ };
51
+ return signedMessage;
52
+ }
@@ -0,0 +1,48 @@
1
+ import type { ThirdwebClient } from "../../../../../client/client.js";
2
+ import { getThirdwebBaseUrl } from "../../../../../utils/domains.js";
3
+ import type { Hex } from "../../../../../utils/encoding/hex.js";
4
+ import { getClientFetch } from "../../../../../utils/fetch.js";
5
+ import type { Ecosystem } from "../../types.js";
6
+ import { getAuthToken } from "../get-auth-token.js";
7
+
8
+ export async function signTransaction({
9
+ client,
10
+ ecosystem,
11
+ payload,
12
+ }: {
13
+ client: ThirdwebClient;
14
+ ecosystem?: Ecosystem;
15
+ payload: Record<string, Hex | number | undefined>;
16
+ }) {
17
+ console.log("payload", payload);
18
+ const clientFetch = getClientFetch(client, ecosystem);
19
+ const authToken = await getAuthToken(client, ecosystem);
20
+
21
+ const response = await clientFetch(
22
+ `${getThirdwebBaseUrl("inAppWallet")}/api/v1/enclave-wallet/sign-transaction`,
23
+ {
24
+ method: "POST",
25
+ headers: {
26
+ "Content-Type": "application/json",
27
+ "x-thirdweb-client-id": client.clientId,
28
+ Authorization: `Bearer embedded-wallet-token:${authToken}`,
29
+ },
30
+ body: JSON.stringify({
31
+ transactionPayload: payload,
32
+ }),
33
+ },
34
+ );
35
+
36
+ if (!response.ok) {
37
+ throw new Error("Failed to sign transaction");
38
+ }
39
+
40
+ const signedTransaction = (await response.json()) as {
41
+ r: string;
42
+ s: string;
43
+ v: number;
44
+ signature: string;
45
+ hash: string;
46
+ };
47
+ return signedTransaction.signature as Hex;
48
+ }
@@ -0,0 +1,51 @@
1
+ import type { TypedData } from "abitype";
2
+ import type { TypedDataDefinition } from "viem";
3
+ import type { ThirdwebClient } from "../../../../../client/client.js";
4
+ import { getThirdwebBaseUrl } from "../../../../../utils/domains.js";
5
+ import { getClientFetch } from "../../../../../utils/fetch.js";
6
+ import type { Ecosystem } from "../../types.js";
7
+ import { getAuthToken } from "../get-auth-token.js";
8
+
9
+ export async function signTypedData<
10
+ const typedData extends TypedData | Record<string, unknown>,
11
+ primaryType extends keyof typedData | "EIP712Domain" = keyof typedData,
12
+ >({
13
+ client,
14
+ ecosystem,
15
+ payload,
16
+ }: {
17
+ client: ThirdwebClient;
18
+ ecosystem?: Ecosystem;
19
+ payload: TypedDataDefinition<typedData, primaryType>;
20
+ }) {
21
+ const clientFetch = getClientFetch(client, ecosystem);
22
+ const authToken = await getAuthToken(client, ecosystem);
23
+
24
+ const response = await clientFetch(
25
+ `${getThirdwebBaseUrl("inAppWallet")}/api/v1/enclave-wallet/sign-typed-data`,
26
+ {
27
+ method: "POST",
28
+ headers: {
29
+ "Content-Type": "application/json",
30
+ "x-thirdweb-client-id": client.clientId,
31
+ Authorization: `Bearer embedded-wallet-token:${authToken}`,
32
+ },
33
+ body: JSON.stringify({
34
+ ...payload,
35
+ }),
36
+ },
37
+ );
38
+
39
+ if (!response.ok) {
40
+ throw new Error("Failed to sign typed data");
41
+ }
42
+
43
+ const signedTypedData = (await response.json()) as {
44
+ r: string;
45
+ s: string;
46
+ v: number;
47
+ signature: string;
48
+ hash: string;
49
+ };
50
+ return signedTypedData;
51
+ }
@@ -10,6 +10,8 @@ import type {
10
10
  } from "../../../core/authentication/types.js";
11
11
  import type { ClientIdWithQuerierType, Ecosystem } from "../../types.js";
12
12
  import type { InAppWalletIframeCommunicator } from "../../utils/iFrameCommunication/InAppWalletIframeCommunicator.js";
13
+ import { generateWallet } from "../actions/generate-wallet.enclave.js";
14
+ import { getUserStatus } from "../actions/get-enclave-user-status.js";
13
15
  import { BaseLogin } from "./base-login.js";
14
16
 
15
17
  export type AuthQuerierTypes = {
@@ -20,12 +22,15 @@ export type AuthQuerierTypes = {
20
22
  clientId: string;
21
23
  authCookie: string;
22
24
  walletUserId: string;
23
- deviceShareStored: string;
25
+ deviceShareStored: string | null;
24
26
  };
25
27
  loginWithStoredTokenDetails: {
26
28
  storedToken: AuthStoredTokenWithCookieReturnType["storedToken"];
27
29
  recoveryCode?: string;
28
30
  };
31
+ migrateFromShardToEnclave: {
32
+ storedToken: AuthStoredTokenWithCookieReturnType["storedToken"];
33
+ };
29
34
  };
30
35
 
31
36
  /**
@@ -33,6 +38,7 @@ export type AuthQuerierTypes = {
33
38
  */
34
39
  export class Auth {
35
40
  protected client: ThirdwebClient;
41
+ protected ecosystem?: Ecosystem;
36
42
  protected AuthQuerier: InAppWalletIframeCommunicator<AuthQuerierTypes>;
37
43
  protected localStorage: ClientScopedStorage;
38
44
  protected onAuthSuccess: (
@@ -58,6 +64,7 @@ export class Auth {
58
64
  ) => Promise<AuthLoginReturnType>;
59
65
  }) {
60
66
  this.client = client;
67
+ this.ecosystem = ecosystem;
61
68
 
62
69
  this.AuthQuerier = querier;
63
70
  this.localStorage = new ClientScopedStorage({
@@ -103,6 +110,42 @@ export class Auth {
103
110
  recoveryCode?: string,
104
111
  ): Promise<AuthLoginReturnType> {
105
112
  await this.preLogin();
113
+
114
+ const user = await getUserStatus({
115
+ authToken: authToken.storedToken.cookieString,
116
+ client: this.client,
117
+ ecosystem: this.ecosystem,
118
+ });
119
+ if (!user) {
120
+ throw new Error("Cannot login, no user found for auth token");
121
+ }
122
+
123
+ // If they're already an enclave wallet, proceed to login
124
+ if (user.wallets.length > 0 && user.wallets[0]?.type === "enclave") {
125
+ return this.postLogin({
126
+ storedToken: authToken.storedToken,
127
+ walletDetails: {
128
+ walletAddress: user.wallets[0].address,
129
+ },
130
+ });
131
+ }
132
+
133
+ if (user.wallets.length === 0 && this.ecosystem) {
134
+ // If this is a new ecosystem wallet without an enclave yet, we'll generate an enclave
135
+ const result = await generateWallet({
136
+ authToken: authToken.storedToken.cookieString,
137
+ client: this.client,
138
+ ecosystem: this.ecosystem,
139
+ });
140
+ return this.postLogin({
141
+ storedToken: authToken.storedToken,
142
+ walletDetails: {
143
+ walletAddress: result.address,
144
+ },
145
+ });
146
+ }
147
+
148
+ // If this is an existing sharded wallet or in-app wallet, we'll login with the sharded wallet
106
149
  const result = await this.AuthQuerier.call<AuthAndWalletRpcReturnType>({
107
150
  procedureName: "loginWithStoredTokenDetails",
108
151
  params: {
@@ -280,15 +323,11 @@ export class Auth {
280
323
  * @internal
281
324
  */
282
325
  async logout(): Promise<LogoutReturnType> {
283
- const { success } = await this.AuthQuerier.call<LogoutReturnType>({
284
- procedureName: "logout",
285
- params: undefined,
286
- });
287
326
  const isRemoveAuthCookie = await this.localStorage.removeAuthCookie();
288
327
  const isRemoveUserId = await this.localStorage.removeWalletUserId();
289
328
 
290
329
  return {
291
- success: success || isRemoveAuthCookie || isRemoveUserId,
330
+ success: isRemoveAuthCookie || isRemoveUserId,
292
331
  };
293
332
  }
294
333
  }
@@ -51,8 +51,8 @@ async function getInAppWalletConnector(
51
51
  export async function getAuthenticatedUser(
52
52
  options: GetAuthenticatedUserParams,
53
53
  ) {
54
- const { client } = options;
55
- const connector = await getInAppWalletConnector(client);
54
+ const { client, ecosystem } = options;
55
+ const connector = await getInAppWalletConnector(client, ecosystem);
56
56
  const user = await connector.getUser();
57
57
  switch (user.status) {
58
58
  case UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED: {
@@ -0,0 +1,245 @@
1
+ import { bytesToHex } from "viem";
2
+ import { getCachedChain } from "../../../../chains/utils.js";
3
+ import type { ThirdwebClient } from "../../../../client/client.js";
4
+ import { eth_sendRawTransaction } from "../../../../rpc/actions/eth_sendRawTransaction.js";
5
+ import { getRpcClient } from "../../../../rpc/rpc.js";
6
+ import { getAddress } from "../../../../utils/address.js";
7
+ import { type Hex, toHex } from "../../../../utils/encoding/hex.js";
8
+ import { parseTypedData } from "../../../../utils/signatures/helpers/parseTypedData.js";
9
+ import { webLocalStorage } from "../../../../utils/storage/webStorage.js";
10
+ import type { Prettify } from "../../../../utils/type-utils.js";
11
+ import type {
12
+ Account,
13
+ SendTransactionOption,
14
+ } from "../../../interfaces/wallet.js";
15
+ import { ClientScopedStorage } from "../../core/authentication/client-scoped-storage.js";
16
+ import {
17
+ type GetUser,
18
+ RecoveryShareManagement,
19
+ UserWalletStatus,
20
+ type WalletAddressObjectType,
21
+ } from "../../core/authentication/types.js";
22
+ import type { Ecosystem } from "../types.js";
23
+ import { getUserStatus } from "./actions/get-enclave-user-status.js";
24
+ import { signMessage as signEnclaveMessage } from "./actions/sign-message.enclave.js";
25
+ import { signTransaction as signEnclaveTransaction } from "./actions/sign-transaction.enclave.js";
26
+ import { signTypedData as signEnclaveTypedData } from "./actions/sign-typed-data.enclave.js";
27
+ import type { IWebWallet, PostWalletSetup } from "./web-wallet.js";
28
+
29
+ export type UserStatus = {
30
+ linkedAccounts: {
31
+ type: string;
32
+ details:
33
+ | { email: string; [key: string]: string }
34
+ | { phone: string; [key: string]: string }
35
+ | { address: string; [key: string]: string }
36
+ | { id: string; [key: string]: string };
37
+ }[];
38
+ wallets:
39
+ | [
40
+ {
41
+ address: string;
42
+ createdAt: string;
43
+ type: "sharded" | "enclave";
44
+ },
45
+ ]
46
+ | [];
47
+ id: string;
48
+ };
49
+
50
+ export class EnclaveWallet implements IWebWallet {
51
+ public client: ThirdwebClient;
52
+ public ecosystem?: Ecosystem;
53
+ public address: string;
54
+ protected localStorage: ClientScopedStorage;
55
+
56
+ constructor({
57
+ client,
58
+ ecosystem,
59
+ address,
60
+ }: Prettify<{
61
+ client: ThirdwebClient;
62
+ ecosystem?: Ecosystem;
63
+ address: string;
64
+ }>) {
65
+ this.client = client;
66
+ this.ecosystem = ecosystem;
67
+ this.address = address;
68
+
69
+ this.localStorage = new ClientScopedStorage({
70
+ storage: webLocalStorage,
71
+ clientId: client.clientId,
72
+ ecosystemId: ecosystem?.id,
73
+ });
74
+ }
75
+
76
+ /**
77
+ * Store the auth token for use
78
+ * @returns `{walletAddress: string }` The user's wallet details
79
+ * @internal
80
+ */
81
+ async postWalletSetUp({
82
+ walletAddress,
83
+ authToken,
84
+ }: PostWalletSetup): Promise<WalletAddressObjectType> {
85
+ await this.localStorage.saveAuthCookie(authToken);
86
+ return { walletAddress };
87
+ }
88
+
89
+ /**
90
+ * Gets the current user's details
91
+ * @internal
92
+ */
93
+ async getUserWalletStatus(): Promise<GetUser> {
94
+ const token = await this.localStorage.getAuthCookie();
95
+ if (!token) {
96
+ return { status: UserWalletStatus.LOGGED_OUT };
97
+ }
98
+
99
+ const userStatus = await getUserStatus({
100
+ authToken: token,
101
+ client: this.client,
102
+ ecosystem: this.ecosystem,
103
+ });
104
+
105
+ if (!userStatus) {
106
+ return { status: UserWalletStatus.LOGGED_OUT };
107
+ }
108
+ const wallet = userStatus.wallets[0];
109
+
110
+ const authDetails = {
111
+ email: userStatus.linkedAccounts.find(
112
+ (account) => account.details.email !== undefined,
113
+ )?.details.email,
114
+ phoneNumber: userStatus.linkedAccounts.find(
115
+ (account) => account.details.phone !== undefined,
116
+ )?.details.phone,
117
+ userWalletId: userStatus.id || "",
118
+ recoveryShareManagement: RecoveryShareManagement.ENCLAVE,
119
+ };
120
+
121
+ if (!wallet) {
122
+ return {
123
+ status: UserWalletStatus.LOGGED_IN_WALLET_UNINITIALIZED,
124
+ authDetails,
125
+ };
126
+ }
127
+
128
+ return {
129
+ status: UserWalletStatus.LOGGED_IN_WALLET_INITIALIZED,
130
+ walletAddress: wallet.address,
131
+ authDetails,
132
+ account: await this.getAccount(),
133
+ };
134
+ }
135
+
136
+ /**
137
+ * Returns an account to perform wallet operations
138
+ * @internal
139
+ */
140
+ async getAccount(): Promise<Account> {
141
+ const client = this.client;
142
+ const ecosystem = this.ecosystem;
143
+
144
+ const _signTransaction = async (tx: SendTransactionOption) => {
145
+ const rpcRequest = getRpcClient({
146
+ client,
147
+ chain: getCachedChain(tx.chainId),
148
+ });
149
+ const transaction: Record<string, Hex | number | undefined> = {
150
+ to: (tx.to as Hex) ?? undefined,
151
+ data: tx.data ? toHex(tx.data) : undefined,
152
+ value: tx.value ? toHex(tx.value) : undefined,
153
+ gas: tx.gas ? toHex(tx.gas + tx.gas / BigInt(10)) : undefined, // Add a 10% buffer to gas
154
+ nonce: tx.nonce
155
+ ? toHex(tx.nonce)
156
+ : toHex(
157
+ await import(
158
+ "../../../../rpc/actions/eth_getTransactionCount.js"
159
+ ).then(({ eth_getTransactionCount }) =>
160
+ eth_getTransactionCount(rpcRequest, {
161
+ address: this.address,
162
+ blockTag: "pending",
163
+ }),
164
+ ),
165
+ ),
166
+ chainId: toHex(tx.chainId),
167
+ };
168
+
169
+ if (tx.maxFeePerGas) {
170
+ transaction.maxFeePerGas = toHex(tx.maxFeePerGas);
171
+ transaction.maxPriorityFeePerGas = tx.maxPriorityFeePerGas
172
+ ? toHex(tx.maxPriorityFeePerGas)
173
+ : undefined;
174
+ transaction.type = 2;
175
+ } else {
176
+ transaction.gasPrice = tx.gasPrice ? toHex(tx.gasPrice) : undefined;
177
+ transaction.type = 0;
178
+ }
179
+
180
+ return signEnclaveTransaction({
181
+ client,
182
+ ecosystem,
183
+ payload: transaction,
184
+ });
185
+ };
186
+ return {
187
+ address: getAddress(this.address),
188
+ async signTransaction(tx) {
189
+ if (!tx.chainId) {
190
+ throw new Error("chainId required in tx to sign");
191
+ }
192
+
193
+ return _signTransaction({
194
+ chainId: tx.chainId,
195
+ ...tx,
196
+ });
197
+ },
198
+ async sendTransaction(tx) {
199
+ const rpcRequest = getRpcClient({
200
+ client,
201
+ chain: getCachedChain(tx.chainId),
202
+ });
203
+ const signedTx = await _signTransaction(tx);
204
+ const transactionHash = await eth_sendRawTransaction(
205
+ rpcRequest,
206
+ signedTx,
207
+ );
208
+ return {
209
+ transactionHash,
210
+ };
211
+ },
212
+ async signMessage({ message }) {
213
+ const messagePayload = (() => {
214
+ if (typeof message === "string") {
215
+ return { message, isRaw: false };
216
+ }
217
+ return {
218
+ message:
219
+ typeof message.raw === "string"
220
+ ? message.raw
221
+ : bytesToHex(message.raw),
222
+ isRaw: true,
223
+ };
224
+ })();
225
+
226
+ const { signature } = await signEnclaveMessage({
227
+ client,
228
+ ecosystem,
229
+ payload: messagePayload,
230
+ });
231
+ return signature as Hex;
232
+ },
233
+ async signTypedData(_typedData) {
234
+ const parsedTypedData = parseTypedData(_typedData);
235
+ const { signature } = await signEnclaveTypedData({
236
+ client,
237
+ ecosystem,
238
+ payload: parsedTypedData,
239
+ });
240
+
241
+ return signature as Hex;
242
+ },
243
+ };
244
+ }
245
+ }
@@ -0,0 +1,17 @@
1
+ import type { ThirdwebClient } from "../../../../client/client.js";
2
+ import { webLocalStorage } from "../../../../utils/storage/webStorage.js";
3
+ import { ClientScopedStorage } from "../../core/authentication/client-scoped-storage.js";
4
+ import type { Ecosystem } from "../types.js";
5
+
6
+ export async function getAuthToken(
7
+ client: ThirdwebClient,
8
+ ecosystem?: Ecosystem,
9
+ ) {
10
+ const localStorage = new ClientScopedStorage({
11
+ storage: webLocalStorage,
12
+ clientId: client.clientId,
13
+ ecosystemId: ecosystem?.id,
14
+ });
15
+
16
+ return localStorage.getAuthCookie();
17
+ }