This repository includes examples of decentralized applications built with Sunodo.
Sunodo streamlines development across different language ecosystems, eliminating the need to navigate intricate configuration settings.
With Sunodo, you can bootstrap a complete Cartesi machine template in your programming language of choice through the CLI without getting lost in configurations.
- Building Applications: Sunodo simplifies the process of compiling applications from source code into a Cartesi Machine.
- Local Development Environment: Run, test, and debug applications in a local development environment.
- Deployment: A simplified deployment process with options to deploy applications on both public and private networks.
- Monitoring: Keep a close eye on the status and performance of applications that are already up and running.
The CLI heavily uses Docker under the hood, so you must have it installed and up-to-date.
The recommended way to have all plugins ready for building is to install Docker Desktop.
If you have Homebrew installed, you can install Sunodo by running this command:
brew install sunodo/tap/sunodo
Alternatively, you can install Sunodo with Node.js by running:
npm install -g @sunodo/cli
You can either use Homebrew on Linux, or install Sunodo with:
npm install -g @sunodo/cli
Install WSL2 and the Ubuntu dsitro from Microsoft Store and install Sunodo with:
npm install -g @sunodo/cli
Use the sunodo create
command to quickly start a Cartesi dApp from scratch. It sets up everything you need with template code.
Here are the available templates:
cpp
: A template for C++ development.cpp-low-level
: C++ template using the low level API, instead of the HTTP servergo
: Go lang templatejavascript
: A node.js 20 template tailored for JavaScript developerslua
: Lua 5.4 templatepython
: python 3 templateruby
: ruby templaterust
: rust templatetypescript
: TypeScript template
To create a new application from a basic Python template, run:
> sunodo create dapp-name --template python
✔ Application created at dapp-name
To build an application, run:
sunodo build
When you run the sunodo build
command:
- Your program's code gets compiled into the RISC-V architecture
- A Cartesi Machine is assembled.
- The end result of this process is a Cartesi Machine snapshot, ready to receive inputs.
.
/ \
/ \
\---/---\ /----\
\ X \
\----/ \---/---\
\ / CARTESI
\ / MACHINE
'
[INFO rollup_http_server] starting http dispatcher service...
[INFO rollup_http_server::http_service] starting http dispatcher http service!
[INFO actix_server::builder] starting 1 workers
[INFO actix_server::server] Actix runtime found; starting in Actix runtime
[INFO rollup_http_server::dapp_process] starting dapp
INFO:__main__:HTTP rollup_server url is http://127.0.0.1:5004
INFO:__main__:Sending finish
Manual yield rx-accepted (0x100000000 data)
Cycles: 2730825066
2730825066: a8a8ac815729549ca97aad13cdf10a5f51205f64e7f3fc77fc4e05050c49caee
Storing machine: please wait
This executes a Cartesi node for the application previously built with sunodo build
.
sunodo run
The sunodo run
command should print this output:
43272d70-prompt-1 | Anvil running at http://localhost:8545
43272d70-prompt-1 | GraphQL running at http://localhost:8080/graphql
43272d70-prompt-1 | Inspect running at http://localhost:8080/inspect/
43272d70-prompt-1 | Explorer running at http://localhost:8080/explorer/
43272d70-prompt-1 | Press Ctrl+C to stop the node
Sunodo run also supports running a node without your application backend packaged as a Cartesi machine.
sunodo run --no-backend
In this case, your application can be executed on the host without being compiled to RISC-V. Here are some drawbacks with --no-backend
:
-
Compilation Requirement: Your application must eventually be compiled to RISC-V during deployment.
-
Sandbox Restrictions: In
--no-backend
mode, the application won't run within the Cartesi machine's sandbox, enabling operations that are otherwise restricted. -
API Compatibility: This mode is compatible only with applications using the Cartesi Rollups HTTP API, not those using the low-level API like the C++ low-level dApp
-
Performance Impact: Expect lower performance inside a Cartesi machine compared to running on the host.
When launching a node with the --no-backend
you must then start your application on the host and fetch inputs from the endpoint running at http://127.0.0.1:8080/host-runner.
By default, the Cartesi node runs in non-verbose mode, providing logs only from your backend application. For more information, use the --verbose
command option.
sunodo run --verbose
Sunodo runs a local private chain powered by Anvil at port 8545
.
All contracts of the Cartesi Rollups framework are deployed and you can inspect their addresses by running:
sunodo address-book
The private chain has a default block time of 5 seconds and it runs on auto-mine mode.
You can manually configure block time by running:
sunodo run --block-time <seconds>
By default the node closes an epoch once a day.
You can manually configure epoch-duration by running:
sunodo run --epoch-duration <seconds>
You can configure Rollups Node services using environment variables.
Create a .sunodo.env
file in your project's root.
If you wish to modify the default deadline for advancing the state in the rollups-advance-runner service, open the .sunodo.env
file and add the desired configuration, for example:
SM_DEADLINE_ADVANCE_STATE=360000
Your applications can receive inputs by sending transactions with the input payload to the InputBox
smart contracts of the Cartesi Rollups framework. Sunodo provides a convenient CLI command to facilitate this process.
To send inputs, use the command:
sunodo send
This command guides you through the process of sending inputs interactively.
? Select send sub-command (Use arrow keys)
❯ Send DApp address input to the application.
Send ERC-20 deposit to the application.
Send ERC-721 deposit to the application.
Send ether deposit to the application.
Send generic input to the application.
There are five types of inputs you can send using sub-commands:
Useful for applications that need to know their own address. The input payload is the address of the application and the sender is the DAppAddressRelay
smart contract.
sunodo send dapp-address
Deposits ERC-20 tokens to the application. Refer to the ERC20Portal
documentation for payload format details.
sunodo send erc20
Deposits ERC-721 tokens (NFT) to the application. Refer to the ERC721Portal
documentation for payload format details.
sunodo send erc721
Deposits Ether (native token) to the application. Refer to the EtherPortal
documentation for payload format details.
sunodo send ether
Send inputs with any payload format. This is suitable for specialized input requirements.
sunodo send generic
The encoding of the payload can be specified with the --input-encoding
option. Supported encodings include:
- hex: Parses user input as a hex-string and converts it to bytes.
- string: Converts user input from a UTF-8 string to bytes.
- abi: Allows the user to specify an ABI-encoded input format in a human-readable format.
Example:
sunodo send generic --input-encoding hex
A basic "hello world" dApp written in Python that simply copies each input received as a corresponding output notice.
Implements the same behavior as the Echo Python dApp above, but with a back-end written in C++.
3. Echo Rust
Implements the same behavior as the Echo Python dApp above, but with a back-end written in Rust.
Implements the same behavior as the Echo Python dApp above, but with a back-end written in Lua.
5. Echo JS dApp
Implements the same behavior as the Echo Python dApp above, but with a back-end written in JavaScript.
6. Echo TS dApp
Implements the same behavior as the Echo Python dApp above, but with a back-end written in TypeScript.
Implements the same behavior as the Echo Python dApp above, but with a back-end written in C++ using the low-level Cartesi Rollups API.
Implements the same behavior as the Echo Python dApp above, but with a back-end written in Ruby.
9. Echo Go dApp
Implements the same behavior as the Echo Python dApp above, but with a back-end written in Go.