Skip to content

Commit

Permalink
feat: transfer mint in demo app (#983)
Browse files Browse the repository at this point in the history
* feat: allow passkey flow in demo app.  handleAuthSuccess callback when complete

* feat: in progress mint card wrapper, add isAuthComplete to useConfig

* fix: switch to use useAuthenticate to determine stage instead of callback

* feat: mdx useAuthentication update

* fix: Update account-kit/react/src/components/auth/context.ts

Co-authored-by: Michael Moldoveanu <michael.moldoveanu@alchemy.com>

* fix: bad casing for authsteptype

* fix: remove stage from useAuthenticate

* fix: bad corner radius on passkey modal, useAuthenticate docs

* fix: remove unused auth step type

* feat: allow passkey flow in demo app.  handleAuthSuccess callback when complete

* feat: mdx useAuthentication update

* feat: draw, check, gas and receipt svgs

* feat: basic styling for nft collect

* feat: separate mint card wrapper, pixel perfect

* feat: hextorgba, loading icon,

* feat: has collected state

* fix: check icon bad params

* feat: switching network to arbitrumSepolia, adding minting logic

* feat: clean up icon status, revert on error

* fix: update contract

* fix: correct nft config

* feat: learn more link

* feat: use nft image from s3 bucket

* fix: ui loading colors dark mode

* fix: remove handle auth success

* fix: remove bad jsdoc, spacing and nft img

* fix: get image from contract, loading state for image, remove unused config

* fix: remove blocking timeout

* fix: pr feedback, fixed flashing nft image

* fix: slower animation speed

* fix: pr feedback

* feat: mint card with gray line

* fix: fixed item height

* feat: white background and card border

* fix: remove mintDemoWrapper, correctly place avatar

* fix: new design layout

* fix: remove brand color bg, un-needed helper method

* fix: code preview spacing

* fix: prevent avatar to render without user

* fix: added priority to image to speed up loading

* feat: wired in NFT transfered to avatar

* fix: paired review feedback

* fix: correct block explorer url

---------

Co-authored-by: Michael Moldoveanu <michael.moldoveanu@alchemy.com>
  • Loading branch information
RobChangCA and moldy530 authored Sep 27, 2024
1 parent 180edad commit 9995330
Show file tree
Hide file tree
Showing 15 changed files with 764 additions and 64 deletions.
14 changes: 12 additions & 2 deletions examples/ui-demo/next.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
await import("./env.mjs");

/** @type {import('next').NextConfig} */
const nextConfig = {};
const nextConfig = {
images: {
remotePatterns: [
{
protocol: 'https',
hostname: 'static.alchemyapi.io',
port: '',
pathname: '/assets/accountkit/**',
},
],
}
};

export default nextConfig;
37 changes: 26 additions & 11 deletions examples/ui-demo/src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@
import { Authentication } from "@/components/configuration/Authentication";
import { Styling } from "@/components/configuration/Styling";
import { Inter, Public_Sans } from "next/font/google";
import { useState } from "react";
import { useContext, useState } from "react";
import { AuthCardWrapper } from "../components/preview/AuthCardWrapper";
import { CodePreview } from "../components/preview/CodePreview";
import { CodePreviewSwitch } from "../components/shared/CodePreviewSwitch";
import { TopNav } from "../components/topnav/TopNav";
import { UserConnectionAvatarWithPopover } from "@/components/shared/user-connection-avatar/UserConnectionAvatarWithPopover";
import { useUser } from "@account-kit/react";
import { useConfig } from "./state";

const publicSans = Public_Sans({
subsets: ["latin"],
Expand All @@ -21,7 +24,8 @@ const inter = Inter({

export default function Home() {
const [showCode, setShowCode] = useState(false);

const { nftTransfered } = useConfig();
const user = useUser();
return (
<main
className={`flex bg-gray-50 flex-col h-screen ${publicSans.className}`}
Expand All @@ -38,19 +42,30 @@ export default function Home() {

<div className="flex flex-col flex-[2] basis-0 relative bg-white border border-border rounded-lg overflow-hidden">
{/* Code toggle header */}
<div className="sticky h-7 top-4 flex items-center justify-end pr-4 gap-2 z-10">
<div className="bg-purple-50 text-[#8B5CF6] px-2 py-1 rounded text-xs font-semibold">
Code preview
<div
className={`absolute h-7 top-6 flex items-center left-6 right-6 ${
!user || showCode ? "justify-end" : "justify-between"
} z-10`}
>
{!showCode && user && (
<UserConnectionAvatarWithPopover
deploymentStatus={nftTransfered}
/>
)}
<div className="flex gap-2">
<div className="bg-purple-50 text-[#8B5CF6] px-2 py-1 rounded text-xs font-semibold">
Code preview
</div>
<CodePreviewSwitch
checked={showCode}
onCheckedChange={setShowCode}
/>
</div>
<CodePreviewSwitch
checked={showCode}
onCheckedChange={setShowCode}
/>
</div>

{/* Don't unmount when showing code preview so that the auth card retains its state */}
<AuthCardWrapper className={showCode ? "hidden" : "-mt-7"} />
{showCode && <CodePreview className="-mt-7" />}
<AuthCardWrapper className={showCode ? "hidden" : "mt-0"} />
{showCode && <CodePreview />}
</div>
</div>
</div>
Expand Down
5 changes: 3 additions & 2 deletions examples/ui-demo/src/app/providers.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"use client";

import { AuthCardHeader } from "@/components/shared/AuthCardHeader";
import { sepolia } from "@account-kit/infra";
import { arbitrumSepolia } from "@account-kit/infra";
import { AlchemyAccountProvider, createConfig } from "@account-kit/react";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { PropsWithChildren, Suspense } from "react";
Expand All @@ -12,8 +12,9 @@ const queryClient = new QueryClient();
const alchemyConfig = createConfig(
{
rpcUrl: "/api/rpc",
chain: sepolia,
chain: arbitrumSepolia,
ssr: true,
policyId: process.env.NEXT_PUBLIC_PAYMASTER_POLICY_ID
},
{
illustrationStyle: DEFAULT_CONFIG.ui.illustrationStyle,
Expand Down
9 changes: 8 additions & 1 deletion examples/ui-demo/src/app/state.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ export type Config = {
export type ConfigContextType = {
config: Config;
setConfig: Dispatch<SetStateAction<Config>>;
nftTransfered: boolean;
setNFTTransfered: Dispatch<SetStateAction<boolean>>;
};

export const DEFAULT_CONFIG: Config = {
Expand All @@ -78,6 +80,8 @@ export const DEFAULT_CONFIG: Config = {
export const ConfigContext = createContext<ConfigContextType>({
config: DEFAULT_CONFIG,
setConfig: () => undefined,
nftTransfered: false,
setNFTTransfered: () => undefined,
});

export function useConfig(): ConfigContextType {
Expand All @@ -88,6 +92,7 @@ export function useConfig(): ConfigContextType {

export function ConfigContextProvider(props: PropsWithChildren) {
const [config, setConfig] = useState<Config>(DEFAULT_CONFIG);
const [nftTransfered, setNFTTransfered] = useState(false);
const { updateConfig } = useUiConfig();

// Sync Alchemy auth UI config
Expand Down Expand Up @@ -151,7 +156,9 @@ export function ConfigContextProvider(props: PropsWithChildren) {
}, [config]);

return (
<ConfigContext.Provider value={{ config, setConfig }}>
<ConfigContext.Provider
value={{ config, setConfig, nftTransfered, setNFTTransfered }}
>
{props.children}
</ConfigContext.Provider>
);
Expand Down
28 changes: 28 additions & 0 deletions examples/ui-demo/src/components/icons/check.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { SVGProps } from "react";

export const CheckIcon = ({
stroke = "currentColor",
...props
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g id="arrow">
<path
id="Icon"
d="M17 9.50049L11 15.5005L8.00003 12.5005M12.5 2.40039C7.19809 2.40039 2.90002 6.69846 2.90002 12.0004C2.90002 17.3023 7.19809 21.6004 12.5 21.6004C17.802 21.6004 22.1 17.3023 22.1 12.0004C22.1 6.69846 17.802 2.40039 12.5 2.40039Z"
stroke={stroke}
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</g>
</svg>
);
};
25 changes: 25 additions & 0 deletions examples/ui-demo/src/components/icons/draw.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { SVGProps } from "react";

export const DrawIcon = ({
fill = "currentColor",
...props
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g id="draw_24dp_5F6368_FILL0_wght400_GRAD0_opsz24">
<path
id="Vector"
d="M4.5 21V16.75L17.675 3.6C17.875 3.4 18.1 3.25 18.35 3.15C18.6 3.05 18.85 3 19.1 3C19.3667 3 19.6208 3.05 19.8625 3.15C20.1042 3.25 20.3167 3.4 20.5 3.6L21.9 5C22.1 5.18333 22.25 5.39583 22.35 5.6375C22.45 5.87917 22.5 6.13333 22.5 6.4C22.5 6.65 22.45 6.9 22.35 7.15C22.25 7.4 22.1 7.625 21.9 7.825L8.75 21H4.5ZM6.5 19H7.9L17.725 9.2L17.025 8.475L16.3 7.775L6.5 17.6V19ZM17.025 8.475L16.3 7.775L17.725 9.2L17.025 8.475ZM14.5 21C15.7333 21 16.875 20.6917 17.925 20.075C18.975 19.4583 19.5 18.6 19.5 17.5C19.5 16.9 19.3417 16.3833 19.025 15.95C18.7083 15.5167 18.2833 15.1417 17.75 14.825L16.275 16.3C16.6583 16.4667 16.9583 16.65 17.175 16.85C17.3917 17.05 17.5 17.2667 17.5 17.5C17.5 17.8833 17.1958 18.2292 16.5875 18.5375C15.9792 18.8458 15.2833 19 14.5 19C14.2167 19 13.9792 19.0958 13.7875 19.2875C13.5958 19.4792 13.5 19.7167 13.5 20C13.5 20.2833 13.5958 20.5208 13.7875 20.7125C13.9792 20.9042 14.2167 21 14.5 21ZM5.075 13.35L6.575 11.85C6.24167 11.7167 5.97917 11.5792 5.7875 11.4375C5.59583 11.2958 5.5 11.15 5.5 11C5.5 10.8 5.65 10.6 5.95 10.4C6.25 10.2 6.88333 9.89167 7.85 9.475C9.31667 8.84167 10.2917 8.26667 10.775 7.75C11.2583 7.23333 11.5 6.65 11.5 6C11.5 5.08333 11.1333 4.35417 10.4 3.8125C9.66667 3.27083 8.7 3 7.5 3C6.75 3 6.07917 3.13333 5.4875 3.4C4.89583 3.66667 4.44167 3.99167 4.125 4.375C3.94167 4.59167 3.86667 4.83333 3.9 5.1C3.93333 5.36667 4.05833 5.58333 4.275 5.75C4.49167 5.93333 4.73333 6.00833 5 5.975C5.26667 5.94167 5.49167 5.83333 5.675 5.65C5.90833 5.41667 6.16667 5.25 6.45 5.15C6.73333 5.05 7.08333 5 7.5 5C8.18333 5 8.6875 5.1 9.0125 5.3C9.3375 5.5 9.5 5.73333 9.5 6C9.5 6.23333 9.35417 6.44583 9.0625 6.6375C8.77083 6.82917 8.1 7.16667 7.05 7.65C5.71667 8.23333 4.79167 8.7625 4.275 9.2375C3.75833 9.7125 3.5 10.3 3.5 11C3.5 11.5333 3.64167 11.9875 3.925 12.3625C4.20833 12.7375 4.59167 13.0667 5.075 13.35Z"
fill={fill}
/>
</g>
</svg>
);
};
2 changes: 1 addition & 1 deletion examples/ui-demo/src/components/icons/external-link.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { SVGProps } from "react";

export const ExternalLinkIcon = ({
stroke = "#475569",
stroke = "currentColor",
...props
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => (
<svg
Expand Down
25 changes: 25 additions & 0 deletions examples/ui-demo/src/components/icons/gas.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { SVGProps } from "react";

export const GasIcon = ({
fill = "currentColor",
...props
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g id="local_gas_station_24dp_5F6368_FILL0_wght400_GRAD0_opsz24">
<path
id="Vector"
d="M4.5 21V5C4.5 4.45 4.69583 3.97917 5.0875 3.5875C5.47917 3.19583 5.95 3 6.5 3H12.5C13.05 3 13.5208 3.19583 13.9125 3.5875C14.3042 3.97917 14.5 4.45 14.5 5V12H15.5C16.05 12 16.5208 12.1958 16.9125 12.5875C17.3042 12.9792 17.5 13.45 17.5 14V18.5C17.5 18.7833 17.5958 19.0208 17.7875 19.2125C17.9792 19.4042 18.2167 19.5 18.5 19.5C18.7833 19.5 19.0208 19.4042 19.2125 19.2125C19.4042 19.0208 19.5 18.7833 19.5 18.5V11.3C19.35 11.3833 19.1917 11.4375 19.025 11.4625C18.8583 11.4875 18.6833 11.5 18.5 11.5C17.8 11.5 17.2083 11.2583 16.725 10.775C16.2417 10.2917 16 9.7 16 9C16 8.46667 16.1458 7.9875 16.4375 7.5625C16.7292 7.1375 17.1167 6.83333 17.6 6.65L15.5 4.55L16.55 3.5L20.25 7.1C20.5 7.35 20.6875 7.64167 20.8125 7.975C20.9375 8.30833 21 8.65 21 9V18.5C21 19.2 20.7583 19.7917 20.275 20.275C19.7917 20.7583 19.2 21 18.5 21C17.8 21 17.2083 20.7583 16.725 20.275C16.2417 19.7917 16 19.2 16 18.5V13.5H14.5V21H4.5ZM6.5 10H12.5V5H6.5V10ZM18.5 10C18.7833 10 19.0208 9.90417 19.2125 9.7125C19.4042 9.52083 19.5 9.28333 19.5 9C19.5 8.71667 19.4042 8.47917 19.2125 8.2875C19.0208 8.09583 18.7833 8 18.5 8C18.2167 8 17.9792 8.09583 17.7875 8.2875C17.5958 8.47917 17.5 8.71667 17.5 9C17.5 9.28333 17.5958 9.52083 17.7875 9.7125C17.9792 9.90417 18.2167 10 18.5 10ZM6.5 19H12.5V12H6.5V19Z"
fill={fill}
/>
</g>
</svg>
);
};
81 changes: 81 additions & 0 deletions examples/ui-demo/src/components/icons/loading.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import { useConfig } from "@/app/state";
export const LoadingIcon = () => {
const {
config: {
ui: { theme },
},
} = useConfig();
const animationClass =
theme === "dark" ? "animate-ui-loading-dark" : "animate-ui-loading-light";

return (
<svg
width="24"
height="24"
viewBox="0 0 48 48"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle
className={animationClass}
cx="4"
cy="24"
r="4"
style={{ animationDelay: "200ms" }}
></circle>
<circle
className={animationClass}
cx="44"
cy="24"
r="4"
style={{ animationDelay: "600ms" }}
></circle>
<circle
className={animationClass}
cx="24"
cy="4"
r="4"
style={{ animationDelay: "400ms" }}
></circle>
<circle
className={animationClass}
cx="24"
cy="44"
r="4"
style={{ animationDelay: "0ms" }}
></circle>
<circle
className={animationClass}
cx="38.1421"
cy="9.85784"
r="4"
transform="rotate(45 38.1421 9.85784)"
style={{ animationDelay: "500ms" }}
></circle>
<circle
className={animationClass}
cx="9.85791"
cy="38.1421"
r="4"
transform="rotate(45 9.85791 38.1421)"
style={{ animationDelay: "100ms" }}
></circle>
<circle
className={animationClass}
cx="38.142"
cy="38.1421"
r="4"
transform="rotate(135 38.142 38.1421)"
style={{ animationDelay: "700ms" }}
></circle>
<circle
className={animationClass}
cx="9.85779"
cy="9.85785"
r="4"
transform="rotate(135 9.85779 9.85785)"
style={{ animationDelay: "300ms" }}
></circle>
</svg>
);
};
25 changes: 25 additions & 0 deletions examples/ui-demo/src/components/icons/receipt.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { SVGProps } from "react";

export const ReceiptIcon = ({
fill = "currentColor",
...props
}: JSX.IntrinsicAttributes & SVGProps<SVGSVGElement>) => {
return (
<svg
width="24"
height="24"
viewBox="0 0 25 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<g id="receipt_long_24dp_5F6368_FILL0_wght400_GRAD0_opsz24">
<path
id="Vector"
d="M6.5 22C5.66667 22 4.95833 21.7083 4.375 21.125C3.79167 20.5417 3.5 19.8333 3.5 19V16H6.5V2L8 3.5L9.5 2L11 3.5L12.5 2L14 3.5L15.5 2L17 3.5L18.5 2L20 3.5L21.5 2V19C21.5 19.8333 21.2083 20.5417 20.625 21.125C20.0417 21.7083 19.3333 22 18.5 22H6.5ZM18.5 20C18.7833 20 19.0208 19.9042 19.2125 19.7125C19.4042 19.5208 19.5 19.2833 19.5 19V5H8.5V16H17.5V19C17.5 19.2833 17.5958 19.5208 17.7875 19.7125C17.9792 19.9042 18.2167 20 18.5 20ZM9.5 9V7H15.5V9H9.5ZM9.5 12V10H15.5V12H9.5ZM17.5 9C17.2167 9 16.9792 8.90417 16.7875 8.7125C16.5958 8.52083 16.5 8.28333 16.5 8C16.5 7.71667 16.5958 7.47917 16.7875 7.2875C16.9792 7.09583 17.2167 7 17.5 7C17.7833 7 18.0208 7.09583 18.2125 7.2875C18.4042 7.47917 18.5 7.71667 18.5 8C18.5 8.28333 18.4042 8.52083 18.2125 8.7125C18.0208 8.90417 17.7833 9 17.5 9ZM17.5 12C17.2167 12 16.9792 11.9042 16.7875 11.7125C16.5958 11.5208 16.5 11.2833 16.5 11C16.5 10.7167 16.5958 10.4792 16.7875 10.2875C16.9792 10.0958 17.2167 10 17.5 10C17.7833 10 18.0208 10.0958 18.2125 10.2875C18.4042 10.4792 18.5 10.7167 18.5 11C18.5 11.2833 18.4042 11.5208 18.2125 11.7125C18.0208 11.9042 17.7833 12 17.5 12ZM6.5 20H15.5V18H5.5V19C5.5 19.2833 5.59583 19.5208 5.7875 19.7125C5.97917 19.9042 6.21667 20 6.5 20Z"
fill={fill}
/>
</g>
</svg>
);
};
35 changes: 11 additions & 24 deletions examples/ui-demo/src/components/preview/AuthCardWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,40 +1,27 @@
import { useConfig } from "@/app/state";
import { cn } from "@/lib/utils";
import { AuthCard, useLogout, useUser } from "@account-kit/react";
import { AuthCard, useUser } from "@account-kit/react";
import { MintCard } from "../shared/MintCard";

export function AuthCardWrapper({ className }: { className?: string }) {
const user = useUser();
const { config } = useConfig();
const { logout } = useLogout();
return (
<div
className={cn(
"flex flex-1 flex-col justify-center items-center overflow-auto relative",
config.ui.theme === "dark" ? "bg-black/70" : "bg-[#EFF4F9]",
config.ui.theme === "dark" ? "bg-black/70" : "bg-white",
className
)}
>
{
!user ? (
<>
<div className="flex flex-col gap-2 w-[368px]">
<div className="modal bg-surface-default shadow-md overflow-hidden">
<AuthCard />
</div>
</div>
</>
) : null
// In flight- will be uncommented in the mint pr, a fast follow <MintDemoWrapper />
}
{user && (
<button
className="text-primary font-semibold text-sm px-3 py-[11px] bg-white border border-gray-300 rounded-lg hover:shadow-md"
onClick={() => {
logout();
}}
>
Logout
</button>
{!user ? (
<div className="flex flex-col gap-2 w-[368px]">
<div className="modal bg-surface-default shadow-md overflow-hidden">
<AuthCard />
</div>
</div>
) : (
<MintCard />
)}
</div>
);
Expand Down
Loading

0 comments on commit 9995330

Please sign in to comment.