Skip to main content

Your First Confidential App

This guide walks you through deploying the VELA example application — a private transfer app — and running your first confidential transaction. By the end you will have deposited ETH into an encrypted account inside the TEE and verified your private balance.

Prerequisites: Complete Local Environment Setup and have docker compose up running before proceeding.

What You're Deploying

The example application (vela-nova) is a private account-based ledger running entirely inside the TEE. Balances, transfers, and transaction history are all encrypted — external observers see only attested state roots on-chain, not the underlying data.

It supports four operations: deposit, privatetransfer, withdraw, and deanonymize (for authorized auditors).

Step 1: Download the Artifacts

Go to the vela-nova v0.1.0 release page and download two files:

  • payment_app.wasm — the compiled WASM module you'll deploy into the TEE
  • novaw-linux — the CLI wallet for interacting with the app

Place both files in a wallet/ folder.

Make novaw-linux executable:

chmod +x novaw-linux

Mac users: novaw-linux is a Linux x86-64 binary and cannot run directly on Mac (neither Intel nor Apple Silicon). All wallet commands must be run inside a Docker container — see the Mac tabs in each step below. Running the binary directly will give exec format error.

Step 2: Configure the Wallet

Copy the wallet config template:

cp wallet.conf.template wallet.conf

Open wallet.conf and set the following values to connect to your local environment.

The URLs differ depending on your OS:

When novaw-linux runs inside Docker, localhost resolves to the container itself — not your Mac. Use host.docker.internal to reach services on your host machine:

rpcUrl=http://host.docker.internal:8545
ProcessorAddress=0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9
TeeAuthenticatorAddress=0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0
AuthorityServiceURL=http://host.docker.internal:8081
SubgraphURL=http://host.docker.internal:8000/subgraphs/name/hcce

These are the deterministic contract addresses deployed by the local deployer service. They will be the same on every fresh environment.

Step 3: Set Your Keys

You need two keys: a secp256k1 key for signing on-chain transactions, and a P-521 key for private communication with the TEE.

secp256k1 key

Use one of the Anvil default account private keys. These accounts are pre-funded with 1000 ETH on the local chain.

Important for deployapp: The account must have DEPLOYER_ROLE on ProcessorEndpoint. In the local dev environment, only Anvil Account #0 has this role pre-granted. Use Account #0's key when running deployapp — any other key will fail with a role error. You can use other Anvil accounts for registeruser, deposit, and other operations.

Anvil Account #0 (required for deployapp):

ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

Add it to wallet.conf:

keySecp256k1=ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80

P-521 key

Generate a fresh key pair:

cd <your-wallet-folder>

docker run --rm --platform linux/amd64 \
-v $(pwd):/wallet -w /wallet \
ubuntu:22.04 /wallet/novaw-linux generatekeys

Copy the printed P521 value into wallet.conf:

keyP521=<generated-p521-key>

The P-521 key is used for ECDH-encrypted communication between your client and the TEE. The TEE uses your registered public key to encrypt all events it sends back to you — only your private key can decrypt them.

Step 4: Deploy the WASM Application

cd <your-wallet-folder>

docker run --rm --platform linux/amd64 \
-v $(pwd):/wallet -w /wallet \
ubuntu:22.04 /wallet/novaw-linux deployapp \
--wasm /wallet/payment_app.wasm --max-value-fee "100 wei"

On success you will see:

Deploy app completed successfully. ApplicationID: <number>

Copy the printed ApplicationID into wallet.conf:

ApplicationID=<number>

What happens under the hood:

  1. The wallet uploads payment_app.wasm to the Authority Service (POST /deploy/upload)
  2. An on-chain deploy request is submitted to ProcessorEndpoint
  3. The Processor Manager picks up the request and forwards the WASM artifact to the Executor inside the TEE
  4. The TEE verifies the WASM fingerprint (SHA-256) against the on-chain descriptor before loading the module
  5. The application is assigned an ApplicationID

Step 5: Register Your User

Before you can interact with the app, register your P-521 public key on-chain. This tells the TEE which key to use when encrypting events back to you:

docker run --rm --platform linux/amd64 -v $(pwd):/wallet -w /wallet \
ubuntu:22.04 /wallet/novaw-linux registeruser

Step 6: Run Your First Private Transaction

Check your public balance (starts at zero):

docker run --rm --platform linux/amd64 -v $(pwd):/wallet -w /wallet \
ubuntu:22.04 /wallet/novaw-linux getpublicbalance

Deposit 1 ETH into your private account inside the TEE:

docker run --rm --platform linux/amd64 -v $(pwd):/wallet -w /wallet \
ubuntu:22.04 /wallet/novaw-linux deposit -a "1 ETH"

The deposit is submitted as an on-chain transaction. The Processor Manager detects it, routes it to the Executor, which credits your encrypted account inside the TEE and emits an encrypted event confirming the operation. Only your P-521 key can decrypt it.

Verify your private balance:

docker run --rm --platform linux/amd64 -v $(pwd):/wallet -w /wallet \
ubuntu:22.04 /wallet/novaw-linux getprivatebalance

If you see 1 ETH reflected in your private balance, the full stack is working correctly.

Troubleshooting

wasm module is empty (code 11)

The manager and authorityservice containers are not sharing a named volume, so the manager cannot find the uploaded WASM artifact. Apply the shared volume fix described in Local Environment Setup, then force-recreate both containers:

cd <repo-root>/dockerfiles
docker compose up -d --force-recreate manager authorityservice

Then retry the deployapp command.

Insufficient funds for gas * price + value

The secp256k1 key in wallet.conf is not an Anvil pre-funded account. Switch to Anvil Account #0's key (see Step 3). Freshly generated keys have 0 ETH and every on-chain transaction will fail.

Full Command Reference

# Mac — replace <cmd> with any command below
docker run --rm --platform linux/amd64 -v $(pwd):/wallet -w /wallet \
ubuntu:22.04 /wallet/novaw-linux <cmd>

# Linux — run directly
./novaw-linux <cmd>

# Commands
generatekeys # Generate a P-521 key pair
deployapp # Deploy a WASM application
registeruser # Register your P-521 key on-chain
getpublicbalance # Query on-chain balance
deposit -a "1 ETH" # Deposit into private account
getprivatebalance # Query encrypted TEE balance
privatetransfer # Transfer between private accounts
help # Full command reference