> For the complete documentation index, see [llms.txt](https://docs.symm.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.symm.io/exchange-builder-documentation/frontend-builder-technical-guidance/sending-a-quote.md).

# Sending a Quote

Sending a quote is a core action on the SYMM platform. It lets PartyA signal an intent to trade by submitting a detailed quote request. For the quote to be accepted and opened by a hedger (PartyB), follow the steps below and provide accurate parameters. Debugging is harder when the call is forwarded through the AccountLayer's `_call`, since the transaction can fail for a number of reasons.

{% hint style="info" %}
In v0.8.5 the quote is encoded and forwarded through the **AccountLayer's** `_call`, not a per-frontend MultiAccount. The current function is `sendQuoteWithAffiliateAndData()`, which takes the parameters below plus a trailing `data` bytes field (an off-chain correlation ID); the AccountLayer routes the quote to the right VirtualAccount. For the exact 0.8.5 encoder see Building a New Frontend, and for a wallet-free, session-key-signed version see the Instant Layer flow.
{% endhint %}

**Function signature**

```solidity
function sendQuoteWithAffiliate(
    address[] memory partyBsWhiteList,
    uint256 symbolId,
    PositionType positionType,
    OrderType orderType,
    uint256 price,
    uint256 quantity,
    uint256 cva,
    uint256 lf,
    uint256 partyAmm,
    uint256 partyBmm,
    uint256 maxFundingRate,
    uint256 deadline,
    address affiliate,
    SingleUpnlAndPriceSig memory upnlSig
) external returns (uint256);
```

### Parameter breakdown

#### `partyBsWhiteList[]`

An array of PartyB addresses (hedgers/solvers) that PartyA is willing to trade with.

```javascript
const partyBsWhiteList = [solverAddress1, solverAddress2];
```

#### `symbolId`

The identifier for the trading symbol.

{% hint style="info" %}
Use `getSymbols()` on the SYMM Diamond to see available symbols, or query a solver's supported symbols from the contract-symbols endpoint (RASA).
{% endhint %}

#### `positionType`

Enum for the position type:

```solidity
enum PositionType { LONG, SHORT }
```

Use `0` for LONG and `1` for SHORT.

#### `orderType`

Enum for the order type:

```solidity
enum OrderType { LIMIT, MARKET }
```

Use `0` for LIMIT and `1` for MARKET.

#### `price`

For a **LIMIT** order, this is the exact price (in 18 decimals) at which you want to open the position.

For a **MARKET** order, the executed price includes the spread the solver charges, so you send a price adjusted from the current market price by a slippage buffer (e.g. 5%) to get the quote accepted:

* **LONG order:** increase the price you get from Muon by 5% (the position opens slightly higher to reflect the hedger's spread).
* **SHORT order:** decrease the price you get from Muon by 5% (the position opens slightly lower to reflect the hedger's spread).

#### `quantity`

The total order quantity in 18-decimal format. For example, a 5 ETH order is `5e18`.

#### `cva, lf, partyAmm, partyBmm`

The locked-value parameters: fractions (as percentages) of the notional value that define the risk and margin requirements.

* **`cva`**: Credit Valuation Adjustment. Either `partyA` (the user) or `partyB` (the hedger) can be liquidated, and `cva` is the penalty the liquidated side pays the other.
* **`lf` (Liquidator Fee):** fee reserved for liquidators.
* **`partyAmm` (Party A Maintenance Margin):** margin required for PartyA.
* **`partyBmm` (Party B Maintenance Margin):** margin required for PartyB.

{% hint style="info" %}
Query the solver's `get_locked_params` endpoint. Multiply the notional value by the returned percentage (divided by 100) for each parameter. For a MARKET order, calculate the notional from the adjustedPrice you sent (with slippage included).
{% endhint %}

The general formula for these values:

**LockedParam (Wei)** = (Notional Value \* lockedParam) / (100 \* leverage)

```javascript
      //CVA
      const cvaWei = notionalValue
      * (new BigNumber(lockedParams.cva))
      / (new BigNumber(100)) 
      / (new BigNumber(lockedParams.leverage))
      / (new BigNumber(1e18));
      console.log("cva: ", cvaWei);
      //LF
      const lfWei = notionalValue
      * (new BigNumber(lockedParams.lf))
      / (new BigNumber(100)) 
      / (new BigNumber(lockedParams.leverage))
      / (new BigNumber(1e18));
      //Maintenance Margins
      const partyAmmWei = notionalValue
      * (new BigNumber(lockedParams.partyAmm))
      / (new BigNumber(100)) 
      / (new BigNumber(lockedParams.leverage))
      / (new BigNumber(1e18));
      
      const partyBmmWei = notionalValue
      * (new BigNumber(lockedParams.partyBmm))
      / (new BigNumber(100)) 
      / (new BigNumber(1e18));
```

{% hint style="info" %}
**The notional value must be calculated from the price you send to the contract, not the Muon price. It should reflect the hedger's spread.**

**For MARKET orders:**

*notionalValue = (quantity \* adjustedPrice)*

**For LIMIT orders:**

*notionalValue = (quantity \* requestedPrice)*
{% endhint %}

*Example response:*

```json
{"cva":"0.7","lf":"0.3","leverage":"1.0","partyAmm":"99.0","partyBmm":"0","message":"Success"}
```

#### `maxFundingRate`

The maximum funding rate PartyA allows, in 18 decimals (usually `200e18`).

{% hint style="info" %}
You can get this from the solver's `contract-symbols` endpoint (RASA).
{% endhint %}

#### `deadline`

A Unix timestamp marking the quote's expiry. Set it far enough in the future for a solver to act.

#### `affiliate`

The affiliate address: your registered affiliate address for this frontend, which links the quote to you for fee tracking and routing.

#### `upnlSig`

A `SingleUpnlAndPriceSig` struct that confirms:

* **`reqId`:** a unique request identifier.
* **`timestamp`:** when the signature was generated.
* **`upnl`:** the unrealized profit and loss for PartyA.
* **`price`:** the verified asset price (in 18 decimals).
* **`gatewaySignature`:** a signature from the trusted gateway.
* **`sigs`:** a Schnorr signature (with `signature`, `owner`, and `nonce` fields).

{% hint style="info" %}
This data comes from the Muon oracle by calling the `uPnl_A_withSymbolPrice` method. A SubAccount bound to a single PartyB skips this Muon check on the trade path and can send an empty `upnlSig`; see the Instant Layer flow.
{% endhint %}

*Example query:*

```
https://muon-oracle4.rasa.capital/v1/?app=symmio&method=uPnl_A_withSymbolPrice&params[partyA]=0xYourAddress&params[chainId]=42161&params[symbolId]=4&params[symmio]=0xSymmioDiamondAddress
```

*Script to fetch and format the upnlSig for `sendQuoteWithAffiliate`, using axios and web3:*

```javascript
require('dotenv').config()
const { Web3 } = require('web3');
// Provide a valid provider URL; you can use your own Infura project URL or another provider.
const web3 = new Web3(new Web3.providers.HttpProvider(process.env.PROVIDER_URL));
const axios = require("axios");

async function getMuonSig(account, chainId, contractAddress, symbolId) {
  const url = "https://muon-oracle4.rasa.capital/v1/";
  const params = {
    app: "symmio",
    method: "uPnl_A_withSymbolPrice",
    "params[partyA]": account,
    "params[chainId]": chainId.toString(),
    "params[symbolId]": symbolId.toString(),
    "params[symmio]": contractAddress
  };

  try {
    const response = await axios.get(url, { params });
    if (!response.data || !response.data.result) {
      throw new Error("Unexpected response structure: " + JSON.stringify(response.data));
    }

    const result = response.data.result;
    if (!result.data) {
      throw new Error("Missing data in result");
    }
    const data = result.data;
    const reqId = result.reqId;
    const timestamp = data.timestamp ? data.timestamp : "0";
    const uPnl = data.result && data.result.uPnl ? data.result.uPnl : "0";
    const price = data.result && data.result.price ? data.result.price : "0";
    const gatewaySignature = result.nodeSignature;
    const sigs = (result.signatures && result.signatures.length > 0)
      ? result.signatures[0]
      : { signature: "0", owner: "0x0" };
    const nonce = data.init && data.init.nonceAddress ? data.init.nonceAddress : "0x0";

    const upnlSigFormatted = {
      reqId: web3.utils.hexToBytes(reqId),
      timestamp: timestamp.toString(),
      upnl: uPnl.toString(),
      price: price.toString(),
      gatewaySignature: web3.utils.hexToBytes(gatewaySignature),
      sigs: {
        signature: sigs.signature.toString(),
        owner: sigs.owner,
        nonce: nonce
      }
    };

    return upnlSigFormatted;
  } catch (error) {
    console.error("Error fetching Muon signature:", error);
    throw error;
  }
}

// Example usage:
(async () => {
  try {
    const account = ""; // Replace with your Party A address
    const chainId = 42161; // Example: Arbitrum chain ID
    const contractAddress = ""; // SYMM Diamond address
    const symbolId = 1; // Example symbolId 1 = BTCUSDT
    const muonSig = await getMuonSig(account, chainId, contractAddress, symbolId);
    console.log("Muon Signature:", muonSig);
  } catch (error) {
    console.error(error);
  }
})();

```

#### Parameter encoding for sendQuoteWithAffiliate

When sending a quote, encode the function call with the Symmio Core ABI before forwarding it through the AccountLayer's `_call`. This formats the parameters correctly and lets the Diamond delegate the call to the right facet.

The transaction payload before encoding should look like this:

```javascript
      //Max funding and deadline
      const sendQuoteWithAffiliateParameters = [
        partyBsWhiteList,
        symbolId,
        positionType,
        orderType,
        requestPrice.toString(), //the MARKET price (with added slippage) or if LIMIT, any price
        requestedQuantityWei.toString(),
        cvaWei.toString(), 
        lfWei.toString(),
        partyAmmWei.toString(),
        partyBmmWei.toString(), 
        maxFundingRate.toString(), 
        deadline.toString(),
        affiliate,
        upnlSigFormatted //signature from muon
    ];
```

**Steps to encode and send a quote:**

1. **Encode the function call.** Use Web3's ABI encoding to turn the `sendQuoteWithAffiliate` call into a byte string:

   ```javascript
   const encodedSendQuoteWithAffiliateData = web3.eth.abi.encodeFunctionCall(
     sendQuoteWithAffiliateFunctionAbi,
     sendQuoteWithAffiliateParameters
   );
   ```

   * **sendQuoteWithAffiliateFunctionAbi:** the ABI definition for `sendQuoteWithAffiliate`.
   * **sendQuoteParameters:** an array of all parameters in the order defined by the function signature.
2. **Prepare the call data.** The AccountLayer's `_call()` method expects the SubAccount address and an array containing your encoded call:

   ```javascript
   const _callData = [ subAccountAddress, [ encodedSendQuoteWithAffiliateData ] ];
   ```
3. **Send the transaction.** Forward the encoded call through the AccountLayer:

   ```javascript
   const sendQuoteWithAffiliateReceipt = await accountLayerContract.methods._call(..._callData).send({
     from: account.address,
     gas: adjustedGasLimit.toString(),
     gasPrice: sendQuotePrice.toString()
   });
   ```

#### Finding the quote ID

Once you send a quote with `sendQuoteWithAffiliate()`, the system emits a **SendQuote** event. It confirms the quote was submitted and carries a unique identifier (the `quoteId`) plus key details. The event is defined as:

```solidity
event SendQuote(
    address partyA,
    uint256 quoteId,
    address[] partyBsWhiteList,
    uint256 symbolId,
    PositionType positionType,
    OrderType orderType,
    uint256 price,
    uint256 marketPrice,
    uint256 quantity,
    uint256 cva,
    uint256 lf,
    uint256 partyAmm,
    uint256 partyBmm,
    uint256 tradingFee,
    uint256 deadline
);
```

Use this ID to track and query the quote later with getQuote().


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.symm.io/exchange-builder-documentation/frontend-builder-technical-guidance/sending-a-quote.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
