Skip to main content

Architecture Overview

The SatsTerminal Borrow SDK is designed with separation of concerns and modularity in mind.

High-Level Architecture

Components

BorrowSDK (Facade)

The main entry point that exposes the public API. It orchestrates the internal managers and provides a unified interface for all operations.
const sdk = new BorrowSDK(config);
await sdk.setup();
await sdk.getLoan({ ... });

WalletManager

Handles smart wallet generation and management:
  • Deterministic derivation - Wallets derived from BTC signatures
  • Multi-wallet support - Each loan gets a unique wallet index
  • Signature caching - Persists signatures to avoid re-signing

LoanManager

Manages all loan-related operations:
  • Quote fetching
  • Borrow execution
  • Repayment processing
  • Collateral management
  • Transaction history

WorkflowTracker

Tracks asynchronous workflow status:
  • Polling-based status updates
  • Callback notifications
  • Automatic cleanup on completion

ApiClient

HTTP abstraction layer:
  • Request/response handling
  • Authentication headers
  • Error transformation

StorageAdapter

Storage abstraction with fallbacks:
  • Uses localStorage in browsers
  • Falls back to MemoryStorage in Node.js
  • Supports custom storage providers

Data Flow

Loan Creation Flow

Module Dependencies

BorrowSDK
├── ApiClient
├── WalletManager
│   ├── ApiClient
│   └── StorageAdapter
├── LoanManager
│   └── ApiClient
└── WorkflowTracker
    └── ApiClient

Design Principles

1. Facade Pattern

The BorrowSDK class acts as a facade, hiding the complexity of internal managers behind a simple API.

2. Dependency Injection

Components receive their dependencies through constructors, making them testable and configurable.

3. Separation of Concerns

Each manager handles a specific domain:
  • WalletManager - Wallet operations
  • LoanManager - Loan operations
  • WorkflowTracker - Async tracking

4. Graceful Degradation

Storage falls back gracefully between localStorage and MemoryStorage.

5. Error Boundaries

Typed errors with context enable precise error handling:
try {
  await sdk.getLoan({ ... });
} catch (error) {
  if (error instanceof ApiError) {
    // Handle API errors
  } else if (error instanceof SmartAccountError) {
    // Handle wallet errors
  }
}

File Structure

src
index.ts – Main SDK class, exports
types.ts – Core type definitions
errors.ts – Error classes
workflow-types.ts – Workflow-related types
utils.ts – Utility functions (BtcUtils)
config
types.ts – Config interfaces
defaults.ts – Default values
validator.ts – Config validation
index.ts – Config exports
internal
api-client.ts – HTTP client
loan-manager.ts – Loan operations
wallet-manager.ts – Wallet management
workflow-tracker.ts – Status tracking
storage-adapter.ts – Storage abstraction
smart-account.ts – Account derivation