# Aje Domain — Technical Specifications

> Technical specifications for the Aje blockchain and Web3 infrastructure
> domain: library inventory, core data models, type definitions, cryptographic
> standards, persistence schemas, and configuration. Every type, schema, and
> enum documented here is taken directly from `libs/aje/*` source.

---

This document is the authoritative type reference for the Aje domain. Where the
features document explains _what_ Aje does in human terms, this document
specifies _exactly how_ it does it: the TypeScript types, Zod schemas,
PostgreSQL DDL, enum values, and function signatures that new engineers need
when integrating with or extending Aje libraries.

The sections are ordered from the most foundational (`@aje/core` primitives)
outward through the chain provider layer, RPC client, wallet specs, account
abstraction, persistence layer, V2 game integrations, and configuration.
Cross-domain integration points are documented at the end.

---

## Domain Scope

Aje is a **library-only** domain. It has no `apps/` and no `services/` —
`ls apps/aje services/aje` returns nothing. It ships **31 packages** under
`libs/aje/*`, each a private `@aje/*` workspace package (`version: 0.1.0`,
ESM-only, `"type": "module"`).

The domain produces composable TypeScript primitives for multi-chain blockchain
work. One package (`@aje/settlement-escrow`) integrates with the Concordia
domain; one set of consumers (`@v2/aje-web3-cosmetic-ownership`,
`@v2/aje-faction-governance`) lives in the V2 game project. There is **no
event-bus integration** in any Aje package — no domain library imports
`@oshun/event-bus`, and no Aje package publishes Kafka/Redis-Stream events.

---

## Technology Stack

| Layer        | Technology                                                                                       |
| ------------ | ------------------------------------------------------------------------------------------------ |
| Language     | TypeScript (ESM, `"type": "module"`)                                                             |
| Runtime      | Node.js (uses `node:crypto` for AES; otherwise pure-JS)                                          |
| Cryptography | `@noble/hashes`, `@noble/curves`, `@scure/base`, `@scure/bip32`, `@scure/bip39`, `@oshun/crypto` |
| Persistence  | Raw SQL DDL via `@oshun/database` (`sqlRaw`, `ParameterizedQuery`) on PostgreSQL                 |
| Build/Test   | Nx + Vitest (`vitest` from the pnpm catalog)                                                     |

**Cryptographic policy**: cryptographic operations use the audited `@noble` and
`@scure` libraries plus the workspace `@oshun/crypto` package. The
encrypted-keystore module additionally uses Node's built-in `node:crypto` for
AES-128-CTR. No custom curve or hash implementations exist in the domain.

---

## Library Inventory

All 31 packages, grouped by role. Names and dependencies are from each package's
`package.json`.

### Foundation

| Package         | Role                                                                                                          |
| --------------- | ------------------------------------------------------------------------------------------------------------- |
| `@aje/core`     | Addresses, transactions, blocks, BigNumber, crypto, ABI/RLP, events, Merkle trees, network config, errors     |
| `@aje/chains`   | Per-chain providers (Ethereum, Arbitrum, Optimism, zkSync, Polygon, Avalanche, Cardano, Solana) + abstraction |
| `@aje/rpc`      | `OshunRpcClient` — multi-chain JSON-RPC client with retry, fallback, fan-out, rate limiting                   |
| `@aje/database` | PostgreSQL DDL + query builders for chain/wallet/DeFi data; block indexer; ORM-schema generator               |

### Wallets and accounts

| Package                    | Role                                                                                                                                    |
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `@aje/wallets`             | HD wallets, MPC/TSS, key management, account abstraction, hardware, institutional, social login, WalletConnect, paymaster, session keys |
| `@aje/account-abstraction` | EIP-7702, ERC-7715, ERC-7579, ERC-6900, advanced AA infrastructure                                                                      |

### DeFi and finance

| Package            | Role                                                                                             |
| ------------------ | ------------------------------------------------------------------------------------------------ |
| `@aje/defi`        | AMM, Uniswap, Curve, lending, liquid staking, yield, derivatives, Cardano/Avalanche DeFi, safety |
| `@aje/payments`    | Stablecoins, Circle, fiat ramps, merchant, streaming payments, CBDC                              |
| `@aje/oracles`     | Chainlink (feeds, VRF, automation, functions), Pyth, RedStone, API3, custom oracle               |
| `@aje/predictions` | Polymarket, prediction-market contracts, resolution oracles, market making, analytics            |
| `@aje/restaking`   | EigenLayer, AVS, liquid restaking tokens                                                         |

### Assets

| Package        | Role                                                                                                              |
| -------------- | ----------------------------------------------------------------------------------------------------------------- |
| `@aje/nft`     | ERC-721, ERC-721A, ERC-1155, token-bound accounts, soulbound, dynamic, marketplace, Cardano NFT, metadata, AI NFT |
| `@aje/rwa`     | Security tokens, treasury tokenization, real estate, commodities, compliance, Chainlink RWA                       |
| `@aje/storage` | IPFS, Filecoin, Arweave, hybrid storage, NFT storage                                                              |

### Protocol

| Package           | Role                                                                                                               |
| ----------------- | ------------------------------------------------------------------------------------------------------------------ |
| `@aje/contracts`  | Compilation, deployment, upgradeable proxies, OpenZeppelin, hooks, testing, fuzzing, Aiken, docs, gas optimization |
| `@aje/bridges`    | LayerZero, Wormhole, CCIP, Axelar, custom bridge, Avalanche Warp, bridge security, aggregation                     |
| `@aje/intents`    | Intent expression, solvers, CoW Protocol, UniswapX, Across, Essential                                              |
| `@aje/governance` | Governor, voting, Snapshot, Tally, treasury, Aragon, Cardano governance                                            |
| `@aje/identity`   | DID, verifiable credentials, ENS, Lens, Farcaster, aggregation                                                     |

### Infrastructure

| Package         | Role                                                                                                       |
| --------------- | ---------------------------------------------------------------------------------------------------------- |
| `@aje/nodes`    | RPC provider management, full node, Avalanche node, Cardano node, light client, validator                  |
| `@aje/security` | Static analysis, formal verification, MEV protection, runtime protection, audit tooling, incident response |
| `@aje/zkp`      | SNARKs, Circom, STARKs, privacy circuits, Semaphore, ZKML, rollups, gnark, Plonky, ZK identity             |
| `@aje/privacy`  | Privacy pools, advanced privacy (FHE/MPC/TEE patterns)                                                     |

### Ecosystem

| Package          | Role                                                                                         |
| ---------------- | -------------------------------------------------------------------------------------------- |
| `@aje/bitcoin`   | Lightning, BTCPay, LSP, Lightning apps, Stacks, sBTC, BitVM, Ordinals, Runes, RGB, other L2s |
| `@aje/sui-move`  | Sui network, Move language, Sui DeFi, Aptos                                                  |
| `@aje/appchains` | Conduit, Caldera, AltLayer, data availability, sequencer, config                             |
| `@aje/gaming`    | MUD, World Engine, game assets, game economy, autonomous worlds, gaming L2s                  |
| `@aje/depin`     | Compute, wireless, IoT, location, energy, storage, rewards DePIN networks                    |
| `@aje/agents`    | Agent wallets, execution, communication, x402 micropayments, AI, frameworks, safety          |

