# GET Contract Symbols

## /contract-symbols

```json
/contract-symbols
```

**Example Query:**

```
https://base-hedger82.rasa.capital/contract-symbols
```

**Example Response:**

```json
   {
      "price_precision": 1,
      "quantity_precision": 3,
      "name": "BTCUSDT",
      "symbol": "BTC",
      "asset": "USDT",
      "symbol_id": 1,
      "is_valid": true,
      "min_acceptable_quote_value": 120,
      "min_acceptable_portion_lf": "0.003000000000000000",
      "trading_fee": "0.000600000000000000",
      "max_leverage": 60,
      "max_notional_value": 2100000,
      "rfq_allowed": true,
      "hedger_fee_open": "0.0006",
      "hedger_fee_close": "0.0006",
      "max_funding_rate": "200",
      "min_notional_value": "100",
      "max_quantity": "1000",
      "lot_size": "0"
    },
    {
      "price_precision": 3,
      "quantity_precision": 1,
      "name": "FILUSDT",
      "symbol": "FIL",
      "asset": "USDT",
      "symbol_id": 55,
      "is_valid": true,
      "min_acceptable_quote_value": 10,
      "min_acceptable_portion_lf": "0.004000000000000000",
      "trading_fee": "0.000800000000000000",
      "max_leverage": 50,
      "max_notional_value": 1750000,
      "rfq_allowed": true,
      "hedger_fee_open": "0.0006",
      "hedger_fee_close": "0.0006",
      "max_funding_rate": "200",
      "min_notional_value": "5",
      "max_quantity": "10000000",
      "lot_size": "0"
    }, //...
```

#### **Data Sources**

Values are derived from two sources:

1. **On-Chain Contract Data**: Immutable parameters fetched directly from the blockchain (via `getSymbol(symbolId)` or`getSymbols(start, size)`).
2. **Hedger-Defined Parameters**: Configurable values set by the market maker/hedger, subject to on-chain constraints.

**Contract-Sourced Values**

* **`symbol_id`**: Unique identifier for the trading pair (e.g., `1` for BTCUSDT). Mapped directly from the contract’s `symbolId`.
* **`name`**: Trading pair name (e.g., `BTCUSDT`).&#x20;
* **`is_valid`**: Indicates if the symbol is active for trading. Mapped from the contract’s `isValid`.
* **`min_acceptable_quote_value`**: Minimum quote value (e.g., $120) required to open a position. Converted from the contract’s fixed-point value (e.g., `120000000000000000000` → `120`).
* **`min_acceptable_portion_lf`**: Minimum portion of the liquidity fee (e.g., `0.003`). Converted from the contract’s fixed-point value (e.g., `3000000000000000` → `0.003`).
* **`trading_fee`**: Fee charged per trade (e.g., `0.0006` or 0.06%). Derived from the contract’s `tradingFee` (e.g., `600000000000000` → `0.0006`).

**Hedger-Defined Values**

* **`max_leverage`**: Maximum leverage allowed (e.g., `60x`). Must be **≤** the contract’s `Leverage` (e.g., `60` ≤ `100`).
* **`max_notional_value`**: Maximum position size (e.g., $2,100,000). Must be **≥** the contract’s `minAcceptableQuoteValue` (e.g., `2100000` ≥ `120`).
* **`max_quantity`**: Maximum tradable quantity (e.g., `1000` BTC). No on-chain constraints.
* **`max_funding_rate`**: Upper limit for funding rate (e.g., `200` ). Set by the hedger.
* **`min_notional_value`**: Minimum position size (e.g., $100). Configured by the hedger.
* **`hedger_fee_open`/`hedger_fee_close`**: Additional fees charged by the hedger (e.g., `0.0006`).
* **`rfq_allowed`**: Whether Request for Quote (RFQ) is enabled for the symbol.

**Derived Values**

* **`symbol`/`asset`**: Base and quote assets (e.g., `BTC` and `USDT`). Parsed from the `name` field (e.g., `BTCUSDT` → `symbol: BTC`, `asset: USDT`).
* **`price_precision`**: Number of decimal places for price (e.g., `1` → $100.1). Determined by the hedger based on market conventions.
* **`quantity_precision`**: Number of decimal places for quantity (e.g., `3` → 0.001 BTC). Derived from `min_acceptable_portion_lf` (e.g., `0.003` implies 3 decimals).
* **`lot_size`**: Always `0` (no minimum lot size enforced).

## Contract Symbols Implementation (Rasa)

### Router

