# & chain (0x26) — agent onboarding > The `&` chain is an agent-native L1 where authority (mandates), identity > tiers, and verifiable execution are protocol primitives, not per-application > conventions. This document tells an autonomous agent everything it needs to > install the tooling, write a mandate, mint a session key, and submit its > first intent. Testnet is live. The tooling below builds, signs locally, and targets the public testnet RPC by default. ## Quick facts - Landing page: https://0x26.xyz - Whitepaper: https://0x26.xyz/whitepaper.pdf - CLI source: https://github.com/0x26xyz/0x26-cli - Rust SDK source: https://github.com/0x26xyz/0x26-rust-sdk (`and-chain-sdk`) - Other SDKs: - TypeScript: `@0x26xyz/and-chain-sdk` - Python: `and-chain-sdk` - .NET: `AndChain.Sdk` - Testnet RPC URL: `https://testnet.0x26.xyz/api` - Signature schemes: ed25519 for session intents and native owner calls; EIP-712 secp256k1 for existing EVM wallet-owned account policy mints. - Hash: SHA256 over Borsh serialization for native/session payloads. - Native accounting units: micro-USDC (1 USDC = 1_000_000 micro-USDC), integer lots, and price ticks. - CLI ergonomic units: use `--amount-usdc`, `--size-base` / `--size-btc`, and `--price` when you do not need raw chain units. Do not assume `1 lot = 1 BTC`; lot size is market-specific and is read from RPC. ## Install the `and` CLI The public testnet CLI is available from the standalone CLI repository: ```sh git clone https://github.com/0x26xyz/0x26-cli.git cd 0x26-cli cargo install --path . ``` Prebuilt release binaries are published on the CLI repository's GitHub Releases page: https://github.com/0x26xyz/0x26-cli/releases Verify the install: ```sh and --version and version and --help ``` ## Fast path — from zero to a reusable agent manifest The `&` chain splits authority into three objects: 1. **Account** — holds funds, owned by a native principal key or a linked EVM wallet principal. 2. **Policy (mandate)** — what an agent operating under this account is allowed to do: markets, volume caps, drawdown caps, rate limits. The policy delegates signing power to a **session key**. 3. **Intent** — a single action (place order, cancel, etc.), signed by the session key, admitted only if it fits inside the policy. The recommended CLI flow for agents is: generate or reuse account authority, mint a policy for a session key, write a manifest, then run follow-on commands through that manifest. The manifest stores public identity, policy, default market, RPC, and the local session-key path. It does not contain chain state. ```sh # Native owner-key path: # 1. Keys. The owner authorises the account; the session key signs intents. and keygen --out owner.key and keygen --out session.key # Optional: see the session pubkey you'll bind to the policy. and public-key session.key # → 0x3a4aa8c5... # 2. Sanity-check the RPC. Default endpoint is testnet.0x26.xyz/api - # override with --rpc or the AND_RPC_URL env var if you're running # a local node. and chain-info # 3. Pick fresh account/policy ids for this testnet agent. # These ids are user-chosen and globally unique on-chain; reusing an # existing id will be rejected. This derives a stable policy id from a # locally random account id. ACCOUNT_ID=$(( 1000000 + 0x$(openssl rand -hex 5) )) POLICY_ID=$(( ACCOUNT_ID * 1000 + 1 )) MARKET_ID=7 # 4. Bootstrap account + policy and write a reusable manifest. # --skip-order avoids placing an initial quote before collateral is ready. and agent bootstrap \ --owner owner.key \ --session session.key \ --account-id "$ACCOUNT_ID" \ --policy-id "$POLICY_ID" \ --market-id "$MARKET_ID" \ --faucet \ --skip-order \ --manifest-out agent.toml ``` For an existing wallet-owned account, use `agent bootstrap-evm` instead. The account must already be linked to the EVM address. The command signs an EIP-712 `EvmOwnerCall`, submits `kombat_submitEvmOwnerCall`, mints a session policy, and writes the same manifest shape used by every trading command. ```sh and keygen --out session.key EVM_ADDRESS=0x... POLICY_ID=$(( $(date +%s) * 1000000 + 61001 )) MARKET_ID=7 and agent bootstrap-evm \ --session session.key \ --wallet-address-hex "$EVM_ADDRESS" \ --policy-id "$POLICY_ID" \ --market-id "$MARKET_ID" \ --private-key-env EVM_PRIVATE_KEY \ --env-file .env \ --skip-order \ --manifest-out agent.toml \ --wait ``` For a new wallet-owned account, add `--new-account`. The command signs an EIP-712 `EvmAccountClaim`, submits `kombat_createEvmAccount`, then mints the session policy and writes the same manifest. ```sh and agent bootstrap-evm \ --new-account \ --session session.key \ --wallet-address-hex "$EVM_ADDRESS" \ --policy-id "$POLICY_ID" \ --market-id "$MARKET_ID" \ --private-key-env EVM_PRIVATE_KEY \ --env-file .env \ --skip-order \ --manifest-out agent.toml \ --wait ``` Signer sources for EVM wallet commands are mutually exclusive: `--private-key-env` with optional `--env-file`, `--private-key-file`, or `--interactive`. Do not pass EVM private keys as literal CLI arguments. After bootstrap, prefer manifest-backed commands: ```sh # Inspect identity, policy nonce, market state, and account risk. and --manifest agent.toml account get and --manifest agent.toml policy get and --manifest agent.toml market snapshot --depth 5 and --manifest agent.toml risk snapshot # Move 50 USDC into isolated collateral on the default market. and --manifest agent.toml collateral deposit --amount-usdc 50 --wait # Submit a tiny IOC market buy using human BTC size, then flatten it. and --manifest agent.toml order market buy --size-btc 0.001 and --manifest agent.toml order flatten # Place a post-only limit using human price and base size. and --manifest agent.toml order place \ --client-order-id 1001 \ --side bid \ --size-btc 0.001 \ --price 78000 \ --tif gtc \ --post-only \ --wait # Inspect and cancel if needed. and --manifest agent.toml order open and --manifest agent.toml order cancel --client-order-id 1001 and --manifest agent.toml events tail --from-seq 0 ``` The session key physically cannot exceed the mandate. The protocol rejects any intent that would breach volume, drawdown, or rate caps. ### Operational rules for agents - Treat `owner.key`, `session.key`, and EVM wallet private keys like SSH private keys. Never print secret-key contents into logs. - Always call `and --manifest agent.toml policy get` before a manual nonce-sensitive sequence. It returns `next_intent_nonce`. - Prefer `--amount-usdc`, `--size-btc`, and `--price` for interactive terminal work. Use raw micro-USDC, lots, and ticks only when a strategy has already queried the market metadata. - `order market buy` and `order market sell` submit IOC market orders and wait for terminal order state by default. `order flatten` reads the current position and sends the opposite-side IOC order. - Public gateway indexes can lag. A wait summary may show `intent_status.stage = "unknown"` while `order_status.stage = "filled"`. Trust the order/account state for fill management. - If a command times out, do not blindly resubmit. Check `policy get`, `order status`, `account trading-state`, and `events list` first. ## Command reference ```sh and keygen --out # generate a new ed25519 keypair and public-key # print the pubkey hex for a secret-key file and chain-info # chain id + head height + state root and version # build provenance JSON and account get --account-id N # account record and account lookup-evm --address-hex 0x... and account trading-state --account-id N and policy get --policy-id N # policy record (state, next nonce, etc.) and policy mint ... # owner-signed CreatePolicy and policy mint-evm ... # EIP-712 wallet-signed CreatePolicy and agent bootstrap-evm ... # existing EVM wallet account -> manifest and mandate get --mandate-id-hex 0x... and delegation get --delegation-id-hex 0x... and faucet fund-account --address-hex 0x... and wallet balances --address-hex 0x... and collateral deposit --amount-usdc 50 and collateral withdraw --amount-usdc 10 and order place ... # session-signed PlaceOrder intent and order market buy --size-btc 0.001 and order market sell --quantity-lots 1000 and order flatten # close current position with IOC and order cancel ... # session-signed CancelOrder intent and order status --account-id N --market-id N --client-order-id N and order open --account-id N --market-id N and market snapshot --market-id N and market state --market-id N and market book --market-id N and risk account-summary --account-id N and risk snapshot --account-id N --market-id N and intent status --intent-id-hex 0x... and events list ... # page through recent runtime events and events tail ... # NDJSON stream of matching events and mandate list and mandate submit-evm --signed-json signed-mandate.json and vault list and vault get --vault-id-hex 0x... and vault deposit --vault-id-hex 0x... --amount-usdc N and vault position and vault history and vault redeem --delegation-id-hex 0x... --shares N ``` Every command accepts `--rpc ` (or env var `AND_RPC_URL`). Manifest-backed commands can use `--manifest agent.toml` to reuse the bootstrap identity, policy, market, and session-key path. ## Units and trading helpers The chain remains integer-first, but the CLI has agent-friendly adapters: | Intent surface | Raw flag | Human flag | Notes | |----------------|----------|------------|-------| | Collateral / vault deposit | `--amount-micro-usdc` | `--amount-usdc` | 6 decimal places | | Order size | `--quantity-lots` | `--size-base`, `--size-btc` | converted through market lot size | | Limit price | `--price-ticks` | `--price` | converted through chain price tick scale | Examples: ```sh and --manifest agent.toml collateral deposit --amount-usdc 50 --wait and --manifest agent.toml order market buy --size-btc 0.001 and --manifest agent.toml order market sell --quantity-lots 1000 and --manifest agent.toml order flatten ``` ## Using the SDKs directly The CLI is a thin wrapper over the Rust SDK. If you're writing a bot, prefer the SDK for your language: ### Rust ```toml [dependencies] and-chain-sdk = { git = "https://github.com/0x26xyz/0x26-rust-sdk", tag = "v0.1.0" } tokio = { version = "1", features = ["macros", "rt-multi-thread"] } ``` ```rust use and_chain_sdk::{ AndChainClient, IntentKind, IntentRequest, Keypair, OrderKind, OrderSide, OwnerAction, OwnerCallRequest, PolicyTermsBuilder, TimeInForce, }; #[tokio::main] async fn main() -> anyhow::Result<()> { let client = AndChainClient::new("https://testnet.0x26.xyz/api"); let owner = Keypair::generate(); let session = Keypair::generate(); let terms = PolicyTermsBuilder::new() .max_volume_per_day_usdc(50_000) .max_drawdown_pct(1_500) .build(); let chain_id = client.chain_info().await?.chain_id; let nonce = client.get_account(22).await?.nonce; client.submit_typed_owner_call(&owner, OwnerCallRequest { account_id: 22, chain_id, nonce, action: OwnerAction::CreatePolicy { policy_id: 42, grantee: session.public_bytes(), expires_at: now_ms() + 86_400_000, terms, }, }, now_ms()).await?; client.submit_typed_intent(&session, IntentRequest { chain_id, account_id: 22, policy_id: 42, nonce: client.next_intent_nonce(42).await?, expires_at: now_ms() + 60_000, predicate: None, kind: IntentKind::PlaceOrder { market_id: 7, client_order_id: 1, side: OrderSide::Bid, quantity_lots: 5, kind: OrderKind::Limit { price_ticks: 103 }, time_in_force: TimeInForce::Gtc, post_only: false, }, }, now_ms()).await?; Ok(()) } ``` ### TypeScript / Python / .NET The TS / Python / .NET packages expose JSON-RPC transport and typed signing helpers. The wire format is the same as the Rust SDK produces. See the individual package READMEs for examples: - TS: https://github.com/0x26xyz/0x26-ts-sdk - Python: https://github.com/0x26xyz/0x26-python-sdk - .NET: https://github.com/0x26xyz/0x26-dotnet-sdk The Rust SDK is the reference implementation; the other SDKs are tested against the same signing fixtures. ## Policy terms — what you can express A mandate is a set of hard numeric caps. Exceeding any one rejects the intent at admission. | Field | Unit | Typical value | |------------------------------|---------------|---------------| | `gas_budget_per_day` | micro-USDC | 10_000_000 | | `gas_refill_per_day` | micro-USDC | 10_000_000 | | `max_intents_per_second` | count | 5 | | `max_intents_per_day` | count | 50_000 | | `max_volume_per_day` | micro-USDC | 50_000_000_000 | | `max_drawdown_pct` | bps × 10 | 1_500 (= 15%) | The CLI `policy mint` flags accept these in more human units (`--max-volume-per-day-usdc`, etc.) and convert for you. ## Intent kinds - `PlaceOrder` — limit or market order on a matched book. - `CancelOrder` — cancel by `(market_id, client_order_id)`. - `ReplaceOrder` — cancel + re-place atomically. - `Transfer` — move token between accounts. - `CreateSubPolicy` — delegate a narrower mandate to another session key. - `RevokePolicy` — owner-signed, invalidates a policy. - `Cancel` — legacy single-order-id cancel. All intents carry: `chain_id`, `account_id`, `policy_id`, `nonce`, `expires_at`, optional time-window `predicate`. ## Signing — for implementers going direct 1. Build the `Intent` struct (Borsh-derivable). 2. `intent_hash = SHA256(borsh::to_vec(&intent))`. 3. Build `SessionPayload { intent_hash, policy_id, chain_id }`. 4. `signing_bytes = borsh::to_vec(&session_payload)`. 5. `signature = ed25519_sign(session_secret, signing_bytes)`. 6. Submit `{ intent, signature_hex }` via `kombat_submitIntent`. Native owner calls use a similar scheme: `signing_bytes = borsh::to_vec(&(account_id, chain_id, &owner_call))` signed with the owner secret. EVM wallet-owned policy mints use EIP-712: - domain: `name = "0x26"`, `version = "1"`, live `chain_id`; - primary type: `EvmOwnerCall(uint256 accountId,uint256 chainId,bytes32 signer,uint256 nonce,string actionKind,bytes actionBytes)`; - `actionBytes` is the Borsh-encoded `OwnerAction`, hashed as EIP-712 `bytes`; - submit `{ account_id, chain_id, signer, nonce, action, signature_hex }` through `kombat_submitEvmOwnerCall`. New EVM wallet-owned account creation uses EIP-712: - primary type: `EvmAccountClaim(uint256 chainId,uint256 accountId,address wallet,bytes32 owner,bytes32 codeHash,uint256 expiresAt)`; - `owner` is `evm_owner_principal(wallet)`; - submit `{ signed_account_claim, timestamp_ms }` through `kombat_createEvmAccount`; - plain `kombat_createAccount` rejects unauthenticated `evm_address_hex`. The Rust SDK does all of this. If you're porting to another language, reproduce the byte ordering exactly — the chain's admission verifier is Borsh-strict and the EIP-712 type string is exact. ## Status - Testnet: **live.** - Mainnet: TBD. - Tooling (CLI, SDKs): available now, wire-format-stable. - The six primitives: five ship in v1, composition primitives in v1.1. ## Where to ask questions - Issues on the CLI: https://github.com/0x26xyz/0x26-cli/issues - Issues on the Rust SDK: https://github.com/0x26xyz/0x26-rust-sdk/issues