Variational Docs
HomeDiscordTwitterBlog
  • Variational Protocol
    • About Variational
    • Peer-to-peer vs DEX
    • Roadmap
    • Key Concepts
      • Trading via RFQ
      • Settlement Pools
      • Margin
      • Slippage
      • Leverage
      • Liquidation
      • Mark price vs index price vs quote price
      • Open Interest & Funding Rates
      • Fully Diluted Valuation (FDV)
      • Fees
      • Market vs. Limit Orders
      • Take Profit & Stop Loss
    • $VAR Token
    • Media Kit
    • Official Links
    • FAQ
    • Getting Help (Support)
  • Variational Omni
    • About Omni
    • Getting Started with Omni
    • Getting Started With Omni (Testnet)
    • Omni Liquidity Provider (OLP)
    • Listings
    • Risk Limits
  • Variational Pro
    • About Pro
  • Technical Documentation
    • Technical Overview
      • Authentication
      • Deposits
      • Withdrawals
      • Trades
    • Derivative Specifications
      • Perpetual Futures
      • Settlement
    • API
      • SDKs
      • Quickstart and Tutorials
        • API Trading Prerequisites and Setup
        • Settlement Pool Deposit Tutorial
        • Taker (RFQ Submitter) Tutorial
        • Maker (RFQ Responder) Tutorial
      • Endpoints
      • Data Models
      • Headers
      • Pagination
      • Rate Limits
      • Authentication
    • Contracts and ABIs
    • Security and Audits
    • Partners
  • Legal
    • Terms of Service
    • Privacy Policy
    • Restricted Persons
  • ARCHIVE
    • Testnet Trading Competition #1 Leaderboard
    • Testnet Trading Competition #2 Leaderboard
    • Testnet Trading Competition #3 Leaderboard
Powered by GitBook
On this page
  • Pick a Received RFQ
  • Create a Quote
  • Wait until Your Quote Is Accepted
  • Perform a Last Look
  • Approve USDC Spending for the Deposit
  • Wait for Clearing Status to Progress
  1. Technical Documentation
  2. API
  3. Quickstart and Tutorials

Maker (RFQ Responder) Tutorial

PreviousTaker (RFQ Submitter) TutorialNextEndpoints

Last updated 1 year ago

This tutorial relies on context established in .

Pick a Received RFQ

Get a list of received RFQs in open status, evaluate them and pick one:

open_rfqs = [r for r in client.get_rfqs_received().result if r["rfq_status"] == "open"]
rfq = open_rfqs[0]
print(json.dumps(rfq, indent=2))
Output
{
  "asks": [],
  "bids": [],
  "clearing_status": null,
  "created_at": "2024-04-18T19:13:48.405834Z",
  "qty": "10000",
  "quotes_common_metadata": {},
  "rfq_expires_at": "2024-04-18T20:13:48.390Z",
  "rfq_id": "38ce49bf-9be9-4fd8-bc9a-5a90529c931f",
  "rfq_legs": [
    {
      "instrument": {
        "funding_interval_s": 3600,
        "instrument_type": "perpetual_future",
        "settlement_asset": "USDC",
        "underlying": "DOGE"
      },
      "qty": "10000",
      "rfq_id": "38ce49bf-9be9-4fd8-bc9a-5a90529c931f",
      "rfq_leg_id": "b55b6240-c245-4de9-a077-39f0edd66b86",
      "side": "buy"
    }
  ],
  "rfq_status": "open",
  "structure": {
    "legs": [
      {
        "instrument": {
          "funding_interval_s": 3600,
          "instrument_type": "perpetual_future",
          "settlement_asset": "USDC",
          "underlying": "DOGE"
        },
        "ratio": 1,
        "side": "buy"
      }
    ]
  },
  "structure_price": {
    "delta": "1",
    "gamma": "0",
    "native_price": "1",
    "price": "0.1499674821151633",
    "rho": "0",
    "theta": "0",
    "timestamp": "2024-04-18T19:14:09.870949585Z",
    "vega": "0"
  },
  "taker_company": "f58b3d2f-b5a6-488d-b8a9-dc2b1f782be8"
}

Create a Quote

from datetime import datetime, timezone, timedelta
from variational import PoolStrategyType, MarginMode

