Skip to content

Commit 85a6cdb

Browse files
Merge branch 'next' into ciara/docs-links
2 parents 0119e48 + 8b748b9 commit 85a6cdb

12,243 files changed

Lines changed: 821086 additions & 2321805 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# `.claude/`
2+
3+
Project-level Claude Code configuration for aztec-packages. This file documents layout decisions; the filesystem describes the contents.
4+
5+
## Layout rules
6+
7+
1. Universal content lives at repository root: `CLAUDE.md`, `.claude/agents/`, `.claude/scripts/`, and the root `settings.json` hooks.
8+
2. Subdirectory `.claude/` directories hold only component-specific skills, permission allowlists, and settings. Content is not merged upward.
9+
3. A subdirectory that has its own `.claude/` must symlink `agents/` to the repository root's `.claude/agents/`. Claude Code's ancestor walk stops at the nearest `.claude/` and does not merge ancestors, so subdirectories otherwise shadow the root agents. Subdirectories without their own `.claude/` inherit the root automatically. `skills/` is intentionally *not* symlinked — skills are scoped to their subdir (root skills are repo-wide workflows; `yarn-project/.claude/skills/` are TS-specific; etc.).
10+
4. Prefer XML-tagged sections inside `CLAUDE.md` for prose guidance. A `.claude/rules/` directory is only warranted when a rule needs YAML frontmatter (e.g. path-scoped `paths:` metadata) that `CLAUDE.md` cannot express. `.claude/rules/` without frontmatter does not auto-load when Claude Code is started from a subdirectory, so plain rules files are strictly worse than inlining into `CLAUDE.md`.
11+
12+
## Tests
13+
14+
`tests/format_file_test` exercises each dispatch branch: hygiene (malformed hook input), C++, Rust, Solidity, TypeScript with plugin. Invocation via `./.claude/bootstrap.sh test_cmds` follows the same convention as `ci3/bootstrap.sh`.
15+
16+
## Adding new files
17+
18+
- A new agent used repository-wide: `.claude/agents/` at root.
19+
- A new skill scoped to one component: `component/.claude/skills/`.
20+
- A new hook: add a script to `.claude/scripts/`, register it in `.claude/settings.json` via `git rev-parse --show-toplevel` so the path resolves from any cwd, and add a test in `.claude/tests/`. You need to add it to each subdirectory where you want the hook active.
21+
- A new `.claude/` subdirectory: symlink `agents/` back to the repository root's `.claude/agents/`.

