@b3dotfun/sdk 0.1.69-alpha.1 → 0.1.69-alpha.10

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 (125) hide show
  1. package/dist/cjs/anyspend/react/components/AnySpendStakeB3.js +1 -1
  2. package/dist/cjs/anyspend/react/components/AnySpendStakeB3ExactIn.js +1 -1
  3. package/dist/cjs/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -4
  4. package/dist/cjs/anyspend/react/components/checkout/CheckoutSuccess.d.ts +2 -1
  5. package/dist/cjs/anyspend/react/components/checkout/CheckoutSuccess.js +5 -3
  6. package/dist/cjs/anyspend/react/components/checkout/FiatCheckoutPanel.js +1 -2
  7. package/dist/cjs/anyspend/react/components/checkout/KycGate.js +1 -2
  8. package/dist/cjs/anyspend/react/components/common/OrderDetails.js +5 -0
  9. package/dist/cjs/anyspend/react/components/common/OrderStatus.js +37 -6
  10. package/dist/cjs/anyspend/react/components/common/StepProgress.d.ts +2 -0
  11. package/dist/cjs/anyspend/react/components/common/StepProgress.js +7 -2
  12. package/dist/cjs/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +4 -6
  13. package/dist/cjs/anyspend/react/hooks/useKycStatus.d.ts +3 -1
  14. package/dist/cjs/anyspend/react/hooks/useKycStatus.js +11 -7
  15. package/dist/cjs/app.shared.js +9 -7
  16. package/dist/cjs/global-account/react/components/B3DynamicModal.js +5 -2
  17. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.d.ts +2 -1
  18. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.js +2 -2
  19. package/dist/cjs/global-account/react/components/B3Provider/B3Provider.native.js +2 -1
  20. package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +3 -1
  21. package/dist/cjs/global-account/react/components/B3Provider/LocalSDKProvider.js +3 -1
  22. package/dist/cjs/global-account/react/components/ManageAccount/SessionDurationContent.d.ts +5 -0
  23. package/dist/cjs/global-account/react/components/ManageAccount/SessionDurationContent.js +57 -0
  24. package/dist/cjs/global-account/react/components/ManageAccount/SettingsContent.js +12 -29
  25. package/dist/cjs/global-account/react/components/SignInWithB3/components/AuthButton.js +10 -1
  26. package/dist/cjs/global-account/react/components/SignInWithB3/steps/LoginStepCustom.js +96 -15
  27. package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +5 -3
  28. package/dist/cjs/global-account/react/components/SignInWithB3/utils/signInUtils.js +15 -2
  29. package/dist/cjs/global-account/react/components/Toast/ToastContext.d.ts +3 -0
  30. package/dist/cjs/global-account/react/components/Toast/ToastContext.js +30 -7
  31. package/dist/cjs/global-account/react/hooks/useAuth.js +26 -15
  32. package/dist/cjs/global-account/react/hooks/useAuthentication.js +23 -12
  33. package/dist/cjs/global-account/react/hooks/useConnect.d.ts +2 -2
  34. package/dist/cjs/global-account/react/hooks/useFirstEOA.d.ts +8 -8
  35. package/dist/cjs/global-account/react/hooks/useTWAuth.js +0 -1
  36. package/dist/cjs/global-account/react/stores/useModalStore.d.ts +10 -1
  37. package/dist/cjs/global-account/react/utils/createWagmiConfig.d.ts +0 -18
  38. package/dist/cjs/global-account/react/utils/createWagmiConfig.js +0 -17
  39. package/dist/cjs/shared/utils/session-duration.d.ts +15 -0
  40. package/dist/cjs/shared/utils/session-duration.js +69 -0
  41. package/dist/esm/anyspend/react/components/AnySpendStakeB3.js +2 -2
  42. package/dist/esm/anyspend/react/components/AnySpendStakeB3ExactIn.js +2 -2
  43. package/dist/esm/anyspend/react/components/checkout/CheckoutPaymentPanel.js +2 -4
  44. package/dist/esm/anyspend/react/components/checkout/CheckoutSuccess.d.ts +2 -1
  45. package/dist/esm/anyspend/react/components/checkout/CheckoutSuccess.js +5 -3
  46. package/dist/esm/anyspend/react/components/checkout/FiatCheckoutPanel.js +2 -3
  47. package/dist/esm/anyspend/react/components/checkout/KycGate.js +2 -3
  48. package/dist/esm/anyspend/react/components/common/OrderDetails.js +6 -1
  49. package/dist/esm/anyspend/react/components/common/OrderStatus.js +34 -3
  50. package/dist/esm/anyspend/react/components/common/StepProgress.d.ts +2 -0
  51. package/dist/esm/anyspend/react/components/common/StepProgress.js +4 -2
  52. package/dist/esm/anyspend/react/hooks/useAnyspendCreateOnrampOrder.js +5 -7
  53. package/dist/esm/anyspend/react/hooks/useKycStatus.d.ts +3 -1
  54. package/dist/esm/anyspend/react/hooks/useKycStatus.js +9 -5
  55. package/dist/esm/app.shared.js +9 -7
  56. package/dist/esm/global-account/react/components/B3DynamicModal.js +5 -2
  57. package/dist/esm/global-account/react/components/B3Provider/B3Provider.d.ts +2 -1
  58. package/dist/esm/global-account/react/components/B3Provider/B3Provider.js +2 -2
  59. package/dist/esm/global-account/react/components/B3Provider/B3Provider.native.js +2 -1
  60. package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +3 -1
  61. package/dist/esm/global-account/react/components/B3Provider/LocalSDKProvider.js +3 -1
  62. package/dist/esm/global-account/react/components/ManageAccount/SessionDurationContent.d.ts +5 -0
  63. package/dist/esm/global-account/react/components/ManageAccount/SessionDurationContent.js +52 -0
  64. package/dist/esm/global-account/react/components/ManageAccount/SettingsContent.js +12 -29
  65. package/dist/esm/global-account/react/components/SignInWithB3/components/AuthButton.js +11 -2
  66. package/dist/esm/global-account/react/components/SignInWithB3/steps/LoginStepCustom.js +100 -19
  67. package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +5 -3
  68. package/dist/esm/global-account/react/components/SignInWithB3/utils/signInUtils.js +14 -1
  69. package/dist/esm/global-account/react/components/Toast/ToastContext.d.ts +3 -0
  70. package/dist/esm/global-account/react/components/Toast/ToastContext.js +30 -7
  71. package/dist/esm/global-account/react/hooks/useAuth.js +28 -17
  72. package/dist/esm/global-account/react/hooks/useAuthentication.js +24 -13
  73. package/dist/esm/global-account/react/hooks/useConnect.d.ts +2 -2
  74. package/dist/esm/global-account/react/hooks/useFirstEOA.d.ts +8 -8
  75. package/dist/esm/global-account/react/hooks/useTWAuth.js +0 -1
  76. package/dist/esm/global-account/react/stores/useModalStore.d.ts +10 -1
  77. package/dist/esm/global-account/react/utils/createWagmiConfig.d.ts +0 -18
  78. package/dist/esm/global-account/react/utils/createWagmiConfig.js +0 -16
  79. package/dist/esm/shared/utils/session-duration.d.ts +15 -0
  80. package/dist/esm/shared/utils/session-duration.js +64 -0
  81. package/dist/styles/index.css +1 -1
  82. package/dist/types/anyspend/react/components/checkout/CheckoutSuccess.d.ts +2 -1
  83. package/dist/types/anyspend/react/components/common/StepProgress.d.ts +2 -0
  84. package/dist/types/anyspend/react/hooks/useKycStatus.d.ts +3 -1
  85. package/dist/types/global-account/react/components/B3Provider/B3Provider.d.ts +2 -1
  86. package/dist/types/global-account/react/components/B3Provider/LocalSDKProvider.d.ts +3 -1
  87. package/dist/types/global-account/react/components/ManageAccount/SessionDurationContent.d.ts +5 -0
  88. package/dist/types/global-account/react/components/SignInWithB3/utils/signInUtils.d.ts +5 -3
  89. package/dist/types/global-account/react/components/Toast/ToastContext.d.ts +3 -0
  90. package/dist/types/global-account/react/hooks/useConnect.d.ts +2 -2
  91. package/dist/types/global-account/react/hooks/useFirstEOA.d.ts +8 -8
  92. package/dist/types/global-account/react/stores/useModalStore.d.ts +10 -1
  93. package/dist/types/global-account/react/utils/createWagmiConfig.d.ts +0 -18
  94. package/dist/types/shared/utils/session-duration.d.ts +15 -0
  95. package/package.json +2 -1
  96. package/src/anyspend/react/components/AnySpendStakeB3.tsx +2 -2
  97. package/src/anyspend/react/components/AnySpendStakeB3ExactIn.tsx +2 -2
  98. package/src/anyspend/react/components/checkout/CheckoutPaymentPanel.tsx +2 -4
  99. package/src/anyspend/react/components/checkout/CheckoutSuccess.tsx +13 -3
  100. package/src/anyspend/react/components/checkout/FiatCheckoutPanel.tsx +9 -3
  101. package/src/anyspend/react/components/checkout/KycGate.tsx +8 -3
  102. package/src/anyspend/react/components/common/OrderDetails.tsx +8 -0
  103. package/src/anyspend/react/components/common/OrderStatus.tsx +38 -3
  104. package/src/anyspend/react/components/common/StepProgress.tsx +15 -5
  105. package/src/anyspend/react/hooks/useAnyspendCreateOnrampOrder.ts +5 -7
  106. package/src/anyspend/react/hooks/useKycStatus.ts +8 -5
  107. package/src/app.shared.ts +9 -8
  108. package/src/global-account/react/components/B3DynamicModal.tsx +5 -2
  109. package/src/global-account/react/components/B3Provider/B3Provider.native.tsx +2 -1
  110. package/src/global-account/react/components/B3Provider/B3Provider.tsx +7 -1
  111. package/src/global-account/react/components/B3Provider/LocalSDKProvider.tsx +5 -0
  112. package/src/global-account/react/components/ManageAccount/SessionDurationContent.tsx +107 -0
  113. package/src/global-account/react/components/ManageAccount/SettingsContent.tsx +28 -30
  114. package/src/global-account/react/components/SignInWithB3/components/AuthButton.tsx +21 -2
  115. package/src/global-account/react/components/SignInWithB3/steps/LoginStepCustom.tsx +207 -54
  116. package/src/global-account/react/components/SignInWithB3/utils/signInUtils.ts +19 -3
  117. package/src/global-account/react/components/Toast/ToastContext.tsx +39 -7
  118. package/src/global-account/react/hooks/useAuth.ts +28 -17
  119. package/src/global-account/react/hooks/useAuthentication.ts +24 -13
  120. package/src/global-account/react/hooks/useConnect.tsx +2 -2
  121. package/src/global-account/react/hooks/useTWAuth.tsx +0 -1
  122. package/src/global-account/react/stores/useModalStore.ts +11 -0
  123. package/src/global-account/react/utils/createWagmiConfig.tsx +0 -18
  124. package/src/shared/utils/session-duration.ts +64 -0
  125. package/src/types/torph.d.ts +4 -0
