# API Docs

## ObsidianSwap API Integration Guide

> **Base URL:** `https://api.obsidian.finance` **Chain ID (Cronos):** `25` **Native Token Address:** `0x0000000000000000000000000000000000000000` **WCRO Address:** `0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23`

***

### Overview

The ObsidianSwap API enables developers to integrate best-route token swapping into any application on the Cronos blockchain. It exposes two sequential HTTP endpoints:

1. **`POST /getquote`** — Fetch the best available swap rate and route.
2. **`POST /getswap`** — Convert the quote into signed transaction calldata.

After receiving calldata, your application sends a standard blockchain transaction. The API handles routing logic, multi-hop paths, and native token wrapping/unwrapping automatically.

***

### Workflow

```
Your App  →  POST /getquote  →  ObsidianSwap Quote API
          ←  QuoteResponse   ←

Your App  →  (user confirms, slippage set, recipient set)

Your App  →  POST /getswap   →  ObsidianSwap Calldata API
          ←  SwapCallData    ←

Your App  →  User signs & broadcasts transaction  →  Cronos Blockchain
```

***

### Endpoint 1 - Get Swap Quote

**URL:** `https://api.obsidian.finance/25/v1/getquote` **Method:** `POST` **Content-Type:** `application/json`

#### Purpose

Returns the optimal swap route, estimated output amount, gas estimate, and fee. Use this to show users a preview before executing.

#### Request Fields

| Field                      | Type           | Required | Description                                                                         |
| -------------------------- | -------------- | -------- | ----------------------------------------------------------------------------------- |
| `chainId`                  | Number         | ✅        | Blockchain ID. Cronos = `25`                                                        |
| `currency`                 | Object         | ✅        | The **output** token you want to receive                                            |
| `currency.address`         | String         | ✅        | Output token contract address. Use `0x000...000` for native CRO                     |
| `currency.decimals`        | Number         | ✅        | Token decimals (e.g. `18`)                                                          |
| `currency.symbol`          | String         | ✅        | Token symbol (e.g. `"LAZY"`)                                                        |
| `tradeType`                | Number         | ✅        | `0` = EXACT\_INPUT. Only supported mode                                             |
| `amount`                   | Object         | ✅        | The **input** token and exact amount to sell                                        |
| `amount.currency.address`  | String         | ✅        | Input token address. Use `0x000...000` for native CRO                               |
| `amount.currency.decimals` | Number         | ✅        | Input token decimals                                                                |
| `amount.currency.symbol`   | String         | ✅        | Input token symbol                                                                  |
| `amount.value`             | String         | ✅        | Exact input amount in smallest unit (wei). E.g. `"150000000000000000000"` = 150 CRO |
| `gasPriceWei`              | String         | ✅        | Current gas price in wei. Used for USD gas estimation                               |
| `maxSplits`                | Number         | ✅        | Max route splits. Use `0` for standard V2/V3 routing                                |
| `poolTypes`                | Array\<Number> | ✅        | Pool types to include: `0` = V2, `1` = V3, `2` = StableSwap                         |

#### Example Request - Swap 150 CRO → LAZY

```json
{
  "chainId": 25,
  "currency": {
    "address": "0x6135c840c511a112457d647Aad82a26412a4fa7D",
    "decimals": 18,
    "symbol": "LAZY"
  },
  "tradeType": 0,
  "amount": {
    "currency": {
      "address": "0x0000000000000000000000000000000000000000",
      "decimals": 18,
      "symbol": "CRO"
    },
    "value": "150000000000000000000"
  },
  "gasPriceWei": "6000000000000",
  "maxSplits": 0,
  "poolTypes": [0, 1, 2]
}
```

#### Response Fields

| Field                       | Type   | Description                                       |
| --------------------------- | ------ | ------------------------------------------------- |
| `fee`                       | Number | Trading fee as a decimal (e.g. `0.002` = 0.2%)    |
| `gasEstimate`               | String | Estimated gas units for the transaction           |
| `gasEstimateInUSD`          | Object | Gas cost in USD, denominated in USDT              |
| `inputAmount`               | Object | Token and raw amount being sold                   |
| `outputAmount`              | Object | Token and raw amount expected to receive          |
| `routes`                    | Array  | One or more route paths found for the swap        |
| `routes[].path`             | Array  | Ordered token hops (first = input, last = output) |
| `routes[].pools`            | Array  | Liquidity pools used in this route leg            |
| `routes[].percent`          | Number | Share of total trade volume handled by this route |
| `routes[].pools[].exchange` | String | DEX name (e.g. `"VVS Finance"`)                   |
| `routes[].pools[].type`     | Number | Pool type (`0` = V2)                              |
| `tradeType`                 | Number | Echoes request value (`0` = EXACT\_INPUT)         |

#### Example Response

