Skip to content

Commit dd6637b

Browse files
authored
Merge pull request #18 from chasefleming/cf/use-kit
Convert to `@onflow/kit`
2 parents 223558f + 52422ad commit dd6637b

File tree

15 files changed

+379
-363
lines changed

15 files changed

+379
-363
lines changed

README.md

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,59 @@
1-
This is a scaffold for an FCL NextJS Dapp on the Flow Blockchain.
1+
This is a scaffold for an a NextJS App on the Flow Blockchain. It uses `@onflow/kit` which is a React library built on top of [FCL](https://github.com/onflow/fcl-js)
22

33
## Features Provided
44

5-
- FCL setup and configuration
5+
- `@onflow/kit` setup and configuration
66
- Wallet Discovery (including Dev Wallet on Emulator)
77
- CLI private key separation for security
88
- Flow.json loading for contract placeholders
99
- Authentication
1010
- CDC file loader
1111
- Custom hooks
12-
- Deployment
1312

14-
## Featues TODO
13+
## Requirements
1514

16-
- Mainnet deployment
17-
- JS Testing
15+
- Node.js
16+
- [Flow CLI](https://docs.onflow.org/flow-cli/install/)
1817

1918
## Running the App
2019

21-
First run:
20+
First run the Emulator:
2221

2322
```
24-
npm install
23+
flow emulator
2524
```
2625

27-
### Local with the Emulator and Dev Wallet
26+
Then run dev wallet for local wallet usage:
2827

29-
Run the following to run the Emulator and Dev Wallet:
30-
31-
```bash
32-
npm run dev:local
28+
```
29+
flow dev-wallet
3330
```
3431

35-
### Testnet
36-
37-
If you haven't yet created a testnet account, in the CLI run:
32+
Then run the app:
3833

3934
```
40-
flow accounts create
35+
npm run dev:local
4136
```
42-
43-
Follow the steps and select testnet. This will create a `[name].pkey` file (make sure this is gitignored) and add your account to flow.json.
44-
45-
Then in `flow.json`, add the contracts you'd like to be deployed to testnet under this account:
46-
4737
```
48-
// Inside of "deployments"
49-
"testnet": {
50-
"testnet-account": [
51-
"HelloWorld"
52-
]
53-
}
38+
npm run dev:emulator
5439
```
5540

56-
Then run:
41+
### Running Tesnet
42+
43+
Run the following the Emulator:
5744

45+
```bash
46+
npm run dev:local
5847
```
59-
npm run dev:testnet:deploy
60-
```
6148

62-
Whenever you need to redeploy changed contracts to Testnet while seeing the diff between deployed contracts and updates being pushed, you can run:
49+
### Testnet
50+
51+
To run against an already deployed contract on Testnet with a non-dev wallet, you can use the following command:
6352

6453
```
65-
npm run dev:testnet:update
54+
npm run dev:testnet
6655
```
56+
57+
## Learning More
58+
59+
To learn more about Flow, Flow CLI, and front end development on Flow, check out the [Getting Started](https://developers.flow.com/build/getting-started/contract-interaction) guide.

components/Container.tsx

Lines changed: 91 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,126 @@
1-
import * as fcl from '@onflow/fcl'
2-
import { useEffect, useState } from 'react'
3-
import ReadHelloWorld from '../cadence/scripts/ReadHelloWorld.cdc'
4-
import UpdateHelloWorld from '../cadence/transactions/UpdateHelloWorld.cdc'
5-
import elementStyles from '../styles/Elements.module.css'
6-
import containerStyles from '../styles/Container.module.css'
7-
import useConfig from '../hooks/useConfig'
8-
import { createExplorerTransactionLink } from '../helpers/links'
1+
import { useState, useEffect } from "react";
2+
import {
3+
useFlowQuery,
4+
useFlowMutate,
5+
useFlowTransaction,
6+
useFlowConfig,
7+
} from "@onflow/kit";
8+
import ReadHelloWorld from "../cadence/scripts/ReadHelloWorld.cdc";
9+
import UpdateHelloWorld from "../cadence/transactions/UpdateHelloWorld.cdc";
10+
import elementStyles from "../styles/Elements.module.css";
11+
import containerStyles from "../styles/Container.module.css";
12+
import { createExplorerTransactionLink } from "../helpers/links";
913

1014
export default function Container() {
11-
const [chainGreeting, setChainGreeting] = useState('?')
12-
const [userGreetingInput, setUserGreetingInput] = useState('')
13-
const [lastTransactionId, setLastTransactionId] = useState<string>()
14-
const [transactionStatus, setTransactionStatus] = useState<number>()
15-
const { network } = useConfig()
15+
const [userGreetingInput, setUserGreetingInput] = useState("");
16+
const [lastTransactionId, setLastTransactionId] = useState<string>();
17+
const { flowNetwork } = useFlowConfig();
1618

17-
const isEmulator = network => network !== 'mainnet' && network !== 'testnet'
18-
const isSealed = statusCode => statusCode === 4 // 4: 'SEALED'
19+
const isEmulator = (network: string) =>
20+
network !== "mainnet" && network !== "testnet";
1921

20-
useEffect(() => {
21-
if (lastTransactionId) {
22-
console.log('Last Transaction ID: ', lastTransactionId)
22+
const {
23+
data: chainGreeting,
24+
refetch: refetchGreeting,
25+
isLoading: isQueryLoading,
26+
} = useFlowQuery({
27+
cadence: ReadHelloWorld,
28+
enabled: true,
29+
});
2330

24-
fcl.tx(lastTransactionId).subscribe(res => {
25-
setTransactionStatus(res.statusString)
26-
27-
// Query for new chain string again if status is sealed
28-
if (isSealed(res.status)) {
29-
queryChain()
30-
}
31-
})
32-
}
33-
}, [lastTransactionId])
31+
const {
32+
mutate,
33+
isPending: isMutating,
34+
data: transactionId,
35+
error: mutationError,
36+
} = useFlowMutate();
3437

35-
const queryChain = async () => {
36-
const res = await fcl.query({
37-
cadence: ReadHelloWorld
38-
})
38+
const { transactionStatus } = useFlowTransaction(transactionId || "");
3939

40-
setChainGreeting(res)
41-
}
40+
useEffect(() => {
41+
if (transactionId && transactionStatus?.status === 4) {
42+
refetchGreeting();
43+
}
44+
}, [transactionStatus?.status, transactionId, refetchGreeting]);
4245

43-
const mutateGreeting = async (event) => {
44-
event.preventDefault()
46+
const mutateGreeting = (event: React.FormEvent) => {
47+
event.preventDefault();
4548

4649
if (!userGreetingInput.length) {
47-
throw new Error('Please add a new greeting string.')
50+
alert("Please add a new greeting string.");
51+
return;
4852
}
4953

50-
const transactionId = await fcl.mutate({
54+
mutate({
5155
cadence: UpdateHelloWorld,
5256
args: (arg, t) => [arg(userGreetingInput, t.String)],
53-
})
57+
});
58+
setLastTransactionId(transactionId);
59+
};
5460

55-
setLastTransactionId(transactionId)
56-
}
57-
58-
const openExplorerLink = (transactionId, network) => window.open(createExplorerTransactionLink({ network, transactionId }), '_blank')
61+
const openExplorerLink = () => {
62+
if (lastTransactionId) {
63+
window.open(
64+
createExplorerTransactionLink({
65+
flowNetwork,
66+
transactionId: lastTransactionId,
67+
}),
68+
"_blank",
69+
);
70+
}
71+
};
5972

6073
return (
6174
<div className={containerStyles.container}>
6275
<h2>Query the Chain</h2>
6376
<div>
64-
<button onClick={queryChain} className={elementStyles.button}>Query Greeting</button>
65-
<h4>Greeting on Chain: { chainGreeting }</h4>
77+
<button
78+
onClick={() => refetchGreeting()}
79+
className={elementStyles.button}
80+
>
81+
Query Greeting
82+
</button>
83+
<h4>
84+
Greeting on Chain:{" "}
85+
{isQueryLoading ? "Loading..." : String(chainGreeting ?? "?")}
86+
</h4>
6687
</div>
6788
<hr />
6889
<div>
6990
<h2>Mutate the Chain</h2>
70-
{!isEmulator(network) && (
71-
<h4>Latest Transaction ID: <a className={elementStyles.link} onClick={() => {openExplorerLink(lastTransactionId, network)}}>{ lastTransactionId }</a></h4>
91+
{!isEmulator(flowNetwork) && lastTransactionId && (
92+
<h4>
93+
Latest Transaction ID:{" "}
94+
<a className={elementStyles.link} onClick={openExplorerLink}>
95+
{lastTransactionId}
96+
</a>
97+
</h4>
7298
)}
73-
<h4>Latest Transaction Status: { transactionStatus }</h4>
99+
<h4>
100+
Latest Transaction Status:{" "}
101+
{transactionStatus?.statusString || "No transaction yet"}
102+
</h4>
74103
<form onSubmit={mutateGreeting}>
75104
<label>
76105
<input
77-
type='text'
78-
placeholder='New Greeting'
106+
type="text"
107+
placeholder="New Greeting"
79108
value={userGreetingInput}
80-
onChange={e => setUserGreetingInput(e.target.value)}
109+
onChange={(e) => setUserGreetingInput(e.target.value)}
81110
className={elementStyles.input}
82111
/>
83112
</label>
84-
<input type='submit' value='Submit' className={elementStyles.button} />
113+
<input
114+
type="submit"
115+
value={isMutating ? "Submitting..." : "Submit"}
116+
className={elementStyles.button}
117+
disabled={isMutating}
118+
/>
85119
</form>
120+
{mutationError && (
121+
<p style={{ color: "red" }}>Error: {mutationError.message}</p>
122+
)}
86123
</div>
87124
</div>
88-
)
89-
}
125+
);
126+
}

components/Navbar.tsx

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,25 @@
1-
import * as fcl from '@onflow/fcl'
2-
import useCurrentUser from '../hooks/useCurrentUser'
3-
import navbarStyles from '../styles/Navbar.module.css'
4-
import elementStyles from '../styles/Elements.module.css'
1+
import { useCurrentFlowUser } from "@onflow/kit";
2+
import navbarStyles from "../styles/Navbar.module.css";
3+
import elementStyles from "../styles/Elements.module.css";
54

65
export default function Navbar() {
7-
const user = useCurrentUser()
6+
const { user, authenticate, unauthenticate } = useCurrentFlowUser();
87

98
return (
109
<div className={navbarStyles.navbar}>
11-
{!user.loggedIn &&
12-
<button
13-
onClick={fcl.authenticate}
14-
className={elementStyles.button}>
10+
{!user.loggedIn && (
11+
<button onClick={authenticate} className={elementStyles.button}>
1512
Log In With Wallet
1613
</button>
17-
}
18-
{user.loggedIn &&
19-
(
20-
<>
21-
<div className={navbarStyles.address}>{ user?.addr }</div>
22-
<button
23-
onClick={fcl.unauthenticate}
24-
className={elementStyles.button}>
25-
Log Out
26-
</button>
27-
</>
28-
)
29-
}
14+
)}
15+
{user.loggedIn && (
16+
<>
17+
<div className={navbarStyles.address}>{user?.addr}</div>
18+
<button onClick={unauthenticate} className={elementStyles.button}>
19+
Log Out
20+
</button>
21+
</>
22+
)}
3023
</div>
31-
)
32-
}
24+
);
25+
}

config/fcl.ts

Lines changed: 0 additions & 15 deletions
This file was deleted.

constants/index.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
export const ACCESS_NODE_URLS = {
2-
'local': 'http://localhost:8888',
3-
'testnet': 'https://rest-testnet.onflow.org',
4-
'mainnet': 'https://rest-mainnet.onflow.org'
5-
}
2+
emulator: "http://localhost:8888",
3+
testnet: "https://rest-testnet.onflow.org",
4+
mainnet: "https://rest-mainnet.onflow.org",
5+
};
66

77
export const BLOCK_EXPLORER_URLS = {
8-
'testnet': 'https://testnet.flowscan.org',
9-
'mainnet': 'https://flowscan.org'
10-
}
8+
testnet: "https://testnet.flowscan.org",
9+
mainnet: "https://flowscan.org",
10+
};

0 commit comments

Comments
 (0)