@b3dotfun/sdk 0.1.69-test.0 → 0.1.70-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 (190) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpend.d.ts +2 -0
  2. package/dist/cjs/anyspend/react/components/AnySpend.js +12 -4
  3. package/dist/cjs/anyspend/react/components/AnySpendCollectorClubPurchase.d.ts +5 -1
  4. package/dist/cjs/anyspend/react/components/AnySpendCollectorClubPurchase.js +2 -2
  5. package/dist/cjs/anyspend/react/components/AnySpendCustom.d.ts +2 -0
  6. package/dist/cjs/anyspend/react/components/AnySpendCustom.js +7 -3
  7. package/dist/cjs/anyspend/react/components/AnySpendDeposit.d.ts +3 -1
  8. package/dist/cjs/anyspend/react/components/AnySpendDeposit.js +3 -3
  9. package/dist/cjs/anyspend/react/components/AnySpendNFT.d.ts +3 -1
  10. package/dist/cjs/anyspend/react/components/AnySpendNFT.js +2 -2
  11. package/dist/cjs/anyspend/react/components/AnySpendStakeUpside.d.ts +3 -1
  12. package/dist/cjs/anyspend/react/components/AnySpendStakeUpside.js +2 -2
  13. package/dist/cjs/anyspend/react/components/checkout/AnySpendCheckout.js +6 -5
  14. package/dist/cjs/anyspend/react/components/checkout/CartItemRow.d.ts +2 -1
  15. package/dist/cjs/anyspend/react/components/checkout/CartSummary.d.ts +6 -4
  16. package/dist/cjs/anyspend/react/components/checkout/CartSummary.js +13 -11
  17. package/dist/cjs/anyspend/react/components/checkout/CheckoutCartPanel.d.ts +3 -1
  18. package/dist/cjs/anyspend/react/components/checkout/CheckoutCartPanel.js +5 -4
  19. package/dist/cjs/anyspend/react/components/checkout/CheckoutFormPanel.d.ts +3 -1
  20. package/dist/cjs/anyspend/react/components/checkout/CheckoutFormPanel.js +2 -2
  21. package/dist/cjs/anyspend/react/components/checkout/DiscountCodeInput.d.ts +3 -1
  22. package/dist/cjs/anyspend/react/components/checkout/DiscountCodeInput.js +3 -6
  23. package/dist/cjs/anyspend/react/components/checkout/PriceSkeleton.d.ts +5 -0
  24. package/dist/cjs/anyspend/react/components/checkout/PriceSkeleton.js +9 -0
  25. package/dist/cjs/anyspend/react/components/checkout/ShippingSelector.d.ts +3 -1
  26. package/dist/cjs/anyspend/react/components/checkout/ShippingSelector.js +3 -2
  27. package/dist/cjs/global-account/react/components/AvatarEditor/AvatarEditor.js +3 -1
  28. package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +5 -1
  29. package/dist/cjs/global-account/react/components/B3Provider/B3ConfigProvider.js +2 -1
  30. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +17 -1
  31. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +3 -2
  32. package/dist/cjs/global-account/react/components/B3Provider/BetterAuthClientProvider.d.ts +17 -0
  33. package/dist/cjs/global-account/react/components/B3Provider/BetterAuthClientProvider.js +31 -0
  34. package/dist/cjs/global-account/react/components/B3Provider/BetterAuthProvider.js +6 -5
  35. package/dist/cjs/global-account/react/components/ManageAccount/BottomNavigation.js +4 -2
  36. package/dist/cjs/global-account/react/components/ManageAccount/Header.js +36 -4
  37. package/dist/cjs/global-account/react/components/ManageAccount/HomeContent.js +4 -1
  38. package/dist/cjs/global-account/react/components/ManageAccount/ManageAccount.js +6 -0
  39. package/dist/cjs/global-account/react/components/ManageAccount/ProfileSection.js +5 -3
  40. package/dist/cjs/global-account/react/components/ManageAccount/SettingsContent.js +3 -1
  41. package/dist/cjs/global-account/react/components/ManageAccount/SettingsProfileCard.js +25 -14
  42. package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthResetPassword.js +3 -2
  43. package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthSignIn.d.ts +6 -1
  44. package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthSignIn.js +15 -5
  45. package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.d.ts +37 -0
  46. package/dist/cjs/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.js +85 -0
  47. package/dist/cjs/global-account/react/components/SignInWithB3/SignIn.js +14 -4
  48. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.d.ts +1 -1
  49. package/dist/cjs/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +2 -2
  50. package/dist/cjs/global-account/react/components/SignInWithB3/components/PasswordInput.d.ts +10 -0
  51. package/dist/cjs/global-account/react/components/SignInWithB3/components/PasswordInput.js +10 -0
  52. package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.d.ts +3 -1
  53. package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.js +8 -5
  54. package/dist/cjs/global-account/react/components/UserAvatar/UserAvatar.d.ts +18 -0
  55. package/dist/cjs/global-account/react/components/UserAvatar/UserAvatar.js +27 -0
  56. package/dist/cjs/global-account/react/components/index.d.ts +3 -0
  57. package/dist/cjs/global-account/react/components/index.js +10 -3
  58. package/dist/cjs/global-account/react/hooks/useBetterAuth.d.ts +1 -1
  59. package/dist/cjs/global-account/react/hooks/useBetterAuth.js +19 -17
  60. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +4 -0
  61. package/dist/cjs/shared/constants/index.d.ts +1 -0
  62. package/dist/cjs/shared/constants/index.js +2 -1
  63. package/dist/esm/anyspend/react/components/AnySpend.d.ts +2 -0
  64. package/dist/esm/anyspend/react/components/AnySpend.js +12 -4
  65. package/dist/esm/anyspend/react/components/AnySpendCollectorClubPurchase.d.ts +5 -1
  66. package/dist/esm/anyspend/react/components/AnySpendCollectorClubPurchase.js +2 -2
  67. package/dist/esm/anyspend/react/components/AnySpendCustom.d.ts +2 -0
  68. package/dist/esm/anyspend/react/components/AnySpendCustom.js +7 -3
  69. package/dist/esm/anyspend/react/components/AnySpendDeposit.d.ts +3 -1
  70. package/dist/esm/anyspend/react/components/AnySpendDeposit.js +3 -3
  71. package/dist/esm/anyspend/react/components/AnySpendNFT.d.ts +3 -1
  72. package/dist/esm/anyspend/react/components/AnySpendNFT.js +2 -2
  73. package/dist/esm/anyspend/react/components/AnySpendStakeUpside.d.ts +3 -1
  74. package/dist/esm/anyspend/react/components/AnySpendStakeUpside.js +2 -2
  75. package/dist/esm/anyspend/react/components/checkout/AnySpendCheckout.js +6 -5
  76. package/dist/esm/anyspend/react/components/checkout/CartItemRow.d.ts +2 -1
  77. package/dist/esm/anyspend/react/components/checkout/CartSummary.d.ts +6 -4
  78. package/dist/esm/anyspend/react/components/checkout/CartSummary.js +13 -11
  79. package/dist/esm/anyspend/react/components/checkout/CheckoutCartPanel.d.ts +3 -1
  80. package/dist/esm/anyspend/react/components/checkout/CheckoutCartPanel.js +5 -4
  81. package/dist/esm/anyspend/react/components/checkout/CheckoutFormPanel.d.ts +3 -1
  82. package/dist/esm/anyspend/react/components/checkout/CheckoutFormPanel.js +2 -2
  83. package/dist/esm/anyspend/react/components/checkout/DiscountCodeInput.d.ts +3 -1
  84. package/dist/esm/anyspend/react/components/checkout/DiscountCodeInput.js +3 -6
  85. package/dist/esm/anyspend/react/components/checkout/PriceSkeleton.d.ts +5 -0
  86. package/dist/esm/anyspend/react/components/checkout/PriceSkeleton.js +6 -0
  87. package/dist/esm/anyspend/react/components/checkout/ShippingSelector.d.ts +3 -1
  88. package/dist/esm/anyspend/react/components/checkout/ShippingSelector.js +3 -2
  89. package/dist/esm/global-account/react/components/AvatarEditor/AvatarEditor.js +3 -1
  90. package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +5 -1
  91. package/dist/esm/global-account/react/components/B3Provider/B3ConfigProvider.js +2 -1
  92. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +17 -1
  93. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +3 -2
  94. package/dist/esm/global-account/react/components/B3Provider/BetterAuthClientProvider.d.ts +17 -0
  95. package/dist/esm/global-account/react/components/B3Provider/BetterAuthClientProvider.js +27 -0
  96. package/dist/esm/global-account/react/components/B3Provider/BetterAuthProvider.js +4 -3
  97. package/dist/esm/global-account/react/components/ManageAccount/BottomNavigation.js +5 -3
  98. package/dist/esm/global-account/react/components/ManageAccount/Header.js +37 -5
  99. package/dist/esm/global-account/react/components/ManageAccount/HomeContent.js +4 -1
  100. package/dist/esm/global-account/react/components/ManageAccount/ManageAccount.js +7 -1
  101. package/dist/esm/global-account/react/components/ManageAccount/ProfileSection.js +6 -4
  102. package/dist/esm/global-account/react/components/ManageAccount/SettingsContent.js +5 -3
  103. package/dist/esm/global-account/react/components/ManageAccount/SettingsProfileCard.js +25 -14
  104. package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthResetPassword.js +4 -3
  105. package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthSignIn.d.ts +6 -1
  106. package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthSignIn.js +16 -6
  107. package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.d.ts +37 -0
  108. package/dist/esm/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.js +82 -0
  109. package/dist/esm/global-account/react/components/SignInWithB3/SignIn.js +15 -5
  110. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.d.ts +1 -1
  111. package/dist/esm/global-account/react/components/SignInWithB3/SignInWithB3Flow.js +2 -2
  112. package/dist/esm/global-account/react/components/SignInWithB3/components/PasswordInput.d.ts +10 -0
  113. package/dist/esm/global-account/react/components/SignInWithB3/components/PasswordInput.js +7 -0
  114. package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.d.ts +3 -1
  115. package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.js +8 -5
  116. package/dist/esm/global-account/react/components/UserAvatar/UserAvatar.d.ts +18 -0
  117. package/dist/esm/global-account/react/components/UserAvatar/UserAvatar.js +21 -0
  118. package/dist/esm/global-account/react/components/index.d.ts +3 -0
  119. package/dist/esm/global-account/react/components/index.js +4 -0
  120. package/dist/esm/global-account/react/hooks/useBetterAuth.d.ts +1 -1
  121. package/dist/esm/global-account/react/hooks/useBetterAuth.js +12 -10
  122. package/dist/esm/global-account/react/stores/useModalStore.d.ts +4 -0
  123. package/dist/esm/shared/constants/index.d.ts +1 -0
  124. package/dist/esm/shared/constants/index.js +1 -0
  125. package/dist/styles/index.css +1 -1
  126. package/dist/types/anyspend/react/components/AnySpend.d.ts +2 -0
  127. package/dist/types/anyspend/react/components/AnySpendCollectorClubPurchase.d.ts +5 -1
  128. package/dist/types/anyspend/react/components/AnySpendCustom.d.ts +2 -0
  129. package/dist/types/anyspend/react/components/AnySpendDeposit.d.ts +3 -1
  130. package/dist/types/anyspend/react/components/AnySpendNFT.d.ts +3 -1
  131. package/dist/types/anyspend/react/components/AnySpendStakeUpside.d.ts +3 -1
  132. package/dist/types/anyspend/react/components/checkout/CartItemRow.d.ts +2 -1
  133. package/dist/types/anyspend/react/components/checkout/CartSummary.d.ts +6 -4
  134. package/dist/types/anyspend/react/components/checkout/CheckoutCartPanel.d.ts +3 -1
  135. package/dist/types/anyspend/react/components/checkout/CheckoutFormPanel.d.ts +3 -1
  136. package/dist/types/anyspend/react/components/checkout/DiscountCodeInput.d.ts +3 -1
  137. package/dist/types/anyspend/react/components/checkout/PriceSkeleton.d.ts +5 -0
  138. package/dist/types/anyspend/react/components/checkout/ShippingSelector.d.ts +3 -1
  139. package/dist/types/global-account/react/components/B3Provider/B3ConfigProvider.d.ts +5 -1
  140. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +17 -1
  141. package/dist/types/global-account/react/components/B3Provider/BetterAuthClientProvider.d.ts +17 -0
  142. package/dist/types/global-account/react/components/SignInWithB3/BetterAuthSignIn.d.ts +6 -1
  143. package/dist/types/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.d.ts +37 -0
  144. package/dist/types/global-account/react/components/SignInWithB3/SignInWithB3Flow.d.ts +1 -1
  145. package/dist/types/global-account/react/components/SignInWithB3/components/PasswordInput.d.ts +10 -0
  146. package/dist/types/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.d.ts +3 -1
  147. package/dist/types/global-account/react/components/UserAvatar/UserAvatar.d.ts +18 -0
  148. package/dist/types/global-account/react/components/index.d.ts +3 -0
  149. package/dist/types/global-account/react/hooks/useBetterAuth.d.ts +1 -1
  150. package/dist/types/global-account/react/stores/useModalStore.d.ts +4 -0
  151. package/dist/types/shared/constants/index.d.ts +1 -0
  152. package/package.json +1 -1
  153. package/src/anyspend/react/components/AnySpend.tsx +24 -12
  154. package/src/anyspend/react/components/AnySpendCollectorClubPurchase.tsx +6 -0
  155. package/src/anyspend/react/components/AnySpendCustom.tsx +12 -2
  156. package/src/anyspend/react/components/AnySpendDeposit.tsx +38 -31
  157. package/src/anyspend/react/components/AnySpendNFT.tsx +4 -0
  158. package/src/anyspend/react/components/AnySpendStakeUpside.tsx +4 -0
  159. package/src/anyspend/react/components/checkout/AnySpendCheckout.tsx +10 -4
  160. package/src/anyspend/react/components/checkout/CartItemRow.tsx +2 -1
  161. package/src/anyspend/react/components/checkout/CartSummary.tsx +24 -20
  162. package/src/anyspend/react/components/checkout/CheckoutCartPanel.tsx +12 -3
  163. package/src/anyspend/react/components/checkout/CheckoutFormPanel.tsx +5 -0
  164. package/src/anyspend/react/components/checkout/DiscountCodeInput.tsx +15 -5
  165. package/src/anyspend/react/components/checkout/PriceSkeleton.tsx +19 -0
  166. package/src/anyspend/react/components/checkout/ShippingSelector.tsx +5 -1
  167. package/src/global-account/react/components/AvatarEditor/AvatarEditor.tsx +3 -1
  168. package/src/global-account/react/components/B3Provider/B3ConfigProvider.tsx +6 -0
  169. package/src/global-account/react/components/B3Provider/B3Provider.tsx +36 -15
  170. package/src/global-account/react/components/B3Provider/BetterAuthClientProvider.tsx +40 -0
  171. package/src/global-account/react/components/B3Provider/BetterAuthProvider.tsx +4 -3
  172. package/src/global-account/react/components/ManageAccount/BottomNavigation.tsx +18 -14
  173. package/src/global-account/react/components/ManageAccount/Header.tsx +71 -4
  174. package/src/global-account/react/components/ManageAccount/HomeContent.tsx +25 -19
  175. package/src/global-account/react/components/ManageAccount/ManageAccount.tsx +13 -0
  176. package/src/global-account/react/components/ManageAccount/ProfileSection.tsx +14 -7
  177. package/src/global-account/react/components/ManageAccount/SettingsContent.tsx +15 -32
  178. package/src/global-account/react/components/ManageAccount/SettingsProfileCard.tsx +29 -20
  179. package/src/global-account/react/components/SignInWithB3/BetterAuthResetPassword.tsx +6 -7
  180. package/src/global-account/react/components/SignInWithB3/BetterAuthSignIn.tsx +27 -7
  181. package/src/global-account/react/components/SignInWithB3/BetterAuthVerifyEmail.tsx +155 -0
  182. package/src/global-account/react/components/SignInWithB3/SignIn.tsx +42 -13
  183. package/src/global-account/react/components/SignInWithB3/SignInWithB3Flow.tsx +8 -1
  184. package/src/global-account/react/components/SignInWithB3/components/PasswordInput.tsx +62 -0
  185. package/src/global-account/react/components/SignInWithB3/steps/LoginStepBetterAuth.tsx +13 -6
  186. package/src/global-account/react/components/UserAvatar/UserAvatar.tsx +45 -0
  187. package/src/global-account/react/components/index.ts +9 -0
  188. package/src/global-account/react/hooks/useBetterAuth.ts +12 -10
  189. package/src/global-account/react/stores/useModalStore.ts +4 -0
  190. package/src/shared/constants/index.ts +2 -0