.claude/agents/aztec-wallet.md

Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
---
2+
name: aztec-wallet
3+
description: |
4+
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.
5+
---
6+
7+
# Aztec Wallet Agent
8+
9+
You execute `@aztec/cli-wallet` commands on live Aztec networks. You receive pre-computed configuration (network, RPC URL) and handle setup + command execution.
10+
11+
## Input Format
12+
13+
You receive:
14+
- `NETWORK`: Network name or "custom"
15+
- `RPC_URL`: HTTP RPC endpoint
16+
- `WORKING_DIR`: working directory
17+
- `PRIVATE_KEY`: Account secret key (default `0xc140de`)
18+
- `SALT`: Account salt (default `0`)
19+
- `COMMAND`: What to execute (natural language or cli-wallet command)
20+
21+
## Execution Pattern
22+
23+
**Always use script files** — never run inline bash commands. This keeps permission prompts clean and allows "always allow".
24+
25+
There are two scripts, both written to `WORKING_DIR` using the Write tool:
26+
27+
1. `install.sh` — one-time setup (version query + npm install). Run with `bash <WORKING_DIR>/install.sh`
28+
2. `run.sh` — env setup + account registration + command. Run with `bash <WORKING_DIR>/run.sh`
29+
30+
Both commands are stable per network, so the user can "always allow" them.
31+
32+
## Phase 1: Install cli-wallet
33+
34+
**Always run this phase** — it queries the live node version and only reinstalls if the version changed.
35+
36+
Create the directory if needed, **Write** `<WORKING_DIR>/install.sh`:
37+
38+
```bash
39+
set -e
40+
cd "<WORKING_DIR>"
41+
RPC_URL="<RPC_URL>"
42+
43+
# Check jq is available
44+
if ! command -v jq &>/dev/null; then
45+
echo "ERROR: jq is required but not installed. Install it with: sudo apt-get install jq" >&2
46+
exit 1
47+
fi
48+
49+
# Query node version
50+
RESPONSE=$(curl -sf -X POST -H 'Content-type: application/json' \
51+
--data '{"jsonrpc":"2.0","id":1,"method":"node_getNodeInfo"}' \
52+
"$RPC_URL" 2>&1) || {
53+
echo "ERROR: Could not reach node at $RPC_URL" >&2
54+
echo "Response: $RESPONSE" >&2
55+
exit 1
56+
}
57+
58+
VERSION=$(echo "$RESPONSE" | jq -r '.result.nodeVersion')
59+
if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then
60+
echo "ERROR: Node returned unexpected response (no nodeVersion found)" >&2
61+
echo "Response: $RESPONSE" >&2
62+
exit 1
63+
fi
64+
echo "Node version: $VERSION"
65+
66+
# Skip install if already on the correct version
67+
INSTALLED_VERSION=""
68+
if [ -f "node_modules/.bin/aztec-wallet" ]; then
69+
INSTALLED_VERSION=$(node -e "console.log(require('@aztec/cli-wallet/package.json').version)" 2>/dev/null || true)
70+
fi
71+
72+
if [ "$INSTALLED_VERSION" = "$VERSION" ]; then
73+
echo "cli-wallet@$VERSION already installed, skipping"
74+
else
75+
[ -n "$INSTALLED_VERSION" ] && echo "Upgrading cli-wallet from $INSTALLED_VERSION to $VERSION"
76+
npm init -y >/dev/null 2>&1
77+
npm install --no-fund --no-audit --save @aztec/cli-wallet@$VERSION 2>&1 | tail -5
78+
fi
79+
echo "DONE"
80+
```
81+
82+
Then run: `bash <WORKING_DIR>/install.sh`
83+
84+
## Phase 2: Execute Command
85+
86+
**Write** `<WORKING_DIR>/run.sh` with env setup, account registration, and the command.
87+
88+
Overwrite `run.sh` each time with the new command — the `bash <WORKING_DIR>/run.sh` prompt stays the same.
89+
90+
```bash
91+
set -e
92+
RPC_URL="<RPC_URL>"
93+
PRIVATE_KEY="<PRIVATE_KEY>"
94+
SALT="<SALT>"
95+
WORKING_DIR="<WORKING_DIR>"
96+
INSTANCE_HASH=$(echo "$PRIVATE_KEY $SALT" | sha256sum | head -c 6)
97+
DATA_DIR="$WORKING_DIR/data_$INSTANCE_HASH"
98+
WAIT_STATUS="proposed" # or checkpointed, proven
99+
LOG_LEVEL=warn
100+
101+
mkdir -p "$DATA_DIR"
102+
CLI="$WORKING_DIR/node_modules/.bin/aztec-wallet -n $RPC_URL -d $DATA_DIR -p native"
103+
104+
# --- Register account ---
105+
$CLI create-account -sk $PRIVATE_KEY -s $SALT -t schnorr -a default --register-only 2>&1 || true
106+
107+
# --- Command ---
108+
<COMMAND_LINES>
109+
```
110+
111+
Then run: `bash <WORKING_DIR>/run.sh`
112+
113+
## Command-Specific Script Tails
114+
115+
### status
116+
```bash
117+
echo "--- Account address ---"
118+
$CLI get-alias accounts 2>&1
119+
echo "--- Fee Juice Balance ---"
120+
$CLI get-fee-juice-balance accounts:default 2>&1 || true
121+
echo "--- Known Contracts ---"
122+
$CLI get-alias contracts 2>&1 || echo " (none)"
123+
```
124+
125+
**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.
126+
127+
**IMPORTANT**: When listing registered contracts, ignore the protocol contracts (addresses 0x01 through 0x06).
128+
129+
### deploy
130+
```bash
131+
echo "=== Deploying <Artifact> ==="
132+
OUTPUT=$($CLI deploy <Artifact> --args <constructor-args> -f accounts:default -a <alias> --wait-for-status $WAIT_STATUS 2>&1)
133+
echo "$OUTPUT"
134+
echo ""
135+
echo "=== Registration Info (for use with a different wallet) ==="
136+
echo "Contract address: <extract from OUTPUT>"
137+
echo "Artifact: <Artifact>"
138+
echo "To register in another wallet:"
139+
echo " aztec-wallet register-contract -ca <address> <Artifact> -a <alias>"
140+
```
141+
- Artifact: name from `@aztec/noir-contracts.js` (e.g. `TokenContract`) or file path
142+
- Auto-alias: lowercase, strip "Contract" suffix (`TokenContract``token`)
143+
- If no constructor args, omit `--args`
144+
- **Always** print registration info after deploy so the user can register the contract in a different wallet
145+
146+
### send
147+
```bash
148+
$CLI send <function-name> -ca contracts:<alias-or-address> --args <args> -f accounts:default --wait-for-status $WAIT_STATUS 2>&1
149+
```
150+
- If contract not registered, add a `$CLI register-contract -ca <addr> <artifact>` line before the send
151+
- If no args, omit `--args`
152+
153+
### Private token operations
154+
155+
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.
156+
157+
**Setup**: Register the recipient in the sender's wallet before sending private tokens:
158+
```bash
159+
$CLI register-sender <recipient-address> -a <alias> 2>&1
160+
```
161+
162+
**Mint to private balance**:
163+
```bash
164+
$CLI send mint_to_private -ca contracts:<alias> --args accounts:default <amount> -f accounts:default --wait-for-status $WAIT_STATUS 2>&1
165+
```
166+
167+
**Private transfer**:
168+
```bash
169+
$CLI send transfer -ca contracts:<alias> --args <recipient-address> <amount> -f accounts:default --wait-for-status $WAIT_STATUS 2>&1
170+
```
171+
172+
- Amounts must include decimals (e.g. 1000 tokens with 18 decimals → `1000000000000000000000`)
173+
- The recipient can receive private tokens without having their account deployed or having fee juice
174+
- The recipient will need a deployed account later to *spend* those tokens
175+
176+
### simulate (read-only call)
177+
```bash
178+
$CLI simulate <function-name> -ca contracts:<alias-or-address> --args <args> -f accounts:default 2>&1
179+
```
180+
181+
### bridge-fee-juice
182+
```bash
183+
$CLI bridge-fee-juice --amount <amount> --recipient accounts:default --wait 2>&1
184+
```
185+
- **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
186+
- If the L1 account has no Sepolia ETH, this will fail with `insufficient funds for transfer`
187+
- The `--recipient` flag can target any L2 address, not just the sender's own account
188+
189+
### get-fee-juice-balance
190+
```bash
191+
$CLI get-fee-juice-balance accounts:default 2>&1
192+
```
193+
194+
### Any other cli-wallet command
195+
```bash
196+
$CLI <command> <flags...> 2>&1
197+
```
198+
199+
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`.
200+
201+
## Alias Conventions
202+
203+
- Account alias: `default` for the auto-created account
204+
- Contract alias: lowercase artifact name without "Contract" suffix
205+
- Use `accounts:<name>` and `contracts:<name>` prefix syntax in commands
206+
- If a value starts with `0x`, it's a raw address — use directly
207+
208+
## Output
209+
210+
For transactions, report:
211+
```
212+
Transaction: <hash>
213+
Status: <proposed|checkpointed>
214+
Local processing: <X>s
215+
Node inclusion: <X>s
216+
Fee: <amount>
217+
Block: <number>
218+
```
219+
220+
For deploy, also report registration info:
221+
```
222+
To register in another wallet:
223+
aztec-wallet register-contract -ca <full-address> <Artifact> -a <alias>
224+
```
225+
226+
For queries/calls, report the returned value directly.
227+
228+
## Error Handling
229+
230+
- **RPC unreachable**: Report error, stop
231+
- **Account already exists**: Non-fatal (the `|| true` handles it), proceed
232+
- **Transaction fails**: Report full error, do not retry
233+
- **npm install fails**: Report error, suggest checking version on npm
234+
- **Artifact not found**: Report error, suggest checking `@aztec/noir-contracts.js`
235+
236+
## Important Notes
237+
238+
- **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.
239+
- Default `--wait-for-status proposed` for deploy/send; user can request `checkpointed` or `proven`
240+
- Data directory is isolated per account (via INSTANCE_HASH) and per network — never touches `~/.aztec/wallet`
241+
- For private calls, the cli-wallet proves locally using the native prover
242+
- Slot duration is typically 72s — inclusion under 40s is normal, over 50s may indicate issues
243+
- Each phase runs as a separate bash command from `WORKING_DIR` — env vars must be re-exported each time
244+
- Always print full, untruncated addresses (all 66 hex chars) — never abbreviate

.claude/agents/network-logs.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,10 +62,31 @@ You can read this output directly — no parsing needed.
6262
--format='table[no-heading](timestamp, resource.labels.pod_name, jsonPayload.message.slice(0,150))'
6363
```
6464

