@haneullabs/create-dapp 0.1.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.
- package/CHANGELOG.md +1159 -0
- package/README.md +33 -0
- package/bin/index.js +4 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +102 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
- package/src/index.ts +130 -0
- package/templates/react-client-dapp/README.md +35 -0
- package/templates/react-client-dapp/index.html +59 -0
- package/templates/react-client-dapp/package.json +35 -0
- package/templates/react-client-dapp/prettier.config.cjs +4 -0
- package/templates/react-client-dapp/src/App.tsx +39 -0
- package/templates/react-client-dapp/src/OwnedObjects.tsx +42 -0
- package/templates/react-client-dapp/src/WalletStatus.tsx +23 -0
- package/templates/react-client-dapp/src/main.tsx +26 -0
- package/templates/react-client-dapp/src/networkConfig.ts +17 -0
- package/templates/react-client-dapp/src/vite-env.d.ts +1 -0
- package/templates/react-client-dapp/tsconfig.json +25 -0
- package/templates/react-client-dapp/tsconfig.node.json +10 -0
- package/templates/react-client-dapp/vite.config.mts +7 -0
- package/templates/react-e2e-counter/README.md +92 -0
- package/templates/react-e2e-counter/index.html +59 -0
- package/templates/react-e2e-counter/move/counter/Move.toml +10 -0
- package/templates/react-e2e-counter/move/counter/sources/counter.move +36 -0
- package/templates/react-e2e-counter/package.json +36 -0
- package/templates/react-e2e-counter/prettier.config.cjs +4 -0
- package/templates/react-e2e-counter/src/App.tsx +61 -0
- package/templates/react-e2e-counter/src/Counter.tsx +106 -0
- package/templates/react-e2e-counter/src/CreateCounter.tsx +60 -0
- package/templates/react-e2e-counter/src/constants.ts +3 -0
- package/templates/react-e2e-counter/src/main.tsx +26 -0
- package/templates/react-e2e-counter/src/networkConfig.ts +31 -0
- package/templates/react-e2e-counter/src/vite-env.d.ts +1 -0
- package/templates/react-e2e-counter/tsconfig.json +25 -0
- package/templates/react-e2e-counter/tsconfig.node.json +10 -0
- package/templates/react-e2e-counter/vite.config.mts +7 -0
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Sui dApp Starter Template
|
|
2
|
+
|
|
3
|
+
This dApp was created using `@haneullabs/create-dapp` that sets up a basic React
|
|
4
|
+
Client dApp using the following tools:
|
|
5
|
+
|
|
6
|
+
- [React](https://react.dev/) as the UI framework
|
|
7
|
+
- [TypeScript](https://www.typescriptlang.org/) for type checking
|
|
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
|
+
- [`@haneullabs/dapp-kit`](https://sdk.haneullabs.com/dapp-kit) for connecting to
|
|
12
|
+
wallets and loading data
|
|
13
|
+
- [pnpm](https://pnpm.io/) for package management
|
|
14
|
+
|
|
15
|
+
For a full guide on how to build this dApp from scratch, visit this
|
|
16
|
+
[guide](http://docs.sui.io/guides/developer/app-examples/e2e-counter#frontend).
|
|
17
|
+
|
|
18
|
+
## Deploying your Move code
|
|
19
|
+
|
|
20
|
+
### Install Sui cli
|
|
21
|
+
|
|
22
|
+
Before deploying your move code, ensure that you have installed the Haneul CLI. You
|
|
23
|
+
can follow the [Sui installation instruction](https://docs.sui.io/build/install)
|
|
24
|
+
to get everything set up.
|
|
25
|
+
|
|
26
|
+
This template uses `testnet` by default, so we'll need to set up a testnet
|
|
27
|
+
environment in the CLI:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
sui client new-env --alias testnet --rpc https://fullnode.testnet.sui.io:443
|
|
31
|
+
sui client switch --env testnet
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
If you haven't set up an address in the sui client yet, you can use the
|
|
35
|
+
following command to get a new address:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
sui client new-address secp256k1
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This well generate a new address and recover phrase for you. You can mark a
|
|
42
|
+
newly created address as you active address by running the following command
|
|
43
|
+
with your new address:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
sui client switch --address 0xYOUR_ADDRESS...
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
We can ensure we have some Sui in our new wallet by requesting Sui from the
|
|
50
|
+
faucet `https://faucet.sui.io`.
|
|
51
|
+
|
|
52
|
+
### Publishing the move package
|
|
53
|
+
|
|
54
|
+
The move code for this template is located in the `move` directory. To publish
|
|
55
|
+
it, you can enter the `move` directory, and publish it with the Haneul CLI:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
cd move
|
|
59
|
+
sui client publish --gas-budget 100000000 counter
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
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`:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
export const TESTNET_COUNTER_PACKAGE_ID = "<YOUR_PACKAGE_ID>";
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Now that we have published the move code, and update the package ID, we can
|
|
70
|
+
start the app.
|
|
71
|
+
|
|
72
|
+
## Starting your dApp
|
|
73
|
+
|
|
74
|
+
To install dependencies you can run
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pnpm install
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
To start your dApp in development mode run
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pnpm dev
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Building
|
|
87
|
+
|
|
88
|
+
To build your app for deployment you can run
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
pnpm build
|
|
92
|
+
```
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en" class="dark-theme" style="color-scheme: dark">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
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
|
+
</head>
|
|
55
|
+
<body>
|
|
56
|
+
<div id="root"></div>
|
|
57
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
58
|
+
</body>
|
|
59
|
+
</html>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
[package]
|
|
2
|
+
name = "counter"
|
|
3
|
+
version = "0.0.1"
|
|
4
|
+
edition = "2024.beta"
|
|
5
|
+
|
|
6
|
+
[dependencies]
|
|
7
|
+
Haneul = { git = "https://github.com/GeunhwaJeong/haneul.git", subdir = "crates/haneul-framework/packages/haneul-framework", rev = "framework/testnet" }
|
|
8
|
+
|
|
9
|
+
[addresses]
|
|
10
|
+
counter = "0x0"
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Copyright (c) Mysten Labs, Inc.
|
|
2
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
|
|
4
|
+
/// This example demonstrates a basic use of a shared object.
|
|
5
|
+
/// Rules:
|
|
6
|
+
/// - anyone can create and share a counter
|
|
7
|
+
/// - everyone can increment a counter by 1
|
|
8
|
+
/// - the owner of the counter can reset it to any value
|
|
9
|
+
module counter::counter {
|
|
10
|
+
/// A shared counter.
|
|
11
|
+
public struct Counter has key {
|
|
12
|
+
id: UID,
|
|
13
|
+
owner: address,
|
|
14
|
+
value: u64
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/// Create and share a Counter object.
|
|
18
|
+
public fun create(ctx: &mut TxContext) {
|
|
19
|
+
transfer::share_object(Counter {
|
|
20
|
+
id: object::new(ctx),
|
|
21
|
+
owner: ctx.sender(),
|
|
22
|
+
value: 0
|
|
23
|
+
})
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/// Increment a counter by 1.
|
|
27
|
+
public fun increment(counter: &mut Counter) {
|
|
28
|
+
counter.value = counter.value + 1;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/// Set value (only runnable by the Counter owner)
|
|
32
|
+
public fun set_value(counter: &mut Counter, value: u64, ctx: &TxContext) {
|
|
33
|
+
assert!(counter.owner == ctx.sender(), 0);
|
|
34
|
+
counter.value = value;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@haneullabs/template-react-e2e-coinflip",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "0.0.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "vite",
|
|
8
|
+
"build": "tsc && vite build",
|
|
9
|
+
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
|
|
10
|
+
"preview": "vite preview"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@haneullabs/dapp-kit": "workspace:*",
|
|
14
|
+
"@haneullabs/haneul": "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"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"@types/react": "^19.2.7",
|
|
25
|
+
"@types/react-dom": "^19.2.3",
|
|
26
|
+
"@typescript-eslint/eslint-plugin": "^8.48.1",
|
|
27
|
+
"@typescript-eslint/parser": "^8.48.1",
|
|
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",
|
|
33
|
+
"typescript": "^5.9.3",
|
|
34
|
+
"vite": "^7.2.6"
|
|
35
|
+
}
|
|
36
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { ConnectButton, useCurrentAccount } from "@haneullabs/dapp-kit";
|
|
2
|
+
import { isValidHaneulObjectId } from "@haneullabs/haneul/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 isValidHaneulObjectId(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,106 @@
|
|
|
1
|
+
import {
|
|
2
|
+
useCurrentAccount,
|
|
3
|
+
useSignAndExecuteTransaction,
|
|
4
|
+
useHaneulClient,
|
|
5
|
+
useHaneulClientQuery,
|
|
6
|
+
} from "@haneullabs/dapp-kit";
|
|
7
|
+
import type { HaneulObjectData } from "@haneullabs/haneul/client";
|
|
8
|
+
import { Transaction } from "@haneullabs/haneul/transactions";
|
|
9
|
+
import { Button, Flex, Heading, Text } from "@radix-ui/themes";
|
|
10
|
+
import { useNetworkVariable } from "./networkConfig";
|
|
11
|
+
import { useState } from "react";
|
|
12
|
+
import ClipLoader from "react-spinners/ClipLoader";
|
|
13
|
+
|
|
14
|
+
export function Counter({ id }: { id: string }) {
|
|
15
|
+
const counterPackageId = useNetworkVariable("counterPackageId");
|
|
16
|
+
const haneulClient = useHaneulClient();
|
|
17
|
+
const currentAccount = useCurrentAccount();
|
|
18
|
+
const { mutate: signAndExecute } = useSignAndExecuteTransaction();
|
|
19
|
+
const { data, isPending, error, refetch } = useHaneulClientQuery("getObject", {
|
|
20
|
+
id,
|
|
21
|
+
options: {
|
|
22
|
+
showContent: true,
|
|
23
|
+
showOwner: true,
|
|
24
|
+
},
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
const [waitingForTxn, setWaitingForTxn] = useState("");
|
|
28
|
+
|
|
29
|
+
const executeMoveCall = (method: "increment" | "reset") => {
|
|
30
|
+
setWaitingForTxn(method);
|
|
31
|
+
|
|
32
|
+
const tx = new Transaction();
|
|
33
|
+
|
|
34
|
+
if (method === "reset") {
|
|
35
|
+
tx.moveCall({
|
|
36
|
+
arguments: [tx.object(id), tx.pure.u64(0)],
|
|
37
|
+
target: `${counterPackageId}::counter::set_value`,
|
|
38
|
+
});
|
|
39
|
+
} else {
|
|
40
|
+
tx.moveCall({
|
|
41
|
+
arguments: [tx.object(id)],
|
|
42
|
+
target: `${counterPackageId}::counter::increment`,
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
signAndExecute(
|
|
47
|
+
{
|
|
48
|
+
transaction: tx,
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
onSuccess: (tx) => {
|
|
52
|
+
haneulClient.waitForTransaction({ digest: tx.digest }).then(async () => {
|
|
53
|
+
await refetch();
|
|
54
|
+
setWaitingForTxn("");
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
},
|
|
58
|
+
);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
if (isPending) return <Text>Loading...</Text>;
|
|
62
|
+
|
|
63
|
+
if (error) return <Text>Error: {error.message}</Text>;
|
|
64
|
+
|
|
65
|
+
if (!data.data) return <Text>Not found</Text>;
|
|
66
|
+
|
|
67
|
+
const ownedByCurrentAccount =
|
|
68
|
+
getCounterFields(data.data)?.owner === currentAccount?.address;
|
|
69
|
+
|
|
70
|
+
return (
|
|
71
|
+
<>
|
|
72
|
+
<Heading size="3">Counter {id}</Heading>
|
|
73
|
+
|
|
74
|
+
<Flex direction="column" gap="2">
|
|
75
|
+
<Text>Count: {getCounterFields(data.data)?.value}</Text>
|
|
76
|
+
<Flex direction="row" gap="2">
|
|
77
|
+
<Button
|
|
78
|
+
onClick={() => executeMoveCall("increment")}
|
|
79
|
+
disabled={waitingForTxn !== ""}
|
|
80
|
+
>
|
|
81
|
+
{waitingForTxn === "increment" ? (
|
|
82
|
+
<ClipLoader size={20} />
|
|
83
|
+
) : (
|
|
84
|
+
"Increment"
|
|
85
|
+
)}
|
|
86
|
+
</Button>
|
|
87
|
+
{ownedByCurrentAccount ? (
|
|
88
|
+
<Button
|
|
89
|
+
onClick={() => executeMoveCall("reset")}
|
|
90
|
+
disabled={waitingForTxn !== ""}
|
|
91
|
+
>
|
|
92
|
+
{waitingForTxn === "reset" ? <ClipLoader size={20} /> : "Reset"}
|
|
93
|
+
</Button>
|
|
94
|
+
) : null}
|
|
95
|
+
</Flex>
|
|
96
|
+
</Flex>
|
|
97
|
+
</>
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
function getCounterFields(data: HaneulObjectData) {
|
|
101
|
+
if (data.content?.dataType !== "moveObject") {
|
|
102
|
+
return null;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return data.content.fields as { value: number; owner: string };
|
|
106
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { Transaction } from "@haneullabs/haneul/transactions";
|
|
2
|
+
import { Button, Container } from "@radix-ui/themes";
|
|
3
|
+
import { useSignAndExecuteTransaction, useHaneulClient } from "@haneullabs/dapp-kit";
|
|
4
|
+
import { useNetworkVariable } from "./networkConfig";
|
|
5
|
+
import ClipLoader from "react-spinners/ClipLoader";
|
|
6
|
+
|
|
7
|
+
export function CreateCounter({
|
|
8
|
+
onCreated,
|
|
9
|
+
}: {
|
|
10
|
+
onCreated: (id: string) => void;
|
|
11
|
+
}) {
|
|
12
|
+
const counterPackageId = useNetworkVariable("counterPackageId");
|
|
13
|
+
const haneulClient = useHaneulClient();
|
|
14
|
+
const {
|
|
15
|
+
mutate: signAndExecute,
|
|
16
|
+
isSuccess,
|
|
17
|
+
isPending,
|
|
18
|
+
} = useSignAndExecuteTransaction();
|
|
19
|
+
|
|
20
|
+
function create() {
|
|
21
|
+
const tx = new Transaction();
|
|
22
|
+
|
|
23
|
+
tx.moveCall({
|
|
24
|
+
arguments: [],
|
|
25
|
+
target: `${counterPackageId}::counter::create`,
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
signAndExecute(
|
|
29
|
+
{
|
|
30
|
+
transaction: tx,
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
onSuccess: async ({ digest }) => {
|
|
34
|
+
const { effects } = await haneulClient.waitForTransaction({
|
|
35
|
+
digest: digest,
|
|
36
|
+
options: {
|
|
37
|
+
showEffects: true,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
onCreated(effects?.created?.[0]?.reference?.objectId!);
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Container>
|
|
49
|
+
<Button
|
|
50
|
+
size="3"
|
|
51
|
+
onClick={() => {
|
|
52
|
+
create();
|
|
53
|
+
}}
|
|
54
|
+
disabled={isSuccess || isPending}
|
|
55
|
+
>
|
|
56
|
+
{isSuccess || isPending ? <ClipLoader size={20} /> : "Create Counter"}
|
|
57
|
+
</Button>
|
|
58
|
+
</Container>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import ReactDOM from "react-dom/client";
|
|
3
|
+
import "@haneullabs/dapp-kit/dist/index.css";
|
|
4
|
+
import "@radix-ui/themes/styles.css";
|
|
5
|
+
|
|
6
|
+
import { HaneulClientProvider, WalletProvider } from "@haneullabs/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
|
+
<HaneulClientProvider networks={networkConfig} defaultNetwork="testnet">
|
|
19
|
+
<WalletProvider autoConnect>
|
|
20
|
+
<App />
|
|
21
|
+
</WalletProvider>
|
|
22
|
+
</HaneulClientProvider>
|
|
23
|
+
</QueryClientProvider>
|
|
24
|
+
</Theme>
|
|
25
|
+
</React.StrictMode>,
|
|
26
|
+
);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { getFullnodeUrl } from "@haneullabs/haneul/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 "@haneullabs/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
|
+
}
|