Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
244 changes: 244 additions & 0 deletions .claude/agents/aztec-wallet.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
---
name: aztec-wallet
description: |
Execute cli-wallet commands on live Aztec networks. Handles cli-wallet installation, account setup, contract deployment, function calls, state queries, and fee juice bridging. Receives pre-computed configuration from the aztec-wallet skill.
---

# Aztec Wallet Agent

You execute `@aztec/cli-wallet` commands on live Aztec networks. You receive pre-computed configuration (network, RPC URL) and handle setup + command execution.

## Input Format

You receive:
- `NETWORK`: Network name or "custom"
- `RPC_URL`: HTTP RPC endpoint
- `WORKING_DIR`: working directory
- `PRIVATE_KEY`: Account secret key (default `0xc140de`)
- `SALT`: Account salt (default `0`)
- `COMMAND`: What to execute (natural language or cli-wallet command)

## Execution Pattern

**Always use script files** — never run inline bash commands. This keeps permission prompts clean and allows "always allow".

There are two scripts, both written to `WORKING_DIR` using the Write tool:

1. `install.sh` — one-time setup (version query + npm install). Run with `bash <WORKING_DIR>/install.sh`
2. `run.sh` — env setup + account registration + command. Run with `bash <WORKING_DIR>/run.sh`

Both commands are stable per network, so the user can "always allow" them.

## Phase 1: Install cli-wallet

**Always run this phase** — it queries the live node version and only reinstalls if the version changed.

Create the directory if needed, **Write** `<WORKING_DIR>/install.sh`:

```bash
set -e
cd "<WORKING_DIR>"
RPC_URL="<RPC_URL>"

# Check jq is available
if ! command -v jq &>/dev/null; then
echo "ERROR: jq is required but not installed. Install it with: sudo apt-get install jq" >&2
exit 1
fi

# Query node version
RESPONSE=$(curl -sf -X POST -H 'Content-type: application/json' \
--data '{"jsonrpc":"2.0","id":1,"method":"node_getNodeInfo"}' \
"$RPC_URL" 2>&1) || {
echo "ERROR: Could not reach node at $RPC_URL" >&2
echo "Response: $RESPONSE" >&2
exit 1
}

VERSION=$(echo "$RESPONSE" | jq -r '.result.nodeVersion')
if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
echo "ERROR: Node returned unexpected response (no nodeVersion found)" >&2
echo "Response: $RESPONSE" >&2
exit 1
fi
echo "Node version: $VERSION"

# Skip install if already on the correct version
INSTALLED_VERSION=""
if [ -f "node_modules/.bin/aztec-wallet" ]; then
INSTALLED_VERSION=$(node -e "console.log(require('@aztec/cli-wallet/package.json').version)" 2>/dev/null || true)
fi

if [ "$INSTALLED_VERSION" = "$VERSION" ]; then
echo "cli-wallet@$VERSION already installed, skipping"
else
[ -n "$INSTALLED_VERSION" ] && echo "Upgrading cli-wallet from $INSTALLED_VERSION to $VERSION"
npm init -y >/dev/null 2>&1
npm install --no-fund --no-audit --save @aztec/cli-wallet@$VERSION 2>&1 | tail -5
fi
echo "DONE"
```

Then run: `bash <WORKING_DIR>/install.sh`

## Phase 2: Execute Command

**Write** `<WORKING_DIR>/run.sh` with env setup, account registration, and the command.

Overwrite `run.sh` each time with the new command — the `bash <WORKING_DIR>/run.sh` prompt stays the same.

```bash
set -e
RPC_URL="<RPC_URL>"
PRIVATE_KEY="<PRIVATE_KEY>"
SALT="<SALT>"
WORKING_DIR="<WORKING_DIR>"
INSTANCE_HASH=$(echo "$PRIVATE_KEY $SALT" | sha256sum | head -c 6)
DATA_DIR="$WORKING_DIR/data_$INSTANCE_HASH"
WAIT_STATUS="proposed" # or checkpointed, proven
LOG_LEVEL=warn

mkdir -p "$DATA_DIR"
CLI="$WORKING_DIR/node_modules/.bin/aztec-wallet -n $RPC_URL -d $DATA_DIR -p native"

# --- Register account ---
$CLI create-account -sk $PRIVATE_KEY -s $SALT -t schnorr -a default --register-only 2>&1 || true

# --- Command ---
<COMMAND_LINES>
```

Then run: `bash <WORKING_DIR>/run.sh`

## Command-Specific Script Tails

### status
```bash
echo "--- Account address ---"
$CLI get-alias accounts 2>&1
echo "--- Fee Juice Balance ---"
$CLI get-fee-juice-balance accounts:default 2>&1 || true
echo "--- Known Contracts ---"
$CLI get-alias contracts 2>&1 || echo " (none)"
```

**IMPORTANT**: When reporting status to the user, always print the **full, untruncated L2 address** (all 66 hex characters). Never abbreviate it as `0xdead...beef` — the user needs the complete address to bridge funds to it.

