This document provides a comprehensive overview of the Agglayer Bridge Hub architecture, design decisions, and system internals.
- System Overview
- Package Architecture
- Data Flow
- Database Design
- API Design
- Security Architecture
- Scalability Considerations
- Design Decisions
The Agglayer Bridge Hub is a microservices-based system designed to facilitate cross-chain bridge transactions. It consists of four main packages that work together to monitor, index, expose, and automatically claim bridge transactions.
┌──────────────────────────────────────────────────────────────────┐
│ External Systems │
├──────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ Aggkit │ │ Blockchain │ │ MongoDB │ │
│ │ Bridge │ │ │ │ Database │ │
│ │ service │ │ │ │ │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ │
└─────────┼─────────────────┼─────────────────┼────────────────────┘
│ │ │
▼ ▼ ▼
┌──────────────────────────────────────────────────────────────────┐
│ Bridge Hub Packages │
│ │
│ ┌───────────────┐ │
│ │ COMMONS │ │
│ │ (Shared Types)│ │
│ └───────┬───────┘ │
│ │ │
│ ┌─────────────┼─────────────┐ │
│ │ │ │ │
│ ▼ ▼ ▼ │
│ ┌──────────┐ ┌─────────┐ ┌───────────┐ │
│ │ CONSUMER │ │ API │ │AUTO-CLAIM │ │
│ │ (Indexer)│ │(Service)│ │(Claimer) │ │
│ └─────┬────┘ └────┬────┘ └─────┬─────┘ │
│ │ │ │ │
│ │ Writes │ Reads │ HTTP │
│ ▼ ▼ ▼ │
│ ┌──────────────────────────┐ ┌─────────────┐ │
│ │ MongoDB Database │ │ Blockchain │ │
│ └──────────────────────────┘ └─────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
The Bridge Hub is designed to index multiple blockchain networks simultaneously. Each network connected to the Agglayer has a unique network ID (e.g., 0 for Ethereum, 1 for zkEVM, etc.). The production deployment runs one consumer instance per source network to index bridge transactions.
┌──────────────────────────────────────────────────────────────────────────────┐
│ AGGLAYER HUB API CLUSTER │
├──────────────────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ ┌─────────────────────────────────┐ │
│ │ Aggkit │ │ netId_0 Consumer │ │
│ │ Bridge │──────▶ │ ┌───────────────────────────┐ │ │
│ │ Service │ │ │ bridgesCron │ │ │
│ │ (net 0) │ │ │ claimsCron │ │──┐ │
│ └─────────────┘ │ │ readyToClaimCron │ │ │ │
│ │ │ mappingsCron │ │ │ │
│ │ └───────────────────────────┘ │ │ │
│ └─────────────────────────────────┘ │ │
│ │ │
│ ┌─────────────┐ ┌─────────────────────────────────┐ │ │
│ │ Aggkit │ │ netId_1 Consumer │ │ │
│ │ Bridge │──────▶ │ ┌───────────────────────────┐ │ │ │
│ │ Service │ │ │ bridgesCron │ │ │ │
│ │ (net 1) │ │ │ claimsCron │ │──┤ │
│ └─────────────┘ │ │ readyToClaimCron │ │ │ │
│ │ │ mappingsCron │ │ │ │
│ │ └───────────────────────────┘ │ │ │
│ └─────────────────────────────────┘ │ │
│ │ │
│ ┌─────────────┐ ┌─────────────────────────────────┐ │ │
│ │ Aggkit │ │ netId_n Consumer │ │ │
│ │ Bridge │──────▶ │ ┌───────────────────────────┐ │ │ │
│ │ Service │ │ │ bridgesCron │ │ │ │
│ │ (net n) │ │ │ claimsCron │ │──┤ │
│ └─────────────┘ │ │ readyToClaimCron │ │ │ │
│ │ │ mappingsCron │ │ │ │
│ │ └───────────────────────────┘ │ │ │
│ └─────────────────────────────────┘ │ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────┐ │
│ │ MongoDB Database │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ Collections (per environment): │ │ │
│ │ │ • bridge_hub_api_transactions │ │ │
│ │ │ • bridge_hub_api_mappings │ │ │
│ │ │ • bridge_hub_api_metadata │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └────────────┬───────────────────────────────┘ │
│ │ │
│ ▼ Reads from │
│ ┌────────────────────────────────────────────┐ │
│ │ API Service │ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ /transactions │ │ │
│ │ │ /token-mappings │ │ │
│ │ │ /token-metadata │ │ │
│ │ │ /claim-proof (proxies to Aggkit) │ │───┐ │
│ │ └──────────────────────────────────────┘ │ │ │
│ └────────────────────────────────────────────┘ │ │
│ │ │
│ HTTP Calls │ │
│ ┌─────────────────────────────────────────────┐ │ │
│ │ Auto-Claim Service (per dest network) │◀─┘ │
│ │ ┌──────────────────────────────────────┐ │ │
│ │ │ Polls /transactions │ │ │
│ │ │ Fetches /claim-proof │ │ │
│ │ │ Submits claims to blockchain │ │ │
│ │ └──────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────────────────┘
Key Architecture Points:
- Consumer Instances: One per source network being indexed (netId_0, netId_1, etc.)
- Naming Convention:
netId_Xis a generalized naming; actual network IDs are 0=Ethereum, 1=zkEVM, etc. - Shared Database: All consumers write to the same MongoDB instance
- Single API: One API service reads from the database and serves all networks
- Auto-Claim Deployment: One instance per destination network you want to auto-claim for
Each blockchain network connected to the Agglayer operates its own Aggkit Bridge Service:
- Ownership: Maintained by the chain operators (not part of Bridge Hub deployment)
- Purpose: Monitors blockchain events and indexes bridge-related data
- Interface: Exposes APIs for bridge transactions, claims, mappings, and L1 info tree data
- Consumer Connection: Each Bridge Hub consumer connects to the corresponding chain's Aggkit service
Important: The consumer does NOT directly monitor the blockchain. Instead, it polls the Aggkit Bridge Service APIs to fetch indexed data.
| Component | Layer | Responsibility |
|---|---|---|
| Commons | Foundation | Shared types, interfaces, schemas |
| Consumer | Data Ingestion | Monitor blockchain, index transactions |
| API | Service | Expose bridge tx data, serve claim-proofs |
| Auto-Claim | Automation | Automatically claim ready transactions |
The Consumer package consists of two main components that run within a single Node.js process:
Contains three cron jobs that fetch data from the Aggkit Bridge Service:
1. bridgesCron
- Purpose: Fetches new bridge deposit transactions
- Data Source: Polls Aggkit Bridge Service API for bridge events
- Database Action: Inserts new transactions into
transactionscollection with statusBRIDGED - Metadata Tracking: Updates
lastIndexedBridgeDepositCountin metadata collection
2. claimsCron
- Purpose: Fetches claim events that occurred on the blockchain
- Data Source: Polls Aggkit Bridge Service API for claim events
- Database Action: Updates transactions in
transactionscollection to statusCLAIMED, addsclaimTransactionHashand timestamp - Metadata Tracking: Updates
lastIndexedClaimBlockNumberin metadata collection
3. mappingsCron
- Purpose: Fetches token mapping events on the chain
- Data Source: Polls Aggkit Bridge Service API for tokenMapping events
- Database Action: Inserts/updates token mappings in
mappingscollection - Metadata Tracking: Updates
lastIndexedMappingBlockNumberin metadata collection
Contains one cron job:
4. readyToClaimCron
- Purpose: Determines when transactions become claimable
- Data Source: Polls Aggkit Bridge Service API for L1 info tree updates
- Database Action: Updates transactions from
BRIDGEDtoREADY_TO_CLAIMstatus, setsleafIndexForProof - Logic: Compares L1 info tree data with transaction data to determine claim readiness
Aggkit Bridge Service (per network)
│
├── /bridges API ────▶ bridgesCron ────▶ transactions collection (BRIDGED)
│
├── /claims API ─────▶ claimsCron ─────▶ transactions collection (CLAIMED)
│
├── /mappings API ───▶ mappingsCron ───▶ mappings collection
│
└── /l1-info-tree ───▶ readyToClaimCron ▶ transactions collection (READY_TO_CLAIM)
Key Points:
- All 4 crons run in a single Node.js process per network
- Crons are scheduled jobs that run at configured intervals
- Consumer does NOT directly monitor blockchain - it polls Aggkit APIs
- Metadata collection tracks indexing progress for resume capability after restarts
Purpose: Type-safe contracts between packages
@agglayer/bridge-hub-commons
├── interfaces/ # TypeScript interfaces
│ ├── bridge_transaction.ts
│ ├── transaction_document.ts
│ ├── proof.ts
│ └── ...
├── enums/ # Enumeration types
│ └── transaction_status.ts
└── index.ts # Main export
Key Patterns:
- Pure TypeScript types (no runtime code)
- Interface segregation (small, focused interfaces)
- Shared across all packages via workspace dependency
Design Decision: Centralizing types prevents inconsistencies and reduces maintenance overhead.
Purpose: Event-driven blockchain indexer
bridge-hub-consumer
├── src/
│ ├── bridge_api_consumer.ts # Polls Bridge Service API
│ ├── claim_readiness_consumer.ts # Monitors blockchain
│ ├── services/ # Data access layer
│ │ ├── transaction.ts
│ │ ├── mapping.ts
│ │ └── metadata.ts
│ ├── mappers/ # Data transformation
│ └── interfaces/ # Local type definitions
Architecture Pattern: Event-Driven with Polling
┌──────────────────┐
│ BridgeAPI │
│ Consumer │ ← Poll every 10s
└────────┬─────────┘
│
▼
┌────────────┐
│ MongoDB │
│ (Write) │
└────────────┘
┌──────────────────┐
│ ClaimReadiness │
│ Consumer │ ← Polls transactions in Bridged status
└────────┬─────────┘ every 10s and updates the status
│
▼
┌────────────┐
│ MongoDB │
│ (Update) │
└────────────┘
Key Patterns:
- Polling: Bridge API Consumer uses time-based polling
- Event Listening: Claim Readiness Consumer listens to blockchain events
- Idempotent Writes: Uses upsert operations to handle duplicate events
- Cursor-Based Pagination: Tracks
depositCountto avoid reprocessing
Design Decision: Separate consumers allow independent scaling and failure isolation.
Purpose: RESTful API with OpenAPI documentation
bridge-hub-api
├── src/
│ ├── server.ts # Application entry point
│ ├── routes/ # Route definitions
│ │ ├── transactions.ts
│ │ ├── proof.ts
│ │ └── index.ts
│ ├── controllers/ # Request handling
│ ├── services/ # Business logic
│ │ ├── transactions.ts
│ │ ├── proof.ts
│ │ ├── mappings.ts
│ │ └── token_metadata.ts
│ ├── schemas/ # Zod validation schemas
│ └── middlewares/ # Custom middleware
Architecture Pattern: Layered Architecture
Request
│
▼
┌──────────────┐
│ Router │ ← Route matching
└──────┬───────┘
│
▼
┌──────────────┐
│ Middleware │ ← CORS, input validation, logging, error handling
└──────┬───────┘
│
▼
┌──────────────┐
│ Controller │ ← Routing request to corresponding service and response formatting
└──────┬───────┘
│
▼
┌──────────────┐
│ Service │ ← Business logic
└──────┬───────┘
│
▼
┌──────────────┐
│ MongoDB │ ← Data persistence
└──────────────┘
Key Patterns:
- OpenAPI-First: Routes defined with Zod schemas for automatic validation
- Cursor-Based Pagination: Uses
startAfterfor consistent results - Stateless Design: No session state, horizontally scalable
- Structured Errors: Consistent error response format
Design Decision: Layered architecture provides clear separation of concerns and testability.
Purpose: Automated transaction claiming
auto-claim-service
├── src/
│ ├── index.ts # Entry point with polling loop
│ ├── services/
│ │ ├── auto-claim.ts # Claiming orchestration
│ │ └── transaction.ts # API client
│ └── constants/
│ └── bridge.ts # Bridge contract ABI
Architecture Pattern: Polling with State Machine
┌─────────────────┐
│ Poll API │
│ (30s interval) │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Filter Txs │
└────────┬────────┘
│
▼
┌─────────────────┐
│ For Each Tx: │
│ 1. Get Proof │
│ 2. Compute Index│
│ 3. Submit Claim │
│ 4. Wait Confirm │
└────────┬────────┘
│
▼
┌─────────────────┐
│ Sleep 30s │
└────────┬────────┘
│
└──────→ (repeat)
Key Patterns:
- Sequential Processing: Claims processed one at a time to avoid nonce issues
- Error Isolation: Errors on one transaction don't affect others
- Confirmation Waiting: Always waits for transaction confirmation
- Idempotent: Safe to run multiple times (blockchain enforces uniqueness)
Design Decision: Sequential processing is simpler and safer than parallel processing with nonce management.
1. USER ACTION
User bridges tokens from L1 → L2
▼
2. CONSUMER: Initial Indexing
BridgeAPIConsumer polls Bridge Service API
→ Fetches new transaction
→ Maps to IHubTransaction
→ Saves to MongoDB (status: BRIDGED)
▼
3. CONSUMER: Claim Readiness Detection
ClaimReadinessConsumer polls txs in bridged status
→ Detects L1 info tree update
→ Updates transaction (status: READY_TO_CLAIM)
→ Sets leafIndex and leafIndexForProof
▼
4. API: Data Exposure
API exposes transaction via GET /transactions
→ Filters by status=READY_TO_CLAIM
→ Returns transaction with pagination
▼
5. AUTO-CLAIM: Discovery
AutoClaimService polls API
→ GET /transactions?status=READY_TO_CLAIM
→ Finds claimable transaction
▼
6. AUTO-CLAIM: Proof Fetching
AutoClaimService fetches proof
→ GET /claim-proof?sourceNetworkId=X&depositCount=Y&leafIndex=Z
→ Receives merkle proof
▼
7. AUTO-CLAIM: Transaction Submission
AutoClaimService submits claim
→ Computes global index
→ Calls bridge.claimAsset() or bridge.claimMessage()
→ Waits for confirmation
▼
8. CONSUMER: Claim Detection
ClaimReadinessConsumer detects claim event
→ Updates transaction (status: CLAIMED)
→ Saves claim transaction hash
→ Updates claim timestamp
The system maintains eventual consistency through event-driven updates:
- Write Path: Consumer → MongoDB
- Read Path: API ← MongoDB
- Claim Path: Auto-Claim → Blockchain
Consistency Guarantees:
- Transactions are immutable once created
- Status updates are atomic
- Duplicate events are handled via upsert
- No distributed transactions needed
The Bridge Hub uses a single shared MongoDB instance across all network indexers and the API service. This centralized database approach simplifies operations while supporting horizontal scaling through replica sets.
Deployment Options:
- Single Instance: For development or low-traffic deployments
- Replica Set: For high availability and read scaling in production
- Sharding: Optional for very high transaction volumes (shard by network or date)
Collections are organized by environment, using the naming convention:
bridge_hub_api_[type]_[environment]
Environments:
- No suffix: Mainnet/production data
_testnet: Testnet data_devnet: Development network data
Collection Types:
bridge_hub_api_transactions
bridge_hub_api_transactions_testnet
bridge_hub_api_transactions_devnet
- Purpose: Store all bridge transactions across all networks
- Modified By:
bridgesCron(upserts),claimsCron(updates),readyToClaimCron(updates) - Key Fields:
hubUID,sourceNetwork,destinationNetwork,status,depositCount - Status Values:
BRIDGED→LEAF_INCLUDED→READY_TO_CLAIM→CLAIMED
bridge_hub_api_mappings
bridge_hub_api_mappings_testnet
bridge_hub_api_mappings_devnet
- Purpose: Store token address mappings between Agglayer networks
- Modified By:
mappingsCron(inserts/updates) - Key Fields:
originNetwork,originTokenAddress,wrappedTokenAddress,destinationNetwork
bridge_hub_api_metadata
bridge_hub_api_metadata_testnet
bridge_hub_api_metadata_devnet
- Purpose: Track indexing progress per network for resume capability
- Modified By: All cron jobs (update their respective checkpoint)
- Document per Network: One document per
NETWORK_IDbeing indexed
Metadata Document Schema:
{
_id: "lastIndexedTransactions", // Document ID
networkId: 0, // Network being indexed (0, 1, etc.)
lastIndexedBridgeDepositCount: 12345, // Resume point for bridgesCron
lastIndexedClaimBlockNumber: 5678900, // Resume point for claimsCron
lastIndexedMappingBlockNumber: 5678900, // Resume point for mappingsCron
lastUpdated: ISODate("2024-01-27T10:00:00Z")
}When a consumer instance restarts (planned maintenance, crash, deployment), it needs to know where to resume indexing. Without metadata:
- Problem: Consumer would re-index from genesis block (hours/days of duplicate work)
- Solution: Consumer reads metadata collection to find last indexed position
- Behavior: Each cron job queries its checkpoint field and resumes from that point
Example Resume Flow:
- Consumer starts for network 1 (zkEVM)
bridgesCronreadslastIndexedBridgeDepositCount→ resumes from deposit #12346claimsCronreadslastIndexedClaimBlockNumber→ resumes from block #5678901mappingsCronreadslastIndexedMappingBlockNumber→ resumes from block #5678901
Consumers (Write-Heavy):
- Upserts new transactions (bridgesCron)
- Update transaction status (claimsCron, readyToClaimCron)
- Upsert token mappings (mappingsCron)
- Update metadata checkpoints (all crons)
API (Read-Heavy):
- Query transactions by status, network, filters
- Query token mappings by network and address
- Generate proofs (proxied to Aggkit, not from DB)
Auto-Claim (Read-Only via API):
- No direct database access
- Calls API endpoints over HTTP
{
_id: ObjectId, // MongoDB primary key
hubUID: String (unique), // Business key
// Network Information
sourceNetwork: Number, // Source chain ID
destinationNetwork: Number, // Destination chain ID
// Transaction Details
transactionHash: String, // Source transaction hash
blockNumber: Number, // Block number on source
timestamp: Number, // Unix timestamp
bridgeHash: String,
// Bridge Details
leafType: String, // "ASSET" or "MESSAGE"
originTokenNetwork: Number,
originTokenAddress: String,
receiverAddress: String,
fromAddress: String,
amount: String, // BigInt as string
depositCount: Number, // Deposit counter
// Claiming Details
leafIndexForProof: Number, // Index for merkle proof
globalIndex: String, // Global index as string
// Status Tracking
status: String, // BRIDGED, LEAF_INCLUDED, READY_TO_CLAIM, CLAIMED
lastUpdatedAt: Number, // Last update timestamp
// Claim Information (populated after claim)
claimTransactionHash: String,
claimBlockNumber: Number,
claimTimestamp: Number
}Indexes:
{
hubUID: 1 // Unique index
status: 1, // Query by status
{ sourceNetwork: 1, destinationNetwork: 1 }, // Filter by networks
depositCount: 1, // Order by deposit count
{ status: 1, destinationNetwork: 1 } // Combined index for common queries
}{
_id: ObjectId,
originNetwork: Number,
originTokenAddress: String,
wrappedTokenAddress: String,
destinationNetwork: Number,
// ... metadata fields
}{
_id: String, // Document type identifier
lastIndexedBridgeDepositCount: Number, // Last indexed deposit count
lastIndexedClaimBlockNumber: Number // Last indexed claim block number
lastIndexedMappingBlockNumber: Number // Last indexed mappings block number
}The API follows REST conventions:
- Resources: Transactions, proofs, mappings, metadata
- HTTP Methods: GET (read-only API)
- Status Codes: 200 (success), 400 (bad request), 404 (not found), 500 (server error)
- Content Type:
application/json
Cursor-Based Pagination:
GET /transactions?limit=50
→ Returns first 50 transactions
→ Includes nextStartAfterCursor if more exist
GET /transactions?limit=50&startAfter=<cursor>
→ Returns next 50 transactions after cursor
Benefits:
- Stable results (no skipping/duplicates on concurrent updates)
- Efficient for large datasets
- No deep pagination performance issues
The API proxies merkle proofs for claiming from the respective Aggkit instances:
Inputs:
sourceNetworkId: Source chain IDdepositCount: Deposit counter valueleafIndex: Leaf index for proof in merkle tree
Process:
- Fetch transaction data from source chain for metadata
- Proxy claim proofs from the source chain's Aggkit proof endpoint
Output:
{
"proof_local_exit_root": ["0x...", "0x..."],
"proof_rollup_exit_root": ["0x...", "0x..."],
"l1_info_tree_leaf": {
/* L1 info */
},
"bridge_tx_metadata": "0x..."
}Note: For security vulnerability reporting and Polygon's bug bounty program, see SECURITY.md.
Input Validation:
- All inputs validated via Zod schemas
- Type safety enforced at TypeScript level
- Query parameter sanitization
Error Handling:
- No sensitive data in error messages
- Structured error responses
- Errors logged with context for debugging
CORS:
- Configurable origins
- Credentials not allowed
- Pre-flight requests supported
Private Key Management:
- Never logged or exposed
- Loaded from environment variables
- Should use secret management systems in production
Transaction Safety:
- Claims are atomic (all-or-nothing)
- Blockchain enforces uniqueness (can't double-claim)
- Failed transactions don't lose funds (reverted)
Wallet Isolation:
- Dedicated wallet for auto-claim only
- Minimal funding (just enough for gas)
- Monitor for unusual activity
Access Control:
- Connection string in environment variables
- MongoDB authentication required
- Network isolation recommended
Data Integrity:
- Unique constraints on business keys
- Atomic updates for status changes
- No cascading deletes
API Package:
- ✅ Stateless design
- ✅ Can run multiple instances behind load balancer
- ✅ No session state
- ✅ MongoDB connection pooling
Consumer Package:
⚠️ Run one instance per network⚠️ Coordination needed for multiple instances- ✅ Can scale by adding more networks
Auto-Claim Package:
⚠️ Sequential processing (one instance per destination)⚠️ Multiple instances cause nonce conflicts- ✅ Can scale by destination network
Database:
- Indexes for common queries
- Connection pooling
- Read replicas for API reads
- Separate write/read concerns
Performance Bottlenecks:
- MongoDB Queries: Solved with proper indexing
- Proof Generation: Computation simplified with proxying proof from Aggkit
Pros:
- Fast startup time
- Built-in TypeScript support
- Native test runner
- NPM-compatible
Cons:
- Relatively new ecosystem
- Some packages may not work
Decision: Benefits outweigh risks for this project's scope.
Pros:
- Flexible schema for evolving transaction data
- Good query performance with indexes
- Easy horizontal scaling
- JSON-native (matches API responses)
Cons:
- No ACID transactions across documents
- Eventual consistency
Decision: Transaction data doesn't require strong consistency, flexible schema is beneficial.
Pros:
- Independent deployment
- Clear boundaries
- Easier testing
- Team autonomy
Cons:
- More complex deployment
- Inter-package communication overhead
Decision: Microservices approach provides better scalability and maintainability.
Pros:
- Simple nonce management
- No coordination needed
- Easier error handling
Cons:
- Lower throughput
- Slower processing
Decision: Simplicity and reliability are more important. Can introduce batch processing in future.
Pros:
- Stable results
- No deep pagination issues
- Efficient for large datasets
Cons:
- Can't jump to arbitrary pages
- Slightly more complex implementation
Decision: Stability and performance are critical for API reliability.
All packages use structured logging:
Logger.info({
location: "Service.method",
action: "description",
data: {
/* relevant context */
},
duration: 123,
});Log Levels:
debug: Detailed information for debugginginfo: General information about system operationwarn: Warning conditionserror: Error conditions requiring attention
Consumer:
- Transactions indexed per minute
- Time lag between bridge event and indexing
- API poll success rate
- MongoDB write latency
API:
- Request rate
- Response time (p50, p95, p99)
- Error rate
- Cache hit rate (if implemented)
Auto-Claim:
- Claims per hour
- Claim success rate
- Gas costs per claim
- Time from READY_TO_CLAIM to CLAIMED
Each service should expose health endpoint:
GET /health-check
{
"status": "success",
"data": {
"status": "success",
"message": "All services are working correctly"
}
}
The Agglayer Bridge Hub architecture provides a robust, scalable solution for bridge transaction management. The separation of concerns, clear data flow, and comprehensive error handling ensure system reliability and maintainability.
For deployment details, see DEPLOYMENT.md.
For contributing guidelines, see CONTRIBUTING.md.