@b3dotfun/sdk 0.0.77 → 0.0.78-alpha.1

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 (66) hide show
  1. package/dist/cjs/anyspend/react/components/common/PanelOnramp.js +1 -1
  2. package/dist/cjs/global-account/react/components/B3DynamicModal.js +18 -4
  3. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +4 -2
  4. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +6 -3
  5. package/dist/cjs/global-account/react/components/B3Provider/types.d.ts +1 -0
  6. package/dist/cjs/global-account/react/components/B3Provider/types.js +1 -0
  7. package/dist/cjs/global-account/react/components/ManageAccount/BottomNavigation.js +2 -2
  8. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +162 -46
  9. package/dist/cjs/global-account/react/components/TurnkeyAuthModal.d.ts +8 -0
  10. package/dist/cjs/global-account/react/components/TurnkeyAuthModal.js +84 -0
  11. package/dist/cjs/global-account/react/components/index.d.ts +1 -0
  12. package/dist/cjs/global-account/react/components/index.js +6 -3
  13. package/dist/cjs/global-account/react/hooks/index.d.ts +1 -0
  14. package/dist/cjs/global-account/react/hooks/index.js +3 -1
  15. package/dist/cjs/global-account/react/hooks/useAuthentication.d.ts +7 -0
  16. package/dist/cjs/global-account/react/hooks/useTurnkeyAuth.d.ts +20 -0
  17. package/dist/cjs/global-account/react/hooks/useTurnkeyAuth.js +112 -0
  18. package/dist/cjs/global-account/react/hooks/useUserQuery.d.ts +7 -0
  19. package/dist/cjs/global-account/react/stores/useAuthStore.d.ts +2 -0
  20. package/dist/cjs/global-account/react/stores/useAuthStore.js +2 -0
  21. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +21 -1
  22. package/dist/esm/anyspend/react/components/common/PanelOnramp.js +1 -1
  23. package/dist/esm/global-account/react/components/B3DynamicModal.js +18 -4
  24. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +4 -2
  25. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +6 -3
  26. package/dist/esm/global-account/react/components/B3Provider/types.d.ts +1 -0
  27. package/dist/esm/global-account/react/components/B3Provider/types.js +1 -0
  28. package/dist/esm/global-account/react/components/ManageAccount/BottomNavigation.js +2 -2
  29. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +162 -46
  30. package/dist/esm/global-account/react/components/TurnkeyAuthModal.d.ts +8 -0
  31. package/dist/esm/global-account/react/components/TurnkeyAuthModal.js +81 -0
  32. package/dist/esm/global-account/react/components/index.d.ts +1 -0
  33. package/dist/esm/global-account/react/components/index.js +2 -0
  34. package/dist/esm/global-account/react/hooks/index.d.ts +1 -0
  35. package/dist/esm/global-account/react/hooks/index.js +1 -0
  36. package/dist/esm/global-account/react/hooks/useAuthentication.d.ts +7 -0
  37. package/dist/esm/global-account/react/hooks/useTurnkeyAuth.d.ts +20 -0
  38. package/dist/esm/global-account/react/hooks/useTurnkeyAuth.js +106 -0
  39. package/dist/esm/global-account/react/hooks/useUserQuery.d.ts +7 -0
  40. package/dist/esm/global-account/react/stores/useAuthStore.d.ts +2 -0
  41. package/dist/esm/global-account/react/stores/useAuthStore.js +2 -0
  42. package/dist/esm/global-account/react/stores/useModalStore.d.ts +21 -1
  43. package/dist/styles/index.css +1 -1
  44. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +4 -2
  45. package/dist/types/global-account/react/components/B3Provider/types.d.ts +1 -0
  46. package/dist/types/global-account/react/components/TurnkeyAuthModal.d.ts +8 -0
  47. package/dist/types/global-account/react/components/index.d.ts +1 -0
  48. package/dist/types/global-account/react/hooks/index.d.ts +1 -0
  49. package/dist/types/global-account/react/hooks/useAuthentication.d.ts +7 -0
  50. package/dist/types/global-account/react/hooks/useTurnkeyAuth.d.ts +20 -0
  51. package/dist/types/global-account/react/hooks/useUserQuery.d.ts +7 -0
  52. package/dist/types/global-account/react/stores/useAuthStore.d.ts +2 -0
  53. package/dist/types/global-account/react/stores/useModalStore.d.ts +21 -1
  54. package/package.json +2 -2
  55. package/src/anyspend/react/components/common/PanelOnramp.tsx +10 -8
  56. package/src/global-account/react/components/B3DynamicModal.tsx +26 -3
  57. package/src/global-account/react/components/B3Provider/B3Provider.tsx +9 -0
  58. package/src/global-account/react/components/B3Provider/types.ts +2 -0
  59. package/src/global-account/react/components/ManageAccount/BottomNavigation.tsx +3 -3
  60. package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +170 -48
  61. package/src/global-account/react/components/TurnkeyAuthModal.tsx +240 -0
  62. package/src/global-account/react/components/index.ts +3 -0
  63. package/src/global-account/react/hooks/index.ts +1 -0
  64. package/src/global-account/react/hooks/useTurnkeyAuth.ts +138 -0
  65. package/src/global-account/react/stores/useAuthStore.ts +4 -0
  66. package/src/global-account/react/stores/useModalStore.ts +22 -0
