Skip to content

[TOOL-2815] Nebula - handle disconnected wallet state, use connected account address in execute config #5821

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions apps/dashboard/src/app/nebula-app/(app)/api/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export type ContextFilters = {
export async function promptNebula(params: {
message: string;
sessionId: string;
config: ExecuteConfig;
config: ExecuteConfig | null;
authToken: string;
handleStream: (res: ChatStreamedResponse) => void;
abortController: AbortController;
Expand All @@ -24,7 +24,6 @@ export async function promptNebula(params: {
user_id: "default-user",
session_id: params.sessionId,
stream: true,
execute_config: params.config,
};

if (params.contextFilters) {
Expand All @@ -34,6 +33,10 @@ export async function promptNebula(params: {
};
}

if (params.config) {
body.execute_config = params.config;
}

const events = await stream(`${NEXT_PUBLIC_NEBULA_URL}/chat`, {
method: "POST",
headers: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import { redirect } from "next/navigation";
import { getValidAccount } from "../../../../account/settings/getAccount";
import {
getAuthToken,
getAuthTokenWalletAddress,
} from "../../../../api/lib/getAuthToken";
import { getAuthToken } from "../../../../api/lib/getAuthToken";
import { loginRedirect } from "../../../../login/loginRedirect";
import { getSessionById } from "../../api/session";
import { ChatPageContent } from "../../components/ChatPageContent";
Expand All @@ -22,12 +19,6 @@ export default async function Page(props: {
loginRedirect(pagePath);
}

const accountAddress = await getAuthTokenWalletAddress();

if (!accountAddress) {
loginRedirect(pagePath);
}

const session = await getSessionById({
authToken,
sessionId: params.session_id,
Expand All @@ -39,7 +30,6 @@ export default async function Page(props: {

return (
<ChatPageContent
accountAddress={accountAddress}
authToken={authToken}
session={session}
type="new-chat"
Expand Down
12 changes: 1 addition & 11 deletions apps/dashboard/src/app/nebula-app/(app)/chat/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { getValidAccount } from "../../../account/settings/getAccount";
import {
getAuthToken,
getAuthTokenWalletAddress,
} from "../../../api/lib/getAuthToken";
import { getAuthToken } from "../../../api/lib/getAuthToken";
import { loginRedirect } from "../../../login/loginRedirect";
import { ChatPageContent } from "../components/ChatPageContent";

Expand All @@ -14,15 +11,8 @@ export default async function Page() {
loginRedirect();
}

const accountAddress = await getAuthTokenWalletAddress();

if (!accountAddress) {
loginRedirect();
}

return (
<ChatPageContent
accountAddress={accountAddress}
authToken={authToken}
session={undefined}
type="new-chat"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export function Chatbar(props: {
return;
}
if (e.key === "Enter" && !props.isChatStreaming) {
e.preventDefault();
setMessage("");
props.sendMessage(message);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
"use client";
import { Button } from "@/components/ui/button";
import {
Dialog,
DialogClose,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { useThirdwebClient } from "@/constants/thirdweb.client";
import type { Account } from "@3rdweb-sdk/react/hooks/useApi";
import { ArrowRightIcon } from "lucide-react";
import Link from "next/link";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { useActiveAccount, useActiveWalletChain } from "thirdweb/react";
import { type ContextFilters, promptNebula } from "../api/chat";
Expand All @@ -15,7 +26,6 @@ import { EmptyStateChatPageContent } from "./EmptyStateChatPageContent";
export function ChatPageContent(props: {
session: SessionInfo | undefined;
authToken: string;
accountAddress: string;
type: "landing" | "new-chat";
account: Account;
initialPrompt: string | undefined;
Expand Down Expand Up @@ -95,12 +105,7 @@ export function ChatPageContent(props: {
// update the context filters to the current user's wallet address and chain id
// eslint-disable-next-line no-restricted-syntax
useEffect(() => {
if (
!isNewSession ||
hasUserUpdatedContextFilters ||
!address ||
!activeChain
) {
if (!isNewSession || hasUserUpdatedContextFilters) {
return;
}

Expand All @@ -109,19 +114,23 @@ export function ChatPageContent(props: {
? { ..._contextFilters }
: {};

updatedContextFilters.walletAddresses = [address];
updatedContextFilters.chainIds = [activeChain.id.toString()];
updatedContextFilters.walletAddresses = address ? [address] : [];
updatedContextFilters.chainIds = activeChain
? [activeChain.id.toString()]
: [];

return updatedContextFilters;
});
}, [address, isNewSession, hasUserUpdatedContextFilters, activeChain]);

const config: ExecuteConfig = useMemo(() => {
return {
mode: "client",
signer_wallet_address: props.accountAddress,
};
}, [props.accountAddress]);
const config: ExecuteConfig | null = useMemo(() => {
return address
? {
mode: "client",
signer_wallet_address: address,
}
: null;
}, [address]);

const [sessionId, _setSessionId] = useState<string | undefined>(
props.session?.id,
Expand Down Expand Up @@ -150,6 +159,7 @@ export function ChatPageContent(props: {

const [isChatStreaming, setIsChatStreaming] = useState(false);
const [enableAutoScroll, setEnableAutoScroll] = useState(false);
const [showConnectModal, setShowConnectModal] = useState(false);

const initSession = useCallback(async () => {
const session = await createSession({
Expand All @@ -163,6 +173,10 @@ export function ChatPageContent(props: {

const handleSendMessage = useCallback(
async (message: string) => {
if (!address) {
setShowConnectModal(true);
return;
}
setUserHasSubmittedMessage(true);
setMessages((prev) => [
...prev,
Expand Down Expand Up @@ -329,6 +343,7 @@ export function ChatPageContent(props: {
props.authToken,
messages.length,
initSession,
address,
],
);

Expand All @@ -350,6 +365,10 @@ export function ChatPageContent(props: {

return (
<div className="flex grow flex-col overflow-hidden">
<WalletDisconnectedDialog
open={showConnectModal}
onOpenChange={setShowConnectModal}
/>
<header className="flex justify-start border-b bg-background p-4">
<ContextFiltersButton
contextFilters={contextFilters}
Expand Down Expand Up @@ -411,3 +430,35 @@ export function ChatPageContent(props: {
</div>
);
}

function WalletDisconnectedDialog(props: {
open: boolean;
onOpenChange: (value: boolean) => void;
}) {
return (
<Dialog open={props.open} onOpenChange={props.onOpenChange}>
<DialogContent className="p-0">
<div className="p-6">
<DialogHeader>
<DialogTitle> Wallet Disconnected </DialogTitle>
<DialogDescription>
Connect your wallet to continue
</DialogDescription>
</DialogHeader>
</div>

<div className="flex justify-end gap-3 border-t bg-muted/50 p-6">
<DialogClose asChild>
<Button variant="outline">Cancel</Button>
</DialogClose>
<Button asChild>
<Link href="/login" className="gap-2">
Connect Wallet
<ArrowRightIcon className="size-4" />
</Link>
</Button>
</div>
</DialogContent>
</Dialog>
);
}
11 changes: 1 addition & 10 deletions apps/dashboard/src/app/nebula-app/(app)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
import { getValidAccount } from "../../account/settings/getAccount";
import {
getAuthToken,
getAuthTokenWalletAddress,
} from "../../api/lib/getAuthToken";
import { getAuthToken } from "../../api/lib/getAuthToken";
import { loginRedirect } from "../../login/loginRedirect";
import { ChatPageContent } from "./components/ChatPageContent";

Expand All @@ -20,16 +17,10 @@ export default async function Page(props: {
loginRedirect();
}

const accountAddress = await getAuthTokenWalletAddress();
const account = await getValidAccount();

if (!accountAddress) {
loginRedirect();
}

return (
<ChatPageContent
accountAddress={accountAddress}
authToken={authToken}
session={undefined}
type="landing"
Expand Down
18 changes: 11 additions & 7 deletions apps/dashboard/src/app/nebula-app/login/NebulaLoginPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,12 @@ export function NebulaLoginPage(props: {
account: Account | undefined;
}) {
const [message, setMessage] = useState<string | undefined>(undefined);
const [showLoginPage, setShowLoginPage] = useState<boolean>(false);

const [showPage, setShowPage] = useState<"connect" | "welcome">(
props.account ? "connect" : "welcome",
);
return (
<div className="relative flex min-h-screen flex-col overflow-hidden bg-background">
{/* nav */}
<header className="border-b">
<div className="container flex items-center justify-between p-4">
<NebulaIcon className="size-8 shrink-0 text-foreground" />
Expand All @@ -37,28 +39,30 @@ export function NebulaLoginPage(props: {
Docs
</Link>

{!showLoginPage && (
<Button size="sm" onClick={() => setShowLoginPage(true)}>
{showPage === "welcome" && (
<Button size="sm" onClick={() => setShowPage("connect")}>
Sign in
</Button>
)}
</div>
</div>
</header>

{showLoginPage ? (
{showPage === "connect" && (
<LoginAndOnboardingPageContent
account={props.account}
redirectPath={
message ? `/?prompt=${encodeURIComponent(message)}` : "/"
}
/>
) : (
)}

{showPage === "welcome" && (
<div className="container relative flex max-w-[800px] grow flex-col justify-center overflow-hidden rounded-lg pb-6">
<EmptyStateChatPageContent
sendMessage={(msg) => {
setMessage(msg);
setShowLoginPage(true);
setShowPage("connect");
}}
/>
</div>
Expand Down
Loading