@iota/create-dapp 0.0.0-experimental-20250611113847

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 (40) hide show
  1. package/CHANGELOG.md +142 -0
  2. package/LICENSE +201 -0
  3. package/README.md +35 -0
  4. package/bin/index.js +7 -0
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.js +103 -0
  7. package/dist/index.js.map +1 -0
  8. package/package.json +45 -0
  9. package/src/index.ts +131 -0
  10. package/templates/react-client-dapp/README.md +35 -0
  11. package/templates/react-client-dapp/eslint.config.js +28 -0
  12. package/templates/react-client-dapp/index.html +59 -0
  13. package/templates/react-client-dapp/package.json +37 -0
  14. package/templates/react-client-dapp/prettier.config.cjs +4 -0
  15. package/templates/react-client-dapp/src/App.tsx +39 -0
  16. package/templates/react-client-dapp/src/OwnedObjects.tsx +42 -0
  17. package/templates/react-client-dapp/src/WalletStatus.tsx +23 -0
  18. package/templates/react-client-dapp/src/main.tsx +26 -0
  19. package/templates/react-client-dapp/src/networkConfig.ts +17 -0
  20. package/templates/react-client-dapp/src/vite-env.d.ts +1 -0
  21. package/templates/react-client-dapp/tsconfig.json +25 -0
  22. package/templates/react-client-dapp/tsconfig.node.json +10 -0
  23. package/templates/react-client-dapp/vite.config.ts +7 -0
  24. package/templates/react-e2e-counter/README.md +100 -0
  25. package/templates/react-e2e-counter/eslint.config.js +28 -0
  26. package/templates/react-e2e-counter/index.html +59 -0
  27. package/templates/react-e2e-counter/move/counter/Move.toml +10 -0
  28. package/templates/react-e2e-counter/move/counter/sources/counter.move +37 -0
  29. package/templates/react-e2e-counter/package.json +37 -0
  30. package/templates/react-e2e-counter/prettier.config.cjs +4 -0
  31. package/templates/react-e2e-counter/src/App.tsx +61 -0
  32. package/templates/react-e2e-counter/src/Counter.tsx +96 -0
  33. package/templates/react-e2e-counter/src/CreateCounter.tsx +61 -0
  34. package/templates/react-e2e-counter/src/constants.ts +3 -0
  35. package/templates/react-e2e-counter/src/main.tsx +26 -0
  36. package/templates/react-e2e-counter/src/networkConfig.ts +31 -0
  37. package/templates/react-e2e-counter/src/vite-env.d.ts +1 -0
  38. package/templates/react-e2e-counter/tsconfig.json +25 -0
  39. package/templates/react-e2e-counter/tsconfig.node.json +10 -0
  40. package/templates/react-e2e-counter/vite.config.ts +7 -0