### SDK and settlement

| Package                  | Role                                                                                 |
| ------------------------ | ------------------------------------------------------------------------------------ |
| `@aje/sdk`               | `core`, `react`, `python`, `cli`, `docs` sub-modules — composition layer and tooling |
| `@aje/settlement-escrow` | Maps Concordia `escrow_release` clauses to chain-ready Aje escrow deployment plans   |

---

## Dependency Hierarchy

`@aje/core` declares only `@oshun/types` as an **optional** peer dependency.
Most domain packages declare `@aje/core` as a peer; packages that need chain
interaction additionally declare `@aje/chains` as a peer. Most packages also
depend on the workspace `@oshun/crypto` package and on `@noble/*` / `@scure/*`
crypto libraries directly.

```
@aje/sdk (composition layer: core / react / python / cli / docs)
        │
        ├── peer: @aje/core, @aje/chains
        │
@aje/wallets, @aje/defi, @aje/nft, @aje/contracts, @aje/oracles, @aje/rwa, …
        │
        ├── peer: @aje/core  (+ @aje/chains where chain access is needed)
        │
@aje/chains ── peer: @aje/core
        │
@aje/core ── optional peer: @oshun/types ;  deps: @noble/*, @scure/*, @oshun/crypto
```

Notable exceptions:

- `@aje/rpc` has **no dependencies and no peers** — it is fully self-contained.
- `@aje/settlement-escrow` depends on `@concordia/contracts` and `zod`; it does
  **not** depend on `@aje/core`.
- `@aje/database` declares peers `@aje/core` and `@oshun/database` and has no
  runtime `dependencies`.
- `@aje/chains` additionally depends on `abstract-level`, `classic-level`, and
  `memory-level` (LevelDB-family stores).

---

## Core Data Types (`@aje/core`)

`@aje/core` is the foundational package that all other Aje libraries build on.
It is barrel-exported from `src/index.ts` across nine areas: addresses,
transactions, BigNumber, blocks, crypto, ABI, events, Merkle trees, network
config, and errors. The subsections below document each area's public types in
detail.

### Addresses (`src/addresses/types.ts`)

Address handling is chain-discriminated: every address carries metadata about
which chain it belongs to, preventing silent cross-chain address misuse (e.g.
accidentally sending an EVM address to a Solana program). The `Chain` union
enumerates all supported chains; `EvmChain` is the EVM-compatible subset used
where only EVM chains are relevant.

```typescript
type Chain =
  | 'ethereum'
  | 'bitcoin'
  | 'cardano'
  | 'avalanche'
  | 'solana'
  | 'polygon'
  | 'arbitrum'
  | 'optimism'
  | 'base'
  | 'bsc'
  | 'avalanche-x'
  | 'avalanche-p'
  | 'avalanche-c';

type EvmChain =
  | 'ethereum'
  | 'polygon'
  | 'arbitrum'
  | 'optimism'
  | 'base'
  | 'bsc'
  | 'avalanche-c';
```

Each chain further defines its own address format variants as literal string
unions:

Chain-specific literal unions:

- `BitcoinAddressType` — `'p2pkh' | 'p2sh' | 'bech32' | 'bech32m'`
- `BitcoinNetwork` — `'mainnet' | 'testnet' | 'regtest'`
- `CardanoAddressType` —
  `'base' | 'pointer' | 'enterprise' | 'reward' | 'bootstrap' | 'byron'`
- `CardanoNetwork` — `'mainnet' | 'testnet' | 'preview' | 'preprod'`
- `AvalancheChainPrefix` — `'X' | 'P' | 'C'`

The universal `Address<M>` generic wraps every supported address format in the
same shape. The `meta` field is a discriminated union (`AddressMeta`) that
narrows to the chain-specific metadata type, so consumers can inspect checksum
status, address type, witness version, stake key hash, and so on without losing
type safety.

| Type                   | Fields                                                                    |
| ---------------------- | ------------------------------------------------------------------------- |
| `Address<M>`           | `raw: string`, `bytes: Uint8Array`, `meta: M`                             |
| `EthereumAddressMeta`  | `chain: EvmChain`, `isChecksum: boolean`, `isContract?: boolean`          |
| `BitcoinAddressMeta`   | `chain: 'bitcoin'`, `addressType`, `network`, `witnessVersion?: number`   |
| `CardanoAddressMeta`   | `chain: 'cardano'`, `addressType`, `network`, `stakeKeyHash?: Uint8Array` |
| `AvalancheAddressMeta` | `chain: 'avalanche-x'\|'-p'\|'-c'`, `chainPrefix`, `hrp: string`          |
| `SolanaAddressMeta`    | `chain: 'solana'`, `isOnCurve: boolean`, `isProgramDerived?: boolean`     |

Supporting types: `AddressBookEntry`, `DerivationPath` (BIP-44: `purpose`,
`coinType`, `account`, `change`, `index`), `DomainResolution`, `DomainResolver`,
`Create2Params` (`deployer`, `salt`, `initCodeHash`). Type guards include
`isEthereumAddress`, `isBitcoinAddress`, `isCardanoAddress`,
`isAvalancheAddress`, `isSolanaAddress`, `isEvmChain`.

### Transactions (`src/transactions/types.ts`)

The transaction types model the lifecycle and wire format of transactions across
all supported chains. `TransactionStatus` tracks where a transaction is in its
lifecycle, from initial submission through eventual finality or failure:
`'pending' | 'submitted' | 'confirmed' | 'failed' | 'dropped' | 'replaced'`.

Ethereum has four distinct transaction formats, each introduced by a different
EIP. `EthTransactionType` — `'legacy' | 'eip2930' | 'eip1559' | 'eip4844'`. The
`EthereumTransaction` union has one interface per type, ensuring that fee fields
specific to each format (e.g. `maxFeePerBlobGas` for EIP-4844) are only present
on the correct variant:

| Interface            | Discriminant `type` | Notable fields                                       |
| -------------------- | ------------------- | ---------------------------------------------------- |
| `LegacyTransaction`  | `'legacy'`          | `gasPrice`, `chainId?`                               |
| `Eip2930Transaction` | `'eip2930'`         | `gasPrice`, `accessList: AccessListEntry[]`          |
| `Eip1559Transaction` | `'eip1559'`         | `maxFeePerGas`, `maxPriorityFeePerGas`, `accessList` |
| `Eip4844Transaction` | `'eip4844'`         | `maxFeePerBlobGas`, `blobVersionedHashes: string[]`  |

All extend `UnsignedTransaction<C extends Chain>` (`chain`, `type`, `nonce?`,
`data?`, `value?`). `AccessListEntry` is `{ address, storageKeys }`.

Non-EVM transaction types:

- `CardanoTransaction` (`type: 'utxo'`) — `inputs: CardanoUtxoInput[]`,
  `outputs: CardanoTxOutput[]`, `fee`, `ttl?`, `validityStart?`,
  `certificates?`, `withdrawals?`, `metadata?`, `mint?`, `collateral?`,
  `requiredSigners?`, `scriptDataHash?`. Values use `CardanoValue`
  (`lovelace: bigint`, optional nested `multiAsset` maps).
