@mysten/create-dapp 0.5.13 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +39 -2
  2. package/README.md +0 -1
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +32 -8
  6. package/dist/index.js.map +1 -1
  7. package/package.json +10 -10
  8. package/src/index.ts +58 -36
  9. package/templates/.oxlintrc.json +5 -0
  10. package/templates/react-client-dapp/README.md +31 -4
  11. package/templates/react-client-dapp/index.html +2 -48
  12. package/templates/react-client-dapp/package.json +14 -17
  13. package/templates/react-client-dapp/prettier.config.cjs +0 -1
  14. package/templates/react-client-dapp/src/App.tsx +12 -30
  15. package/templates/react-client-dapp/src/OwnedObjects.tsx +58 -31
  16. package/templates/react-client-dapp/src/WalletStatus.tsx +38 -13
  17. package/templates/react-client-dapp/src/components/ui/card.tsx +75 -0
  18. package/templates/react-client-dapp/src/dApp-kit.ts +24 -0
  19. package/templates/react-client-dapp/src/index.css +39 -0
  20. package/templates/react-client-dapp/src/lib/utils.ts +6 -0
  21. package/templates/react-client-dapp/src/main.tsx +8 -14
  22. package/templates/react-client-dapp/vite.config.mts +2 -1
  23. package/templates/react-e2e-counter/.gitattributes +2 -0
  24. package/templates/react-e2e-counter/README.md +53 -7
  25. package/templates/react-e2e-counter/index.html +2 -48
  26. package/templates/react-e2e-counter/package.json +18 -20
  27. package/templates/react-e2e-counter/prettier.config.cjs +0 -1
  28. package/templates/react-e2e-counter/src/App.tsx +29 -30
  29. package/templates/react-e2e-counter/src/Counter.tsx +147 -74
  30. package/templates/react-e2e-counter/src/CreateCounter.tsx +84 -43
  31. package/templates/react-e2e-counter/src/components/ui/button.tsx +52 -0
  32. package/templates/react-e2e-counter/src/components/ui/card.tsx +75 -0
  33. package/templates/react-e2e-counter/src/constants.ts +4 -3
  34. package/templates/react-e2e-counter/src/contracts/counter/counter.ts +96 -0
  35. package/templates/react-e2e-counter/src/contracts/utils/index.ts +243 -0
  36. package/templates/react-e2e-counter/src/dApp-kit.ts +48 -0
  37. package/templates/react-e2e-counter/src/index.css +39 -0
  38. package/templates/react-e2e-counter/src/lib/utils.ts +6 -0
  39. package/templates/react-e2e-counter/src/main.tsx +8 -14
  40. package/templates/react-e2e-counter/sui-codegen.config.ts +13 -0
  41. package/templates/react-e2e-counter/vite.config.mts +2 -1
  42. package/templates/react-client-dapp/src/networkConfig.ts +0 -17
  43. package/templates/react-e2e-counter/src/networkConfig.ts +0 -31
@@ -1,23 +1,48 @@
1
- import { useCurrentAccount } from "@mysten/dapp-kit";
2
- import { Container, Flex, Heading, Text } from "@radix-ui/themes";
1
+ import { useCurrentAccount } from "@mysten/dapp-kit-react";
3
2
  import { OwnedObjects } from "./OwnedObjects";
3
+ import {
4
+ Card,
5
+ CardContent,
6
+ CardDescription,
7
+ CardHeader,
8
+ CardTitle,
9
+ } from "./components/ui/card";
10
+ import { Wallet, CheckCircle2 } from "lucide-react";
4
11
 