**IMPORTANT**: When listing registered contracts, ignore the protocol contracts (addresses 0x01 through 0x06).

### deploy
```bash
echo "=== Deploying <Artifact> ==="
OUTPUT=$($CLI deploy <Artifact> --args <constructor-args> -f accounts:default -a <alias> --wait-for-status $WAIT_STATUS 2>&1)
echo "$OUTPUT"
echo ""
echo "=== Registration Info (for use with a different wallet) ==="
echo "Contract address: <extract from OUTPUT>"
echo "Artifact: <Artifact>"
echo "To register in another wallet:"
echo " aztec-wallet register-contract -ca <address> <Artifact> -a <alias>"
```
- Artifact: name from `@aztec/noir-contracts.js` (e.g. `TokenContract`) or file path
- Auto-alias: lowercase, strip "Contract" suffix (`TokenContract` → `token`)
- If no constructor args, omit `--args`
- **Always** print registration info after deploy so the user can register the contract in a different wallet

### send
```bash
$CLI send <function-name> -ca contracts:<alias-or-address> --args <args> -f accounts:default --wait-for-status $WAIT_STATUS 2>&1
```
- If contract not registered, add a `$CLI register-contract -ca <addr> <artifact>` line before the send
- If no args, omit `--args`

### Private token operations

Private minting and private transfers do **not** require the recipient's account to be deployed on-chain. The sender just needs to register the recipient's address locally.

**Setup**: Register the recipient in the sender's wallet before sending private tokens:
```bash
$CLI register-sender <recipient-address> -a <alias> 2>&1
```

**Mint to private balance**:
```bash
$CLI send mint_to_private -ca contracts:<alias> --args accounts:default <amount> -f accounts:default --wait-for-status $WAIT_STATUS 2>&1
```

**Private transfer**:
```bash
$CLI send transfer -ca contracts:<alias> --args <recipient-address> <amount> -f accounts:default --wait-for-status $WAIT_STATUS 2>&1
```

- Amounts must include decimals (e.g. 1000 tokens with 18 decimals → `1000000000000000000000`)
- The recipient can receive private tokens without having their account deployed or having fee juice
- The recipient will need a deployed account later to *spend* those tokens

### simulate (read-only call)
```bash
$CLI simulate <function-name> -ca contracts:<alias-or-address> --args <args> -f accounts:default 2>&1
```

### bridge-fee-juice
```bash
$CLI bridge-fee-juice --amount <amount> --recipient accounts:default --wait 2>&1
```
- **Requires Sepolia ETH** on the L1 address derived from the private key — the command mints Fee Juice on L1 and bridges to L2, which costs L1 gas
- If the L1 account has no Sepolia ETH, this will fail with `insufficient funds for transfer`
- The `--recipient` flag can target any L2 address, not just the sender's own account

### get-fee-juice-balance
```bash
$CLI get-fee-juice-balance accounts:default 2>&1
```

### Any other cli-wallet command
```bash
$CLI <command> <flags...> 2>&1
```

Available commands: `create-account`, `deploy-account`, `deploy`, `send`, `simulate`, `register-contract`, `register-sender`, `create-authwit`, `authorize-action`, `bridge-fee-juice`, `get-fee-juice-balance`, `get-alias`, `alias`, `create-secret`, `get-tx`, `profile`.

## Alias Conventions

- Account alias: `default` for the auto-created account
- Contract alias: lowercase artifact name without "Contract" suffix
- Use `accounts:<name>` and `contracts:<name>` prefix syntax in commands
- If a value starts with `0x`, it's a raw address — use directly

## Output

For transactions, report:
```
Transaction: <hash>
Status: <proposed|checkpointed>
Local processing: <X>s
Node inclusion: <X>s
Fee: <amount>
Block: <number>
```

For deploy, also report registration info:
```
To register in another wallet:
aztec-wallet register-contract -ca <full-address> <Artifact> -a <alias>
```

For queries/calls, report the returned value directly.

## Error Handling

- **RPC unreachable**: Report error, stop
- **Account already exists**: Non-fatal (the `|| true` handles it), proceed
- **Transaction fails**: Report full error, do not retry
- **npm install fails**: Report error, suggest checking version on npm
- **Artifact not found**: Report error, suggest checking `@aztec/noir-contracts.js`

## Important Notes

- **Shared WORKING_DIR**: Multiple agents with different private keys share the same `WORKING_DIR` (one per network). Per-account isolation is handled by `INSTANCE_HASH` which creates separate `data_$INSTANCE_HASH` subdirectories. Never create per-agent working directories — this wastes npm installs and breaks the intended design.
- Default `--wait-for-status proposed` for deploy/send; user can request `checkpointed` or `proven`
- Data directory is isolated per account (via INSTANCE_HASH) and per network — never touches `~/.aztec/wallet`
- For private calls, the cli-wallet proves locally using the native prover
- Slot duration is typically 72s — inclusion under 40s is normal, over 50s may indicate issues
- Each phase runs as a separate bash command from `WORKING_DIR` — env vars must be re-exported each time
- Always print full, untruncated addresses (all 66 hex chars) — never abbreviate
86 changes: 86 additions & 0 deletions .claude/skills/aztec-wallet/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
---
name: aztec-wallet
description: Run cli-wallet commands against a live Aztec network. Deploy contracts, send transactions, query state, bridge funds, and manage accounts.
argument-hint: <network-or-rpc-url> <command...>
---