@@ -0,0 +1,61 @@
1
+ import { ConnectButton, useCurrentAccount } from "@iota/dapp-kit";
2
+ import { isValidIotaObjectId } from "@iota/iota-sdk/utils";
3
+ import { Box, Container, Flex, Heading } from "@radix-ui/themes";
4
+ import { useState } from "react";
5
+ import { Counter } from "./Counter";
6
+ import { CreateCounter } from "./CreateCounter";
7
+
8
+ function App() {
9
+ const currentAccount = useCurrentAccount();
10
+ const [counterId, setCounter] = useState(() => {
11
+ const hash = window.location.hash.slice(1);
12
+ return isValidIotaObjectId(hash) ? hash : null;
13
+ });
14
+
15
+ 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>
31
+ <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
+ >
41
+ {currentAccount ? (
42
+ counterId ? (
43
+ <Counter id={counterId} />
44
+ ) : (
45
+ <CreateCounter
46
+ onCreated={(id) => {
47
+ window.location.hash = id;
48
+ setCounter(id);
49
+ }}
50
+ />
51
+ )
52
+ ) : (
53
+ <Heading>Please connect your wallet</Heading>
54
+ )}
55
+ </Container>
56
+ </Container>
57
+ </>
58
+ );
59
+ }
60
+
61
+ export default App;
@@ -0,0 +1,96 @@
1
+ import {
2
+ useCurrentAccount,
3
+ useSignAndExecuteTransaction,
4
+ useIotaClient,
5
+ useIotaClientQuery,
6
+ } from "@iota/dapp-kit";
7
+ import type { IotaObjectData } from "@iota/iota-sdk/client";
8
+ import { Transaction } from "@iota/iota-sdk/transactions";
9
+ import { Button, Flex, Heading, Text } from "@radix-ui/themes";
10
+ import { useNetworkVariable } from "./networkConfig";
11
+
12
+ export function Counter({ id }: { id: string }) {
13
+ const counterPackageId = useNetworkVariable("counterPackageId");
14
+ const iotaClient = useIotaClient();
15
+ const currentAccount = useCurrentAccount();
16
+ const { mutate: signAndExecute } = useSignAndExecuteTransaction({
17
+ execute: async ({ bytes, signature }) =>
18
+ await iotaClient.executeTransactionBlock({
19
+ transactionBlock: bytes,
20
+ signature,
21
+ options: {
22
+ // Raw effects are required so the effects can be reported back to the wallet
23
+ showRawEffects: true,
24
+ showEffects: true,
25
+ },
26
+ }),
27
+ });
28
+ const { data, isPending, error, refetch } = useIotaClientQuery("getObject", {
29
+ id,
30
+ options: {
31
+ showContent: true,
32
+ showOwner: true,
33
+ },
34
+ });
35
+
36
+ const executeMoveCall = (method: "increment" | "reset") => {
37
+ const tx = new Transaction();
38
+
39
+ if (method === "reset") {
40
+ tx.moveCall({
41
+ arguments: [tx.object(id), tx.pure.u64(0)],
42
+ target: `${counterPackageId}::counter::set_value`,
43
+ });
44
+ } else {
45
+ tx.moveCall({
46
+ arguments: [tx.object(id)],
47
+ target: `${counterPackageId}::counter::increment`,
48
+ });
49
+ }
50
+
51
+ signAndExecute(
52
+ {
53
+ transaction: tx,
54
+ },
55
+ {
56
+ onSuccess: async () => {
57
+ await refetch();
58
+ },
59
+ },
60
+ );
61
+ };
62
+
63
+ if (isPending) return <Text>Loading...</Text>;
64
+
65
+ if (error) return <Text>Error: {error.message}</Text>;
66
+
67
+ if (!data.data) return <Text>Not found</Text>;
68
+
69
+ const ownedByCurrentAccount =
70
+ getCounterFields(data.data)?.owner === currentAccount?.address;
71
+
72
+ return (
73
+ <>
74
+ <Heading size="3">Counter {id}</Heading>
75
+
76
+ <Flex direction="column" gap="2">
77
+ <Text>Count: {getCounterFields(data.data)?.value}</Text>
78
+ <Flex direction="row" gap="2">
79
+ <Button onClick={() => executeMoveCall("increment")}>
80
+ Increment
81
+ </Button>
82
+ {ownedByCurrentAccount ? (
83
+ <Button onClick={() => executeMoveCall("reset")}>Reset</Button>
84
+ ) : null}
85
+ </Flex>
86
+ </Flex>
87
+ </>
88
+ );
89
+ }
90
+ function getCounterFields(data: IotaObjectData) {
91
+ if (data.content?.dataType !== "moveObject") {
92
+ return null;
93
+ }
94
+
95
+ return data.content.fields as { value: number; owner: string };
96
+ }
@@ -0,0 +1,61 @@
1
+ import { Transaction } from "@iota/iota-sdk/transactions";
2
+ import { Button, Container } from "@radix-ui/themes";
3
+ import { useSignAndExecuteTransaction, useIotaClient } from "@iota/dapp-kit";
4
+ import { useNetworkVariable } from "./networkConfig";
5
+
6
+ export function CreateCounter({
7
+ onCreated,
8
+ }: {
9
+ onCreated: (id: string) => void;
10
+ }) {
11
+ const counterPackageId = useNetworkVariable("counterPackageId");
12
+ const iotaClient = useIotaClient();
13
+ const { mutate: signAndExecute } = useSignAndExecuteTransaction({
14
+ execute: async ({ bytes, signature }) =>
15
+ await iotaClient.executeTransactionBlock({
16
+ transactionBlock: bytes,
17
+ signature,
18
+ options: {
19
+ // Raw effects are required so the effects can be reported back to the wallet
20
+ showRawEffects: true,
21
+ showEffects: true,
22
+ },
23
+ }),
24
+ });
25
+
26
+ return (
27
+ <Container>
28
+ <Button
29
+ size="3"
30
+ onClick={() => {
31
+ create();
32
+ }}
33
+ >
34
+ Create Counter
35
+ </Button>
36
+ </Container>
37
+ );
38
+
39
+ function create() {
40
+ const tx = new Transaction();
41
+
42
+ tx.moveCall({
43
+ arguments: [],
44
+ target: `${counterPackageId}::counter::create`,
45
+ });
46
+
47
+ signAndExecute(
48
+ {
49
+ transaction: tx,
50
+ },
51
+ {
52
+ onSuccess: (result) => {
53
+ const objectId = result.effects?.created?.[0]?.reference?.objectId;
54
+ if (objectId) {
55
+ onCreated(objectId);
56
+ }
57
+ },
58
+ },
59
+ );
60
+ }
61
+ }
@@ -0,0 +1,3 @@
1
+ export const DEVNET_COUNTER_PACKAGE_ID = "0xTODO";
2
+ export const TESTNET_COUNTER_PACKAGE_ID = "0xTODO";
3
+ export const MAINNET_COUNTER_PACKAGE_ID = "0xTODO";
@@ -0,0 +1,26 @@
1
+ import React from "react";
2
+ import ReactDOM from "react-dom/client";
3
+ import "@iota/dapp-kit/dist/index.css";
4
+ import "@radix-ui/themes/styles.css";
5
+
6
+ import { IotaClientProvider, WalletProvider } from "@iota/dapp-kit";
7
+ import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
8
+ import { Theme } from "@radix-ui/themes";
9
+ import App from "./App.tsx";
10
+ import { networkConfig } from "./networkConfig.ts";
11
+
12
+ const queryClient = new QueryClient();
13
+
14
+ ReactDOM.createRoot(document.getElementById("root")!).render(
15
+ <React.StrictMode>
16
+ <Theme appearance="dark">
17
+ <QueryClientProvider client={queryClient}>
18
+ <IotaClientProvider networks={networkConfig} defaultNetwork="testnet">
19
+ <WalletProvider autoConnect>
20
+ <App />
21
+ </WalletProvider>
22
+ </IotaClientProvider>
23
+ </QueryClientProvider>
24
+ </Theme>
25
+ </React.StrictMode>,
26
+ );
@@ -0,0 +1,31 @@
1
+ import { getFullnodeUrl } from "@iota/iota-sdk/client";
2
+ import {
3
+ DEVNET_COUNTER_PACKAGE_ID,
4
+ TESTNET_COUNTER_PACKAGE_ID,
5
+ MAINNET_COUNTER_PACKAGE_ID,
6
+ } from "./constants.ts";
7
+ import { createNetworkConfig } from "@iota/dapp-kit";
8
+
9
+ const { networkConfig, useNetworkVariable, useNetworkVariables } =
10
+ createNetworkConfig({
11
+ devnet: {
12
+ url: getFullnodeUrl("devnet"),
13
+ variables: {
14
+ counterPackageId: DEVNET_COUNTER_PACKAGE_ID,
15
+ },
16
+ },
17
+ testnet: {
18
+ url: getFullnodeUrl("testnet"),
19
+ variables: {
20
+ counterPackageId: TESTNET_COUNTER_PACKAGE_ID,
21
+ },
22
+ },
23
+ mainnet: {
24
+ url: getFullnodeUrl("mainnet"),
25
+ variables: {
26
+ counterPackageId: MAINNET_COUNTER_PACKAGE_ID,
27
+ },
28
+ },
29
+ });
30
+
31
+ export { useNetworkVariable, useNetworkVariables, networkConfig };
@@ -0,0 +1 @@
1
+ /// <reference types="vite/client" />
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+
9
+ /* Bundler mode */
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "resolveJsonModule": true,
13
+ "isolatedModules": true,
14
+ "noEmit": true,
15
+ "jsx": "react-jsx",
16
+
17
+ /* Linting */
18
+ "strict": true,
19
+ "noUnusedLocals": true,
20
+ "noUnusedParameters": true,
21
+ "noFallthroughCasesInSwitch": true
22
+ },
23
+ "include": ["src"],
24
+ "references": [{ "path": "./tsconfig.node.json" }]
25
+ }
@@ -0,0 +1,10 @@
1
+ {
2
+ "compilerOptions": {
3
+ "composite": true,
4
+ "skipLibCheck": true,
5
+ "module": "ESNext",
6
+ "moduleResolution": "bundler",
7
+ "allowSyntheticDefaultImports": true
8
+ },
9
+ "include": ["vite.config.ts"]
10
+ }
@@ -0,0 +1,7 @@
1
+ import { defineConfig } from "vite";
2
+ import react from "@vitejs/plugin-react-swc";
3
+
4
+ // https://vitejs.dev/config/
5
+ export default defineConfig({
6
+ plugins: [react()],
7
+ });