diff --git a/apps/playground/frontend/package.json b/apps/playground/frontend/package.json index 2a5fe09..c190cdc 100644 --- a/apps/playground/frontend/package.json +++ b/apps/playground/frontend/package.json @@ -11,6 +11,8 @@ }, "dependencies": { "@meshsdk/midnight-react": "*", + "@meshsdk/midnight-core": "*", + "@meshsdk/midnight-wallet": "*", "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/vite": "^4.1.11", diff --git a/apps/playground/frontend/src/App.tsx b/apps/playground/frontend/src/App.tsx index 9914ccb..7de3baf 100644 --- a/apps/playground/frontend/src/App.tsx +++ b/apps/playground/frontend/src/App.tsx @@ -1,9 +1,11 @@ import * as pino from "pino"; import { MidnightMeshProvider } from "@meshsdk/midnight-react"; import { ThemeProvider } from "@/components/theme-provider" -import "@meshsdk/midnight-react/styles.css"; import { BrowserRouter, Route, Routes } from "react-router-dom"; import { Home } from "./pages/home"; +import { MainLayout } from "./layouts/layout"; +import { WalletUI } from "./pages/wallet-ui"; +import { Counter } from "./pages/counter"; const logger = pino.pino({ level: "trace", @@ -11,18 +13,20 @@ const logger = pino.pino({ function App() { - return ( - <> + return ( - - - } /> - - + + + }> + } /> + } /> + } /> + + + - - + ) } diff --git a/apps/playground/frontend/src/components/loading.tsx b/apps/playground/frontend/src/components/loading.tsx new file mode 100644 index 0000000..0f7eef8 --- /dev/null +++ b/apps/playground/frontend/src/components/loading.tsx @@ -0,0 +1,7 @@ +export const Loading = () => { + return ( +
+

Loading...

+
+ ); +}; \ No newline at end of file diff --git a/apps/playground/frontend/src/layouts/layout.tsx b/apps/playground/frontend/src/layouts/layout.tsx new file mode 100644 index 0000000..e7309d0 --- /dev/null +++ b/apps/playground/frontend/src/layouts/layout.tsx @@ -0,0 +1,40 @@ +import { Outlet, NavLink } from 'react-router-dom'; + +export const MainLayout = () => { + return ( +
+
+ +
+
+ +
+
+ ); +}; \ No newline at end of file diff --git a/apps/playground/frontend/src/main.tsx b/apps/playground/frontend/src/main.tsx index 8090697..1ae3cfa 100644 --- a/apps/playground/frontend/src/main.tsx +++ b/apps/playground/frontend/src/main.tsx @@ -1,11 +1,16 @@ -import { StrictMode } from 'react' +import { StrictMode, Suspense, lazy } from 'react' import { createRoot } from 'react-dom/client' -import App from './App.tsx' +import { Loading } from '@/components/loading' + import './index.css' import '@/global.ts' +const LazyApp = lazy(() => import('./App')); + createRoot(document.getElementById('root')!).render( - + }> + + , ) diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/button.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/button.tsx new file mode 100644 index 0000000..3f29f7a --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/button.tsx @@ -0,0 +1,58 @@ +import type { VariantProps } from "class-variance-authority"; +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva } from "class-variance-authority"; + +import { cn } from "./cn"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/cn.ts b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/cn.ts new file mode 100644 index 0000000..88283f0 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/cn.ts @@ -0,0 +1,7 @@ +import type { ClassValue } from "clsx"; +import { clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/dialog.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/dialog.tsx new file mode 100644 index 0000000..9ce8acc --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/dialog.tsx @@ -0,0 +1,121 @@ +import * as React from "react"; +import * as DialogPrimitive from "@radix-ui/react-dialog"; +import { X } from "lucide-react"; + +import { cn } from "./cn"; + +const Dialog = DialogPrimitive.Root; + +const DialogTrigger = DialogPrimitive.Trigger; + +const DialogPortal = DialogPrimitive.Portal; + +const DialogClose = DialogPrimitive.Close; + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogHeader.displayName = "DialogHeader"; + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogFooter.displayName = "DialogFooter"; + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +}; diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/dropdown-menu.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/dropdown-menu.tsx new file mode 100644 index 0000000..004b854 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/dropdown-menu.tsx @@ -0,0 +1,202 @@ +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "./cn" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + svg]:size-4 [&>svg]:shrink-0", + inset && "pl-8", + className + )} + {...props} + /> +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-book-dashed.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-book-dashed.tsx new file mode 100644 index 0000000..185604a --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-book-dashed.tsx @@ -0,0 +1,34 @@ +export default function IconBookDashed() { + return ( + + + + + + + + + + + + + + ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-chevron-right.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-chevron-right.tsx new file mode 100644 index 0000000..513880f --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-chevron-right.tsx @@ -0,0 +1,24 @@ +export default function IconChevronRight() { + return ( + + + + ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-download.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-download.tsx new file mode 100644 index 0000000..d2cd1b7 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-download.tsx @@ -0,0 +1,26 @@ +export default function IconDownload() { + return ( + + + + + + ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-fingerprint.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-fingerprint.tsx new file mode 100644 index 0000000..dae5b32 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-fingerprint.tsx @@ -0,0 +1,32 @@ +export default function IconFingerprint() { + return ( + + + + + + + + + + + + ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-lace.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-lace.tsx new file mode 100644 index 0000000..79d14a1 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-lace.tsx @@ -0,0 +1,16 @@ +export default function IconLace() { + return ( + + + + + + + + + + + + + ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-monitor-smartphone.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-monitor-smartphone.tsx new file mode 100644 index 0000000..5efbaf0 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-monitor-smartphone.tsx @@ -0,0 +1,26 @@ +export default function IconMonitorSmartphone() { + return ( + + + + + + + ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-plus.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-plus.tsx new file mode 100644 index 0000000..3edadba --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/icons/icon-plus.tsx @@ -0,0 +1,24 @@ +export default function IconPlus() { + return ( + + + + + ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/common/tooltip.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/tooltip.tsx new file mode 100644 index 0000000..e13c14b --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/common/tooltip.tsx @@ -0,0 +1,32 @@ +"use client" + +import * as React from "react" +import * as TooltipPrimitive from "@radix-ui/react-tooltip" + +import { cn } from "./cn" + +const TooltipProvider = TooltipPrimitive.Provider + +const Tooltip = TooltipPrimitive.Root + +const TooltipTrigger = TooltipPrimitive.Trigger + +const TooltipContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +TooltipContent.displayName = TooltipPrimitive.Content.displayName + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/index.ts b/apps/playground/frontend/src/modules/midnight/wallet-widget/index.ts new file mode 100644 index 0000000..96e9a89 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/index.ts @@ -0,0 +1,2 @@ +export * from "./midnight-wallet"; + diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/connected-button.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/connected-button.tsx new file mode 100644 index 0000000..96c5611 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/connected-button.tsx @@ -0,0 +1,40 @@ +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../common/dropdown-menu'; +import { Button } from '../common/button'; +import { useAssets, useWallet } from '@meshsdk/midnight-react'; + +export default function ConnectedButton() { + const { disconnect } = useWallet(); + const { address } = useAssets(); + + return ( + <> + {address && ( + + + + + + { + navigator.clipboard.writeText(address); + }} + > + Copy Address + + { + disconnect(); + }} + > + Disconnect + + + + )} + + ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/data.ts b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/data.ts new file mode 100644 index 0000000..d2fad0d --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/data.ts @@ -0,0 +1,5 @@ +export const screens = { + main: { + title: "Connect Wallet", + }, +}; diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/index.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/index.tsx new file mode 100644 index 0000000..4eb713f --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/index.tsx @@ -0,0 +1,91 @@ +import { useState } from "react"; +import { Button } from "../common/button"; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "../common/dialog"; +import { useAssets, useWallet } from "@meshsdk/midnight-react"; +import ConnectedButton from "./connected-button"; +import { screens } from "./data"; +import ScreenMain from "./screen-main"; + +export const MidnightWallet = () => { + const { open, setOpen } = useWallet(); + const [screen] = useState("main"); + const { hasConnectedWallet } = useAssets(); + + return ( + +
+ {!hasConnectedWallet ? ( + + + + ) : ( + + )} +
+ + event.preventDefault()} + > +
+ {screen == "main" && } +
+ +
+ ); +}; + +interface HeaderProps { + screen: string; + setScreen: (screen: string) => void; +} + +function Header({ + screen, +}: Omit) { + return ( + + + + + {/* @ts-expect-error any type */} + {screens[screen].title} + + + + + ); +} + +function Footer() { + return ( + + + Powered by + + + + Mesh SDK + + + ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/screen-main.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/screen-main.tsx new file mode 100644 index 0000000..57ff999 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/screen-main.tsx @@ -0,0 +1,51 @@ +import IconLace from '../common/icons/icon-lace'; +import { TooltipProvider } from '../common/tooltip'; +import { useWallet, useWalletList } from '@meshsdk/midnight-react'; +import WalletIcon from './wallet-icon'; +import { type JSX } from 'react'; + +export default function ScreenMain({ + setOpen, +}: { + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type + setOpen: Function; +}) { + const wallets = useWalletList(); + const { connectWallet } = useWallet(); + + // Example config map for wallet overrides + const walletsConfig: { [key: string]: { key: string; displayName: string; icon: JSX.Element } } = { + lace: { key: 'mnLace', displayName: 'LACE', icon: } + }; + + return ( + +
+ {wallets.map((wallet, index) => { + const config = walletsConfig[wallet.name]; + if (!config) return null; // Skip rendering if config is not found + const walletKey = config.key; + const displayName = config.displayName; + const icon = config.icon; + + return ( + { + connectWallet(walletKey); + setOpen(false); + }} + /> + ); + })} +
+
+ ); +} diff --git a/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/wallet-icon.tsx b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/wallet-icon.tsx new file mode 100644 index 0000000..b31f507 --- /dev/null +++ b/apps/playground/frontend/src/modules/midnight/wallet-widget/midnight-wallet/wallet-icon.tsx @@ -0,0 +1,34 @@ +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "../common/tooltip"; + +export default function WalletIcon({ + icon, + name, + action, + iconReactNode, +}: { + icon?: string; + name: string; + action: () => void; + iconReactNode?: React.ReactNode; +}) { + return ( + + + + + +

{name}

+
+
+ ); +} diff --git a/apps/playground/frontend/src/pages/counter/index.tsx b/apps/playground/frontend/src/pages/counter/index.tsx new file mode 100644 index 0000000..e426407 --- /dev/null +++ b/apps/playground/frontend/src/pages/counter/index.tsx @@ -0,0 +1,9 @@ +export const Counter = () => { + + return ( + <> + Work in progress... + + ); +}; + diff --git a/apps/playground/frontend/src/pages/home/index.tsx b/apps/playground/frontend/src/pages/home/index.tsx index 2b836e7..10d1798 100644 --- a/apps/playground/frontend/src/pages/home/index.tsx +++ b/apps/playground/frontend/src/pages/home/index.tsx @@ -1,76 +1,8 @@ -import { - MidnightWallet, - useAssets, - useWallet, - } from "@meshsdk/midnight-react"; - import { ModeToggle } from "@/components/mode-toggle"; - - export function Home() { - const { - address, - coinPublicKey, - encryptionPublicKey, - hasConnectedWallet, - isProofServerOnline, - uris, - walletName, - } = useAssets(); - const { connectingWallet, disconnect, setOpen, connectWallet } = useWallet(); - - return ( - <> -

Wallet Dashboard

-
-
-

Wallet Widget

- - -
-

Wallet Actions

-
- - - -
-
-
- -
-

Asset Details

-
-
Wallet Name: {walletName}
-
Address: {address}
-
Coin Public Key: {coinPublicKey}
-
Encryption Public Key: {encryptionPublicKey}
-
Has Connected Wallet: {hasConnectedWallet ? "Yes" : "No"}
-
- Is Proof Server Online: {isProofServerOnline ? "Yes" : "No"} -
-
Indexer: {uris?.indexerUri}
-
IndexerWS: {uris?.indexerWsUri}
-
Proof Server: {uris?.proverServerUri}
-
Node: {uris?.substrateNodeUri}
- - Connecting: {connectingWallet ? "Yes" : "No"} - -
-
-
- - ); - } \ No newline at end of file +export function Home() { + + return ( + <> + Work in progress... + + ); +} diff --git a/apps/playground/frontend/src/pages/wallet-ui/index.tsx b/apps/playground/frontend/src/pages/wallet-ui/index.tsx new file mode 100644 index 0000000..9f106ea --- /dev/null +++ b/apps/playground/frontend/src/pages/wallet-ui/index.tsx @@ -0,0 +1,79 @@ +import { + MidnightWallet, +} from "@/modules/midnight/wallet-widget"; + +import { + useAssets, + useWallet, +} from "@meshsdk/midnight-react"; +import { ModeToggle } from "@/components/mode-toggle"; + +export function WalletUI() { + const { + address, + coinPublicKey, + encryptionPublicKey, + hasConnectedWallet, + isProofServerOnline, + uris, + walletName, + } = useAssets(); + const { connectingWallet, disconnect, setOpen, connectWallet } = useWallet(); + + return ( + <> +

Wallet Dashboard

+
+
+

Wallet Widget

+ + +
+

Wallet Actions

+
+ + + +
+
+
+ +
+

Asset Details

+
+
Wallet Name: {walletName}
+
Address: {address}
+
Coin Public Key: {coinPublicKey}
+
Encryption Public Key: {encryptionPublicKey}
+
Has Connected Wallet: {hasConnectedWallet ? "Yes" : "No"}
+
+ Is Proof Server Online: {isProofServerOnline ? "Yes" : "No"} +
+
Indexer: {uris?.indexerUri}
+
IndexerWS: {uris?.indexerWsUri}
+
Proof Server: {uris?.proverServerUri}
+
Node: {uris?.substrateNodeUri}
+ + Connecting: {connectingWallet ? "Yes" : "No"} + +
+
+
+ + ); +} diff --git a/package-lock.json b/package-lock.json index 3a84d08..4b35847 100644 --- a/package-lock.json +++ b/package-lock.json @@ -146,7 +146,9 @@ "apps/playground/frontend": { "version": "0.0.0", "dependencies": { + "@meshsdk/midnight-core": "*", "@meshsdk/midnight-react": "*", + "@meshsdk/midnight-wallet": "*", "@radix-ui/react-dropdown-menu": "^2.1.15", "@radix-ui/react-slot": "^1.2.3", "@tailwindcss/vite": "^4.1.11", @@ -3154,6 +3156,7 @@ "version": "1.1.14", "resolved": "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.14.tgz", "integrity": "sha512-+CpweKjqpzTmwRwcYECQcNYbI8V9VSQt0SNFKeEBLgfucbsLssU6Ppq7wUdNXEGb573bMjFhVjKVll8rmV6zMw==", + "dev": true, "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.2", @@ -3297,6 +3300,16 @@ } } }, + "node_modules/@radix-ui/react-icons": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@radix-ui/react-icons/-/react-icons-1.3.2.tgz", + "integrity": "sha512-fyQIhGDhzfc9pK2kH6Pl9c4BDJGfMkPqkyIgYDthyNYoNg3wVhoJMMh19WS4Up/1KMPFVpNsT2q3WmXn2N1m6g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "react": "^16.x || ^17.x || ^18.x || ^19.0.0 || ^19.0.0-rc" + } + }, "node_modules/@radix-ui/react-id": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@radix-ui/react-id/-/react-id-1.1.1.tgz", @@ -3511,6 +3524,7 @@ "version": "1.2.7", "resolved": "https://registry.npmjs.org/@radix-ui/react-tooltip/-/react-tooltip-1.2.7.tgz", "integrity": "sha512-Ap+fNYwKTYJ9pzqW+Xe2HtMRbQ/EeWkj2qykZ6SuEV4iS/o1bZI5ssJbk4D2r8XuDuOBVz/tIx2JObtuqU+5Zw==", + "dev": true, "license": "MIT", "dependencies": { "@radix-ui/primitive": "1.1.2", @@ -3666,6 +3680,7 @@ "version": "1.2.3", "resolved": "https://registry.npmjs.org/@radix-ui/react-visually-hidden/-/react-visually-hidden-1.2.3.tgz", "integrity": "sha512-pzJq12tEaaIhqjbzpCuv/OypJY/BPavOofm+dbab+MHLajy277+1lLm6JFcGgF5eskJ6mquGirhXY2GD/8u8Ug==", + "dev": true, "license": "MIT", "dependencies": { "@radix-ui/react-primitive": "2.1.3" @@ -21027,10 +21042,6 @@ "dependencies": { "@meshsdk/midnight-core": "0.0.5", "@meshsdk/midnight-wallet": "0.0.5", - "@radix-ui/react-dialog": "^1.1.6", - "@radix-ui/react-dropdown-menu": "^2.1.6", - "@radix-ui/react-slot": "^1.1.2", - "@radix-ui/react-tooltip": "^1.1.8", "class-variance-authority": "^0.7.1", "lucide-react": "^0.532.0", "tailwind-merge": "^2.6.0", @@ -21038,6 +21049,11 @@ }, "devDependencies": { "@meshsdk/configs": "*", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-icons": "^1.3.2", + "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-tooltip": "^1.1.8", "@types/react": "^19.1.9", "@types/react-dom": "^19.1.7", "autoprefixer": "^10.4.18", diff --git a/packages/mesh-midnight-cli/README.md b/packages/mesh-midnight-cli/README.md new file mode 100644 index 0000000..d7dc898 --- /dev/null +++ b/packages/mesh-midnight-cli/README.md @@ -0,0 +1 @@ +# npx-able CLI that installs templates into a user app \ No newline at end of file diff --git a/packages/mesh-midnight-core/package.json b/packages/mesh-midnight-core/package.json index 4c5c985..7a5784b 100644 --- a/packages/mesh-midnight-core/package.json +++ b/packages/mesh-midnight-core/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/midnight-core", - "version": "0.0.5", + "version": "0.0.6", "description": "Core", "main": "./dist/index.cjs", "browser": "./dist/index.js", diff --git a/packages/mesh-midnight-react/package.json b/packages/mesh-midnight-react/package.json index 5fe4a36..13d1660 100644 --- a/packages/mesh-midnight-react/package.json +++ b/packages/mesh-midnight-react/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/midnight-react", - "version": "0.0.5", + "version": "0.0.6", "description": "React component library ", "main": "./dist/index.cjs", "browser": "./dist/index.js", @@ -29,12 +29,8 @@ "prepack:all": "npm run clean && npm install && npm run build && npm run pack" }, "dependencies": { - "@meshsdk/midnight-core": "0.0.5", - "@meshsdk/midnight-wallet": "0.0.5", - "@radix-ui/react-dialog": "^1.1.6", - "@radix-ui/react-dropdown-menu": "^2.1.6", - "@radix-ui/react-slot": "^1.1.2", - "@radix-ui/react-tooltip": "^1.1.8", + "@meshsdk/midnight-core": "0.0.6", + "@meshsdk/midnight-wallet": "0.0.6", "class-variance-authority": "^0.7.1", "lucide-react": "^0.532.0", "tailwind-merge": "^2.6.0", @@ -48,7 +44,12 @@ "concurrently": "^8.0.1", "postcss": "^8.4.35", "tailwindcss": "^3.4.1", - "typescript": "latest" + "typescript": "latest", + "@radix-ui/react-dialog": "^1.1.6", + "@radix-ui/react-dropdown-menu": "^2.1.6", + "@radix-ui/react-icons": "^1.3.2", + "@radix-ui/react-slot": "^1.1.2", + "@radix-ui/react-tooltip": "^1.1.8" }, "peerDependencies": { "@types/react": "*", diff --git a/packages/mesh-midnight-react/src/common/button.tsx b/packages/mesh-midnight-react/src/common/button.tsx index 0c0adc8..1c0bcfc 100644 --- a/packages/mesh-midnight-react/src/common/button.tsx +++ b/packages/mesh-midnight-react/src/common/button.tsx @@ -1,25 +1,24 @@ -import type { VariantProps } from "class-variance-authority"; -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { cva } from "class-variance-authority"; +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" -import { cn } from "./cn"; +import { cn } from "./cn" const buttonVariants = cva( - "mesh-inline-flex mesh-items-center mesh-justify-center mesh-gap-2 mesh-whitespace-nowrap mesh-rounded-md mesh-text-sm mesh-font-medium mesh-transition-colors mesh-focus-visible:outline-none mesh-focus-visible:ring-1 mesh-focus-visible:ring-ring mesh-disabled:pointer-events-none mesh-disabled:opacity-50 [&_svg]:mesh-pointer-events-none [&_svg]:mesh-size-4 [&_svg]:mesh-shrink-0", + "mesh-inline-flex mesh-items-center mesh-justify-center mesh-whitespace-nowrap mesh-rounded-md mesh-text-sm mesh-font-medium mesh-transition-colors focus-visible:mesh-outline-none focus-visible:mesh-ring-1 focus-visible:mesh-ring-zinc-950 disabled:mesh-pointer-events-none disabled:mesh-opacity-50 dark:focus-visible:mesh-ring-zinc-300 dark:mesh-text-white", { variants: { variant: { default: - "mesh-bg-primary mesh-text-primary-foreground mesh-shadow mesh-hover:bg-primary/90", + "mesh-bg-zinc-900 mesh-text-zinc-50 mesh-shadow hover:mesh-bg-zinc-900/90 dark:mesh-bg-zinc-50 dark:mesh-text-zinc-900 dark:hover:mesh-bg-zinc-50/90", destructive: - "mesh-bg-destructive mesh-text-destructive-foreground mesh-shadow-sm mesh-hover:bg-destructive/90", + "mesh-bg-red-500 mesh-text-zinc-50 mesh-shadow-sm hover:mesh-bg-red-500/90 dark:mesh-bg-red-900 dark:mesh-text-zinc-50 dark:hover:mesh-bg-red-900/90", outline: - "mesh-border mesh-border-input mesh-bg-background mesh-shadow-sm mesh-hover:bg-accent mesh-hover:text-accent-foreground", + "mesh-border mesh-border-zinc-200 mesh-bg-white mesh-shadow-sm hover:mesh-bg-zinc-100 hover:mesh-text-zinc-900 dark:mesh-border-zinc-800 dark:mesh-bg-zinc-950 dark:hover:mesh-bg-zinc-800 dark:hover:mesh-text-zinc-50", secondary: - "mesh-bg-secondary mesh-text-secondary-foreground mesh-shadow-sm mesh-hover:bg-secondary/80", - ghost: "mesh-hover:bg-accent mesh-hover:text-accent-foreground", - link: "mesh-text-primary mesh-underline-offset-4 mesh-hover:underline", + "mesh-bg-zinc-100 mesh-text-zinc-900 mesh-shadow-sm hover:mesh-bg-zinc-100/80 dark:mesh-bg-zinc-800 dark:mesh-text-zinc-50 dark:hover:mesh-bg-zinc-800/80", + ghost: "hover:mesh-bg-zinc-100 hover:mesh-text-zinc-900 dark:hover:mesh-bg-zinc-800 dark:hover:mesh-text-zinc-50", + link: "mesh-text-zinc-900 mesh-underline-offset-4 hover:mesh-underline dark:mesh-text-zinc-50", }, size: { default: "mesh-h-9 mesh-px-4 mesh-py-2", @@ -32,27 +31,27 @@ const buttonVariants = cva( variant: "default", size: "default", }, - }, -); + } +) export interface ButtonProps extends React.ButtonHTMLAttributes, VariantProps { - asChild?: boolean; + asChild?: boolean } const Button = React.forwardRef( ({ className, variant, size, asChild = false, ...props }, ref) => { - const Comp = asChild ? Slot : "button"; + const Comp = asChild ? Slot : "button" return ( - ); - }, -); -Button.displayName = "Button"; + ) + } +) +Button.displayName = "Button" -export { Button, buttonVariants }; +export { Button, buttonVariants } diff --git a/packages/mesh-midnight-react/src/common/dialog.tsx b/packages/mesh-midnight-react/src/common/dialog.tsx index 4ac344c..dd4bfe1 100644 --- a/packages/mesh-midnight-react/src/common/dialog.tsx +++ b/packages/mesh-midnight-react/src/common/dialog.tsx @@ -1,35 +1,31 @@ -"use client"; +import * as React from "react" +import * as DialogPrimitive from "@radix-ui/react-dialog" +import { Cross2Icon } from "@radix-ui/react-icons" -import * as React from "react"; -import * as DialogPrimitive from "@radix-ui/react-dialog"; -import { X } from "lucide-react"; +import { cn } from "./cn" -import { cn } from "./cn"; +const Dialog = DialogPrimitive.Root -const Dialog = DialogPrimitive.Root; +const DialogTrigger = DialogPrimitive.Trigger -const DialogTrigger = DialogPrimitive.Trigger; +const DialogPortal = DialogPrimitive.Portal -const DialogPortal = DialogPrimitive.Portal; - -const DialogClose = DialogPrimitive.Close; +const DialogClose = DialogPrimitive.Close const DialogOverlay = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, ...props }, ref) => ( -
- -
-)); -DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +)) +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName const DialogContent = React.forwardRef< React.ElementRef, @@ -37,25 +33,23 @@ const DialogContent = React.forwardRef< >(({ className, children, ...props }, ref) => ( -
- - {children} - - - Close - - -
+ + {children} + + + Close + +
-)); -DialogContent.displayName = DialogPrimitive.Content.displayName; +)) +DialogContent.displayName = DialogPrimitive.Content.displayName const DialogHeader = ({ className, @@ -63,13 +57,13 @@ const DialogHeader = ({ }: React.HTMLAttributes) => (
-); -DialogHeader.displayName = "DialogHeader"; +) +DialogHeader.displayName = "DialogHeader" const DialogFooter = ({ className, @@ -78,12 +72,12 @@ const DialogFooter = ({
-); -DialogFooter.displayName = "DialogFooter"; +) +DialogFooter.displayName = "DialogFooter" const DialogTitle = React.forwardRef< React.ElementRef, @@ -93,12 +87,12 @@ const DialogTitle = React.forwardRef< ref={ref} className={cn( "mesh-text-lg mesh-font-semibold mesh-leading-none mesh-tracking-tight", - className, + className )} {...props} /> -)); -DialogTitle.displayName = DialogPrimitive.Title.displayName; +)) +DialogTitle.displayName = DialogPrimitive.Title.displayName const DialogDescription = React.forwardRef< React.ElementRef, @@ -106,11 +100,11 @@ const DialogDescription = React.forwardRef< >(({ className, ...props }, ref) => ( -)); -DialogDescription.displayName = DialogPrimitive.Description.displayName; +)) +DialogDescription.displayName = DialogPrimitive.Description.displayName export { Dialog, @@ -123,4 +117,4 @@ export { DialogFooter, DialogTitle, DialogDescription, -}; +} \ No newline at end of file diff --git a/packages/mesh-midnight-react/src/common/dropdown-menu.tsx b/packages/mesh-midnight-react/src/common/dropdown-menu.tsx index 253734e..2bb07a3 100644 --- a/packages/mesh-midnight-react/src/common/dropdown-menu.tsx +++ b/packages/mesh-midnight-react/src/common/dropdown-menu.tsx @@ -1,6 +1,10 @@ import * as React from "react" import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" -import { Check, ChevronRight, Circle } from "lucide-react" +import { + CheckIcon, + ChevronRightIcon, + DotFilledIcon, +} from "@radix-ui/react-icons" import { cn } from "./cn" @@ -25,14 +29,14 @@ const DropdownMenuSubTrigger = React.forwardRef< {children} - + )) DropdownMenuSubTrigger.displayName = @@ -45,7 +49,7 @@ const DropdownMenuSubContent = React.forwardRef< svg]:mesh-size-4 [&>svg]:mesh-shrink-0", - inset && "pl-8", + "mesh-relative mesh-flex mesh-cursor-default mesh-select-none mesh-items-center mesh-rounded-sm mesh-px-2 mesh-py-1.5 mesh-text-sm mesh-outline-none mesh-transition-colors hover:mesh-bg-slate-100 focus:mesh-bg-slate-100 focus:mesh-text-slate-900 data-[disabled]:mesh-pointer-events-none data-[disabled]:mesh-opacity-50", + inset && "mesh-pl-8", className )} {...props} @@ -98,7 +102,7 @@ const DropdownMenuCheckboxItem = React.forwardRef< - + {children} @@ -122,14 +126,14 @@ const DropdownMenuRadioItem = React.forwardRef< - + {children} @@ -161,7 +165,8 @@ const DropdownMenuSeparator = React.forwardRef< >(({ className, ...props }, ref) => ( )) diff --git a/packages/mesh-midnight-react/src/common/tooltip.tsx b/packages/mesh-midnight-react/src/common/tooltip.tsx index cb580e7..e34bd33 100644 --- a/packages/mesh-midnight-react/src/common/tooltip.tsx +++ b/packages/mesh-midnight-react/src/common/tooltip.tsx @@ -1,5 +1,3 @@ -"use client" - import * as React from "react" import * as TooltipPrimitive from "@radix-ui/react-tooltip" @@ -15,17 +13,15 @@ const TooltipContent = React.forwardRef< React.ElementRef, React.ComponentPropsWithoutRef >(({ className, sideOffset = 4, ...props }, ref) => ( - - - + )) TooltipContent.displayName = TooltipPrimitive.Content.displayName diff --git a/packages/mesh-midnight-react/src/index.ts b/packages/mesh-midnight-react/src/index.ts index 2b34e62..3050f8a 100644 --- a/packages/mesh-midnight-react/src/index.ts +++ b/packages/mesh-midnight-react/src/index.ts @@ -2,5 +2,5 @@ export * from "./midnight-wallet"; export * from "./contexts"; export * from "./hooks"; -export * from "./mesh-badge"; + diff --git a/packages/mesh-midnight-react/src/mesh-badge/index.tsx b/packages/mesh-midnight-react/src/mesh-badge/index.tsx deleted file mode 100644 index b3c4a89..0000000 --- a/packages/mesh-midnight-react/src/mesh-badge/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import { MeshLogo } from "./mesh-logo"; - -export const MeshBadge = ({ isDark = false }) => ( - - - Mesh - -); diff --git a/packages/mesh-midnight-react/src/mesh-badge/mesh-logo.tsx b/packages/mesh-midnight-react/src/mesh-badge/mesh-logo.tsx deleted file mode 100644 index 0af0411..0000000 --- a/packages/mesh-midnight-react/src/mesh-badge/mesh-logo.tsx +++ /dev/null @@ -1,10 +0,0 @@ -export const MeshLogo = () => ( - - - -); diff --git a/packages/mesh-midnight-react/src/midnight-wallet/connected-button.tsx b/packages/mesh-midnight-react/src/midnight-wallet/connected-button.tsx index 712fb81..f7d73f8 100644 --- a/packages/mesh-midnight-react/src/midnight-wallet/connected-button.tsx +++ b/packages/mesh-midnight-react/src/midnight-wallet/connected-button.tsx @@ -11,7 +11,7 @@ export default function ConnectedButton() { {address && ( - diff --git a/packages/mesh-midnight-react/src/midnight-wallet/index.tsx b/packages/mesh-midnight-react/src/midnight-wallet/index.tsx index 55c350c..2e58567 100644 --- a/packages/mesh-midnight-react/src/midnight-wallet/index.tsx +++ b/packages/mesh-midnight-react/src/midnight-wallet/index.tsx @@ -13,29 +13,36 @@ import ConnectedButton from './connected-button'; import { screens } from './data'; import ScreenMain from './screen-main'; -export const MidnightWallet = () => { +interface ButtonProps { + isDark?: boolean; +} + +export const MidnightWallet = ({ isDark }: ButtonProps) => { const { open, setOpen } = useWallet(); const [screen, setScreen] = useState('main'); - const { hasConnectedWallet } = useAssets(); + const { hasConnectedWallet } = useAssets(); return ( - +
+
{!hasConnectedWallet ? ( - + ) : ( )}
- event.preventDefault()}>
{screen == 'main' && }
+
+
+ ); }; @@ -61,11 +68,12 @@ function Footer() { Powered by - + Mesh SDK diff --git a/packages/mesh-midnight-react/src/styles.css b/packages/mesh-midnight-react/src/styles.css index 00cf810..a90f074 100644 --- a/packages/mesh-midnight-react/src/styles.css +++ b/packages/mesh-midnight-react/src/styles.css @@ -2,58 +2,3 @@ @tailwind components; @tailwind utilities; -:root { - --background: 0 0% 100%; - --background2: 0 0% 100%; - --foreground: 0 0% 3.9%; - --card: 0 0% 100%; - --card-foreground: 0 0% 3.9%; - --popover: 0 0% 100%; - --popover-foreground: 0 0% 3.9%; - --primary: 0 0% 9%; - --primary-foreground: 0 0% 98%; - --secondary: 0 0% 96.1%; - --secondary-foreground: 0 0% 9%; - --muted: 0 0% 96.1%; - --muted-foreground: 0 0% 45.1%; - --accent: 0 0% 96.1%; - --accent-foreground: 0 0% 9%; - --destructive: 0 84.2% 60.2%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 89.8%; - --input: 0 0% 89.8%; - --ring: 0 0% 3.9%; - --chart-1: 12 76% 61%; - --chart-2: 173 58% 39%; - --chart-3: 197 37% 24%; - --chart-4: 43 74% 66%; - --chart-5: 27 87% 67%; - --radius: 0.5rem; -} -.dark { - --background: 0 0% 3.9%; - --background2: 0 0% 3.9%; - --foreground: 0 0% 98%; - --card: 0 0% 3.9%; - --card-foreground: 0 0% 98%; - --popover: 0 0% 3.9%; - --popover-foreground: 0 0% 98%; - --primary: 0 0% 98%; - --primary-foreground: 0 0% 9%; - --secondary: 0 0% 14.9%; - --secondary-foreground: 0 0% 98%; - --muted: 0 0% 14.9%; - --muted-foreground: 0 0% 63.9%; - --accent: 0 0% 14.9%; - --accent-foreground: 0 0% 98%; - --destructive: 0 62.8% 30.6%; - --destructive-foreground: 0 0% 98%; - --border: 0 0% 14.9%; - --input: 0 0% 14.9%; - --ring: 0 0% 83.1%; - --chart-1: 220 70% 50%; - --chart-2: 160 60% 45%; - --chart-3: 30 80% 55%; - --chart-4: 280 65% 60%; - --chart-5: 340 75% 55%; -} \ No newline at end of file diff --git a/packages/mesh-midnight-react/tailwind.config.ts b/packages/mesh-midnight-react/tailwind.config.ts index 1564147..814cb56 100644 --- a/packages/mesh-midnight-react/tailwind.config.ts +++ b/packages/mesh-midnight-react/tailwind.config.ts @@ -8,53 +8,10 @@ const config: Pick< > = { content: ["./src/**/*.tsx", "./src/common/**/*.tsx"], darkMode: 'class', - prefix: "mesh-", + prefix: "mesh-", presets: [sharedConfig], theme: { extend: { - colors: { - background: 'hsl(var(--background))', - background2: 'hsl(var(--background2))', - foreground: 'hsl(var(--foreground))', - card: { - DEFAULT: 'hsl(var(--card))', - foreground: 'hsl(var(--card-foreground))' - }, - popover: { - DEFAULT: 'hsl(var(--popover))', - foreground: 'hsl(var(--popover-foreground))' - }, - primary: { - DEFAULT: 'hsl(var(--primary))', - foreground: 'hsl(var(--primary-foreground))' - }, - secondary: { - DEFAULT: 'hsl(var(--secondary))', - foreground: 'hsl(var(--secondary-foreground))' - }, - muted: { - DEFAULT: 'hsl(var(--muted))', - foreground: 'hsl(var(--muted-foreground))' - }, - accent: { - DEFAULT: 'hsl(var(--accent))', - foreground: 'hsl(var(--accent-foreground))' - }, - destructive: { - DEFAULT: 'hsl(var(--destructive))', - foreground: 'hsl(var(--destructive-foreground))' - }, - border: 'hsl(var(--border))', - input: 'hsl(var(--input))', - ring: 'hsl(var(--ring))', - chart: { - '1': 'hsl(var(--chart-1))', - '2': 'hsl(var(--chart-2))', - '3': 'hsl(var(--chart-3))', - '4': 'hsl(var(--chart-4))', - '5': 'hsl(var(--chart-5))' - } - }, keyframes: { "accordion-down": { from: { diff --git a/packages/mesh-midnight-ui-templates/README.md b/packages/mesh-midnight-ui-templates/README.md new file mode 100644 index 0000000..3821b66 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/README.md @@ -0,0 +1 @@ +# The copyable UI source (Tailwind v4 + ShadCN) \ No newline at end of file diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/button.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/button.tsx new file mode 100644 index 0000000..3f29f7a --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/button.tsx @@ -0,0 +1,58 @@ +import type { VariantProps } from "class-variance-authority"; +import * as React from "react"; +import { Slot } from "@radix-ui/react-slot"; +import { cva } from "class-variance-authority"; + +import { cn } from "./cn"; + +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: + "bg-primary text-primary-foreground shadow hover:bg-primary/90", + destructive: + "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90", + outline: + "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground", + secondary: + "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80", + ghost: "hover:bg-accent hover:text-accent-foreground", + link: "text-primary underline-offset-4 hover:underline", + }, + size: { + default: "h-9 px-4 py-2", + sm: "h-8 rounded-md px-3 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + }, + defaultVariants: { + variant: "default", + size: "default", + }, + }, +); + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean; +} + +const Button = React.forwardRef( + ({ className, variant, size, asChild = false, ...props }, ref) => { + const Comp = asChild ? Slot : "button"; + return ( + + ); + }, +); +Button.displayName = "Button"; + +export { Button, buttonVariants }; diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/cn.ts b/packages/mesh-midnight-ui-templates/wallet-widget/common/cn.ts new file mode 100644 index 0000000..88283f0 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/cn.ts @@ -0,0 +1,7 @@ +import type { ClassValue } from "clsx"; +import { clsx } from "clsx"; +import { twMerge } from "tailwind-merge"; + +export function cn(...inputs: ClassValue[]) { + return twMerge(clsx(inputs)); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/dialog.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/dialog.tsx new file mode 100644 index 0000000..9ce8acc --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/dialog.tsx @@ -0,0 +1,121 @@ +import * as React from "react"; +import * as DialogPrimitive from "@radix-ui/react-dialog"; +import { X } from "lucide-react"; + +import { cn } from "./cn"; + +const Dialog = DialogPrimitive.Root; + +const DialogTrigger = DialogPrimitive.Trigger; + +const DialogPortal = DialogPrimitive.Portal; + +const DialogClose = DialogPrimitive.Close; + +const DialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; + +const DialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + {children} + + + Close + + + +)); +DialogContent.displayName = DialogPrimitive.Content.displayName; + +const DialogHeader = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogHeader.displayName = "DialogHeader"; + +const DialogFooter = ({ + className, + ...props +}: React.HTMLAttributes) => ( +
+); +DialogFooter.displayName = "DialogFooter"; + +const DialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogTitle.displayName = DialogPrimitive.Title.displayName; + +const DialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +DialogDescription.displayName = DialogPrimitive.Description.displayName; + +export { + Dialog, + DialogPortal, + DialogOverlay, + DialogTrigger, + DialogClose, + DialogContent, + DialogHeader, + DialogFooter, + DialogTitle, + DialogDescription, +}; diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/dropdown-menu.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/dropdown-menu.tsx new file mode 100644 index 0000000..004b854 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/dropdown-menu.tsx @@ -0,0 +1,202 @@ +import * as React from "react" +import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu" +import { Check, ChevronRight, Circle } from "lucide-react" + +import { cn } from "./cn" + +const DropdownMenu = DropdownMenuPrimitive.Root + +const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger + +const DropdownMenuGroup = DropdownMenuPrimitive.Group + +const DropdownMenuPortal = DropdownMenuPrimitive.Portal + +const DropdownMenuSub = DropdownMenuPrimitive.Sub + +const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup + +const DropdownMenuSubTrigger = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, children, ...props }, ref) => ( + + {children} + + +)) +DropdownMenuSubTrigger.displayName = + DropdownMenuPrimitive.SubTrigger.displayName + +const DropdownMenuSubContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSubContent.displayName = + DropdownMenuPrimitive.SubContent.displayName + +const DropdownMenuContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName + +const DropdownMenuItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + svg]:size-4 [&>svg]:shrink-0", + inset && "pl-8", + className + )} + {...props} + /> +)) +DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName + +const DropdownMenuCheckboxItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, checked, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuCheckboxItem.displayName = + DropdownMenuPrimitive.CheckboxItem.displayName + +const DropdownMenuRadioItem = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, children, ...props }, ref) => ( + + + + + + + {children} + +)) +DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName + +const DropdownMenuLabel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef & { + inset?: boolean + } +>(({ className, inset, ...props }, ref) => ( + +)) +DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName + +const DropdownMenuSeparator = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)) +DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName + +const DropdownMenuShortcut = ({ + className, + ...props +}: React.HTMLAttributes) => { + return ( + + ) +} +DropdownMenuShortcut.displayName = "DropdownMenuShortcut" + +export { + DropdownMenu, + DropdownMenuTrigger, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuCheckboxItem, + DropdownMenuRadioItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuShortcut, + DropdownMenuGroup, + DropdownMenuPortal, + DropdownMenuSub, + DropdownMenuSubContent, + DropdownMenuSubTrigger, + DropdownMenuRadioGroup, +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-book-dashed.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-book-dashed.tsx new file mode 100644 index 0000000..185604a --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-book-dashed.tsx @@ -0,0 +1,34 @@ +export default function IconBookDashed() { + return ( + + + + + + + + + + + + + + ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-chevron-right.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-chevron-right.tsx new file mode 100644 index 0000000..513880f --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-chevron-right.tsx @@ -0,0 +1,24 @@ +export default function IconChevronRight() { + return ( + + + + ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-download.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-download.tsx new file mode 100644 index 0000000..d2cd1b7 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-download.tsx @@ -0,0 +1,26 @@ +export default function IconDownload() { + return ( + + + + + + ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-fingerprint.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-fingerprint.tsx new file mode 100644 index 0000000..dae5b32 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-fingerprint.tsx @@ -0,0 +1,32 @@ +export default function IconFingerprint() { + return ( + + + + + + + + + + + + ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-lace.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-lace.tsx new file mode 100644 index 0000000..79d14a1 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-lace.tsx @@ -0,0 +1,16 @@ +export default function IconLace() { + return ( + + + + + + + + + + + + + ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-monitor-smartphone.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-monitor-smartphone.tsx new file mode 100644 index 0000000..5efbaf0 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-monitor-smartphone.tsx @@ -0,0 +1,26 @@ +export default function IconMonitorSmartphone() { + return ( + + + + + + + ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-plus.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-plus.tsx new file mode 100644 index 0000000..3edadba --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/icons/icon-plus.tsx @@ -0,0 +1,24 @@ +export default function IconPlus() { + return ( + + + + + ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/common/tooltip.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/common/tooltip.tsx new file mode 100644 index 0000000..e13c14b --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/common/tooltip.tsx @@ -0,0 +1,32 @@ +"use client" + +import * as React from "react" +import * as TooltipPrimitive from "@radix-ui/react-tooltip" + +import { cn } from "./cn" + +const TooltipProvider = TooltipPrimitive.Provider + +const Tooltip = TooltipPrimitive.Root + +const TooltipTrigger = TooltipPrimitive.Trigger + +const TooltipContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, sideOffset = 4, ...props }, ref) => ( + + + +)) +TooltipContent.displayName = TooltipPrimitive.Content.displayName + +export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/index.ts b/packages/mesh-midnight-ui-templates/wallet-widget/index.ts new file mode 100644 index 0000000..96e9a89 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/index.ts @@ -0,0 +1,2 @@ +export * from "./midnight-wallet"; + diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/connected-button.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/connected-button.tsx new file mode 100644 index 0000000..96c5611 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/connected-button.tsx @@ -0,0 +1,40 @@ +import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from '../common/dropdown-menu'; +import { Button } from '../common/button'; +import { useAssets, useWallet } from '@meshsdk/midnight-react'; + +export default function ConnectedButton() { + const { disconnect } = useWallet(); + const { address } = useAssets(); + + return ( + <> + {address && ( + + + + + + { + navigator.clipboard.writeText(address); + }} + > + Copy Address + + { + disconnect(); + }} + > + Disconnect + + + + )} + + ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/data.ts b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/data.ts new file mode 100644 index 0000000..d2fad0d --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/data.ts @@ -0,0 +1,5 @@ +export const screens = { + main: { + title: "Connect Wallet", + }, +}; diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/index.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/index.tsx new file mode 100644 index 0000000..4eb713f --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/index.tsx @@ -0,0 +1,91 @@ +import { useState } from "react"; +import { Button } from "../common/button"; +import { + Dialog, + DialogContent, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "../common/dialog"; +import { useAssets, useWallet } from "@meshsdk/midnight-react"; +import ConnectedButton from "./connected-button"; +import { screens } from "./data"; +import ScreenMain from "./screen-main"; + +export const MidnightWallet = () => { + const { open, setOpen } = useWallet(); + const [screen] = useState("main"); + const { hasConnectedWallet } = useAssets(); + + return ( + +
+ {!hasConnectedWallet ? ( + + + + ) : ( + + )} +
+ + event.preventDefault()} + > +
+ {screen == "main" && } +
+ +
+ ); +}; + +interface HeaderProps { + screen: string; + setScreen: (screen: string) => void; +} + +function Header({ + screen, +}: Omit) { + return ( + + + + + {/* @ts-expect-error any type */} + {screens[screen].title} + + + + + ); +} + +function Footer() { + return ( + + + Powered by + + + + Mesh SDK + + + ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/screen-main.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/screen-main.tsx new file mode 100644 index 0000000..57ff999 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/screen-main.tsx @@ -0,0 +1,51 @@ +import IconLace from '../common/icons/icon-lace'; +import { TooltipProvider } from '../common/tooltip'; +import { useWallet, useWalletList } from '@meshsdk/midnight-react'; +import WalletIcon from './wallet-icon'; +import { type JSX } from 'react'; + +export default function ScreenMain({ + setOpen, +}: { + // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type + setOpen: Function; +}) { + const wallets = useWalletList(); + const { connectWallet } = useWallet(); + + // Example config map for wallet overrides + const walletsConfig: { [key: string]: { key: string; displayName: string; icon: JSX.Element } } = { + lace: { key: 'mnLace', displayName: 'LACE', icon: } + }; + + return ( + +
+ {wallets.map((wallet, index) => { + const config = walletsConfig[wallet.name]; + if (!config) return null; // Skip rendering if config is not found + const walletKey = config.key; + const displayName = config.displayName; + const icon = config.icon; + + return ( + { + connectWallet(walletKey); + setOpen(false); + }} + /> + ); + })} +
+
+ ); +} diff --git a/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/wallet-icon.tsx b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/wallet-icon.tsx new file mode 100644 index 0000000..b31f507 --- /dev/null +++ b/packages/mesh-midnight-ui-templates/wallet-widget/midnight-wallet/wallet-icon.tsx @@ -0,0 +1,34 @@ +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "../common/tooltip"; + +export default function WalletIcon({ + icon, + name, + action, + iconReactNode, +}: { + icon?: string; + name: string; + action: () => void; + iconReactNode?: React.ReactNode; +}) { + return ( + + + + + +

{name}

+
+
+ ); +} diff --git a/packages/mesh-midnight-wallet/package.json b/packages/mesh-midnight-wallet/package.json index 807e40d..0823711 100644 --- a/packages/mesh-midnight-wallet/package.json +++ b/packages/mesh-midnight-wallet/package.json @@ -1,6 +1,6 @@ { "name": "@meshsdk/midnight-wallet", - "version": "0.0.5", + "version": "0.0.6", "description": "Wallets", "main": "./dist/index.cjs", "browser": "./dist/index.js", @@ -31,7 +31,7 @@ }, "devDependencies": { "@meshsdk/configs": "*", - "@meshsdk/midnight-core": "0.0.5", + "@meshsdk/midnight-core": "0.0.6", "eslint": "^8.57.0", "tsup": "^8.0.2", "typedoc": "^0.26.3", diff --git a/packages/mesh-midnight-wallet/src/embedded/embedded-wallet.ts b/packages/mesh-midnight-wallet/src/embedded/embedded-wallet.ts index 908c2c7..473b9de 100644 --- a/packages/mesh-midnight-wallet/src/embedded/embedded-wallet.ts +++ b/packages/mesh-midnight-wallet/src/embedded/embedded-wallet.ts @@ -7,52 +7,60 @@ import { wordlist as english } from '@scure/bip39/wordlists/english'; import { HDKey } from '@scure/bip32'; import { generateRandomSeed, HDWallet, Roles } from '@midnight-ntwrk/wallet-sdk-hd'; -export const mnemonicToWords: (mnemonic: string) => string[] = (mnemonic: string) => mnemonic.split(' '); - -export const generateMnemonicWords: (strength?: number) => string[] = (strength = 256) => - mnemonicToWords(bip39.generateMnemonic(english, strength)); - -export const validateMnemonic = (mnemonic: string): boolean => bip39.validateMnemonic(mnemonic, english); - -const mnemonicWords = generateMnemonicWords().join(' '); -const seedDerived = mnemonicToSeedSync(mnemonicWords); // 64 bytes - -const seddDerivedHex = Buffer.from(seedDerived).toString('hex'); // 64 bytes -// This is the seed that will be used to generate the wallet since the wallet implementation expects 32 bytes hex string. -const seedDerivedHex32 = Buffer.from(seedDerived).subarray(0, 32).toString('hex'); // 32 bytes -// Optionally generate a random seed -const seedGenerated = generateRandomSeed(); //32 bytes - -// The following code is for reference only, Midnight provides a HDWallet abstraction using the HdKey from scure/bip32 implementation -const rootKey = HDKey.fromMasterSeed(seedDerived); -// How to calculate the path -// const path = `m/${PURPOSE}'/${COIN_TYPE}'/${this.account}'/${this.role}/${index}`; -// const derivedKey = rootKey.derive(path); - -// This is for reference only, another way to create a root key using BIP32 -const bip32 = BIP32Factory(ecc); -const root = bip32.fromSeed(seedDerived); - -console.log({ mnemonicWords: mnemonicWords }); -console.log({ seedDerived }); -console.log({ seddDerivedHex }); -console.log({ seedDerivedHex32 }); -console.log({ seedGenerated }); -console.log({ rootKey }); -console.log({ root }); -console.log({ validateMnemonic: validateMnemonic(mnemonicWords) }); - -const generatedWallet = HDWallet.fromSeed(seedDerived); //seed could be 32 bytes or 64 bytes - -if (generatedWallet.type == 'seedOk') { - const zswapKey = generatedWallet.hdWallet.selectAccount(0).selectRole(Roles.Zswap).deriveKeyAt(0); - if (zswapKey.type === 'keyDerived') { - console.log('success', zswapKey.key); +export function initializeWallet() { + const mnemonicToWords: (mnemonic: string) => string[] = (mnemonic: string) => mnemonic.split(' '); + + const generateMnemonicWords: (strength?: number) => string[] = (strength = 256) => + mnemonicToWords(bip39.generateMnemonic(english, strength)); + + const validateMnemonic = (mnemonic: string): boolean => bip39.validateMnemonic(mnemonic, english); + + const mnemonicWords = generateMnemonicWords().join(' '); + const seedDerived = mnemonicToSeedSync(mnemonicWords); // 64 bytes + + const seddDerivedHex = Buffer.from(seedDerived).toString('hex'); // 64 bytes + // This is the seed that will be used to generate the wallet since the wallet implementation expects 32 bytes hex string. + const seedDerivedHex32 = Buffer.from(seedDerived).subarray(0, 32).toString('hex'); // 32 bytes + // Optionally generate a random seed + const seedGenerated = generateRandomSeed(); //32 bytes + + // The following code is for reference only, Midnight provides a HDWallet abstraction using the HdKey from scure/bip32 implementation + const rootKey = HDKey.fromMasterSeed(seedDerived); + // How to calculate the path + // const path = `m/${PURPOSE}'/${COIN_TYPE}'/${this.account}'/${this.role}/${index}`; + // const derivedKey = rootKey.derive(path); + + // This is for reference only, another way to create a root key using BIP32 + const bip32 = BIP32Factory(ecc); + const root = bip32.fromSeed(seedDerived); + + console.log({ mnemonicWords }); + console.log({ seedDerived }); + console.log({ seddDerivedHex }); + console.log({ seedDerivedHex32 }); + console.log({ seedGenerated }); + console.log({ rootKey }); + console.log({ root }); + console.log({ validateMnemonic: validateMnemonic(mnemonicWords) }); + + const generatedWallet = HDWallet.fromSeed(seedDerived); //seed could be 32 bytes or 64 bytes + + if (generatedWallet.type == 'seedOk') { + const zswapKey = generatedWallet.hdWallet.selectAccount(0).selectRole(Roles.Zswap).deriveKeyAt(0); + if (zswapKey.type === 'keyDerived') { + console.log('success', zswapKey.key); + return { success: true, key: zswapKey.key }; + } else { + console.error('Error deriving key'); + return { success: false, error: 'Error deriving key' }; + } } else { - console.error('Error deriving key'); + console.error('Error generating HDWallet'); + return { success: false, error: 'Error generating HDWallet' }; } -} else { - console.error('Error generating HDWallet'); } +// Uncomment this line if you want to run the wallet initialization when this module is imported +// initializeWallet(); +