GET Contract Symbols

/contract-symbols

/contract-symbols

Example Query:

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

Example Response:

   {
      "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) orgetSymbols(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).

  • 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., 120000000000000000000120).

  • min_acceptable_portion_lf: Minimum portion of the liquidity fee (e.g., 0.003). Converted from the contract’s fixed-point value (e.g., 30000000000000000.003).

  • trading_fee: Fee charged per trade (e.g., 0.0006 or 0.06%). Derived from the contract’s tradingFee (e.g., 6000000000000000.0006).

Hedger-Defined Values

  • max_leverage: Maximum leverage allowed (e.g., 60x). Must be the contract’s Leverage (e.g., 60100).

  • max_notional_value: Maximum position size (e.g., $2,100,000). Must be the contract’s minAcceptableQuoteValue (e.g., 2100000120).

  • 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., BTCUSDTsymbol: 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

@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

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.

A size of 500 may be insufficient for future symbols added to the SYMM contracts.

Filters & Whitelists

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

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

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.

Full Controller Snippet

@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:

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]
}

Last updated