# Building on Mox

> **Status:** Current

From an empty directory to a contract running on a local network, called from a browser.
Everything here runs on one machine and costs nothing.

## 1. A local network and its gateway

```bash
cargo build --release -p mox-cli -p mox-node
mox devnet init --dealer --accounts 20 --dir devnet     # 4 validators, 20 funded test accounts
mox devnet up --dir devnet
mox gateway --dir devnet --faucet-account 0             # http://127.0.0.1:8080
```

The gateway (`crates/mox-gateway`) is the one endpoint browsers and dapps use:

| Endpoint | What |
|---|---|
| `POST /` | JSON-RPC (the node's methods, forwarded to the best healthy validator; submissions limited per IP) |
| `POST /faucet {address}` | Testnet MUR (once per address per hour, a few per IP) |
| `GET /api/tx/{hash}`, `/api/address/{address}/txs`, `/api/commits`, `/api/commit/{i}`, `/api/events`, `/api/stats`, `/api/search?q=` | History from the gateway's indexer |
| `GET /events`, `GET /dag` | Live contract events and the live DAG (Server-Sent Events) |
| `GET /status` | Validators' health, indexer progress, faucet |

## 2. The console

A wallet and explorer in the browser (`console/`: React and `@mox/sdk`), served by the gateway:

```bash
(cd sdk && npm install && npm run build) && (cd console && npm install && npm run build)
mox gateway --dir devnet --faucet-account 0 --static console/dist   # open http://127.0.0.1:8080
```

- **Wallet:**
  - create a wallet (12 words, checked back) or import one;
  - the phrase is encrypted with your password (Argon2id → ChaCha20-Poly1305, in WebAssembly) and kept in the browser's IndexedDB;
  - the wallet locks on reload and after 15 minutes idle;
  - several accounts from one phrase; receive with a QR code;
  - send with a confirmation screen that shows the signed transaction decoded, the estimated fee and a dry run before anything is submitted.
- **Faucet:** testnet MUR for the selected account.
- **Explorer** (no wallet needed): search by transaction, address or commit; live height and throughput; transactions with their events decoded by each contract's interface (amounts in the token's decimals); address history and balance; commits.
- **Tokens:** your balances; create an MRC-20; send and mint.
- **Trade:** markets on the standard exchange; create one from two tokens; a live order book; limit and market orders that attach exactly what they lock; what each commit's batch clearing did to your order; open orders with cancel; the trade tape.
- **Stake:** bootstrap phase and gate, validators (committee weight, stake by class, blocks, rewards, jail), bond and unbond.
- **Mesh:** peer networks and their anchored checkpoints, messages in flight, MUR sent to another network (burned here, minted there on delivery).
- **Network:** validators by region, the live DAG (committed leaders, parent links), block propagation between validators, committee and epoch, the latest checkpoint.
- **Analytics:** throughput, commit and round rates, latency percentiles, mempools, memory, network, execution time by phase, drops by reason, fees; per validator. The gateway collects them from every validator's `/metrics` (no Prometheus needed).
- **Settings:** networks (any gateway), accounts, show the phrase (asks for the password), remove the wallet, connected sites.
- **Development:** `cd console && npm run dev` (Vite on :5173, talks to the gateway at 127.0.0.1:8080, or `VITE_GATEWAY`).
- **End to end:** `console/tests/run-e2e.sh` starts a fresh devnet and gateway and runs Playwright in the installed Chrome. It creates a wallet, uses the faucet, sends to a second account, checks the explorer, locks and unlocks, and restores from the phrase.

## 3. A contract project

```bash
rustup target add wasm32-unknown-unknown    # once
mox new counter
cd counter && ./build.sh test               # build the contract, run its tests
./build.sh deploy ../devnet 0               # prints the contract address
mox call --dir ../devnet --from 1 0x… click 3
mox call --dir ../devnet 0x… clicks_of 1
```

`mox new` writes:
- **`counter.mxi`:** the interface. State, functions, views, events and errors; clients encode calls and decode results from it. Each function's coordination class is inferred from the state it touches (`click` adds to a grow-only counter, so it is MONOTONE and never waits for ordering).
- **`src/lib.rs`:** the contract, plain `#![no_std]` Rust against the host functions in `mox.rs`.
- **`tests/`:** tests on an in-process chain ([`mox-testkit`](../../crates/mox-testkit)): the real executor, ten funded accounts, calls and views with JSON arguments, events decoded, interface errors by name, and several calls in one commit (`queue`, then `commit`). Each test runs in milliseconds.

