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`
|
||||
|
||||
154
docs/specs/multichain/entity-graph.md
Normal file
154
docs/specs/multichain/entity-graph.md
Normal file
@@ -0,0 +1,154 @@
|
||||
# Cross-Chain Entity Graph
|
||||
|
||||
## Overview
|
||||
|
||||
This document specifies the cross-chain entity graph for tracking relationships between addresses, contracts, and protocols across multiple chains.
|
||||
|
||||
## Graph Structure
|
||||
|
||||
See `../database/graph-schema.md` for detailed Neo4j schema.
|
||||
|
||||
### Node Types
|
||||
|
||||
- **Address**: Blockchain addresses (can exist on multiple chains)
|
||||
- **Contract**: Smart contracts (chain-specific instances)
|
||||
- **Token**: Token contracts
|
||||
- **Protocol**: DeFi protocols (cross-chain presence)
|
||||
|
||||
### Relationship Types
|
||||
|
||||
- **TRANSFERRED_TO**: Token transfers
|
||||
- **CALLED**: Contract calls
|
||||
- **OWNS**: Token ownership
|
||||
- **CLUSTERED_WITH**: Address clustering (same entity)
|
||||
- **CCIP_MESSAGE_LINK**: Cross-chain message links
|
||||
|
||||
## Address Clustering
|
||||
|
||||
### Clustering Heuristics
|
||||
|
||||
**1. Multi-Signature Wallets**:
|
||||
- Addresses controlled by same set of signers
|
||||
- High confidence
|
||||
|
||||
**2. Transaction Patterns**:
|
||||
- Addresses that frequently transact together
|
||||
- Similar transaction timing
|
||||
- Medium confidence
|
||||
|
||||
**3. Funding Patterns**:
|
||||
- Addresses funded from same source
|
||||
- Sequential funding
|
||||
- Medium confidence
|
||||
|
||||
**4. Contract Deployment**:
|
||||
- Addresses deploying contracts with similar code
|
||||
- Same deployer patterns
|
||||
- Low-medium confidence
|
||||
|
||||
### Confidence Scores
|
||||
|
||||
**High (0.9+)**: Multi-sig, verified relationships
|
||||
**Medium (0.7-0.9)**: Pattern-based clustering
|
||||
**Low (0.5-0.7)**: Weak patterns, needs verification
|
||||
|
||||
### Implementation
|
||||
|
||||
**Algorithm**:
|
||||
1. Analyze transaction patterns
|
||||
2. Calculate similarity scores
|
||||
3. Cluster addresses above threshold
|
||||
4. Store relationships in graph database
|
||||
|
||||
## Contract/Protocol Tagging
|
||||
|
||||
### Protocol Identification
|
||||
|
||||
**Methods**:
|
||||
1. **Known Address Lists**: Maintain list of known protocol addresses
|
||||
2. **Code Similarity**: Compare contract code
|
||||
3. **Interaction Patterns**: Analyze usage patterns
|
||||
4. **Labels**: User-submitted labels
|
||||
|
||||
### Protocol Categories
|
||||
|
||||
- **DEX**: Decentralized exchanges
|
||||
- **Lending**: Lending protocols
|
||||
- **Bridge**: Cross-chain bridges
|
||||
- **NFT Marketplace**: NFT trading platforms
|
||||
- **Governance**: DAOs and governance protocols
|
||||
|
||||
### Tagging System
|
||||
|
||||
**Tags**:
|
||||
- Category tags (DEX, Lending, etc.)
|
||||
- Protocol tags (Uniswap, Aave, etc.)
|
||||
- Risk tags (verified, audited, etc.)
|
||||
|
||||
## Cross-Chain Entity Resolution
|
||||
|
||||
### Address Resolution
|
||||
|
||||
**Challenge**: Same entity may use different addresses on different chains
|
||||
|
||||
**Solution**:
|
||||
- Use clustering to link addresses
|
||||
- Use CCIP message links
|
||||
- Use bridge transaction patterns
|
||||
|
||||
### Entity Unification
|
||||
|
||||
**Process**:
|
||||
1. Identify entity across chains
|
||||
2. Create unified entity node
|
||||
3. Link chain-specific addresses to unified entity
|
||||
4. Aggregate metrics across chains
|
||||
|
||||
## Graph Query Patterns
|
||||
|
||||
### Find Entity Across Chains
|
||||
|
||||
```cypher
|
||||
MATCH (e:Entity)-[:HAS_ADDRESS]->(a:Address)
|
||||
WHERE e.id = "entity_123"
|
||||
RETURN a.address, a.chainId;
|
||||
```
|
||||
|
||||
### Find Cross-Chain Transactions
|
||||
|
||||
```cypher
|
||||
MATCH (a1:Address {address: "0x...", chainId: 138})
|
||||
-[:CCIP_MESSAGE_LINK]->
|
||||
(a2:Address {chainId: 1})
|
||||
RETURN a2.address, a2.chainId;
|
||||
```
|
||||
|
||||
### Find Protocol Users Across Chains
|
||||
|
||||
```cypher
|
||||
MATCH (a:Address)-[r:INTERACTS_WITH]->(p:Protocol {name: "Uniswap"})
|
||||
RETURN a.address, a.chainId, count(r) as interactions
|
||||
ORDER BY interactions DESC;
|
||||
```
|
||||
|
||||
## Data Ingestion
|
||||
|
||||
### Cross-Chain Data Sources
|
||||
|
||||
1. **Blockchain Data**: Indexed transactions and transfers
|
||||
2. **CCIP Messages**: Cross-chain message links
|
||||
3. **Bridge Transactions**: Bridge usage patterns
|
||||
4. **User Labels**: User-submitted entity relationships
|
||||
|
||||
### Update Frequency
|
||||
|
||||
**Real-time**: New transactions and transfers
|
||||
**Batch**: Clustering analysis (daily)
|
||||
**On-demand**: User-requested clustering
|
||||
|
||||
## References
|
||||
|
||||
- Graph Database Schema: See `../database/graph-schema.md`
|
||||
- CCIP Integration: See `../ccip/ccip-tracking.md`
|
||||
- Multi-chain Indexing: See `multichain-indexing.md`
|
||||
|
||||
179
docs/specs/multichain/multichain-indexing.md
Normal file
179
docs/specs/multichain/multichain-indexing.md
Normal file
@@ -0,0 +1,179 @@
|
||||
# Multi-Chain Indexing Strategy
|
||||
|
||||
## Overview
|
||||
|
||||
This document specifies the strategy for indexing multiple blockchain networks with shared schema and per-chain workers.
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph Chains[Blockchain Networks]
|
||||
C1[Chain 138]
|
||||
C2[Chain 1]
|
||||
C3[Chain 137]
|
||||
end
|
||||
|
||||
subgraph Workers[Indexer Workers]
|
||||
W1[Worker: Chain 138]
|
||||
W2[Worker: Chain 1]
|
||||
W3[Worker: Chain 137]
|
||||
end
|
||||
|
||||
subgraph DB[(Shared Database)]
|
||||
PG[(PostgreSQL<br/>chain_id partitioned)]
|
||||
ES[(Elasticsearch<br/>per-chain indices)]
|
||||
end
|
||||
|
||||
C1 --> W1
|
||||
C2 --> W2
|
||||
C3 --> W3
|
||||
|
||||
W1 --> PG
|
||||
W2 --> PG
|
||||
W3 --> PG
|
||||
|
||||
W1 --> ES
|
||||
W2 --> ES
|
||||
W3 --> ES
|
||||
```
|
||||
|
||||
## Per-Chain Indexer Workers
|
||||
|
||||
### Worker Architecture
|
||||
|
||||
**Design**: One indexer worker process per chain
|
||||
|
||||
**Isolation**:
|
||||
- Separate processes/containers per chain
|
||||
- Independent scaling per chain
|
||||
- Chain-specific configuration
|
||||
|
||||
**Shared Components**:
|
||||
- Database connection pool
|
||||
- Message queue consumers
|
||||
- Common indexing logic
|
||||
|
||||
### Worker Configuration
|
||||
|
||||
```yaml
|
||||
workers:
|
||||
- chain_id: 138
|
||||
name: "indexer-chain-138"
|
||||
rpc_url: "http://192.168.11.221:8545" # Internal IP for direct connection
|
||||
adapter: "evm"
|
||||
enabled: true
|
||||
|
||||
- chain_id: 1
|
||||
name: "indexer-chain-1"
|
||||
rpc_url: "https://eth-mainnet.alchemyapi.io/..."
|
||||
adapter: "evm"
|
||||
enabled: true
|
||||
```
|
||||
|
||||
### Worker Scaling
|
||||
|
||||
**Horizontal Scaling**:
|
||||
- Multiple workers per chain for high-throughput chains
|
||||
- Partition blocks across workers (by block number range)
|
||||
- Coordinate via database locks or message queue
|
||||
|
||||
**Scaling Strategy**:
|
||||
- Scale workers based on chain activity
|
||||
- Monitor worker lag per chain
|
||||
- Auto-scale based on metrics
|
||||
|
||||
## Shared Schema with Chain ID Partitioning
|
||||
|
||||
### Database Partitioning
|
||||
|
||||
**Strategy**: Partition all tables by `chain_id`
|
||||
|
||||
**Benefits**:
|
||||
- Efficient queries (partition pruning)
|
||||
- Independent maintenance per chain
|
||||
- Easy data isolation
|
||||
|
||||
**Implementation**: See `../database/postgres-schema.md`
|
||||
|
||||
### Index Strategy
|
||||
|
||||
**Global Indexes**: Across all chains for unified queries
|
||||
**Chain-Specific Indexes**: Within partitions for chain-specific queries
|
||||
|
||||
## Cross-Chain Data Consistency
|
||||
|
||||
### Consistency Model
|
||||
|
||||
**Per-Chain Consistency**: Strong consistency within each chain
|
||||
**Cross-Chain Consistency**: Eventual consistency (independent chains)
|
||||
|
||||
### Transaction Ordering
|
||||
|
||||
**Within Chain**: Maintain strict block/transaction ordering
|
||||
**Across Chains**: No ordering guarantees (independent chains)
|
||||
|
||||
## Worker Coordination
|
||||
|
||||
### Block Processing Coordination
|
||||
|
||||
**Strategy**: Use database locks or message queue for coordination
|
||||
|
||||
**Approach 1: Database Locks**
|
||||
- Acquire lock before processing block
|
||||
- Release lock after completion
|
||||
- Prevent duplicate processing
|
||||
|
||||
**Approach 2: Message Queue**
|
||||
- Single consumer per chain partition
|
||||
- Queue ensures ordering
|
||||
- Automatic retry on failure
|
||||
|
||||
### Checkpointing
|
||||
|
||||
**Per-Chain Checkpoints**:
|
||||
- Track last processed block per chain
|
||||
- Stored in database
|
||||
- Enable recovery and resume
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Chain-Specific Optimizations
|
||||
|
||||
**High-Activity Chains**:
|
||||
- More workers
|
||||
- Larger batch sizes
|
||||
- Optimized processing
|
||||
|
||||
**Low-Activity Chains**:
|
||||
- Fewer workers
|
||||
- Longer polling intervals
|
||||
- Resource-efficient processing
|
||||
|
||||
### Resource Allocation
|
||||
|
||||
**CPU/Memory**: Allocate based on chain activity
|
||||
**Database Connections**: Pool per chain
|
||||
**Network Bandwidth**: Prioritize high-activity chains
|
||||
|
||||
## Monitoring
|
||||
|
||||
### Per-Chain Metrics
|
||||
|
||||
- Block lag (current block - last indexed)
|
||||
- Processing rate (blocks/minute)
|
||||
- Error rate
|
||||
- Worker health
|
||||
|
||||
### Cross-Chain Metrics
|
||||
|
||||
- Total chains indexed
|
||||
- Total blocks indexed across all chains
|
||||
- System-wide throughput
|
||||
|
||||
## References
|
||||
|
||||
- Chain Adapter Interface: See `chain-adapter-interface.md`
|
||||
- Database Schema: See `../database/postgres-schema.md`
|
||||
- Indexer Architecture: See `../indexing/indexer-architecture.md`
|
||||
|
||||
192
docs/specs/multichain/unified-search.md
Normal file
192
docs/specs/multichain/unified-search.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# Unified Search Architecture
|
||||
|
||||
## Overview
|
||||
|
||||
This document specifies the unified search architecture that enables searching across multiple chains and entity types with relevance ranking.
|
||||
|
||||
## Architecture
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
Query[Search Query]
|
||||
Router[Query Router]
|
||||
|
||||
subgraph Search[Search Services]
|
||||
ES1[Elasticsearch<br/>Chain 138]
|
||||
ES2[Elasticsearch<br/>Chain 1]
|
||||
ES3[Elasticsearch<br/>Chain 137]
|
||||
end
|
||||
|
||||
Agg[Aggregator]
|
||||
Rank[Relevance Ranking]
|
||||
Results[Unified Results]
|
||||
|
||||
Query --> Router
|
||||
Router --> ES1
|
||||
Router --> ES2
|
||||
Router --> ES3
|
||||
ES1 --> Agg
|
||||
ES2 --> Agg
|
||||
ES3 --> Agg
|
||||
Agg --> Rank
|
||||
Rank --> Results
|
||||
```
|
||||
|
||||
## Search Algorithm
|
||||
|
||||
### Query Processing
|
||||
|
||||
**Steps**:
|
||||
1. Parse query (extract terms, filters)
|
||||
2. Determine chain scope (all chains or specific chain)
|
||||
3. Route to appropriate search indices
|
||||
4. Execute searches in parallel
|
||||
5. Aggregate results
|
||||
6. Rank by relevance
|
||||
7. Return unified results
|
||||
|
||||
### Query Types
|
||||
|
||||
**Exact Match** (Hash, Address):
|
||||
- Direct lookup in specific chain
|
||||
- Return single result if found
|
||||
|
||||
**Full-Text Search** (Name, Symbol, Label):
|
||||
- Search across all chains
|
||||
- Rank by relevance
|
||||
- Return top N results per chain
|
||||
|
||||
**Fuzzy Search** (Typos, Partial matches):
|
||||
- Use fuzzy matching
|
||||
- Rank by similarity
|
||||
- Include suggestions
|
||||
|
||||
## Ranking and Relevance Scoring
|
||||
|
||||
### Relevance Factors
|
||||
|
||||
**1. Exact Match Score**:
|
||||
- Exact match: 100%
|
||||
- Prefix match: 80%
|
||||
- Fuzzy match: 60%
|
||||
|
||||
**2. Chain Relevance**:
|
||||
- User's preferred chain: +20%
|
||||
- Popular chains: +10%
|
||||
|
||||
**3. Entity Type Relevance**:
|
||||
- Addresses: Highest (most specific)
|
||||
- Transactions: High
|
||||
- Blocks: Medium
|
||||
- Tokens: Medium
|
||||
- Contracts: Lower (unless verified)
|
||||
|
||||
**4. Popularity Score**:
|
||||
- Transaction count
|
||||
- Token holder count
|
||||
- Contract usage
|
||||
|
||||
### Scoring Formula
|
||||
|
||||
```
|
||||
score = (exact_match_score * 0.5) +
|
||||
(chain_relevance * 0.2) +
|
||||
(entity_type_relevance * 0.2) +
|
||||
(popularity_score * 0.1)
|
||||
```
|
||||
|
||||
## Result Aggregation
|
||||
|
||||
### Aggregation Strategy
|
||||
|
||||
**Per-Chain Results**:
|
||||
- Limit results per chain (e.g., top 10)
|
||||
- Combine across chains
|
||||
- Remove duplicates (same address on multiple chains)
|
||||
|
||||
### Result Format
|
||||
|
||||
```json
|
||||
{
|
||||
"query": "0x123...",
|
||||
"total_results": 5,
|
||||
"results": [
|
||||
{
|
||||
"type": "address",
|
||||
"chain_id": 138,
|
||||
"address": "0x123...",
|
||||
"label": "My Wallet",
|
||||
"score": 0.95
|
||||
},
|
||||
{
|
||||
"type": "transaction",
|
||||
"chain_id": 138,
|
||||
"hash": "0x123...",
|
||||
"score": 0.80
|
||||
}
|
||||
],
|
||||
"chains_searched": [138, 1, 137]
|
||||
}
|
||||
```
|
||||
|
||||
## Performance Optimization
|
||||
|
||||
### Caching
|
||||
|
||||
**Cache Strategy**:
|
||||
- Cache popular queries (top 1000)
|
||||
- Cache duration: 1 minute
|
||||
- Invalidate on data updates
|
||||
|
||||
### Parallel Search
|
||||
|
||||
**Strategy**: Execute searches across chains in parallel
|
||||
|
||||
**Benefits**:
|
||||
- Faster response time
|
||||
- Better resource utilization
|
||||
|
||||
### Result Limiting
|
||||
|
||||
**Per-Chain Limit**: Top 10-20 results per chain
|
||||
**Total Limit**: Top 50-100 results total
|
||||
|
||||
## Search Indexes
|
||||
|
||||
### Per-Chain Indices
|
||||
|
||||
**Index Names**: `{entity_type}-{chain_id}` (e.g., `addresses-138`)
|
||||
|
||||
**Benefits**:
|
||||
- Independent scaling per chain
|
||||
- Chain-specific optimizations
|
||||
- Easy chain addition/removal
|
||||
|
||||
### Global Index (Optional)
|
||||
|
||||
**Use Case**: Quick lookup across all chains
|
||||
|
||||
**Implementation**:
|
||||
- Separate index with chain_id field
|
||||
- Less detailed than per-chain indices
|
||||
- Faster for simple queries
|
||||
|
||||
## API Endpoint
|
||||
|
||||
### Unified Search
|
||||
|
||||
`GET /api/v1/search`
|
||||
|
||||
**Query Parameters**:
|
||||
- `q` (string, required): Search query
|
||||
- `chain_id` (integer, optional): Filter by chain
|
||||
- `type` (string, optional): Filter by type (address, transaction, block, token, contract)
|
||||
- `limit` (integer, default: 50): Max results
|
||||
|
||||
**Response**: Unified search results (see format above)
|
||||
|
||||
## References
|
||||
|
||||
- Search Index Schema: See `../database/search-index-schema.md`
|
||||
- Multi-chain Indexing: See `multichain-indexing.md`
|
||||
|
||||
Reference in New Issue
Block a user