- `AvalancheAtomicTransaction` (`type: 'atomic'`) — `sourceChain`/
  `destinationChain` ∈ `'X'|'P'|'C'`, `inputs: AvalancheTransferableInput[]`,
  `outputs: AvalancheTransferableOutput[]`, `memo?`.

Result and envelope types:

- `SignedTransaction<T>` — `transaction`, `signature`, `hash`, `rawSerialized`
- `TransactionSignature` — `r`, `s`, `v?`, `yParity?`, `publicKey?`
- `TransactionReceipt` — normalized across chains: `chain`, `hash`, `blockHash`,
  `blockNumber`, `transactionIndex`, `from`, `to`,
  `status: 'success' | 'reverted'`, `gasUsed`, `effectiveGasPrice`,
  `cumulativeGasUsed`, `logs: TransactionLog[]`, `contractAddress`,
  `blobGasUsed?`, `blobGasPrice?`
- `TransactionLog`, `TransactionSimulation` (`success`, `gasUsed`,
  `returnData?`, `error?`, `revertReason?`, `logs`, `stateChanges?`),
  `StateChange`, `ReplacementConfig`, `TransactionBundle`

### BigNumber (`src/bignum/types.ts`)

On-chain token amounts are integers denominated in the token's smallest unit
(e.g. wei for ETH, lovelace for ADA). Using floating-point arithmetic for these
values would introduce rounding errors that could be financially significant.
Accordingly, all on-chain amounts in Aje use `bigint`; no floating point.

- `TokenAmount` — `{ value: bigint; decimals: number }`
- `FixedPoint` — `{ value: bigint; scale: number }` (real value
  `= value / 10^scale`)
- `CurrencyUnit` — `{ name, symbol, decimals, smallestUnit, chain? }`
- `RoundingMode` — `'floor' | 'ceil' | 'round' | 'trunc'`

Pre-configured `CurrencyUnit` constants: `ETH_UNIT`, `ADA_UNIT`, `AVAX_UNIT`,
`SOL_UNIT`, `USDC_UNIT`, `USDT_UNIT`, `BTC_UNIT`, `WBTC_UNIT`, `DAI_UNIT`.
Factory/utility functions: `tokenAmount`, `fixedPoint`, `currencyUnit`,
`tokenAmountToFixedPoint`, `fixedPointToTokenAmount`, `tokenAmountsEqual`,
`compareTokenAmounts` (the last two throw if `decimals` differ).

### Blocks (`src/blocks/types.ts`)

Different blockchains identify and structure blocks in fundamentally different
ways — Ethereum uses block numbers, Cardano uses slots within epochs, and
Avalanche uses heights within subnets. The block types in `@aje/core` provide a
unified layer over these differences while still exposing chain-specific fields
where necessary.

`BlockHeight` (`height`, optional `epoch`, `slotInEpoch`) abstracts block number
/ Cardano slot / Avalanche height. `BlockTag` —
`'latest' | 'earliest' | 'pending' | 'safe' | 'finalized'`. `BlockIdentifier` is
a discriminated union of `{type:'number'}`, `{type:'tag'}`, `{type:'hash'}`.

Consensus proofs (`ConsensusProof` union): `ProofOfWork` (`nonce`, `mixHash`,
`difficulty`, `totalDifficulty?`), `ProofOfStake` (`proposer`, `slot?`,
`epoch?`, `attestationCount?`, `randaoReveal?`), `DelegatedProofOfStake`
(`delegate`, `round?`, `isElected`, `delegatedStake?`).

Headers: `BlockHeader<P>` base plus `EthereumBlockHeader` (EIP-1559
`baseFeePerGas?`, EIP-4844 `blobGasUsed?`/`excessBlobGas?`/
`parentBeaconBlockRoot?`, `withdrawalsRoot?`), `CardanoBlockHeader` (`poolId`,
`operationalCertificate?`, `protocolVersion`), `AvalancheBlockHeader`
(`subChain`, `chainId`, `blockSize`). Blocks: `Block<H>`, `EthereumBlock`
(`uncles`, `withdrawals?`, `blobSidecars?`), `CardanoBlock`, `AvalancheBlock`.

EIP-4844 blob types: `Blob` (`data` 128 KiB, `kzgCommitment` 48 B, `kzgProof` 48
B), `BlobSidecar`, `BlockBlobSidecars`. Genesis types: `GenesisAllocation`,
`GenesisConfig`, `GenesisChainConfig` (per-fork activation blocks from Homestead
through Cancun). `Withdrawal` (post-Shanghai). Constructor helpers:
`blockHeight`, `blockByNumber`, `blockByTag`, `blockByHash`.

### Network configuration (`src/network/types.ts`, `src/network/chains.ts`)

`ChainId = number`. `NetworkType` —
`'mainnet' | 'testnet' | 'devnet' | 'local'`. `ConsensusType` —
`'pow' | 'pos' | 'dpos' | 'poa' | 'pbft'`.

`ChainConfig` carries `chainId`, `name`, `networkType`, `consensus`,
`nativeCurrency`, `rpcEndpoints`, `blockExplorers`, optional `forks`,
`averageBlockTime`, `confirmations`, `isEvm`, and `parent`
(`{ chainId, type: 'L2' | 'sidechain' | 'subnet' }`). Supporting types:
`NativeCurrency`, `BlockExplorer`, `RpcEndpoint`, `GasPriceOracle`, `FeeData`,
`HardFork`, `NetworkHealth`, `NetworkHealthMonitor`.

Pre-built `ChainConfig` constants in `chains.ts`: `ETHEREUM_MAINNET` (1),
`ETHEREUM_SEPOLIA` (11155111), `POLYGON_MAINNET` (137), `ARBITRUM_ONE` (42161),
`OPTIMISM` (10), `BASE_MAINNET` (8453), `BSC_MAINNET` (56), `AVALANCHE_C_CHAIN`
(43114), aggregated in the `CHAINS` record. Helper functions:
`estimateConfirmationTime`, `isEip1559Chain`, `suggestPriorityFee`.

### ABI (`src/abi/types.ts`)

`SolidityType` is a string template union covering `address`, `bool`, `string`,
`bytes`, `bytes1`–`bytes32`, `uint8`–`uint256`, `int8`–`int256`, `tuple`, plus a
string catch-all for array types.

ABI items: `ABIFunction`, `ABIEvent`, `ABIError`, `ABIConstructor`,
`ABIFallback`, `ABIReceive` (union `ABIItem`; `ABI = readonly ABIItem[]`).
`ABIFunction.stateMutability` ∈ `'pure' | 'view' | 'nonpayable' | 'payable'`.
`ABIParameter` carries `name`, `type`, optional `indexed`, nested `components?`,
`internalType?`. `ABITypeCategory` — `'static' | 'dynamic'`. Decoded shapes:
`DecodedParameter`, `DecodedEventLog`, `DecodedError`. `HumanReadableABI` is a
signature-string alias. The module also provides RLP encoding
(`src/abi/rlp.ts`), an encoder, decoder, and parser.

### Events (`src/events/types.ts`)

