sdk-js/README.md
Aere Network 6f13c671f1 0.16.13: repair ~130 client selectors that did not match the deployed contracts (D-512)
Ten clients (RaaS, Sink, Agent and x402 settlement, state channels, compliance,
lending, the compliant pool) carried hand-written function selectors that matched
neither the compiled ABI nor the signature written next to them, so every call
through them reverted. Every selector is now the keccak of a signature in the
compiled ABI. Functions the contracts never had are replaced by the real ones:
AereSanctionsRegistry (latestEpoch, isSanctioned with epoch, isSanctionedLatest,
currentRoot via snapshotStatus), ChainalysisOracleWrapper (upstreamOracle),
AereTravelRuleHashRegistry (status by commitment id), AereInsuranceFund (two-step
proposeMarket + registerMarket). AereRaaSFactoryClient.registerRollup targets the
canonical AereRaaSFactoryV2 (11 parameters, optional defenseGrace).

Proof: the gate aerenew/scripts/deschise/sdk-selectori-corecti.cjs reads 330 of
330 selectors correct and fails on a planted one; src/test/selectors-live.ts reads
18 values from the deployed contracts through the shipped clients, and the old
rollupCount selector still reverts (its negative control).

Also: state-window-live records that both public endpoints now refuse state
outside the 512-block window ("World state unavailable") instead of returning a
false 0x0, and proves the guard against an endpoint that still lies; npm test
runs the offline suite through scripts/run-tests.mjs (61/61), live proofs stay
separate. README network facts brought to 2026-10-15.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 15:10:49 +03:00

370 lines
19 KiB
Markdown