@@ -0,0 +1,37 @@
1
+ export type BetterAuthVerifyEmailState = "success" | "expired" | "invalid" | "already-verified" | "error";
2
+ export interface BetterAuthVerifyEmailProps {
3
+ /**
4
+ * Error code from the callback URL's `?error=` query param. Pass `null` /
5
+ * `undefined` when the user landed here cleanly (successful verification).
6
+ * Better Auth appends this param when server-side verification fails.
7
+ */
8
+ errorCode?: string | null;
9
+ /** Called when the user clicks the "Go to sign in" button. */
10
+ onGoToSignIn?: () => void;
11
+ /** Fallback href used when `onGoToSignIn` is not provided. Defaults to "/login". */
12
+ signInHref?: string;
13
+ /** Optional override for the success headline. */
14
+ successTitle?: string;
15
+ /** Optional override for the success body text. */
16
+ successMessage?: string;
17
+ /** Optional class name for the root container. */
18
+ className?: string;
19
+ }
20
+ /**
21
+ * Standalone email-verification confirmation page. Render on the route you
22
+ * set as `callbackURL` when calling `betterAuthClient.sendVerificationEmail`
23
+ * (or the `verifyCallbackURL` arg on `useBetterAuth().signUpWithEmail`).
24
+ *
25
+ * Better Auth verifies the token server-side before redirecting here. This
26
+ * component only displays the outcome based on the `?error=` query param.
27
+ *
28
+ * Usage:
29
+ * ```tsx
30
+ * const error = new URLSearchParams(window.location.search).get("error");
31
+ * <BetterAuthVerifyEmail
32
+ * errorCode={error}
33
+ * onGoToSignIn={() => router.push("/login")}
34
+ * />
35
+ * ```
36
+ */
37
+ export declare function BetterAuthVerifyEmail({ errorCode, onGoToSignIn, signInHref, successTitle, successMessage, className, }: BetterAuthVerifyEmailProps): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,82 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button } from "../../../../global-account/react/index.js";
3
+ import { debugB3React } from "../../../../shared/utils/debug.js";
4
+ const debug = debugB3React("BetterAuthVerifyEmail");
5
+ function classifyError(code) {
6
+ if (!code)
7
+ return "success";
8
+ const normalized = code.toLowerCase();
9
+ // Exact matches for Better Auth's documented verification error codes.
10
+ if (normalized === "expired_token")
11
+ return "expired";
12
+ if (normalized === "invalid_token")
13
+ return "invalid";
14
+ if (normalized === "already_verified" || normalized === "email_already_verified")
15
+ return "already-verified";
16
+ // Loose fallbacks for close variants. Order matters — check "already" before
17
+ // "verified" so `email_already_verified` maps to already-verified, not invalid.
18
+ if (normalized.includes("expired"))
19
+ return "expired";
20
+ if (normalized.includes("already"))
21
+ return "already-verified";
22
+ if (normalized.includes("invalid"))
23
+ return "invalid";
24
+ return "error";
25
+ }
26
+ const COPY = {
27
+ success: {
28
+ title: "Email verified",
29
+ message: "Your email is confirmed. You can now sign in to your account.",
30
+ },
31
+ expired: {
32
+ title: "Link expired",
33
+ message: "This verification link has expired. Request a new one from the sign-in page.",
34
+ },
35
+ invalid: {
36
+ title: "Invalid link",
37
+ message: "This verification link is invalid or has already been used. Try signing in or request a new link.",
38
+ },
39
+ "already-verified": {
40
+ title: "Already verified",
41
+ message: "Your email was already confirmed. You can sign in now.",
42
+ },
43
+ error: {
44
+ title: "Verification failed",
45
+ message: "We couldn't verify your email. Request a new link from the sign-in page.",
46
+ },
47
+ };
48
+ /**
49
+ * Standalone email-verification confirmation page. Render on the route you
50
+ * set as `callbackURL` when calling `betterAuthClient.sendVerificationEmail`
51
+ * (or the `verifyCallbackURL` arg on `useBetterAuth().signUpWithEmail`).
52
+ *
53
+ * Better Auth verifies the token server-side before redirecting here. This
54
+ * component only displays the outcome based on the `?error=` query param.
55
+ *
56
+ * Usage:
57
+ * ```tsx
58
+ * const error = new URLSearchParams(window.location.search).get("error");
59
+ * <BetterAuthVerifyEmail
60
+ * errorCode={error}
61
+ * onGoToSignIn={() => router.push("/login")}
62
+ * />
63
+ * ```
64
+ */
65
+ export function BetterAuthVerifyEmail({ errorCode, onGoToSignIn, signInHref = "/login", successTitle, successMessage, className, }) {
66
+ const state = classifyError(errorCode);
67
+ const isSuccess = state === "success" || state === "already-verified";
68
+ const copy = COPY[state];
69
+ const title = isSuccess && successTitle ? successTitle : copy.title;
70
+ const message = isSuccess && successMessage ? successMessage : copy.message;
71
+ debug("Rendering verify-email state", { state, errorCode });
72
+ const handleClick = () => {
73
+ if (onGoToSignIn) {
74
+ onGoToSignIn();
75
+ return;
76
+ }
77
+ if (typeof window !== "undefined") {
78
+ window.location.href = signInHref;
79
+ }
80
+ };
81
+ return (_jsx("div", { className: `w-full max-w-[400px] px-6 ${className || ""}`, children: _jsxs("div", { className: "space-y-6 text-center", children: [_jsx("div", { className: `mx-auto flex h-12 w-12 items-center justify-center rounded-full ${isSuccess ? "bg-green-100" : "bg-red-100"}`, children: isSuccess ? (_jsx("svg", { className: "h-6 w-6 text-green-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) })) : (_jsx("svg", { className: "h-6 w-6 text-red-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", "aria-hidden": "true", children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M6 18L18 6M6 6l12 12" }) })) }), _jsxs("div", { children: [_jsx("h1", { className: "text-[28px] font-semibold tracking-tight text-gray-900 dark:text-gray-100", children: title }), _jsx("p", { className: "mt-3 text-[15px] text-gray-500 dark:text-gray-400", children: message })] }), _jsx(Button, { onClick: handleClick, 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", children: isSuccess ? "Go to sign in" : "Back to sign in" })] }) }));
82
+ }
@@ -1,15 +1,18 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { IPFSMediaRenderer, SignInWithB3, StyleRoot, useAccountWallet, useAuthentication, useB3Config, useIsMobile, } from "../../../../global-account/react/index.js";
2
+ import { IPFSMediaRenderer, SignInWithB3, StyleRoot, useAccountWallet, useAuthStore, useAuthentication, useB3Config, useIsMobile, } from "../../../../global-account/react/index.js";
3
3
  import Icon from "../../../../global-account/react/components/custom/Icon.js";
4
4
  import { ecosystemWalletId } from "../../../../shared/constants/index.js";
5
5
  import { cn, truncateAddress } from "../../../../shared/utils/index.js";
6
6
  import { Menu, MenuButton, MenuItems, Transition } from "@headlessui/react";
7
7
  import { useEffect } from "react";
8
8
  import { useConnectedWallets, useSetActiveWallet, useWalletImage } from "thirdweb/react";
9
+ import { useUser } from "../../hooks/useUser.js";
10
+ import { UserAvatar } from "../UserAvatar/UserAvatar.js";
9
11
  import { ManageAccountButton } from "../custom/ManageAccountButton.js";
10
12
  export function SignIn(props) {
11
13
  const { className } = props;
12
- const { automaticallySetFirstEoa, partnerId } = useB3Config();
14
+ const { automaticallySetFirstEoa, partnerId, authStrategy } = useB3Config();
15
+ const isBetterAuth = authStrategy === "better-auth";
13
16
  const { address: globalAddress, ensName, connectedSmartWallet, connectedEOAWallet, isActiveSmartWallet, isActiveEOAWallet, smartWalletIcon, } = useAccountWallet();
14
17
  const { data: walletImage } = useWalletImage(connectedEOAWallet?.id);
15
18
  const isMobile = useIsMobile();
@@ -19,6 +22,10 @@ export function SignIn(props) {
19
22
  };
20
23
  const connectedWallets = useConnectedWallets();
21
24
  const setActiveWallet = useSetActiveWallet();
25
+ // Better Auth state
26
+ const isAuthenticated = useAuthStore(state => state.isAuthenticated);
27
+ const { user } = useUser();
28
+ const userDisplayName = user?.username || user?.email || "Account";
22
29
  const handleSetActiveAccount = (selectedWalletId) => {
23
30
  if (!selectedWalletId ||
24
31
  !connectedWallets ||
@@ -34,12 +41,15 @@ export function SignIn(props) {
34
41
  setActiveWallet(connectedEOAWallet);
35
42
  }
36
43
  }, [connectedEOAWallet, isActiveEOAWallet, setActiveWallet, automaticallySetFirstEoa]);
44
+ const isLoggedIn = isBetterAuth ? isAuthenticated : !!globalAddress;
37
45
  // Desktop version - original dropdown menu
38
- return (_jsx(StyleRoot, { children: _jsx(Menu, { className: `relative flex items-center ${className || ""}`, as: "div", children: globalAddress ? (_jsxs(_Fragment, { children: [_jsxs(MenuButton, { className: "bg-b3-react-background group flex h-10 items-center gap-1 rounded-xl px-3 focus:outline-none", children: [!!walletImage && (_jsx(IPFSMediaRenderer, { src: walletImage, alt: "Wallet Image", className: "bg-b3-react-primary h-6 w-6 rounded-full object-cover opacity-100" })), _jsx("div", { className: "text-as-primary", children: ensName ? ensName : truncateAddress(globalAddress) })] }), _jsx(Transition, { enter: "duration-200 ease-out", enterFrom: "scale-95 opacity-0", enterTo: "scale-100 opacity-100", leave: "duration-300 ease-out", leaveFrom: "scale-100 opacity-100", leaveTo: "scale-95 opacity-0", children: _jsx(MenuItems, { className: "b3-root absolute -right-4 top-full min-w-64 rounded-2xl border focus:outline-none lg:right-0", modal: false,
46
+ return (_jsx(StyleRoot, { children: _jsx(Menu, { className: `relative flex items-center ${className || ""}`, as: "div", children: isLoggedIn ? (_jsxs(_Fragment, { children: [_jsxs(MenuButton, { className: "bg-b3-react-background group flex h-10 items-center gap-1 rounded-xl px-3 focus:outline-none", children: [isBetterAuth ? (_jsx(UserAvatar, { avatarUrl: user?.avatar, name: userDisplayName, size: 24 })) : (!!walletImage && (_jsx(IPFSMediaRenderer, { src: walletImage, alt: "Wallet Image", className: "bg-b3-react-primary h-6 w-6 rounded-full object-cover opacity-100" }))), _jsx("div", { className: "text-as-primary", children: isBetterAuth ? userDisplayName : ensName ? ensName : truncateAddress(globalAddress ?? "") })] }), _jsx(Transition, { enter: "duration-200 ease-out", enterFrom: "scale-95 opacity-0", enterTo: "scale-100 opacity-100", leave: "duration-300 ease-out", leaveFrom: "scale-100 opacity-100", leaveTo: "scale-95 opacity-0", children: _jsx(MenuItems, { className: "b3-root absolute -right-4 top-full min-w-64 rounded-2xl border focus:outline-none lg:right-0", modal: false,
39
47
  // TODO: Figure out why setting anchor on mobile causes z-index issues where it appears under elements
40
- anchor: isMobile ? "top end" : undefined, children: _jsxs("div", { className: "bg-b3-react-background", children: [connectedEOAWallet ? (_jsxs("div", { className: cn("border-b3-react-subtle bg-b3-react-background flex cursor-pointer items-center justify-between rounded-xl p-3"), onClick: () => handleSetActiveAccount(connectedEOAWallet?.id), children: [_jsxs("div", { className: "flex items-center", children: [_jsx("img", { className: "bg-b3-react-primary h-16 w-16 rounded-full opacity-100", src: walletImage, alt: connectedEOAWallet?.id }), _jsxs("div", { className: "ml-4 grow", children: [ensName && _jsx("div", { children: ensName }), _jsx("div", { children: truncateAddress(globalAddress) })] })] }), isActiveEOAWallet && _jsx(Icon, { className: "fill-b3-react-primary", name: "check" })] })) : (connectedSmartWallet && (_jsxs("div", { className: cn("mb-2 flex cursor-pointer items-center justify-between rounded-xl p-3", isActiveSmartWallet
48
+ anchor: isMobile ? "top end" : undefined, children: _jsxs("div", { className: "bg-b3-react-background", children: [isBetterAuth ? (
49
+ /* Better Auth: show user info instead of wallet switching */
50
+ _jsxs("div", { className: "flex items-center gap-3 rounded-xl p-3", children: [_jsx(UserAvatar, { avatarUrl: user?.avatar, name: userDisplayName, size: 48 }), _jsxs("div", { className: "flex flex-col gap-0.5", children: [user?.username && _jsx("div", { className: "text-b3-react-primary font-semibold", children: user.username }), user?.email && _jsx("div", { className: "text-b3-react-secondary text-sm", children: user.email })] })] })) : connectedEOAWallet ? (_jsxs("div", { className: cn("border-b3-react-subtle bg-b3-react-background flex cursor-pointer items-center justify-between rounded-xl p-3"), onClick: () => handleSetActiveAccount(connectedEOAWallet?.id), children: [_jsxs("div", { className: "flex items-center", children: [_jsx("img", { className: "bg-b3-react-primary h-16 w-16 rounded-full opacity-100", src: walletImage, alt: connectedEOAWallet?.id }), _jsxs("div", { className: "ml-4 grow", children: [ensName && _jsx("div", { children: ensName }), _jsx("div", { children: truncateAddress(globalAddress ?? "") })] })] }), isActiveEOAWallet && _jsx(Icon, { className: "fill-b3-react-primary", name: "check" })] })) : (connectedSmartWallet && (_jsxs("div", { className: cn("mb-2 flex cursor-pointer items-center justify-between rounded-xl p-3", isActiveSmartWallet
41
51
  ? "bg-b3-react-background"
42
- : "bg-b3-react-background hover:bg-b3-react-background"), onClick: () => handleSetActiveAccount(connectedSmartWallet?.id), children: [_jsxs("div", { className: "flex items-center", children: [_jsx("img", { className: "bg-b3-react-primary h-16 w-16 rounded-full opacity-100", src: smartWalletIcon, alt: connectedSmartWallet?.id }), _jsxs("div", { className: "grow pl-4", children: [ensName && _jsx("div", { children: ensName }), _jsx("div", { children: truncateAddress(globalAddress) }), _jsx("div", { children: "Smart wallet" })] })] }), isActiveSmartWallet && _jsx(Icon, { className: "fill-b3-react-primary", name: "check" })] }))), _jsx("div", { className: "ml-3", children: _jsx(ManageAccountButton, { ...props, className: "w-[calc(100%-12px)]" }) }), _jsx("button", { className: "mb-2 w-full space-y-1", onClick: onDisconnect, children: _jsxs("div", { className: "hover:bg-b3-react-background group flex h-12 items-center rounded-xl px-4 transition-colors", children: [_jsx(Icon, { className: "fill-b3-react-primary mr-4 shrink-0 transition-colors", name: "logout" }), _jsx("div", { className: "text-b3-react-primary mr-auto transition-colors", children: "Disconnect" })] }) })] }) }) })] })) : (_jsx(SignInWithB3, { closeAfterLogin: true, onLoginSuccess: async (globalAccount) => {
52
+ : "bg-b3-react-background hover:bg-b3-react-background"), onClick: () => handleSetActiveAccount(connectedSmartWallet?.id), children: [_jsxs("div", { className: "flex items-center", children: [_jsx("img", { className: "bg-b3-react-primary h-16 w-16 rounded-full opacity-100", src: smartWalletIcon, alt: connectedSmartWallet?.id }), _jsxs("div", { className: "grow pl-4", children: [ensName && _jsx("div", { children: ensName }), _jsx("div", { children: truncateAddress(globalAddress ?? "") }), _jsx("div", { children: "Smart wallet" })] })] }), isActiveSmartWallet && _jsx(Icon, { className: "fill-b3-react-primary", name: "check" })] }))), _jsx("div", { className: "ml-3", children: _jsx(ManageAccountButton, { ...props, className: "w-[calc(100%-12px)]" }) }), _jsx("button", { className: "mb-2 w-full space-y-1", onClick: onDisconnect, children: _jsxs("div", { className: "hover:bg-b3-react-background group flex h-12 items-center rounded-xl px-4 transition-colors", children: [_jsx(Icon, { className: "fill-b3-react-primary mr-4 shrink-0 transition-colors", name: "logout" }), _jsx("div", { className: "text-b3-react-primary mr-auto transition-colors", children: isBetterAuth ? "Sign out" : "Disconnect" })] }) })] }) }) })] })) : (_jsx(SignInWithB3, { closeAfterLogin: true, onLoginSuccess: async (globalAccount) => {
43
53
  console.log("User authenticated with Global Account!", globalAccount);
44
54
  }, ...props })) }) }));
45
55
  }
@@ -3,4 +3,4 @@ import { SignInWithB3ModalProps } from "../../../../global-account/react";
3
3
  * Component that manages the authentication flow for Sign In With B3
4
4
  * Handles different login providers, authentication steps, and session key management
5
5
  */
6
- export declare function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySuccess, onError, chain, sessionKeyAddress, partnerId, closeAfterLogin, source, signersEnabled, }: SignInWithB3ModalProps): import("react/jsx-runtime").JSX.Element | null;
6
+ export declare function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySuccess, onError, chain, sessionKeyAddress, partnerId, closeAfterLogin, source, signersEnabled, verifyEmailRedirectTo, }: SignInWithB3ModalProps): import("react/jsx-runtime").JSX.Element | null;
@@ -13,7 +13,7 @@ const MAX_REFETCH_ATTEMPTS = 20;
13
13
  * Component that manages the authentication flow for Sign In With B3
14
14
  * Handles different login providers, authentication steps, and session key management
15
15
  */
16
- export function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySuccess, onError, chain, sessionKeyAddress, partnerId, closeAfterLogin = false, source = "signInWithB3Button", signersEnabled = false, }) {
16
+ export function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySuccess, onError, chain, sessionKeyAddress, partnerId, closeAfterLogin = false, source = "signInWithB3Button", signersEnabled = false, verifyEmailRedirectTo, }) {
17
17
  const { automaticallySetFirstEoa, authStrategy } = useB3Config();
18
18
  // skipAutoConnect: this component intentionally logs out on mount to show a fresh login screen.
19
19
  // AuthenticationProvider is the sole owner of useAutoConnect to avoid competing auth cycles.
@@ -244,7 +244,7 @@ export function SignInWithB3Flow({ strategies, onLoginSuccess, onSessionKeySucce
244
244
  // Better Auth manages its own loading/verification states internally.
245
245
  // Don't gate on isAuthenticating — it would unmount the component
246
246
  // and lose verification state when setIsAuthenticating(false) fires.
247
- content = _jsx(LoginStepBetterAuth, { onSuccess: () => handleLoginSuccess({}), onError: onError });
247
+ content = (_jsx(LoginStepBetterAuth, { onSuccess: () => handleLoginSuccess({}), onError: onError, verifyEmailRedirectTo: verifyEmailRedirectTo }));
248
248
  }
249
249
  else if (!readyToShowLogin || isAuthenticating || isFetchingSigners) {
250
250
  content = (_jsx(LoginStepContainer, { partnerId: partnerId, children: _jsx("div", { className: "my-8 flex min-h-[350px] items-center justify-center", children: _jsx(Loading, { variant: "white", size: "lg" }) }) }));
@@ -0,0 +1,10 @@
1
+ interface PasswordInputProps {
2
+ value: string;
3
+ onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
4
+ disabled?: boolean;
5
+ placeholder?: string;
6
+ onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement>) => void;
7
+ className?: string;
8
+ }
9
+ export declare function PasswordInput({ value, onChange, disabled, placeholder, onKeyDown, className, }: PasswordInputProps): import("react/jsx-runtime").JSX.Element;
10
+ export {};
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Input } from "../../../../../global-account/react/index.js";
3
+ import { useState } from "react";
4
+ export function PasswordInput({ value, onChange, disabled, placeholder = "Password", onKeyDown, className, }) {
5
+ const [showPassword, setShowPassword] = useState(false);
6
+ return (_jsxs("div", { className: "relative", children: [_jsx(Input, { type: showPassword ? "text" : "password", placeholder: placeholder, value: value, onChange: onChange, disabled: disabled, onKeyDown: onKeyDown, className: className }), _jsx("button", { type: "button", onClick: () => setShowPassword(!showPassword), "aria-label": showPassword ? "Hide password" : "Show password", className: "absolute right-3 top-1/2 -translate-y-1/2 text-gray-400 hover:text-gray-600 dark:text-gray-500 dark:hover:text-gray-300", tabIndex: -1, children: showPassword ? (_jsx("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M3.98 8.223A10.477 10.477 0 001.934 12C3.226 16.338 7.244 19.5 12 19.5c.993 0 1.953-.138 2.863-.395M6.228 6.228A10.45 10.45 0 0112 4.5c4.756 0 8.773 3.162 10.065 7.498a10.523 10.523 0 01-4.293 5.774M6.228 6.228L3 3m3.228 3.228l3.65 3.65m7.894 7.894L21 21m-3.228-3.228l-3.65-3.65m0 0a3 3 0 10-4.243-4.243m4.242 4.242L9.88 9.88" }) })) : (_jsxs("svg", { className: "h-5 w-5", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 1.5, children: [_jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M2.036 12.322a1.012 1.012 0 010-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178z" }), _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M15 12a3 3 0 11-6 0 3 3 0 016 0z" })] })) })] }));
7
+ }
@@ -1,6 +1,8 @@
1
1
  interface LoginStepBetterAuthProps {
2
2
  onSuccess?: () => void;
3
3
  onError?: (error: Error) => Promise<void>;
4
+ /** URL Better Auth redirects to after server-side email verification. */
5
+ verifyEmailRedirectTo?: string;
4
6
  }
5
- export declare function LoginStepBetterAuth({ onSuccess, onError }: LoginStepBetterAuthProps): import("react/jsx-runtime").JSX.Element;
7
+ export declare function LoginStepBetterAuth({ onSuccess, onError, verifyEmailRedirectTo }: LoginStepBetterAuthProps): import("react/jsx-runtime").JSX.Element;
6
8
  export {};
@@ -4,6 +4,7 @@ import { debugB3React } from "../../../../../shared/utils/debug.js";
4
4
  import { useState } from "react";
5
5
  import { EmailVerificationRequiredError, useBetterAuth, } from "../../../hooks/useBetterAuth.js";
6
6
  import { AuthButton } from "../components/AuthButton.js";
7
+ import { PasswordInput } from "../components/PasswordInput.js";
7
8
  const debug = debugB3React("LoginStepBetterAuth");
8
9
  const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
9
10
  const SOCIAL_PROVIDERS = [
@@ -13,7 +14,7 @@ const SOCIAL_PROVIDERS = [
13
14
  { id: "microsoft", label: "Microsoft" },
14
15
  { id: "slack", label: "Slack" },
15
16
  ];
16
- export function LoginStepBetterAuth({ onSuccess, onError }) {
17
+ export function LoginStepBetterAuth({ onSuccess, onError, verifyEmailRedirectTo }) {
17
18
  const { partnerId } = useB3Config();
18
19
  const { signInWithEmail, signUpWithEmail, signInWithSocial, requestPasswordReset } = useBetterAuth();
19
20
  const [mode, setMode] = useState("sign-in");
@@ -44,7 +45,7 @@ export function LoginStepBetterAuth({ onSuccess, onError }) {
44
45
  setError(null);
45
46
  if (mode === "sign-up") {
46
47
  debug("Signing up", { email: normalizedEmail, name: name.trim() });
47
- await signUpWithEmail(normalizedEmail, password, name.trim());
48
+ await signUpWithEmail(normalizedEmail, password, name.trim(), verifyEmailRedirectTo);
48
49
  }
49
50
  else {
50
51
  debug("Signing in", { email: normalizedEmail });
@@ -111,7 +112,9 @@ export function LoginStepBetterAuth({ onSuccess, onError }) {
111
112
  setPassword("");
112
113
  }, className: "text-sm text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-300", children: "Back to sign in" })] }) }));
113
114
  }