5
12
  export function WalletStatus() {
6
13
  const account = useCurrentAccount();
7
14
 
8
15
  return (
9
- <Container my="2">
10
- <Heading mb="2">Wallet Status</Heading>
16
+ <div className="space-y-6">
17
+ <Card>
18
+ <CardHeader>
19
+ <CardTitle className="flex items-center gap-2">
20
+ <Wallet className="h-5 w-5" />
21
+ Wallet Status
22
+ </CardTitle>
23
+ <CardDescription>
24
+ {account
25
+ ? "Your wallet is connected"
26
+ : "Connect your wallet to get started"}
27
+ </CardDescription>
28
+ </CardHeader>
29
+ <CardContent>
30
+ {account ? (
31
+ <div className="flex items-center gap-2">
32
+ <CheckCircle2 className="h-4 w-4 text-green-500" />
33
+ <span className="font-mono text-sm break-all">
34
+ {account.address}
35
+ </span>
36
+ </div>
37
+ ) : (
38
+ <p className="text-muted-foreground">
39
+ Click the connect button above to link your Sui wallet.
40
+ </p>
41
+ )}
42
+ </CardContent>
43
+ </Card>
11
44
 
12
- {account ? (
13
- <Flex direction="column">
14
- <Text>Wallet connected</Text>
15
- <Text>Address: {account.address}</Text>
16
- </Flex>
17
- ) : (
18
- <Text>Wallet not connected</Text>
19
- )}
20
45
  <OwnedObjects />
21
- </Container>
46
+ </div>
22
47
  );
23
48
  }
