The off-chain backend for AureumDCA: a schedule executor, a Soroban event indexer, and a REST portfolio API — all written in Node.js/TypeScript. It watches the deployed dca-vault-contract on Stellar testnet, triggers due swaps permissionlessly, indexes swap history into SQLite, and exposes that history via HTTP.
┌─────────────────────────────────────────────────────────┐
│ dca-vault-backend │
│ │
│ ┌──────────┐ ┌──────────┐ ┌────────────────────┐ │
│ │ Poller │ │ Executor │ │ REST API │ │
│ │ │ │ │ │ │ │
│ │ polls │ │ polls │ │ GET /health │ │
│ │ Soroban │ │ vault │ │ GET /vaults/:owner │ │
│ │ events │ │ state, │ │ GET /vaults/:owner │ │
│ │ → SQLite │ │ submits │ │ /history │ │
│ │ │ │ execute_ │ │ GET /vaults/:owner │ │
│ │ │ │ swap txs │ │ /performance │ │
│ └────┬─────┘ └────┬─────┘ └────────┬───────────┘ │
│ │ │ │ │
└────────┼──────────────┼───────────────────┼─────────────┘
│ │ │
▼ ▼ ▼
Soroban RPC Soroban RPC SQLite DB
(read events) (simulate + (swap_events,
submit txs) indexer_state)
- Poller (
src/indexer/poller.ts): subscribes toswapcontract events viagetEvents, decodes them withscValToNative, stores them inswap_eventswith deduplication. Resumes from the last indexed ledger on restart. - Executor (
src/executor/executor.ts): polls known vault owners, simulatesexecute_swap, and submits the transaction when a schedule is due and unpaused. - REST API (
src/api/): Express server exposing vault state, swap history, and performance calculations backed by the SQLite database.
| Method | Path | Description |
|---|---|---|
GET |
/health |
Returns { status: "ok" } |
GET |
/vaults/:owner |
Simulates get_vault on the contract and returns the vault state for owner |
GET |
/vaults/:owner/history |
Returns all indexed swap events for owner from SQLite |
GET |
/vaults/:owner/performance |
Returns { total_invested, total_received, avg_price, swap_count } computed from swap history |
| Variable | Description | Example |
|---|---|---|
CONTRACT_ID |
Deployed dca-vault-contract address | CDJF7V5NLGKAV7RHTBCR3LMHC7MUS7IWL6KYSLO6ZWEEJYJGWUVGEDEO |
NETWORK_PASSPHRASE |
Stellar network identifier | Test SDF Network ; September 2015 |
RPC_URL |
Soroban RPC endpoint | https://soroban-testnet.stellar.org |
EXECUTOR_SECRET |
Secret key of the executor account (must be funded) | S... |
POLL_INTERVAL_MS |
Polling interval in milliseconds | 30000 |
PORT |
Express server port | 3001 |
DB_PATH |
SQLite database file path | ./data/dca.db |
git clone https://github.com/AureumDCA/dca-vault-backend.git
cd dca-vault-backend
npm ci
cp .env.example .env
# edit .env with your values
mkdir -p data
npm run devThe server and both background services (poller + executor) start together. Logs appear on stdout.
npm run typecheck # must be zero errors
npm run build # compiles TypeScript to dist/
npm start # runs the compiled outputThe executor discovers vault owners by reading the swap_events table — it only knows about owners who have had at least one swap executed. A brand-new vault with no swap history will not be picked up by the executor until after its first swap completes. The fix is to also index create_schedule events and seed the known-owners list from there. This is tracked as a contributor issue.
See CONTRIBUTING.md for prerequisites, setup, branch naming, commit style, the PR checklist, and Drips Wave rules.