> For the complete documentation index, see [llms.txt](https://docs.aftermath.finance/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.aftermath.finance/for-developers/api/ccxt.md).

# CCXT

About Aftermath CCXT API /api/ccxt/...

CCXT maintains integration docs here: <https://docs.ccxt.com/#/exchanges/aftermath>\
\
The CCXT section of the Aftermath Finance API provides an easy way for users to read from and write to the Sui blockchain for anything related to the Aftermath Perpetuals exchange. The CCXT endpoints are all prefixed with `/api/ccxt`; e.g., `/api/ccxt/build/createAccount`.

### Transaction Execution

Using the CCXT API, you can call `/api/ccxt/build/*` endpoints for several operations and get back the transaction bytes and its signing digest. See the `TransactionBuildResponse` schema for the data that's returned by **all** `/api/ccxt/build/*` endpoints. Then, clients can sign the transaction digest with any of Sui's [supported signature scheme](https://docs.sui.io/concepts/cryptography/transaction-auth/signatures).

The transaction bytes and signatures can be sent back to the corresponding `/api/ccxt/submit/*` endpoint, which will send the authenticated transaction to the Sui network, parse its effects and send them back to the client in an easy-to-understand format.

### Why \`/api/ccxt/build\` endpoints?

Our `/api/ccxt/build` endpoints provide a convenience service for clients that can't do [BCS](https://move-book.com/programmability/bcs.html) and/or Blake2b-256 locally. CCXT also implements a uniform interface across many exchanges, alleviating the overhead of integrating a new exchange.\
\
Our CCXT API:

1. Creates the \[`Transaction`]
2. Serializes (BCS) the `Transaction` into bytes
3. Prepends an [Intent](https://docs.rs/sui-sdk-types/latest/sui_sdk_types/struct.Intent.html) to it (always `[0, 0, 0]` for user transactions on Sui)
4. Hashes the bytes with Blake2b-256

Another important aspect of the `/api/ccxt/build` endpoints is that they will automatically adapt some Move calls depending on the state of the chain, which the service keeps track of internally. This will be used for things like automatically including an oracle update if necessary, but not if the onchain price is fresh enough already.

### Is there any way to verify the response of the first API call?

Yes, you can. The `TransactionBuildResponse.transactionBytes` is the output of step 2 above. You can deserialize into the `Transaction` if you have access to a [BCS](https://move-book.com/programmability/bcs.html) implementation (e.g., [Rust](https://docs.rs/bcs/latest/bcs/), [Go](https://github.com/fardream/go-bcs), [Typescript](https://sdk.mystenlabs.com/bcs)).

### Example user flow

1. Fund the wallet with SUI for gas and native USDC for collateral on Sui mainnet
2. Create an account using `/api/ccxt/build/createAccount` then `/api/ccxt/submit/createAccount`
3. Call `/api/ccxt/build/deposit` then `/api/ccxt/submit/deposit` into the account (`.type == "account"`) that's created in the last step
4. `/api/ccxt/build/allocate` then `/api/ccxt/submit/allocate` a certain amount to a market (this should automatically create a position)
5. `/api/ccxt/build/createOrders` then `/api/ccxt/submit/createOrders`
6. `/api/ccxt/build/cancelOrders` then `/api/ccxt/submit/cancelOrders`

## Endpoint Groups

### Public market data

```
GET  /api/ccxt/markets
GET  /api/ccxt/currencies
POST /api/ccxt/orderbook
POST /api/ccxt/ticker
POST /api/ccxt/OHLCV
POST /api/ccxt/trades
```

`OHLCV` requires `chId` and accepts optional `timeframe`, `since`, and `limit`. `timeframe` defaults to `"1h"`; supported labels are `1m | 5m | 15m | 30m | 1h | 4h | 12h | 1d | 3d | 1w | 1mo`. The API clamps `limit` to `512`.

### Account reads

```
POST /api/ccxt/accounts
POST /api/ccxt/balance
POST /api/ccxt/positions
POST /api/ccxt/myPendingOrders
```

### Signed writes (build -> sign -> submit)

```
POST /api/ccxt/build/createOrders   -> POST /api/ccxt/submit/createOrders
POST /api/ccxt/build/cancelOrders   -> POST /api/ccxt/submit/cancelOrders
POST /api/ccxt/build/createAccount  -> POST /api/ccxt/submit/createAccount
POST /api/ccxt/build/deposit        -> POST /api/ccxt/submit/deposit
POST /api/ccxt/build/withdraw       -> POST /api/ccxt/submit/withdraw
POST /api/ccxt/build/allocate       -> POST /api/ccxt/submit/allocate
POST /api/ccxt/build/deallocate     -> POST /api/ccxt/submit/deallocate
POST /api/ccxt/build/setLeverage    -> POST /api/ccxt/submit/setLeverage
```

### Streams

```
GET /api/ccxt/stream/orderbook?chId={marketId}
GET /api/ccxt/stream/orders?chId={marketId}
GET /api/ccxt/stream/positions?accountNumber={number}
GET /api/ccxt/stream/trades?chId={marketId}
```

```typescript
const orderbookWs = new WebSocket(
  `wss://aftermath.finance/api/ccxt/stream/orderbook?chId=${marketId}`,
);

// Alternative native multiplexed WebSocket API
const nativeWs = new WebSocket("wss://aftermath.finance/api/perpetuals/ws/updates");
```

***

## CCXT IDs

| Field           | Meaning                                                   |
| --------------- | --------------------------------------------------------- |
| `chId`          | Market object ID                                          |
| `accountId`     | Account capability object ID (for writes)                 |
| `accountNumber` | Numeric account identifier (for reads/streams)            |
| `account`       | Balance lookup identifier accepted by `/api/ccxt/balance` |

***

## Request Types (Current Schema)

```typescript
interface OrderRequest {
  chId: string;
  type: "market" | "limit";
  side: "buy" | "sell";
  amount?: number;
  price?: number;
  reduceOnly?: boolean;
  expirationTimestampMs?: number;
  clientOrderId?: string;
}

interface CancelOrdersRequest {
  accountId: string;
  chId: string;
  orderIds: string[];
  deallocateFreeCollateral: boolean;
  metadata: TransactionMetadata;
  shouldAbortOnMissingId?: boolean; // default false: missing IDs tolerated
  clientOrderIds?: string[];        // client-managed IDs to cancel, in addition to orderIds
}

interface TransactionMetadata {
  sender: string;
  gasBudget?: number;
  gasPrice?: number;
  sponsor?: string;
  gasCoins?: Array<{ objectId: string; version: number; digest: string }>;
  gasFromAddressBalance?: boolean;
}

interface TransactionBuildResponse {
  transactionBytes: string;
  signingDigest: string;
}

interface SubmitTransactionRequest {
  transactionBytes: string;
  signatures: string[];
}
```

Notes:

* Sign `signingDigest`, not `transactionBytes`.
* `signingDigest` is base64-encoded. Decode it before signing unless your signer accepts base64 directly.
* Each `signatures` entry is a base64-encoded complete Sui `UserSignature` byte sequence.
* `signatures` can contain multiple signatures (for example sender + separate gas owner/sponsor signer).
* `POST /api/ccxt/balance` expects `account`, not `accountId` or `accountNumber`.
* `OrderRequest` supports optional `clientOrderId`. Do not send unsupported `timeInForce` or `postOnly` fields.
* `metadata.gasFromAddressBalance` is mutually exclusive with `gasCoins`. When true, pay gas from the gas owner's SUI address balance; the transaction carries the required single-epoch expiration.
* `/api/ccxt/build/deposit` accepts `fromAddressBalance` (default `false`) to fund the deposit from the sender's address balance instead of owned coin objects. Do not mix both funding modes.
* `/api/ccxt/build/withdraw` accepts `toAddressBalance` (default `false`) to deliver withdrawn funds to the sender's address balance instead of an owned coin object.
* When address-balance gas is enabled, embedded oracle update fees are paid from the sender's SUI balance. `gasBudget` remains denominated in SUI MIST.
* CCXT order responses can still include omitted or nullable fields such as `clientOrderId`, `postOnly`, `timeInForce`, `stopPrice`, and `takeProfitPrice`.

Submit responses:

| Route suffix                            | Response    |
| --------------------------------------- | ----------- |
| `createAccount`                         | `Account[]` |
| `deposit`, `withdraw`                   | `Account`   |
| `allocate`, `deallocate`, `setLeverage` | `Position`  |
| `createOrders`, `cancelOrders`          | `Order[]`   |

***

## Common Examples

### Place orders

```http
POST /api/ccxt/build/createOrders
Content-Type: application/json

{
  "orders": [{ "chId": "0x...", "type": "limit", "side": "buy", "amount": 0.01, "price": 95000 }],
  "accountId": "0x...",
  "deallocateFreeCollateral": false,
  "metadata": { "sender": "0x...", "gasFromAddressBalance": true }
}
```

Address-balance deposit example:

```http
POST /api/ccxt/build/deposit
Content-Type: application/json

{
  "accountId": "0x...",
  "amount": 10,
  "fromAddressBalance": true,
  "metadata": { "sender": "0x...", "gasFromAddressBalance": true }
}
```

### Fetch paginated trades

```http
POST /api/ccxt/trades
Content-Type: application/json

{ "chId": "0x...", "limit": 50, "cursor": null, "until": null }
// -> { trades: Trade[], nextCursor: number | null }
```

The API clamps trade pages to `50`. Omitting `until` uses the current time.

***

## Source of Truth

* Swagger UI: `https://aftermath.finance/docs`
* Production OpenAPI JSON: `https://aftermath.finance/api/openapi/spec.json`