@@ -0,0 +1,75 @@
1
+ import type { HTMLAttributes } from "react";
2
+ import { cn } from "../../lib/utils";
3
+
4
+ function Card({
5
+ className,
6
+ ref,
7
+ ...props
8
+ }: HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) {
9
+ return (
10
+ <div
11
+ ref={ref}
12
+ className={cn(
13
+ "rounded-xl border bg-card text-card-foreground shadow",
14
+ className,
15
+ )}
16
+ {...props}
17
+ />
18
+ );
19
+ }
20
+
21
+ function CardHeader({
22
+ className,
23
+ ref,
24
+ ...props
25
+ }: HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) {
26
+ return (
27
+ <div
28
+ ref={ref}
29
+ className={cn("flex flex-col space-y-1.5 p-6", className)}
30
+ {...props}
31
+ />
32
+ );
33
+ }
34
+
35
+ function CardTitle({
36
+ className,
37
+ ref,
38
+ ...props
39
+ }: HTMLAttributes<HTMLHeadingElement> & {
40
+ ref?: React.Ref<HTMLHeadingElement>;
41
+ }) {
42
+ return (
43
+ <h3
44
+ ref={ref}
45
+ className={cn("font-semibold leading-none tracking-tight", className)}
46
+ {...props}
47
+ />
48
+ );
49
+ }
50
+
51
+ function CardDescription({
52
+ className,
53
+ ref,
54
+ ...props
55
+ }: HTMLAttributes<HTMLParagraphElement> & {
56
+ ref?: React.Ref<HTMLParagraphElement>;
57
+ }) {
58
+ return (
59
+ <p
60
+ ref={ref}
61
+ className={cn("text-sm text-muted-foreground", className)}
62
+ {...props}
63
+ />
64
+ );
65
+ }
66
+
67
+ function CardContent({
68
+ className,
69
+ ref,
70
+ ...props
71
+ }: HTMLAttributes<HTMLDivElement> & { ref?: React.Ref<HTMLDivElement> }) {
72
+ return <div ref={ref} className={cn("p-6 pt-0", className)} {...props} />;
73
+ }
74
+
75
+ export { Card, CardHeader, CardTitle, CardDescription, CardContent };
@@ -0,0 +1,24 @@
1
+ import { createDAppKit } from "@mysten/dapp-kit-react";
2
+ import { SuiGrpcClient } from "@mysten/sui/grpc";
3
+
4
+ const GRPC_URLS = {
5
+ mainnet: "https://fullnode.mainnet.sui.io:443",
6
+ testnet: "https://fullnode.testnet.sui.io:443",
7
+ devnet: "https://fullnode.devnet.sui.io:443",
8
+ };
9
+
10
+ export const dAppKit = createDAppKit({
11
+ enableBurnerWallet: import.meta.env.DEV,
12
+ networks: ["mainnet", "testnet", "devnet"],
13
+ defaultNetwork: "testnet",
14
+ createClient(network) {
15
+ return new SuiGrpcClient({ network, baseUrl: GRPC_URLS[network] });
16
+ },
17
+ });
18
+
19
+ // global type registration necessary for the hooks to work correctly
20
+ declare module "@mysten/dapp-kit-react" {
21
+ interface Register {
22
+ dAppKit: typeof dAppKit;
23
+ }
24
+ }
@@ -0,0 +1,39 @@
1
+ @import "tailwindcss";
2
+
3
+ @theme {
4
+ --color-background: oklch(0.145 0 0);
5
+ --color-foreground: oklch(0.985 0 0);
6
+ --color-card: oklch(0.145 0 0);
7
+ --color-card-foreground: oklch(0.985 0 0);
8
+ --color-primary: oklch(0.985 0 0);
9
+ --color-primary-foreground: oklch(0.205 0 0);
10
+ --color-secondary: oklch(0.269 0 0);
11
+ --color-secondary-foreground: oklch(0.985 0 0);
12
+ --color-muted: oklch(0.269 0 0);
13
+ --color-muted-foreground: oklch(0.708 0 0);
14
+ --color-accent: oklch(0.269 0 0);
15
+ --color-accent-foreground: oklch(0.985 0 0);
16
+ --color-destructive: oklch(0.396 0.141 25.723);
17
+ --color-destructive-foreground: oklch(0.637 0.237 25.331);
18
+ --color-border: oklch(0.269 0 0);
19
+ --color-input: oklch(0.269 0 0);
20
+ --color-ring: oklch(0.556 0 0);
21
+ --color-sui: oklch(0.7 0.2 220);
22
+
23
+ --radius-sm: 0.25rem;
24
+ --radius-md: 0.375rem;
25
+ --radius-lg: 0.5rem;
26
+ --radius-xl: 0.75rem;
27
+ }
28
+
29
+ * {
30
+ border-color: var(--color-border);
31
+ }
32
+
33
+ body {
34
+ background-color: var(--color-background);
35
+ color: var(--color-foreground);
36
+ font-family:
37
+ ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
38
+ "Segoe UI Symbol", "Noto Color Emoji";
39
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from "clsx";
2
+ import { twMerge } from "tailwind-merge";
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -1,26 +1,20 @@
1
1
  import React from "react";
2
2
  import ReactDOM from "react-dom/client";
3
- import "@mysten/dapp-kit/dist/index.css";
4
- import "@radix-ui/themes/styles.css";
3
+ import "./index.css";
5
4
 
6
- import { SuiClientProvider, WalletProvider } from "@mysten/dapp-kit";
5
+ import { DAppKitProvider } from "@mysten/dapp-kit-react";
7
6
  import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
8
- import { Theme } from "@radix-ui/themes";
9
7
  import App from "./App.tsx";
10
- import { networkConfig } from "./networkConfig.ts";
8
+ import { dAppKit } from "./dApp-kit.ts";
11
9
 
12
10
  const queryClient = new QueryClient();
13
11
 
14
12
  ReactDOM.createRoot(document.getElementById("root")!).render(
15
13
  <React.StrictMode>
16
- <Theme appearance="dark">
17
- <QueryClientProvider client={queryClient}>
18
- <SuiClientProvider networks={networkConfig} defaultNetwork="testnet">
19
- <WalletProvider autoConnect>
20
- <App />
21
- </WalletProvider>
22
- </SuiClientProvider>
23
- </QueryClientProvider>
24
- </Theme>
14
+ <QueryClientProvider client={queryClient}>
15
+ <DAppKitProvider dAppKit={dAppKit}>
16
+ <App />
17
+ </DAppKitProvider>
18
+ </QueryClientProvider>
25
19
  </React.StrictMode>,
26
20
  );
@@ -1,7 +1,8 @@
1
1
  import { defineConfig } from "vite";
2
2
  import react from "@vitejs/plugin-react-swc";
3
+ import tailwindcss from "@tailwindcss/vite";
3
4
 
4
5
  // https://vitejs.dev/config/
5
6
  export default defineConfig({
6
- plugins: [react()],
7
+ plugins: [react(), tailwindcss()],
7
8
  });
@@ -0,0 +1,2 @@
1
+ # Mark generated files
2
+ src/contracts/** linguist-generated=true
@@ -6,15 +6,32 @@ Client dApp using the following tools:
6
6
  - [React](https://react.dev/) as the UI framework
7
7
  - [TypeScript](https://www.typescriptlang.org/) for type checking
8
8
  - [Vite](https://vitejs.dev/) for build tooling
9
- - [Radix UI](https://www.radix-ui.com/) for pre-built UI components
10
- - [ESLint](https://eslint.org/) for linting
11
- - [`@mysten/dapp-kit`](https://sdk.mystenlabs.com/dapp-kit) for connecting to
12
- wallets and loading data
9
+ - [Tailwind CSS v4](https://tailwindcss.com/) for styling
10
+ - [Lucide React](https://lucide.dev/) for icons
11
+ - [`@mysten/dapp-kit-react`](https://sdk.mystenlabs.com/dapp-kit) for connecting
12
+ to wallets and loading data
13
+ - [`@mysten/codegen`](https://sdk.mystenlabs.com/codegen) for generating
14
+ TypeScript bindings from Move code
13
15
  - [pnpm](https://pnpm.io/) for package management
14
16
 
15
17
  For a full guide on how to build this dApp from scratch, visit this
16
18
  [guide](http://docs.sui.io/guides/developer/app-examples/e2e-counter#frontend).
17
19
 
20
+ ## Project Structure
21
+
22
+ ```
23
+ src/
24
+ ├── components/ui/ # Reusable UI components (Button, Card)
25
+ ├── contracts/ # Generated TypeScript bindings (via codegen)
26
+ ├── lib/utils.ts # Utility functions (cn for classnames)
27
+ ├── App.tsx # Main application component
28
+ ├── Counter.tsx # Counter display and controls
29
+ ├── CreateCounter.tsx # Counter creation component
30
+ ├── dApp-kit.ts # dApp Kit configuration
31
+ ├── constants.ts # Package IDs per network
32
+ └── index.css # Tailwind CSS with theme variables
33
+ ```
34
+
18
35
  ## Deploying your Move code
19
36
 
20
37
  ### Install Sui cli
@@ -60,14 +77,29 @@ sui client publish --gas-budget 100000000 counter
60
77
  ```
61
78
 
62
79
  In the output there will be an object with a `"packageId"` property. You'll want
63
- to save that package ID to the `src/constants.ts` file as `PACKAGE_ID`:
80
+ to save that package ID to the `src/constants.ts` file:
64
81
 
65
82
  ```ts
66
83
  export const TESTNET_COUNTER_PACKAGE_ID = "<YOUR_PACKAGE_ID>";
67
84
  ```
68
85
 
69
- Now that we have published the move code, and update the package ID, we can
70
- start the app.
86
+ The package ID is mapped to the local package name `@local-pkg/counter` in
87
+ `src/dApp-kit.ts` via MVR overrides. This allows the generated TypeScript
88
+ bindings to resolve the package address automatically.
89
+
90
+ ### Generating TypeScript bindings
91
+
92
+ After publishing your Move code, generate the TypeScript bindings:
93
+
94
+ ```bash
95
+ pnpm codegen
96
+ ```
97
+
98
+ This generates type-safe functions and BCS types in `src/contracts/` based on
99
+ your Move modules.
100
+
101
+ Now that we have published the move code, updated the package ID, and generated
102
+ the TypeScript bindings, we can start the app.
71
103
 
72
104
  ## Starting your dApp
73
105
 
@@ -90,3 +122,17 @@ To build your app for deployment you can run
90
122
  ```bash
91
123
  pnpm build
92
124
  ```
125
+
126
+ ## Customizing the UI
127
+
128
+ This template uses [Tailwind CSS v4](https://tailwindcss.com/docs) for styling
129
+ with [shadcn/ui](https://ui.shadcn.com/)-style components. The UI components in
130
+ `src/components/ui/` are based on shadcn/ui patterns and can be customized or
131
+ extended.
132
+
133
+ To add more shadcn/ui components, you can copy them from the
134
+ [shadcn/ui components](https://ui.shadcn.com/docs/components) documentation and
135
+ adapt them to work with your project.
136
+
137
+ Theme variables are defined in `src/index.css` using Tailwind's `@theme`
138
+ directive.
@@ -1,58 +1,12 @@
1
1
  <!doctype html>
2
- <html lang="en" class="dark-theme" style="color-scheme: dark">
2
+ <html lang="en">
3
3
  <head>
4
4
  <meta charset="UTF-8" />
5
5
  <link rel="icon" type="image/svg+xml" href="/vite.svg" />
6
6
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
7
7
  <title>Sui dApp Starter</title>
8
-
9
- <style>
10
- /*
11
- Josh's Custom CSS Reset
12
- https://www.joshwcomeau.com/css/custom-css-reset/
13
- */
14
- *,
15
- *::before,
16
- *::after {
17
- box-sizing: border-box;
18
- }
19
- * {
20
- margin: 0;
21
- }
22
- body {
23
- line-height: 1.5;
24
- -webkit-font-smoothing: antialiased;
25
- }
26
- img,
27
- picture,
28
- video,
29
- canvas,
30
- svg {
31
- display: block;
32
- max-width: 100%;
33
- }
34
- input,
35
- button,
36
- textarea,
37
- select {
38
- font: inherit;
39
- }
40
- p,
41
- h1,
42
- h2,
43
- h3,
44
- h4,
45
- h5,
46
- h6 {
47
- overflow-wrap: break-word;
48
- }
49
- #root,
50
- #__next {
51
- isolation: isolate;
52
- }
53
- </style>
54
8
  </head>