```json
{
  "fee": 0.002,
  "gasEstimate": "280000",
  "gasEstimateInUSD": {
    "currency": {
      "address": "0x66e428c3f67a68878562e79A0234c1F83c208770",
      "decimals": 6,
      "symbol": "USDT"
    },
    "value": "0.85"
  },
  "inputAmount": {
    "currency": {
      "address": "0x0000000000000000000000000000000000000000",
      "decimals": 18,
      "symbol": "CRO"
    },
    "value": "150000000000000000000"
  },
  "outputAmount": {
    "currency": {
      "address": "0x6135c840c511a112457d647Aad82a26412a4fa7D",
      "decimals": 18,
      "symbol": "LAZY"
    },
    "value": "20028343121762563187544"
  },
  "routes": [
    {
      "percent": 100,
      "path": [
        { "address": "0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23", "symbol": "WCRO", "decimals": 18 },
        { "address": "0x3b41B27E74Dd366CE27cB389dc7877D4e1516d4d", "symbol": "MERY", "decimals": 18 },
        { "address": "0x6135c840c511a112457d647Aad82a26412a4fa7D", "symbol": "LAZY", "decimals": 18 }
      ],
      "pools": [
        { "address": "0xA51231984ff01F4933a9FA24E8fd143f18ae6772", "exchange": "VVS Finance", "type": 0 },
        { "address": "0xD9A74F078418e66BF787036c2a722B3c38704281", "exchange": "VVS Finance", "type": 0 }
      ]
    }
  ],
  "tradeType": 0
}
```

***

### Endpoint 2 - Get Swap Calldata

