From bed432f8c21ba042267620cda4cf849a7bd05dfe Mon Sep 17 00:00:00 2001 From: Joaquim Verges Date: Fri, 9 May 2025 07:11:15 +1200 Subject: [PATCH] [Dashboard] Store Engine access token in localStorage during FTUX --- .../engine/cloud/analytics/ftux.client.tsx | 11 +++++++++-- .../cloud/analytics/send-test-tx.client.tsx | 18 ++++++++++++------ .../engine/cloud/analytics/utils.ts | 18 ++++++++++++++++++ .../components/create-vault-account.client.tsx | 6 ++++++ 4 files changed, 45 insertions(+), 8 deletions(-) create mode 100644 apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/utils.ts diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/ftux.client.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/ftux.client.tsx index 2fabb70b740..c5b9f21ccb4 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/ftux.client.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/ftux.client.tsx @@ -8,6 +8,7 @@ import CreateServerWallet from "../server-wallets/components/create-server-walle import type { Wallet } from "../server-wallets/wallet-table/types"; import CreateVaultAccountButton from "../vault/components/create-vault-account.client"; import { SendTestTransaction } from "./send-test-tx.client"; +import { deleteUserAccessToken } from "./utils"; interface Props { managementAccessToken: string | undefined; @@ -78,6 +79,11 @@ export const EngineChecklist: React.FC = (props) => { props.teamSlug, ]); + const isComplete = useMemo( + () => finalSteps.every((step) => step.completed), + [finalSteps], + ); + if (props.testTxWithWallet) { return ( = (props) => { ); } - if (finalSteps.length === 1) { + if (finalSteps.length === 0 || isComplete) { + // clear token from local storage after FTUX is complete + deleteUserAccessToken(props.project.id); return null; } - return ( ); diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/send-test-tx.client.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/send-test-tx.client.tsx index f9453587794..144d2bd9ba1 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/send-test-tx.client.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/send-test-tx.client.tsx @@ -30,6 +30,7 @@ import { CopyTextButton } from "../../../../../../../../@/components/ui/CopyText import { useTrack } from "../../../../../../../../hooks/analytics/useTrack"; import type { Wallet } from "../server-wallets/wallet-table/types"; import { SmartAccountCell } from "../server-wallets/wallet-table/wallet-table-ui.client"; +import { deleteUserAccessToken, getUserAccessToken } from "./utils"; const formSchema = z.object({ accessToken: z.string().min(1, "Access token is required"), @@ -53,10 +54,13 @@ export function SendTestTransaction(props: { const router = useDashboardRouter(); const trackEvent = useTrack(); + const userAccessToken = + props.userAccessToken ?? getUserAccessToken(props.project.id) ?? ""; + const form = useForm({ resolver: zodResolver(formSchema), defaultValues: { - accessToken: props.userAccessToken ?? "", + accessToken: userAccessToken, walletIndex: props.wallets && props.walletId ? props.wallets @@ -147,7 +151,7 @@ export function SendTestTransaction(props: { )}

- {props.userAccessToken + {userAccessToken ? "Copy your Vault access token, you'll need it for every HTTP call to Engine." : "Every wallet action requires your Vault access token."}

@@ -157,12 +161,12 @@ export function SendTestTransaction(props: {

Vault Access Token

- {props.userAccessToken ? ( + {userAccessToken ? (
@@ -175,7 +179,7 @@ export function SendTestTransaction(props: { ) : ( {props.walletId ? "Close" : "Complete Setup"} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/utils.ts b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/utils.ts new file mode 100644 index 00000000000..69ca753fd9d --- /dev/null +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/analytics/utils.ts @@ -0,0 +1,18 @@ +export function storeUserAccessToken(projectId: string, accessToken: string) { + localStorage.setItem( + `thirdweb:engine-cloud-user-access-token-${projectId}`, + accessToken, + ); +} + +export function getUserAccessToken(projectId: string) { + return localStorage.getItem( + `thirdweb:engine-cloud-user-access-token-${projectId}`, + ); +} + +export function deleteUserAccessToken(projectId: string) { + localStorage.removeItem( + `thirdweb:engine-cloud-user-access-token-${projectId}`, + ); +} diff --git a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/vault/components/create-vault-account.client.tsx b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/vault/components/create-vault-account.client.tsx index 7fa2bb264fb..d95abd9e2ba 100644 --- a/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/vault/components/create-vault-account.client.tsx +++ b/apps/dashboard/src/app/(app)/team/[team_slug]/[project_slug]/engine/cloud/vault/components/create-vault-account.client.tsx @@ -19,6 +19,7 @@ import { CheckIcon, DownloadIcon, Loader2Icon, LockIcon } from "lucide-react"; import { useState } from "react"; import { toast } from "sonner"; import { useTrack } from "../../../../../../../../../hooks/analytics/useTrack"; +import { storeUserAccessToken } from "../../analytics/utils"; import { createManagementAccessToken, createWalletAccessToken, @@ -86,6 +87,11 @@ export default function CreateVaultAccountButton(props: { throw new Error("Failed to create access token"); } + // save in local storage in case the user refreshes the page during FTUX + storeUserAccessToken( + props.project.id, + userAccessTokenRes.data.accessToken, + ); props.onUserAccessTokenCreated?.(userAccessTokenRes.data.accessToken); return {