# @aere/sdk
Official AERE Network TypeScript SDK. Wraps `ethers v6` with typed clients for the
live AERE L1 (chain ID 2800): the DeFi, agentic-settlement, compliance,
account-abstraction and post-quantum contract surface, the seedless hybrid PQC
wallet, and AERE's native NIST post-quantum precompiles.
**SDK version:** 0.16.13
**Last updated:** 2026-10-15 (network facts, state window, client selectors; the rest is as of 2026-07-16)
**0.16.13, 2026-10-15: client selectors repaired.** Until this release about 130 hand-written function selectors in ten
clients (RaaS, Sink, Agent and x402 settlement, state channels, compliance, lending, the compliant pool) did not match
the deployed contracts, so calls through them reverted. Every selector is now the keccak of a signature in the compiled
ABI, checked by a gate on each change, and `src/test/selectors-live.ts` reads the deployed contracts through the shipped
clients. API changes: `AereSanctionsRegistryClient` gains `latestEpoch()`, `isSanctioned(epoch, ...)` and
`isSanctionedLatest(...)`, and `currentRoot(epoch?)` now reads the root of an epoch; `ChainalysisOracleWrapperClient`
gains `upstreamOracle()`; `AereTravelRuleHashRegistryClient.status` takes a commitment id; `AereInsuranceFundClient`
registers a market in two steps, `proposeMarket` then `registerMarket`; `AereRaaSFactoryClient.registerRollup` targets
the canonical `AereRaaSFactoryV2` and accepts an optional `defenseGrace`.
**Network state at this release:** 35+ typed contract clients over a canonical
address book of 130+ live contracts on chain 2800.
---
## Network parameters
| | |
|---|---|
| Chain name | AERE Network |
| Chain ID | 2800 (`0xAF0`) |
| Consensus | QBFT; per-block finality on classical secp256k1 ECDSA commit seals, with post-quantum validator seals on consensus messages and a post-quantum certificate under every 32nd block's hash (details on aere.network) |
| Validators | 10 since 2026-09-11, Byzantine-fault tolerance f=3, commit quorum 7 of 10 |
| Operator / client diversity | Single operator (the Foundation); two client implementations, Besu-derived and Nethermind-derived (one validator, since 2026-09-11) |
| Block period | 0.5 s target; measured 0.62 s (median of five 20,000-block windows, 2026-10-15); deterministic finality |
| Native token | AERE (18 decimals) |
| Max supply | 2,800,000,000 AERE (capped at genesis-v2, 2026-05-07) |
| EVM ruleset | Pectra + Fusaka opcode and precompile set (Besu), plus five AERE post-quantum precompiles; not full parity with Ethereum mainnet (the beacon-chain system contracts, e.g. EIP-4788 beacon roots, have no code on chain 2800) |
| HTTP RPC | `https://rpc.aere.network` |
| WebSocket RPC | `wss://wss.aere.network` |
| Explorer (Blockscout) | `https://explorer.aere.network` |
| Indexer REST | `https://api.aere.network` |
## Consensus and post-quantum boundary (read this)
AERE draws a hard line between consensus and the application layer, and this SDK
keeps it:
- **Consensus is classical ECDSA on every block, with a post-quantum checkpoint
every 32 blocks.** Blocks are proposed and sealed under Besu QBFT with secp256k1
ECDSA signatures (nine Foundation validators, quorum 6 of 9, f=2). Since block
13,014,000 anchor blocks also carry, under the block hash, a certificate of
validator Falcon-512 seals, and since 2026-08-14 a node rejects an anchor block
with fewer than three valid seals (f+1 of nine, not a quorum). That is the whole
post-quantum part of consensus: not a per-block quorum (the claim published on
2026-08-15 was withdrawn on 2026-08-19). A second client (Nethermind) validates
and follows the public chain at client2.aere.network; it does not produce blocks.
- **PQC lives at the application layer.** Five NIST post-quantum verification
precompiles are live on mainnet (see below). Contracts and this SDK use them for
application-layer signatures, attestations, key registries, agent DIDs, t-of-n
custody and a seedless wallet. None of that makes mainnet consensus
post-quantum, and the SDK never claims it does.
## Genesis allocation (2,800,000,000 AERE)
| Wallet | Allocation | Address |
|---|---:|---|
| Strategic Investor | 100,000,000 | `0xaee2f3989f0AB23296Fa3b92247fe67587141311` |
| Foundation (chain admin) | 180,000,000 | `0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3` |
| Mining Reserve | 1,400,000,000 | `0x038f59A40ceeCd599A4588E4B0ff4642a0fbfFB8` |
| Ecosystem Reserve | 560,000,000 | `0xB6a364F47d21DC2CbEB803565c111c1026e11C75` |
| Team Reserve | 420,000,000 | `0x7968C438204a78B4e032fcFFd9A56Edb15fdCCdf` |
| Airdrop Reserve | 140,000,000 | `0x261913fA73D6F109382F1aE98Ff6822ff03628B1` |
## What the SDK covers
The canonical address book (`AERE_MAINNET` in `src/addresses.ts`) maps 130+ live
contracts on chain 2800. On top of it the SDK ships 35 typed client classes (34
dedicated contract clients plus the `AereClient` facade, which itself wraps 8
core contracts), plus function-based PQC, wallet and MPC modules, grouped by
domain:
| Domain | Representative clients |
|---|---|
| Core L1 | `AereClient` (WAERE, locked + delegated staking V2, identity, faucet, AMM factory, bridge handles) |
| Flywheel | `sAEREClient` (ERC-4626 receipt vault, V2), `AereSinkClient` (immutable 3-bucket router) |
| DeFi | `LendingMarketClient`, `AereInsuranceFundClient`, `RWATransferAdapterClient`, `AereCoreBookClient` (native CLOB) |
| Rollup / RaaS | `AereRaaSFactoryClient`, `AereRollupSettlementClient` |
| Agentic (x402) | `AereAgentClient`, `AERE402SettlementClient`, `createAere402Middleware`, `AereAgentBondClient`, `AereAIReputationClient`, `AereInferNetClient`, `AereAgentMemoryVaultClient` |
| Compliance | `AereSanctionsRegistryClient`, `ChainalysisOracleWrapperClient`, `AereTravelRuleHashRegistryClient`, `AereForensicEventRegistryClient`, `AereZKScreenClient`, `AereAIProofClient`, `AereCompliancePoolClient`, `AereAttestationGatewayClient` |
| Payments | `AereStateChannelsClient` (bidirectional channels + HTLC), `BestExClient` (MiCA Article 78 receipts) |
| Post-quantum | `AerePQCClient`, `AerePQCKeyRegistryClient`, `AereAgentDIDClient`, `AereCryptoRegistryClient`, `AereHybridAuthorizerClient` |
| Account abstraction | `ModularAccountClient`, `SessionKeyClient`, `SocialRecoveryClient`, `AerePQCSocialRecoveryClient` (ERC-7579 modular accounts, bound to AereEntryPointV2) |
| PQC custody | `AereThresholdAccountClient` (non-custodial t-of-n post-quantum ERC-4337 account) |
| Seedless wallet | `wallet/` module (see below) |
Ownership is **not** uniform. The original 2026-05-07 core contracts (WAERE,
treasury, identity, faucet, and similar) are owned by the Foundation key
`0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3`. Many later corrected forks and
frontier primitives (the `*V2` redeploys, the PQC wave-1 contracts, the MPC and
interop primitives) are either **ownerless** or owned by the deployer key
`0xbeB3…6465`, and several are deployed **inert** (holding no value, not wired
live) pending a founder-supervised migration. Each entry in `src/addresses.ts`
documents its own owner, status and any deprecation. Do not assume a single owner
across the whole book.
## Post-quantum precompiles (5 live on mainnet)
Activated on chain 2800 at block 9,189,161. Address band `0x0AE1`..`0x0AE5`:
| Precompile | Scheme |
|---|---|
| `0x0AE1` | Falcon-512 (NIST) |
| `0x0AE2` | Falcon-1024 (NIST) |
| `0x0AE3` | ML-DSA-44 (Dilithium2, FIPS 204) |
| `0x0AE4` | SLH-DSA-SHA2-128s (SPHINCS+, FIPS 205) |
| `0x0AE5` | SHAKE256 |
`src/pqc` provides pure-JS keygen and internal-interface signing for all four
signature schemes, proven interoperable against the live precompiles
(`src/test/pqc-interop.test.ts`). Falcon-1024 and ML-DSA-44 signatures can be
recorded on-chain through `AerePQCAttestation`
(`0x465d9E3b476BF98Aa1393079e240Db5D2a9bEA6A`), which verifies each signature via
the matching precompile before storing it. AERE also ships extended EIP-2935
block-hash lookback (an 8191-block window) live on mainnet, used by the
canonical-binding validity anchors.
## Seedless hybrid PQC wallet
`src/wallet` implements a wallet with **no seed phrase**: a WebAuthn passkey is
the everyday factor and a NIST Falcon-512 co-owner is the quantum-durable root.
```ts
import {
createSeedlessAccount, generateFalconRoot, encryptFalconSecretKey,
upgradeToPostQuantum, buildUpgradeAttestation, signPqcAccountUserOp,
} from '@aere/sdk';
const descriptor = createSeedlessAccount({ passkey }); // pre-upgrade
const root = generateFalconRoot(); // Falcon-512 keypair
const enc = encryptFalconSecretKey(root, passphrase); // client-side-encrypted
const upgraded = upgradeToPostQuantum(descriptor, root.publicKey); // one-tap PQC
```
The Falcon root is verified by the on-chain `AereFalcon512Verifier` /
`AerePQCAttestation` path; the secret key is encrypted client-side and never
leaves the device unencrypted. See `docs/PQC-WALLET-DESIGN.md`.
## Post-quantum identity — one front door
The PQC pieces (Falcon root, key registry, agent DID, guardians) stitch into a
single flow. Three ready-made entry points:
- **End-to-end example** — `examples/pqc-identity-e2e.mjs`. One runnable script
that generates a Falcon-512 root, client-encrypts it, registers it with on-chain
proof-of-possession, opens an `AereAgentDID` with a revocable session key, and
sets a quantum-durable guardian committee. It is **read-only**: it reads live
chain state, **cross-checks the PoP / issuance / action challenges against the
on-chain views**, and prints the exact transactions each write flow would send —
nothing is signed with a funded key. Run:
```bash
npm run build && node examples/pqc-identity-e2e.mjs
```
- **Reference wallet dApp** — `pqc-wallet/` in the (not yet published) website source tree. A single
self-contained HTML page (no external CDN, all crypto bundled inline) that walks
the same flow in the browser against the live read-only RPC. Build it with
`node pqc-wallet/build.mjs`; the output is served at `/pqc-wallet.html`.
- **Project scaffolder** — `create-aere-pqc` (in the private working tree; not yet published).
Generates a wired-up wallet or agent project:
```bash
node aerenew/tools/create-aere-pqc/index.mjs my-pqc-wallet # or --template agent
cd my-pqc-wallet && npm install && npm run dev
```
The `AerePQCSocialRecoveryClient` guardian committee (M-of-N NIST PQC keys, 48h
timelock) uses the repo-shipped `AerePQCSocialRecoveryModule` contract; that module
is **not yet deployed to mainnet**, so those flows construct calldata and derive the
recovery challenge locally rather than reading a live module.
## Install
```bash
npm i @aere/sdk ethers
```
## Quickstart
```ts
import { AERE_MAINNET } from '@aere/sdk/addresses';
import { ethers } from 'ethers';
const provider = new ethers.JsonRpcProvider(AERE_MAINNET.rpc);
// Read a balance
const bal = await provider.getBalance(AERE_MAINNET.Foundation);
console.log(ethers.formatEther(bal), 'AERE');
// Subscribe to incoming WAERE transfers for an address
const waere = new ethers.Contract(
AERE_MAINNET.WAERE,
['event Transfer(address indexed from, address indexed to, uint256 value)'],
provider,
);
waere.on('Transfer', (from, to, value) => {
if (to.toLowerCase() === '0xMyHotWallet'.toLowerCase()) {
console.log(`got ${ethers.formatEther(value)} WAERE from ${from}`);
}
});
// Delegated stake 100 AERE via the canonical AereStakingV2 pool
const signer = new ethers.Wallet(process.env.PRIVATE_KEY!, provider);
const staking = new ethers.Contract(
AERE_MAINNET.AereStakingV2,
['function delegate(address validator) payable'],
signer,
);
const tx = await staking.delegate(validatorAddress, { value: ethers.parseEther('100') });
await tx.wait();
```
## CLI (`aere`)
The SDK ships a small, read-only developer CLI. After `npm i @aere/sdk` it is on
your path as `aere`; from a clone, build first (`npm run build`) and run
`node dist/cli/aere-cli.js <command>`.
Every command is **read-only or purely local**. The CLI never signs a real
transaction and never accepts a private key. Values are read live from the RPC
and printed verbatim; on an RPC or connection error it writes to stderr and exits
non-zero.
```bash
aere chain # chain id, block height, base fee, gas price, validators, peers
aere block <number|latest> # block summary: hash, parent, timestamp, tx count, gas, proposer
aere tx <hash> # transaction + receipt summary
aere addr <address> # native balance, nonce, and code size
aere pqc schemes # supported PQC schemes, precompiles, key/signature sizes
aere pqc keygen --scheme <1-4> # generate a PQC keypair locally (public key only)
```
Options:
| Option | Applies to | Meaning |
|---|---|---|
| `--rpc <url>` | all chain commands | RPC endpoint (default `https://rpc.aere.network`) |
| `--scheme <1\|2\|3\|4>` | `pqc keygen` | 1=Falcon-512, 2=Falcon-1024, 3=ML-DSA-44, 4=SLH-DSA-SHA2-128s |
| `--show-secret` | `pqc keygen` | also print the secret key. Dangerous, off by default |
| `--version`, `-V` | | print the SDK version |
| `--help`, `-h` | any | usage (also `aere <command> --help`) |
```bash
$ aere chain
AERE chain — https://rpc.aere.network
Chain ID 2800 (0xaf0)
Block height 22945693
Base fee 1.0 gwei (1000000000 wei)
Gas price 1.0 gwei (1000000000 wei)
Validators 10
- 0x38fb1510d4d11624564a74e6ebfd752e666849c3
...
```
(Output of 2026-10-15. Since block 20,836,228 the validator list holds post-quantum validator ids, not ECDSA addresses.)
## State window on the public RPC (read before pinning a historical block)
Both public endpoints are **pruning full nodes**, not archive nodes.
- Blocks, transactions, receipts, logs and `qbft_getValidatorsByBlockNumber` go back to **block 0**.
- **World state is kept for only about the most recent 512 blocks**, roughly 5 minutes 17 seconds
at the 0.62 s block interval measured on 2026-10-15. That bounds `eth_getBalance`, `eth_getCode`,
`eth_getStorageAt`, `eth_call`, `eth_getProof` and `eth_getTransactionCount`.
Outside the window both public endpoints now say so for every state method: measured on 2026-10-15,
`eth_getTransactionCount`, `eth_getBalance` and `eth_getProof` all return `-32000 World state unavailable`.
Until October 2026 they did not: `eth_getBalance` / `eth_getCode` / `eth_getStorageAt` returned `null`, and
**`eth_getTransactionCount` returned `0x0`**, well formed and indistinguishable from an account that has
never transacted (block 8,236,382 holds a transaction from `0xbeb33d20dfbbd49ec7ac1f617667f1f02dfd6465` with
nonce 123,063, and the endpoint answered `0x0` for that address at that block). Other endpoints and other
node versions may still answer that way, which is why the reader below keeps its guards.
`StateWindowReader` returns a value or throws. It never returns a placeholder.
```ts
import { StateWindowReader, StateWindowError } from '@aere/sdk';
const reader = new StateWindowReader((m, p) => provider.send(m, p));
await reader.getTransactionCount(addr); // latest: fine
await reader.getBalance(addr, head - 100); // inside the window: fine
try {
await reader.getTransactionCount(addr, 8_236_382); // throws, never returns 0
} catch (e) {
if (e instanceof StateWindowError) console.log(e.detail.reason);
}
// Has this account ever signed anything? Answered only where it can be answered.
await reader.hasEverSigned(addr); // { signed, nonce, atBlock, method }
// Do not trust the 512 constant, measure it against the endpoint you are using.
await reader.measureWindow(); // { head, deepestOkDepth: 511, firstFailDepth: 512 }
```
Three rules if you are not using the reader: read state at `latest`; check the depth before
pinning a historical block; and never test a nonce for zero at a historical block.
## Operational notes (honest state)
- **Non-custodial.** End users hold their own keys. Consumer apps (wallets, card programs)
can use Privy / Magic / Web3Auth to provision wallets via email/social, then
pass that signer into the SDK, or use the seedless PQC wallet above.
- **Fiat rails are out of scope.** AERE is the on-chain settlement layer; fiat
IBANs / cards / SEPA come from a BaaS partner (Striga, Baanx, Kulipa, etc.).
- **Decentralization.** 10 QBFT validators give f=3 (the chain keeps producing
blocks while up to 3 validators are down), commit quorum 7 of 10. All 10 are
operated by the Foundation; nine run the Besu-derived client and one, since
2026-09-11, the Nethermind-derived client. That is fault tolerance and a second
code base, not yet operator diversity: independent validator operators are roadmap.
- **Foundation key, not a multisig.** `0x0243A4f47D44b40b65D33f20329dE20D00c6f3C3`
is a single-key EOA (zero bytecode on-chain), described here as a
Foundation-controlled account. A real Safe-style threshold multisig is roadmap,
not deployed. Governance contracts (Governor + Timelock + gAERE) are deployed
but own nothing until an audit-gated ownership transfer runs.
- **Price oracle.** `AereOracleV2` enforces a minimum fresh-reporter quorum
(`getPrice` reverts below it) and supersedes the flawed V1, which returned a
median even with a single fresh reporter. The V1 contract stays the live read
source for existing consumers until a founder-supervised repoint. Treat the
live feed as single-reporter-grade until that repoint lands.
- **Cross-chain bridging is not yet value-carrying.** The legacy `AereBridge`
reports `threshold()` == 1 on-chain and has no operational relayer. The current
approach is the Hyperlane-based `AereWarpRouteV3`, whose AERE side is deployed
but whose Ethereum leg awaits L1 bring-up. Do not route value across the bridge
until threshold expansion and a relayer are live.
- **Audit status.** Contracts have had an internal self-audit (Slither, Aderyn,
Semgrep, Mythril, SMTChecker, Halmos, Medusa) and several confirmed findings
were fixed via the `*V2` corrected forks documented in `src/addresses.ts`. An
external third-party audit is still pending; do not read "audited" as external.
- **Validity anchors.** The full-EVM validity anchors (`AereEVMValidityV2`,
`AereEVMValidityBatchV2`) are deployed and canonical-bound but not yet
exercised on mainnet (`provenCount()` reads 0 for both).
## Roadmap (deployed but inert, or not yet live)
Several contracts are on-chain but inert (holding no value, not wired live)
pending a founder-supervised migration, and a few product surfaces are not yet
deployed. Representative items:
- Cross-chain relayer + Ethereum-side counterparties for the Warp Route / bridge
- A real Safe-style Foundation multisig, and the audit-gated governance ownership
transfer
- Multi-operator validator set and a second consensus client
- External third-party security audit
- Founder-supervised migrations for the `*V2` inert forks (sAEREv2, settlement
hub V2, delegate-7702 V2, and others; runbooks live under `aerenew/docs/`)
Each contract's exact status is documented inline in `src/addresses.ts`.
## Source
- SDK source: <https://git.aere.network/aere-network/sdk-js>
- Contract source: <https://git.aere.network/aere-network/aere-contracts> (published Solidity sources and tests; the full working tree is private)
- Website source: not published yet
## License
MIT