Skip to main content

State and Storage

State in dappTerminal is split between in-memory execution context (per-tab, volatile) and persistent database storage (Prisma, for faucet and analytics). Observability is handled through structured responses, history, and audit logs.


ExecutionContext (In-Memory)

The runtime state for a single terminal tab. See Concepts: Execution Context for the full shape.

Key fields:

  • activeProtocol — the current fiber M_p.
  • protocolState — per-protocol cache (quotes, routes, tx plans).
  • history — command execution log for UX and debugging.
  • wallet — address, chain ID, and connection status.

Example protocolState shapes:

protocolState:
wormhole:
lastQuote: { bestRoute, quotes, transferRequest }
selectedRouteType: AutomaticCCTPRoute
stargate:
lastQuote: { stargateSteps, fullQuote }
lifi:
selectedRoute: { id, steps, fees }
execution: { stepHashes, updatedAt }

Consistency guidelines:

  • Cache only serializable data inside protocolState (no functions, no class instances).
  • Invalidate cached quotes when wallet.chainId changes.
  • Persist user-facing identifiers (tx hash, request ID) for follow-up commands.
  • Use a lastUpdated timestamp if you need staleness detection.

Persistent Storage (Faucet)

The faucet uses Prisma-backed PostgreSQL models for durability and abuse protection.

Schema: prisma/schema.prisma

Core models:

ModelPurpose
FaucetRequestRequest lifecycle: pending → completed/failed
RateLimitRecordPer-address and per-IP rate limit windows
FaucetConfigPer-network faucet configuration
FaucetAuditLogStructured event history

Primary surfaces:

  • src/lib/faucet/rate-limit-db.ts — DB-backed rate limiting
  • src/lib/faucet/transaction.ts — transaction sending service

Swap and Bridge Tracking

The tracking system records all swap and bridge transactions across protocols, with aggregated statistics for analytics.

Location: src/lib/tracking/swaps.ts

Database Schema

SwapTransaction — individual transaction records:

{
txHash: string
chainId: number
blockNumber?: number
status: 'pending' | 'confirmed' | 'failed'
protocol: string // 'uniswap-v4', '1inch', 'lifi', etc.
commandType: string
txType: 'swap' | 'bridge'
walletAddress: string
tokenIn: string
tokenOut: string
amountIn: string // stored as string for BigInt precision
amountOut?: string
gasUsed?: string
gasPrice?: string
routeInfo?: Json // multi-hop route data
createdAt: DateTime
confirmedAt?: DateTime
failedAt?: DateTime
}

ProtocolVolume — daily aggregates per protocol and chain:

{
date: DateTime // day boundary
protocol: string
chainId: number
totalTransactions: number
successfulTxs: number
failedTxs: number
uniqueUsers: number
totalVolumeIn: string
totalVolumeOut: string
}

UserSwapActivity — per-user activity:

{
walletAddress: string
protocol: string
chainId: number
totalSwaps: number
totalBridges: number
totalVolumeIn: string
firstTxAt: DateTime
lastTxAt: DateTime
}

Tracking Service Functions

FunctionDescription
trackSwapTransaction(data)Records transaction and updates aggregates
updateProtocolVolume(data)Upserts daily volume statistics
updateUserActivity(data)Updates user-specific metrics
getUserTransactionHistory(wallet, opts)Paginated user history
getProtocolVolumeStats(opts)Protocol volume data
getGlobalStats()Platform-wide statistics

Protocol Integration Points

Tracking is called from protocol handlers after successful transaction submission:

ProtocolHandler fileLines
Uniswap v4src/plugins/uniswap-v4/handlers.ts287-299, 607-620
1inchsrc/plugins/1inch/handlers.ts149-162
LiFisrc/plugins/lifi/handlers.ts168-190
Stargatesrc/plugins/stargate/handlers.ts125-147
Wormholesrc/plugins/wormhole/handlers.ts299-320

All tracking calls are wrapped in .catch() — tracking failures never affect the swap/bridge flow.

Analytics API Endpoints

EndpointMethodDescription
/api/analytics/user-historyGETPaginated transaction history for a wallet
/api/analytics/protocol-volumeGETVolume data with protocol/chain/date filters
/api/analytics/global-statsGETPlatform-wide metrics

Security note: These endpoints currently skip authentication. This is a known open item — they should be protected with the same API key gate used on other routes. See Internal: Security Findings.


Observability

  • Command history in ExecutionContext.history — per-tab, volatile.
  • Standard API envelope { success, data | error } — consistent structure for error tracking.
  • Faucet audit logs — structured event history for request lifecycle events.
  • Analytics endpoints — swap/bridge transaction history and aggregates.

Database Indexes

Key indexes for query performance:

SwapTransaction:

  • (walletAddress, createdAt) — user history queries
  • (protocol, createdAt) — protocol filtering
  • (chainId, createdAt) — chain filtering
  • txHash — transaction lookups

ProtocolVolume:

  • (date, protocol, chainId) — unique constraint for upsert operations

UserSwapActivity:

  • (walletAddress, protocol, chainId) — unique constraint for upsert operations