LogoLogo
  • Overview
    • Introduction
    • Table of Contents
  • Token Information
    • Symmio Foundation
  • Protocol Architecture
    • Protocol Introduction
    • Technical Documentation
      • Building an Application with SYMM
        • Introduction and Diamond Explainer
        • Querying Info from the SYMM Diamond
        • MultiAccount
        • Creating an Account and Depositing Funds
        • Sending a Quote
        • Closing a Quote
        • Instant Trading
          • Instant Login (EOA)
          • Instant Login (Account Abstraction)
          • Sending a Quote (Instant Open)
          • Sending a Quote (Instant Close)
        • Frequently Used Queries
      • Solver Docs
        • Solver Docs (github)
        • Solver Implementation Guide (High Level Overview)
        • Building a Solver on SYMMIO
          • 1. Intent Creation
          • 2. Seeing the Intent
          • 3. Hedging Off-Chain
          • 4. Opening/Closing a Position On-Chain
          • Creating the APIs
            • GET Contract Symbols
            • GET Open Interest
            • GET Notional Cap
            • GET Price Range
            • GET Error Codes
            • GET Get Locked Params
            • GET Get Funding Info
            • POST Position State
          • Solver Flow Summary Example
          • Recommended Architecture for Solvers
          • Glossary
        • Conditional Orders Handler
        • Rasa Solver TP/SL Implementation
        • Instant Trading
          • Instant Trading (Solvers)
          • Rasa Instant Trading Implementation
          • Instant Trading Condition Checks
        • Fetching Gas Prices Script
        • How to Add a Market as a Solver
        • Verifying Account Abstracted Instant Actions (ERC-4337)
      • Frontend Docs
        • Setting up a Frontend with SYMMIO
        • Frontend SDK Setup Guide
        • MultiAccount Deployment Guide
        • Instant Trading (Frontends)
          • Account Abstracted Instant Actions (Frontends)
        • Implement a Trading Bot on Symmio (OLD)
          • Setup
          • Creating a Sub-Account
          • Minting Collateral Tokens (Optional)
          • Depositing and Allocating Tokens
          • Obtaining Muon Signatures
          • Sending a Quote
          • Monitoring Price for Execution
      • Contract Docs
        • SYMMIO CORE v0.82
        • Contracts Documentation 0.8.2
          • Main Flow
          • The SYMM Diamond
          • Facets
            • Account Facet
            • Control Facet
            • Funding Rate Facet
            • PartyA Facet
            • PartyB Facet
            • Liquidation Facet
            • View Facet
          • MultiAccount
            • PartyA
            • PartyB
          • SYMM App (Muon)
            • LibMuon
            • MuonStorage
        • Contracts Documentation 0.8.3
          • Facets
            • Control Facet
            • Account Facet
            • PartyA Facet
            • PartyB Facet
            • View Facet
            • Bridge Facet
            • Liquidation Facet (Implementation)
          • Modified Events
          • New Events
          • MuonStorage
        • Contracts Documentation 0.8.4
          • Main Flow (0.8.4)
          • The SYMM Diamond (0.8.4)
          • Facets
            • Account Facet (0.8.4)
            • Bridge Facet (0.8.4)
            • Control Facet (0.8.4)
            • Force Actions Facet (0.8.4)
            • Funding Rate Facet (0.8.4)
            • Liquidations Facet (0.8.4)
            • PartyA Facet (0.8.4)
            • PartyB Group Actions Facet (0.8.4)
            • PartyB Quote Actions Facet (0.8.4)
            • PartyB Position Actions Facet (0.8.4)
            • Settlement Facet (0.8.4)
            • View Facet (0.8.4)
          • MultiAccount (0.8.4)
            • SymmioPartyA
            • SymmioPartyB
          • SYMM App (Muon)
            • LibMuon (0.8.4)
            • MuonStorage (0.8.4)
      • Contract Addresses / Solver Endpoints
        • Mantle
        • Mode
        • IOTA
        • Base
        • BSC
        • Arbitrum
        • Polygon
        • Berachain
        • Solver Endpoints and Addresses
          • Perps Hub
          • Rasa Capital
          • Rasa Capital (Zero Spread)
          • Zenith
      • How to Query our Contracts
      • Muon API Queries
      • Solver Error Codes
      • Interacting with SYMMIO Contracts
    • Protocol higher level architecture
      • 12-Hour Fraud Proof Window
      • PartyB
      • Solver Settings
      • Max Leverage
      • Maintenance Margin (CVA) Calculations
    • Symmio Whitepaper
  • Building on Symmio
    • Builders introduction
    • Solving for Symmio
      • Solver documentation
      • Solver - Example Flow
    • Trading Fees
      • Perps - Settlement Costs
      • Pair Trading - Settlement costs
    • Exchanges (Frontends)
      • Frontend Introduction
      • SDK - SYMM client
      • Trade on Symmio
  • Legal & Brand & Security
    • Security (Audits / Bugbounty)
      • Bug bounty / Coverage
        • How to contact ?
      • Audits
        • SYMM - V0.8 - 0.81
          • Sherlock Audit - Jun 15, 2023
          • Smart State - Jul 2, 2023
        • SYMM - 0.82
          • Sherlock Audit -Aug 30, 2023
        • SYMM - 0.83
          • Sherlock Audit - Jun 17, 2024
        • SYMM - 0.84
          • Sherlock Audit - Oct 3, 2024
        • Vaults
          • Sherlock Audit - Jan 2, 2024
    • Terms of Service & Licensing
      • TRADEMARK & COPYRIGHT NOTICE
      • CONTACT US
      • TERMS OF SERVICE
      • FRONTEND LICENSE
        • Frontend Modifications
        • Frontend Use Grants
      • CONTRACT LICENSE
        • Contract Use Grants
        • Contract Modifications
    • Brand - Assets Logos