@@ -1,8 +1,8 @@
1
1
  import { AuthenticationClient } from "@feathersjs/authentication-client";
2
2
  import Cookies from "js-cookie";
3
3
  import { B3_AUTH_COOKIE_NAME } from "./shared/constants/index.js";
4
+ import { getSessionDurationDays } from "./shared/utils/session-duration.js";
4
5
  export const B3_API_URL = process.env.EXPO_PUBLIC_B3_API || process.env.NEXT_PUBLIC_B3_API || process.env.PUBLIC_B3_API || "https://api.b3.fun";
5
- const DEV_USER_GROUP = 4;
6
6
  export const authenticate = async (app, accessToken, identityToken, params) => {
7
7
  const fullToken = `${accessToken}+${identityToken}`;
8
8
  // Do not authenticate if there is no token
@@ -17,12 +17,14 @@ export const authenticate = async (app, accessToken, identityToken, params) => {
17
17
  }, {
18
18
  query: params || {},
19
19
  });
20
- // Extend cookie expiration to 30 days for dev users
21
- if (response?.user?.userGroups?.includes(DEV_USER_GROUP)) {
22
- const token = Cookies.get(B3_AUTH_COOKIE_NAME);
23
- if (token) {
24
- Cookies.set(B3_AUTH_COOKIE_NAME, token, { expires: 30 });
25
- }
20
+ const token = Cookies.get(B3_AUTH_COOKIE_NAME);
21
+ if (token) {
22
+ const days = getSessionDurationDays(response?.user?.preferences, params?.partnerId);
23
+ Cookies.set(B3_AUTH_COOKIE_NAME, token, {
24
+ ...(days > 0 ? { expires: days } : {}),
25
+ secure: true,
26
+ sameSite: "Lax",
27
+ });
26
28
  }
27
29
  return response;
28
30
  }
@@ -17,6 +17,7 @@ import { LinkAccount } from "./LinkAccount/LinkAccount.js";
17
17
  import { LinkNewAccount } from "./LinkAccount/LinkNewAccount.js";
18
18
  import { ManageAccount } from "./ManageAccount/ManageAccount.js";
19
19
  import NotificationsContent from "./ManageAccount/NotificationsContent.js";
20
+ import SessionDurationContent from "./ManageAccount/SessionDurationContent.js";
20
21
  import { RequestPermissions } from "./RequestPermissions/RequestPermissions.js";
21
22
  import { Send } from "./Send/Send.js";
22
23
  import { SignInWithB3Flow } from "./SignInWithB3/SignInWithB3Flow.js";