`EventLog` (full log: `address`, `topics`, `data`, `blockNumber`, `blockHash`,
`transactionHash`, `transactionIndex`, `logIndex`, `removed`),
`DecodedEvent<T>`, `EventFilter`, `EventSubscription`, `EventCallback<T>`,
`EventProvider`, `TransferEvent`, `ApprovalEvent`, `PaginatedEventQuery`,
`PaginatedEventResult`.

> These are blockchain log-event types — they describe on-chain event logs, not
> a service event bus. Aje publishes no inter-domain messages.

### Errors (`src/errors/types.ts`)

Precise error handling is critical in a financial domain — catching a generic
`Error` and retrying blindly can double-spend, whereas catching a specific
`RateLimitError` and backing off is the correct behavior. The error module
provides two numeric enums for well-known error codes, plus a typed class
hierarchy rooted at `BlockchainError`.

`RpcErrorCode` maps the numeric codes from the JSON-RPC 2.0 spec and the
Ethereum provider spec to named constants. The standard JSON-RPC 2.0 range
covers `PARSE_ERROR = -32700` through `INTERNAL_ERROR = -32603`; the server
range covers `-32000` through `-32006`; and the Ethereum EIP-1474/1193 provider
codes add `USER_REJECTED_REQUEST = 4001`, `UNAUTHORIZED = 4100`,
`UNSUPPORTED_METHOD = 4200`, `DISCONNECTED = 4900`, `CHAIN_DISCONNECTED = 4901`.

`PanicCode` maps the numeric panic codes that Solidity emits when an assertion
fails, to named constants: `ASSERT_FAILURE = 0x01`,
`ARITHMETIC_OVERFLOW = 0x11`, `DIVISION_BY_ZERO = 0x12`,
`ENUM_CONVERSION_OUT_OF_RANGE = 0x21`, `STORAGE_ENCODING_ERROR = 0x22`,
`POP_EMPTY_ARRAY = 0x31`, `ARRAY_OUT_OF_BOUNDS = 0x32`,
`MEMORY_OVERFLOW = 0x41`, `ZERO_INITIALIZED_FUNCTION = 0x51`.

The error class hierarchy gives consuming code fine-grained catch targets. All
classes are rooted at `BlockchainError` (`code: number`, `chainId?`,
`details?`):

| Class                    | Extends            | Extra fields                       |
| ------------------------ | ------------------ | ---------------------------------- |
| `BlockchainError`        | `Error`            | `code`, `chainId?`, `details?`     |
| `TransactionError`       | `BlockchainError`  | `txHash?`                          |
| `RpcError`               | `BlockchainError`  | `rpcCode`, `data?`                 |
| `ValidationError`        | `BlockchainError`  | `field?`, `value?`                 |
| `ContractError`          | `BlockchainError`  | `contractAddress?`, `method?`      |
| `NetworkError`           | `BlockchainError`  | `url?`                             |
| `AuthenticationError`    | `BlockchainError`  | (code `UNAUTHORIZED`)              |
| `InsufficientFundsError` | `TransactionError` | `required?`, `available?`          |
| `NonceError`             | `TransactionError` | `expectedNonce?`, `providedNonce?` |
| `GasEstimationError`     | `TransactionError` | `gasLimit?`                        |
| `RevertError`            | `ContractError`    | `reason?`, `decodedData?`          |
| `PanicError`             | `ContractError`    | `panicCode: PanicCode`             |

`RetryStrategy` config: `maxRetries`, `baseDelay`, `maxDelay`,
`backoffMultiplier`.

### Cryptography (`src/crypto/`)

`@aje/core` re-exports the full audited cryptographic surface used across Aje.
All functions delegate to `@noble/*`, `@scure/*`, or Node's `node:crypto` — no
custom implementations. The exports cover hashing, signing, encryption, key
derivation, and the types that go with them. Hashing: `keccak256`, `sha256`,
`sha512`, `blake2b`, `ripemd160`, `hash160Hex`, `doubleSha256`, `hashMessage`,
EIP-712 helpers (`encodeType`, `typeHash`, `hashTypedData`). Signatures:
secp256k1 (`secp256k1Sign`/`Verify`/`GetPublicKey`, `ecrecover`,
`ecrecoverAddress`), ed25519, BLS12-381 (`bls12381Sign`/`Verify`/
`GetPublicKey`/`AggregateSignatures`), Schnorr. Encryption: `aesGcmEncrypt`/
`Decrypt`, ECIES, `pbkdf2`, `scryptDerive`. Mnemonics/HD: `generateMnemonic`,
`validateMnemonic`, `mnemonicToSeed`, `hdKeyFromSeed`, `deriveHDKey`,
`DERIVATION_PATHS`, `HARDENED_OFFSET`. Crypto types: `PoseidonHasher`,
`EIP712Domain`, `EIP712Types`, `EIP712TypedData`, `Secp256k1Signature`,
`Ed25519Signature`, `SchnorrSignature`, `AesGcmEncrypted`, `EciesEncrypted`,
`ScryptOptions`, `Argon2Options`, `MnemonicStrength`, `HDKeyNode`.

---

## Multi-Chain Provider Layer (`@aje/chains`)

`@aje/chains` is structured as one named namespace per chain, each containing
the provider, RPC client, gas estimator, bridge/messaging helpers, and any
chain-specific modules. For example, the `ethereum` namespace has `flashbots.ts`
and `multicall.ts`; the `solana` namespace has `jito.ts`, `program.ts`, and
`token.ts`; the `cardano` namespace has `plutus.ts`, `hydra.ts`, and
`governance.ts`; and the `polygon` namespace also exports `linea`, `scroll`, and
`starknet`. The top-level package re-exports these via `export * as ethereum`,
`export * as arbitrum`, etc., plus `export * as abstraction`.

### Chain abstraction interface (`src/abstraction/types.ts`)

The abstraction namespace defines the `ChainProvider` interface that every chain
module must implement. This is what application code uses when it doesn't need
to know which specific chain it's talking to — the interface provides a
consistent API for block queries, balance lookups, transaction submission, and
health checks regardless of the underlying chain.

`ChainType` — `'evm' | 'cardano' | 'solana' | 'avalanche-x' | 'avalanche-p'`.
`ChainId` here is a **string** (e.g. `"ethereum:1"`, `"solana:mainnet-beta"`),
distinct from the numeric `ChainId` in `@aje/core/network`.

`ChainProvider` is the unified adapter interface every chain module implements:

```typescript
interface ChainProvider {
  readonly chain: ChainInfo;
  readonly capabilities: ChainCapabilities;
  getBlockHeight(): Promise<bigint>;
  getBalance(address: string): Promise<bigint>;
  getNonce(address: string): Promise<bigint>;
  estimateGas(tx: UnifiedTransactionRequest): Promise<GasEstimate>;
  sendTransaction(signedTx: string): Promise<string>;
  getTransactionReceipt(
    txHash: string
  ): Promise<UnifiedTransactionReceipt | null>;
  getLogs(query: LogQuery): Promise<readonly UnifiedLog[]>;
  healthCheck(): Promise<ProviderHealthStatus>;
  destroy(): void;
}
```