Powered by GitBook
LogoLogo

All rights to the people (c) 2023 Symmetry Labs A.G.

On this page
  • Instant Open Trade
  • 1. Fetch the Current Price and Apply Slippage
  • 2. Fetch Locked Parameters
  • 3. Calculate Notional Value
  • 4. Compute Normalized Locked Values:
  • 5. Build the Trade Payload
  • 6. Send the Instant Open Request:
  • Sample Script
  1. Protocol Architecture
  2. Technical Documentation
  3. Building an Application with SYMM
  4. Instant Trading

Sending a Quote (Instant Open)

PreviousInstant Login (Account Abstraction)NextSending a Quote (Instant Close)

Last updated 2 months ago

Instant Open Trade

Instant Opens enable you to open a position immediately by using a market order. This process leverages a prior SIWE login to obtain an access token and then uses that token to send your trade payload to the solver’s instant‑open endpoint.

Instant Trading is only for sending MARKET orders

1. Fetch the Current Price and Apply Slippage

Retrieve the asset price from Muon (returned in wei). Use the method to get this price.

// Fetch the asset price from Muon (price returned in wei)
async function fetchMuonPrice() {
  try {
    const response = await axios.get(MUON_URL);
    const fetchedPriceWei = response.data.result.data.result.price;
    if (!fetchedPriceWei) {
      throw new Error("Muon price not found in response.");
    }
    return fetchedPriceWei; // as a string (in wei)
  } catch (error) {
    console.error(
      "Error fetching Muon price:",
      error.response?.data || error.message
    );
    throw error;
  }
}

For LONG positions, you should increase the fetched price by a fixed percentage (e.g., +1%) to account for the hedger’s spread, for SHORT decrease the price by the same amount. This is the adjustedPrice that will be sent to the API endpoint. The adjusted price becomes the basis for calculating the notional value.

2. Fetch Locked Parameters

3. Calculate Notional Value

For MARKET orders, compute the notional value as: notionalValue = quantity * adjustedPrice

4. Compute Normalized Locked Values:

For each risk parameter (e.g., CVA, LF, PartyAmm, PartyBmm), the normalized locked value is calculated using the formula:

Normalized Locked Value (Wei) = (Notional Value × lockedParam) / (100 * leverage)

For partyBmm, leverage is not used in the calculation

For example:

  • CVA: (notionalValue * cva) / (100 * leverage)

  • LF: (notionalValue * lf) / (100 * leverage)

  • PartyAmm: (notionalValue * partyAmm) / (100 * leverage)

  • PartyBmm: (notionalValue * partyBmm) / 100)

5. Build the Trade Payload

Create an object containing all the required parameters:

  • quantity: The trade quantity (in 18‑decimals).

  • cva, lf, partyAmm, partyBmm: The normalized locked values calculated above.

  • deadline: A Unix timestamp indicating when the trade request expires. It's recommended to use a longer dated expiry (>1 day)

6. Send the Instant Open Request:

Use the access token obtained via SIWE login and send the trade payload to the /instant_open endpoint of the solver. This is done via an HTTP POST with appropriate headers.

Sample Script

Below is a simplified JavaScript example (using ethers and axios) that demonstrates the instant open flow using a LONG XRP order. This includes the login component:

require("dotenv").config();
const { ethers } = require("ethers");
const axios = require("axios");
const BigNumber = require("bignumber.js");

const PRIVATE_KEY = process.env.PRIVATE_KEY;
const activeAccount = process.env.activeAccount; // Your sub-account address
const wallet = new ethers.Wallet(PRIVATE_KEY);

