sdk-js/README.md

387 lines
21 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.14
**Last updated:** 2026-10-20 (deposit watching on post-quantum transactions; network facts, state window, client selectors 2026-10-15; the rest is as of 2026-07-16)
**0.16.14, 2026-10-20: `watchTransfersTo` reads post-quantum transactions.** Until this release it asked ethers for the block with
full transactions; ethers does not know the post-quantum transaction type 0x50 (AIP-20), so on a block carrying one (the first on chain
2800 is block 19,900,028) the handler threw, every deposit of that block was missed, and a deposit made with a post-quantum transaction
was never credited. The block is now read as the node serves it (`eth_getBlockByNumber`), and the filter is the exported
`transfersToFromRawBlock(block, addr)`, tested offline on the real transaction of that block (`src/test/transfers-raw-block.test.ts`).
**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, final on commit at the validators; since block 24,300,000 (AIP-22 stage 4) the Besu-derived validators count a vote only through its post-quantum seal, and a block is post-quantum final once the next anchor, at most 32 blocks later, carries the certificate that covers it (headers are still admitted on their ECDSA commit seals until AIP-22 stage 5); every 32nd block carries a post-quantum certificate whose digest sits under its hash (details on aere.network; corrected 2026-10-28: this row said per-block finality on classical secp256k1 ECDSA commit seals) |
| 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` |
| Data API (recent blocks and transactions, no indexed history) | `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 QBFT with post-quantum layers on top of it, each dated
(headers are still admitted on their ECDSA commit seals until AIP-22 stage 5).** Blocks are proposed and committed
by ten Foundation validators since 2026-09-11 (quorum 7 of 10, f=3; nine, quorum 6 of 9, f=2,
until then): nine run the Besu-derived client, and the tenth, since 2026-09-11, a second,
Nethermind-derived client that proposes and seals blocks (its public read endpoint is
client2.aere.network). Since block 13,014,000 every anchor block carries a certificate of
validator post-quantum seals whose 32-byte digest sits under the block hash, and since block
20,715,632 (2026-09-29) a node rejects an anchor block with fewer than seven valid seals per
scheme, as many as the quorum (three, f+1 of nine, from 2026-08-14; six from 2026-08-21); from
block 24,148,752 (AIP-22 stage R) a certificate that carries the quorum of one round proves the
decision. Every validator refuses a commit without a valid Falcon-512 seal of its author, and
since block 24,300,000 (AIP-22 stage 4, 2026-10-25) the Besu-derived validators count a
consensus vote only through the verified post-quantum seal of its author. Aere does not claim
post-quantum consensus: the transport between nodes is still authenticated by secp256k1, the
ten validators are run by one operator, and no third party has audited the system. (Corrected
2026-10-28: until that date this paragraph described the network of August 2026 at the present
tense: classical ECDSA on every block, nine validators, a minimum of three seals per anchor and
a second client that does not produce blocks. A per-block post-quantum quorum claimed on
2026-08-15 was withdrawn on 2026-08-19.)
- **PQC lives at the application layer.** Five NIST post-quantum precompiles are live on
mainnet (see below), four signature verifiers and the SHAKE256 hash (corrected 2026-10-28: this
called all five verification precompiles). 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