Supporting types: `ChainInfo`, `NativeCurrency`, `ChainCapabilities` (feature
flags: `smartContracts`, `nativeMultiAsset`, `accountAbstraction`, `l2Bridge`,
`zkProofs`, `utxoModel`, `eip1559`, `eip4844`, `websocketSubscriptions`,
`staking`, `governance`, `crossChainMessaging`, `custom[]`),
`ChainProviderConfig`, `UnifiedTransactionRequest`, `GasSpeed`
(`'slow' | 'standard' | 'fast'`), `GasEstimate`, `GasSpeedEstimate`,
`UnifiedTransactionReceipt`, `UnifiedLog`, `EventFilter`, `LogQuery`,
`EventSubscription`, `BalanceQuery`, `BalanceResult`, `NameSystem`
(`'ens' | 'unstoppable' | 'ada-handle' | 'sns' | 'custom'`), `ResolvedAddress`,
`AddressValidation`, `ProviderHealthStatus`, `AggregatedHealthStatus`,
`NonceState`, `ChainSwitchResult`, `MultiChainBatch`, `BatchStatus`
(`'pending' | 'submitting' | 'partial' | 'completed' | 'failed'`),
`BatchTransactionResult`, `OptimizationHint`, `OptimizationCategory`,
`MigrationPlan` / `MigrationStep` / `MigrationStepType` / `MigrationStepStatus`
/ `MigrationStatus`, `FallbackConfig`, `RpcEndpointState`. The abstraction
package also ships `chain-registry.ts`, `transaction-builder.ts`,
`address-resolver.ts`, and `unified-provider.ts`.

---

## RPC Client (`@aje/rpc`)

`@aje/rpc` is the only Aje package with no dependencies and no peers. It is
fully self-contained by design: any environment that can import an ESM module
can use it without pulling in the rest of the Aje stack. It provides
`OshunRpcClient` — a multi-chain JSON-RPC client with retry, fallback, fan-out,
rate limiting, nonce management, gas estimation, and typed confirmation helpers.
Public exports (`src/index.ts`):

- **Client**: `OshunRpcClient`, `HttpTransport`
- **Providers** (`src/providers/`): `EthereumRpcProvider`, `BitcoinRpcProvider`,
  `AvalancheRpcProvider`, `SolanaRpcProvider`
- **Errors**: `RpcError`, `RpcExhaustedError`, `RpcMethodError`,
  `RpcNetworkError`, `RpcParseError`, `RpcQuorumError`, `RpcRateLimitError`,
  `RpcTimeoutError`
- **Rate limiting**: `createRateLimiter`, `NoopRateLimiter`, `RateLimiter`
- **Retry**: `DEFAULT_RETRY_POLICY`, `mergeRetry`, `withRetry`
- **Nonce**: `NonceManager`, `NonceLease`, `NonceManagerOptions`
- **Gas**: `GasEstimator`, `GasEstimate`, `EstimateOptions`, `EvmChain`
- **Confirmations**: `getConfirmationPolicy`, `getConfirmationDepth`,
  `waitForEthereumConfirmation`, `waitForBitcoinConfirmation`,
  `waitForSolanaConfirmation`, with `ConfirmationLevel`, `ConfirmationPolicy`,
  `ConfirmationChain`, `ConfirmationResult`, `WaitOptions`

### Key types (`src/types.ts`)

The types below govern how requests are constructed, how failures are
classified, and how retry/fallback behavior is configured. Understanding
`RpcFailureKind` in particular is important: it determines which failure
categories are retried versus propagated immediately.

- `JsonRpcRequest` / `JsonRpcSuccessResponse<T>` / `JsonRpcErrorResponse` /
  `JsonRpcErrorBody` — JSON-RPC 2.0 envelopes for Ethereum, Avalanche EVM,
  Solana. `BitcoinRpcRequest` models Bitcoin Core's JSON-RPC 1.0 dialect.
- `RpcFailureKind` —
  `'network' | 'rate-limit' | 'rpc-error' | 'timeout' | 'parse'`. Distinguishes
  retry/fallback behavior.
- `RetryPolicy` — `maxRetries`, `baseDelayMs`, `maxDelayMs`,
  `backoffMultiplier`, `jitter` (±ratio), `retryOn: RpcFailureKind[]`. Defaults:
  3 retries, 100 ms base, 10 s max, ×2, 0.25 jitter; retries network +
  rate-limit + timeout.
- `RpcSendOptions` — per-call overrides: `timeoutMs?`, `retry?`, `fallback?`,
  `fanOut?`, `traceId?`, `signal?` (`AbortSignal`).
- `FallbackStrategy`, `FanOutStrategy` — multi-endpoint walking and fan-out.
- `EndpointConfig`, `OshunRpcClientOptions`, `RateLimit`, `RpcCallResult`,
  `RpcTransport`, `RequestHook`, `ResponseHook`.

---

## Wallet Specifications (`@aje/wallets`)

`@aje/wallets` is organised as ten sub-modules, each covering a distinct aspect
of wallet management: `hd-wallet`, `mpc`, `key-management`,
`account-abstraction`, `hardware-wallet`, `institutional`, `social-login`,
`wallet-connect`, `paymaster`, and `session-keys`. The subsections below
document the key types from the three most foundational sub-modules.

### HD wallets (`src/hd-wallet/types.ts`)

`MnemonicStrength` — `128 | 160 | 192 | 224 | 256` (entropy bits).
`MnemonicWordCount` — `12 | 15 | 18 | 21 | 24`. `DerivationStandard` —
`'bip44' | 'bip84' | 'bip86' | 'cip1852' | 'custom'`. `ExtendedKeyType` —
`'xpub' | 'xprv' | 'ypub' | 'yprv' | 'zpub' | 'zprv'`. `ChainType` (HD-wallet
flavour) —
`'bitcoin' | 'ethereum' | 'cardano' | 'solana' | 'avalanche' | 'polygon' | 'bnb' | 'cosmos' | 'polkadot' | 'litecoin'`.

Core types: `Mnemonic` (`phrase`, `wordCount`, `language`, `entropy`),
`MnemonicGenerationOptions`, `MnemonicValidationResult`, `Seed`,
`PathComponent`, `DerivationPath`, `ExtendedKey`, `NetworkVersionBytes`,
`DerivedKeyPair`, `DerivedAddress`, `CoinType` (`chain`, `coinType`,
`curve: 'secp256k1' | 'ed25519'`, `defaultPath`, `standard`),
`MultiChainWalletConfig`, `ChainAccount`, `MultiChainWallet`,
`AccountDiscoveryConfig`, `AccountDiscoveryScanResult`, `DiscoveryResult`,
`SerializedExtendedKey`, `WalletExport`, and `AddressUsageChecker`.

### MPC / threshold signatures (`src/mpc/types.ts`)

MPC (Multi-Party Computation) wallet types model the distributed key generation
and signing ceremonies where multiple parties must cooperate to produce a
signature. The protocol proceeds through multiple communication rounds; the
state machine and message types below govern the ceremony lifecycle.

`MpcCurve` — `'secp256k1' | 'ed25519'`. `MpcProtocol` —
`'gg18' | 'gg20' | 'cmp' | 'frost' | 'lindell17'`.

