SW4P Documentation
Browse documentation
Dollar-Cost Averaging

This page describes the DCA integration contract. DCA execution and other background workers are currently disabled during the backend migration. Do not fund a DCA wallet or create a live schedule on the basis of these examples.

When enabled and independently qualified, SW4P DCA schedules recurring USDC swaps from a user's WaaS Solana wallet into a target Solana token such as 555 or wrapped SOL. The worker is designed to check funded USDC balance, execute the Jupiter swap, and record execution history.

User Flow

  1. Open DCA Scheduler in the SW4P app.
  2. Choose the funding chain, target token, USDC amount per execution, interval, and duration.
  3. Create the schedule. For EVM funding, SW4P returns the user's WaaS Solana deposit address and a helper deposit URL.
  4. Only after production execution is explicitly available and verified, fund the designated wallet for the planned executions. Do not send funds during maintenance.
  5. Monitor runs, pause/resume schedules, or cancel the schedule from the same UI.

If the worker sees repeated insufficient-balance failures, it auto-pauses the schedule with pauseReason: "insufficient_balance" so the user can top up before resuming.

Execution Semantics

The worker atomically claims due schedules by advancing nextExecutionAt before it checks balance or submits a swap. That prevents duplicate execution across backend replicas. It also means transient failures are retried at the next configured interval instead of immediately retrying in a tight loop.

After an on-chain swap is submitted successfully, terminal database persistence is retried three times before the worker emits a structured alert="dca_orphan_execution" log with the schedule ID, execution ID, and swap transaction signature. Operators should page on that alert and reconcile the execution row from the logged transaction signature.

SDK Usage

ts
import { Sw4pClient } from "@sw4p/sdk";

const sw4p = new Sw4pClient({ apiKey: process.env.SW4P_API_KEY! });

const schedule = await sw4p.createDCA({
  source_chain: "BASE",
  token_out: "CQwwRomsuWsUCPYomZmRnwMns4ZCTASc31ExMvSysAF2",
  token_out_symbol: "555",
  amount_usdc: 25,
  frequency_hours: 24,
  max_executions: 12,
});

await sw4p.pauseDca(schedule.id);
await sw4p.resumeDca(schedule.id);
await sw4p.cancelDCA(schedule.id);
rust
use sw4p_sdk::{CreateDcaParams, Sw4pClient};

let client = Sw4pClient::new(std::env::var("SW4P_API_KEY")?);
let schedule = client.create_dca(&CreateDcaParams {
    source_chain: Some("BASE".to_string()),
    token_out: "CQwwRomsuWsUCPYomZmRnwMns4ZCTASc31ExMvSysAF2".to_string(),
    token_out_symbol: Some("555".to_string()),
    amount_usdc: 25.0,
    frequency_hours: 24,
    max_executions: Some(12),
    referrer_code: None,
}).await?;

client.pause_dca(&schedule.id).await?;
client.resume_dca(&schedule.id).await?;
client.cancel_dca(&schedule.id).await?;

Monitoring

Developer Console analytics includes a DCA Worker Health panel scoped to the connected wallet. It reports active schedules, due schedules, auto-pauses, 24-hour successes/failures, total executions, and the next scheduled run. A state of ATTENTION means at least one schedule is due, auto-paused, or has recent failures.

QA Gate

Before closing a production DCA ticket, capture devnet evidence for the flows that are supported by the configured devnet execution provider:

  • Create: schedule returns ACTIVE, source chain, target token, interval, and next execution time.
  • Execute: worker records a SUCCESS execution with swapTxHash only when the configured swap provider supports the devnet input/output mints.
  • Complete: finite schedules move to COMPLETED once maxExecutions is reached.
  • Controls: pause, resume, and cancel each return the updated schedule and are reflected in the UI.
  • Critical failure: insufficient balance records failed executions and auto-pauses after the configured retry threshold.

Current provider note: SW4P's production DCA executor uses Jupiter for Solana swaps. Public Jupiter quote responses must be verified against the active devnet mints before claiming devnet swap-readiness; if Jupiter rejects a devnet mint as not tradable, keep the PR in draft and attach that blocker instead of fabricating a successful execution row.