@b3dotfun/sdk 0.1.69-alpha.23 → 0.1.69-alpha.24
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/SignInWithB3/BetterAuthSignIn.d.ts +6 -1
- package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthSignIn.js +2 -2
- package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.d.ts +37 -0
- package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.js +85 -0
- package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.d.ts +1 -1
- package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +2 -2
- package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.d.ts +3 -1
- package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.js +2 -2
- package/dist/cjs/global-account/react/components/index.d.ts +1 -0
- package/dist/cjs/global-account/react/components/index.js +5 -3
- package/dist/cjs/global-account/react/hooks/useBetterAuth.d.ts +1 -1
- package/dist/cjs/global-account/react/hooks/useBetterAuth.js +5 -4
- package/dist/cjs/global-account/react/stores/useModalStore.d.ts +2 -0
- package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthSignIn.d.ts +6 -1
- package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthSignIn.js +2 -2
- package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.d.ts +37 -0
- package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.js +82 -0
- package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.d.ts +1 -1
- package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +2 -2
- package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.d.ts +3 -1
- package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.js +2 -2
- package/dist/esm/global-account/react/components/index.d.ts +1 -0
- package/dist/esm/global-account/react/components/index.js +1 -0
- package/dist/esm/global-account/react/hooks/useBetterAuth.d.ts +1 -1
- package/dist/esm/global-account/react/hooks/useBetterAuth.js +5 -4
- package/dist/esm/global-account/react/stores/useModalStore.d.ts +2 -0
- package/dist/styles/index.css +1 -1
- package/dist/types/global-account/react/components/SignInWithB3/BetterAuthSignIn.d.ts +6 -1
- package/dist/types/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.d.ts +37 -0
- package/dist/types/global-account/react/components/SignInWithB3/SignInWithB3Flow.d.ts +1 -1
- package/dist/types/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.d.ts +3 -1
- package/dist/types/global-account/react/components/index.d.ts +1 -0
- package/dist/types/global-account/react/hooks/useBetterAuth.d.ts +1 -1
- package/dist/types/global-account/react/stores/useModalStore.d.ts +2 -0
- package/package.json +1 -1
- package/src/global-account/react/components/SignInWithB3/BetterAuthSignIn.tsx +7 -1
- package/src/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.tsx +155 -0
- package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +8 -1
- package/src/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.tsx +4 -2
- package/src/global-account/react/components/index.ts +5 -0
- package/src/global-account/react/hooks/useBetterAuth.ts +5 -4
- package/src/global-account/react/stores/useModalStore.ts +2 -0
|
@@ -8,6 +8,7 @@ export { useB3Config } from "./B3Provider/useB3Config";
|
|
|
8
8
|
export { StyleRoot } from "./StyleRoot";
|
|
9
9
|
export { BetterAuthResetPassword, type BetterAuthResetPasswordProps } from "./SignInWithB3/BetterAuthResetPassword";
|
|
10
10
|
export { BetterAuthSignIn, type BetterAuthSignInProps } from "./SignInWithB3/BetterAuthSignIn";
|
|
11
|
+
export { BetterAuthVerifyEmail, type BetterAuthVerifyEmailProps, type BetterAuthVerifyEmailState, } from "./SignInWithB3/BetterAuthVerifyEmail";
|
|
11
12
|
export { AuthButton } from "./SignInWithB3/components/AuthButton";
|
|
12
13
|
export { PermissionItem } from "./SignInWithB3/components/PermissionItem";
|
|
13
14
|
export { WalletRow } from "./SignInWithB3/components/WalletRow";
|
|
@@ -13,7 +13,7 @@ export declare class EmailVerificationRequiredError extends Error {
|
|
|
13
13
|
*/
|
|
14
14
|
export declare function useBetterAuth(): {
|
|
15
15
|
signInWithEmail: (email: string, password: string) => Promise<import("@feathersjs/authentication").AuthenticationResult>;
|
|
16
|
-
signUpWithEmail: (email: string, password: string, name: string) => Promise<import("@feathersjs/authentication").AuthenticationResult>;
|
|
16
|
+
signUpWithEmail: (email: string, password: string, name: string, verifyCallbackURL?: string) => Promise<import("@feathersjs/authentication").AuthenticationResult>;
|
|
17
17
|
signInWithSocial: (provider: BetterAuthSocialProvider) => Promise<void>;
|
|
18
18
|
requestPasswordReset: (email: string, redirectTo?: string) => Promise<{
|
|
19
19
|
data: {
|
|
@@ -41,6 +41,8 @@ export interface SignInWithB3ModalProps extends BaseModalProps {
|
|
|
41
41
|
source?: "signInWithB3Button" | "requestPermissions";
|
|
42
42
|
/** Whether to show the signers enabled modal */
|
|
43
43
|
signersEnabled?: boolean;
|
|
44
|
+
/** URL Better Auth redirects to after server-side email verification. */
|
|
45
|
+
verifyEmailRedirectTo?: string;
|
|
44
46
|
}
|
|
45
47
|
/**
|
|
46
48
|
* Props for the Request Permissions modal
|
package/package.json
CHANGED
|
@@ -33,6 +33,11 @@ export interface BetterAuthSignInProps {
|
|
|
33
33
|
showEmail?: boolean;
|
|
34
34
|
/** URL to redirect to after password reset link is clicked. Token is appended as ?token=... */
|
|
35
35
|
passwordResetRedirectTo?: string;
|
|
36
|
+
/**
|
|
37
|
+
* URL Better Auth redirects to after server-side email verification. Render
|
|
38
|
+
* `BetterAuthVerifyEmail` at this route so the user gets a confirmation page.
|
|
39
|
+
*/
|
|
40
|
+
verifyEmailRedirectTo?: string;
|
|
36
41
|
/** Called after successful authentication */
|
|
37
42
|
onSuccess?: () => void;
|
|
38
43
|
/** Called on authentication error */
|
|
@@ -61,6 +66,7 @@ export function BetterAuthSignIn({
|
|
|
61
66
|
socialProviders = DEFAULT_SOCIAL_PROVIDERS.map(p => p.id),
|
|
62
67
|
showEmail = true,
|
|
63
68
|
passwordResetRedirectTo,
|
|
69
|
+
verifyEmailRedirectTo,
|
|
64
70
|
onSuccess,
|
|
65
71
|
onError,
|
|
66
72
|
className,
|
|
@@ -153,7 +159,7 @@ export function BetterAuthSignIn({
|
|
|
153
159
|
setError(null);
|
|
154
160
|
|
|
155
161
|
if (mode === "sign-up") {
|
|
156
|
-
await signUpWithEmail(normalizedEmail, password, name.trim());
|
|
162
|
+
await signUpWithEmail(normalizedEmail, password, name.trim(), verifyEmailRedirectTo);
|
|
157
163
|
} else {
|
|
158
164
|
await signInWithEmail(normalizedEmail, password);
|
|
159
165
|
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { Button } from "@b3dotfun/sdk/global-account/react";
|
|
2
|
+
import { debugB3React } from "@b3dotfun/sdk/shared/utils/debug";
|
|
3
|
+
|
|
4
|
+
const debug = debugB3React("BetterAuthVerifyEmail");
|
|
5
|
+
|
|
6
|
+
export type BetterAuthVerifyEmailState = "success" | "expired" | "invalid" | "already-verified" | "error";
|
|
7
|
+
|
|
8
|
+
export interface BetterAuthVerifyEmailProps {
|
|
9
|
+
/**
|
|
10
|
+
* Error code from the callback URL's `?error=` query param. Pass `null` /
|
|
11
|
+
* `undefined` when the user landed here cleanly (successful verification).
|
|
12
|
+
* Better Auth appends this param when server-side verification fails.
|
|
13
|
+
*/
|
|
14
|
+
errorCode?: string | null;
|
|
15
|
+
/** Called when the user clicks the "Go to sign in" button. */
|
|
16
|
+
onGoToSignIn?: () => void;
|
|
17
|
+
/** Fallback href used when `onGoToSignIn` is not provided. Defaults to "/login". */
|
|
18
|
+
signInHref?: string;
|
|
19
|
+
/** Optional override for the success headline. */
|
|
20
|
+
successTitle?: string;
|
|
21
|
+
/** Optional override for the success body text. */
|
|
22
|
+
successMessage?: string;
|
|
23
|
+
/** Optional class name for the root container. */
|
|
24
|
+
className?: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function classifyError(code: string | null | undefined): BetterAuthVerifyEmailState {
|
|
28
|
+
if (!code) return "success";
|
|
29
|
+
const normalized = code.toLowerCase();
|
|
30
|
+
|
|
31
|
+
// Exact matches for Better Auth's documented verification error codes.
|
|
32
|
+
if (normalized === "expired_token") return "expired";
|
|
33
|
+
if (normalized === "invalid_token") return "invalid";
|
|
34
|
+
if (normalized === "already_verified" || normalized === "email_already_verified") return "already-verified";
|
|
35
|
+
|
|
36
|
+
// Loose fallbacks for close variants. Order matters — check "already" before
|
|
37
|
+
// "verified" so `email_already_verified` maps to already-verified, not invalid.
|
|
38
|
+
if (normalized.includes("expired")) return "expired";
|
|
39
|
+
if (normalized.includes("already")) return "already-verified";
|
|
40
|
+
if (normalized.includes("invalid")) return "invalid";
|
|
41
|
+
return "error";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const COPY: Record<BetterAuthVerifyEmailState, { title: string; message: string }> = {
|
|
45
|
+
success: {
|
|
46
|
+
title: "Email verified",
|
|
47
|
+
message: "Your email is confirmed. You can now sign in to your account.",
|
|
48
|
+
},
|
|
49
|
+
expired: {
|
|
50
|
+
title: "Link expired",
|
|
51
|
+
message: "This verification link has expired. Request a new one from the sign-in page.",
|
|
52
|
+
},
|
|
53
|
+
invalid: {
|
|
54
|
+
title: "Invalid link",
|
|
55
|
+
message: "This verification link is invalid or has already been used. Try signing in or request a new link.",
|
|
56
|
+
},
|
|
57
|
+
"already-verified": {
|
|
58
|
+
title: "Already verified",
|
|
59
|
+
message: "Your email was already confirmed. You can sign in now.",
|
|
60
|
+
},
|
|
61
|
+
error: {
|
|
62
|
+
title: "Verification failed",
|
|
63
|
+
message: "We couldn't verify your email. Request a new link from the sign-in page.",
|
|
64
|
+
},
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Standalone email-verification confirmation page. Render on the route you
|
|
69
|
+
* set as `callbackURL` when calling `betterAuthClient.sendVerificationEmail`
|
|
70
|
+
* (or the `verifyCallbackURL` arg on `useBetterAuth().signUpWithEmail`).
|
|
71
|
+
*
|
|
72
|
+
* Better Auth verifies the token server-side before redirecting here. This
|
|
73
|
+
* component only displays the outcome based on the `?error=` query param.
|
|
74
|
+
*
|
|
75
|
+
* Usage:
|
|
76
|
+
* ```tsx
|
|
77
|
+
* const error = new URLSearchParams(window.location.search).get("error");
|
|
78
|
+
* <BetterAuthVerifyEmail
|
|
79
|
+
* errorCode={error}
|
|
80
|
+
* onGoToSignIn={() => router.push("/login")}
|
|
81
|
+
* />
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
export function BetterAuthVerifyEmail({
|
|
85
|
+
errorCode,
|
|
86
|
+
onGoToSignIn,
|
|
87
|
+
signInHref = "/login",
|
|
88
|
+
successTitle,
|
|
89
|
+
successMessage,
|
|
90
|
+
className,
|
|
91
|
+
}: BetterAuthVerifyEmailProps) {
|
|
92
|
+
const state = classifyError(errorCode);
|
|
93
|
+
const isSuccess = state === "success" || state === "already-verified";
|
|
94
|
+
const copy = COPY[state];
|
|
95
|
+
const title = isSuccess && successTitle ? successTitle : copy.title;
|
|
96
|
+
const message = isSuccess && successMessage ? successMessage : copy.message;
|
|
97
|
+
|
|
98
|
+
debug("Rendering verify-email state", { state, errorCode });
|
|
99
|
+
|
|
100
|
+
const handleClick = () => {
|
|
101
|
+
if (onGoToSignIn) {
|
|
102
|
+
onGoToSignIn();
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (typeof window !== "undefined") {
|
|
106
|
+
window.location.href = signInHref;
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div className={`w-full max-w-[400px] px-6 ${className || ""}`}>
|
|
112
|
+
<div className="space-y-6 text-center">
|
|
113
|
+
<div
|
|
114
|
+
className={`mx-auto flex h-12 w-12 items-center justify-center rounded-full ${
|
|
115
|
+
isSuccess ? "bg-green-100" : "bg-red-100"
|
|
116
|
+
}`}
|
|
117
|
+
>
|
|
118
|
+
{isSuccess ? (
|
|
119
|
+
<svg
|
|
120
|
+
className="h-6 w-6 text-green-600"
|
|
121
|
+
fill="none"
|
|
122
|
+
viewBox="0 0 24 24"
|
|
123
|
+
stroke="currentColor"
|
|
124
|
+
aria-hidden="true"
|
|
125
|
+
>
|
|
126
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
|
127
|
+
</svg>
|
|
128
|
+
) : (
|
|
129
|
+
<svg
|
|
130
|
+
className="h-6 w-6 text-red-600"
|
|
131
|
+
fill="none"
|
|
132
|
+
viewBox="0 0 24 24"
|
|
133
|
+
stroke="currentColor"
|
|
134
|
+
aria-hidden="true"
|
|
135
|
+
>
|
|
136
|
+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M6 18L18 6M6 6l12 12" />
|
|
137
|
+
</svg>
|
|
138
|
+
)}
|
|
139
|
+
</div>
|
|
140
|
+
|
|
141
|
+
<div>
|
|
142
|
+
<h1 className="text-[28px] font-semibold tracking-tight text-gray-900 dark:text-gray-100">{title}</h1>
|
|
143
|
+
<p className="mt-3 text-[15px] text-gray-500 dark:text-gray-400">{message}</p>
|
|
144
|
+
</div>
|
|
145
|
+
|
|
146
|
+
<Button
|
|
147
|
+
onClick={handleClick}
|
|
148
|
+
className="h-11 w-full bg-gray-900 text-[15px] font-medium text-white hover:bg-gray-800 dark:bg-white dark:text-gray-900 dark:hover:bg-gray-100"
|
|
149
|
+
>
|
|
150
|
+
{isSuccess ? "Go to sign in" : "Back to sign in"}
|
|
151
|
+
</Button>
|
|
152
|
+
</div>
|
|
153
|
+
</div>
|
|
154
|
+
);
|
|
155
|
+
}
|
|
@@ -34,6 +34,7 @@ export function SignInWithB3Flow({
|
|
|
34
34
|
closeAfterLogin = false,
|
|
35
35
|
source = "signInWithB3Button",
|
|
36
36
|
signersEnabled = false,
|
|
37
|
+
verifyEmailRedirectTo,
|
|
37
38
|
}: SignInWithB3ModalProps) {
|
|
38
39
|
const { automaticallySetFirstEoa, authStrategy } = useB3Config();
|
|
39
40
|
// skipAutoConnect: this component intentionally logs out on mount to show a fresh login screen.
|
|
@@ -292,7 +293,13 @@ export function SignInWithB3Flow({
|
|
|
292
293
|
// Better Auth manages its own loading/verification states internally.
|
|
293
294
|
// Don't gate on isAuthenticating — it would unmount the component
|
|
294
295
|
// and lose verification state when setIsAuthenticating(false) fires.
|
|
295
|
-
content =
|
|
296
|
+
content = (
|
|
297
|
+
<LoginStepBetterAuth
|
|
298
|
+
onSuccess={() => handleLoginSuccess({} as Account)}
|
|
299
|
+
onError={onError}
|
|
300
|
+
verifyEmailRedirectTo={verifyEmailRedirectTo}
|
|
301
|
+
/>
|
|
302
|
+
);
|
|
296
303
|
} else if (!readyToShowLogin || isAuthenticating || isFetchingSigners) {
|
|
297
304
|
content = (
|
|
298
305
|
<LoginStepContainer partnerId={partnerId}>
|
|
@@ -23,9 +23,11 @@ const SOCIAL_PROVIDERS: { id: BetterAuthSocialProvider; label: string }[] = [
|
|
|
23
23
|
interface LoginStepBetterAuthProps {
|
|
24
24
|
onSuccess?: () => void;
|
|
25
25
|
onError?: (error: Error) => Promise<void>;
|
|
26
|
+
/** URL Better Auth redirects to after server-side email verification. */
|
|
27
|
+
verifyEmailRedirectTo?: string;
|
|
26
28
|
}
|
|
27
29
|
|
|
28
|
-
export function LoginStepBetterAuth({ onSuccess, onError }: LoginStepBetterAuthProps) {
|
|
30
|
+
export function LoginStepBetterAuth({ onSuccess, onError, verifyEmailRedirectTo }: LoginStepBetterAuthProps) {
|
|
29
31
|
const { partnerId } = useB3Config();
|
|
30
32
|
const { signInWithEmail, signUpWithEmail, signInWithSocial, requestPasswordReset } = useBetterAuth();
|
|
31
33
|
|
|
@@ -63,7 +65,7 @@ export function LoginStepBetterAuth({ onSuccess, onError }: LoginStepBetterAuthP
|
|
|
63
65
|
|
|
64
66
|
if (mode === "sign-up") {
|
|
65
67
|
debug("Signing up", { email: normalizedEmail, name: name.trim() });
|
|
66
|
-
await signUpWithEmail(normalizedEmail, password, name.trim());
|
|
68
|
+
await signUpWithEmail(normalizedEmail, password, name.trim(), verifyEmailRedirectTo);
|
|
67
69
|
} else {
|
|
68
70
|
debug("Signing in", { email: normalizedEmail });
|
|
69
71
|
await signInWithEmail(normalizedEmail, password);
|
|
@@ -12,6 +12,11 @@ export { StyleRoot } from "./StyleRoot";
|
|
|
12
12
|
// SignInWithB3 Components
|
|
13
13
|
export { BetterAuthResetPassword, type BetterAuthResetPasswordProps } from "./SignInWithB3/BetterAuthResetPassword";
|
|
14
14
|
export { BetterAuthSignIn, type BetterAuthSignInProps } from "./SignInWithB3/BetterAuthSignIn";
|
|
15
|
+
export {
|
|
16
|
+
BetterAuthVerifyEmail,
|
|
17
|
+
type BetterAuthVerifyEmailProps,
|
|
18
|
+
type BetterAuthVerifyEmailState,
|
|
19
|
+
} from "./SignInWithB3/BetterAuthVerifyEmail";
|
|
15
20
|
export { AuthButton } from "./SignInWithB3/components/AuthButton";
|
|
16
21
|
export { PermissionItem } from "./SignInWithB3/components/PermissionItem";
|
|
17
22
|
export { WalletRow } from "./SignInWithB3/components/WalletRow";
|
|
@@ -87,7 +87,7 @@ export function useBetterAuth() {
|
|
|
87
87
|
);
|
|
88
88
|
|
|
89
89
|
const signUpWithEmail = useCallback(
|
|
90
|
-
async (email: string, password: string, name: string) => {
|
|
90
|
+
async (email: string, password: string, name: string, verifyCallbackURL?: string) => {
|
|
91
91
|
debug("Signing up with email", { email, name });
|
|
92
92
|
setHasStartedConnecting(true);
|
|
93
93
|
setIsAuthenticating(true);
|
|
@@ -101,11 +101,12 @@ export function useBetterAuth() {
|
|
|
101
101
|
|
|
102
102
|
const token = result.data?.token;
|
|
103
103
|
if (!token) {
|
|
104
|
-
// requireEmailVerification is enabled — send verification email
|
|
105
|
-
//
|
|
104
|
+
// requireEmailVerification is enabled — send verification email with
|
|
105
|
+
// a callbackURL Better Auth redirects to after server-side verify.
|
|
106
|
+
// Pass verifyCallbackURL to land on a dedicated confirmation page.
|
|
106
107
|
await betterAuthClient.sendVerificationEmail({
|
|
107
108
|
email,
|
|
108
|
-
callbackURL: `${window.location.origin}?authStrategy=better-auth`,
|
|
109
|
+
callbackURL: verifyCallbackURL || `${window.location.origin}?authStrategy=better-auth`,
|
|
109
110
|
});
|
|
110
111
|
throw new EmailVerificationRequiredError();
|
|
111
112
|
}
|
|
@@ -44,6 +44,8 @@ export interface SignInWithB3ModalProps extends BaseModalProps {
|
|
|
44
44
|
source?: "signInWithB3Button" | "requestPermissions";
|
|
45
45
|
/** Whether to show the signers enabled modal */
|
|
46
46
|
signersEnabled?: boolean;
|
|
47
|
+
/** URL Better Auth redirects to after server-side email verification. */
|
|
48
|
+
verifyEmailRedirectTo?: string;
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
/**
|