**URL:** [`https://api.obsidian.finance/api/v1/getswap`](https://api.obsidian.finance/api/v1/getswap) **Method:** `POST` **Content-Type:** `application/json`

#### Purpose

Converts a `QuoteResponse` into executable blockchain transaction data. Call this immediately after the user confirms the quote.

#### Building the `trade` Object from QuoteResponse

You must transform the quote response before sending it to `/getswap`. The mapping rules are:

**`trade.tradeType`**

* `QuoteResponse.tradeType === 0` → set to string `"EXACT_INPUT"`

**`trade.inputAmount`**

* `currency.isNative`: `true` if address is `0x000...000`, else `false`
* `currency.wrapped.address`: Always use the address from the quote (even `0x000...000` for native — the API resolves WCRO internally)
* `quotient`: `QuoteResponse.inputAmount.value`

**`trade.outputAmount`**

* `currency.isNative`: `true` if address is `0x000...000`, else `false`
* `currency.wrapped.address`: Use the token address. **If output is native CRO, this field must be the WCRO address** (`0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23`) — the API appends an unwrap step
* `quotient`: `QuoteResponse.outputAmount.value`

**`trade.routes[]`** — for each route in the quote:

* `path`: Array of `{ "wrapped": { "address": "<token address>" } }` for each token in `quoteRoute.path`
* `pools`: Array of `{ "address": "<pool address>" }` for each pool in `quoteRoute.pools`
* `inputAmount` / `outputAmount`: Same `isNative` + `wrapped.address` + `quotient` mapping as above
* `type`: Pool type string — derive from `quoteRoute.pools[0].type` (e.g. `0` → `"V2"`)

#### Request Fields

| Field                                 | Type   | Required | Description                                                  |
| ------------------------------------- | ------ | -------- | ------------------------------------------------------------ |
| `trade`                               | Object | ✅        | Transformed trade object (see above)                         |
| `options.slippageTolerance`           | Object | ✅        | `{ numerator, denominator }` — e.g. `5/1000` = 0.5% slippage |
| `options.recipient`                   | String | ✅        | Wallet address to receive the output tokens                  |
| `options.deadlineOrPreviousBlockhash` | String | ✅        | Unix timestamp (seconds) for transaction expiry              |
| `chainId`                             | Number | ✅        | Must match the chainId used in the quote (`25` for Cronos)   |
| `userAddress`                         | String | ✅        | Wallet address of the user initiating the swap               |

#### Example Request - Executing the CRO → LAZY Swap

```json
{
  "trade": {
    "routes": [
      {
        "path": [
          { "wrapped": { "address": "0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23" } },
          { "wrapped": { "address": "0x3b41B27E74Dd366CE27cB389dc7877D4e1516d4d" } },
          { "wrapped": { "address": "0x6135c840c511a112457d647Aad82a26412a4fa7D" } }
        ],
        "pools": [
          { "address": "0xA51231984ff01F4933a9FA24E8fd143f18ae6772" },
          { "address": "0xD9A74F078418e66BF787036c2a722B3c38704281" }
        ],
        "inputAmount": {
          "currency": {
            "wrapped": { "address": "0x0000000000000000000000000000000000000000" },
            "isNative": true
          },
          "quotient": "150000000000000000000"
        },
        "outputAmount": {
          "currency": {
            "wrapped": { "address": "0x6135c840c511a112457d647Aad82a26412a4fa7D" },
            "isNative": false
          },
          "quotient": "20028343121762563187544"
        },
        "type": "V2"
      }
    ],
    "inputAmount": {
      "currency": {
        "wrapped": { "address": "0x0000000000000000000000000000000000000000" },
        "isNative": true
      },
      "quotient": "150000000000000000000"
    },
    "outputAmount": {
      "currency": {
        "wrapped": { "address": "0x6135c840c511a112457d647Aad82a26412a4fa7D" },
        "isNative": false
      },
      "quotient": "20028343121762563187544"
    },
    "tradeType": "EXACT_INPUT"
  },
  "options": {
    "slippageTolerance": {
      "numerator": "5",
      "denominator": "1000"
    },
    "recipient": "0xA503c42e75567fB9C5a73ab05B7939bC9838042B",
    "deadlineOrPreviousBlockhash": "1747804299"
  },
  "chainId": 25,
  "userAddress": "0xA503c42e75567fB9C5a73ab05B7939bC9838042B"
}
```

#### Response Fields

| Field                  | Type    | Description                                                                                        |
| ---------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| `calldata`             | String  | Hex-encoded transaction data. Use as the `data` field when sending the transaction                 |
| `value`                | String  | Native token amount in wei to send with the transaction. Non-zero only for native input (e.g. CRO) |
| `routerAddress`        | String  | The ObsidianSwap router contract to send the transaction to (`to` field)                           |
| `chainId`              | Number  | Echoes the request chain ID                                                                        |
| `estimatedGas`         | String  | Estimated gas units. Add a 20–30% buffer before broadcasting                                       |
| `inputCurrency`        | String  | Address of the input token (wrapped native address if input was native)                            |
| `outputCurrency`       | String  | Address of the output token (wrapped native address if output was native)                          |
| `inputAmount`          | String  | Raw input token amount                                                                             |
| `expectedOutputAmount` | String  | Raw expected output amount (pre-slippage, pre-execution)                                           |
| `paths`                | Array   | Simplified route summary: `path[]` (token addresses) and `pools[]` (pool addresses)                |
| `recipient`            | String  | Echoes the recipient address from the request                                                      |
| `multiHopRoute`        | Boolean | `true` if the swap routes through more than one pool                                               |

#### Example Response

```json
{
  "calldata": "0x5ae401dc...",
  "value": "150000000000000000000",
  "routerAddress": "0x1189331089b6ca8beA989C1F2fFd0EfAdCd33a69",
  "chainId": 25,
  "estimatedGas": "299283",
  "inputCurrency": "0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23",
  "outputCurrency": "0x6135c840c511a112457d647Aad82a26412a4fa7D",
  "inputAmount": "150000000000000000000",
  "expectedOutputAmount": "20028343121762563187544",
  "paths": [
    {
      "path": [
        "0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23",
        "0x3b41B27E74Dd366CE27cB389dc7877D4e1516d4d",
        "0x6135c840c511a112457d647Aad82a26412a4fa7D"
      ],
      "pools": [
        "0xA51231984ff01F4933a9FA24E8fd143f18ae6772",
        "0xD9A74F078418e66BF787036c2a722B3c38704281"
      ]
    }
  ],
  "recipient": "0xA503c42e75567fB9C5a73ab05B7939bC9838042B",
  "multiHopRoute": true
}
```

***

### Step 3 - Execute the Transaction

Broadcast the calldata using any Cronos-compatible wallet client (viem, ethers.js, wagmi, etc.).

#### Transaction Parameters

| Parameter  | Source                               | Notes                                             |
| ---------- | ------------------------------------ | ------------------------------------------------- |
| `to`       | `SwapCallDataResponse.routerAddress` | ObsidianSwap router contract                      |
| `data`     | `SwapCallDataResponse.calldata`      | Hex-encoded swap instruction                      |
| `value`    | `SwapCallDataResponse.value`         | In wei. Must be non-zero when input is native CRO |
| `gasLimit` | `SwapCallDataResponse.estimatedGas`  | Add 20–30% buffer recommended                     |
| `gasPrice` | Current network conditions           | Query the RPC or use EIP-1559 fields              |

#### Example (viem)

```typescript
const txHash = await walletClient.sendTransaction({
  account: address,
  to: swapData.routerAddress as `0x${string}`,
  data: swapData.calldata as `0x${string}`,
  value: BigInt(swapData.value),
  // Optional: add 20% gas buffer
  // gas: BigInt(swapData.estimatedGas) * BigInt(120) / BigInt(100),
});

console.log("Swap submitted:", txHash);
```

***

### Reference - Key Addresses (Cronos, Chain ID 25)

| Label                     | Address                                      |
| ------------------------- | -------------------------------------------- |
| Native CRO (input/output) | `0x0000000000000000000000000000000000000000` |
| WCRO (Wrapped CRO)        | `0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23` |
| ObsidianSwap Router       | `0x1189331089b6ca8beA989C1F2fFd0EfAdCd33a69` |

***

### Important Behavior Notes

#### Native Token Handling

* To **sell native CRO**: use `0x000...000` as the input address and set `isNative: true` in the trade object. The `value` field in the response will equal the input amount — pass this as the transaction `value`.
* To **receive native CRO**: set `isNative: true` for the output, but use the **WCRO address** (`0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23`) in `currency.wrapped.address`. The API automatically appends an unwrap step to the transaction.
* All internal routing operates on ERC-20 tokens. The API handles native↔wrapped conversion transparently.

#### Pool Types

| Value | Type                                         |
| ----- | -------------------------------------------- |
| `0`   | V2 (UniswapV2-style)                         |
| `1`   | V3 (UniswapV3-style, concentrated liquidity) |
| `2`   | StableSwap                                   |

#### Slippage

* Expressed as a fraction: `numerator / denominator`
* Example: `5 / 1000` = 0.5%
* Protects users from price movement between quote and execution. Always set a reasonable value — do not set to zero.

#### Deadlines

* `deadlineOrPreviousBlockhash` must be a **future** Unix timestamp in seconds.
* Prevents stuck transactions from executing at stale prices.
* A standard value is `Math.floor(Date.now() / 1000) + 1200` (20 minutes from now).

#### Gas Estimation

* `estimatedGas` is an estimate and may undercount on volatile networks or complex paths.
* Recommended: multiply by `1.2` to `1.5` before broadcasting.

#### Chain Consistency

* `chainId` must match across both API calls and the on-chain transaction.
* Always use `25` for Cronos Mainnet.

***

### Complete Integration Pseudocode

```typescript
// 1. Fetch quote
const quoteRes = await fetch("https://api.obsidian.finance/25/v1/getquote", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    chainId: 25,
    currency: { address: OUTPUT_TOKEN_ADDRESS, decimals: 18, symbol: "TOKEN" },
    tradeType: 0,
    amount: {
      currency: { address: "0x0000000000000000000000000000000000000000", decimals: 18, symbol: "CRO" },
      value: amountInWei.toString()
    },
    gasPriceWei: "6000000000000",
    maxSplits: 0,
    poolTypes: [0, 1, 2]
  })
});
const quote = await quoteRes.json();

// 2. Build trade object
const isInputNative = quote.inputAmount.currency.address === "0x0000000000000000000000000000000000000000";
const isOutputNative = quote.outputAmount.currency.address === "0x0000000000000000000000000000000000000000";

const trade = {
  tradeType: "EXACT_INPUT",
  inputAmount: {
    currency: { wrapped: { address: quote.inputAmount.currency.address }, isNative: isInputNative },
    quotient: quote.inputAmount.value
  },
  outputAmount: {
    currency: {
      wrapped: {
        address: isOutputNative
          ? "0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23" // WCRO for native output
          : quote.outputAmount.currency.address
      },
      isNative: isOutputNative
    },
    quotient: quote.outputAmount.value
  },
  routes: quote.routes.map(route => ({
    path: route.path.map(t => ({ wrapped: { address: t.address } })),
    pools: route.pools.map(p => ({ address: p.address })),
    inputAmount: {
      currency: { wrapped: { address: route.inputAmount.currency.address }, isNative: isInputNative },
      quotient: route.inputAmount.value
    },
    outputAmount: {
      currency: {
        wrapped: {
          address: isOutputNative
            ? "0x5C7F8A570d578ED84E63fdFA7b1eE72dEae1AE23"
            : route.outputAmount.currency.address
        },
        isNative: isOutputNative
      },
      quotient: route.outputAmount.value
    },
    type: route.pools[0].type === 0 ? "V2" : route.pools[0].type === 1 ? "V3" : "STABLE"
  }))
};

// 3. Fetch calldata
const swapRes = await fetch("https://api.obsidian.finance/api/v1/getswap", {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    trade,
    options: {
      slippageTolerance: { numerator: "5", denominator: "1000" },
      recipient: userAddress,
      deadlineOrPreviousBlockhash: String(Math.floor(Date.now() / 1000) + 1200)
    },
    chainId: 25,
    userAddress
  })
});
const swapData = await swapRes.json();

// 4. Send transaction
const txHash = await walletClient.sendTransaction({
  account: userAddress,
  to: swapData.routerAddress,
  data: swapData.calldata,
  value: BigInt(swapData.value),
  gas: BigInt(swapData.estimatedGas) * BigInt(130) / BigInt(100) // +30% buffer
});
```

***

*For support, reach out via the Obsidian Finance community channels.*
