From ac1a5e321c0a58ec6c6bf0df6c975009840e7065 Mon Sep 17 00:00:00 2001 From: blake duncan Date: Fri, 30 May 2025 17:33:29 -0400 Subject: [PATCH 01/23] feat: fix readme and clean up ui --- README.md | 2 +- app/components/nft-mint-card.tsx | 64 ++++++++++++++++++++++++++++--- app/components/user-info-card.tsx | 4 +- tsconfig.json | 24 +++++++++--- 4 files changed, 80 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 7b2661e..e1d5258 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ tailwind.config.ts ## 🏗️ How it works -1. `config.ts` initializes Account Kit with your API key, Base Sepolia chain, and Gas Sponsorship policy. +1. `config.ts` initializes Account Kit with your API key, Arbitrum Sepolia chain, and Gas Sponsorship policy. 2. `Providers` wraps the app with `AlchemyAccountProvider` & React Query. 3. `LoginCard` opens the authentication modal (`useAuthModal`). 4. After login, `useSmartAccountClient` exposes the smart wallet. diff --git a/app/components/nft-mint-card.tsx b/app/components/nft-mint-card.tsx index 06bb9cc..a24d78b 100644 --- a/app/components/nft-mint-card.tsx +++ b/app/components/nft-mint-card.tsx @@ -1,5 +1,11 @@ -import { useState } from "react"; -import { ExternalLink, Loader2, PlusCircle } from "lucide-react"; +import { useState, useEffect } from "react"; +import { + ExternalLink, + Loader2, + PlusCircle, + ImageIcon, + CheckCircle, +} from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, @@ -19,6 +25,7 @@ import { NFT_CONTRACT_ADDRESS } from "@/lib/constants"; export default function NftMintCard() { const [isImageLoading, setIsImageLoading] = useState(true); + const [showSuccess, setShowSuccess] = useState(true); const { client } = useSmartAccountClient({}); @@ -33,6 +40,17 @@ export default function NftMintCard() { }, }); + // Reset success animation when new transaction appears + useEffect(() => { + if (transactionUrl) { + setShowSuccess(true); + const timer = setTimeout(() => { + setShowSuccess(false); + }, 4000); + return () => clearTimeout(timer); + } + }, [transactionUrl]); + return ( @@ -124,16 +142,50 @@ export default function NftMintCard() { )} diff --git a/app/components/user-info-card.tsx b/app/components/user-info-card.tsx index 438cdec..b7134ca 100644 --- a/app/components/user-info-card.tsx +++ b/app/components/user-info-card.tsx @@ -57,9 +57,9 @@ export default function UserInfo() { className="h-6 w-6" onClick={() => { const address = client?.account?.address; - if (address) { + if (address && client?.chain?.blockExplorers?.default?.url) { window.open( - `https://sepolia.basescan.org/address/${address}`, + `${client.chain.blockExplorers.default.url}/address/${address}`, "_blank" ); } diff --git a/tsconfig.json b/tsconfig.json index e7ff90f..d81d4ee 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,10 @@ { "compilerOptions": { - "lib": ["dom", "dom.iterable", "esnext"], + "lib": [ + "dom", + "dom.iterable", + "esnext" + ], "allowJs": true, "skipLibCheck": true, "strict": true, @@ -18,9 +22,19 @@ } ], "paths": { - "@/*": ["./*"] - } + "@/*": [ + "./*" + ] + }, + "target": "ES2017" }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], - "exclude": ["node_modules"] + "include": [ + "next-env.d.ts", + "**/*.ts", + "**/*.tsx", + ".next/types/**/*.ts" + ], + "exclude": [ + "node_modules" + ] } From 373ae76b4a85aa5f65cb9cd80cb36781cfec2752 Mon Sep 17 00:00:00 2001 From: Blake Duncan Date: Fri, 30 May 2025 17:34:53 -0400 Subject: [PATCH 02/23] Update README.md with the app image --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index e1d5258..e21a44d 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,8 @@ Use this template to get started with **embedded smart wallets** using [Alchemy - Server‑side rendering ready – session persisted with cookies - TailwindCSS + shadcn/ui components, React Query, TypeScript +![Smart Wallet Quickstart](https://github.com/user-attachments/assets/2903fb78-e632-4aaa-befd-5775c60e1ca2) + ## 📍 Network & Demo Contract This quickstart is configured to run on **Arbitrum Sepolia** testnet. A free demo NFT contract has been deployed specifically for this quickstart, allowing you to mint NFTs without any setup or deployment steps. The contract is pre-configured and ready to use out of the box. From 4d4b4fa0c8b3883a7d8a031b281c8028a398fcf5 Mon Sep 17 00:00:00 2001 From: blake duncan Date: Fri, 30 May 2025 17:38:29 -0400 Subject: [PATCH 03/23] feat: add tooltip on copying of the address --- app/components/user-info-card.tsx | 43 +++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 11 deletions(-) diff --git a/app/components/user-info-card.tsx b/app/components/user-info-card.tsx index b7134ca..713c317 100644 --- a/app/components/user-info-card.tsx +++ b/app/components/user-info-card.tsx @@ -1,4 +1,5 @@ -import { Info, ExternalLink, Copy } from "lucide-react"; +import { useState } from "react"; +import { ExternalLink, Copy } from "lucide-react"; import { Button } from "@/components/ui/button"; import { Card, @@ -8,14 +9,27 @@ import { CardTitle, } from "@/components/ui/card"; import { Badge } from "@/components/ui/badge"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { formatAddress } from "@/lib/utils"; import { useUser, useSmartAccountClient } from "@account-kit/react"; export default function UserInfo() { + const [isCopied, setIsCopied] = useState(false); const user = useUser(); const userEmail = user?.email ?? "anon"; const { client } = useSmartAccountClient({}); + const handleCopy = () => { + navigator.clipboard.writeText(client?.account?.address ?? ""); + setIsCopied(true); + setTimeout(() => setIsCopied(false), 2000); + }; + return ( @@ -41,16 +55,23 @@ export default function UserInfo() { {formatAddress(client?.account?.address ?? "")} - + + + + + + +

Copied!

+
+
+