# REST API

### 1. Authentication

Include the following headers with each request:

* `solver` - name of the Solver
* `authorization` - authorization token

### 2. View connected makers

Use the following endpoint to retrieve a list of currently connected makers:

**URL:** `https://api.liquorice.tech/v1/solver/connected-makers`

**Method:** `GET`

#### Response:

```typescript
[
    "maker-a", 
    "maker-b"
]
```

### 3. Obtain list of supported tokens

Use the following endpoint to retrieve a list of currently supported tokens:

**URL:** `https://api.liquorice.tech/v1/solver/supported-tokens?chainId=<string>`&#x20;

**Method:** `GET`

#### Response:

```typescript
[
    {
        "symbol": "USDT",
        "address": "0xdac17f958d2ee523a2206206994597c13d831ec7",
        "decimals": 6
    },
    {
        "symbol": "WETH",
        "address": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2",
        "decimals": 18
    }
]
```

### 4. Query price levels

To understand indicative prices and available liquidity, we expose price levels for the different market makers.&#x20;

This step will allow you to do price discovery before requesting signed quotes.

**URL:** `https://api.liquorice.tech/v1/solver/price-levels?chainId=<string>`&#x20;

**Method:** `GET`&#x20;

#### Response:

```json
{
  "prices": {
    "maker_a": [
      {
        "baseToken": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
        "quoteToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
        "levels": [
          ["2999.5", "0.5"],
          ["3000.5", "1"],
          ["3002.0", "2"]
        ],
        "updatedAt": 1769174084710
      }
    ]
  }
}
```

Assuming that trader wants to swap `2 WETH` for `USDC`, the maker would be buying `0.5 WETH` for `2999.5 USDC`, `1 WETH` for `3000.5 USDC`, and another `0.5 WETH` for `3002.0 USDC`&#x20;

### 5. RFQ

To obtain a quote from Liquorice, send an RFQ to the following endpoint:

**URL:** `https://api.liquorice.tech/v1/solver/rfq`

**Method:** `POST`

**Body:**&#x20;

```typescript
{
    /// Chain ID (e.g for ArbitrumOne chainId = 42161)
    chainId: number;
    /// UUID of the RFQ (Must be generated by caller)
    rfqId: string;
    /// RFQ expiration UNIX timestamp (seconds)
    expiry: number,
    /// Address of token to be sent by trader
    baseToken: string;
    /// Address of the token to be received by trader
    quoteToken: string;
    /// Address of the account receiving quoteToken   
    trader: string;
    /// Optional address of the account sending baseToken
    /// If omitted, the system assumes that baseToken will be sent from trader address 
    effectiveTrader?: string;
    /// Note: Exactly one of the following two fields must be present
    /// Amount of baseToken with up to 18 decimal places, e.g. 100000000 (1 WBTC)
    baseTokenAmount?: string;
    /// Amount of quoteToken with up to 18 decimal places
    quoteTokenAmount?: string;
    /// List of maker names excluded from RFQ processing
    excludedMakers?: string[];
    /// Optional metadata that provides context about the intent origin
    intentMetadata?: {
        source: 'cow_protocol';
        content: { 
            /// CoW auction ID
            auctionId: number;
        }
    }
}
```

* The RFQ must include either `baseTokenAmount` or `quoteTokenAmount`, but not both.\
  \
  When `baseTokenAmount` is specified, the `trader` (order initiator) is requesting the amount of `quoteToken` they would receive in exchange for a specific amount of `baseToken`.\
  \
  When `quoteTokenAmount` is specified, the `trader` (order initiator) is requesting the amount of `baseToken` they need to provide to receive a specific amount of `quoteToken`.
* `excludedMakers`- to exclude specific makers from RFQ processing, obtain the complete maker list from the relevant [API endpoint](#id-2.-connected-makers)
* `intentMetadata` - For the moment, only CoW Protocol is supported. Omit this setting when requesting quotes for other intent origins.

#### Response

```typescript
{
  /// UUID of the RFQ
  rfqId: string,
  /// Indicates whether liquidity is available to fulfill RFQ
  liquidityAvailable: boolean,
  /// Array of available quote levels.
  /// Empty when liquidityAvailable is false
  levels: [{
    /// UUID of the maker RFQ that sourced this quote level
    makerRfqId: string,
    /// Name of the maker providing this quote level
    maker: string,
    /// Hex-encoded 32-byte nonce
    nonce: string,
    /// Quote expiration UNIX timestamp (seconds)
    expiry: number,
    /// Transaction details
    tx: {
      /// Address of the LiquoriceSettlement contract
      to: string,
      /// 0x-prefixed calldata string for the function within 
      /// LiquoriceSettlement contract
      data: string
    },
    /// Address of token to be sent by trader
    baseToken: string,
    /// Address of the token to be received by trader
    quoteToken: string,
    /// Amount of baseToken with up to 18 decimal places, e.g. 100000000 (1 WBTC)
    baseTokenAmount: string,
    /// Amount of quoteToken with up to 18 decimal places
    quoteTokenAmount: string,
    /// Settings for partial fill functionality.
    /// If absent, the order cannot be filled partially
    partialFill?: {
      /// Byte offset of the fill amount parameter in tx.data
      offset: number,
      /// Minimum fillable amount of baseToken, with up to 18 decimal places
      minBaseTokenAmount: string
    },
    /// List of allowances that trader should approve before executing settlement transaction
    allowances: [{
      /// Address of the Token
      token: string,
      /// Address of the spender 
      spender: string,
      /// Amount of the token to approve
      amount: string,
    }]
  }]
}
```

Market makers can provide multiple quote levels with different amounts, but the quoted amounts will not exceed those specified in the RFQ.

Example\
For an RFQ where:

* baseToken = ETH
* quoteToken = USDT
* baseTokenAmount = 1 ETH

The resulting quote may contain these levels:&#x20;

Level 0: Exchange 1 ETH for 3,000 USDT&#x20;

Level 1: Exchange 0.5 ETH for 1,502 USDT&#x20;

Level 2: Exchange 0.1 ETH for 310 USDT

<mark style="color:red;">**IMPORTANT NOTE**</mark>: While solvers typically execute a single quote level, it is technically possible to execute multiple quote levels if they come from different market makers. \
When using multiple quote levels, ensure that they come from different makers, as quotes from the same maker will result in only one successful execution.

### 5.1. Partial fills

The quote level's `partialFill.offset` field specifies the byte offset of `filledTakerAmount` parameter within tx.data.

The partial fill amount must be greater than or equal to `partialFill.minBaseTokenAmount`.

If the `partialFill` field is not present, the quote level must be filled completely.

```javascript
let calldata = tx.data.slice(0, 10 + partialFill.offset * 2) // Calldata up to offset. 2 is for `0x` prefix and 8 for the function selector.
    + fillAmount.toString(16).padStart(64, "0") // Replace with partial fill amount in hex, padded to 64 chars
    + tx.data.slice(10 + partialFillOffset * 2 + 64); // Remaining calldata after filledTakerAmount
```
