By Gauthier Sebille

In this tutorial, we demonstrate how to create a parametric blockchain with Deku-P, using the Deku TypeScript-SDK. To do so, we are going to create a state machine using Typescript, execute it within Deku blockchain, and interact with it!


Running Deku

       1. Install Nix by following the official guide. Additionally, you must enable the flakes feature:

 echo 'experimental-features = nix-command flakes' >> /etc/nix/nix.conf

Nix automatically installs all the dependencies and devtools needed for development, including Tilt, Docker, etc.

Note: Nix is the tool used by marigold to create reproductible environment, other distribution models will be available for the release

       2. Install direnv and don’t forget to “hook direnv to your shell”

       3. You can clone the github directory and use the branch doc/deku-pTutorial, on your terminal type:

$ git clone https://github.com/marigold-dev/deku.git 
$ cd deku
$ git switch arthur/doc/deku-pTutorial
$ direnv allow
# if `direnv allow` fails, please use: $ nix develop -c $SHELL
    # ONLY If you are on MacOS:
    $ brew tap ligolang/ligo https://gitlab.com/ligolang/ligo.git
    $ brew install ligolang/ligo/ligo
# This installation may takes a few minutes, please be patient
$ docker compose up -d
$ ./scripts/deploy_contracts.sh
$ dune build

You can follow our readme on how to compile Deku.

Init empty typescript application

- We will use Typescript as a main language for our blockchain application. Create the folder for your new project within the examples folder, in the terminal it looks like:

$ cd examples
$ mkdir myApp
$ cd myApp
$ npm init

npm init will initialize your project it will create a package.json file

- Run npm install typescript,.
As a good practice, we will add some compiler settings, within package.json specify to use the tsconfig.json containing all the configurations for your typescript project (created at next step).

"scripts": {
    "build": "tsc --p tsconfig.json",
    "test": "echo \"Error: no test specified\" && exit 1"

Create a new file tsconfig.json at the same level of your previously created package.json

$ touch tsconfig.json

You can copy the content of our tsconfig.json

Install deku-sdk manually by running:

$ npm install "file:../../sdks/typescript-sdk"
# ../../ because we are in deku/examples/myApp

Write your application!

Create an index.ts file. This file will contain all the business of your application, which will be your state machine.

$ touch index.ts

Write the blockchain state machine

Let's start to write our business: print out Hello World (yes, I know, this is crazy business) in the Deku-P virtual machine.

Inside index.ts we import the library deku-sdk to play with the Deku VMs state.

Please add the // @ts-ignore before the import, to avoid an error due to our tsconfig.json

// @ts-ignore
import  { main, get, set, transaction } from "deku-sdk"

- main: takes two parameters:
     - initial state of your VM
    -  transition function, to execute when there is a new operation submitted

- get: retrieves the value from the local state, it will take a single parameter key, and will return the stored value.

- set: set a value  in a Deku state for a given key. It takes two parameters:
- key: a key of the state
- value: a value is a string encoded in JSON format

- transition: is a JSON received from the chain, it contains

interface transaction {
  source: string;
  tx_hash: string;
  op_hash: string;
  operation: { [key: string]: any };

The complete index.ts example:

import { main, get, set, transaction } from "deku-sdk"

const transition = (_tx: transaction) => {
    // get the current value of `state` field defined in `main` function
    const currentValue = JSON.parse(get("myState"));
    // set the new value to `Hello world!`
    const nextValue = "Hello World!";
    // save the new state
    set("myState", nextValue);

- The transition function:

const transition = (tx: transaction) => {

The tx which is a transaction will allow you to retrieve and save the state of your application.

- The main function declares the initial state:

main({ myState: "" }, transition);

- myState: "": it is the initial state, it is a JSON object with the tz1xxx address as key

- transition: to update the state

Submit your first operation

We provide 2 CLI commands to try out your state.

The first one is deku-cli mock-transaction which needs to arguments:

- A wallet.json:

you just need a public tz1xxx address and its related secret, something like:

  "address": "tz1xxxxxxxxx",
  "priv_key": "edskxxxxxxxxx"

You can generate one by running:

# In Deku root folder
$ deku-cli generate-identity --output="wallet.json"

Then you can use the deku-cli mock-transaction command where arguments are:

- The payload we want to submit, in this case, it is an empty string.

- The file index.js (transpiled one) which we have written before.

# In index.ts folder
$ npm run build 
# In deku root folder
$ deku-cli mock-transaction wallet.json '' 'node examples/myApp/index.js'

fifo path: /tmp/vm_pipe
opening read
opening write
vm started
Parsed message: [
    operation_raw_hash: '5551d57390de99e6d2348b1ecf7decc728e645aaee8886dad75dd46178d6cd36',
    source: 'tz1Tbj2G1MgPtyjQwEUNCAoiZFPfZ6XScFqZ',
    operation: '',
    tickets: []
{ "myState": "Hello World!" }

As you have noticed, the VM is “mocked”, which means it is not really running. The command mock-transaction is the fastest way to check your state is working as you want, and the state is not “persisted”.

We will see in the following section how to start a VM or a Deku cluster.

Before that, let’s make our state a bit more complex.

Provide the operation

Instead of giving an empty string, we will provide Hello World from the dApp to the Deku-P cluster.

Let's modify the code in the function transition in index.ts as follow:

const transition = (tx: transaction) => {
    console.log("Getting source");
    const currentValue = JSON.parse(get("myState"));
    console.log("Current value: " + currentValue);
    // tx.operation is the second argument of `deku-cli` command line
    const nextValue = tx.operation;
    console.log("New value: " + nextValue);
    set("myState", nextValue);

We will simply provide it as the second argument of deku-cli mock-transaction command:

$ deku-cli mock-transaction wallet.json '"Hello world!"' 'node examples/myApp/index.js'

Getting source
Current value: null
New value: Hello world!
{ "myState": "\"\"", "state": "Hello world!" }
# As you can see, the state was previously undefined, and is now our provided value

Since the mock-transaction command doesn’t persist the state, we can’t see the several changes.

Let’s use deku-cli submit-transaction to see state evolution!

First step is to locally run a Deku cluster:

# Run the tutorial script, which will simply start a Deku cluster with 4 nodes and 4 VMs using examples/myApp/index.js
# run the following command in a dedicated terminal, because we need to see the logs to validate our operation was successful!
# Modify the line 32 to point on your index.js:
# node examples/myApp/index.js "./chain/data/$N/pipe" &
$ ./tutorial.sh
# In another terminal, run the submit-transaction command:
$ deku-cli submit-transaction wallet.json '"Hello world!"' 'node examples/myApp/index.js'

The result should be printed in the first terminal (where ./tutorial.sh is running)

Getting source
Current value: null
New value: "Hello World!"

Now let’s change this value:

$ deku-cli submit-transaction wallet.json '"Something else!"' 'node examples/myApp/index.js'

Getting source
Current value: "Hello World!"
New value: "Something else!"

And… we're done! The complete source code of this basic dApp is available here.

This is great!

We did our first interaction with Deku-P! Of course, you must be thinking:

"But this is only from the command-line… We need to do the same from the outside world, like a web application!"

In the second part of this tutorial (Create a cookie game Blockchain app with Deku-P), we will implement a cookie-clicker game as our state machine!

We will provide you the technical steps with the needed explanation, to interact with the vm-state from your Web application.

If you want to know more about Marigold, please follow us on social media (Twitter, Reddit, Linkedin)!

Scroll to top