@@ -31,7 +32,7 @@ export function B3DynamicModal() {
31
32
  const navigateBack = useModalStore(state => state.navigateBack);
32
33
  const { theme } = useB3Config();
33
34
  const isMobile = useIsMobile();
34
- const { toasts, removeToast } = useToastContext();
35
+ const { toasts, removeToast, headerMode } = useToastContext();
35
36
  // Define arrays for different modal type groups
36
37
  const fullWidthTypes = [
37
38
  "anySpend",
@@ -140,6 +141,8 @@ export function B3DynamicModal() {
140
141
  return _jsx(Send, { ...contentType });
141
142
  case "notifications":
142
143
  return _jsx(NotificationsContent, { ...contentType });
144
+ case "sessionDuration":
145
+ return _jsx(SessionDurationContent, { partnerId: contentType.partnerId });
143
146
  // Add other modal types here
144
147
  default:
145
148
  return null;
@@ -162,7 +165,7 @@ export function B3DynamicModal() {
162
165
  contentType?.type === "send" ||
163
166
  contentType?.type === "avatarEditor" ||
164
167
  contentType?.type === "notifications") &&
165
- "p-0", "mx-auto w-full max-w-md sm:max-w-lg"), hideCloseButton: hideCloseButton, hideGABranding: isAnySpendType, onEscapeKeyDown: !isClosable ? e => e.preventDefault() : undefined, children: [_jsx(ModalTitle, { className: "sr-only hidden", children: contentType?.type || "Modal" }), _jsx(ModalDescription, { className: "sr-only hidden", children: contentType?.type || "Modal Body" }), _jsxs("div", { className: cn("b3-modal-content no-scrollbar dark:bg-b3-background flex max-h-[90dvh] flex-col overflow-auto sm:max-h-[80dvh]"), children: [!hideCloseButton && (_jsxs("button", { onClick: navigateBack, className: "flex items-center gap-2 px-6 py-4 text-gray-600 transition-colors hover:text-gray-900 dark:text-gray-400 dark:hover:text-white", children: [_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M15.8337 10H4.16699", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M10.0003 15.8334L4.16699 10L10.0003 4.16669", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }), _jsx("span", { className: "font-inter text-sm font-semibold", children: "Back" })] })), _jsx("div", { className: "flex-1", children: renderContent() }), _jsx(AnimatePresence, { children: toasts.length > 0 && (_jsx(motion.div, { initial: { height: 0 }, animate: { height: "auto" }, exit: { height: 0 }, transition: { duration: 0.3, ease: "easeInOut" }, className: "toast-section relative z-10 overflow-hidden bg-white dark:border-neutral-800 dark:bg-neutral-900", children: _jsx(motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -10 }, transition: { duration: 0.2, delay: 0.1 }, className: "p-4 pt-0", children: _jsx(ToastContainer, { toasts: toasts, onDismiss: removeToast, theme: theme }) }) })) })] })] }), isOpen && !isAnySpendType && (_jsx("style", { children: `
168
+ "p-0", "mx-auto w-full max-w-md sm:max-w-lg"), hideCloseButton: hideCloseButton, hideGABranding: isAnySpendType, onEscapeKeyDown: !isClosable ? e => e.preventDefault() : undefined, children: [_jsx(ModalTitle, { className: "sr-only hidden", children: contentType?.type || "Modal" }), _jsx(ModalDescription, { className: "sr-only hidden", children: contentType?.type || "Modal Body" }), _jsxs("div", { className: cn("b3-modal-content no-scrollbar dark:bg-b3-background flex max-h-[90dvh] flex-col overflow-auto sm:max-h-[80dvh]"), children: [!hideCloseButton && (_jsxs("button", { onClick: navigateBack, className: "flex items-center gap-2 px-6 py-4 text-gray-600 transition-colors hover:text-gray-900 dark:text-gray-400 dark:hover:text-white", children: [_jsxs("svg", { width: "20", height: "20", viewBox: "0 0 20 20", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: [_jsx("path", { d: "M15.8337 10H4.16699", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" }), _jsx("path", { d: "M10.0003 15.8334L4.16699 10L10.0003 4.16669", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round" })] }), _jsx("span", { className: "font-inter text-sm font-semibold", children: "Back" })] })), _jsx("div", { className: "flex-1", children: renderContent() }), _jsx(AnimatePresence, { children: !headerMode && toasts.length > 0 && (_jsx(motion.div, { initial: { height: 0 }, animate: { height: "auto" }, exit: { height: 0 }, transition: { duration: 0.3, ease: "easeInOut" }, className: "toast-section relative z-10 overflow-hidden bg-white dark:border-neutral-800 dark:bg-neutral-900", children: _jsx(motion.div, { initial: { opacity: 0, y: -10 }, animate: { opacity: 1, y: 0 }, exit: { opacity: 0, y: -10 }, transition: { duration: 0.2, delay: 0.1 }, className: "p-4 pt-0", children: _jsx(ToastContainer, { toasts: toasts, onDismiss: removeToast, theme: theme }) }) })) })] })] }), isOpen && !isAnySpendType && (_jsx("style", { children: `
166
169
  .modal-inner-content {
167
170
  transition: margin-bottom 0.3s ease-in-out;
168
171
  margin-bottom: ${toasts.length > 0 ? "0px" : "23px"} !important;
@@ -8,7 +8,7 @@ import { ClientType } from "../../../client-manager";
8
8
  /**
9
9
  * Main B3Provider component
10
10
  */
11
- export declare function B3Provider({ theme, children, accountOverride, environment, automaticallySetFirstEoa, defaultEoaProvider, simDuneApiKey, toaster: _toaster, clientType, rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors, createClientReferenceId, defaultPermissions, }: {
11
+ export declare function B3Provider({ theme, children, accountOverride, environment, automaticallySetFirstEoa, defaultEoaProvider, simDuneApiKey, toaster: _toaster, clientType, rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors, createClientReferenceId, defaultPermissions, disableBSMNTAuthentication, }: {
12
12
  theme: "light" | "dark";
13
13
  children: React.ReactNode;
14
14
  accountOverride?: Account;
@@ -32,4 +32,5 @@ export declare function B3Provider({ theme, children, accountOverride, environme
32
32
  overrideDefaultConnectors?: boolean;
33
33
  createClientReferenceId?: (params: CreateOrderParams | CreateOnrampOrderParams) => Promise<string>;
34
34
  defaultPermissions?: PermissionsConfig;
35
+ disableBSMNTAuthentication?: boolean;
35
36
  }): import("react/jsx-runtime").JSX.Element;
@@ -20,7 +20,7 @@ const queryClient = new QueryClient();
20
20
  */
21
21
  export function B3Provider({ theme = "light", children, accountOverride, environment, automaticallySetFirstEoa, defaultEoaProvider, simDuneApiKey,
22
22
  // deprecated since v0.0.87
23
- toaster: _toaster, clientType = "rest", rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors = false, createClientReferenceId, defaultPermissions, }) {
23
+ toaster: _toaster, clientType = "rest", rpcUrls, partnerId, stripePublishableKey, onConnect, onLogout, connectors, overrideDefaultConnectors = false, createClientReferenceId, defaultPermissions, disableBSMNTAuthentication = false, }) {
24
24
  // Initialize Google Analytics on mount
25
25
  useEffect(() => {
26
26
  loadGA4Script();
@@ -30,7 +30,7 @@ toaster: _toaster, clientType = "rest", rpcUrls, partnerId, stripePublishableKey
30
30
  setClientType(clientType);
31
31
  }, [clientType]);
32
32
  const wagmiConfig = useMemo(() => createWagmiConfig({ partnerId, rpcUrls, connectors, overrideDefaultConnectors }), [partnerId, rpcUrls, connectors, overrideDefaultConnectors]);
33
- return (_jsx(ThirdwebProvider, { children: _jsx(WagmiProvider, { config: wagmiConfig, reconnectOnMount: false, children: _jsx(QueryClientProvider, { client: queryClient, children: _jsx(TooltipProvider, { children: _jsx(ToastProvider, { children: _jsx(LocalSDKProvider, { onConnectCallback: onConnect, onLogoutCallback: onLogout, children: _jsxs(B3ConfigProvider, { accountOverride: accountOverride, environment: environment, automaticallySetFirstEoa: !!automaticallySetFirstEoa, theme: theme, clientType: clientType, partnerId: partnerId, stripePublishableKey: stripePublishableKey, createClientReferenceId: createClientReferenceId, defaultPermissions: defaultPermissions, children: [_jsx(ToastContextConnector, {}), _jsxs(RelayKitProviderWrapper, { simDuneApiKey: simDuneApiKey, children: [children, _jsx(StyleRoot, { id: "b3-root" })] }), _jsx(AuthenticationProvider, { partnerId: partnerId, automaticallySetFirstEoa: !!automaticallySetFirstEoa, defaultEoaProvider: defaultEoaProvider })] }) }) }) }) }) }) }));
33
+ return (_jsx(ThirdwebProvider, { children: _jsx(WagmiProvider, { config: wagmiConfig, reconnectOnMount: false, children: _jsx(QueryClientProvider, { client: queryClient, children: _jsx(TooltipProvider, { children: _jsx(ToastProvider, { children: _jsx(LocalSDKProvider, { onConnectCallback: onConnect, onLogoutCallback: onLogout, disableBSMNTAuthentication: disableBSMNTAuthentication, children: _jsxs(B3ConfigProvider, { accountOverride: accountOverride, environment: environment, automaticallySetFirstEoa: !!automaticallySetFirstEoa, theme: theme, clientType: clientType, partnerId: partnerId, stripePublishableKey: stripePublishableKey, createClientReferenceId: createClientReferenceId, defaultPermissions: defaultPermissions, children: [_jsx(ToastContextConnector, {}), _jsxs(RelayKitProviderWrapper, { simDuneApiKey: simDuneApiKey, children: [children, _jsx(StyleRoot, { id: "b3-root" })] }), _jsx(AuthenticationProvider, { partnerId: partnerId, automaticallySetFirstEoa: !!automaticallySetFirstEoa, defaultEoaProvider: defaultEoaProvider })] }) }) }) }) }) }) }));
34
34
  }
35
35
  /**
36
36
  * Component to connect the toast context to the global toast API
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
3
3
  import { ThirdwebProvider } from "thirdweb/react";
4
+ import { useMemo } from "react";
4
5
  import { WagmiProvider } from "wagmi";
5
6
  import { createWagmiConfig } from "../../utils/createWagmiConfig.js";
6
7
  import AuthenticationProvider from "./AuthenticationProvider.js";
@@ -18,6 +19,6 @@ export function B3Provider({ theme = "light", children, accountOverride, environ
18
19
  * Inner provider component for native
19
20
  */
20
21
  export function InnerProvider({ children, accountOverride, environment, defaultPermissions, theme = "light", clientType = "socket", partnerId, rpcUrls, }) {
21
- const wagmiConfig = createWagmiConfig({ partnerId, rpcUrls });
22
+ const wagmiConfig = useMemo(() => createWagmiConfig({ partnerId, rpcUrls }), [partnerId, rpcUrls]);
22
23
  return (_jsx(WagmiProvider, { config: wagmiConfig, children: _jsx(QueryClientProvider, { client: queryClient, children: _jsx(B3ConfigProvider, { accountOverride: accountOverride, environment: environment, automaticallySetFirstEoa: false, theme: theme, clientType: clientType, partnerId: partnerId, defaultPermissions: defaultPermissions, children: children }) }) }));
23
24
  }
@@ -6,13 +6,15 @@ import { Wallet } from "thirdweb/wallets";
6
6
  export interface LocalSDKContextType {
7
7
  onConnectCallback?: (wallet: Wallet, b3Jwt: string) => void | Promise<void>;
8
8
  onLogoutCallback?: () => void | Promise<void>;
9
+ disableBSMNTAuthentication?: boolean;
9
10
  }
10
11
  export declare const LocalSDKContext: import("react").Context<LocalSDKContextType>;
11
12
  /**
12
13
  * Local SDK Provider that wraps the app and provides internal SDK state
13
14
  */
14
- export declare function LocalSDKProvider({ children, onConnectCallback, onLogoutCallback, }: {
15
+ export declare function LocalSDKProvider({ children, onConnectCallback, onLogoutCallback, disableBSMNTAuthentication, }: {
15
16
  children: React.ReactNode;
16
17
  onConnectCallback?: (wallet: Wallet, b3Jwt: string) => void | Promise<void>;
17
18
  onLogoutCallback?: () => void | Promise<void>;
19
+ disableBSMNTAuthentication?: boolean;
18
20
  }): import("react/jsx-runtime").JSX.Element;
@@ -3,13 +3,15 @@ import { createContext } from "react";
3
3
  export const LocalSDKContext = createContext({
4
4
  onConnectCallback: undefined,
5
5
  onLogoutCallback: undefined,
6
+ disableBSMNTAuthentication: false,
6
7
  });
7
8
  /**
8
9
  * Local SDK Provider that wraps the app and provides internal SDK state
9
10
  */
10
- export function LocalSDKProvider({ children, onConnectCallback, onLogoutCallback, }) {
11
+ export function LocalSDKProvider({ children, onConnectCallback, onLogoutCallback, disableBSMNTAuthentication, }) {
11
12
  return (_jsx(LocalSDKContext.Provider, { value: {
12
13
  onConnectCallback,
13
14
  onLogoutCallback,
15
+ disableBSMNTAuthentication,
14
16
  }, children: children }));
15
17
  }
@@ -0,0 +1,5 @@
1
+ interface SessionDurationContentProps {
2
+ partnerId: string;
3
+ }
4
+ declare const SessionDurationContent: ({ partnerId }: SessionDurationContentProps) => import("react/jsx-runtime").JSX.Element;
5
+ export default SessionDurationContent;
@@ -0,0 +1,52 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import app from "../../../../global-account/app.js";
3
+ import { useAuthentication, useModalStore } from "../../../../global-account/react/index.js";
4
+ import { getSessionDurationDays, SESSION_DURATION_LABELS, SESSION_DURATION_OPTIONS, setSessionDurationDays, } from "../../../../shared/utils/session-duration.js";
5
+ import { useState } from "react";
6
+ import ModalHeader from "../ModalHeader/ModalHeader.js";
7
+ const DESCRIPTIONS = {
8
+ 0: "Sign out when browser closes",
9
+ 1: "Stay signed in for 1 day",
10
+ 7: "Stay signed in for 7 days",
11
+ 14: "Stay signed in for 2 weeks",
12
+ 30: "Stay signed in for 30 days",
13
+ };
14
+ const SessionDurationContent = ({ partnerId }) => {
15
+ const { user, setUser } = useAuthentication(partnerId);
16
+ const navigateBack = useModalStore(state => state.navigateBack);
17
+ const [sessionDays, setSessionDays] = useState(() => getSessionDurationDays(user?.preferences, partnerId));
18
+ const [saving, setSaving] = useState(false);
19
+ const handleSelect = async (days) => {
20
+ const previous = sessionDays;
21
+ setSessionDurationDays(days, partnerId);
22
+ setSessionDays(days);
23
+ if (user?.userId) {
24
+ setSaving(true);
25
+ try {
26
+ const updated = await app.service("users").patch(user.userId, {
27
+ preferences: {
28
+ ...user.preferences,
29
+ [partnerId]: {
30
+ ...((user.preferences ?? {})[partnerId] ?? {}),
31
+ sessionDuration: days,
32
+ },
33
+ },
34
+ });
35
+ setUser(updated);
36
+ }
37
+ catch (error) {
38
+ console.error("Failed to save session duration preference:", error);
39
+ // Revert optimistic update so UI stays consistent with server state
40
+ setSessionDays(previous);
41
+ setSessionDurationDays(previous, partnerId);
42
+ }
43
+ finally {
44
+ setSaving(false);
45
+ }
46
+ }
47
+ };
48
+ return (_jsxs("div", { className: "flex h-[470px] flex-col", children: [_jsx(ModalHeader, { showBackButton: true, showCloseButton: false, title: "Stay signed in", handleBack: navigateBack }), _jsx("div", { className: "flex flex-col gap-2 p-5", children: SESSION_DURATION_OPTIONS.map(days => (_jsxs("button", { type: "button", onClick: () => handleSelect(days), disabled: saving, className: `flex items-center justify-between rounded-xl border px-4 py-3 transition-colors ${sessionDays === days
49
+ ? "border-[#3f3f46] bg-[#f4f4f5] dark:border-white dark:bg-white/10"
50
+ : "border-[#e4e4e7] bg-transparent hover:bg-[#f4f4f5] dark:border-white/10 dark:hover:bg-white/5"}`, children: [_jsxs("div", { className: "flex flex-col items-start gap-0.5", children: [_jsx("span", { className: "font-neue-montreal-semibold text-[14px] leading-none tracking-[-0.28px] text-[#3f3f46] dark:text-white", children: SESSION_DURATION_LABELS[days] }), _jsx("span", { className: "font-neue-montreal-medium text-[13px] leading-none tracking-[-0.26px] text-[#70707b] dark:text-white/50", children: DESCRIPTIONS[days] })] }), sessionDays === days && (_jsx("div", { className: "flex size-5 items-center justify-center rounded-full bg-[#3f3f46] dark:bg-white", children: _jsx("svg", { width: "10", height: "8", viewBox: "0 0 10 8", fill: "none", children: _jsx("path", { d: "M1 4L3.5 6.5L9 1", stroke: "white", strokeWidth: "1.5", strokeLinecap: "round", strokeLinejoin: "round", className: "dark:stroke-[#3f3f46]" }) }) }))] }, days))) })] }));
51
+ };
52
+ export default SessionDurationContent;
@@ -1,6 +1,7 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useAuthentication, useModalStore } from "../../../../global-account/react/index.js";
3
3
  import { client } from "../../../../shared/utils/thirdweb.js";
4
+ import { getSessionDurationDays, SESSION_DURATION_LABELS } from "../../../../shared/utils/session-duration.js";
4
5
  import { Loader2 } from "lucide-react";
5
6
  import { useState } from "react";
6
7
  import { useProfiles } from "thirdweb/react";
@@ -11,47 +12,29 @@ import SettingsProfileCard from "./SettingsProfileCard.js";
11
12
  const SettingsContent = ({ partnerId, onLogout, chain, }) => {
12
13
  const setB3ModalContentType = useModalStore(state => state.setB3ModalContentType);
13
14
  const setB3ModalOpen = useModalStore(state => state.setB3ModalOpen);
14
- const { logout } = useAuthentication(partnerId);
15
+ const { logout, user } = useAuthentication(partnerId);
15
16
  const [logoutLoading, setLogoutLoading] = useState(false);
17
+ const sessionDays = getSessionDurationDays(user?.preferences, partnerId);
16
18
  const { data: profilesRaw = [] } = useProfiles({ client });
17
19
  const profiles = profilesRaw.filter((profile) => !["custom_auth_endpoint"].includes(profile.type));
18
20
  const handleNavigate = (type) => {
19
21
  if (type === "home") {
20
- setB3ModalContentType({
21
- type: "manageAccount",
22
- chain,
23
- partnerId,
24
- onLogout,
25
- activeTab: "home",
26
- });
22
+ setB3ModalContentType({ type: "manageAccount", chain, partnerId, onLogout, activeTab: "home" });
27
23
  }
28
24
  else if (type === "swap") {
29
- setB3ModalContentType({
30
- type: "manageAccount",
31
- chain,
32
- partnerId,
33
- onLogout,
34
- activeTab: "tokens",
35
- });
25
+ setB3ModalContentType({ type: "manageAccount", chain, partnerId, onLogout, activeTab: "tokens" });
36
26
  }
37
27
  else if (type === "linkAccount") {
38
- setB3ModalContentType({
39
- type: "linkAccount",
40
- chain,
41
- partnerId,
42
- });
28
+ setB3ModalContentType({ type: "linkAccount", chain, partnerId });
43
29
  }
44
30
  else if (type === "notifications") {
45
- setB3ModalContentType({
46
- type: "notifications",
47
- chain,
48
- partnerId,
49
- });
31
+ setB3ModalContentType({ type: "notifications", chain, partnerId });
32
+ }
33
+ else if (type === "sessionDuration") {
34
+ setB3ModalContentType({ type: "sessionDuration", chain, partnerId });
50
35
  }
51
36
  else {
52
- setB3ModalContentType({
53
- type: "avatarEditor",
54
- });
37
+ setB3ModalContentType({ type: "avatarEditor" });
55
38
  }
56
39
  setB3ModalOpen(true);
57
40
  };
@@ -62,7 +45,7 @@ const SettingsContent = ({ partnerId, onLogout, chain, }) => {
62
45
  setB3ModalOpen(false);
63
46
  setLogoutLoading(false);
64
47
  };
65
- return (_jsxs("div", { className: "flex h-[470px] flex-col", children: [_jsx(ModalHeader, { showBackButton: false, showCloseButton: false, title: "Settings" }), _jsx("div", { className: "p-5", children: _jsx("div", { className: "b3-modal-settings-profile-card dark:border-b3-line dark:bg-b3-background flex items-center rounded-xl border border-[#e4e4e7] bg-[#f4f4f5] p-4", children: _jsx(SettingsProfileCard, {}) }) }), _jsxs("div", { className: "space-y-3 px-5", children: [_jsx(SettingsMenuItem, { icon: _jsx("svg", { width: "40", height: "40", viewBox: "0 0 40 40", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M0 12C0 5.37258 5.37258 0 12 0H28C34.6274 0 40 5.37258 40 12V28C40 34.6274 34.6274 40 28 40H12C5.37258 40 0 34.6274 0 28V12Z", fill: "#F4F4F5" }) }), title: "Linked Accounts", subtitle: `${profiles.length} connected account${profiles.length > 1 ? "s" : ""}`, onClick: () => handleNavigate("linkAccount") }), _jsx(SettingsMenuItem, { icon: _jsx("svg", { width: "40", height: "40", viewBox: "0 0 40 40", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M0 12C0 5.37258 5.37258 0 12 0H28C34.6274 0 40 5.37258 40 12V28C40 34.6274 34.6274 40 28 40H12C5.37258 40 0 34.6274 0 28V12Z", fill: "#F4F4F5" }) }), title: "Notifications", subtitle: "Manage your notifications", onClick: () => handleNavigate("notifications") })] }), _jsx("div", { className: "mt-auto px-5 pb-5", children: _jsxs("button", { className: "b3-modal-sign-out-button border-b3-line hover:bg-b3-line bg-b3-background dark:bg-b3-background dark:border-b3-line dark:hover:bg-b3-line/80 flex w-full items-center justify-center gap-1.5 rounded-xl border border-solid p-3 transition-colors", onClick: onLogoutEnhanced, disabled: logoutLoading, style: {
48
+ return (_jsxs("div", { className: "flex h-[470px] flex-col", children: [_jsx(ModalHeader, { showBackButton: false, showCloseButton: false, title: "Settings" }), _jsx("div", { className: "p-5", children: _jsx("div", { className: "b3-modal-settings-profile-card dark:border-b3-line dark:bg-b3-background flex items-center rounded-xl border border-[#e4e4e7] bg-[#f4f4f5] p-4", children: _jsx(SettingsProfileCard, {}) }) }), _jsxs("div", { className: "space-y-3 px-5", children: [_jsx(SettingsMenuItem, { icon: _jsx("svg", { width: "40", height: "40", viewBox: "0 0 40 40", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M0 12C0 5.37258 5.37258 0 12 0H28C34.6274 0 40 5.37258 40 12V28C40 34.6274 34.6274 40 28 40H12C5.37258 40 0 34.6274 0 28V12Z", fill: "#F4F4F5" }) }), title: "Linked Accounts", subtitle: `${profiles.length} connected account${profiles.length > 1 ? "s" : ""}`, onClick: () => handleNavigate("linkAccount") }), _jsx(SettingsMenuItem, { icon: _jsx("svg", { width: "40", height: "40", viewBox: "0 0 40 40", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M0 12C0 5.37258 5.37258 0 12 0H28C34.6274 0 40 5.37258 40 12V28C40 34.6274 34.6274 40 28 40H12C5.37258 40 0 34.6274 0 28V12Z", fill: "#F4F4F5" }) }), title: "Notifications", subtitle: "Manage your notifications", onClick: () => handleNavigate("notifications") }), _jsx(SettingsMenuItem, { icon: _jsx("svg", { width: "40", height: "40", viewBox: "0 0 40 40", fill: "none", xmlns: "http://www.w3.org/2000/svg", children: _jsx("path", { d: "M0 12C0 5.37258 5.37258 0 12 0H28C34.6274 0 40 5.37258 40 12V28C40 34.6274 34.6274 40 28 40H12C5.37258 40 0 34.6274 0 28V12Z", fill: "#F4F4F5" }) }), title: "Stay signed in", subtitle: SESSION_DURATION_LABELS[sessionDays] ?? `${sessionDays} days`, onClick: () => handleNavigate("sessionDuration") })] }), _jsx("div", { className: "mt-auto px-5 pb-5", children: _jsxs("button", { type: "button", className: "b3-modal-sign-out-button border-b3-line hover:bg-b3-line bg-b3-background dark:bg-b3-background dark:border-b3-line dark:hover:bg-b3-line/80 flex w-full items-center justify-center gap-1.5 rounded-xl border border-solid p-3 transition-colors", onClick: onLogoutEnhanced, disabled: logoutLoading, style: {
66
49
  boxShadow: "inset 0px 0px 0px 1px rgba(10,13,18,0.18), inset 0px -2px 0px 0px rgba(10,13,18,0.05)",
67
50
  }, children: [logoutLoading ? (_jsx(Loader2, { className: "text-b3-grey animate-spin", size: 20 })) : (_jsx(SignOutIcon, { size: 20, className: "text-b3-grey", color: "currentColor" })), _jsx("p", { className: "text-b3-grey dark:text-b3-foreground-muted font-neue-montreal-semibold text-base", children: "Sign out" })] }) })] }));
68
51
  };
@@ -1,6 +1,15 @@
1
1
  import { jsx as _jsx } from "react/jsx-runtime";
2
2
  import { Button } from "../../custom/Button.js";
3
- import { strategyIcons } from "../utils/signInUtils.js";
3
+ import { Github, Mail } from "lucide-react";
4
+ import { strategyIcons, strategyLabels } from "../utils/signInUtils.js";
5
+ const fallbackIcons = {
6
+ github: Github,
7
+ email: Mail,
8
+ };
4
9
  export function AuthButton({ strategy, onClick, isLoading, }) {
5
- return (_jsx(Button, { onClick: onClick, disabled: isLoading, className: "flex w-full items-center justify-center bg-gray-100 px-2 py-3 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700", children: _jsx("img", { src: strategyIcons[strategy], className: "h-9 w-9" }) }, strategy));
10
+ const strategyIcon = strategyIcons[strategy];
11
+ const strategyLabel = strategyLabels[strategy] || strategy;
12
+ const FallbackIcon = fallbackIcons[strategy];
13
+ const buttonLabel = `Sign in with ${strategyLabel}`;
14
+ return (_jsx(Button, { onClick: onClick, disabled: isLoading, "aria-label": buttonLabel, title: buttonLabel, className: "flex w-full items-center justify-center bg-gray-100 px-2 py-3 hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700", children: strategyIcon ? (_jsx("img", { src: strategyIcon, alt: `${strategyLabel} icon`, className: "h-9 w-9" })) : FallbackIcon ? (_jsx(FallbackIcon, { className: "h-9 w-9 text-gray-900 dark:text-gray-100" })) : (_jsx("span", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: strategyLabel.charAt(0) })) }, strategy));
6
15
  }
@@ -1,38 +1,52 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { AuthButton, Button, getConnectOptionsFromStrategy, isWalletType, LoginStepContainer, useAuthentication, useAuthStore, useB3Config, useConnect, WalletRow, } from "../../../../../global-account/react/index.js";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { AuthButton, Button, getConnectOptionsFromStrategy, Input, isWalletType, LoginStepContainer, useAuthentication, useAuthStore, useB3Config, useConnect, WalletRow, } from "../../../../../global-account/react/index.js";
3
+ import { ecosystemWalletId } from "../../../../../shared/constants/index.js";
3
4
  import { debugB3React } from "../../../../../shared/utils/debug.js";
4
5
  import { client } from "../../../../../shared/utils/thirdweb.js";
5
6
  import { useState } from "react";
6
- import { useConnect as useConnectTW } from "thirdweb/react";
7
- import { createWallet } from "thirdweb/wallets";
7
+ import { useConnectedWallets, useConnect as useConnectTW } from "thirdweb/react";
8
+ import { createWallet, preAuthenticate, } from "thirdweb/wallets";
8
9
  const debug = debugB3React("LoginStepCustom");
10
+ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
9
11
  export function LoginStepCustom({ onSuccess, onError, chain, strategies, maxInitialWallets = 2, automaticallySetFirstEoa, }) {
10
12
  const { partnerId } = useB3Config();
11
13
  const [isLoading, setIsLoading] = useState(false);
12
14
  const [showAllWallets, setShowAllWallets] = useState(false);
15
+ const [showEmailFlow, setShowEmailFlow] = useState(false);
16
+ const [email, setEmail] = useState("");
17
+ const [verificationCode, setVerificationCode] = useState("");
18
+ const [emailCodeSent, setEmailCodeSent] = useState(false);
19
+ const [emailError, setEmailError] = useState(null);
13
20
  const { connect } = useConnect(partnerId, chain);
14
21
  const setIsAuthenticating = useAuthStore(state => state.setIsAuthenticating);
15
- const setIsAuthenticated = useAuthStore(state => state.setIsAuthenticated);
16
- const { logout } = useAuthentication(partnerId, { skipAutoConnect: true });
22
+ const { connect: onAuthConnect, logout } = useAuthentication(partnerId, { skipAutoConnect: true });
17
23
  const { connect: connectTW } = useConnectTW();
24
+ const connectedWallets = useConnectedWallets();
18
25
  // Split strategies into auth and wallet types
19
26
  const authStrategies = strategies.filter(s => !isWalletType(s));
20
27
  const walletStrategies = strategies.filter(isWalletType);
21
28
  const initialWallets = walletStrategies.slice(0, maxInitialWallets);
22
29
  const additionalWallets = walletStrategies.slice(maxInitialWallets);
23
- const handleConnect = async (strategy) => {
30
+ const authGridColumns = Math.max(1, Math.min(authStrategies.length, 4));
31
+ const resetEmailFlow = () => {
32
+ setShowEmailFlow(false);
33
+ setEmailCodeSent(false);
34
+ setVerificationCode("");
35
+ setEmailError(null);
36
+ };
37
+ const connectWithOptions = async (strategy, options) => {
24
38
  try {
25
39
  setIsLoading(true);
26
40
  debug("setIsAuthenticating:true:3");
27
41
  setIsAuthenticating(true);
28
- const options = getConnectOptionsFromStrategy(strategy);
29
42
  let connectResult;
30
- if (automaticallySetFirstEoa) {
31
- if (!options.wallet?.id) {
43
+ if (automaticallySetFirstEoa && isWalletType(strategy) && options.strategy === "wallet") {
44
+ const walletId = options.wallet?.id;
45
+ if (!walletId) {
32
46
  throw new Error("Wallet ID is required");
33
47
  }
34
48
  connectResult = await connectTW(async () => {
35
- const wallet = createWallet(options.wallet?.id);
49
+ const wallet = createWallet(walletId);
36
50
  await wallet.connect({
37
51
  client,
38
52
  });
@@ -40,20 +54,27 @@ export function LoginStepCustom({ onSuccess, onError, chain, strategies, maxInit
40
54
  });
41
55
  }
42
56
  else {
43
- // @ts-expect-error we have custom strategies too and we also get things like "apple" isn't assignable to "wallet"
44
57
  connectResult = await connect(options);
45
58
  }
46
59
  const account = connectResult?.getAccount();
47
60
  debug("@@connectResult", { connectResult, account, options });
48
- if (!account)
61
+ if (!account || !connectResult)
49
62
  throw new Error("Failed to connect");
63
+ const allConnectedWallets = connectedWallets.length > 0 && connectedWallets.some(wallet => wallet.id === connectResult.id)
64
+ ? connectedWallets
65
+ : [connectResult, ...connectedWallets.filter(wallet => wallet.id !== connectResult.id)];
66
+ await onAuthConnect(connectResult, allConnectedWallets);
50
67
  await onSuccess(account);
51
- setIsAuthenticated(true);
68
+ if (strategy === "email") {
69
+ resetEmailFlow();
70
+ }
52
71
  }
53
72
  catch (error) {
73
+ if (strategy === "email") {
74
+ setEmailError(error instanceof Error ? error.message : "Failed to sign in with email");
75
+ }
54
76
  await onError?.(error);
55
77
  await logout();
56
- setIsAuthenticated(false);
57
78
  }
58
79
  finally {
59
80
  setIsLoading(false);
@@ -61,8 +82,68 @@ export function LoginStepCustom({ onSuccess, onError, chain, strategies, maxInit
61
82
  setIsAuthenticating(false);
62
83
  }
63
84
  };
64
- return (_jsxs(LoginStepContainer, { partnerId: partnerId, children: [authStrategies.length > 0 && (_jsx("div", { className: `mb-6 w-full ${authStrategies.length <= 3 ? "space-y-3 px-3" : "grid grid-cols-4 gap-4"}`, children: authStrategies.map(strategy => {
65
- console.log("strategy", strategy);
66
- return (_jsx(AuthButton, { strategy: strategy, onClick: () => handleConnect(strategy), isLoading: isLoading }, strategy));
67
- }) })), _jsx("div", { className: "mb-4 w-full space-y-2", children: initialWallets.map(walletId => (_jsx(WalletRow, { walletId: walletId, onClick: () => handleConnect(walletId), isLoading: isLoading }, walletId))) }), additionalWallets.length > 0 && (_jsxs("div", { className: "w-full", children: [_jsx(Button, { onClick: () => setShowAllWallets(!showAllWallets), className: "mb-2 w-full bg-transparent text-gray-600 hover:bg-gray-100", children: showAllWallets ? "Show less" : "More options" }), showAllWallets && (_jsx("div", { className: "max-h-60 space-y-2 overflow-y-auto", children: additionalWallets.map(walletId => (_jsx(WalletRow, { walletId: walletId, onClick: () => handleConnect(walletId), isLoading: isLoading }, walletId))) }))] }))] }));
85
+ const handleConnect = async (strategy) => {
86
+ if (strategy === "email") {
87
+ setShowEmailFlow(true);
88
+ setEmailCodeSent(false);
89
+ setVerificationCode("");
90
+ setEmailError(null);
91
+ return;
92
+ }
93
+ const options = getConnectOptionsFromStrategy(strategy);
94
+ await connectWithOptions(strategy, options);
95
+ };
96
+ const handleSendEmailCode = async () => {
97
+ const normalizedEmail = email.trim().toLowerCase();
98
+ if (!normalizedEmail) {
99
+ setEmailError("Please enter your email address");
100
+ return;
101
+ }
102
+ if (!EMAIL_REGEX.test(normalizedEmail)) {
103
+ setEmailError("Please enter a valid email address");
104
+ return;
105
+ }
106
+ try {
107
+ setIsLoading(true);
108
+ setEmailError(null);
109
+ await preAuthenticate({
110
+ client,
111
+ strategy: "email",
112
+ email: normalizedEmail,
113
+ ecosystem: {
114
+ id: ecosystemWalletId,
115
+ partnerId,
116
+ },
117
+ });
118
+ setEmail(normalizedEmail);
119
+ setEmailCodeSent(true);
120
+ }
121
+ catch (error) {
122
+ setEmailError(error instanceof Error ? error.message : "Failed to send verification code");
123
+ await onError?.(error);
124
+ }
125
+ finally {
126
+ setIsLoading(false);
127
+ }
128
+ };
129
+ const handleEmailLogin = async () => {
130
+ const normalizedEmail = email.trim().toLowerCase();
131
+ const normalizedCode = verificationCode.trim();
132
+ if (!EMAIL_REGEX.test(normalizedEmail)) {
133
+ setEmailError("Please enter a valid email address");
134
+ return;
135
+ }
136
+ if (!normalizedCode) {
137
+ setEmailError("Please enter your verification code");
138
+ return;
139
+ }
140
+ await connectWithOptions("email", {
141
+ strategy: "email",
142
+ email: normalizedEmail,
143
+ verificationCode: normalizedCode,
144
+ });
145
+ };
146
+ return (_jsx(LoginStepContainer, { partnerId: partnerId, children: showEmailFlow ? (_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: "Sign in with email" }), _jsx(Input, { type: "email", placeholder: "you@example.com", value: email, onChange: event => setEmail(event.target.value), disabled: isLoading || emailCodeSent }), emailCodeSent && (_jsx(Input, { type: "text", placeholder: "Enter verification code", value: verificationCode, onChange: event => setVerificationCode(event.target.value), disabled: isLoading })), emailError && _jsx("p", { className: "text-sm text-red-500", children: emailError }), _jsx(Button, { onClick: emailCodeSent ? handleEmailLogin : handleSendEmailCode, disabled: isLoading, className: "w-full", children: isLoading ? "Loading..." : emailCodeSent ? "Verify code" : "Send code" }), emailCodeSent && (_jsx(Button, { variant: "outline", onClick: handleSendEmailCode, disabled: isLoading, className: "w-full", children: "Resend code" })), _jsx(Button, { variant: "outline", onClick: resetEmailFlow, disabled: isLoading, className: "w-full", children: "Back" })] })) : (_jsxs(_Fragment, { children: [authStrategies.length > 0 && (_jsx("div", { className: `mb-6 grid w-full gap-4 px-3 ${authStrategies.length > 4 ? "grid-cols-4" : ""}`, style: authStrategies.length <= 4
147
+ ? { gridTemplateColumns: `repeat(${authGridColumns}, minmax(0, 1fr))` }
148
+ : undefined, children: authStrategies.map(strategy => (_jsx(AuthButton, { strategy: strategy, onClick: () => handleConnect(strategy), isLoading: isLoading }, strategy))) })), _jsx("div", { className: "mb-4 w-full space-y-2", children: initialWallets.map(walletId => (_jsx(WalletRow, { walletId: walletId, onClick: () => handleConnect(walletId), isLoading: isLoading }, walletId))) }), additionalWallets.length > 0 && (_jsxs("div", { className: "w-full", children: [_jsx(Button, { onClick: () => setShowAllWallets(!showAllWallets), className: "mb-2 w-full bg-transparent text-gray-600 hover:bg-gray-100", children: showAllWallets ? "Show less" : "More options" }), showAllWallets && (_jsx("div", { className: "max-h-60 space-y-2 overflow-y-auto", children: additionalWallets.map(walletId => (_jsx(WalletRow, { walletId: walletId, onClick: () => handleConnect(walletId), isLoading: isLoading }, walletId))) }))] }))] })) }));
68
149
  }
@@ -3,15 +3,17 @@ import { SingleStepAuthArgsType, Wallet } from "thirdweb/wallets";
3
3
  type WalletType = Wallet["id"];
4
4
  type StrategyType = SingleStepAuthArgsType["strategy"];
5
5
  type CustomStrategyType = "basement" | "privy";
6
- type AllowedStrategies = StrategyType | WalletType | CustomStrategyType;
7
- export declare const allowedStrategies: readonly ["apple", "google", "x", "discord", "guest", "walletConnect", "io.metamask", "com.coinbase.wallet", "basement", "privy"];
6
+ type AllowedStrategies = StrategyType | WalletType | CustomStrategyType | "email";
7
+ type NonWalletStrategyType = Exclude<AllowedStrategies, WalletType>;
8
+ export declare const allowedStrategies: readonly ["apple", "google", "github", "x", "discord", "email", "guest", "walletConnect", "io.metamask", "com.coinbase.wallet", "basement", "privy"];
8
9
  export type AllowedStrategy = (typeof allowedStrategies)[number];
9
10
  export declare function isWalletType(strategy: AllowedStrategies): strategy is WalletType;
10
- export declare function isStrategyType(strategy: AllowedStrategies): strategy is StrategyType;
11
+ export declare function isStrategyType(strategy: AllowedStrategies): strategy is NonWalletStrategyType;
11
12
  export declare function getConnectOptionsFromStrategy(strategy: AllowedStrategy): {
12
13
  strategy: StrategyType;
13
14
  wallet?: Wallet;
14
15
  chain?: Chain;
15
16
  };
16
17
  export declare const strategyIcons: Record<string, string>;
18
+ export declare const strategyLabels: Record<string, string>;
17
19
  export {};
@@ -5,9 +5,10 @@ export const allowedStrategies = [
5
5
  // Auth strategies
6
6
  "apple",
7
7
  "google",
8
+ "github",
8
9
  "x",
9
10
  "discord",
10
- // "github",
11
+ "email",
11
12
  "guest",
12
13
  // Wallet IDs
13
14
  "walletConnect",
@@ -29,6 +30,9 @@ export function getConnectOptionsFromStrategy(strategy) {
29
30
  if (!allowedStrategies.includes(strategy)) {
30
31
  throw new Error(`Invalid strategy: ${strategy}`);
31
32
  }
33
+ if (strategy === "email") {
34
+ throw new Error("Email strategy requires OTP flow and cannot be connected in a single step");
35
+ }
32
36
  if (isWalletType(strategy)) {
33
37
  return { strategy: "wallet", wallet: createWallet(strategy) };
34
38
  }
@@ -45,6 +49,15 @@ export const strategyIcons = {
45
49
  guest: "https://cdn.b3.fun/incognito.svg",
46
50
  // Add more strategies as needed
47
51
  };
52
+ export const strategyLabels = {
53
+ google: "Google",
54
+ x: "X",
55
+ discord: "Discord",
56
+ apple: "Apple",
57
+ guest: "Guest",
58
+ github: "GitHub",
59
+ email: "Email",
60
+ };
48
61
  // Test it
49
62
  // console.log(getConnectOptionsFromStrategy("io.metamask"));
50
63
  // console.log(getConnectOptionsFromStrategy("google"));
@@ -11,6 +11,9 @@ interface ToastContextType {
11
11
  addToast: (type: ToastType, message: string, duration?: number) => string;
12
12
  removeToast: (id: string) => void;
13
13
  clearAll: () => void;
14
+ headerMode: boolean;
15
+ setHeaderMode: (enabled: boolean) => void;
16
+ latestToast: ToastItem | null;
14
17
  }
15
18
  export declare function ToastProvider({ children }: {
16
19
  children: React.ReactNode;