55
- <body>
9
+ <body class="min-h-screen antialiased">
56
10
  <div id="root"></div>
57
11
  <script type="module" src="/src/main.tsx"></script>
58
12
  </body>
@@ -1,36 +1,34 @@
1
1
  {
2
- "name": "@mysten/template-react-e2e-coinflip",
2
+ "name": "@mysten/template-react-e2e-counter",
3
3
  "private": true,
4
4
  "version": "0.0.0",
5
5
  "type": "module",
6
6
  "scripts": {
7
7
  "dev": "vite",
8
8
  "build": "tsc && vite build",
9
- "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
10
- "preview": "vite preview"
9
+ "preview": "vite preview",
10
+ "codegen": "rm -rf src/contracts && sui-ts-codegen generate"
11
11
  },
12
12
  "dependencies": {
13
- "@mysten/dapp-kit": "workspace:*",
14
- "@mysten/sui": "workspace:*",
15
- "@radix-ui/colors": "^3.0.0",
16
- "@radix-ui/react-icons": "^1.3.0",
17
- "@radix-ui/themes": "^3.2.1",
18
- "@tanstack/react-query": "^5.90.11",
19
- "react": "^19.2.1",
20
- "react-dom": "^19.2.1",
21
- "react-spinners": "^0.17.0"
13
+ "@mysten/dapp-kit-react": "workspace:^",
14
+ "@mysten/sui": "workspace:^",
15
+ "@nanostores/react": "^1.0.0",
16
+ "@tanstack/react-query": "^5.90.16",
17
+ "clsx": "^2.1.1",
18
+ "lucide-react": "^0.562.0",
19
+ "react": "^19.2.3",
20
+ "react-dom": "^19.2.3",
21
+ "tailwind-merge": "^3.4.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@types/react": "^19.2.7",
24
+ "@mysten/codegen": "workspace:^",
25
+ "@tailwindcss/vite": "^4.0.0",
26
+ "@types/react": "^19.2.8",
25
27
  "@types/react-dom": "^19.2.3",
26
- "@typescript-eslint/eslint-plugin": "^8.48.1",
27
- "@typescript-eslint/parser": "^8.48.1",
28
28
  "@vitejs/plugin-react-swc": "^4.2.2",
29
- "eslint": "^9.17.0",
30
- "eslint-plugin-react-hooks": "^5.2.0",
31
- "eslint-plugin-react-refresh": "^0.4.20",
32
- "prettier": "^3.7.3",
29
+ "prettier": "^3.7.4",
30
+ "tailwindcss": "^4.1.18",
33
31
  "typescript": "^5.9.3",
34
- "vite": "^7.2.6"
32
+ "vite": "^7.3.1"
35
33
  }
36
34
  }