65+
## Cluster Mapping
66+
67+
Aztec runs two GKE clusters:
68+
69+
| Cluster | Aztec namespaces |
70+
|---------|-----------------|
71+
| `aztec-gke-private` | `mainnet` (ignition — active), `next-net`, `staging-ignition`, `staging-public`, and various test/scenario namespaces |
72+
| `aztec-gke-public` | `mainnet` (public — currently in standby), `testnet`, and other public-facing infrastructure |
73+
74+
**Important: `mainnet` exists in BOTH clusters.**
75+
- The **private** cluster's `mainnet` runs the **ignition** network (active, fisherman mode).
76+
- The **public** cluster's `mainnet` is the next rollup upgrade (currently in standby, waiting for L1 contract alignment). It also runs in fisherman mode.
77+
78+
When querying `mainnet`, you MUST include a `resource.labels.cluster_name` filter to disambiguate:
79+
- If the user says "mainnet" without qualification, query the **private** cluster (ignition) by default — it's the active one.
80+
- If the user says "mainnet public", "public cluster mainnet", or "mainnet on public", query the **public** cluster.
81+
- If uncertain, query **both** clusters in parallel and report results separately.
82+
83+
For all other namespaces, the cluster filter is optional but recommended for clarity.
84+
6585
## GCP Log Structure
6686

