Skip to content

Latest commit

Β 

History

History
560 lines (506 loc) Β· 18.9 KB

File metadata and controls

560 lines (506 loc) Β· 18.9 KB

Architecture Diagram

System Overview

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         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                                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Request Flow

Successful Request

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

Transient Failure with Retry

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

Circuit Breaker Trip

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 Recovery

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

Component Responsibilities

Controller Layer (src/controllers/)

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

Service Layer (src/services/)

Responsibilities:

  • Business logic
  • Transaction building
  • Account loading
  • Fee fetching

Does NOT:

  • HTTP concerns
  • Error status code mapping
  • Request validation

Resilience Layer (src/lib/)

Responsibilities:

  • Retry with exponential backoff
  • Circuit breaker state management
  • Failure counting
  • Cooldown timing

Does NOT:

  • Business logic
  • HTTP concerns
  • Stellar-specific logic

Error Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         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

State Diagram

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                  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   β”‚
              β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜       β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Data Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    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

Monitoring Flow

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                      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

Deployment Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    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.

Testing Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                        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

Summary

The architecture implements a layered approach with clear separation of concerns:

  1. HTTP Layer - Request/response handling
  2. Business Layer - Transaction building logic
  3. Resilience Layer - Retry and circuit breaker
  4. 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.