AI agent documentation index: llms.txt. Raw markdown for any page is available by appending .md to the URL. Full content snapshot: llms-full.txt.
llms.txt — complete Cartesi documentation index. Append .md to any page URL for raw Markdown (e.g. /cartesi-rollups/2.0/development/building-an-application.md).
Skip to main content

Getting started

This page shows you how to add the CMA library to a Cartesi application and build a small wallet that accepts deposits of a single ERC20 token and answers balance queries.

Start from a template

The fastest way to start is with the official application templates. The repository contains ready to build projects for Python, Rust and C++. Each one already wires the library, the build files and the portal addresses together.

git clone https://github.com/Mugen-Builders/libcma-app-templates

Copy the folder for your language into your workspace and use it as the base of your application.

Add the library to an existing application

You can also add CMA to an application you already have.

Install pycma from the prebuilt RISC-V wheels:

pip3 install pycma --find-links https://prototyp3-dev.github.io/pip-wheels-riscv/wheels/

Or build it from the repository:

pip3 install pycma@git+https://github.com/Mugen-Builders/libcma-binding-python

The package is compiled for the RISC-V target, so run the install step inside the Dockerfile that builds your application's machine image.

Your first wallet

The example below accepts deposits of one ERC20 token, records them in a single asset ledger and answers balance queries. The single asset ledger keeps balances on the accounts flash drive, so they can be recovered on the base layer with the default emergency withdrawal tooling. See Single-asset ledger for the details.

from pycma import RollupCma, Ledger, decode_erc20_deposit, decode_inspect

ERC20_PORTAL_ADDRESS = "0x22E57511C30CcE6CDaa742E13CE3b774fDC663b1"[2:].lower()
TOKEN = "0x88A2120B7068E78692C8fd12E751d610B6377E4d"

rollup = RollupCma()

# A single asset ledger on the accounts flash drive, fixed to one ERC20 token
ledger = Ledger(
memory_filename="/dev/pmem1",
offset=0,
mem_length=4 * 1024 * 1024,
n_accounts=4096,
n_assets=1, # unused by the single asset ledger, but must be non zero
n_balances=1, # unused by the single asset ledger, but must be non zero
single_asset_account_drive=True,
account_drive_token=TOKEN,
)

# The single asset always has id 0
asset = ledger.retrieve_asset(token=TOKEN)
ASSET_ID = asset["asset_id"]

def handle_advance(rollup, ledger):
advance = rollup.read_advance_state()
msg_sender = advance["msg_sender"].hex().lower()

if msg_sender == ERC20_PORTAL_ADDRESS:
deposit = decode_erc20_deposit(advance)
account = ledger.retrieve_account(account=deposit["sender"])
ledger.deposit(ASSET_ID, account["account_id"], deposit["amount"])
return True

return False

def handle_inspect(rollup, ledger):
inspect = rollup.read_inspect_state()
query = decode_inspect(inspect)

if query["type"] == "BALANCE":
account = ledger.retrieve_account(account=query["account"])
balance = ledger.balance(ASSET_ID, account["account_id"])
rollup.emit_report(balance.to_bytes(32, "big"))
return True

return False

handlers = {"advance": handle_advance, "inspect": handle_inspect}

accept = True
while True:
next_request_type = rollup.finish(accept)
accept = handlers[next_request_type](rollup, ledger)

Build and run it

Applications using the CMA library build and run like any other Cartesi application. Follow Building an application to produce the machine image, then Running an application to start a local node. Use Sending inputs and assets to make a deposit and watch your wallet handle it.

Next steps

We use cookies to ensure that we give you the best experience on our website. By using the website, you agree to the use of cookies.