-> Get started
This guide will walk you through the process of installing the Layer AVS CLI, setting up your environment, and deploying example contracts to create a service.
Prerequisites
The only thing you'll need to start is a Rust compiler. The exact way to install will depend on your operating system, but in general you can use the rustup
tool:
bash curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
Check out the official Rust installation site for more information: https://www.rust-lang.org/tools/install
You could also skip to the next step and run:
scripts/setup_wasi.sh
to install the necessary dependencies.
Clone the AVS repo
Use the following command to clone the Layer AVS toolkit repository: https://github.com/Lay3rLabs/avs-toolkit
git clone https://github.com/Lay3rLabs/avs-toolkit.git
This command will create a new directory called avs-toolkit
in your current directory.
Install the CLI
From within the [avs-toolkit](https://github.com/Lay3rLabs/avs-toolkit)
directory, navigate to tools/cli
:
cd avs-toolkit/tools/cli
And then install the CLI using Cargo:
cargo install --path .
It will take some time to finish.
When completed, navigate to the root of the directory
cd ...
Set up Your Wallet
Run the following commands to create a wallet and a local mnemonic. This will print the mnemonic
to standard out for you to see, as well as add it to your .env
locally.
M=$(avs-toolkit-cli wallet create | tail -1 | cut -c16-)echo "TEST_MNEMONIC=\"$M\"" > .envcat .env
This should have a nice 24-word phrase.
Once you have a wallet, you can add funds from the faucet:
avs-toolkit-cli faucet tap
You can view your funds with the following commands:
avs-toolkit-cli wallet show
Build Your Contracts
Before proceeding, make sure that Docker is installed and running:
- Install Docker desktop.
- Run Docker in your desktop.
If you are following this quide in sequence, you should already have the avs-toolkit repo on your machine from installing.
Run the following to build your contracts:
./scripts/optimizer.sh
After running this, you should see several .wasm
files that correspond to your contracts in your artifacts
folder
Note: you'll need to rebuild and redeploy your contracts whenever you make any changes to them.
Deploy the example verifier, operator, and task queue contracts
The following steps will deploy a simple verifier, task queue, and operator contracts for your AVS.
Run the following to deploy the contracts:
avs-toolkit-cli deploy --mode verifier-simple contracts --artifacts-path ./artifacts --operators wasmatic
The output of the deployment should look like the following:
INFO ---- All contracts instantiated successfully ----INFO Mock Operators: layer1qx7239qjwgm9dj8e0hunu3f89zw45fehaduvzu7ql9mq3rast93q37saghINFO Verifier Simple: layer19l2kyvvzf4cq9wlkn0r6phn5va0gh08f7dns6ud39vl6qpnesg0s2wjmglINFO Task Queue: layer1qwtnzhgvzwrvdt598lmu093thd8juw6z6uj8ggkv508s695psqzsc33r6aINFO export LOCAL_TASK_QUEUE_ADDRESS=layer1qwtnzhgvzwrvdt598lmu093thd8juw6z6uj8ggkv508s695psqzsc33r6aINFO export TEST_TASK_QUEUE_ADDRESS=layer1qwtnzhgvzwrvdt598lmu093thd8juw6z6uj8ggkv508s695psqzsc33r6a
Run the last line of the output from your terminal to export the task queue address for the contract.
For example, the command should look like the following:
export export TEST_TASK_QUEUE_ADDRESS=<your_layer_task_queue_address>
To view the deployed verifier contracts after this point, run the following commands.
avs-toolkit-cli task-queue view-queue
It's important to be able to find the Task Contract Address and the Verifier Contract Address by using these commands, so that you can use them when developing WASM components in the next section of this tutorial.
Create your WASM Component
This guide will walk you through developing a WASM component, which is the core logic of a service. In this example, you'll be building the Squaring Service, which takes a number as an input, and multiplies it by itself as an output. You can read more in-depth about this example in the Squaring Service Example Guide.
Setup
Even though we will be building a Wasm component that targets WASI Preview 2, the Rust wasm32-wasip2
build target is not quite ready yet. So we will use cargo-component
to compile the wasm32-wasip1
binaries and package to use WASI Preview 2.
- If you haven't yet, add the WASI Preview 1 target:
rustup target add wasm32-wasip1
- Install
cargo-component
andwkg
CLIs:
cargo install cargo-component wkg
- Set the default registry configuration, where the
lay3r:avs
WIT package is published:
wkg config --default-registry wa.dev
For more information about configuration, visit the wkg docs.
Create your project
-
Before starting, navigate to the directory where you would like to create your project.
-
To create a new Wasm Component, use
cargo component
to scaffold a new project with a task queue trigger. Feel free to choose a different project name other than "my-task".
cargo component new --lib --target lay3r:avs/task-queue my-task && cd my-task
- Open the directory in your code editor.
code .
- In your code editor, open
/src/lib.rs
. This file will contain all of the logic for your WASM service. You can delete the existing code in the file. Then, copy and paste the example below into yourlib.rs
file to create a service that squares a given number.
#[allow(warnings)]mod bindings;use anyhow::anyhow;use bindings::{Guest, Output, TaskQueueInput};use serde::{Deserialize, Serialize};#[derive(Deserialize, Debug)]pub struct TaskRequestData {pub x: u64,}#[derive(Serialize, Debug)]pub struct TaskResponseData {pub y: u64,}struct Component;impl Guest for Component {fn run_task(request: TaskQueueInput) -> Output {let TaskRequestData { x } = serde_json::from_slice(&request.request).map_err(|e| anyhow!("Could not deserialize input request from JSON: {}", e)).unwrap();let y = x * x;println!("{}^2 = {}", x, y);Ok(serde_json::to_vec(&TaskResponseData { y }).map_err(|e| anyhow!("Could not serialize output data into JSON: {}", e)).unwrap())}}bindings::export!(Component with_types_in bindings);
You'll notice that this example takes an input from a task queue trigger (x
), multiplies the number by itself, and returns the result (y
).
Layer makes things simple. You'll notice that the logic for this service is only a few lines of code. You can play around with this example to see for yourself how easy it is to make the logic for a simple AVS. For example, you could try cubing the number by modifying the equation to let y = x * x * x;
- Then, run the following in the root of your project to add the dependencies used in the example:
cargo add anyhow serde-json serde --features serde/derive
- Let's do the first build to generate the
src/bindings.rs
file. Afterward, you can do the familiarcargo
commands such ascargo test
andcargo clippy
. It may be helpful to inspectsrc/bindings.rs
during development to see the type information for producing the Wasm component.
cargo component build --release
You may need to create a .env
file in your project. Use the following command to copy the file you made earlier:
cp ../avs-toolkit/.env .
- Run the following code to upload the compiled Wasm component to the Wasmatic node using the avs-toolkit-cli CLI tool.
When doing an upload, you'll need to choose a unique name for your app, so that you can identify and test it, or remove your deployment if needed. In this example, replace <task-name
> with a unique name for your task.
avs-toolkit-cli wasmatic deploy --name <task-name> \--wasm-source ./target/wasm32-wasip1/release/my_task.wasm \--testable \--task $TEST_TASK_QUEUE_ADDRESS
If you get an appname conflict error, it means that someone else has submitted the same name. Change the <task-name>
in the previous step to something more unique. You can also remove the deployment by following this guide.
cp ../avs-toolkit/.env .
Add a Task
Now that your service is ready, you can add a task to the queue and see your service in action! To create tasks for your contract task queue, you can run the following commands.
- You can view the task queue by running the following command. It should be empty before you begin:
avs-toolkit-cli task-queue view-queue
- Run the following command to add a task to the queue. In this example, you'll input the number 15. Remember to change
<my-task>
to the name of your task from the previous section.
avs-toolkit-cli wasmatic test --name <task-name> --input '{"x": 13}'
After waiting a few second, you should be able to view the output. In this case, you'll see all 3 operators that were runnning your task have output the same value (169). Congratulations, you've just run a fully-decentralized offchain service using Layer!
Test executed successfully!Output for operator `https://op3.layer-p.net`: {"output":{"y":169}}Test executed successfully!Output for operator `https://op1.layer-p.net`: {"output":{"y":169}}Test executed successfully!Output for operator `https://op2.layer-p.net`: {"output":{"y":169}}
If you want, you can go back to the Create your project section, modify the lib.rs
section and run the commands again to create a custom service.
Connect a frontend to your contracts
Follow the frontend connection guide to learn how to connect the frontend to your contract. You'll need to edit the frontend code to add your task queue address.