@@ -0,0 +1,240 @@
1
+ import React, { useState, useEffect, useRef } from "react";
2
+ import { useTurnkeyAuth } from "../hooks/useTurnkeyAuth";
3
+
4
+ type ModalStep = "email" | "otp" | "success";
5
+
6
+ interface TurnkeyAuthModalProps {
7
+ onClose: () => void;
8
+ onSuccess: (_user: any) => void;
9
+ initialEmail?: string;
10
+ skipToOtp?: boolean;
11
+ }
12
+
13
+ export function TurnkeyAuthModal({ onClose, onSuccess, initialEmail = "", skipToOtp = false }: TurnkeyAuthModalProps) {
14
+ const [step, setStep] = useState<ModalStep>(skipToOtp ? "otp" : "email");
15
+ const [email, setEmail] = useState(initialEmail);
16
+ const [otpCode, setOtpCode] = useState("");
17
+ const [otpId, setOtpId] = useState("");
18
+ const autoSubmitTriggeredRef = useRef(false);
19
+
20
+ const { initiateLogin, verifyOtp, isLoading, error, clearError } = useTurnkeyAuth();
21
+
22
+ // Update email when initialEmail changes
23
+ useEffect(() => {
24
+ if (initialEmail && initialEmail !== email) {
25
+ setEmail(initialEmail);
26
+ }
27
+ }, [initialEmail, email]);
28
+
29
+ // Auto-submit email form if skipToOtp is true - triggers on mount when skipToOtp=true
30
+ useEffect(() => {
31
+ if (skipToOtp && email && step === "otp" && !otpId && !isLoading && !autoSubmitTriggeredRef.current) {
32
+ autoSubmitTriggeredRef.current = true;
33
+ // Call initiateLogin directly to get OTP
34
+ initiateLogin(email)
35
+ .then(result => {
36
+ setOtpId(result.otpId);
37
+ })
38
+ .catch(err => {
39
+ console.error("Failed to initiate login:", err);
40
+ });
41
+ }
42
+ // eslint-disable-next-line react-hooks/exhaustive-deps
43
+ }, [skipToOtp, email, step, otpId, isLoading]);
44
+
45
+ const handleEmailSubmit = async (e: React.FormEvent) => {
46
+ e.preventDefault();
47
+
48
+ try {
49
+ const result = await initiateLogin(email);
50
+ setOtpId(result.otpId);
51
+ setStep("otp");
52
+ } catch (err) {
53
+ // Error is handled by the hook
54
+ console.error("Failed to initiate login:", err);
55
+ }
56
+ };
57
+
58
+ const handleOtpSubmit = async (e: React.FormEvent) => {
59
+ e.preventDefault();
60
+
61
+ try {
62
+ const result = await verifyOtp(otpId, otpCode);
63
+ setStep("success");
64
+
65
+ // Auto-close after success and notify parent
66
+ setTimeout(() => {
67
+ onSuccess(result.user);
68
+ handleClose();
69
+ }, 1500);
70
+ } catch (err) {
71
+ // Error is handled by the hook
72
+ console.error("Failed to verify OTP:", err);
73
+ }
74
+ };
75
+
76
+ const handleClose = () => {
77
+ // Reset state
78
+ setStep("email");
79
+ setEmail("");
80
+ setOtpCode("");
81
+ setOtpId("");
82
+ autoSubmitTriggeredRef.current = false;
83
+ clearError();
84
+ onClose();
85
+ };
86
+
87
+ const handleResendOtp = async () => {
88
+ try {
89
+ const result = await initiateLogin(email);
90
+ setOtpId(result.otpId);
91
+ clearError();
92
+ } catch (err) {
93
+ console.error("Failed to resend OTP:", err);
94
+ }
95
+ };
96
+
97
+ return (
98
+ <div className="font-neue-montreal p-8">
99
+ {/* Email Step */}
100
+ {step === "email" && (
101
+ <>
102
+ <h2 className="mb-6 text-center text-2xl font-bold text-gray-900 dark:text-white">
103
+ Setup your AnySpend Wallet
104
+ </h2>
105
+ <div className="mb-6 space-y-3 text-center text-sm text-gray-600 dark:text-gray-400">
106
+ <p>
107
+ AnySpend uses a secure,
108
+ <br />
109
+ embedded wallet to fund your workflows.
110
+ </p>
111
+ <p>
112
+ Please provide an email address to secure
113
+ <br />
114
+ your wallet.
115
+ </p>
116
+ </div>
117
+
118
+ <form onSubmit={handleEmailSubmit} className="space-y-4">
119
+ <div>
120
+ <input
121
+ type="email"
122
+ placeholder="email"
123
+ value={email}
124
+ onChange={e => setEmail(e.target.value)}
125
+ required
126
+ disabled={isLoading}
127
+ className="w-full rounded-lg border border-gray-300 px-4 py-3 text-center text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/20 disabled:cursor-not-allowed disabled:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
128
+ />
129
+ </div>
130
+
131
+ {error && (
132
+ <div className="rounded-md bg-red-50 p-3 text-sm text-red-800 dark:bg-red-900/20 dark:text-red-400">
133
+ {error}
134
+ </div>
135
+ )}
136
+
137
+ <button
138
+ type="submit"
139
+ disabled={isLoading || !email}
140
+ className="w-full rounded-lg bg-blue-600 px-6 py-3 font-semibold text-white transition-all duration-200 hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-gray-300 dark:disabled:bg-gray-700"
141
+ >
142
+ {isLoading ? (
143
+ <span className="flex items-center justify-center gap-2">
144
+ <div className="h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent"></div>
145
+ Sending...
146
+ </span>
147
+ ) : (
148
+ "Continue"
149
+ )}
150
+ </button>
151
+ </form>
152
+ </>
153
+ )}
154
+
155
+ {/* OTP Step */}
156
+ {step === "otp" && (
157
+ <>
158
+ <h2 className="mb-4 text-center text-2xl font-bold text-gray-900 dark:text-white">2FA Security</h2>
159
+ <div className="mb-6 space-y-3 text-center text-sm text-gray-600 dark:text-gray-400">
160
+ <p>
161
+ AnySpend uses a secure,
162
+ <br />
163
+ embedded wallet to fund your workflows.
164
+ <br />
165
+ Please provide 2FA code sent to your email.
166
+ </p>
167
+ </div>
168
+
169
+ <form onSubmit={handleOtpSubmit} className="space-y-4">
170
+ <div>
171
+ <input
172
+ type="text"
173
+ placeholder="Enter code"
174
+ value={otpCode}
175
+ onChange={e => setOtpCode(e.target.value.toUpperCase())}
176
+ required
177
+ disabled={isLoading}
178
+ autoFocus
179
+ className="w-full rounded-lg border border-gray-300 px-4 py-3 text-center font-mono text-lg uppercase tracking-wider text-gray-900 placeholder-gray-400 focus:border-blue-500 focus:outline-none focus:ring-2 focus:ring-blue-500/20 disabled:cursor-not-allowed disabled:bg-gray-50 dark:border-gray-700 dark:bg-gray-800 dark:text-white dark:placeholder-gray-500"
180
+ maxLength={20}
181
+ />
182
+ </div>
183
+
184
+ {error && (
185
+ <div className="rounded-md bg-red-50 p-3 text-sm text-red-800 dark:bg-red-900/20 dark:text-red-400">
186
+ {error}
187
+ </div>
188
+ )}
189
+
190
+ <div className="flex flex-col gap-2">
191
+ <button
192
+ type="submit"
193
+ disabled={isLoading || !otpCode}
194
+ className="w-full rounded-lg bg-blue-600 px-6 py-3 font-semibold text-white transition-all duration-200 hover:bg-blue-700 disabled:cursor-not-allowed disabled:bg-gray-300 dark:disabled:bg-gray-700"
195
+ >
196
+ {isLoading ? (
197
+ <span className="flex items-center justify-center gap-2">
198
+ <div className="h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent"></div>
199
+ Verifying...
200
+ </span>
201
+ ) : (
202
+ "Confirm"
203
+ )}
204
+ </button>
205
+
206
+ <button
207
+ type="button"
208
+ onClick={handleResendOtp}
209
+ disabled={isLoading}
210
+ className="text-sm text-blue-600 hover:text-blue-700 hover:underline disabled:cursor-not-allowed disabled:text-gray-400 dark:text-blue-400 dark:hover:text-blue-300"
211
+ >
212
+ Resend code
213
+ </button>
214
+ </div>
215
+ </form>
216
+ </>
217
+ )}
218
+
219
+ {/* Success Step */}
220
+ {step === "success" && (
221
+ <div className="text-center">
222
+ <div className="mb-6 flex items-center justify-center">
223
+ <div className="flex h-16 w-16 items-center justify-center rounded-full bg-green-100 dark:bg-green-900/20">
224
+ <svg
225
+ className="h-8 w-8 text-green-600 dark:text-green-400"
226
+ fill="none"
227
+ viewBox="0 0 24 24"
228
+ stroke="currentColor"
229
+ >
230
+ <path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
231
+ </svg>
232
+ </div>
233
+ </div>
234
+ <h2 className="mb-2 text-2xl font-bold text-gray-900 dark:text-white">Successfully Authenticated!</h2>
235
+ <p className="text-sm text-gray-600 dark:text-gray-400">Redirecting...</p>
236
+ </div>
237
+ )}
238
+ </div>
239
+ );
240
+ }
@@ -17,6 +17,9 @@ export { SignInWithB3Privy } from "./SignInWithB3/SignInWithB3Privy";
17
17
  export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep";