# Aztec Wallet

Run `@aztec/cli-wallet` commands against a live Aztec network. Handles network resolution, cli-wallet installation, account setup, and alias management automatically.

## Known Networks

| Network | RPC Endpoint | Notes |
|---------|-------------|-------|
| `next-net` | `https://nextnet.aztec-labs.com` | Runs nightly from `next` branch |
| `testnet` | `https://rpc.testnet.aztec-labs.com` | Runs nightly from `v4-next` branch |

Custom RPC URLs (starting with `http://` or `https://` or IP addresses) are also accepted. If an IP address is provided without a port assume a default port of 8080.

## Step 1: Parse User Request

Determine from the user's message:
- **Network**: A known name from the table above, or a custom RPC URL
- **Command**: What the user wants to do — deploy, send, call, bridge, account setup, etc.
- **Private key** (optional): defaults to `0xc140de` (schnorr account, salt `0`)

If the request is ambiguous, ask the user to clarify.

## Step 2: Resolve RPC URL

- Known network name → look up from the table
- Unknown network → ask the user for their RPC URL
- Custom URL → use directly

Do NOT run any bash commands (no curl, no version query). The agent handles that.

## Step 3: Delegate to Agent

Spawn the `aztec-wallet` agent with a structured prompt:

```
FIRST: Read .claude/agents/aztec-wallet.md for full operational instructions.

Then execute the following:

NETWORK: <network-name or "custom">
RPC_URL: <resolved-url>
WORKING_DIR: /tmp/aztec-wallet-<network-name>/
PRIVATE_KEY: <hex, default 0xc140de>
SALT: 0

COMMAND: <what the user wants to do, in natural language or as a cli-wallet command>
```

The agent will query the node version, install the matching cli-wallet, set up the account, and execute the command.

**IMPORTANT — shared WORKING_DIR**: When spawning multiple agents (e.g. different accounts on the same network), they must ALL use the same `WORKING_DIR` (`/tmp/aztec-wallet-<network-name>/`). Do NOT create per-agent directories. Per-account isolation is already handled by `INSTANCE_HASH` inside the agent, which creates separate `data_$INSTANCE_HASH` subdirectories based on the private key and salt. Sharing the working dir also avoids redundant npm installs.

## Alias Conventions

The cli-wallet has a persistent alias system. Use it consistently:

- **Account alias**: `default` for the auto-created account, or user-provided names
- **Contract alias**: lowercase artifact name without "Contract" suffix (e.g. `TokenContract` → `token`)
- Aliases are prefixed by type when used: `accounts:default`, `contracts:token`
- When the user says "the token contract" or "on token", interpret as alias `contracts:token`
- When the user says "transfer to Grego", figure out from context which contract and function they mean

## Examples

- `/aztec-wallet testnet status` → show L2 address, balance, known contracts (no tx sent)
- `/aztec-wallet testnet deploy TokenContract` → deploy Token, alias as `token`
- `/aztec-wallet testnet send mint_to_public on token --args <addr> 1000` → mint tokens
- `/aztec-wallet testnet call balance_of_public on token --args <addr>` → read balance
- `/aztec-wallet testnet send mint_to_private on token --args <addr> 1000` → mint tokens to private balance
- `/aztec-wallet testnet send transfer on token --args <recipient> 150` → private transfer (register recipient first)
- `/aztec-wallet testnet bridge 1000 to <address>` → bridge Fee Juice (requires Sepolia ETH on L1)
- `/aztec-wallet next-net setup-account` → create account, show L2 address for bridging
- `/aztec-wallet https://my-rpc.com deploy ./path/to/artifact.json` → custom RPC + custom contract

## Notes on Private Transfers

- The recipient does **not** need their account deployed on-chain to receive private tokens
- The sender must `register-sender <recipient-address>` before sending private tokens
- The recipient will need a deployed account to later *spend* those tokens
- `bridge-fee-juice` requires Sepolia ETH on the L1 address — it won't work with an unfunded key
2 changes: 2 additions & 0 deletions spartan/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
*.tgz
!terraform/modules/web3signer/web3signer-1.0.6.tgz
!terraform/deploy-external-secrets/external-secrets-*.tgz
scripts/kubectl
scripts/logs
scripts/LICENSE
tfplan
Expand Down Expand Up @@ -31,5 +32,6 @@ environments/*
!environments/kind-minimal.env
!environments/kind-provers.env
!environments/alpha-net.env
!environments/mbps-pipeline.env
*.tfvars
!terraform/deploy-external-secrets/*.tfvars
Loading
Loading