`MpcOperationState` (state machine) —
`'initialized' | 'round1' | 'round2' | 'round3' | 'completed' | 'failed' | 'aborted' | 'timed-out'`.

`MpcMessageType` —
`'commitment' | 'share' | 'decommitment' | 'challenge' | 'response' | 'proof' | 'partial-signature' | 'abort' | 'ack'`.

Distributed key generation runs in three rounds: `DkgRound1Data` (commitments +
public coefficients + proof), `DkgRound2Data` (per-recipient encrypted secret
share — ChaCha20-Poly1305 ciphertext sealed with a 12-byte nonce under an
HKDF-SHA256 key derived from an X25519 shared secret), `DkgRound3Data`
(verification + complaints). `DkgSession`, `DkgMessage`, and `DkgResult`
orchestrate the ceremony. Signing produces `PartialSignature`s aggregated into
an `AggregatedSignature` (`r`, `s`, `v?`, `signature`, `publicKey`,
`messageHash`, `signers`); `PreSignData` supports faster signing. `KeyShare`
(`partyIndex`, `shareData`, `publicKeyShare`, `groupPublicKey`, `threshold`,
`totalParties`, `curve`, `chainCode?`, `version`), `ShareVerificationData` (with
`feldmanCoefficients`). `KeyRefreshSession.reason` ∈
`'scheduled' | 'party-change' | 'compromise'`. Additional types: `MpcParty`
(`status: 'online' | 'offline' | 'removed'`), `ThresholdConfig`,
`SigningSession`, `SecureChannel`, `EncryptedMessage`, `MpcAuditEntry`,
`MpcPerformanceMetrics`, `BatchSignRequest`, `BatchSignResult`.

### Key management (`src/key-management/types.ts`)

`KeyType` — `'secp256k1' | 'ed25519' | 'sr25519' | 'bls12-381'`. `KeyPurpose` —
`'signing' | 'encryption' | 'authentication' | 'derivation' | 'master'`.
`KeyState` — `'active' | 'rotated' | 'compromised' | 'expired' | 'destroyed'`.
`RotationStrategy` —
`'time-based' | 'usage-based' | 'manual' | 'on-compromise'`.

Encrypted keystore (Ethereum V3 format): `KeystoreV3` with
`crypto: KeystoreCrypto`. `KeystoreCipher` is the literal `'aes-128-ctr'`;
`KdfType` is `'scrypt' | 'pbkdf2'`. `ScryptParams` and `Pbkdf2Params` carry the
KDF parameters; `CipherParams` carries the IV. The MAC is
`SHA256(derivedKey[16:32] || ciphertext)`. Encryption/decryption use Node's
`node:crypto` `createCipheriv('aes-128-ctr', …)`. Default scrypt parameters are
defined in `keystore.ts`.

Other key-management types: `KeyMetadata`, `KeyEntry`, `KeystoreEncryptOptions`,
`RotationPolicy`, `RotationEvent`, `SecretShare` / `ShamirConfig` /
`ShamirSplitResult` / `ShamirRecoverResult` (Shamir secret sharing), `Guardian`
/ `SocialRecoveryConfig` / `RecoveryRequest` (social recovery), `HsmInterface`,
`SecureEnclaveInterface`, `BiometricInterface`, `KeyAccessPolicy` with
`AccessRestriction` (`TimeRestriction | IpRestriction | RateLimitRestriction`),
`KeyAuditEntry`, `TimeLockedKeyConfig`, `DeadManSwitchConfig`,
`KeyStorageBackend`.

---

## Account Abstraction (`@aje/account-abstraction`)

`@aje/account-abstraction` is a standalone package that goes beyond the basic
ERC-4337 support in `@aje/wallets`. It implements the newer and more advanced
account abstraction standards that give EOAs smart-account capabilities without
requiring an address migration. It exports five namespaces (Phase 37.26):

- `eip7702` — EIP-7702 "set code for EOAs" delegation: lets a standard Ethereum
  address temporarily act as a smart contract for batching, gas sponsorship, and
  session keys
- `erc7715` — ERC-7715 "grant permissions": a permission grant standard that
  works with EIP-7702 delegation
- `erc7579` — ERC-7579 modular smart accounts: composable execution, validation,
  hook, and fallback modules assembled as building blocks
- `erc6900` — ERC-6900 modular accounts (Alchemy): plugins that define both
  validation and execution logic for more powerful compositions
- `advancedAA` — advanced account-abstraction infrastructure

---

## Settlement Escrow (`@aje/settlement-escrow`)

`@aje/settlement-escrow` (Phase 179.7.2.4) is the integration point between the
Concordia domain's clause lifecycle and Aje's blockchain execution layer. It
bridges a validated Concordia `escrow_release` clause to a chain-ready escrow
deployment plan. The entire implementation lives in `src/escrow-adapter.ts`,
which exports Zod schemas, the inferred TypeScript types, and two functions. It
depends on `@concordia/contracts` and `zod`; notably it does **not** depend on
`@aje/core`, keeping it lightweight and independently deployable.

The schemas below use Zod, which provides both runtime validation and TypeScript
type inference. Each inferred type is derived via `z.infer<typeof Schema>`.

### `EscrowChainSchema` — `z.enum`

`'ethereum' | 'polygon' | 'arbitrum' | 'optimism' | 'base' | 'starknet' | 'aptos' | 'sui' | 'solana' | 'near' | 'cosmos' | 'bitcoin' | 'tenant_private_chain'`.
Inferred type `EscrowChain`.

### `OracleSourceSchema` — `z.enum`

`'mediator_attestation' | 'dual_party_attestation' | 'oracle_chainlink' | 'oracle_uma' | 'court_order' | 'kleros_arbitration' | 'tenant_admin'`.
Inferred type `OracleSource`.

### `EscrowMilestonePlanSchema`

| Field                     | Type / rule                                                     |
| ------------------------- | --------------------------------------------------------------- |
| `id`                      | non-empty string                                                |
| `label`                   | non-empty string                                                |
| `releaseFraction`         | number in `[0, 1]`                                              |
| `dueAt`                   | optional ISO datetime with offset                               |
| `oracleSource`            | `OracleSource`                                                  |
| `releaseAmountMinorUnits` | decimal-digit string (`/^\d+$/`) — bigint amount in minor units |

### `EscrowDeploymentPlanSchema`

| Field                    | Type / rule                                                                                             |
| ------------------------ | ------------------------------------------------------------------------------------------------------- |
| `caseId`                 | non-empty string                                                                                        |
| `clauseId`               | non-empty string                                                                                        |
| `chain`                  | `EscrowChain`                                                                                           |
| `tokenRef`               | non-empty string                                                                                        |
| `tokenDecimals`          | integer in `[0, 36]`                                                                                    |
| `principalAmount`        | decimal-digit string (`/^\d+$/`)                                                                        |
| `escrowContractRef`      | non-empty string — deployment ref that will hold the escrow                                             |
| `milestones`             | readonly array of `EscrowMilestonePlan`, min length 1                                                   |
| `arbitrationBackstop`    | `'kleros' \| 'uma_optimistic' \| 'court_order' \| 'platform_arbitrator' \| 'tenant_reviewer' \| 'none'` |
| `challengeWindowSeconds` | optional non-negative integer                                                                           |
| `agreementHash`          | optional `0x`-prefixed 64-hex-char string — clause-text hash anchored on-chain at deposit               |