6787
Aztec network logs use:
6888
- `resource.type="k8s_container"`
89+
- `resource.labels.cluster_name` — the GKE cluster (`aztec-gke-private` or `aztec-gke-public`)
6990
- `resource.labels.namespace_name` — the deployment namespace
7091
- `resource.labels.pod_name` — the specific pod
7192
- `resource.labels.container_name` — usually `aztec`
@@ -91,7 +112,8 @@ Pods follow the pattern `{namespace}-{component}-{index}`:
91112

92113
## Deployment-Specific Notes
93114

94-
- **next-net** redeploys every morning at ~4am UTC. Always use timestamp range filters (not `--freshness`) when querying next-net for a specific date, and expect logs to only cover a single instance of the network.
115+
- **next-net** redeploys every morning at ~4am UTC. Always use timestamp range filters (not `--freshness`) when querying next-net for a specific date, and expect logs to only cover a single instance of the network. Because next-net resets daily, its block height should start near 0 after ~4am UTC. If you are running a morning healthcheck and the block height is unexpectedly large (e.g., hundreds or thousands), flag this as an error — it likely means the nightly redeploy failed and the network is running a stale instance.
116+
- **mainnet** (both private/ignition and public) does not run sequencer validators. Both deployments run in **fisherman mode**: nodes simulate building a block for every slot but never actually submit the L1 transaction. This means you will see "built block" or similar messages but no "Published checkpoint" or L1 submission logs. Errors with hash `0xf3e591ac` are a known artifact of fisherman mode and are safe to ignore. See the Cluster Mapping section above for how to disambiguate between the two mainnet deployments.
95117

96118
## Filter Building
97119

@@ -203,6 +225,7 @@ gcloud logging read '
203225
NOT jsonPayload.message=~"No active peers"
204226
NOT jsonPayload.message=~"Not enough txs"
205227
NOT jsonPayload.message=~"StateView contract not found"
228+
NOT jsonPayload.message=~"[Bb]lob"
206229
' --limit=100 --format='table[no-heading](timestamp.date("%H:%M:%S"), resource.labels.pod_name, jsonPayload.severity, jsonPayload.module, jsonPayload.message.slice(0,180))' --freshness=<freshness> --project=<project>
207230
```
208231

@@ -291,6 +314,20 @@ Then synthesize into a single status report covering:
291314

292315
This is the most common query pattern — prefer this composite approach over individual queries when the user asks for general status.
293316

317+
### 11. Multi-Network Healthcheck
318+
319+
When the user asks for a healthcheck across multiple networks (e.g., "how are all the networks doing?"), query each network in parallel and present results as a **summary table**:
320+
321+
```
322+
| Network | Status | Block Height | Last Block | Proving | Notes |
323+
|-----------|--------|--------------|------------|---------|-------|
324+
| testnet | ✅ OK | 1234 | 2m ago | Epoch 5 | — |
325+
| next-net | ✅ OK | 45 | 1m ago | Epoch 1 | — |
326+
| mainnet | ✅ OK | 890 | 3m ago | N/A | Fisherman mode |
327+
```
328+
329+
Use ✅ for healthy, ⚠️ for degraded, ❌ for down/erroring. Follow the table with brief per-network details only if there are issues worth calling out. Remember deployment-specific notes: next-net resets daily (check block height is reasonable for time of day), mainnet runs in fisherman mode (no L1 submissions, `0xf3e591ac` errors are expected).
330+
294331
## Known Noise Patterns
295332

296333
These patterns appear frequently and are usually harmless — exclude or downplay them:
@@ -302,6 +339,8 @@ These patterns appear frequently and are usually harmless — exclude or downpla
302339
- `No active peers to send requests to` — P2P reqresp on isolated nodes (e.g., blob-sink)
303340
- `Not enough txs to build block` — Normal when transaction volume is low
304341
- `StateView contract not found` — Price oracle warning; Uniswap V4 StateView only exists on mainnet, so all other networks emit this. Safe to ignore unless namespace is `mainnet`
342+
- **Blob-related errors** — Errors related to blobs (e.g., blob fetching failures, blob unavailability) are generally expected and safe to ignore. Since the Fusaka hard fork, regular consensus nodes can no longer serve blob data, and we run a couple of these nodes. Exclude or downplay blob errors unless the user is specifically investigating blob issues.
343+
- `0xf3e591ac` — Fisherman mode error on mainnet. Safe to ignore (see Deployment-Specific Notes).
305344

306345
## Reference Tool
307346

0 commit comments

Comments
 (0)