Skip to content

Latest commit

 

History

History
78 lines (62 loc) · 2.56 KB

File metadata and controls

78 lines (62 loc) · 2.56 KB

Technical Decisions

Goal System (v0.1.4)

Holdings vs Value Goals

Problem: The original goal system converted total portfolio value to the target currency. This meant having 0 ZEC but equivalent BTC would show "ZEC goal met" — misleading for users who want to accumulate a specific asset.

Solution: Two distinct goal types:

  • Holdings goals: Compare actual asset holdings to target ("I want to own 10 ZEC")
  • Value goals: Compare total portfolio value converted to target currency ("I want portfolio worth 0.1 BTC")

Goal ID Management

  • IDs are simple integers starting at 1
  • next_goal_id only increments, never decrements
  • Deleted goal IDs are never reused
  • Ensures stable references for users managing multiple goals

Config Schema v2

{
  "version": 2,
  "goals": [
    { "id": 1, "type": "holdings", "asset": "zec", "operator": ">=", "target": "10", "created_at": 1737108600000 }
  ],
  "next_goal_id": 2
}
  • Goals stored as array (not object) for ordering and ID management
  • Target stored as string for decimal.js precision
  • Timestamps as epoch ms to avoid timezone issues

Migration Strategy

  • Automatic, non-interactive (works in scripts/CI)
  • Creates .backup file before migrating
  • Old goals converted to "value" type (preserves original behavior)
  • One-time warning printed to stderr

TTY Detection

const isInteractive = process.stdin.isTTY && process.stdout.isTTY;
  • Interactive wizard when TTY detected and no arguments
  • List goals when non-TTY (for scripts/pipes)

Shorthand Syntax

shieldstack goal btc 0.1 defaults to "value" type for backwards compatibility with v0.1.2/v0.1.3 behavior.

Storage (v0.1.0+)

Atomic Writes

All file writes use tmp-then-rename pattern:

await fs.writeFile('config.json.tmp', data);
await fs.rename('config.json.tmp', 'config.json');

Prevents corruption if process interrupted mid-write.

Decimal Handling

  • Use decimal.js for all calculations
  • Convert to primitives before storage (never store Decimal objects)
  • Target amounts stored as strings in config for precision

API Integration

CoinGecko

  • Single API source for MVP simplicity
  • 5-minute cache for current prices
  • 24-hour cache for historical data
  • Graceful degradation: use cache on failure, warn on stderr
  • User-Agent header includes package version

Display

Progress Bar Clamping

Progress percentages can exceed 100% (goal exceeded), but bars clamp at 100% to prevent visual overflow.

Goal Sorting

Dashboard sorts goals: unmet first, then by created_at (oldest first).