```python
@common_router.get(
    '/contract-symbols', responses={status.HTTP_200_OK: {"model": SymbolsContractResponseSchema}},
    response_model=SymbolsContractResponseSchema
)
async def get_contract_symbols():
    symbols = await get_contract_all_symbols()
    return dict(count=len(symbols), symbols=symbols)
```

### Controller Logic

**Caching**

Uses `@redis_ttl_cache(ttl=300)`, so the *entire* symbol list is stored in Redis for 5 minutes. Subsequent calls within that window skip on-chain and DB work.

**On-Chain Fetching**

```python
symbols = await symmio_contract.functions
                         .getSymbols(start=0, size=500)
                         .call_async()
```

Calls the SYMMIO “diamond” contract’s `getSymbols` method to retrieve up to 500 entries and returns a list of tuples matching the on-chain `Symbol` struct fields.

{% hint style="info" %}
*A size of 500 may be insufficient for future symbols added to the SYMM contracts.*
{% endhint %}

**Filters & Whitelists**

```python
if not symbol[2]:                     # on-chain `isValid == false`
    continue
if symbol[1].upper() not in whitelist:
    continue
```

Drops any symbol with `isValid == false` or if the symbol is not in your hedger’s own whitelist (normalized to uppercase).

**Price Precision and Quantity Precision**

```python
price_precision    = Symbol.get_price_precision(symbol[1])
quantity_precision = Symbol.get_quantity_precision(symbol[1])
```

These methods query the **Postgres** `Symbol` table for the precision values you configured.

**USDT-Pair Restriction**

```python
if symbol[1].endswith("USDT"):
    … include in result …
```

Only includes symbols quoted in USDT.

### **Composing the Response Object**

**The response dict consists of:**

* **On-chain fields**: `symbolId`, `name`, `isValid`, `minAcceptableQuoteValue`, etc.
* **DB/config fields**: `price_precision`, `quantity_precision`, plus hedger parameters (max leverage, fees, notional caps) via `HedgerParameters`.
* Returns a list of dicts, one per symbol.&#x20;

**Full Controller Snippet**

```python
@redis_ttl_cache(ttl=300)
async def get_contract_all_symbols():
    symbols: List[Tuple] = await symmio_contract.functions.getSymbols(start=0, size=500).call_async()
    symbols_list = []
    symbol_whitelist = get_symbol_whitelist()
    for symbol in symbols:
        if not symbol[2]:
            continue
        if symbol[1].upper() not in symbol_whitelist:
            continue
        try:
            price_precision = Symbol.get_price_precision(symbol[1])
            quantity_precision = Symbol.get_quantity_precision(symbol[1])
        except PreConditionException:
            price_precision = None
            quantity_precision = None
        if 'USDT' == symbol[1][-4:]:
            symbols_list.append({
                'name': symbol[1].upper(), 'symbol': symbol[1][:-4], 'asset': 'USDT', 'symbol_id': symbol[0],
                'price_precision': price_precision,
                'quantity_precision': quantity_precision,
                'is_valid': symbol[2],
                'min_acceptable_quote_value': (Decimal(symbol[3]) / Scale) * MinQuoteValueMultiplier,
                'min_acceptable_portion_lf': Decimal(symbol[4]) / Scale,
                'trading_fee': Decimal(symbol[5]) / Scale,
                'max_leverage': int(
                    HedgerParameters.get_by_key(f"quote_boundaries::dynamic::{symbol[1]}::leverage::max")),
                'max_notional_value': HedgerParameters.get_by_key_convert_decimal(
                    f'quote_boundaries::{symbol[1]}::notionalValue::max'),
                'rfq_allowed': symbol[1].upper() not in OpenPositionSymbolBlackList,
                'max_funding_rate': HedgerParameters.get_by_key_convert_decimal('quote::max-funding-rate'),
                'hedger_fee_open': HedgerParameters.get_by_key(
                    f'{HedgerParameterPrefixes.open_order_gap}{symbol[1].upper()}'),
                'hedger_fee_close': HedgerParameters.get_by_key(
                    f'{HedgerParameterPrefixes.close_order_gap}{symbol[1].upper()}')
            })
    return symbols_list
```

For reference, the structure of an on-chain `Symbol` is here:

```solidity
struct Symbol {
    uint256 symbolId;                   // tuple index [0]
    string  name;                       // index [1]
    bool    isValid;                    // index [2]
    uint256 minAcceptableQuoteValue;    // index [3]
    uint256 minAcceptablePortionLF;     // index [4]
    uint256 tradingFee;                 // index [5]
    uint256 maxLeverage;                // index [6]
    uint256 fundingRateEpochDuration;   // index [7]
    uint256 fundingRateWindowTime;      // index [8]
}
```
