Technical Overview

Deep dive into how SavingsWallet works under the hood

System Architecture

SavingsWallet is a serverless Next.js application deployed on Vercel that provides automated crypto-to-USDT conversion across two blockchains: Solana and Base. The architecture follows an event-driven pattern for Solana and a polling-based pattern for Base, each optimized for the constraints of their respective environments.

High-Level Data Flow

  1. 1. User creates a wallet (encrypted on-chain or via our API)
  2. 2. User deposits tokens to their wallet address
  3. 3. Incoming transfer is detected (webhook or poll)
  4. 4. System checks gas balance, USD value, and min-swap threshold
  5. 5. Swap is executed via the optimal DEX aggregator for each chain
  6. 6. Transaction result is recorded in the database
  7. 7. If value exceeds cold wallet threshold, it is forwarded

Solana Swap Monitor (Helius Webhook)

On Solana, incoming transfers are detected via Helius webhooks. Helius provides real-time streaming of on-chain transactions through a webhook callback. When a transaction involving a monitored wallet is confirmed, Helius sends a POST request to /api/webhook/helius with the parsed transaction data.

Webhook Processing Flow

1. Validate HMAC signature (authenticity check)

2. Extract account addresses & parse token transfers

3. Check rate limit (per-wallet, 30s cooldown)

4. Look up wallet in DB by `publicKey`

5. Verify `auto_convert_enabled` flag

6. Check SOL gas balance (min 0.003 SOL)

7. Estimate USD value via Jupiter quote

8. Skip if below $3 minimum swap threshold

9. Execute swap via Jupiter Aggregator API

10. Save transaction record to Supabase

11. If value ≥ cold wallet threshold, forward tokens

Key Details
  • • Webhooks are registered per-wallet via the Helius API during wallet activation
  • • The HMAC secret is stored as HELIUS_WEBHOOK_SECRET env var
  • • Jupiter API handles best-route discovery across all Solana DEXs
  • • Slippage is configurable per-wallet (default 0.5%)
  • • Native SOL transfers are not swapped (only SPL tokens)

Base Swap Monitor (Polling + Cron)

Base is an EVM-compatible L2, so it uses a different monitoring approach. Since Helius only supports Solana, Base monitoring is handled via a polling endpoint triggered by a Vercel Cron Job at /api/base/monitor (once daily).

Polling Cycle

1. Fetch all Base wallets with `auto_convert_enabled=true`

2. For each wallet, scan last 200 blocks for ERC20 Transfer events

3. Filter events where `to` address matches the wallet

4. Deduplicate by checking `incoming_tx_hash` in transactions table

5. Fetch token metadata (symbol, decimals) via chain

6. If token is USDT — record directly (no swap needed)

7. If other token — check ETH gas balance (min 0.0005 ETH)

8. Estimate USD value via Aerodrome quote

9. Skip if below $3 minimum swap threshold

