Add full monorepo: virtual-banker, backend, frontend, docs, scripts, deployment
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
293
docs/specs/multichain/chain-adapter-interface.md
Normal file
293
docs/specs/multichain/chain-adapter-interface.md
Normal file
@@ -0,0 +1,293 @@
|
||||
# Chain Adapter Interface Specification
|
||||
|
||||
## Overview
|
||||
|
||||
This document specifies the abstract chain adapter interface that enables multi-chain support by abstracting chain-specific differences behind a unified interface.
|
||||
|
||||
## Adapter Interface
|
||||
|
||||
### Core Interface
|
||||
|
||||
```typescript
|
||||
interface ChainAdapter {
|
||||
// Chain identification
|
||||
getChainId(): number;
|
||||
getChainName(): string;
|
||||
|
||||
// RPC capabilities
|
||||
getBlock(blockNumber: number | string): Promise<Block>;
|
||||
getBlockByHash(hash: string): Promise<Block>;
|
||||
getTransaction(hash: string): Promise<Transaction>;
|
||||
getTransactionReceipt(hash: string): Promise<Receipt>;
|
||||
getBalance(address: string, blockNumber?: string): Promise<string>;
|
||||
call(transaction: CallRequest, blockNumber?: string): Promise<string>;
|
||||
|
||||
// Advanced capabilities
|
||||
traceTransaction(hash: string): Promise<Trace[]>;
|
||||
traceBlock(blockNumber: number): Promise<Trace[]>;
|
||||
getCode(address: string, blockNumber?: string): Promise<string>;
|
||||
|
||||
// Subscription capabilities
|
||||
subscribeNewBlocks(callback: (block: Block) => void): Subscription;
|
||||
subscribePendingTransactions(callback: (tx: Transaction) => void): Subscription;
|
||||
|
||||
// Capability queries
|
||||
supportsTracing(): boolean;
|
||||
supportsArchive(): boolean;
|
||||
supportsDebug(): boolean;
|
||||
}
|
||||
```
|
||||
|
||||
## RPC Capabilities Abstraction
|
||||
|
||||
### Archive Mode
|
||||
|
||||
**Interface**:
|
||||
```typescript
|
||||
interface ArchiveCapability {
|
||||
getHistoricalBalance(address: string, blockNumber: number): Promise<string>;
|
||||
getHistoricalCode(address: string, blockNumber: number): Promise<string>;
|
||||
getHistoricalStorage(address: string, slot: string, blockNumber: number): Promise<string>;
|
||||
}
|
||||
```
|
||||
|
||||
**Implementation**:
|
||||
- EVM chains: Use `eth_getBalance` with block number
|
||||
- Non-EVM: Chain-specific historical queries
|
||||
|
||||
### Tracing Capabilities
|
||||
|
||||
**Interface**:
|
||||
```typescript
|
||||
interface TracingCapability {
|
||||
traceCall(call: CallRequest, traceType: string[]): Promise<TraceResult>;
|
||||
traceTransaction(hash: string, traceType: string[]): Promise<Trace[]>;
|
||||
traceBlock(blockNumber: number, traceType: string[]): Promise<Trace[][]>;
|
||||
}
|
||||
```
|
||||
|
||||
**Trace Types**:
|
||||
- `call`: Call traces
|
||||
- `trace`: Full trace information
|
||||
- `vmTrace`: VM execution trace
|
||||
- `stateDiff`: State differences
|
||||
|
||||
**Implementation**:
|
||||
- EVM chains: Use `debug_trace*` methods
|
||||
- Non-EVM: Chain-specific trace methods
|
||||
|
||||
### Debug Capabilities
|
||||
|
||||
**Interface**:
|
||||
```typescript
|
||||
interface DebugCapability {
|
||||
debugTraceTransaction(hash: string, options: TraceOptions): Promise<TraceResult>;
|
||||
debugTraceBlock(blockNumber: number, options: TraceOptions): Promise<TraceResult[]>;
|
||||
debugTraceCall(call: CallRequest, blockNumber: number, options: TraceOptions): Promise<TraceResult>;
|
||||
}
|
||||
```
|
||||
|
||||
**Use Cases**: Advanced debugging, detailed transaction analysis
|
||||
|
||||
## Token Standards Abstraction
|
||||
|
||||
### Token Interface
|
||||
|
||||
```typescript
|
||||
interface TokenStandard {
|
||||
// Common methods
|
||||
getBalance(address: string, tokenAddress: string): Promise<string>;
|
||||
getTotalSupply(tokenAddress: string): Promise<string>;
|
||||
getDecimals(tokenAddress: string): Promise<number>;
|
||||
getName(tokenAddress: string): Promise<string>;
|
||||
getSymbol(tokenAddress: string): Promise<string>;
|
||||
|
||||
// Standard-specific
|
||||
getTokenId(owner: string, index: number): Promise<string>; // ERC-721/1155
|
||||
getTokenURI(tokenAddress: string, tokenId: string): Promise<string>; // ERC-721/1155
|
||||
}
|
||||
```
|
||||
|
||||
### Standard Detection
|
||||
|
||||
**ERC-20**:
|
||||
- Detect `balanceOf`, `totalSupply`, `transfer` functions
|
||||
- Standard interface ID: `0x36372b07`
|
||||
|
||||
**ERC-721**:
|
||||
- Detect `balanceOf`, `ownerOf`, `tokenURI` functions
|
||||
- Standard interface ID: `0x80ac58cd`
|
||||
|
||||
**ERC-1155**:
|
||||
- Detect `balanceOf`, `balanceOfBatch`, `uri` functions
|
||||
- Standard interface ID: `0xd9b67a26`
|
||||
|
||||
**Non-EVM Standards**:
|
||||
- Chain-specific token standards
|
||||
- Custom detection logic
|
||||
|
||||
## Gas Model Abstraction
|
||||
|
||||
### Gas Interface
|
||||
|
||||
```typescript
|
||||
interface GasModel {
|
||||
// Gas estimation
|
||||
estimateGas(transaction: TransactionRequest): Promise<number>;
|
||||
|
||||
// Fee calculation
|
||||
getGasPrice(): Promise<string>;
|
||||
getFeeData(): Promise<FeeData>; // EIP-1559
|
||||
|
||||
// Gas limit
|
||||
getBlockGasLimit(): Promise<number>;
|
||||
getBlockGasUsed(): Promise<number>;
|
||||
}
|
||||
```
|
||||
|
||||
### EIP-1559 Support
|
||||
|
||||
**Interface**:
|
||||
```typescript
|
||||
interface EIP1559GasModel extends GasModel {
|
||||
getBaseFee(): Promise<string>;
|
||||
getMaxFeePerGas(): Promise<string>;
|
||||
getMaxPriorityFeePerGas(): Promise<string>;
|
||||
}
|
||||
```
|
||||
|
||||
**Detection**: Check for `baseFeePerGas` in block header
|
||||
|
||||
### Legacy Gas Model
|
||||
|
||||
**Interface**: Simple gas price model (pre-EIP-1559)
|
||||
|
||||
## Finality Model Abstraction
|
||||
|
||||
### Finality Interface
|
||||
|
||||
```typescript
|
||||
interface FinalityModel {
|
||||
getFinalityDepth(): number; // Blocks until final
|
||||
isFinal(blockNumber: number): Promise<boolean>;
|
||||
getFinalityTime(): number; // Estimated time to finality (seconds)
|
||||
}
|
||||
```
|
||||
|
||||
### Finality Types
|
||||
|
||||
**Immediate Finality** (BFT chains):
|
||||
- Finality depth: 1
|
||||
- Examples: Cosmos, Polkadot (with finality gadgets)
|
||||
|
||||
**Probabilistic Finality** (PoW):
|
||||
- Finality depth: 12-100 blocks
|
||||
- Examples: Ethereum (pre-merge), Bitcoin
|
||||
|
||||
**Economic Finality** (PoS):
|
||||
- Finality depth: 1-2 epochs
|
||||
- Examples: Ethereum (post-merge), Cardano
|
||||
|
||||
## Implementation Examples
|
||||
|
||||
### EVM Chain Adapter
|
||||
|
||||
```typescript
|
||||
class EVMChainAdapter implements ChainAdapter {
|
||||
constructor(private rpcUrl: string, private chainId: number) {}
|
||||
|
||||
async getBlock(blockNumber: number | string): Promise<Block> {
|
||||
const response = await this.rpcCall('eth_getBlockByNumber', [
|
||||
blockNumber === 'latest' ? 'latest' : `0x${blockNumber.toString(16)}`,
|
||||
true
|
||||
]);
|
||||
return this.transformBlock(response);
|
||||
}
|
||||
|
||||
supportsTracing(): boolean {
|
||||
return true; // Most EVM chains support tracing
|
||||
}
|
||||
|
||||
// ... other methods
|
||||
}
|
||||
```
|
||||
|
||||
### Non-EVM Chain Adapter
|
||||
|
||||
```typescript
|
||||
class NonEVMChainAdapter implements ChainAdapter {
|
||||
// Chain-specific implementation
|
||||
// Map chain-specific RPC calls to standard interface
|
||||
}
|
||||
```
|
||||
|
||||
## Adapter Registry
|
||||
|
||||
### Registry Interface
|
||||
|
||||
```typescript
|
||||
interface ChainAdapterRegistry {
|
||||
register(chainId: number, adapter: ChainAdapter): void;
|
||||
get(chainId: number): ChainAdapter;
|
||||
list(): ChainAdapter[];
|
||||
supports(chainId: number): boolean;
|
||||
}
|
||||
```
|
||||
|
||||
### Configuration
|
||||
|
||||
```yaml
|
||||
chains:
|
||||
- chain_id: 138
|
||||
name: "ChainID 138"
|
||||
adapter: "evm"
|
||||
rpc_url: "http://192.168.11.221:8545" # Internal IP for direct connection
|
||||
supports_tracing: true
|
||||
supports_archive: true
|
||||
|
||||
- chain_id: 1
|
||||
name: "Ethereum Mainnet"
|
||||
adapter: "evm"
|
||||
rpc_url: "https://eth-mainnet.alchemyapi.io/v2/..."
|
||||
supports_tracing: true
|
||||
supports_archive: true
|
||||
```
|
||||
|
||||
## Error Handling
|
||||
|
||||
### Chain-Specific Errors
|
||||
|
||||
**Handling**:
|
||||
- Map chain-specific errors to standard error codes
|
||||
- Provide error context (chain_id, method called)
|
||||
- Log chain-specific error details
|
||||
|
||||
### Capability Errors
|
||||
|
||||
**Handling**:
|
||||
- Check capability before calling method
|
||||
- Return appropriate error if capability not supported
|
||||
- Provide alternative methods when possible
|
||||
|
||||
## Testing
|
||||
|
||||
### Adapter Tests
|
||||
|
||||
**Test Cases**:
|
||||
- Standard interface methods
|
||||
- Error handling
|
||||
- Capability detection
|
||||
- Data transformation
|
||||
|
||||
### Integration Tests
|
||||
|
||||
**Test Cases**:
|
||||
- Multi-chain queries
|
||||
- Adapter switching
|
||||
- Error propagation
|
||||
|
||||
## References
|
||||
|
||||
- Multi-chain Indexing: See `multichain-indexing.md`
|
||||
- Database Schema: See `../database/postgres-schema.md`
|
||||
|
||||
Reference in New Issue
Block a user