@b3dotfun/sdk 0.0.77-alpha.1 → 0.0.77-alpha.2
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.
- package/dist/cjs/global-account/react/components/B3DynamicModal.js +17 -3
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +4 -2
- package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +6 -3
- package/dist/cjs/global-account/react/components/B3Provider/types.d.ts +1 -0
- package/dist/cjs/global-account/react/components/B3Provider/types.js +1 -0
- package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +162 -46
- package/dist/cjs/global-account/react/components/TurnkeyAuthModal.d.ts +8 -0
- package/dist/cjs/global-account/react/components/TurnkeyAuthModal.js +84 -0
- package/dist/cjs/global-account/react/components/index.d.ts +1 -0
- package/dist/cjs/global-account/react/components/index.js +6 -3
- package/dist/cjs/global-account/react/hooks/index.d.ts +1 -0
- package/dist/cjs/global-account/react/hooks/index.js +3 -1
- package/dist/cjs/global-account/react/hooks/useAuthentication.d.ts +7 -0
- package/dist/cjs/global-account/react/hooks/useTurnkeyAuth.d.ts +20 -0
- package/dist/cjs/global-account/react/hooks/useTurnkeyAuth.js +112 -0
- package/dist/cjs/global-account/react/hooks/useUserQuery.d.ts +7 -0
- package/dist/cjs/global-account/react/stores/useAuthStore.d.ts +2 -0
- package/dist/cjs/global-account/react/stores/useAuthStore.js +2 -0
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +21 -1
- package/dist/esm/global-account/react/components/B3DynamicModal.js +17 -3
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +4 -2
- package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +6 -3
- package/dist/esm/global-account/react/components/B3Provider/types.d.ts +1 -0
- package/dist/esm/global-account/react/components/B3Provider/types.js +1 -0
- package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +162 -46
- package/dist/esm/global-account/react/components/TurnkeyAuthModal.d.ts +8 -0
- package/dist/esm/global-account/react/components/TurnkeyAuthModal.js +81 -0
- package/dist/esm/global-account/react/components/index.d.ts +1 -0
- package/dist/esm/global-account/react/components/index.js +2 -0
- package/dist/esm/global-account/react/hooks/index.d.ts +1 -0
- package/dist/esm/global-account/react/hooks/index.js +1 -0
- package/dist/esm/global-account/react/hooks/useAuthentication.d.ts +7 -0
- package/dist/esm/global-account/react/hooks/useTurnkeyAuth.d.ts +20 -0
- package/dist/esm/global-account/react/hooks/useTurnkeyAuth.js +106 -0
- package/dist/esm/global-account/react/hooks/useUserQuery.d.ts +7 -0
- package/dist/esm/global-account/react/stores/useAuthStore.d.ts +2 -0
- package/dist/esm/global-account/react/stores/useAuthStore.js +2 -0
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +21 -1
- package/dist/styles/index.css +1 -1
- package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +4 -2
- package/dist/types/global-account/react/components/B3Provider/types.d.ts +1 -0
- package/dist/types/global-account/react/components/TurnkeyAuthModal.d.ts +8 -0
- package/dist/types/global-account/react/components/index.d.ts +1 -0
- package/dist/types/global-account/react/hooks/index.d.ts +1 -0
- package/dist/types/global-account/react/hooks/useAuthentication.d.ts +7 -0
- package/dist/types/global-account/react/hooks/useTurnkeyAuth.d.ts +20 -0
- package/dist/types/global-account/react/hooks/useUserQuery.d.ts +7 -0
- package/dist/types/global-account/react/stores/useAuthStore.d.ts +2 -0
- package/dist/types/global-account/react/stores/useModalStore.d.ts +21 -1
- package/package.json +2 -2
- package/src/global-account/react/components/B3DynamicModal.tsx +20 -1
- package/src/global-account/react/components/B3Provider/B3Provider.tsx +9 -0
- package/src/global-account/react/components/B3Provider/types.ts +2 -0
- package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +170 -48
- package/src/global-account/react/components/TurnkeyAuthModal.tsx +240 -0
- package/src/global-account/react/components/index.ts +3 -0
- package/src/global-account/react/hooks/index.ts +1 -0
- package/src/global-account/react/hooks/useTurnkeyAuth.ts +138 -0
- package/src/global-account/react/stores/useAuthStore.ts +4 -0
- package/src/global-account/react/stores/useModalStore.ts +22 -0
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState, useEffect, useRef } from "react";
|
|
3
|
+
import { useTurnkeyAuth } from "../hooks/useTurnkeyAuth.js";
|
|
4
|
+
export function TurnkeyAuthModal({ onClose, onSuccess, initialEmail = "", skipToOtp = false }) {
|
|
5
|
+
const [step, setStep] = useState(skipToOtp ? "otp" : "email");
|
|
6
|
+
const [email, setEmail] = useState(initialEmail);
|
|
7
|
+
const [otpCode, setOtpCode] = useState("");
|
|
8
|
+
const [otpId, setOtpId] = useState("");
|
|
9
|
+
const autoSubmitTriggeredRef = useRef(false);
|
|
10
|
+
const { initiateLogin, verifyOtp, isLoading, error, clearError } = useTurnkeyAuth();
|
|
11
|
+
// Update email when initialEmail changes
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
if (initialEmail && initialEmail !== email) {
|
|
14
|
+
setEmail(initialEmail);
|
|
15
|
+
}
|
|
16
|
+
}, [initialEmail, email]);
|
|
17
|
+
// Auto-submit email form if skipToOtp is true - triggers on mount when skipToOtp=true
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
if (skipToOtp && email && step === "otp" && !otpId && !isLoading && !autoSubmitTriggeredRef.current) {
|
|
20
|
+
autoSubmitTriggeredRef.current = true;
|
|
21
|
+
// Call initiateLogin directly to get OTP
|
|
22
|
+
initiateLogin(email)
|
|
23
|
+
.then(result => {
|
|
24
|
+
setOtpId(result.otpId);
|
|
25
|
+
})
|
|
26
|
+
.catch(err => {
|
|
27
|
+
console.error("Failed to initiate login:", err);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
31
|
+
}, [skipToOtp, email, step, otpId, isLoading]);
|
|
32
|
+
const handleEmailSubmit = async (e) => {
|
|
33
|
+
e.preventDefault();
|
|
34
|
+
try {
|
|
35
|
+
const result = await initiateLogin(email);
|
|
36
|
+
setOtpId(result.otpId);
|
|
37
|
+
setStep("otp");
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
// Error is handled by the hook
|
|
41
|
+
console.error("Failed to initiate login:", err);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
const handleOtpSubmit = async (e) => {
|
|
45
|
+
e.preventDefault();
|
|
46
|
+
try {
|
|
47
|
+
const result = await verifyOtp(otpId, otpCode);
|
|
48
|
+
setStep("success");
|
|
49
|
+
// Auto-close after success and notify parent
|
|
50
|
+
setTimeout(() => {
|
|
51
|
+
onSuccess(result.user);
|
|
52
|
+
handleClose();
|
|
53
|
+
}, 1500);
|
|
54
|
+
}
|
|
55
|
+
catch (err) {
|
|
56
|
+
// Error is handled by the hook
|
|
57
|
+
console.error("Failed to verify OTP:", err);
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
const handleClose = () => {
|
|
61
|
+
// Reset state
|
|
62
|
+
setStep("email");
|
|
63
|
+
setEmail("");
|
|
64
|
+
setOtpCode("");
|
|
65
|
+
setOtpId("");
|
|
66
|
+
autoSubmitTriggeredRef.current = false;
|
|
67
|
+
clearError();
|
|
68
|
+
onClose();
|
|
69
|
+
};
|
|
70
|
+
const handleResendOtp = async () => {
|
|
71
|
+
try {
|
|
72
|
+
const result = await initiateLogin(email);
|
|
73
|
+
setOtpId(result.otpId);
|
|
74
|
+
clearError();
|
|
75
|
+
}
|
|
76
|
+
catch (err) {
|
|
77
|
+
console.error("Failed to resend OTP:", err);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
return (_jsxs("div", { className: "font-neue-montreal p-8", children: [step === "email" && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "mb-6 text-center text-2xl font-bold text-gray-900 dark:text-white", children: "Setup your AnySpend Wallet" }), _jsxs("div", { className: "mb-6 space-y-3 text-center text-sm text-gray-600 dark:text-gray-400", children: [_jsxs("p", { children: ["AnySpend uses a secure,", _jsx("br", {}), "embedded wallet to fund your workflows."] }), _jsxs("p", { children: ["Please provide an email address to secure", _jsx("br", {}), "your wallet."] })] }), _jsxs("form", { onSubmit: handleEmailSubmit, className: "space-y-4", children: [_jsx("div", { children: _jsx("input", { type: "email", placeholder: "email", value: email, onChange: e => setEmail(e.target.value), required: true, disabled: isLoading, 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" }) }), error && (_jsx("div", { className: "rounded-md bg-red-50 p-3 text-sm text-red-800 dark:bg-red-900/20 dark:text-red-400", children: error })), _jsx("button", { type: "submit", disabled: isLoading || !email, 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", children: isLoading ? (_jsxs("span", { className: "flex items-center justify-center gap-2", children: [_jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" }), "Sending..."] })) : ("Continue") })] })] })), step === "otp" && (_jsxs(_Fragment, { children: [_jsx("h2", { className: "mb-4 text-center text-2xl font-bold text-gray-900 dark:text-white", children: "2FA Security" }), _jsx("div", { className: "mb-6 space-y-3 text-center text-sm text-gray-600 dark:text-gray-400", children: _jsxs("p", { children: ["AnySpend uses a secure,", _jsx("br", {}), "embedded wallet to fund your workflows.", _jsx("br", {}), "Please provide 2FA code sent to your email."] }) }), _jsxs("form", { onSubmit: handleOtpSubmit, className: "space-y-4", children: [_jsx("div", { children: _jsx("input", { type: "text", placeholder: "Enter code", value: otpCode, onChange: e => setOtpCode(e.target.value.toUpperCase()), required: true, disabled: isLoading, autoFocus: true, 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", maxLength: 20 }) }), error && (_jsx("div", { className: "rounded-md bg-red-50 p-3 text-sm text-red-800 dark:bg-red-900/20 dark:text-red-400", children: error })), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx("button", { type: "submit", disabled: isLoading || !otpCode, 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", children: isLoading ? (_jsxs("span", { className: "flex items-center justify-center gap-2", children: [_jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-white border-t-transparent" }), "Verifying..."] })) : ("Confirm") }), _jsx("button", { type: "button", onClick: handleResendOtp, disabled: isLoading, 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", children: "Resend code" })] })] })] })), step === "success" && (_jsxs("div", { className: "text-center", children: [_jsx("div", { className: "mb-6 flex items-center justify-center", children: _jsx("div", { className: "flex h-16 w-16 items-center justify-center rounded-full bg-green-100 dark:bg-green-900/20", children: _jsx("svg", { className: "h-8 w-8 text-green-600 dark:text-green-400", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) }) }), _jsx("h2", { className: "mb-2 text-2xl font-bold text-gray-900 dark:text-white", children: "Successfully Authenticated!" }), _jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: "Redirecting..." })] }))] }));
|
|
81
|
+
}
|
|
@@ -12,6 +12,7 @@ export { SignInWithB3Flow } from "./SignInWithB3/SignInWithB3Flow";
|
|
|
12
12
|
export { SignInWithB3Privy } from "./SignInWithB3/SignInWithB3Privy";
|
|
13
13
|
export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep";
|
|
14
14
|
export { getConnectOptionsFromStrategy, isWalletType, type AllowedStrategy } from "./SignInWithB3/utils/signInUtils";
|
|
15
|
+
export { TurnkeyAuthModal } from "./TurnkeyAuthModal";
|
|
15
16
|
export { ManageAccount } from "./ManageAccount/ManageAccount";
|
|
16
17
|
export { Deposit } from "./Deposit/Deposit";
|
|
17
18
|
export { Send } from "./Send/Send";
|
|
@@ -15,6 +15,8 @@ export { SignInWithB3Flow } from "./SignInWithB3/SignInWithB3Flow.js";
|
|
|
15
15
|
export { SignInWithB3Privy } from "./SignInWithB3/SignInWithB3Privy.js";
|
|
16
16
|
export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep.js";
|
|
17
17
|
export { getConnectOptionsFromStrategy, isWalletType } from "./SignInWithB3/utils/signInUtils.js";
|
|
18
|
+
// Turnkey Components
|
|
19
|
+
export { TurnkeyAuthModal } from "./TurnkeyAuthModal.js";
|
|
18
20
|
// ManageAccount Components
|
|
19
21
|
export { ManageAccount } from "./ManageAccount/ManageAccount.js";
|
|
20
22
|
// Deposit Components
|
|
@@ -40,5 +40,6 @@ export { useTokenFromUrl } from "./useTokenFromUrl";
|
|
|
40
40
|
export { useTokenPrice } from "./useTokenPrice";
|
|
41
41
|
export { useTokenPriceWithFallback } from "./useTokenPriceWithFallback";
|
|
42
42
|
export { useTokensFromAddress } from "./useTokensFromAddress";
|
|
43
|
+
export { useTurnkeyAuth } from "./useTurnkeyAuth";
|
|
43
44
|
export { useUnifiedChainSwitchAndExecute } from "./useUnifiedChainSwitchAndExecute";
|
|
44
45
|
export { useURLParams } from "./useURLParams";
|
|
@@ -40,5 +40,6 @@ export { useTokenFromUrl } from "./useTokenFromUrl.js";
|
|
|
40
40
|
export { useTokenPrice } from "./useTokenPrice.js";
|
|
41
41
|
export { useTokenPriceWithFallback } from "./useTokenPriceWithFallback.js";
|
|
42
42
|
export { useTokensFromAddress } from "./useTokensFromAddress.js";
|
|
43
|
+
export { useTurnkeyAuth } from "./useTurnkeyAuth.js";
|
|
43
44
|
export { useUnifiedChainSwitchAndExecute } from "./useUnifiedChainSwitchAndExecute.js";
|
|
44
45
|
export { useURLParams } from "./useURLParams.js";
|
|
@@ -46,6 +46,11 @@ export declare function useAuthentication(partnerId: string): {
|
|
|
46
46
|
fid?: string | undefined;
|
|
47
47
|
};
|
|
48
48
|
}[] | undefined;
|
|
49
|
+
turnkeySubOrgs?: {
|
|
50
|
+
hasDelegatedUser?: boolean | undefined;
|
|
51
|
+
subOrgId: string;
|
|
52
|
+
accounts: Record<string, any>[];
|
|
53
|
+
}[] | undefined;
|
|
49
54
|
_id: string | {};
|
|
50
55
|
userId: string;
|
|
51
56
|
smartAccountAddress: string;
|
|
@@ -54,6 +59,8 @@ export declare function useAuthentication(partnerId: string): {
|
|
|
54
59
|
partnerIds: {
|
|
55
60
|
privyId?: string | undefined;
|
|
56
61
|
thirdwebId?: string | undefined;
|
|
62
|
+
turnkeyId?: string | undefined;
|
|
63
|
+
turnkeyOtpId?: string | undefined;
|
|
57
64
|
};
|
|
58
65
|
} | undefined;
|
|
59
66
|
refetchUser: (wallet?: Wallet) => Promise<import("@feathersjs/authentication").AuthenticationResult>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TurnkeyAuthInitResponse } from "@b3dotfun/b3-api";
|
|
2
|
+
interface UseTurnkeyAuthReturn {
|
|
3
|
+
initiateLogin: (_email: string) => Promise<TurnkeyAuthInitResponse>;
|
|
4
|
+
verifyOtp: (_otpId: string, _otpCode: string) => Promise<{
|
|
5
|
+
user: any;
|
|
6
|
+
}>;
|
|
7
|
+
isLoading: boolean;
|
|
8
|
+
error: string | null;
|
|
9
|
+
clearError: () => void;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Hook for Turnkey email-based OTP authentication
|
|
13
|
+
*
|
|
14
|
+
* Usage:
|
|
15
|
+
* 1. Call initiateLogin(email) → User receives OTP email
|
|
16
|
+
* 2. Call verifyOtp(...) → Verifies OTP and authenticates with b3-api
|
|
17
|
+
* 3. User is authenticated, JWT stored in cookies automatically
|
|
18
|
+
*/
|
|
19
|
+
export declare function useTurnkeyAuth(): UseTurnkeyAuthReturn;
|
|
20
|
+
export {};
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import app from "../../app.js";
|
|
2
|
+
import { useAuthStore } from "../stores/index.js";
|
|
3
|
+
import { useCallback, useState } from "react";
|
|
4
|
+
import { useB3 } from "../components/B3Provider/useB3.js";
|
|
5
|
+
import { debugB3React } from "../../../shared/utils/debug.js";
|
|
6
|
+
const debug = debugB3React("useTurnkeyAuth");
|
|
7
|
+
/**
|
|
8
|
+
* Hook for Turnkey email-based OTP authentication
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* 1. Call initiateLogin(email) → User receives OTP email
|
|
12
|
+
* 2. Call verifyOtp(...) → Verifies OTP and authenticates with b3-api
|
|
13
|
+
* 3. User is authenticated, JWT stored in cookies automatically
|
|
14
|
+
*/
|
|
15
|
+
export function useTurnkeyAuth() {
|
|
16
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
17
|
+
const [error, setError] = useState(null);
|
|
18
|
+
const setIsAuthenticating = useAuthStore(state => state.setIsAuthenticating);
|
|
19
|
+
const setIsAuthenticated = useAuthStore(state => state.setIsAuthenticated);
|
|
20
|
+
const { user } = useB3();
|
|
21
|
+
/**
|
|
22
|
+
* Step 1: Initiate login with email
|
|
23
|
+
* - Calls backend to create sub-org (if needed) and send OTP
|
|
24
|
+
* - Returns otpId to use in verification step
|
|
25
|
+
*/
|
|
26
|
+
const initiateLogin = useCallback(async (email) => {
|
|
27
|
+
setIsLoading(true);
|
|
28
|
+
setError(null);
|
|
29
|
+
setIsAuthenticating(true);
|
|
30
|
+
try {
|
|
31
|
+
if (!user?.userId) {
|
|
32
|
+
throw new Error("User ID is required to initiate Turnkey login.");
|
|
33
|
+
}
|
|
34
|
+
debug(`Initiating login for: ${email}`);
|
|
35
|
+
// Call FeathersJS service to initialize OTP
|
|
36
|
+
const data = await app.service("turnkey-auth").init({ email, userId: user.userId });
|
|
37
|
+
debug(`OTP initialized successfully. OtpId: ${data.otpId}`);
|
|
38
|
+
return data;
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
debug("Error initiating login:", err);
|
|
42
|
+
const errorMessage = err.message || "Failed to send OTP email. Please try again.";
|
|
43
|
+
setError(errorMessage);
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
finally {
|
|
47
|
+
setIsLoading(false);
|
|
48
|
+
setIsAuthenticating(false);
|
|
49
|
+
}
|
|
50
|
+
}, [user, setIsAuthenticating]);
|
|
51
|
+
/**
|
|
52
|
+
* Step 2: Verify OTP and authenticate
|
|
53
|
+
* - Verifies OTP with backend
|
|
54
|
+
* - Gets Turnkey session JWT
|
|
55
|
+
* - Authenticates with b3-api using "turnkey-jwt" strategy
|
|
56
|
+
* - JWT automatically stored in cookies by SDK
|
|
57
|
+
*/
|
|
58
|
+
const verifyOtp = useCallback(async (otpId, otpCode) => {
|
|
59
|
+
setIsLoading(true);
|
|
60
|
+
setError(null);
|
|
61
|
+
setIsAuthenticating(true);
|
|
62
|
+
try {
|
|
63
|
+
debug(`Verifying OTP...`, { userId: user?.userId });
|
|
64
|
+
// Step 1: Verify OTP and get Turnkey session JWT
|
|
65
|
+
const { turnkeySessionJwt } = await app.service("turnkey-auth").verify({
|
|
66
|
+
otpId,
|
|
67
|
+
otpCode,
|
|
68
|
+
});
|
|
69
|
+
debug(`OTP verified! Authenticating with b3-api...`);
|
|
70
|
+
// Step 2: Authenticate with b3-api using Turnkey JWT
|
|
71
|
+
// The SDK will automatically store the b3-api JWT in cookies
|
|
72
|
+
const authResult = await app.authenticate({
|
|
73
|
+
strategy: "turnkey-jwt",
|
|
74
|
+
accessToken: turnkeySessionJwt,
|
|
75
|
+
});
|
|
76
|
+
debug(`Successfully authenticated with b3-api!`, authResult);
|
|
77
|
+
// Update auth store to reflect authenticated state
|
|
78
|
+
setIsAuthenticated(true);
|
|
79
|
+
// Return user data
|
|
80
|
+
return {
|
|
81
|
+
user: authResult.user,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
debug("Error verifying OTP:", err);
|
|
86
|
+
const errorMessage = err.message || "Failed to verify OTP. Please try again.";
|
|
87
|
+
setError(errorMessage);
|
|
88
|
+
setIsAuthenticated(false);
|
|
89
|
+
throw err;
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
setIsLoading(false);
|
|
93
|
+
setIsAuthenticating(false);
|
|
94
|
+
}
|
|
95
|
+
}, [user, setIsAuthenticating, setIsAuthenticated]);
|
|
96
|
+
const clearError = useCallback(() => {
|
|
97
|
+
setError(null);
|
|
98
|
+
}, []);
|
|
99
|
+
return {
|
|
100
|
+
initiateLogin,
|
|
101
|
+
verifyOtp,
|
|
102
|
+
isLoading,
|
|
103
|
+
error,
|
|
104
|
+
clearError,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
@@ -41,6 +41,11 @@ export declare function useUserQuery(): {
|
|
|
41
41
|
fid?: string | undefined;
|
|
42
42
|
};
|
|
43
43
|
}[] | undefined;
|
|
44
|
+
turnkeySubOrgs?: {
|
|
45
|
+
hasDelegatedUser?: boolean | undefined;
|
|
46
|
+
subOrgId: string;
|
|
47
|
+
accounts: Record<string, any>[];
|
|
48
|
+
}[] | undefined;
|
|
44
49
|
_id: string | {};
|
|
45
50
|
userId: string;
|
|
46
51
|
smartAccountAddress: string;
|
|
@@ -49,6 +54,8 @@ export declare function useUserQuery(): {
|
|
|
49
54
|
partnerIds: {
|
|
50
55
|
privyId?: string | undefined;
|
|
51
56
|
thirdwebId?: string | undefined;
|
|
57
|
+
turnkeyId?: string | undefined;
|
|
58
|
+
turnkeyOtpId?: string | undefined;
|
|
52
59
|
};
|
|
53
60
|
} | undefined;
|
|
54
61
|
setUser: (newUser?: Users) => void;
|
|
@@ -27,6 +27,8 @@ interface AuthState {
|
|
|
27
27
|
setIsAuthenticating: (isAuthenticating: boolean) => void;
|
|
28
28
|
hasStartedConnecting: boolean;
|
|
29
29
|
setHasStartedConnecting: (hasStartedConnecting: boolean) => void;
|
|
30
|
+
justCompletedLogin: boolean;
|
|
31
|
+
setJustCompletedLogin: (justCompletedLogin: boolean) => void;
|
|
30
32
|
}
|
|
31
33
|
export declare const useAuthStore: import("zustand").UseBoundStore<import("zustand").StoreApi<AuthState>>;
|
|
32
34
|
export {};
|
|
@@ -39,4 +39,6 @@ export const useAuthStore = create(set => ({
|
|
|
39
39
|
setIsAuthenticating: isAuthenticating => set({ isAuthenticating: isAuthenticating }),
|
|
40
40
|
hasStartedConnecting: false,
|
|
41
41
|
setHasStartedConnecting: hasStartedConnecting => set({ hasStartedConnecting }),
|
|
42
|
+
justCompletedLogin: false,
|
|
43
|
+
setJustCompletedLogin: justCompletedLogin => set({ justCompletedLogin }),
|
|
42
44
|
}));
|
|
@@ -10,6 +10,8 @@ import { Account } from "thirdweb/wallets";
|
|
|
10
10
|
interface BaseModalProps {
|
|
11
11
|
/** Whether to show a back button in the modal header */
|
|
12
12
|
showBackButton?: boolean;
|
|
13
|
+
/** Whether the modal can be closed by clicking outside or pressing escape. Defaults to true */
|
|
14
|
+
closable?: boolean;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Props for the Sign In With B3 modal
|
|
@@ -39,6 +41,24 @@ export interface SignInWithB3ModalProps extends BaseModalProps {
|
|
|
39
41
|
/** Whether to show the signers enabled modal */
|
|
40
42
|
signersEnabled?: boolean;
|
|
41
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* Props for the Turnkey Authentication modal
|
|
46
|
+
* Handles Turnkey email/OTP authentication flow
|
|
47
|
+
*/
|
|
48
|
+
export interface TurnkeyAuthModalProps extends BaseModalProps {
|
|
49
|
+
/** Modal type identifier */
|
|
50
|
+
type: "turnkeyAuth";
|
|
51
|
+
/** Callback function called when authentication is successful */
|
|
52
|
+
onSuccess: (_user: any) => void;
|
|
53
|
+
/** Callback function called when modal is closed */
|
|
54
|
+
onClose: () => void;
|
|
55
|
+
/** Initial email to pre-fill */
|
|
56
|
+
initialEmail?: string;
|
|
57
|
+
/** Whether to skip directly to OTP step */
|
|
58
|
+
skipToOtp?: boolean;
|
|
59
|
+
/** Whether the modal can be closed - defaults to false for Turnkey */
|
|
60
|
+
closable?: boolean;
|
|
61
|
+
}
|
|
42
62
|
/**
|
|
43
63
|
* Props for the Request Permissions modal
|
|
44
64
|
* Used to request permission for session keys to interact with contracts
|
|
@@ -451,7 +471,7 @@ export interface AnySpendCollectorClubPurchaseProps extends BaseModalProps {
|
|
|
451
471
|
/**
|
|
452
472
|
* Union type of all possible modal content types
|
|
453
473
|
*/
|
|
454
|
-
export type ModalContentType = SignInWithB3ModalProps | RequestPermissionsModalProps | ManageAccountModalProps | AnySpendModalProps | AnyspendOrderDetailsProps | AnySpendNftProps | AnySpendJoinTournamentProps | AnySpendFundTournamentProps | AnySpendOrderHistoryProps | AnySpendStakeB3Props | AnySpendStakeB3ExactInProps | AnySpendStakeUpsideProps | AnySpendStakeUpsideExactInProps | AnySpendDepositUpsideProps | AnySpendBuySpinProps | AnySpendSignatureMintProps | AnySpendBondKitProps | LinkAccountModalProps | LinkNewAccountModalProps | AnySpendDepositHypeProps | AvatarEditorModalProps | DepositModalProps | SendModalProps | NotificationsModalProps | AnySpendCollectorClubPurchaseProps;
|
|
474
|
+
export type ModalContentType = SignInWithB3ModalProps | TurnkeyAuthModalProps | RequestPermissionsModalProps | ManageAccountModalProps | AnySpendModalProps | AnyspendOrderDetailsProps | AnySpendNftProps | AnySpendJoinTournamentProps | AnySpendFundTournamentProps | AnySpendOrderHistoryProps | AnySpendStakeB3Props | AnySpendStakeB3ExactInProps | AnySpendStakeUpsideProps | AnySpendStakeUpsideExactInProps | AnySpendDepositUpsideProps | AnySpendBuySpinProps | AnySpendSignatureMintProps | AnySpendBondKitProps | LinkAccountModalProps | LinkNewAccountModalProps | AnySpendDepositHypeProps | AvatarEditorModalProps | DepositModalProps | SendModalProps | NotificationsModalProps | AnySpendCollectorClubPurchaseProps;
|
|
455
475
|
/**
|
|
456
476
|
* State interface for the modal store
|
|
457
477
|
*/
|