// --------------------------------------------------------------------
// Trade Configuration
// --------------------------------------------------------------------

const ORIGIN = "http://localhost:3000";
const CHAIN_ID = 42161;
const LOGIN_URI = `${SOLVER_BASE_URL}/login`;
const ISSUED_AT = new Date().toISOString();
const EXPIRATION_DATE = new Date(Date.now() + 24 * 60 * 60 * 1000).toISOString();
// For locked parameters, append the leverage to the URL:
const LEVERAGE = "1"; // Example leverage value
const LOCKED_PARAMS_URL = `https://www.perps-streaming.com/v1/42161a/0x141269E29a770644C34e05B127AB621511f20109/get_locked_params/XRPUSDT?leverage=${LEVERAGE}`;
const SOLVER_BASE_URL =
  "https://www.perps-streaming.com/v1/42161a/0x141269E29a770644C34e05B127AB621511f20109";
const DOMAIN = "localhost";
// For XRP, the marketId is "340"
const symbolId = 340;
// Position type: 0 for long, 1 for short
const positionType = 0;
// Order type: 0 = limit, 1 = market (instant trading only uses market orders)
const orderType = 1;
// Trade quantity (6.1 XRP tokens) – ensure this exceeds the minimum notional value (e.g. ~$15)
const quantity = "6.1";
// Maximum funding rate as a string (e.g. "200")
const maxFundingRate = "200";
// Deadline: current timestamp + 1 hour (in seconds)
const deadline = Math.floor(Date.now() / 1000) + 3600;

// --------------------------------------------------------------------
// Helper Functions
// --------------------------------------------------------------------
function buildSiweMessage({
  domain,
  address,
  statement,
  uri,
  version,
  chainId,
  nonce,
  issuedAt,
  expirationTime
}) {
  return `${domain} wants you to sign in with your Ethereum account:
${address}

${statement}

URI: ${uri}
Version: ${version}
Chain ID: ${chainId}
Nonce: ${nonce}
Issued At: ${issuedAt}
Expiration Time: ${expirationTime}`;
}

async function getNonce(address) {
  const url = `${SOLVER_BASE_URL}/nonce/${address}`;
  const { data } = await axios.get(url);
  return data.nonce;
}

async function fetchMuonPrice() {
  try {
  //Replace MUON_URL with your GET endpoint for uPnL_A_WithSymbolPrice
    const MUON_URL =
      "";
    const response = await axios.get(MUON_URL);
    const fetchedPriceWei = response.data.result.data.result.price;
    if (!fetchedPriceWei) {
      throw new Error("Muon price not found in response.");
    }
    return fetchedPriceWei;
  } catch (error) {
    console.error(
      "Error fetching Muon price:",
      error.response?.data || error.message
    );
    throw error;
  }
}

async function fetchLockedParams() {
  try {
    const response = await axios.get(LOCKED_PARAMS_URL);
    if (response.data && response.data.message === "Success") {
      return response.data; // Contains: cva, lf, leverage, partyAmm, partyBmm
    } else {
      throw new Error("Failed to fetch locked parameters.");
    }
  } catch (error) {
    console.error(
      "Error fetching locked parameters:",
      error.response?.data || error.message
    );
    throw error;
  }
}

// Compute normalized locked value for a given parameter (e.g. CVA, LF, PartyAmm)
// For CVA, LF, and PartyAmm, the formula is: (notionalValue * lockedParam) / (100 * leverage)
// For PartyBmm, the formula is: (notionalValue * partyBmm) / 100
function calculateNormalizedLockedValue(notional, lockedParam, leverage, applyLeverage = true) {
  if (applyLeverage) {
    return notional.multipliedBy(new BigNumber(lockedParam)).dividedBy(100 * leverage);
  } else {
    return notional.multipliedBy(new BigNumber(lockedParam)).dividedBy(100);
  }
}

