@b3dotfun/sdk 0.1.69-alpha.24 → 0.1.69-alpha.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/global-account/react/components/AvatarEditor/AvatarEditor.js +3 -1
- package/dist/cjs/global-account/react/components/ManageAccount/BottomNavigation.js +4 -2
- package/dist/cjs/global-account/react/components/ManageAccount/Header.js +36 -4
- package/dist/cjs/global-account/react/components/ManageAccount/HomeContent.js +4 -1
- package/dist/cjs/global-account/react/components/ManageAccount/ManageAccount.js +6 -0
- package/dist/cjs/global-account/react/components/ManageAccount/ProfileSection.js +5 -3
- package/dist/cjs/global-account/react/components/ManageAccount/SettingsContent.js +3 -1
- package/dist/cjs/global-account/react/components/ManageAccount/SettingsProfileCard.js +25 -14
- package/dist/cjs/global-account/react/components/SignInWithB3/SignIn.js +14 -4
- package/dist/cjs/global-account/react/components/UserAvatar/UserAvatar.d.ts +18 -0
- package/dist/cjs/global-account/react/components/UserAvatar/UserAvatar.js +27 -0
- package/dist/cjs/global-account/react/components/index.d.ts +1 -0
- package/dist/cjs/global-account/react/components/index.js +6 -3
- package/dist/cjs/shared/constants/index.d.ts +1 -0
- package/dist/cjs/shared/constants/index.js +2 -1
- package/dist/esm/global-account/react/components/AvatarEditor/AvatarEditor.js +3 -1
- package/dist/esm/global-account/react/components/ManageAccount/BottomNavigation.js +5 -3
- package/dist/esm/global-account/react/components/ManageAccount/Header.js +37 -5
- package/dist/esm/global-account/react/components/ManageAccount/HomeContent.js +4 -1
- package/dist/esm/global-account/react/components/ManageAccount/ManageAccount.js +7 -1
- package/dist/esm/global-account/react/components/ManageAccount/ProfileSection.js +6 -4
- package/dist/esm/global-account/react/components/ManageAccount/SettingsContent.js +5 -3
- package/dist/esm/global-account/react/components/ManageAccount/SettingsProfileCard.js +25 -14
- package/dist/esm/global-account/react/components/SignInWithB3/SignIn.js +15 -5
- package/dist/esm/global-account/react/components/UserAvatar/UserAvatar.d.ts +18 -0
- package/dist/esm/global-account/react/components/UserAvatar/UserAvatar.js +21 -0
- package/dist/esm/global-account/react/components/index.d.ts +1 -0
- package/dist/esm/global-account/react/components/index.js +2 -0
- package/dist/esm/shared/constants/index.d.ts +1 -0
- package/dist/esm/shared/constants/index.js +1 -0
- package/dist/types/global-account/react/components/UserAvatar/UserAvatar.d.ts +18 -0
- package/dist/types/global-account/react/components/index.d.ts +1 -0
- package/dist/types/shared/constants/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/global-account/react/components/AvatarEditor/AvatarEditor.tsx +3 -1
- package/src/global-account/react/components/ManageAccount/BottomNavigation.tsx +18 -14
- package/src/global-account/react/components/ManageAccount/Header.tsx +71 -4
- package/src/global-account/react/components/ManageAccount/HomeContent.tsx +25 -19
- package/src/global-account/react/components/ManageAccount/ManageAccount.tsx +13 -0
- package/src/global-account/react/components/ManageAccount/ProfileSection.tsx +14 -7
- package/src/global-account/react/components/ManageAccount/SettingsContent.tsx +15 -32
- package/src/global-account/react/components/ManageAccount/SettingsProfileCard.tsx +29 -20
- package/src/global-account/react/components/SignInWithB3/SignIn.tsx +42 -13
- package/src/global-account/react/components/UserAvatar/UserAvatar.tsx +45 -0
- package/src/global-account/react/components/index.ts +3 -0
- package/src/shared/constants/index.ts +2 -0
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { TabsContentPrimitive, TabsPrimitive, useModalStore, } from "../../../../global-account/react/index.js";
|
|
2
|
+
import { TabsContentPrimitive, TabsPrimitive, useB3Config, useModalStore, } from "../../../../global-account/react/index.js";
|
|
3
3
|
import BottomNavigation from "./BottomNavigation.js";
|
|
4
4
|
import { HomeContent } from "./HomeContent.js";
|
|
5
5
|
import SettingsContent from "./SettingsContent.js";
|
|
6
6
|
export function ManageAccount({ onLogout, onSwap: _onSwap, onDeposit: _onDeposit, chain, partnerId, showSwap, showDeposit, }) {
|
|
7
|
+
const { authStrategy } = useB3Config();
|
|
8
|
+
const isBetterAuth = authStrategy === "better-auth";
|
|
7
9
|
const contentType = useModalStore(state => state.contentType);
|
|
8
10
|
const { activeTab = "home", setActiveTab } = contentType;
|
|
9
11
|
const setB3ModalContentType = useModalStore(state => state.setB3ModalContentType);
|
|
12
|
+
// Better Auth: single-view layout — no Home/Swap tabs, just settings content
|
|
13
|
+
if (isBetterAuth) {
|
|
14
|
+
return (_jsx("div", { className: "b3-manage-account flex-1", children: _jsx(SettingsContent, { partnerId: partnerId, onLogout: onLogout, chain: chain }) }));
|
|
15
|
+
}
|
|
10
16
|
return (_jsx("div", { className: "b3-manage-account flex-1", children: _jsxs(TabsPrimitive, { defaultValue: activeTab, onValueChange: value => {
|
|
11
17
|
const tab = value;
|
|
12
18
|
if (tab === "swap") {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useAccountWallet, useModalStore, useProfile, useSimBalance, useUser, } from "../../../../global-account/react/index.js";
|
|
2
|
+
import { useAccountWallet, useB3Config, useModalStore, useProfile, useSimBalance, useUser, } from "../../../../global-account/react/index.js";
|
|
3
3
|
import { validateImageUrl } from "../../../../global-account/react/utils/profileDisplay.js";
|
|
4
|
+
import { AVATAR_COLORS } from "../../../../shared/constants/index.js";
|
|
4
5
|
import { formatUsername } from "../../../../shared/utils/index.js";
|
|
5
6
|
import { formatDisplayNumber } from "../../../../shared/utils/number.js";
|
|
6
7
|
import Avatar from "boring-avatars";
|
|
@@ -9,8 +10,9 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
|
|
9
10
|
import { useActiveAccount } from "thirdweb/react";
|
|
10
11
|
import { useFirstEOA } from "../../hooks/useFirstEOA.js";
|
|
11
12
|
import { IPFSMediaRenderer } from "../IPFSMediaRenderer/IPFSMediaRenderer.js";
|
|
12
|
-
const AVATAR_COLORS = ["#3368ef", "#272727", "#6366f1", "#06b6d4", "#eeb0d9", "#ba3fbf", "#ff777b", "#dfbb53"];
|
|
13
13
|
const ProfileSection = () => {
|
|
14
|
+
const { authStrategy } = useB3Config();
|
|
15
|
+
const isBetterAuth = authStrategy === "better-auth";
|
|
14
16
|
const account = useActiveAccount();
|
|
15
17
|
const { address: eoaAddress } = useFirstEOA();
|
|
16
18
|
const { address: smartWalletAddress } = useAccountWallet();
|
|
@@ -45,7 +47,7 @@ const ProfileSection = () => {
|
|
|
45
47
|
setImgError(false);
|
|
46
48
|
}, [avatarSrc]);
|
|
47
49
|
const currentUsername = user?.username || profile?.displayName || formatUsername(profile?.name || "");
|
|
48
|
-
const avatarSeed = eoaAddress || account?.address || smartWalletAddress || currentUsername || "user";
|
|
49
|
-
return (_jsx("div", { className: "flex items-center justify-between px-5 py-6", children: _jsxs("div", { className: "global-account-profile flex items-center gap-4", children: [_jsxs("div", { className: "global-account-profile-avatar relative", children: [_jsx("div", { className: "border-b3-line border-1 bg-b3-primary-wash size-14 overflow-hidden rounded-full border", children: avatarSrc && !imgError ? (_jsx(IPFSMediaRenderer, { src: avatarSrc, alt: "Profile Avatar", className: "h-full w-full object-cover", onError: handleImgError })) : (_jsx(Avatar, { name: avatarSeed, variant: "beam", size: 56, colors: AVATAR_COLORS })) }), _jsx("button", { onClick: handleEditAvatar, className: "border-b3-background hover:bg-b3-grey/80 absolute -bottom-1 -right-1 flex size-6 items-center justify-center rounded-full border-4 bg-[#a0a0ab] transition-colors", children: _jsx(Pencil, { size: 10, className: "text-b3-background" }) })] }), _jsxs("div", { className: "global-account-profile-info flex flex-col gap-1", children: [_jsxs("h2", { className: "text-b3-grey font-neue-montreal-semibold flex h-[38px] items-center gap-1 text-xl", children: [_jsx("div", { className: "text-b3-foreground-muted", children: " $" }), _jsx("div", { className: "text-[30px]", children: formatDisplayNumber(totalBalanceUsd, { fractionDigits: 2 }) })] }), _jsx("div", { className: "b3-modal-username font-neue-montreal-semibold text-base leading-none text-[#0B57C2]", children: currentUsername })] })] }) }));
|
|
50
|
+
const avatarSeed = eoaAddress || account?.address || smartWalletAddress || currentUsername || user?.email || "user";
|
|
51
|
+
return (_jsx("div", { className: "flex items-center justify-between px-5 py-6", children: _jsxs("div", { className: "global-account-profile flex items-center gap-4", children: [_jsxs("div", { className: "global-account-profile-avatar relative", children: [_jsx("div", { className: "border-b3-line border-1 bg-b3-primary-wash size-14 overflow-hidden rounded-full border", children: avatarSrc && !imgError ? (_jsx(IPFSMediaRenderer, { src: avatarSrc, alt: "Profile Avatar", className: "h-full w-full object-cover", onError: handleImgError })) : (_jsx(Avatar, { name: avatarSeed, variant: "beam", size: 56, colors: AVATAR_COLORS })) }), _jsx("button", { onClick: handleEditAvatar, className: "border-b3-background hover:bg-b3-grey/80 absolute -bottom-1 -right-1 flex size-6 items-center justify-center rounded-full border-4 bg-[#a0a0ab] transition-colors", children: _jsx(Pencil, { size: 10, className: "text-b3-background" }) })] }), _jsxs("div", { className: "global-account-profile-info flex flex-col gap-1", children: [!isBetterAuth && (_jsxs("h2", { className: "text-b3-grey font-neue-montreal-semibold flex h-[38px] items-center gap-1 text-xl", children: [_jsx("div", { className: "text-b3-foreground-muted", children: " $" }), _jsx("div", { className: "text-[30px]", children: formatDisplayNumber(totalBalanceUsd, { fractionDigits: 2 }) })] })), _jsx("div", { className: "b3-modal-username font-neue-montreal-semibold text-base leading-none text-[#0B57C2]", children: currentUsername }), isBetterAuth && user?.email && (_jsx("div", { className: "text-b3-foreground-muted font-neue-montreal-medium text-sm", children: user.email }))] })] }) }));
|
|
50
52
|
};
|
|
51
53
|
export default ProfileSection;
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useAuthentication, useModalStore } from "../../../../global-account/react/index.js";
|
|
2
|
+
import { useAuthentication, useB3Config, useModalStore } from "../../../../global-account/react/index.js";
|
|
3
3
|
import { client } from "../../../../shared/utils/thirdweb.js";
|
|
4
4
|
import { getSessionDurationDays, SESSION_DURATION_LABELS } from "../../../../shared/utils/session-duration.js";
|
|
5
|
-
import { Loader2 } from "lucide-react";
|
|
5
|
+
import { Bell, Clock, Link, Loader2 } from "lucide-react";
|
|
6
6
|
import { useState } from "react";
|
|
7
7
|
import { useProfiles } from "thirdweb/react";
|
|
8
8
|
import SignOutIcon from "../icons/SignOutIcon.js";
|
|
@@ -10,6 +10,8 @@ import ModalHeader from "../ModalHeader/ModalHeader.js";
|
|
|
10
10
|
import SettingsMenuItem from "./SettingsMenuItem.js";
|
|
11
11
|
import SettingsProfileCard from "./SettingsProfileCard.js";
|
|
12
12
|
const SettingsContent = ({ partnerId, onLogout, chain, }) => {
|
|
13
|
+
const { authStrategy } = useB3Config();
|
|
14
|
+
const isBetterAuth = authStrategy === "better-auth";
|
|
13
15
|
const setB3ModalContentType = useModalStore(state => state.setB3ModalContentType);
|
|
14
16
|
const setB3ModalOpen = useModalStore(state => state.setB3ModalOpen);
|
|
15
17
|
const { logout, user } = useAuthentication(partnerId);
|
|
@@ -45,7 +47,7 @@ const SettingsContent = ({ partnerId, onLogout, chain, }) => {
|
|
|
45
47
|
setB3ModalOpen(false);
|
|
46
48
|
setLogoutLoading(false);
|
|
47
49
|
};
|
|
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(
|
|
50
|
+
return (_jsxs("div", { className: "flex h-[470px] flex-col", children: [!isBetterAuth && _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: [!isBetterAuth && (_jsx(SettingsMenuItem, { icon: _jsx(Link, { size: 18, className: "text-[#51525c]" }), title: "Linked Accounts", subtitle: `${profiles.length} connected account${profiles.length > 1 ? "s" : ""}`, onClick: () => handleNavigate("linkAccount") })), _jsx(SettingsMenuItem, { icon: _jsx(Bell, { size: 18, className: "text-[#51525c]" }), title: "Notifications", subtitle: "Manage your notifications", onClick: () => handleNavigate("notifications") }), _jsx(SettingsMenuItem, { icon: _jsx(Clock, { size: 18, className: "text-[#51525c]" }), 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: {
|
|
49
51
|
boxShadow: "inset 0px 0px 0px 1px rgba(10,13,18,0.18), inset 0px -2px 0px 0px rgba(10,13,18,0.05)",
|
|
50
52
|
}, 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" })] }) })] }));
|
|
51
53
|
};
|
|
@@ -16,7 +16,8 @@ const SettingsProfileCard = () => {
|
|
|
16
16
|
address: eoaAddress || account?.address,
|
|
17
17
|
fresh: true,
|
|
18
18
|
});
|
|
19
|
-
const { partnerId } = useB3Config();
|
|
19
|
+
const { partnerId, authStrategy } = useB3Config();
|
|
20
|
+
const isBetterAuth = authStrategy === "better-auth";
|
|
20
21
|
const { user, setUser } = useAuthentication(partnerId);
|
|
21
22
|
const setB3ModalOpen = useModalStore(state => state.setB3ModalOpen);
|
|
22
23
|
const setB3ModalContentType = useModalStore(state => state.setB3ModalContentType);
|
|
@@ -66,19 +67,29 @@ const SettingsProfileCard = () => {
|
|
|
66
67
|
}
|
|
67
68
|
setIsSaving(true);
|
|
68
69
|
try {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
70
|
+
let updatedUser;
|
|
71
|
+
if (isBetterAuth) {
|
|
72
|
+
// Better Auth: register username without wallet signing (DB-only, no ENS)
|
|
73
|
+
// Skip ens_normalize — it rejects underscores/mixed-case that are valid non-ENS usernames
|
|
74
|
+
const sanitizedUsername = editedUsername.trim().toLowerCase();
|
|
75
|
+
// Type assertion needed: b3-mono now accepts message/hash as optional for Better Auth users
|
|
76
|
+
updatedUser = (await app
|
|
77
|
+
.service("users")
|
|
78
|
+
.registerUsername({ username: sanitizedUsername }, {}));
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
// Thirdweb: register username with wallet signature + on-chain ENS
|
|
82
|
+
const sanitizedUsername = ens_normalize(editedUsername.trim());
|
|
83
|
+
const b3Username = `${sanitizedUsername}.b3.fun`;
|
|
84
|
+
const usernameSignMessage = `Register "${b3Username}"`;
|
|
85
|
+
const usernameSignature = await account?.signMessage({ message: usernameSignMessage });
|
|
86
|
+
if (!usernameSignature) {
|
|
87
|
+
throw new Error("Failed to sign username registration message");
|
|
88
|
+
}
|
|
89
|
+
updatedUser = (await app
|
|
90
|
+
.service("users")
|
|
91
|
+
.registerUsername({ username: sanitizedUsername, message: usernameSignMessage, hash: usernameSignature }, {}));
|
|
75
92
|
}
|
|
76
|
-
console.log("@@usernameSignature", usernameSignature);
|
|
77
|
-
// Register username with ENS
|
|
78
|
-
// Note: Type assertion needed until @b3dotfun/b3-api package is updated with RegisterUsername type
|
|
79
|
-
const updatedUser = (await app
|
|
80
|
-
.service("users")
|
|
81
|
-
.registerUsername({ username: sanitizedUsername, message: usernameSignMessage, hash: usernameSignature }, {}));
|
|
82
93
|
// Update user state - registerUsername returns an array with single user
|
|
83
94
|
setUser(Array.isArray(updatedUser) ? updatedUser[0] : updatedUser);
|
|
84
95
|
// Refresh profile to get updated data
|
|
@@ -107,6 +118,6 @@ const SettingsProfileCard = () => {
|
|
|
107
118
|
/* Edit mode - inline input */
|
|
108
119
|
_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("input", { ref: inputRef, type: "text", value: editedUsername, onChange: e => setEditedUsername(e.target.value), onKeyDown: handleKeyDown, disabled: isSaving, className: "border-b3-line bg-b3-background text-b3-grey placeholder:text-b3-foreground-muted font-neue-montreal-medium focus:border-b3-primary-blue text-md w-full rounded-md border px-2 py-1 leading-none transition-colors focus:outline-none disabled:opacity-50", placeholder: "Enter username" }), _jsxs("div", { className: "flex items-center gap-1", children: [_jsx("button", { onClick: handleSaveUsername, disabled: isSaving, className: "text-b3-primary-blue hover:text-b3-primary-blue/80 flex items-center justify-center rounded-md p-1 transition-colors disabled:opacity-50", "aria-label": "Save username", children: isSaving ? _jsx(Loader2, { size: 18, className: "animate-spin" }) : _jsx(Check, { size: 18, strokeWidth: 2.5 }) }), _jsx("button", { onClick: handleCancelEdit, disabled: isSaving, className: "text-b3-foreground-muted hover:text-b3-grey flex items-center justify-center rounded-md p-1 transition-colors disabled:opacity-50", "aria-label": "Cancel editing", children: _jsx(X, { size: 18, strokeWidth: 2.5 }) })] })] })) : (
|
|
109
120
|
/* Display mode */
|
|
110
|
-
_jsxs(_Fragment, { children: [_jsx("div", { className: "flex items-center gap-1", children: _jsx("p", { className: "b3-modal-username font-neue-montreal-semibold text-lg leading-none text-[#0B57C2]", children: currentUsername }) }), _jsx("button", { onClick: handleEditUsername, className: "flex items-center justify-center gap-1 text-left transition-opacity hover:opacity-80", children: _jsx("p", { className: "font-inter text-sm font-semibold leading-5 text-[#51525C] dark:text-white", children: "Edit Username" }) })] })) })] }));
|
|
121
|
+
_jsxs(_Fragment, { children: [_jsx("div", { className: "flex items-center gap-1", children: _jsx("p", { className: "b3-modal-username font-neue-montreal-semibold text-lg leading-none text-[#0B57C2]", children: currentUsername || user?.email }) }), _jsx("button", { onClick: handleEditUsername, className: "flex items-center justify-center gap-1 text-left transition-opacity hover:opacity-80", children: _jsx("p", { className: "font-inter text-sm font-semibold leading-5 text-[#51525C] dark:text-white", children: "Edit Username" }) })] })) })] }));
|
|
111
122
|
};
|
|
112
123
|
export default SettingsProfileCard;
|
|
@@ -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:
|
|
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: [
|
|
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
|
}
|
|
@@ -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
|
+
}
|
|
@@ -18,6 +18,7 @@ export { SignInWithB3Privy } from "./SignInWithB3/SignInWithB3Privy";
|
|
|
18
18
|
export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep";
|
|
19
19
|
export { getConnectOptionsFromStrategy, isWalletType, type AllowedStrategy } from "./SignInWithB3/utils/signInUtils";
|
|
20
20
|
export { ManageAccount } from "./ManageAccount/ManageAccount";
|
|
21
|
+
export { UserAvatar } from "./UserAvatar/UserAvatar";
|
|
21
22
|
export { Deposit } from "./Deposit/Deposit";
|
|
22
23
|
export { Send } from "./Send/Send";
|
|
23
24
|
export { IPFSMediaRenderer } from "./IPFSMediaRenderer/IPFSMediaRenderer";
|
|
@@ -21,6 +21,8 @@ export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep.js";
|
|
|
21
21
|
export { getConnectOptionsFromStrategy, isWalletType } from "./SignInWithB3/utils/signInUtils.js";
|
|
22
22
|
// ManageAccount Components
|
|
23
23
|
export { ManageAccount } from "./ManageAccount/ManageAccount.js";
|
|
24
|
+
// UserAvatar
|
|
25
|
+
export { UserAvatar } from "./UserAvatar/UserAvatar.js";
|
|
24
26
|
// Deposit Components
|
|
25
27
|
export { Deposit } from "./Deposit/Deposit.js";
|
|
26
28
|
// Send Components
|
|
@@ -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"];
|
|
@@ -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 {};
|
|
@@ -18,6 +18,7 @@ export { SignInWithB3Privy } from "./SignInWithB3/SignInWithB3Privy";
|
|
|
18
18
|
export { LoginStepContainer } from "./SignInWithB3/steps/LoginStep";
|
|
19
19
|
export { getConnectOptionsFromStrategy, isWalletType, type AllowedStrategy } from "./SignInWithB3/utils/signInUtils";
|
|
20
20
|
export { ManageAccount } from "./ManageAccount/ManageAccount";
|
|
21
|
+
export { UserAvatar } from "./UserAvatar/UserAvatar";
|
|
21
22
|
export { Deposit } from "./Deposit/Deposit";
|
|
22
23
|
export { Send } from "./Send/Send";
|
|
23
24
|
export { IPFSMediaRenderer } from "./IPFSMediaRenderer/IPFSMediaRenderer";
|
|
@@ -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[];
|
package/package.json
CHANGED
|
@@ -62,6 +62,8 @@ export function AvatarEditor({ onSetAvatar, className }: AvatarEditorProps) {
|
|
|
62
62
|
const setB3ModalContentType = useModalStore(state => state.setB3ModalContentType);
|
|
63
63
|
const contentType = useModalStore(state => state.contentType);
|
|
64
64
|
|
|
65
|
+
const { authStrategy } = useB3Config();
|
|
66
|
+
const isBetterAuth = authStrategy === "better-auth";
|
|
65
67
|
const account = useActiveAccount();
|
|
66
68
|
const { data: profile, refetch: refreshProfile } = useProfile({
|
|
67
69
|
address: account?.address,
|
|
@@ -162,7 +164,7 @@ export function AvatarEditor({ onSetAvatar, className }: AvatarEditorProps) {
|
|
|
162
164
|
};
|
|
163
165
|
|
|
164
166
|
const handleSaveChanges = async () => {
|
|
165
|
-
if (!account?.address) {
|
|
167
|
+
if (!isBetterAuth && !account?.address) {
|
|
166
168
|
toast.error("No account connected");
|
|
167
169
|
return;
|
|
168
170
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TabsListPrimitive, TabTriggerPrimitive, useModalStore } from "@b3dotfun/sdk/global-account/react";
|
|
1
|
+
import { TabsListPrimitive, TabTriggerPrimitive, useB3Config, useModalStore } from "@b3dotfun/sdk/global-account/react";
|
|
2
2
|
|
|
3
3
|
const HomeIcon = () => {
|
|
4
4
|
return (
|
|
@@ -42,6 +42,8 @@ const SettingsIcon = () => {
|
|
|
42
42
|
|
|
43
43
|
const BottomNavigation = () => {
|
|
44
44
|
const setB3ModalContentType = useModalStore(state => state.setB3ModalContentType);
|
|
45
|
+
const { authStrategy } = useB3Config();
|
|
46
|
+
const isBetterAuth = authStrategy === "better-auth";
|
|
45
47
|
|
|
46
48
|
return (
|
|
47
49
|
<div className="b3-modal-bottom-navigation sticky bottom-0 left-0 w-full rounded-b-xl border-t border-gray-200 bg-[#FAFAFA]">
|
|
@@ -54,19 +56,21 @@ const BottomNavigation = () => {
|
|
|
54
56
|
<span className="text-b3-grey font-neue-montreal-semibold text-xs">Home</span>
|
|
55
57
|
</TabTriggerPrimitive>
|
|
56
58
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
59
|
+
{!isBetterAuth && (
|
|
60
|
+
<TabTriggerPrimitive
|
|
61
|
+
value="swap"
|
|
62
|
+
className="data-[state=active]:border-b3-primary-blue group flex flex-initial flex-col items-center gap-1 border-r-0 border-t-0 px-6 pb-2 pt-2.5 text-[#a0a0ab] data-[state=active]:border-t-4 data-[state=active]:text-[#18181B] dark:data-[state=active]:text-white"
|
|
63
|
+
onClick={() => {
|
|
64
|
+
setB3ModalContentType({
|
|
65
|
+
type: "anySpend",
|
|
66
|
+
showBackButton: true,
|
|
67
|
+
});
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
<SwapIcon />
|
|
71
|
+
<span className="text-b3-grey font-neue-montreal-semibold text-xs">Swap</span>
|
|
72
|
+
</TabTriggerPrimitive>
|
|
73
|
+
)}
|
|
70
74
|
|
|
71
75
|
<TabTriggerPrimitive
|
|
72
76
|
value="settings"
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
CopyToClipboard,
|
|
3
3
|
ManageAccountModalProps,
|
|
4
4
|
useAuthentication,
|
|
5
|
+
useB3Config,
|
|
5
6
|
useModalStore,
|
|
6
7
|
} from "@b3dotfun/sdk/global-account/react";
|
|
7
8
|
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
|
@@ -10,6 +11,7 @@ import { Loader2 } from "lucide-react";
|
|
|
10
11
|
import { useState } from "react";
|
|
11
12
|
import { useActiveWallet, useConnectedWallets, useSetActiveWallet, useWalletImage } from "thirdweb/react";
|
|
12
13
|
import { Wallet } from "thirdweb/wallets";
|
|
14
|
+
import { UserAvatar } from "../UserAvatar/UserAvatar";
|
|
13
15
|
import { ChevronDownIcon } from "../icons/ChevronDownIcon";
|
|
14
16
|
import LinkIcon from "../icons/LinkIcon";
|
|
15
17
|
import SignOutIcon from "../icons/SignOutIcon";
|
|
@@ -89,7 +91,69 @@ function WalletItem({ wallet, isActive, onClick }: { wallet: Wallet; isActive: b
|
|
|
89
91
|
);
|
|
90
92
|
}
|
|
91
93
|
|
|
94
|
+
function BetterAuthHeader({ onLogout }: { onLogout?: () => void }) {
|
|
95
|
+
const contentType = useModalStore(state => state.contentType) as ManageAccountModalProps;
|
|
96
|
+
const setB3ModalOpen = useModalStore(state => state.setB3ModalOpen);
|
|
97
|
+
const partnerId = contentType?.partnerId;
|
|
98
|
+
const { logout, user } = useAuthentication(partnerId);
|
|
99
|
+
const [logoutLoading, setLogoutLoading] = useState(false);
|
|
100
|
+
|
|
101
|
+
const displayName = user?.username || user?.email || "Account";
|
|
102
|
+
|
|
103
|
+
const onLogoutEnhanced = async () => {
|
|
104
|
+
setLogoutLoading(true);
|
|
105
|
+
try {
|
|
106
|
+
await logout();
|
|
107
|
+
onLogout?.();
|
|
108
|
+
} finally {
|
|
109
|
+
setB3ModalOpen(false);
|
|
110
|
+
setLogoutLoading(false);
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<div className="bg-b3-background border-b3-line flex items-center justify-between border-b px-5 py-3">
|
|
116
|
+
<div className="flex items-center gap-2">
|
|
117
|
+
<UserAvatar avatarUrl={user?.avatar} name={displayName} size={40} className="shrink-0" />
|
|
118
|
+
<div className="flex flex-col gap-0.5">
|
|
119
|
+
{user?.username && (
|
|
120
|
+
<p className="text-b3-grey font-neue-montreal-semibold text-left text-sm">{user.username}</p>
|
|
121
|
+
)}
|
|
122
|
+
{user?.email && (
|
|
123
|
+
<div className="flex items-center gap-1">
|
|
124
|
+
<p className="text-b3-foreground-muted font-neue-montreal-medium text-sm">{user.email}</p>
|
|
125
|
+
<CopyToClipboard text={user.email} />
|
|
126
|
+
</div>
|
|
127
|
+
)}
|
|
128
|
+
</div>
|
|
129
|
+
</div>
|
|
130
|
+
<button
|
|
131
|
+
className="border-b3-line hover:bg-b3-line flex items-center justify-center gap-1.5 rounded-xl border border-solid px-3 py-2 transition-colors"
|
|
132
|
+
onClick={onLogoutEnhanced}
|
|
133
|
+
disabled={logoutLoading}
|
|
134
|
+
>
|
|
135
|
+
{logoutLoading ? (
|
|
136
|
+
<Loader2 className="animate-spin" size={16} />
|
|
137
|
+
) : (
|
|
138
|
+
<SignOutIcon size={16} className="text-b3-grey" />
|
|
139
|
+
)}
|
|
140
|
+
<p className="text-b3-grey font-neue-montreal-semibold text-sm">Sign out</p>
|
|
141
|
+
</button>
|
|
142
|
+
</div>
|
|
143
|
+
);
|
|
144
|
+
}
|
|
145
|
+
|
|
92
146
|
export function Header({ onLogout }: { onLogout?: () => void }) {
|
|
147
|
+
const { authStrategy } = useB3Config();
|
|
148
|
+
|
|
149
|
+
if (authStrategy === "better-auth") {
|
|
150
|
+
return <BetterAuthHeader onLogout={onLogout} />;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
return <WalletHeader onLogout={onLogout} />;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function WalletHeader({ onLogout }: { onLogout?: () => void }) {
|
|
93
157
|
const activeWallet = useActiveWallet();
|
|
94
158
|
|
|
95
159
|
const connectedWallets = useConnectedWallets();
|
|
@@ -110,10 +174,13 @@ export function Header({ onLogout }: { onLogout?: () => void }) {
|
|
|
110
174
|
|
|
111
175
|
const onLogoutEnhanced = async () => {
|
|
112
176
|
setLogoutLoading(true);
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
177
|
+
try {
|
|
178
|
+
await logout();
|
|
179
|
+
onLogout?.();
|
|
180
|
+
} finally {
|
|
181
|
+
setB3ModalOpen(false);
|
|
182
|
+
setLogoutLoading(false);
|
|
183
|
+
}
|
|
117
184
|
};
|
|
118
185
|
|
|
119
186
|
const handleWalletSwitch = (wallet: Wallet) => {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { useB3Config } from "@b3dotfun/sdk/global-account/react";
|
|
1
2
|
import { Tabs, TabsContent, TabsList, TabTrigger } from "../ui/Tabs";
|
|
2
3
|
import { Header } from "./Header";
|
|
3
4
|
import HomeActions from "./HomeActions";
|
|
@@ -11,31 +12,36 @@ interface HomeContentProps {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
export function HomeContent({ showDeposit = false, showSwap = true }: HomeContentProps) {
|
|
15
|
+
const { authStrategy } = useB3Config();
|
|
16
|
+
const isBetterAuth = authStrategy === "better-auth";
|
|
17
|
+
|
|
14
18
|
return (
|
|
15
19
|
<div className="flex flex-col">
|
|
16
20
|
<Header />
|
|
17
21
|
<div className="flex flex-col">
|
|
18
22
|
<ProfileSection />
|
|
19
23
|
|
|
20
|
-
<HomeActions showDeposit={showDeposit} showSwap={showSwap} />
|
|
21
|
-
|
|
22
|
-
<
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
<
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
24
|
+
{!isBetterAuth && <HomeActions showDeposit={showDeposit} showSwap={showSwap} />}
|
|
25
|
+
{!isBetterAuth && (
|
|
26
|
+
<div className="b3-modal-balance-content space-y-2 p-5">
|
|
27
|
+
<Tabs defaultValue={"balance"}>
|
|
28
|
+
<TabsList className="b3-modal-balance-tabs-list">
|
|
29
|
+
<TabTrigger value="balance" className="font-neue-montreal-semibold p-0 pr-3">
|
|
30
|
+
Balance
|
|
31
|
+
</TabTrigger>
|
|
32
|
+
<TabTrigger value="nfts" className="font-neue-montreal-semibold p-0 pr-3">
|
|
33
|
+
NFTs
|
|
34
|
+
</TabTrigger>
|
|
35
|
+
</TabsList>
|
|
36
|
+
<TabsContent value="balance" className="px-0 pb-4 pt-2">
|
|
37
|
+
<TokenContent />
|
|
38
|
+
</TabsContent>
|
|
39
|
+
<TabsContent value="nfts" className="px-0 pb-4 pt-2">
|
|
40
|
+
<NFTContent />
|
|
41
|
+
</TabsContent>
|
|
42
|
+
</Tabs>
|
|
43
|
+
</div>
|
|
44
|
+
)}
|
|
39
45
|
</div>
|
|
40
46
|
</div>
|
|
41
47
|
);
|
|
@@ -2,6 +2,7 @@ import {
|
|
|
2
2
|
ManageAccountModalProps,
|
|
3
3
|
TabsContentPrimitive,
|
|
4
4
|
TabsPrimitive,
|
|
5
|
+
useB3Config,
|
|
5
6
|
useModalStore,
|
|
6
7
|
} from "@b3dotfun/sdk/global-account/react";
|
|
7
8
|
import { Chain } from "thirdweb";
|
|
@@ -74,9 +75,21 @@ export function ManageAccount({
|
|
|
74
75
|
showSwap,
|
|
75
76
|
showDeposit,
|
|
76
77
|
}: ManageAccountProps) {
|
|
78
|
+
const { authStrategy } = useB3Config();
|
|
79
|
+
const isBetterAuth = authStrategy === "better-auth";
|
|
77
80
|
const contentType = useModalStore(state => state.contentType);
|
|
78
81
|
const { activeTab = "home", setActiveTab } = contentType as ManageAccountModalProps;
|
|
79
82
|
const setB3ModalContentType = useModalStore(state => state.setB3ModalContentType);
|
|
83
|
+
|
|
84
|
+
// Better Auth: single-view layout — no Home/Swap tabs, just settings content
|
|
85
|
+
if (isBetterAuth) {
|
|
86
|
+
return (
|
|
87
|
+
<div className="b3-manage-account flex-1">
|
|
88
|
+
<SettingsContent partnerId={partnerId} onLogout={onLogout} chain={chain} />
|
|
89
|
+
</div>
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
80
93
|
return (
|
|
81
94
|
<div className="b3-manage-account flex-1">
|
|
82
95
|
<TabsPrimitive
|