18
18
  export { getConnectOptionsFromStrategy, isWalletType, type AllowedStrategy } from "./SignInWithB3/utils/signInUtils";
19
19
 
20
+ // Turnkey Components
21
+ export { TurnkeyAuthModal } from "./TurnkeyAuthModal";
22
+
20
23
  // ManageAccount Components
21
24
  export { ManageAccount } from "./ManageAccount/ManageAccount";
22
25
 
@@ -49,5 +49,6 @@ export { useTokenFromUrl } from "./useTokenFromUrl";
49
49
  export { useTokenPrice } from "./useTokenPrice";
50
50
  export { useTokenPriceWithFallback } from "./useTokenPriceWithFallback";
51
51
  export { useTokensFromAddress } from "./useTokensFromAddress";
52
+ export { useTurnkeyAuth } from "./useTurnkeyAuth";
52
53
  export { useUnifiedChainSwitchAndExecute } from "./useUnifiedChainSwitchAndExecute";
53
54
  export { useURLParams } from "./useURLParams";
@@ -0,0 +1,138 @@
1
+ import app from "../../app";
2
+ import { useAuthStore } from "../stores";
3
+ import { useCallback, useState } from "react";
4
+ import { useB3 } from "../components/B3Provider/useB3";
5
+ import { TurnkeyAuthInitResponse } from "@b3dotfun/b3-api";
6
+ import { debugB3React } from "@b3dotfun/sdk/shared/utils/debug";
7
+
8
+ const debug = debugB3React("useTurnkeyAuth");
9
+
10
+ interface TurnkeyVerifyResponse {
11
+ turnkeySessionJwt: string;
12
+ }
13
+
14
+ interface UseTurnkeyAuthReturn {
15
+ initiateLogin: (_email: string) => Promise<TurnkeyAuthInitResponse>;
16
+ verifyOtp: (_otpId: string, _otpCode: string) => Promise<{ user: any }>;
17
+ isLoading: boolean;
18
+ error: string | null;
19
+ clearError: () => void;
20
+ }
21
+
22
+ /**
23
+ * Hook for Turnkey email-based OTP authentication
24
+ *
25
+ * Usage:
26
+ * 1. Call initiateLogin(email) → User receives OTP email
27
+ * 2. Call verifyOtp(...) → Verifies OTP and authenticates with b3-api
28
+ * 3. User is authenticated, JWT stored in cookies automatically
29
+ */
30
+ export function useTurnkeyAuth(): UseTurnkeyAuthReturn {
31
+ const [isLoading, setIsLoading] = useState(false);
32
+ const [error, setError] = useState<string | null>(null);
33
+ const setIsAuthenticating = useAuthStore(state => state.setIsAuthenticating);
34
+ const setIsAuthenticated = useAuthStore(state => state.setIsAuthenticated);
35
+ const { user } = useB3();
36
+
37
+ /**
38
+ * Step 1: Initiate login with email
39
+ * - Calls backend to create sub-org (if needed) and send OTP
40
+ * - Returns otpId to use in verification step
41
+ */
42
+ const initiateLogin = useCallback(
43
+ async (email: string): Promise<TurnkeyAuthInitResponse> => {
44
+ setIsLoading(true);
45
+ setError(null);
46
+ setIsAuthenticating(true);
47
+
48
+ try {
49
+ if (!user?.userId) {
50
+ throw new Error("User ID is required to initiate Turnkey login.");
51
+ }
52
+ debug(`Initiating login for: ${email}`);
53
+
54
+ // Call FeathersJS service to initialize OTP
55
+ const data: TurnkeyAuthInitResponse = await app.service("turnkey-auth").init({ email, userId: user.userId });
56
+
57
+ debug(`OTP initialized successfully. OtpId: ${data.otpId}`);
58
+
59
+ return data;
60
+ } catch (err: any) {
61
+ debug("Error initiating login:", err);
62
+ const errorMessage = err.message || "Failed to send OTP email. Please try again.";
63
+ setError(errorMessage);
64
+ throw err;
65
+ } finally {
66
+ setIsLoading(false);
67
+ setIsAuthenticating(false);
68
+ }
69
+ },
70
+ [user, setIsAuthenticating],
71
+ );
72
+
73
+ /**
74
+ * Step 2: Verify OTP and authenticate
75
+ * - Verifies OTP with backend
76
+ * - Gets Turnkey session JWT
77
+ * - Authenticates with b3-api using "turnkey-jwt" strategy
78
+ * - JWT automatically stored in cookies by SDK
79
+ */
80
+ const verifyOtp = useCallback(
81
+ async (otpId: string, otpCode: string): Promise<{ user: any }> => {
82
+ setIsLoading(true);
83
+ setError(null);
84
+ setIsAuthenticating(true);
85
+
86
+ try {
87
+ debug(`Verifying OTP...`, { userId: user?.userId });
88
+
89
+ // Step 1: Verify OTP and get Turnkey session JWT
90
+ const { turnkeySessionJwt }: TurnkeyVerifyResponse = await app.service("turnkey-auth").verify({
91
+ otpId,
92
+ otpCode,
93
+ });
94
+
95
+ debug(`OTP verified! Authenticating with b3-api...`);
96
+
97
+ // Step 2: Authenticate with b3-api using Turnkey JWT
98
+ // The SDK will automatically store the b3-api JWT in cookies
99
+ const authResult = await app.authenticate({
100
+ strategy: "turnkey-jwt",
101
+ accessToken: turnkeySessionJwt,
102
+ } as any);
103
+
104
+ debug(`Successfully authenticated with b3-api!`, authResult);
105
+
106
+ // Update auth store to reflect authenticated state
107
+ setIsAuthenticated(true);
108
+
109
+ // Return user data
110
+ return {
111
+ user: authResult.user,
112
+ };
113
+ } catch (err: any) {
114
+ debug("Error verifying OTP:", err);
115
+ const errorMessage = err.message || "Failed to verify OTP. Please try again.";
116
+ setError(errorMessage);
117
+ setIsAuthenticated(false);
118
+ throw err;
119
+ } finally {
120
+ setIsLoading(false);
121
+ setIsAuthenticating(false);
122
+ }
123
+ },
124
+ [user, setIsAuthenticating, setIsAuthenticated],
125
+ );
126
+
127
+ const clearError = useCallback(() => {
128
+ setError(null);
129
+ }, []);
130
+
131
+ return {
132
+ initiateLogin,
133
+ verifyOtp,
134
+ isLoading,
135
+ error,
136
+ clearError,
137
+ };
138
+ }
@@ -29,6 +29,8 @@ interface AuthState {
29
29
  setIsAuthenticating: (isAuthenticating: boolean) => void;
30
30
  hasStartedConnecting: boolean;
31
31
  setHasStartedConnecting: (hasStartedConnecting: boolean) => void;
32
+ justCompletedLogin: boolean;
33
+ setJustCompletedLogin: (justCompletedLogin: boolean) => void;
32
34
  }