10. Execute swap via Aerodrome (Base's leading DEX)

Why Polling vs Webhook?
  • • Helius does not support EVM chains — only Solana
  • • Vercel Cron Jobs can invoke serverless functions on a schedule
  • • Base block times (~2s) mean 200 blocks covers ~7 minutes of history
  • • Saves duplicate transactions by checking `incoming_tx_hash`
  • • Each wallet's private key is decrypted server-side only during processing

Swap Execution

Swaps are executed through chain-optimized DEX aggregators using the existing liquidity on each network:

Solana → Jupiter

  • • Best-route across all Solana DEXs
  • • Handles token decimals automatically
  • • Configurable slippage
  • • Full transaction building & signing
  • • Post-swap USDT balance verification

Base → Aerodrome

  • • Base's leading liquidity DEX
  • • ERC20 approve + swap transaction pair
  • • Supports most traded Base tokens
  • • ethers v6 for all EVM interactions
  • • Quote-before-swap pattern for accuracy

Both swap modules share a common interface: get a quote first, validate the output against the minimum threshold, then execute. Failed swaps are recorded with the error details and the incoming token remains in the wallet for manual recovery.

Security Model

Key Encryption

Private keys are encrypted with AES-256-GCM before being stored in the database. The encryption key is derived from the user's password, which never leaves the browser in plaintext. The server stores only the encrypted blob. We cannot access user funds.

Authentication

API routes that handle sensitive operations (swap, export, create) require the user's password to be sent in the request body. The password is hashed with SHA-256 before being used as the encryption key for AES-256-GCM. This ensures that even if the database is compromised, private keys remain encrypted.

Webhook Verification

Helius webhook requests include an HMAC-SHA256 signature in the x-helius-signature header, verified against a shared secret. This prevents unauthorized actors from injecting fake transactions.

Rate Limiting

In-memory rate limiting prevents duplicate processing within 30-second windows. The system also checks for existing transaction records by `incoming_tx_hash` to ensure idempotency across serverless invocations.

Infrastructure & Data Model

Tech Stack

Next.js 15

App framework

Vercel

Hosting & Cron

Supabase

Postgres DB

Helius

Solana RPC + Webhooks

Jupiter

Solana DEX aggregator

Aerodrome

Base DEX

ethers v6

EVM interactions

Tailwind CSS v4

UI styling

Core Database Tables

wallets

Stores encrypted private keys, public addresses, chain type, auto-convert settings, cold wallet config, and swap preferences per wallet.

transactions

Records every detected incoming transfer and its corresponding swap result. Includes chain, token, amounts, USD values, swap hash, and status.

payments

Tracks USDT accumulations. Each incoming USDT transfer (whether direct or resulting from a swap) is recorded as a payment entry for accounting.

Environment Variables

VariablePurpose
SUPABASE_URLSupabase project URL
SUPABASE_SERVICE_ROLE_KEYServer-side DB access
SOLANA_RPC_URLSolana RPC endpoint
BASE_RPC_URLBase L2 RPC endpoint
HELIUS_API_KEYHelius API access
HELIUS_WEBHOOK_SECRETWebhook HMAC verification
ENCRYPTION_KEYServer-side encryption salt
JUPITER_API_BASEJupiter API base URL

Thresholds & Configuration

Swap Thresholds
  • Minimum swap: $3 USD equivalent
  • Cold wallet: $500+ → auto-forward
  • • Sub-threshold amounts accumulate in wallet
  • • Native gas tokens (SOL/ETH) not swapped
Gas Requirements
  • Solana: min 0.003 SOL
  • Base: min 0.0005 ETH
  • • Insufficient gas → skip swap, record pending
  • • Gas costs are borne by the wallet owner
Rate Limiting
  • • Per-wallet cooldown: 30 seconds between swaps
  • • Deduplication: by incoming_tx_hash in DB
  • • In-memory: resets per serverless invocation

Technical FAQs

What happens if a swap fails?
The transaction is recorded with a "failed" status and the error details. The incoming tokens remain in the wallet. The system will not re-attempt the swap automatically. Users can manually withdraw or retry from the dashboard.
How are private keys stored?
Keys are encrypted with AES-256-GCM using a key derived from your password via SHA-256. The encrypted blob is stored in Supabase. Your password never reaches the server — it is hashed in the browser before being sent.
Which tokens are supported?
All SPL tokens on Solana tradable via Jupiter, and all ERC20 tokens on Base tradable via Aerodrome. Native gas tokens (SOL, ETH) are not swapped. USDT is detected and recorded without swapping.
How often does the Base monitor run?
The Base monitor is triggered by a Vercel Cron Job once daily (midnight UTC). It scans the last 200 blocks (~7 minutes of history) for each monitored wallet.
What is the minimum swap amount?
The minimum is $3 USD equivalent. Transfers below this threshold are still detected and recorded, but not swapped to avoid paying gas fees that exceed the value.
Can I use my own RPC endpoint?
Currently RPC endpoints are managed server-side. The system uses Helius for Solana and a public Base RPC. Custom RPC support could be added in a future update.

Last updated: June 1, 2026 · SavingsWallet is experimental software. Terms