Skip to main content

Overview

Starkzap supports Dollar-Cost Averaging (DCA) through AVNU and Ekubo. Users can create recurring buy orders (sell token X, buy token Y on a schedule), preview the expected swap per cycle, and cancel orders. DCA providers handle order creation, execution, and cancellation independently. Swap providers are only used for previewCycle quoting. What users can do with DCA:
  • 📅 Create recurring orders - Set token pair, amount per cycle, and frequency (e.g. daily); optional min/max bounds with AVNU
  • 📊 Preview a cycle - See the expected buy amount for the next cycle before creating or on existing orders
  • 📋 List orders - Fetch active (and optionally past) DCA orders for the wallet
  • Cancel orders - Cancel by order id or order address
  • 📦 Batch with other actions - Use the transaction builder to combine DCA create/cancel with transfers or swaps
DCA providers (AVNU, Ekubo) handle cycle execution on their own backend — swap providers are not involved in execution. However, previewCycle uses the wallet’s default (or specified) swap provider to quote the next cycle. Register swap providers if you want to use previewCycle.

Configuration

Registering DCA providers

Register DCA providers when connecting the wallet (or at runtime). The wallet’s dca() client uses these providers for create/cancel and for cycle preview (which uses the swap provider to quote the next cycle).
import { StarkZap, AvnuSwapProvider, EkuboSwapProvider, AvnuDcaProvider, EkuboDcaProvider } from "starkzap";

const sdk = new StarkZap({ network: "mainnet" });

const wallet = await sdk.connectWallet({
  account: { signer, accountClass: ArgentPreset },
  swapProviders: [new AvnuSwapProvider(), new EkuboSwapProvider()],
  defaultSwapProviderId: "avnu",
  dcaProviders: [
    new AvnuDcaProvider(),
    new EkuboDcaProvider(),
  ],
  defaultDcaProviderId: "avnu",
});
At runtime (e.g. after Cartridge onboard), register DCA providers and set the default the same way you do for swap providers: wallet.dca().registerProvider(provider), wallet.dca().setDefaultProvider(providerId).
Register swap providers and a default swap provider if you want to use previewCycle. Cycle execution is handled by the DCA provider backend and does not require swap providers.

Creating a DCA order

Create a recurring order with token pair, amount per cycle, frequency, and optional bounds (AVNU supports min/max buy amount per cycle; Ekubo uses TWAMM-style continuous execution).
const tx = await wallet.dca().create({
  sellToken: STRK,
  buyToken: USDC,
  sellAmount: Amount.parse("100", STRK), // total amount to sell across all cycles
  sellAmountPerCycle: Amount.parse("10", STRK),
  frequency: "P1D", // ISO 8601 duration, e.g. daily
  // Optional (AVNU): pricingStrategy with min/max bounds
  // Optional: provider, startTime, endTime
});
await tx.wait();
To batch DCA create with other operations, use the Tx Builder (e.g. .dcaCreate(...)).

Previewing a cycle

Show users the expected outcome of the next DCA cycle (quote from the swap provider) before they create the order or to display on an existing order:
const quote = await wallet.dca().previewCycle({
  sellToken: STRK,
  buyToken: USDC,
  sellAmountPerCycle: Amount.parse("10", STRK),
  // optional: swapProvider, slippageBps
});
console.log(quote.amountOutBase); // expected buy amount for one cycle

Listing and cancelling orders

List active (and optionally past) DCA orders for the wallet, then cancel by order id or order address:
const page = await wallet.dca().getOrders({ provider: "avnu" });

for (const order of page.content) {
  console.log(order.id, order.sellTokenAddress, order.buyTokenAddress, order.frequency);
}

// Cancel by order id (provider-specific string) or by order address
const tx = await wallet.dca().cancel({ orderId: page.content[0].id });
await tx.wait();

Using the transaction builder

Batch DCA create or cancel with other actions:
const tx = await wallet
  .tx()
  .dcaCreate({
    sellToken: STRK,
    buyToken: USDC,
    sellAmount: Amount.parse("100", STRK),
    sellAmountPerCycle: Amount.parse("10", STRK),
    frequency: "P1D",
  })
  .transfer(USDC, [{ to: recipient, amount: Amount.parse("5", USDC) }])
  .send();
await tx.wait();
Cancel via the builder:
const tx = await wallet.tx().dcaCancel({ orderId: myOrderId }).send();
await tx.wait();
See Tx Builder for the full list of builder methods.

DCA providers

ProviderIdDescription
AVNUavnuRecurring orders with optional min/max buy amount per cycle; uses AVNU swap routing for execution.
EkuboekuboTWAMM-style continuous DCA; no discrete per-cycle amount (continuous flow). Supports order list and cancel.
Provider-specific options (e.g. AVNU bounds, Ekubo time alignment) are documented in the SDK types. Use wallet.dca().listProviders() to see registered DCA provider ids and setDefaultProvider(providerId) to change the default.

Best practices

  1. Register swap providers if you want previewCycle to have a quote source (not required for DCA execution itself).
  2. Use token presets from getPresets(chainId) or mainnetTokens / sepoliaTokens for tokenIn and tokenOut so addresses and decimals match the chain.
  3. Preview before create — call previewCycle and show users the expected buy amount per cycle before they confirm the order.
  4. Handle provider differences — AVNU supports discrete cycles and optional min/max bounds; Ekubo is continuous (TWAMM). Validate inputs per provider when building forms.

Troubleshooting

”No default DCA provider configured”

Register at least one DCA provider and call setDefaultProvider(providerId) (or pass defaultDcaProviderId when connecting). Alternatively, pass provider: "avnu" or provider: "ekubo" on each DCA request.

DCA relies on swap providers

If previewCycle fails, ensure swap providers are registered and a default swap provider is set. Swap providers are only used for cycle quoting — actual cycle execution is handled by the DCA provider backend (AVNU/Ekubo).

Chain or provider mismatch

Ensure the wallet is on a chain supported by the chosen DCA provider (AVNU and Ekubo support mainnet and Sepolia). Align the SDK network config with the RPC/wallet chain.

Next steps