**Validation rules** (`superRefine`):

1. Milestone `releaseFraction` values must sum to 1 (tolerance 1e-6).
2. The sum of milestone `releaseAmountMinorUnits` must exactly equal
   `principalAmount`.

### Functions

- `planDeployment(args)` — builds an `EscrowDeploymentPlan` from a Concordia
  `escrow_release` payload. It allocates each milestone's
  `releaseAmountMinorUnits` from `releaseFraction` using integer math at a
  1,000,000 scale; the final milestone absorbs any rounding dust so totals match
  exactly. The result is validated through `EscrowDeploymentPlanSchema`.
- `nextMilestoneAfter(plan, cutoff)` — returns the next unreleased milestone in
  due-date order after `cutoff`, or `null`. Milestones without `dueAt` are
  excluded from the ordering.

---

## Persistence (`@aje/database`)

`@aje/database` is a DDL-and-query-builder library, **not** a Drizzle-ORM
runtime. The distinction matters: it does not introduce an ORM abstraction layer
or a connection pool of its own. Instead, it emits PostgreSQL DDL and
parameterized queries via `@oshun/database` helpers (`sql`, `sqlRaw`,
`ParameterizedQuery`). Each table has a corresponding `create<Name>Table()`
function that returns a `ParameterizedQuery` object containing an idempotent
`CREATE TABLE IF NOT EXISTS` statement. The package exports five namespaces,
each grouping related tables by domain concern: `coreSchema`, `defiSchema`,
`walletSchema`, `indexer`, `maintenance`.

### Tables by namespace

The table below lists every table in each namespace. `coreSchema` covers the raw
blockchain data (chains, blocks, transactions, logs, tokens); `walletSchema`
covers user-facing wallet and identity records; `defiSchema` covers DeFi
protocol positions and portfolio analytics; `indexer` covers the on-chain event
ingestion pipeline; and `maintenance` covers operational and compliance records.

| Namespace      | Tables                                                                                                                                                                                                                                                                                     |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `coreSchema`   | `chain_configs`, `network_status`, `rpc_endpoints`, `block_explorers`, `reorg_events`, `indexer_checkpoints`, `block_gaps`, `blocks`, `transactions`, `transaction_receipts`, `event_logs`, `contracts`, `address_labels`, `tokens`, `nfts`, `balances`, `allowances`, `gas_price_history` |
| `walletSchema` | `wallets`, `aa_accounts`, `session_keys`, `multisig_configs`, `did_documents`, `verifiable_credentials`, `ens_cache`, `wallet_address_labels`, `contacts`, `wallet_transactions`, `notifications`, `wallet_preferences`, `audit_logs`, `kyc_records`, `compliance_rules`                   |
| `defiSchema`   | `dex_swaps`, `dex_volumes`, `dex_fees`, `liquidity_pools`, `liquidity_positions`, `impermanent_loss`, `lending_positions`, `liquidation_events`, `borrowing_rates`, `yield_sources`, `reward_claims`, `apy_history`, `protocol_tvl`, `portfolio_pnl`, `portfolio_snapshots`                |
| `indexer`      | `price_feeds`, `contract_events_index`, `token_transfers`, `subgraph_entities`, `api_keys`, `websocket_subscriptions`, `indexer_jobs`, `ingestion_logs`, `indexer_health`, `indexer_alerts`                                                                                                |
| `maintenance`  | `blockchain_migrations`, `migration_locks`, `backup_records`, `retention_policies`, `gdpr_requests`, `compliance_audit_log`                                                                                                                                                                |

### Representative table definitions

The two DDL samples below illustrate the table design conventions: UUID primary
keys, foreign key constraints with `ON DELETE CASCADE`, `CHECK` constraints for
enum-like columns, `TIMESTAMPTZ` timestamps, and `NUMERIC(78)` for 256-bit
on-chain integers. All `CREATE TABLE` statements are `IF NOT EXISTS` and are
therefore safe to re-run on startup.

`chain_configs`:

```sql
CREATE TABLE IF NOT EXISTS chain_configs (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  chain_id INTEGER NOT NULL,
  name VARCHAR(128) NOT NULL,
  short_name VARCHAR(32),
  network_type VARCHAR(16) NOT NULL CHECK (network_type IN ('mainnet','testnet','devnet','local')),
  consensus_type VARCHAR(8) NOT NULL CHECK (consensus_type IN ('pow','pos','dpos','poa','pbft')),
  native_currency_name VARCHAR(64) NOT NULL,
  native_currency_symbol VARCHAR(16) NOT NULL,
  native_currency_decimals INTEGER NOT NULL DEFAULT 18,
  is_evm BOOLEAN NOT NULL DEFAULT false,
  average_block_time_ms INTEGER,
  required_confirmations INTEGER NOT NULL DEFAULT 12,
  is_active BOOLEAN NOT NULL DEFAULT true,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE (chain_id, network_type)
);
```

`transactions` carries `chain_config_id` and `block_id` foreign keys, `tx_hash`,
`tx_index`, `tx_type`, `from_address`, `to_address`, `value`, `nonce`,
`gas_limit`, `gas_price`, `max_fee_per_gas`, `max_priority_fee_per_gas`,
`input_data`, a `status` check constraint
(`'pending','submitted','confirmed','failed','dropped','replaced'`),
`block_number`, `block_hash`, `timestamp`, and is unique on
`(chain_config_id, tx_hash)`. `transaction_receipts` has a one-to-one
`transaction_id` FK and a `status` check (`'success','reverted'`). High-value
numerics use `NUMERIC(78)` to hold 256-bit on-chain integers.

`wallets`:

```sql
CREATE TABLE IF NOT EXISTS wallets (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  chain_config_id UUID NOT NULL REFERENCES chain_configs(id) ON DELETE CASCADE,
  address VARCHAR(128) NOT NULL,
  wallet_type VARCHAR(16) NOT NULL CHECK (wallet_type IN ('eoa','smart_account','multisig','hardware','mpc')),
  name VARCHAR(128),
  derivation_path VARCHAR(64),
  public_key VARCHAR(256),
  is_imported BOOLEAN NOT NULL DEFAULT false,
  is_active BOOLEAN NOT NULL DEFAULT true,
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  UNIQUE (chain_config_id, address)
);
```

`aa_accounts` records ERC-4337 accounts (`factory_address`,
`implementation_address`, `entry_point_address`, `owner_address`, `salt`,
`is_deployed`, `deploy_tx_hash`). `session_keys` records scoped keys
(`permissions JSONB`, `valid_after`, `valid_until`, `spending_limit`,
`spending_used`, `is_revoked`).

### ORM-schema generator (`maintenance/orm-integration.ts`)

The `maintenance` namespace contains a code generator that converts an internal
`OrmSchemaDefinition` into Prisma **or** Drizzle schema source. It exposes
`sqlTypeToPrisma`, `sqlTypeToDrizzle`, `generateDrizzleTable`,
`generateDrizzleSchema`, and Prisma equivalents. This is a developer tool that
emits schema strings; it is not how `@aje/database` itself talks to PostgreSQL.