margin_params = {
    "margin_mode": MarginMode.SIMPLE,
    "params": {
        "liquidation_penalty": "0.1",
        "auto_liquidation": True,
        "asset_params": {},
        "default_asset_param": {
            "futures_initial_margin": "0.02",
            "futures_maintenance_margin": "0.01",
            "futures_leverage": "1000000000",
            "option_initial_margin": "0.15",
            "option_initial_margin_min": "0.1",
            "option_maintenance_margin": "0.075",
        },
    }
}
quote = client.create_quote(
    rfq_id=rfq["rfq_id"],
    expires_at=(datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),
    leg_quotes=[
        {
            "target_rfq_leg_id": "b55b6240-c245-4de9-a077-39f0edd66b86",
            "bid": "0.148",
            "ask": None,  # both "bid" and "ask" could be included
        }
    ],
    pool_strategy={
        "strategy": PoolStrategyType.CREATE_NEW,
        "name": "Maker tutorial pool",
        "creator_params": margin_params,
        "other_params": margin_params,
    }
).result
print(json.dumps(quote, indent=2))
Output
{
  "aggregated_ask": null,
  "aggregated_bid": "0.148000000000",
  "clearing_events": [],
  "clearing_status": null,
  "client_quote_id": null,
  "creator_params": {
    "margin_mode": "simple",
    "params": {
      "asset_params": {},
      "auto_liquidation": true,
      "default_asset_param": {
        "futures_initial_margin": "0.02",
        "futures_leverage": "1000000000",
        "futures_maintenance_margin": "0.01",
        "option_initial_margin": "0.15",
        "option_initial_margin_min": "0.1",
        "option_maintenance_margin": "0.075"
      },
      "liquidation_penalty": "0.1"
    }
  },
  "expires_at": "2024-04-18T20:16:13.647117Z",
  "maker_company": "1ebc7ece-093e-42aa-8cdf-028ccb1fc68a",
  "new_pool_name": "Maker tutorial pool",
  "other_params": {
    "margin_mode": "simple",
    "params": {
      "asset_params": {},
      "auto_liquidation": true,
      "default_asset_param": {
        "futures_initial_margin": "0.02",
        "futures_leverage": "1000000000",
        "futures_maintenance_margin": "0.01",
        "option_initial_margin": "0.15",
        "option_initial_margin_min": "0.1",
        "option_maintenance_margin": "0.075"
      },
      "liquidation_penalty": "0.1"
    }
  },
  "parent_quote_id": "be295917-ac71-4417-bc4a-550de0fb4f3a",
  "per_leg_quotes": [
    {
      "ask": null,
      "bid": "0.148000000000",
      "target_rfq_leg_id": "b55b6240-c245-4de9-a077-39f0edd66b86"
    }
  ],
  "pool_location": null,
  "target_rfq_id": "38ce49bf-9be9-4fd8-bc9a-5a90529c931f"
}

Wait until Your Quote Is Accepted

Before you can take the next step, the creator of the RFQ needs to accept your quote and approve their deposit if needed. Then the quote clearing status will change to pending_maker_last_look.

You can use the helper to wait for a single quote:

from variational import ClearingStatus
long_poller = PollingHelper(client=client, interval=10, attempts=100)
quote = long_poller.wait_for_clearing_status(
    parent_quote_id=quote["parent_quote_id"],
    status=ClearingStatus.PENDING_MAKER_LAST_LOOK
)

Or check all outstanding quotes:

accepted_quotes = list(
    [q for q in paginate(client.get_quotes_sent)
     if q["clearing_status"] == ClearingStatus.PENDING_MAKER_LAST_LOOK])

Before your quote is accepted, you can update it by replacing it with a new one:

quote = client.replace_quote(
    rfq_id=rfq["rfq_id"],
    parent_quote_id=quote["parent_quote_id"],
    expires_at=(datetime.now(timezone.utc) + timedelta(hours=1)).isoformat(),
    leg_quotes=[
        {
            "target_rfq_leg_id": "b55b6240-c245-4de9-a077-39f0edd66b86",
            "bid": "0.147",
            "ask": None,  # both "bid" and "ask" could be included
        }
    ],
    pool_strategy={
        "strategy": PoolStrategyType.CREATE_NEW,
        "name": "Maker tutorial pool",
        "creator_params": margin_params,
        "other_params": margin_params,
    }
).result

Perform a Last Look

When your quote is pending_maker_last_look and is still looking good, approve it:

from variational import RequestAction

last_look = client.maker_last_look(
    rfq_id=rfq["rfq_id"],
    parent_quote_id=quote["parent_quote_id"],
    action=RequestAction.ACCEPT,
).result
print(json.dumps(last_look, indent=2))
Output
{
  "new_clearing_status": "pending_maker_deposit_approval",
  "pending_deposits_sum_qty": "9.519183",
  "settlement_pool_address": "0x24b044aa809712867f6332aa465a302705013b92"
}

Note that if new_clearing_status is not pending_maker_deposit_approval, it means that the deposit for this trade is covered by a previously issued approval or there is enough funds in the pool, so you can skip the next part.

Approve USDC Spending for the Deposit

permits.sign_and_submit_decimal(
    pool_address=last_look['settlement_pool_address'],
    allowance=last_look['pending_deposits_sum_qty']
)

Wait for Clearing Status to Progress

At this point, the trade should automatically progress to the final state success_trades_booked_into_pool, but it can take a few seconds.

Use the helper to wait for the trade to clear:

quote = poller.wait_for_clearing_status(
    parent_quote_id=quote["parent_quote_id"],
    status=ClearingStatus.SUCCESS_TRADES_BOOKED_INTO_POOL,
)

If new_clearing_status is pending_maker_deposit_approval, you need to sign and submit a spending approval for the deposit:

Prerequisites and Setup
ERC-2612