βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Client Application β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β HTTP Request
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Express HTTP Server β
β (src/index.ts) β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β Route to Controller
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Deposit Controller β
β (src/controllers/depositController.ts) β
β β
β β’ Request validation β
β β’ Error mapping (CircuitBreakerOpenError β 502) β
β β’ Response formatting β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β Call Service
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Transaction Builder Service β
β (src/services/transactionBuilder.ts) β
β β
β β’ buildVaultDepositTransaction() β
β β’ loadAccount() β
β β’ fetchBaseFee() β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β Wrapped with Resilience
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Circuit Breaker β
β (src/lib/circuitBreaker.ts) β
β β
β ββββββββββββ ββββββββββββ ββββββββββββββββ β
β β CLOSED βββββββΊβ OPEN βββββββΊβ HALF_OPEN β β
β β (Normal) β β(Fast-Fail)β β (Testing) β β
β ββββββ¬ββββββ ββββββββββββ ββββββββ¬ββββββββ β
β β β β
β βββββββββββββββββββββββββββββββββββββββββ β
β β
β β’ State management β
β β’ Failure counting β
β β’ Cooldown timing β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β If CLOSED or HALF_OPEN
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Retry Mechanism β
β (src/lib/retry.ts) β
β β
β Attempt 1: Immediate β
β Attempt 2: ~1000ms (exponential backoff) β
β Attempt 3: ~2000ms (with jitter) β
β β
β β’ Exponential backoff β
β β’ Jitter to prevent thundering herd β
β β’ Configurable max attempts β
ββββββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
β Network Call
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Stellar Horizon API β
β (horizon-testnet.stellar.org) β
β β
β β’ loadAccount(publicKey) β
β β’ feeStats() β
β β’ Transaction submission β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Client
β
β POST /api/deposits/build
βΌ
Controller (validate request)
β
β Valid
βΌ
Transaction Builder
β
β buildVaultDepositTransaction()
βΌ
Circuit Breaker (CLOSED)
β
β Allow
βΌ
Retry Mechanism
β
β Attempt 1
βΌ
Horizon API
β
β 200 OK
βΌ
Return Account Data
β
βΌ
Build Transaction
β
βΌ
Return XDR
β
βΌ
Controller (format response)
β
β 200 OK
βΌ
Client
Client
β
β POST /api/deposits/build
βΌ
Controller
β
βΌ
Transaction Builder
β
βΌ
Circuit Breaker (CLOSED)
β
βΌ
Retry Mechanism
β
β Attempt 1
βΌ
Horizon API
β
β Network Timeout β
βΌ
Retry Mechanism
β
β Wait ~1000ms (backoff)
β Attempt 2
βΌ
Horizon API
β
β 200 OK β
βΌ
Return Account Data
β
βΌ
Build Transaction
β
βΌ
Return XDR
β
βΌ
Controller (200 OK)
β
βΌ
Client
Client
β
β POST /api/deposits/build (Request 1)
βΌ
Circuit Breaker (CLOSED)
β
β consecutiveFailures: 0
βΌ
Retry β Horizon API β (All attempts fail)
β
β consecutiveFailures: 1
βΌ
Controller (502 Bad Gateway)
β
βΌ
Client
βββββββββββββββββββββββββββββ
Client
β
β POST /api/deposits/build (Request 2-5)
βΌ
Circuit Breaker (CLOSED)
β
β consecutiveFailures: 1-4
βΌ
Retry β Horizon API β (All attempts fail)
β
β consecutiveFailures: 2-5
βΌ
Controller (502 Bad Gateway)
β
βΌ
Client
βββββββββββββββββββββββββββββ
Client
β
β POST /api/deposits/build (Request 6)
βΌ
Circuit Breaker (CLOSED)
β
β consecutiveFailures: 5
βΌ
Retry β Horizon API β (All attempts fail)
β
β consecutiveFailures: 6 β₯ threshold (5)
β STATE TRANSITION: CLOSED β OPEN π΄
βΌ
Controller (502 Bad Gateway)
β
βΌ
Client
βββββββββββββββββββββββββββββ
Client
β
β POST /api/deposits/build (Request 7+)
βΌ
Circuit Breaker (OPEN)
β
β Fast-fail immediately β‘
β No network call made
βΌ
CircuitBreakerOpenError
β
βΌ
Controller (502 Bad Gateway)
β
βΌ
Client
Circuit Breaker (OPEN)
β
β Wait cooldown period (30s)
β
β STATE TRANSITION: OPEN β HALF_OPEN π‘
βΌ
Client
β
β POST /api/deposits/build (Probe request)
βΌ
Circuit Breaker (HALF_OPEN)
β
β Allow single probe
βΌ
Retry β Horizon API
β
β 200 OK β
β
β STATE TRANSITION: HALF_OPEN β CLOSED π’
βΌ
Return Success
β
βΌ
Controller (200 OK)
β
βΌ
Client
βββββββββββββββββββββββββββββ
Circuit Breaker (CLOSED)
β
β Normal operation resumed
β consecutiveFailures: 0
βΌ
All subsequent requests succeed
Responsibilities:
- HTTP request/response handling
- Request validation
- Error mapping to HTTP status codes
- Response formatting
Does NOT:
- Business logic
- Direct Horizon calls
- Retry logic
- State management
Responsibilities:
- Business logic
- Transaction building
- Account loading
- Fee fetching
Does NOT:
- HTTP concerns
- Error status code mapping
- Request validation
Responsibilities:
- Retry with exponential backoff
- Circuit breaker state management
- Failure counting
- Cooldown timing
Does NOT:
- Business logic
- HTTP concerns
- Stellar-specific logic
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Error Types β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Network Error (Horizon)
β
βΌ
Retry Mechanism
β
βββΊ Success after retry β Return result
β
βββΊ All retries fail
β
βΌ
RetryExhaustedError
β
βΌ
Circuit Breaker (increment failures)
β
βββΊ Below threshold β Propagate error
β
βββΊ At threshold β Transition to OPEN
β
βΌ
CircuitBreakerOpenError (future requests)
β
βΌ
Controller (map to BadGatewayError)
β
βΌ
HTTP 502 Response
β
βΌ
Client
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Circuit Breaker State Machine β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
ββββββββββββββββββββ
β CLOSED β
β (Normal Op) β
β β
β β’ Allow requests β
β β’ Count failures β
β β’ Reset on successβ
ββββββββββ¬ββββββββββ
β
β consecutiveFailures β₯ threshold
β
βΌ
ββββββββββββββββββββ
β OPEN β
β (Fast-Fail) β
β β
β β’ Reject requestsβ
β β’ No network callsβ
β β’ Start cooldown β
ββββββββββ¬ββββββββββ
β
β cooldown elapsed
β
βΌ
ββββββββββββββββββββ
β HALF_OPEN β
β (Testing) β
β β
β β’ Allow 1 probe β
β β’ Test recovery β
ββββββββββ¬ββββββββββ
β
ββββββββββ΄βββββββββ
β β
Success Failure
β β
βΌ βΌ
βββββββββββ βββββββββββ
β CLOSED β β OPEN β
βββββββββββ βββββββββββ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Configuration Flow β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Environment Variables (.env)
β
βββΊ HORIZON_URL
βββΊ STELLAR_BASE_FEE
βββΊ CIRCUIT_BREAKER_THRESHOLD
βββΊ CIRCUIT_BREAKER_COOLDOWN_MS
βββΊ RETRY_MAX_ATTEMPTS
βββΊ RETRY_BASE_DELAY_MS
β
βΌ
Transaction Builder Config
β
βββΊ Circuit Breaker Instance
β β
β βββΊ failureThreshold
β cooldownMs
β
βββΊ Retry Config
β
βββΊ maxAttempts
baseDelayMs
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Metrics Collection β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Circuit Breaker
β
βββΊ state (CLOSED/OPEN/HALF_OPEN)
βββΊ consecutiveFailures
βββΊ consecutiveSuccesses
βββΊ totalFailures
βββΊ totalSuccesses
βββΊ lastFailureTime
βββΊ lastStateChange
β
βΌ
GET /api/deposits/health
β
βΌ
JSON Response
β
βΌ
Monitoring System
β
βββΊ Alert on state=OPEN
βββΊ Track failure rate
βββΊ Dashboard visualization
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Production Deployment β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Load Balancer
β
βββΊ Instance 1 (Circuit Breaker A)
β β
β βββΊ Horizon Testnet
β
βββΊ Instance 2 (Circuit Breaker B)
β β
β βββΊ Horizon Testnet
β
βββΊ Instance 3 (Circuit Breaker C)
β
βββΊ Horizon Testnet
Note: Each instance has its own circuit breaker state.
For shared state, consider Redis or distributed circuit breaker.
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Test Layers β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Unit Tests (lib/)
β
βββΊ retry.test.ts
β β
β βββΊ Mock operations
β βββΊ Fake timers
β βββΊ Test backoff timing
β
βββΊ circuitBreaker.test.ts
β
βββΊ Mock operations
βββΊ Test state transitions
βββΊ Test thresholds
Integration Tests (services/)
β
βββΊ transactionBuilder.test.ts
β
βββΊ Mock Stellar SDK
βββΊ Test retry integration
βββΊ Test circuit breaker integration
HTTP Tests (controllers/)
β
βββΊ depositController.test.ts
β
βββΊ Mock transaction builder
βββΊ Test error mapping
βββΊ Test HTTP responses
The architecture implements a layered approach with clear separation of concerns:
- HTTP Layer - Request/response handling
- Business Layer - Transaction building logic
- Resilience Layer - Retry and circuit breaker
- Network Layer - Stellar Horizon API
Each layer has a single responsibility and communicates through well-defined interfaces, making the system maintainable, testable, and resilient to failures.