```rust
let mut chain = TestChain::new();
let c = chain.deploy(0, WASM, json!([]));
let out = chain.call(1, &c, "click", json!([3]));
out.ok();
assert_eq!(out.event("Clicked").unwrap()["times"], 3);
chain.call(1, &c, "click", json!([101])).fails_with("TooMany");
assert_eq!(chain.view(&c, "clicks_of", json!([chain.address(1)])), 3);
```

The standard contracts published at genesis are there too: `chain.create(0, "mrc20", json!(["Gold", "GLD", 2, 100000, null]))`.

## 4. From a browser or Node: `@mox/sdk`

```bash
cd sdk && npm install && npm run build      # builds mox-wasm (needs Homebrew LLVM: brew install llvm)
```

```ts
import { load, Mox, Wallet } from "@mox/sdk";

await load();                                     // the WebAssembly module
const mox = new Mox("http://127.0.0.1:8080");     // a gateway
const wallet = Wallet.create();                   // 12 words; Wallet.fromPhrase(…) restores
const me = wallet.account(0);                     // m/44'/7337'/0'
await mox.waitReceipt((await mox.faucet(me.address)).hash);
await (await mox.transfer(me, wallet.account(1).address, "2.5")).wait();

const gold = await mox.create(me, "mrc20", ["Gold", "GLD", 2, 100000, null]);
const r = await (await gold.call(me, "transfer", { to: wallet.account(1).address, amount: "12.5" })).wait();
r.events[0].name;                                 // "Transfer", fields decoded
await gold.view("balance", [me.address]);         // 9998750
await mox.api(`/address/${me.address}/txs`);      // history from the indexer
const stop = mox.events({ contract: gold.address }, (e) => console.log(e));
```

**What runs where:**
- Keys, signing, encoding and decoding run in WebAssembly ([`mox-wasm`](../../crates/mox-wasm)): the same Rust as the node and the CLI ([`mox-client`](../../crates/mox-client)), checked against shared golden vectors.
- Private keys never leave the page.
- Amounts are decimal text in the token's decimals ("12.5"). Integers beyond 2^53 travel as strings, so JavaScript never rounds them.
- Calls use the inferred class of the function and the contract's domain; compute is estimated by a dry run before signing.

## 5. A dapp, end to end: the clicker

The worked example: a contract, its tests, a deployment and a front end whose wallet is the
console. It is the same path for any dapp.

1. **The contract** (section 3): `mox new clicker && cd clicker && ./build.sh test`, then
   `./build.sh deploy ../devnet 0` prints its address.
2. **The front end** ([`examples/clicker-dapp`](../../examples/clicker-dapp)): one page of
   plain JavaScript on `@mox/sdk`:
   - **Reads need no wallet:** `new Mox(gateway).contract(address)`, `view("clicks_of", [me])`, past events from `/api/events`, live ones from `mox.events({contract})`, all decoded by the contract's interface.
   - **Writes go through the console:** `const wallet = await connect(consoleUrl, { app: "Clicker" })` opens the console in a popup. The person unlocks it and approves the site, which then sees the account's address.
   - **Every call is approved there:** `await wallet.call(address, "click", [5])` shows the console's decoded confirmation (it names the site and `click(5)`) and resolves with the receipt, or rejects if the person declines.
   - **MetaMask-style:** `installProvider(consoleUrl)` sets `window.mox`, so `await window.mox.request({ method: "mox_requestAccounts" })` works too.
3. **Run it:**
   ```bash
   cd examples/clicker-dapp && npm install && npm run dev
   # open http://127.0.0.1:5174/?contract=0x…&console=http://127.0.0.1:8080
   ```

**Security model:**
- The dapp never sees a key.
- The console answers only the window that opened it, and pins that window's origin.
- It shows the origin on every request.
- Connected sites are remembered and can be disconnected; nothing is signed without the confirmation.

## 6. Testing it all

| What | How |
|---|---|
| A contract | `./build.sh test` in its project (`mox-testkit`) |
| Rust client code | `cargo test -p mox-client` (golden vectors: `MOX_WRITE_VECTORS=1` to regenerate after an intended change) |
| The WebAssembly build | `crates/mox-wasm/build.sh && node crates/mox-wasm/tests/vectors.mjs` |
| Gateway and wallet path | `node crates/mox-wasm/tests/gateway.mjs http://127.0.0.1:8080` (devnet + gateway with a faucet) |
| The SDK | `cd sdk && npm run build && node test/e2e.mjs http://127.0.0.1:8080` |
| The console and the sample dapp | `console/tests/run-e2e.sh`: two fresh peered devnets with relayers, gateways, the clicker deployed and its dapp served; Playwright covers the wallet, faucet, send, explorer, tokens, a market, staking, the mesh, the network and analytics views, and the dapp connection |