---

## V2 Game-Domain Integrations

Two services in the V2 game project consume Aje primitives behind a
gameplay-safety envelope. Both exist on disk under `V2/services/`. The safety
envelope is important: blockchain features for games carry regulatory
uncertainty in many jurisdictions, so both services require explicit opt-in from
the user, check a platform cert-ban table before surfacing any blockchain UI,
and are blocked at binary cook time by a Python check script when the relevant
platforms are not cleared.

### V2 Web3 Cosmetic Ownership Contract — `@v2/aje-web3-cosmetic-ownership`

Consumes `@aje/identity` and `@aje/nft` for wallet-bound cosmetic ownership. Aje
owns the wallet/DID and NFT primitives; V2 owns the safety boundary:

- The `V2_AJE_WEB3_COSMETIC_OWNERSHIP_WARNING` constant must be accepted before
  any wallet-bound cosmetic is surfaced; the service supplies it as
  `warningText`. `evaluateV2AjeWeb3CosmeticOwnershipPolicy` returns
  `blocked-warning-not-accepted` until that exact string is acknowledged, and
  `blocked-missing-opt-in` until `optIn.granted` is set.
- The surface only verifies — never mints — ownership:
  `credentials.verifyCredential` (`@aje/identity`) proves the wallet/DID binding
  and `erc721.getTokenOwnership` (`@aje/nft`) confirms on-chain custody of the
  cosmetic token. It carries `mayInfluenceRollback: false`, so a wallet's
  cosmetic display can never alter deterministic match simulation.
- `V2/legal/platform-cert-bans.json` is the legal source of truth for platform,
  region, age-rating, banned surfaces, and effective-date windows. The shared
  `V2/ue/Tools/check-platform-cert-bans.py` gate validates that table and the
  `PlatformCookAjeReachability.json` manifest, returning
  `blocked-platform-cert-banned` for the `on_chain_in_game_items` /
  `cosmetic_nft_ownership` / `web3_cosmetic_ownership` surfaces wherever a
  publisher-legal entry bans them.
- `V2/ue/Tools/check-v2-aje-web3-cosmetic-ownership.py` blocks cooked binaries
  when `@aje/identity` or `@aje/nft` is reachable on a platform where on-chain
  in-game items are banned or not explicitly cleared.

### V2 Fan-Token Faction Governance Contract — `@v2/aje-faction-governance`

Consumes `@aje/governance` for optional fan-token-gated faction governance:

- The `V2_AJE_FACTION_GOVERNANCE_WARNING` constant must be accepted before any
  fan-token faction vote opens. `evaluateV2AjeFactionGovernancePolicy` enforces
  `requiresExplicitOptIn: true` and only then composes a Snapshot vote via
  `snapshot.createERC20Strategy` / `snapshot.buildSpace` /
  `snapshot.buildProposal`, so an external ERC-20 fan-token balance gates a
  faction ballot rather than in-game state. The decision surface is
  `offRollback: true` / `mayInfluenceRollback: false`.
- The `fan_token_gated_gameplay` surface in `V2/legal/platform-cert-bans.json`
  governs where this is allowed. The shared
  `V2/ue/Tools/check-platform-cert-bans.py` gate (which lists `@aje/governance`
  in `REQUIRED_AJE_SURFACE_PACKAGES`) refuses any cook that reaches the
  governance package on a platform that has not explicitly cleared
  `fan_token_gated_gameplay`, and
  `V2/ue/Tools/check-v2-aje-faction-governance.py` enforces the per-binary
  wiring.

---

## Configuration

Aje deliberately avoids a monolithic global configuration object. Each package
is independently configured through the typed objects it defines, and consumers
pass those objects at construction time. This makes each package usable in
isolation without having to reason about the full domain config. Representative
configuration types include `ChainProviderConfig`, `OshunRpcClientOptions`,
`RetryPolicy`, `FallbackConfig`, `MultiChainWalletConfig`, and
`KeystoreEncryptOptions`. There is no single global `AjeConfig` type and no
central config file in the domain.

---

## Cross-Domain Integration Points

Aje is a foundational domain: it depends outward on a small set of shared
workspace packages, and it is consumed inward by two specialised surfaces in the
V2 game project. There is no event-bus integration in either direction — no Aje
package imports `@oshun/event-bus`, and Aje publishes no Kafka or Redis-Stream
messages.

| Counterpart                 | Direction       | Mechanism                                                             |
| --------------------------- | --------------- | --------------------------------------------------------------------- |
| `@oshun/crypto`             | aje → shared    | Workspace crypto package; runtime dependency of most Aje packages     |
| `@oshun/types`              | aje → shared    | Optional peer dependency of `@aje/core`                               |
| `@oshun/database`           | aje → shared    | Peer of `@aje/database`; provides `sql`/`sqlRaw`/`ParameterizedQuery` |
| `@concordia/contracts`      | aje → concordia | Runtime dependency of `@aje/settlement-escrow`                        |
| `@aje/identity`, `@aje/nft` | V2 → aje        | Consumed by `@v2/aje-web3-cosmetic-ownership`                         |
| `@aje/governance`           | V2 → aje        | Consumed by `@v2/aje-faction-governance`                              |

---

## Acceptance Criteria

- All 31 `@aje/*` packages build and pass their Vitest suites (each package
  ships `*.spec.ts` files alongside its modules).
- `@aje/core` exposes addresses, transactions, blocks, BigNumber, crypto, ABI,
  events, Merkle trees, network config, and errors through one barrel export.
- Cryptography uses only `@noble`, `@scure`, `@oshun/crypto`, and Node's
  built-in `node:crypto` (AES). No custom curve or hash code exists.
- `@aje/settlement-escrow` rejects any deployment plan whose milestone fractions
  do not sum to 1 or whose milestone amounts do not sum to the principal.
- `@aje/database` DDL functions produce idempotent `CREATE TABLE IF NOT EXISTS`
  statements with the documented columns, check constraints, and uniqueness
  constraints.
- `@aje/rpc` retries only the failure kinds in `RetryPolicy.retryOn` and walks
  endpoints per the configured `FallbackStrategy` / `FanOutStrategy`.

---

## Grounding

Every type, enum, schema, table, and function above was read directly from
`libs/aje/*` source: `@aje/core` (`addresses/`, `transactions/`, `blocks/`,
`bignum/`, `network/`, `abi/`, `events/`, `errors/`, `crypto/`),
`@aje/chains/abstraction`, `@aje/rpc`, `@aje/wallets` (`hd-wallet/`, `mpc/`,
`key-management/`), `@aje/account-abstraction`, `@aje/database`, and
`@aje/settlement-escrow`. The library inventory comes from each package's
`package.json` and `src/index.ts`. The V2 integration is grounded in
`apps/v2/aje-*` and `V2/ue/Tools/check-v2-aje-*.py`. Phase 37 is the Aje domain
backlog in `TODOS.md`; `@aje/settlement-escrow` is Phase 179.7.2.4 and is listed
as Implemented in `DOMAINS/concordia/specifications.md`.