// --------------------------------------------------------------------
// openInstantTrade: Executes the instant open trade process
// --------------------------------------------------------------------
async function openInstantTrade(token) {
  try {
    // 1. Fetch the raw asset price (in wei) from Muon.
    const fetchedPriceWei = await fetchMuonPrice();
    console.log("Fetched price (wei):", fetchedPriceWei);

    // 2. Apply a fixed +5% slippage.
    const fetchedPriceBN = new BigNumber(fetchedPriceWei);
    const adjustedPriceBN = fetchedPriceBN.multipliedBy(1.05); //Because we're going LONG, adjust by increasing to account for hedger spread..
    const adjustedPrice = ethers.formatUnits(adjustedPriceBN.toFixed(), 18);
    console.log("Adjusted price (+5%):", adjustedPrice);

    // 3. Fetch locked parameters (includes leverage).
    const lockedParams = await fetchLockedParams();
    console.log("Locked parameters:", lockedParams);

    // 4. Compute the notional value (for MARKET orders: quantity * adjustedPrice)
    const notional = new BigNumber(adjustedPrice).multipliedBy(new BigNumber(quantity));
    console.log("Notional:", notional.toString());

    // 5. Compute normalized locked values:
    const leverage = new BigNumber(lockedParams.leverage);
    const normalizedCVA = calculateNormalizedLockedValue(notional, lockedParams.cva, leverage, true).toFixed();
    const normalizedLF = calculateNormalizedLockedValue(notional, lockedParams.lf, leverage, true).toFixed();
    const normalizedPartyAmm = calculateNormalizedLockedValue(notional, lockedParams.partyAmm, leverage, true).toFixed();
    const normalizedPartyBmm = calculateNormalizedLockedValue(notional, lockedParams.partyBmm, leverage, false).toFixed();

    console.log("Normalized CVA:", normalizedCVA);
    console.log("Normalized LF:", normalizedLF);
    console.log("Normalized PartyAmm:", normalizedPartyAmm);
    console.log("Normalized PartyBmm:", normalizedPartyBmm);

    // 6. Build the trade payload with normalized values.
    const tradeParams = {
      symbolId: symbolId,           // For XRP, this is 340
      positionType: positionType,   // 0 for long (or 1 for short)
      orderType: orderType,         // 1 for market order
      price: adjustedPrice,         // Adjusted price after slippage
      quantity: quantity,           // Quantity in human-readable format (e.g., "6.1")
      cva: normalizedCVA,
      lf: normalizedLF,
      partyAmm: normalizedPartyAmm,
      partyBmm: normalizedPartyBmm,
      maxFundingRate: maxFundingRate,
      deadline: deadline            // Unix timestamp for deadline
    };

    console.log("Trade Payload:", tradeParams);

    // 7. Send the instant open request using the access token.
    const headers = {
      "Content-Type": "application/json",
      Authorization: `Bearer ${token}`
    };

    const response = await axios.post(`${SOLVER_BASE_URL}/instant_open`, tradeParams, { headers });
    console.log("Instant open response:", response.data);
  } catch (error) {
    console.error("Error in openInstantTrade:", error.response?.data || error.message);
  }
}

// --------------------------------------------------------------------
// MAIN FLOW: SIWE Login then Instant Open Trade
// --------------------------------------------------------------------
(async function main() {
  try {
    console.log(`\n[1/4] Wallet Address: ${wallet.address}`);
    const nonce = await getNonce(activeAccount);
    console.log(`[2/4] Got nonce: ${nonce}`);

    const siweMessage = buildSiweMessage({
      domain: DOMAIN,
      address: wallet.address,
      statement: `msg: ${activeAccount}`,
      uri: LOGIN_URI,
      version: "1",
      chainId: CHAIN_ID,
      nonce,
      issuedAt: ISSUED_AT,
      expirationTime: EXPIRATION_DATE
    });
    console.log("\n[3/4] SIWE message to sign:\n", siweMessage);

    const signature = await wallet.signMessage(siweMessage);
    console.log("\nSignature:", signature);

    const loginBody = {
      account_address: activeAccount,
      expiration_time: EXPIRATION_DATE,
      issued_at: ISSUED_AT,
      signature,
      nonce
    };
    const loginHeaders = {
      "Content-Type": "application/json",
      Origin: ORIGIN,
      Referer: ORIGIN
    };

    console.log("\n[4/4] Sending login request...");
    const loginResponse = await axios.post(`${SOLVER_BASE_URL}/login`, loginBody, { headers: loginHeaders });
    console.log("Login response:", loginResponse.data);

    const token = loginResponse.data.access_token;
    if (!token) {
      throw new Error("No access token received from login.");
    }

    await openInstantTrade(token);
  } catch (err) {
    console.error("Error in SIWE login flow:", err.response?.data || err.message);
  }
})();

Query the solver’s endpoint to obtain CVA, LF, PartyAmm, and PartyBmm (provided as percentages). These parameters define the collateral requirements for the trade.

: The identifier for the asset (e.g., "340" for XRP).

: 0 for LONG (or 1 for SHORT) – note that in instant trading, market orders are used.

: Set to 1 for MARKET orders.

: The adjusted price (after applying slippage).

: Maximum funding rate allowed by Party A (converted to 18 decimals).

maxFundingRate
symbolId
positionType
orderType
price
uPnL_A_WithSymbolPrice
get_locked_params