Skip to content

Commit

Permalink
Merge pull request #940 from kadena-community/feat/docs/voting-dapp
Browse files Browse the repository at this point in the history
feat(docs): new election dApp tutorial
  • Loading branch information
jessevanmuijden committed Oct 13, 2023
2 parents c8953bb + 831d1a8 commit 977ed69
Show file tree
Hide file tree
Showing 18 changed files with 3,180 additions and 43 deletions.
5 changes: 5 additions & 0 deletions .changeset/unlucky-planets-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@kadena/docs': patch
---

Add Election dApp tutorial
2 changes: 0 additions & 2 deletions packages/apps/docs/next.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@ const nextConfig = {

pageExtensions: ['ts', 'tsx', 'js', 'jsx', 'md', 'mdx'],
reactStrictMode: true,
productionBrowserSourceMaps: true,

transpilePackages: ['@kadena/react-ui', 'react-tweet'],
images: {
remotePatterns: [
Expand Down
2 changes: 1 addition & 1 deletion packages/apps/docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"7d:query": "npx 7d",
"algolia-dev": "ALGOLIA_INDEX_NAME=docs_website_dev OPENAI_API_KEY=dummy-key121 npx 7d ingest --files 'src/pages/**/*.md' --files 'src/pages/**/*.mdx' --files 'src/specs/**/*.json' --db algolia --skip-embeddings",
"algolia-prod": "ALGOLIA_INDEX_NAME=docs_website_prod OPENAI_API_KEY=dummy-key121 npx 7d ingest --files 'src/pages/**/*.md' --files 'src/pages/**/*.mdx' --files 'src/specs/**/*.json' --db algolia --skip-embeddings",
"build": "pnpm run build:scripts && next build",
"build": "NODE_OPTIONS=--max-old-space-size=8192 pnpm run build:scripts && next build",
"build:next": "pnpm run build:scripts && next build",
"build:scripts": "node ./src/scripts/build.mjs",
"build:storybook": "pnpm run build:scripts && storybook build",
Expand Down
1 change: 1 addition & 0 deletions packages/apps/docs/public/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sitemap.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
---
title: "01: Getting started"
description: "In the first chapter of the Election dApp tutorial you will download the code of the project, explore the project structure and run the frontend."
menu: Election dApp tutorial
label: "01: Getting started"
order: 1
layout: full
tags: [pact, smart contract, typescript, tutorial]
---

# Chapter 01: Getting started

In this chapter, you will download the starter code for the election website
in its initial state. You will first explore the project structure. Then, you
will install the dependencies of the front-end application and run it. The
front-end will run without a connection to any blockchain. All data is stored
in memory for now. In the following chapters, you will gradually integrate
this front-end application with the blockchain. At the start of every next
chapter, you will find the name of the branch containing the solution of the
previous chapter. This will allow you to complete the entire tutorial even if
you get stuck in a particular chapter.

## Get the code

```bash
git clone git@github.com:kadena-community/election-dapp.git
cd election-dapp
git checkout 01-getting-started
```

If you want to take a peek at the completed code for this tutorial, check out
the following branch.

```bash
git checkout 00-complete
```

## Visual Studio Code

The most convenient way to work with the Election dApp project and its files is
to load the project into your [Visual Studio Code](https://code.visualstudio.com/)
workspace. Kadena has developed a "PACT" extension for this editor. It features
syntax highlighting, error reporting and code coverage reporting to improve your
smart contract development workflow. The extension does require you to have `pact`
and `pact-lsp` installed on your computer. You can configure the path to each
executable in the plugin settings. If you are using another editor, you may also
profit from just `pact-lsp` which provides the syntax highlighting. The links
to the installation instructions are listed on the
[main page](/build/guides/election-dapp-tutorial) of this tutorial.

## Project structure

At the root of the project you will see three folders: `frontend`, `pact` and
`snippets`. Each of these folders contain a set of files for a specific purpose.
Let's explore these folders one by one.

### Pact

This is where the `.pact` files for your smart contracts go, as well as `.repl`
files that will be used to test your smart contracts in isolation. You will
notice a `./root` folder that already contains some `.pact` files. They contain
Pact modules that the smart contracts you will create in later chapters depend
on. They only need to be there for local testing with `.repl` files. You do not
need to deploy them to the blockchain alongside your own `.pact` files, because
they are already deployed on Devnet, Testnet and Mainnet by default. So, once
your Pact module is deployed on the blockchain it will be able to load these
dependencies from the blockchain.

### Front-end

For the front-end of the election website, a basic React app was created. You
could use any other framework to create the front-end, because the connection
with the blockchain is established through the
[Kadena Client](https://www.npmjs.com/package/@kadena/client) npm package
that can be imported in any JavaScript project. At the end of the line, this
package simply makes HTTP API requests to the blockchain.
Inside of the React components, data is manipulated by calling service methods
the services get a specific implementation of repositories injected, depending
on the projects configuration. Initially, the project is configured to use
the in-memory implementation of repositories. The in-memory repositories
simply perform all data operations on JavaScript arrays and objects defined
in the same file. This implementation was created for you to have a simple
representation of the data flow as a reference while you are building the
blockchain implementation. Also, you can try out the app before you start
building, so you will have some contextual information about what you are
going to work on. Instructions for running the front-end with the in-memory
repository implementation will be provided later in this chapter.

### Snippets

In this folder you will find several JavaScript snippets that use the Kadena
Client library to perform actions against the blockchain that are not directly
related to the functionality of the election dApp per se, like deploy and
upgrading smart contracts, creating and funding accounts, and more. You will
learn more about these snippets in the following chapters.

## Run the front-end

Run the following commands in your terminal, assuming that you have cloned
the repository, changed the directory to the project root and switched
to the `01-getting-started` branch.

```bash
cd ./frontend
npm install
npm run start
```

Open a browser window and visit `http://localhost:3000`. You will see the working
front-end of the election website. Because all data is manipulated in memory,
you can freely click around and submit data. The state of the front-end will be
reset as soon as you refresh the page. The website shows a list of candidates
and the number of votes they have received. There is an option to set your
account name. This can be anything at this point of the tutorial. After you have
set an account name, you can cast a vote on any of the candidates. You can only
cast one vote per account. It is also possible to add a candidate or candidates
in bulk. This operation is not yet limited to certain accounts with a specific
permission, but we will get to that soon enough.

*[Screenshot of the front-end]*

## Next steps

At this point you should have a working development environment and an understanding
of the project structure. You have installed and run the front-end of the election
website, and you have an understanding of its features. In the next chapter of this
tutorial you will run a blockchain on your own computer using Docker. After that,
you will be ready to start developing smart contracts and creating the Devnet
implementations of the front-end repositories.
Original file line number Diff line number Diff line change
@@ -0,0 +1,214 @@
---
title: "02: Running Devnet"
description: "In the second chapter of the Election dApp tutorial you will use Docker to run a blockchain on your computer."
menu: Election dApp tutorial
label: "02: Running Devnet"
order: 2
layout: full
tags: [pact, smart contract, typescript, tutorial]
---

# Chapter 02: Running Devnet

The back-end of the election website will be implemented with smart contracts
running on the Kadena blockchain. The smart contract contains rules for voting
and nominating candidates and stores the nominated candidates and the votes
for each candidate. Before publishing your smart contract on a public network,
like Testnet or Mainnet, it is good practice to test if it works as expected
on your local computer. Using Docker, you can spin up a fully functional
Kadena blockchain network called Devnet.

```bash
docker run -it -p 8080:8080 kadena/devnet:latest
```

In case you do not want or are unable to run the Pact executable on your local
computer, you can mount the `./pact` folder of the project to the container.

```bash
docker run -it -p 8080:8080 -v ./pact:/pact-cli:ro kadena/devnet:latest
```

This will enable you to execute `pact` commands against your `.pact` and `.repl`
files via aninteractive `pact>` shell in your browser at
[http://localhost:8080/ttyd/pact-cli/](http://localhost:8080/ttyd/pact-cli/).

In this tutorial you will not need to create a persistent volume to maintain
the state of your local blockchain between restarts of your Docker container.
In fact, you can conveniently start with a clean slate by stopping the container
with `Ctrl+c` and starting it again with the command above. If you do want to
use a persistent volume, start the container as follows. Whenever you want to
start from scratch, you will need to recreate the volume.

```bash
docker volume create kadena_devnet
docker run -it -p 8080:8080 -v kadena_devnet:/data -v ./pact:/pact-cli:ro --name devnet kadena/devnet
```

## Configure Devnet in Chainweaver

Throughout this tutorial, you will frequently use Chainweaver to debug your
locally running blockchain via Chainweaver's graphical user interface. Open
Chainweaver and create an account if you have not already. After unlocking
Chainweaver, navigate to `Settings` on the bottom left of the screen and
choose `Network`. Under `Edit networks` you will see Testnet and Mainnet
preconfigured. In the `Create new network` field type `Devnet` and click
`Create`. Devnet should appear in the list. Click the arrow button next to
Devnet to reveal a form where that allows you to add a node. You only need
to add one node: `localhost:8080`. If your Docker container is running, the
circle to the right of the node name turns green. Press `Ok` to confirm.
On the far left in the top bar of the Chainweaver window, you can now switch
your network to Devnet. This ensures that all actions that you perform in
Chainweaver will be executed against Devnet.

## Explore Devnet contracts

In Chainweaver, expand the left navigation bar and click contracts. Select
`Module Explorer` at the top of the right panel to reveal a list of contracts
that are already deployed on your Devnet. Next to the search box on top of
that list, change `All chains` to any particular chain to narrow down the
list to the unique contracts that are deployed to Devnet by default:

* coin
* fungible-v1
* fungible-v2
* fungible-xchain-v1
* gas-payer-v1
* ns

As the names of the contracts suggest, they provide the basic functionality
required for using tokens (coin, fungible), paying transaction fees (gas)
and organizing contracts in namespaces (ns). Notice the overlap with the
contracts in the `./pact/root` folder of your project. Do your remember
from [Chapter 01](/build/guides/election-dapp-tutorial/01-getting-started) why these
files need to exist in your project, even though the corresponding contracts
are already deployed on Mainnet, Testnet, as well as Devnet? Also note that
there are not contracts related to the election yet. You will be creating
those yourself in the course of this tutorial. Click the `View`
button in the row of the `coin` contract to view its details. At the top of
the right pane you can click `Open` to load the source code into the left pane.
You will use this functionality in later chapters to verify upgrades of your own
smart contracts. Scrolling down in the right pane you will encounter a list
of functions inside the contract that you can call directly from Chainweaver.
In this tutorial, however, you will mainly use the Kadena JavaScript client
to call smart contract functions. Scroll back up a bit to
`Implemented interfaces` and view the `fungible-v2` interface. Read the
documentation of the following functions:

* transfer
* transfer-create
* get-balance
* create-account

These are some of the first smart contract functions that you will interact
with in the upcoming chapters of this tutorial.

## List modules with Kadena Client

Open up your editor and navigate to the `./snippets` folder of the election
dApp project. In the `./snippets/package.json` file you will find a list of
npm scripts defined that call TypeScript files in the `./snippets` folder.
The first script you will execute is `list-modules:devnet`. As the name implies,
this script will list the modules deployed on Devnet. It does so by executing
the `./snippets/list-modules.ts` file. Before running the script,
let's install the dependencies of the snippets first and then take a closer
look at what happens in the `./snippets/list-modules.ts` file. Open a terminal
and execute the following commands from the root of the election dApp project.

```bash
cd ./snippets
npm install
```

Open the file `./snippets/configuration.ts`. When the environment variable
`KADENA_NETWORK` is set to `devnet`, the functions exported from this file
will return `fast-development` as the network id, `1` as the chain id and
and API base URL with the host and port of your local devnet and a path
composed of the aforementioned network id and chain id. This configuration
is loaded into the `./snippets/list-modules.ts` file to configure the
transaction that is sent to your local blockchain using the Kadena Client.

In the main function of this file, the `Pact.builder` is used to create a
transaction for executing the Pact code `(list-modules)`, which is a
globally available function, not tied to a particular deployed contract.
Calling this read operation does not cost any gas, so it can be executed
by passing the transaction to the `dirtyRead` method of the Kadena Client
instance. Internally, this method transforms the transaction object to a
json object that is posted to an HTTP API endpoint of your Devnet node.
The remainder of the main function deals with processing the response
from the API.

```ts
// ./snippets/list-modules.ts

import { Pact, createClient } from '@kadena/client';
import { getApiHost, getChainId, getNetworkId } from './configuration';

const client = createClient(getApiHost());

main();

async function main() {
const transaction = Pact.builder
.execution('(list-modules)')
.setMeta({ chainId: getChainId() })
.setNetworkId(getNetworkId())
.createTransaction();

try {
const response = await client.dirtyRead(transaction);

const { result } = response;

if (result.status === 'success') {
console.log(result.data);
} else {
console.error(result.error);
}
} catch (e: unknown) {
console.error((e as Error).message);
}
}
```

Execute the snippet by running the following command in a terminal window
with the current directory set to the `./snippets` folder:

```bash
npm run list-modules:devnet
```

The script will produce the following output, a list of modules deployed on
your local Devnet:

```ts
[
'coin',
'fungible-v1',
'fungible-v2',
'fungible-xchain-v1',
'gas-payer-v1',
'ns'
]
```

Notice that the list is exactly the same as the list displayed in the module
explorer of Chainweaver. Both these tools can be used interchangably to interact
with the Kadena blockchain. They both support the execution of simple read
operations as well as the execution of complex multi-step transactions, as will
become clear when you will be using both approaches to test the smart contracts
that you will develop for the election website back-end in the remainder of this
tutorial.

## Next steps

At the end of this chapter you should have a full-fledged Kadena blockchain network
called Devnet running on your local computer. You have learned which contracts
are deployed on the Kadena networks by default and how you can explore them using
either Chainweaver or the Kadena JavaScript client. In the next chapter, you will
create an account on Devnet. This account will govern several aspects of the smart
contracts you will create in this tutorial: the namespace, keyset definition and
module. The account will also get exclusive permission to call certain functions in the
election smart contract, such as adding candidates. After setting up this account,
namespace and keyset definitions, all will be in place to deploy the smart contract
that will become the new back-end of the election website.
Loading

2 comments on commit 977ed69

@vercel
Copy link

@vercel vercel bot commented on 977ed69 Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

docs-storybook – ./packages/apps/docs

docs-storybook-git-main-kadena-js.vercel.app
docs-storybook-kadena-js.vercel.app
kadena-js-docs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on 977ed69 Oct 13, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

alpha-docs – ./packages/apps/docs

alpha-docs-git-main-kadena-js.vercel.app
docs-silk-two.vercel.app
alpha-docs.kadena.io
alpha-docs-kadena-js.vercel.app

Please sign in to comment.