33
35
 
34
36
  export const useAuthStore = create<AuthState>(set => ({
@@ -73,4 +75,6 @@ export const useAuthStore = create<AuthState>(set => ({
73
75
  setIsAuthenticating: isAuthenticating => set({ isAuthenticating: isAuthenticating }),
74
76
  hasStartedConnecting: false,
75
77
  setHasStartedConnecting: hasStartedConnecting => set({ hasStartedConnecting }),
78
+ justCompletedLogin: false,
79
+ setJustCompletedLogin: justCompletedLogin => set({ justCompletedLogin }),
76
80
  }));
@@ -12,6 +12,8 @@ import { create } from "zustand";
12
12
  interface BaseModalProps {
13
13
  /** Whether to show a back button in the modal header */
14
14
  showBackButton?: boolean;
15
+ /** Whether the modal can be closed by clicking outside or pressing escape. Defaults to true */
16
+ closable?: boolean;
15
17
  }
16
18
 
17
19
  /**
@@ -43,6 +45,25 @@ export interface SignInWithB3ModalProps extends BaseModalProps {
43
45
  signersEnabled?: boolean;
44
46
  }
45
47
 
48
+ /**
49
+ * Props for the Turnkey Authentication modal
50
+ * Handles Turnkey email/OTP authentication flow
51
+ */
52
+ export interface TurnkeyAuthModalProps extends BaseModalProps {
53
+ /** Modal type identifier */
54
+ type: "turnkeyAuth";
55
+ /** Callback function called when authentication is successful */
56
+ onSuccess: (_user: any) => void;
57
+ /** Callback function called when modal is closed */
58
+ onClose: () => void;
59
+ /** Initial email to pre-fill */
60
+ initialEmail?: string;
61
+ /** Whether to skip directly to OTP step */
62
+ skipToOtp?: boolean;
63
+ /** Whether the modal can be closed - defaults to false for Turnkey */
64
+ closable?: boolean;
65
+ }
66
+
46
67
  /**
47
68
  * Props for the Request Permissions modal
48
69
  * Used to request permission for session keys to interact with contracts
@@ -481,6 +502,7 @@ export interface AnySpendCollectorClubPurchaseProps extends BaseModalProps {
481
502
  */
482
503
  export type ModalContentType =
483
504
  | SignInWithB3ModalProps
505
+ | TurnkeyAuthModalProps
484
506
  | RequestPermissionsModalProps
485
507
  | ManageAccountModalProps
486
508
  | AnySpendModalProps