DRAFT
We will be building a complete Holochain app that includes testing and a user interface. We'll start with a simple zome, add the smallest test we can write, and call the zome from a simple web client.
Once we have something simple that operates across the full stack, we'll add more complexity in future parts of this tutorial by adding more features to the app. This will allow us to learn different aspects of Holochain as we need the functionality.
As far as what we're building β¦ I haven't decided yet. We're just going to start. Perhaps we'll identify the path we're on once we start walking.
Install the Nix package manager
Create a folder to build this tutorial in. Optionally make it a git repo.
Ensure you have Node.js and npm installed correctly by running: node -v; npm -v
Create additional folders. Make them look like this:
If it's easier, feel free to use this:
mkdir -p service/tests/src service/workdir service/zomes/greeter/src
And just for completeness, let's drop a .gitignore
file in the service
folder with these contents:
Now that we have our files and folders in place, let's finish setting up our development environment.
In order to ensure a consistent environment, the Holochain dev environment uses Nix/NixOS. At the moment, we're using project-specific environment configurations and they exist in the form of a default.nix
file.
Create a default.nix
file with these contents in your tutorial folder.
Alternatively, you can download this one (they're the same).
In your terminal, navigate to your tutorial folder and open the Nix shell.
This might take a while, so let's continue to prepare while we wait. It's fine to open another terminal window in the same folder, open your code editor, create files, etc. while we wait.
We're going to take real small baby steps to start off. Our first zome will contain a single function, named hello
, that has no input parameters and returns a static string.
Create service/zomes/greeter/src/lib.rs
with these contents:
The use
statement on line #1 brings in the HDK.
The hdk_extern
attribute marks the function as available to be called by the Holochain conductor.
The ExternResult
type ensures we're returning a type that can be serialized back to the user interface.
Create service/zomes/greeter/Cargo.toml
with these contents:
This file defines the metadata for our greeter
zome.
Create another Cargo.toml
file with these contents:
This file defines all of the zomes in our project.
Hopefully our Nix shell has finished building. If not, you'll have to wait before completing this step. Let's build the zome into Web Assembly (WASM). From the service
folder, inside your nix-shell, run this:
If this succeeded, you won't see any errors, but you will have an service/target/wasm32-unknown-unknown/release/greeter.wasm
file.
Now let's build the DNA file
When prompted, enter greeter
as the name and leave the uuid with its default value by just hitting enter.
Add the zome to the zomes
array in the newly created DNA file service/workdir/dna/dna.yaml
so it looks like this:
Package the WASM into a DNA file.
This will create service/workdir/dna/greeter.dna
. Now we're ready to do zome testing
We have the option of writing 2 different types of tests: unit tests written in Rust, and integration tests written in TypeScript. Writing a unit test doesn't have anything to do with Holochain - we just write them as we would any Rust code. However, our integration tests use the Tryorama tool to create a mock environment. We'll forego writing unit tests for the time being and setup our integration testing environment instead.
Inside your service/tests
folder, let's create some new files.
package.json
tsconfig.json
.gitignore
In preparation for our test run, from the service/tests
folder, install our dependencies.
npm install
For our test file, let's create this index.ts
file in our src
folder.
Now, from inside our service/tests
folder, we can run our test with: npm test
. Everything is passing/working if the end of our output is
Now is a good time to make sure you can break the test in an expected way. For example, on line #30, change "Hello Holo Dev"
to something else and re-run the test to watch it fail.
Holochain doesn't force you to use specific technologies for the user interface. You only need to use something that can send msgpack messages to the Websocket endpoint the conductor is listening to. To make this easier, we'll use JavaScript so we can use the conductor-api package.
The user interface technology, and how to use it, is not the focus of this tutorial. So we're going to do the most basic thing we can that keeps the focus on how to interact with the Holochain conductor. To that end, we're going to use Svelte and Snowpack.
Note: this is my first time using Svelte and Snowpack. So if you see something egregious, please let me know.
Let's start in our tutorial folder (not service
) and get a basic web app in place by running this in your terminal:
We don't need Git submodules, so delete the new repo and install some necessary dependencies.
Note: we'll stay in the ui
folder for the remainder of the UI part of the tutorial.
Tell Snowpack about Svelte by adding its plugin to the config. Make this change to line 6 of snowpack.config.js
:
Add an App.svelte
file:
Fix up our index.js
file so it looks like this:
Ensure we're working up to this point.
This should open your browser on http://localhost:8080. You should be able to see the message display when you click this button without any errors in your console.
hello
zomeBefore we can call the zome, we need to build the hApp bundle and deploy it to the local Holochain.
Create the hApp bundle by running this in your nix-shell from the service
folder:
When prompted, enter tutorial
for the name and Tutorial hApp
for the description.
Update our service/workdir/happ/happ.yaml
to fix the bundle path of our DNA by making its dna
section look like this:
Package our DNA into a hApp bundle by running this in your nix-shell.
This will create service/workdir/happ/greeter.happ
Deploy the hApp to a local sandbox Holochain by running this in your nix-shell:
Invoke the zome function from the web UI.