@@ -1,4 +1,3 @@
1
- // eslint-disable-next-line no-undef
2
1
  module.exports = {
3
2
  proseWrap: "always",
4
3
  };
@@ -1,9 +1,10 @@
1
- import { ConnectButton, useCurrentAccount } from "@mysten/dapp-kit";
1
+ import { ConnectButton, useCurrentAccount } from "@mysten/dapp-kit-react";
2
2
  import { isValidSuiObjectId } from "@mysten/sui/utils";
3
- import { Box, Container, Flex, Heading } from "@radix-ui/themes";
4
3
  import { useState } from "react";
5
4
  import { Counter } from "./Counter";
6
5
  import { CreateCounter } from "./CreateCounter";
6
+ import { Card, CardContent, CardHeader, CardTitle } from "./components/ui/card";
7
+ import { Wallet } from "lucide-react";
7
8
 
8
9
  function App() {
9
10
  const currentAccount = useCurrentAccount();
@@ -13,31 +14,16 @@ function App() {
13
14
  });
14
15
 
15
16
  return (
16
- <>
17
- <Flex
18
- position="sticky"
19
- px="4"
20
- py="2"
21
- justify="between"
22
- style={{
23
- borderBottom: "1px solid var(--gray-a2)",
24
- }}
25
- >
26
- <Box>
27
- <Heading>dApp Starter Template</Heading>
28
- </Box>
29
-
30
- <Box>
17
+ <div className="min-h-screen">
18
+ <header className="sticky top-0 z-50 border-b bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60">
19
+ <div className="container mx-auto flex h-14 items-center justify-between px-4">
20
+ <h1 className="text-lg font-semibold">Sui Counter dApp</h1>
31
21
  <ConnectButton />
32
- </Box>
33
- </Flex>
34
- <Container>
35
- <Container
36
- mt="5"
37
- pt="2"
38
- px="4"
39
- style={{ background: "var(--gray-a2)", minHeight: 500 }}
40
- >
22
+ </div>
23
+ </header>
24
+
25
+ <main className="container mx-auto px-4 py-8">
26
+ <div className="mx-auto max-w-md">
41
27
  {currentAccount ? (
42
28
  counterId ? (
43
29
  <Counter id={counterId} />
@@ -50,11 +36,24 @@ function App() {
50
36
  />
51
37
  )
52
38
  ) : (
53
- <Heading>Please connect your wallet</Heading>
39
+ <Card>
40
+ <CardHeader>
41
+ <CardTitle className="flex items-center gap-2">
42
+ <Wallet className="h-5 w-5" />
43
+ Connect Wallet
44
+ </CardTitle>
45
+ </CardHeader>
46
+ <CardContent>
47
+ <p className="text-muted-foreground">
48
+ Connect your wallet to create and interact with counters on
49
+ the Sui blockchain.
50
+ </p>
51
+ </CardContent>
52
+ </Card>
54
53
  )}
55
- </Container>
56
- </Container>
57
- </>
54
+ </div>
55
+ </main>
56
+ </div>
58
57
  );
59
58
  }
60
59