> For the complete documentation index, see [llms.txt](https://cetus-1.gitbook.io/cetus-developer-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cetus-1.gitbook.io/cetus-developer-docs/developer/via-sdk-v2/sdk-modules/cetusprotocol-dca-sdk/open-dca-order.md).

# Open Dca Order

### Core Workflow

Opening a DCA order requires two steps:

1. **Fetch a signed quote** from the Cetus DCA Quote API. The response provides `fee_rate`, `per_cycle_in_amount_limit`, `timestamp`, and `signature`, which the on-chain contract validates before accepting the order.
2. **Build and submit** the open-order transaction via `sdk.Dca.dcaOpenOrderPayload()`.

```
User wallet ──► Quote API ──► signed quote ──► dcaOpenOrderPayload ──► Sui transaction
```

### Quote API (Signature) <a href="#user-content-quote-api-signature" id="user-content-quote-api-signature"></a>

Before calling `dcaOpenOrderPayload`, request a quote from the Cetus backend. The server signs order constraints (input coin, cycle frequency, cycle count, and per-cycle input cap). The contract rejects orders with invalid or expired signatures.

**Endpoint**

```
GET https://api-sui.cetus.zone/dca/quote
```

**Query parameters**

<table><thead><tr><th width="120.81787109375">Parameter</th><th width="104.265625">Type</th><th width="110.442626953125">Required</th><th>Description</th></tr></thead><tbody><tr><td><code>in_coin</code></td><td><code>string</code></td><td>Yes</td><td>Full Move type of the input (pay) coin, e.g. <code>0x2::sui::SUI</code> or normalized long-form address</td></tr><tr><td><code>freq</code></td><td><code>number</code></td><td>Yes</td><td>Cycle interval in <strong>seconds</strong> (must meet on-chain <code>min_cycle_frequency</code>; see Global Config)</td></tr><tr><td><code>count</code></td><td><code>number</code></td><td>Yes</td><td>Total number of execution cycles (must meet on-chain <code>min_cycle_count</code>)</td></tr><tr><td><code>sender</code></td><td><code>string</code></td><td>Yes</td><td>Sui address of the order creator (same as <code>sdk.setSenderAddress</code>)</td></tr></tbody></table>

**Example request**

```
https://api-sui.cetus.zone/dca/quote?in_coin=0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC&freq=3600&count=2&sender=0xc5cea39da987d8fe16bf0c6db51bfbf4897aef0edf9588e035ae175ac416fdd1
```

**Example response**

```json
{
  "code": 200,
  "msg": "Success",
  "data": {
    "signer": "0x3124f1006b3a48b41648d6dd2beddc26d96beef0d5aa198c2589e3f44e2bcea4",
    "coin_type": "0xdba34672e30cb065b1f93e3ab55318768fd6fef66c15942c9f7cb846e2f900e7::usdc::USDC",
    "fee_rate": 0,
    "amount_in_limit_per_cycle": 3000689,
    "timestamp": 1780399709,
    "signature": "008385eba204435555c4d730bd1723e8ee9d25e8ea9d3dc3727c24263bd2814b544a25ac9193d63991aa0244e89f685e43577787f682cd3beb493e48eaf7ec570997b4eb4448da38141944bd7c2c42cdf63e94b65fac24da132cb732c9bf6d4f30"
  }
}
```

**Response field mapping**

| Quote API field (`data`)    | `dcaOpenOrderPayload` param | Description                                                           |
| --------------------------- | --------------------------- | --------------------------------------------------------------------- |
| `fee_rate`                  | `fee_rate`                  | Protocol fee rate for the order                                       |
| `amount_in_limit_per_cycle` | `per_cycle_in_amount_limit` | Maximum input amount allowed per cycle (base units)                   |
| `timestamp`                 | `timestamp`                 | Quote expiry timestamp (Unix seconds); must be used before it expires |
| `signature`                 | `signature`                 | Backend signature authorizing the quote parameters                    |

**Fetch quote in TypeScript**

> **Note:** Quotes are time-bound. Fetch a fresh quote immediately before building the transaction. Reusing an expired `timestamp` or `signature` will cause the on-chain call to fail.

### Open DCA Order <a href="#user-content-open-dca-order" id="user-content-open-dca-order"></a>

#### Parameter overview <a href="#user-content-parameter-overview" id="user-content-parameter-overview"></a>

<table><thead><tr><th width="236.958251953125">Parameter</th><th width="93.5625">Type</th><th>Description</th></tr></thead><tbody><tr><td><code>in_coin_type</code></td><td><code>string</code></td><td>Input coin Move type (coin deposited into the DCA order)</td></tr><tr><td><code>out_coin_type</code></td><td><code>string</code></td><td>Output coin Move type (coin received each cycle via swap)</td></tr><tr><td><code>in_coin_amount</code></td><td><code>string</code></td><td>Total input amount to deposit, in <strong>base units</strong> (integer string)</td></tr><tr><td><code>cycle_frequency</code></td><td><code>number</code></td><td>Seconds between each swap execution</td></tr><tr><td><code>cycle_count</code></td><td><code>number</code></td><td>Number of cycles; <code>in_coin_amount</code> is split evenly across cycles</td></tr><tr><td><code>per_cycle_min_out_amount</code></td><td><code>string</code></td><td>Minimum acceptable output per cycle (base units); swap reverts if output is below this</td></tr><tr><td><code>per_cycle_max_out_amount</code></td><td><code>string</code></td><td>Maximum acceptable output per cycle (base units); used as slippage upper bound</td></tr><tr><td><code>per_cycle_in_amount_limit</code></td><td><code>string</code></td><td>From quote API <code>amount_in_limit_per_cycle</code>; caps input spent per cycle</td></tr><tr><td><code>fee_rate</code></td><td><code>number</code></td><td>From quote API</td></tr><tr><td><code>timestamp</code></td><td><code>number</code></td><td>From quote API</td></tr><tr><td><code>signature</code></td><td><code>string</code></td><td>From quote API</td></tr></tbody></table>

#### Slippage bounds (`per_cycle_min/max_out_amount`) <a href="#user-content-slippage-bounds-per_cycle_minmax_out_amount" id="user-content-slippage-bounds-per_cycle_minmax_out_amount"></a>

These define the acceptable swap output range per cycle. A common approach:

1. Compute human-readable input per cycle: `in_coin_amount / 10^inDecimals / cycle_count`
2. Derive expected output using price bounds:
   * `per_cycle_max_out_amount` ≈ `cycleInput / minPrice × 10^outDecimals` (best case)
   * `per_cycle_min_out_amount` ≈ `cycleInput / maxPrice × 10^outDecimals` (worst case)

#### Full example <a href="#user-content-full-example" id="user-content-full-example"></a>

```typescript
import { d } from '@cetusprotocol/common-sdk'
import Decimal from 'decimal.js'

const wallet = 'YOUR_WALLET_ADDRESS'
sdk.setSenderAddress(wallet)

const in_coin_type = '0x0000000000000000000000000000000000000000000000000000000000000002::sui::SUI'
const out_coin_type = '0x26b3bc67befc214058ca78ea9a2690298d731a2d4309485ec3d40198063c4abc::usdc::USDC'
const cycle_count = 4
const cycle_frequency = 3600 // 1 hour
const in_coin_amount = '40000000000' // 40 SUI (9 decimals)

// Step 1: fetch signed quote
const quote = await fetchDcaQuote({
  in_coin_type,
  cycle_frequency,
  cycle_count,
  sender: wallet,
})

// Step 2: compute slippage bounds (example: SUI → USDC)
const inDecimals = 9
const outDecimals = 6
const cycleInputHuman = new Decimal(in_coin_amount).div(10 ** inDecimals).div(cycle_count)
const minPrice = 0.83854  // conservative min output price
const maxPrice = 2.172898 // conservative max input price
const per_cycle_max_out_amount = d(cycleInputHuman).div(d(minPrice)).mul(10 ** outDecimals).toFixed(0)
const per_cycle_min_out_amount = d(cycleInputHuman).div(d(maxPrice)).mul(10 ** outDecimals).toFixed(0)

// Step 3: build and submit transaction
const payload = sdk.Dca.dcaOpenOrderPayload({
  in_coin_type,
  out_coin_type,
  in_coin_amount,
  cycle_frequency,
  cycle_count,
  per_cycle_min_out_amount,
  per_cycle_max_out_amount,
  per_cycle_in_amount_limit: String(quote.amount_in_limit_per_cycle),
  fee_rate: quote.fee_rate,
  timestamp: quote.timestamp,
  signature: quote.signature,
})

const send_key_pair = 'THE_KEY_PAIR_GENERATED_BY_YOUR_PRIVATE_KEY'
const result = await sdk.FullClient.sendTransaction(send_key_pair, payload)
```