114
- return (_jsx(LoginStepContainer, { partnerId: partnerId, children: mode === "forgot-password" ? (_jsxs("div", { className: "mb-6 w-full space-y-3 px-3", children: [_jsx("p", { className: "text-center text-sm font-medium text-gray-900 dark:text-gray-100", children: "Reset password" }), _jsx("p", { className: "text-center text-xs text-gray-500", children: "Enter your email and we'll send you a reset link" }), resetEmailSent ? (_jsx("div", { className: "space-y-3 py-4 text-center", children: _jsx("p", { className: "text-sm text-green-600", children: "Check your email for a reset link." }) })) : (_jsxs(_Fragment, { children: [_jsx(Input, { type: "email", placeholder: "you@example.com", value: email, onChange: event => setEmail(event.target.value), disabled: isLoading, onKeyDown: event => {
115
+ return (_jsx(LoginStepContainer, { partnerId: partnerId, children: mode === "forgot-password" ? (_jsxs("div", { className: "mb-6 w-full space-y-3 px-3", children: [_jsx("p", { className: "text-center text-sm font-medium text-gray-900 dark:text-gray-100", children: "Reset password" }), _jsx("p", { className: "text-center text-xs text-gray-500", children: resetEmailSent
116
+ ? "We've sent a password reset link to your email"
117
+ : "Enter your email and we'll send you a reset link" }), resetEmailSent ? (_jsx("div", { className: "space-y-3 py-4 text-center", children: _jsx("p", { className: "text-sm text-green-600", children: "Check your email for a reset link." }) })) : (_jsxs(_Fragment, { children: [_jsx(Input, { type: "email", placeholder: "you@example.com", value: email, onChange: event => setEmail(event.target.value), disabled: isLoading, onKeyDown: event => {
115
118
  if (event.key === "Enter")
116
119
  handleForgotPassword();
117
120
  } }), error && _jsx("p", { className: "text-sm text-red-500", children: error }), _jsx(Button, { onClick: handleForgotPassword, disabled: isLoading, className: "w-full", children: isLoading ? "Sending..." : "Send reset link" })] })), _jsx("button", { onClick: () => {
@@ -119,10 +122,10 @@ export function LoginStepBetterAuth({ onSuccess, onError }) {
119
122
  setShowEmailForm(true);
120
123
  setError(null);
121
124
  setResetEmailSent(false);
122
- }, className: "w-full text-center text-sm text-gray-500 hover:text-gray-700", children: "Back to sign in" })] })) : showEmailForm ? (_jsxs("div", { className: "mb-6 w-full space-y-3 px-3", children: [_jsx("p", { className: "text-center text-sm font-medium text-gray-900 dark:text-gray-100", children: mode === "sign-in" ? "Sign in with email" : "Create an account" }), mode === "sign-up" && (_jsx(Input, { type: "text", placeholder: "Your name", value: name, onChange: event => setName(event.target.value), disabled: isLoading })), _jsx(Input, { type: "email", placeholder: "you@example.com", value: email, onChange: event => setEmail(event.target.value), disabled: isLoading }), _jsx(Input, { type: "password", placeholder: "Password", value: password, onChange: event => setPassword(event.target.value), disabled: isLoading, onKeyDown: event => {
125
+ }, className: "w-full text-center text-sm text-gray-500 hover:text-gray-700", children: "Back to sign in" })] })) : showEmailForm ? (_jsxs("div", { className: "mb-6 w-full space-y-3 px-3", children: [_jsx("p", { className: "text-center text-sm font-medium text-gray-900 dark:text-gray-100", children: mode === "sign-in" ? "Sign in with email" : "Create an account" }), mode === "sign-up" && (_jsx(Input, { type: "text", placeholder: "Your name", value: name, onChange: event => setName(event.target.value), disabled: isLoading })), _jsx(Input, { type: "email", placeholder: "you@example.com", value: email, onChange: event => setEmail(event.target.value), disabled: isLoading }), _jsx(PasswordInput, { value: password, onChange: event => setPassword(event.target.value), disabled: isLoading, onKeyDown: event => {
123
126
  if (event.key === "Enter")
124
127
  handleEmailSubmit();
125
- } }), error && _jsx("p", { className: "text-sm text-red-500", children: error }), _jsx(Button, { onClick: handleEmailSubmit, disabled: isLoading, className: "w-full", children: isLoading ? "Loading..." : mode === "sign-in" ? "Sign in" : "Sign up" }), mode === "sign-in" && (_jsx("button", { onClick: () => {
128
+ }, className: "pr-11" }, mode), error && _jsx("p", { className: "text-sm text-red-500", children: error }), _jsx(Button, { onClick: handleEmailSubmit, disabled: isLoading, className: "w-full", children: isLoading ? "Loading..." : mode === "sign-in" ? "Sign in" : "Sign up" }), mode === "sign-in" && (_jsx("button", { onClick: () => {
126
129
  setMode("forgot-password");
127
130
  setError(null);
128
131
  }, disabled: isLoading, className: "w-full text-center text-xs text-gray-500 hover:text-gray-700", children: "Forgot password?" })), _jsx("button", { onClick: () => {
@@ -0,0 +1,18 @@
1
+ interface UserAvatarProps {
2
+ /** Direct avatar URL (IPFS or HTTP). Resolved and validated internally. */
3
+ avatarUrl?: string | null;
4
+ /** Seed for the generated fallback avatar + alt text. Use email, username, or address. */
5
+ name?: string;
6
+ /** Avatar size in pixels (square). */
7
+ size?: number;
8
+ /** Additional className for the outer container. */
9
+ className?: string;
10
+ }
11
+ /**
12
+ * Renders a user avatar with IPFS support and boring-avatars fallback.
13
+ *
14
+ * - If `avatarUrl` is provided and valid, renders via IPFSMediaRenderer.
15
+ * - On load failure or missing URL, falls back to a deterministic boring-avatars beam.
16
+ */
17
+ export declare function UserAvatar({ avatarUrl, name, size, className }: UserAvatarProps): import("react/jsx-runtime").JSX.Element;
18
+ export {};
@@ -0,0 +1,21 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { validateImageUrl } from "../../../../global-account/react/utils/profileDisplay.js";
3
+ import { AVATAR_COLORS } from "../../../../shared/constants/index.js";
4
+ import Avatar from "boring-avatars";
5
+ import { useCallback, useEffect, useState } from "react";
6
+ import { IPFSMediaRenderer } from "../IPFSMediaRenderer/IPFSMediaRenderer.js";
7
+ /**
8
+ * Renders a user avatar with IPFS support and boring-avatars fallback.
9
+ *
10
+ * - If `avatarUrl` is provided and valid, renders via IPFSMediaRenderer.
11
+ * - On load failure or missing URL, falls back to a deterministic boring-avatars beam.
12
+ */
13
+ export function UserAvatar({ avatarUrl, name = "user", size = 40, className }) {
14
+ const resolvedSrc = validateImageUrl(avatarUrl);
15
+ const [imgError, setImgError] = useState(false);
16
+ useEffect(() => {
17
+ setImgError(false);
18
+ }, [avatarUrl]);
19
+ const handleImgError = useCallback(() => setImgError(true), []);
20
+ return (_jsx("div", { className: className, style: { width: size, height: size, minWidth: size, minHeight: size }, children: resolvedSrc && !imgError ? (_jsx("div", { onErrorCapture: handleImgError, className: "h-full w-full overflow-hidden rounded-full", children: _jsx(IPFSMediaRenderer, { src: resolvedSrc, alt: name, className: "h-full w-full object-cover" }) })) : (_jsx(Avatar, { name: name, variant: "beam", size: size, colors: AVATAR_COLORS })) }));
21
+ }
@@ -5,9 +5,11 @@ export { RelayKitProviderWrapper } from "./B3Provider/RelayKitProviderWrapper";
5
5
  export { useB3 } from "./B3Provider/useB3";
6
6
  export { useB3Account } from "./B3Provider/useB3Account";
7
7
  export { useB3Config } from "./B3Provider/useB3Config";
8
+ export { useBetterAuthClient } from "./B3Provider/BetterAuthClientProvider";
8
9
  export { StyleRoot } from "./StyleRoot";
9
10
  export { BetterAuthResetPassword, type BetterAuthResetPasswordProps } from "./SignInWithB3/BetterAuthResetPassword";
10
11
  export { BetterAuthSignIn, type BetterAuthSignInProps } from "./SignInWithB3/BetterAuthSignIn";
12
+ export { BetterAuthVerifyEmail, type BetterAuthVerifyEmailProps, type BetterAuthVerifyEmailState, } from "./SignInWithB3/BetterAuthVerifyEmail";
11
13
  export { AuthButton } from "./SignInWithB3/components/AuthButton";
12
14
  export { PermissionItem } from "./SignInWithB3/components/PermissionItem";
13
15
  export { WalletRow } from "./SignInWithB3/components/WalletRow";
@@ -17,6 +19,7 @@ export { SignInWithB3Privy } from "./SignInWithB3/SignInWithB3Privy";
17
19
  export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep";
18
20
  export { getConnectOptionsFromStrategy, isWalletType, type AllowedStrategy } from "./SignInWithB3/utils/signInUtils";
19
21
  export { ManageAccount } from "./ManageAccount/ManageAccount";
22
+ export { UserAvatar } from "./UserAvatar/UserAvatar";
20
23
  export { Deposit } from "./Deposit/Deposit";
21
24
  export { Send } from "./Send/Send";
22
25
  export { IPFSMediaRenderer } from "./IPFSMediaRenderer/IPFSMediaRenderer";
@@ -6,10 +6,12 @@ export { RelayKitProviderWrapper } from "./B3Provider/RelayKitProviderWrapper.js
6
6
  export { useB3 } from "./B3Provider/useB3.js";
7
7
  export { useB3Account } from "./B3Provider/useB3Account.js";
8
8
  export { useB3Config } from "./B3Provider/useB3Config.js";
9
+ export { useBetterAuthClient } from "./B3Provider/BetterAuthClientProvider.js";
9
10
  export { StyleRoot } from "./StyleRoot.js";
10
11
  // SignInWithB3 Components
11
12
  export { BetterAuthResetPassword } from "./SignInWithB3/BetterAuthResetPassword.js";
12
13
  export { BetterAuthSignIn } from "./SignInWithB3/BetterAuthSignIn.js";
14
+ export { BetterAuthVerifyEmail, } from "./SignInWithB3/BetterAuthVerifyEmail.js";
13
15
  export { AuthButton } from "./SignInWithB3/components/AuthButton.js";
14
16
  export { PermissionItem } from "./SignInWithB3/components/PermissionItem.js";
15
17
  export { WalletRow } from "./SignInWithB3/components/WalletRow.js";
@@ -20,6 +22,8 @@ export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep.js";
20
22
  export { getConnectOptionsFromStrategy, isWalletType } from "./SignInWithB3/utils/signInUtils.js";
21
23
  // ManageAccount Components
22
24
  export { ManageAccount } from "./ManageAccount/ManageAccount.js";
25
+ // UserAvatar
26
+ export { UserAvatar } from "./UserAvatar/UserAvatar.js";
23
27
  // Deposit Components
24
28
  export { Deposit } from "./Deposit/Deposit.js";
25
29
  // Send Components
@@ -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: {
@@ -2,7 +2,7 @@ import app from "../../../global-account/app.js";
2
2
  import { useAuthStore, useB3Config } from "../../../global-account/react/index.js";
3
3
  import { debugB3React } from "../../../shared/utils/debug.js";
4
4
  import { useCallback } from "react";
5
- import { betterAuthClient } from "../../better-auth-client.js";
5
+ import { useBetterAuthClient } from "../components/B3Provider/BetterAuthClientProvider.js";
6
6
  import { useUserQuery } from "./useUserQuery.js";
7
7
  const debug = debugB3React("useBetterAuth");
8
8
  /** Thrown when email verification is required before the user can sign in. */
@@ -22,6 +22,7 @@ export class EmailVerificationRequiredError extends Error {
22
22
  */
23
23
  export function useBetterAuth() {
24
24
  const { partnerId } = useB3Config();
25
+ const betterAuthClient = useBetterAuthClient();
25
26
  const { setUser } = useUserQuery();
26
27
  const setIsAuthenticated = useAuthStore(state => state.setIsAuthenticated);
27
28
  const setIsAuthenticating = useAuthStore(state => state.setIsAuthenticating);
@@ -64,8 +65,8 @@ export function useBetterAuth() {
64
65
  debug("Sign in failed", error);
65
66
  throw error;
66
67
  }
67
- }, [exchangeForFeathersJWT, setIsAuthenticating, setHasStartedConnecting]);
68
- const signUpWithEmail = useCallback(async (email, password, name) => {
68
+ }, [exchangeForFeathersJWT, setIsAuthenticating, setHasStartedConnecting, betterAuthClient]);
69
+ const signUpWithEmail = useCallback(async (email, password, name, verifyCallbackURL) => {
69
70
  debug("Signing up with email", { email, name });
70
71
  setHasStartedConnecting(true);
71
72
  setIsAuthenticating(true);
@@ -76,11 +77,12 @@ export function useBetterAuth() {
76
77
  }
77
78
  const token = result.data?.token;
78
79
  if (!token) {
79
- // requireEmailVerification is enabled — send verification email
80
- // with the client's origin as callbackURL so the user returns here
80
+ // requireEmailVerification is enabled — send verification email with
81
+ // a callbackURL Better Auth redirects to after server-side verify.
82
+ // Pass verifyCallbackURL to land on a dedicated confirmation page.
81
83
  await betterAuthClient.sendVerificationEmail({
82
84
  email,
83
- callbackURL: `${window.location.origin}?authStrategy=better-auth`,
85
+ callbackURL: verifyCallbackURL || `${window.location.origin}?authStrategy=better-auth`,
84
86
  });
85
87
  throw new EmailVerificationRequiredError();
86
88
  }
@@ -91,7 +93,7 @@ export function useBetterAuth() {
91
93
  debug("Sign up failed", error);
92
94
  throw error;
93
95
  }
94
- }, [exchangeForFeathersJWT, setIsAuthenticating, setHasStartedConnecting]);
96
+ }, [exchangeForFeathersJWT, setIsAuthenticating, setHasStartedConnecting, betterAuthClient]);
95
97
  const signInWithSocial = useCallback(async (provider) => {
96
98
  debug("Signing in with social provider", { provider });
97
99
  setHasStartedConnecting(true);
@@ -112,7 +114,7 @@ export function useBetterAuth() {
112
114
  debug("Social sign in failed", error);
113
115
  throw error;
114
116
  }
115
- }, [setIsAuthenticating, setHasStartedConnecting]);
117
+ }, [setIsAuthenticating, setHasStartedConnecting, betterAuthClient]);
116
118
  const requestPasswordReset = useCallback(async (email, redirectTo) => {
117
119
  debug("Requesting password reset", { email });
118
120
  const result = await betterAuthClient.requestPasswordReset({
@@ -124,7 +126,7 @@ export function useBetterAuth() {
124
126
  }
125
127
  debug("Password reset email sent");
126
128
  return result;
127
- }, []);
129
+ }, [betterAuthClient]);
128
130
  const resetPassword = useCallback(async (newPassword, token) => {
129
131
  debug("Resetting password");
130
132
  const result = await betterAuthClient.resetPassword({
@@ -136,7 +138,7 @@ export function useBetterAuth() {
136
138
  }
137
139
  debug("Password reset successful");
138
140
  return result;
139
- }, []);
141
+ }, [betterAuthClient]);
140
142
  return {
141
143
  signInWithEmail,
142
144
  signUpWithEmail,
@@ -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
@@ -609,6 +611,8 @@ export interface AnySpendDepositModalProps extends BaseModalProps {
609
611
  actionLabel?: string;
610
612
  /** Whether to show chain selection step. Defaults to true if sourceTokenChainId is not provided */
611
613
  showChainSelection?: boolean;
614
+ /** Whether to show the "Fund with Fiat" option in the deposit options list. Defaults to true */
615
+ showFiatOption?: boolean;
612
616
  /** Minimum pool size for filtering tokens (default: 1,000,000) */
613
617
  minPoolSize?: number;
614
618
  /** Custom title for chain selection step */
@@ -16,3 +16,4 @@ export declare const CLIENT_APP_BUNDLE_ID: string;
16
16
  export declare const B3_AUTH_COOKIE_NAME = "b3-auth";
17
17
  export declare const ENS_GATEWAY_URL = "https://ens-gateway.b3.fun/";
18
18
  export declare const PUBLIC_BASE_RPC_URL = "https://base-rpc.publicnode.com";
19
+ export declare const AVATAR_COLORS: string[];
@@ -21,3 +21,4 @@ export const CLIENT_APP_BUNDLE_ID = process.env.EXPO_PUBLIC_B3_BUNDLE_ID || "";
21
21
  export const B3_AUTH_COOKIE_NAME = "b3-auth";
22
22
  export const ENS_GATEWAY_URL = "https://ens-gateway.b3.fun/";
23
23
  export const PUBLIC_BASE_RPC_URL = "https://base-rpc.publicnode.com";
24
+ export const AVATAR_COLORS = ["#3368ef", "#272727", "#6366f1", "#06b6d4", "#eeb0d9", "#ba3fbf", "#ff777b", "#dfbb53"];