> 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-sdk.md).

# Frontend Builder SDK

## Frontend Builder SDK

### SYMM client SDK

[An SDK to interact with SYMMIO contracts, hedgers, and peripherals.](https://github.com/SYMM-IO/frontend-sdk)

{% hint style="info" %}
The official Frontend SDK targets the earlier MultiAccount flow. On Symmio v0.8.5 you build against the **AccountLayer**, with an **AccountManager** wrapper deployed for you on affiliate registration. See [Building a New Frontend](/exchange-builder-documentation/frontend-builder-technical-guidance/building-a-new-frontend.md) and [Upgrading from MultiAccount (0.8.4)](/exchange-builder-documentation/frontend-builder-technical-guidance/migrating-from-multiaccount-0.8.4.md). Where this page says "MultiAccount," read it as the AccountManager entry point onto the AccountLayer.
{% endhint %}

* To enable path-completion suggestions in VSCode, build the project first with `yarn build`, then set "TypeScript > Tsc: Auto Detect" to "on" in the VSCode settings.
* Don't use the `publicProvider` from Wagmi; it causes errors in the SDK.

[Wagmi's docs](https://wagmi.sh/core/getting-started#configure-chains) note:

> In a production app, it is not recommended to only pass publicProvider to configureChains as you will probably face rate-limiting on the public provider endpoints. It is recommended to also pass an alchemyProvider or infuraProvider as well.

### Setup guide

{% hint style="info" %}
Setup won't work with Yarn modern. Run these steps with Yarn classic (v1).
{% endhint %}

{% hint style="info" %}
The **Polygon** network is used internally and may have intermittent downtime as updates and new deployments roll out, so it isn't recommended for external partner testing. A test environment with a stable test hedger may be made available in the future.
{% endhint %}

First, run:

```
yarn install
```

Navigate to one of the app folders, for example the alpha app or the Next.js app:

```
cd apps/alpha/
```

To set up your environment:

1. Locate the `.env.example` file in the `apps/alpha` directory.
2. Rename `.env.example` to `.env`.
3. Update the fields in `.env` as required. Each chain needs a unique `HEDGER_URL` and public RPC.

Contract addresses aren't hardcoded here, because they change as new versions deploy. Pull them from the authoritative source for each one:

* **Diamond addresses** (Symmio core, AccountLayer, InstantLayer): look them up in the [SYMMIO explorer](https://intent.symmscan.com/inspector). Pick the chain and browse the deployed diamonds and their facets; Querying Info from the SYMMIO Diamond walks through it. The collateral token address is readable from the core with `getCollateral()`.
* **Hedger URLs and PartyB (solver) addresses**: consult each [hedger's API endpoints](/api-endpoints-and-deployments/symmio-perps-deployments.md) and reference pages under API Endpoints and Deployments, for example Rasa Capital. Each hedger publishes its own URL, PartyB address, and API base there.

Set the values you need in your `.env` per chain.

Finally, run:

```
yarn dev
```

The development server starts at `http://localhost:3000`.

**NOTE:** The Alpha and Next.js applications are identical; they just have different UIs.

### Configuring the app

**User configuration**

Supported chains are declared in the core package's `src/constants/chains.ts`:

```typescript
export enum SupportedChainId {
  NOT_SET = 0,
  MAINNET = 1,
  ROPSTEN = 3,
  RINKEBY = 4,
  BSC = 56,
  BASE = 8453,
  BSC_TESTNET = 97,
  POLYGON = 137,
  FANTOM = 250,
  ARBITRUM = 42161,
}
```

To add a chain for the user to connect to, pick one or more chains from the supported chain IDs and add them to the `ClientChain` variable in `nextjs/constants/chains.ts`:

```typescript
export const ClientChain = [
  SupportedChainId.POLYGON,
  SupportedChainId.BSC,
  SupportedChainId.BASE,
]; //Adding chains...
```

**Configuring the Hedger API**

Go to `app/constants/chains/hedgers.ts` and add the chain to `HedgerInfo`. Here's an example declaration:

```typescript
  [SupportedChainId.POLYGON]: [
    {
      apiUrl: "https://fapi.binance.com/",
      webSocketUrl: "wss://fstream.binance.com/stream",
      baseUrl: `https://${process.env.NEXT_PUBLIC_POLYGON_HEDGER_URL}`,
      webSocketUpnlUrl: `wss://${process.env.NEXT_PUBLIC_POLYGON_HEDGER_URL}/ws/upnl-ws`,
      webSocketNotificationUrl: `wss://${process.env.NEXT_PUBLIC_POLYGON_HEDGER_URL}/ws/position-state-ws3`,
      webSocketFundingRateUrl: `wss://${process.env.NEXT_PUBLIC_POLYGON_HEDGER_URL}/ws/funding-rate-ws`,
      defaultMarketId: 1,
      markets: [],
      openInterest: { total: 0, used: 0 } as OpenInterest,
      id: "",
      fetchData: true,
      clientName: "",
    },
  ],
```

The `apiUrl` and `webSocketUrl` don't change with the chain, because frontends listen directly to the Binance API for price data.

**Configuring addresses**

So the frontend interacts correctly with the deployed contracts, update `constants/chains/addresses.ts` with the right contract addresses for each chain, and add any necessary contract ABIs to the `/abi` folder. Source the diamond addresses from the [SYMMIO explorer](https://intent.symmscan.com/inspector) and the hedger/solver addresses from each hedger's API reference.

```typescript
export const CustomChain: ChainType = {
  COLLATERAL_SYMBOL: "",
  COLLATERAL_DECIMALS: ,
  COLLATERAL_ADDRESS: "",

  DIAMOND_ADDRESS: "",
  MULTI_ACCOUNT_ADDRESS: "",
  PARTY_B_WHITELIST: "",
  SIGNATURE_STORE_ADDRESS: "",

  MULTICALL3_ADDRESS: "",
  USDC_ADDRESS: "",
  WRAPPED_NATIVE_ADDRESS: "",
  ANALYTICS_SUBGRAPH_ADDRESS:
    "",
  ORDER_HISTORY_SUBGRAPH_ADDRESS:
    "",
};
```

**Configuring subgraphs**

To fetch a user's balance history or order history, determine the right GraphQL subgraph URI for the chain ID, then use Apollo Client to query it. Go to `packages/core/src/apollo/client` and edit `balanceHistory.ts` and `orderHistory.ts` to add the new chain. For example:

```typescript
const testClient = createApolloClient(
  `${getSubgraphName(SupportedChainId.TEST)}`
);
```

Then add it as a case for `getBalanceHistoryApolloClient` and `getOrderHistoryApolloClient`:

```typescript
export function getBalanceHistoryApolloClient(chainId: SupportedChainId) {
  switch (chainId) {
    case SupportedChainId.TEST:
      return testClient;
```

**Configuring Muon**

Muon verifies the price of an asset and a user's uPnL. Its signatures are required by the smart contracts to execute functions related to user positions. In most cases you won't need to change the Muon base URLs, but you can update them in `/constants/chains/misc.ts`.

### State-component relationships

### Account management (AccountLayer)

The user will, via the frontend, create and switch between SubAccounts on the **AccountLayer**. The auto-deployed **AccountManager** exposes the familiar `addAccount` / `_call` / `getAccounts` API as a backward-compatible entry point.

When a user interacts with the Symmio contracts through a SubAccount to send or modify quotes, the frontend encodes the Symmio core call and passes it to `_call(account, _callData)`: the SubAccount address plus a bytes array. The AccountLayer routes the call from the SubAccount, creating or reusing a VirtualAccount according to the SubAccount's isolation type.

Users select an account from a drop-down in the header, which lets them isolate positions across SubAccounts. Users provide a name when they create one. The `useActiveAccountAddress` hook returns the SubAccount address, and `useActiveWagmi` returns the wallet address.

### Querying the hedger

Symmio provides off-chain information to help users find a suitable hedger, in two categories: APIs and WebSockets.

These APIs aim to reduce failed user requests. They're subject to each hedger's policies: if a hedger doesn't require a whitelist, the related APIs are unnecessary.

Many endpoints take your frontend's account-contract address as a parameter, which in v0.8.5 is the **AccountManager** address. This is the address users interact with to create SubAccounts and call functions for opening and closing positions on the Symmio diamond.

### Testing guidelines

#### Testing environments

**Preferred networks for testing**

* **Base and Arbitrum (mainnets):** recommended for testing interactions, especially opening and closing positions, since they're more stable than test networks. Testing here needs a small amount of USDC to verify functionality.
* **Setting up environment variables in `.env`:** add the following to your `.env` to specify the hedger URL and public RPC URL:

  ```json
  NEXT_PUBLIC_BASE_HEDGER_URL="base-hedger82.rasa.capital"
  NEXT_PUBLIC_BASE_PUBLIC_RPC_URL="https://base.llamarpc.com"
  ```

#### Using test tokens

* For Base and Arbitrum, testing currently needs real capital (small amounts of USDC). Polygon supports test tokens, but the test hedger isn't stable enough for reliable frontend testing.

#### Setting up account contracts

* For initial testing of functions like `sendQuote`, frontend builders can trade under an existing affiliate's setup without registering their own.
* For production, register as an affiliate; an AccountManager is deployed for you on approval and registered with the solvers. You no longer deploy your own account contract.

### Hedger API

The Hedger API helps users monitor their positions. It exposes the status of positions, total open interest, notional caps, and the capital required to open positions.

Some useful endpoints:

#### GET `contract-symbols`

Returns the total number of symbols the hedger offers, with key data for each.

**Returns:**

* **`count`**: the total number of trading symbols available through the hedger.
* **`symbols`**: an array of objects, each representing a trading symbol or contract the hedger offers, with the fields below.
  * **`name`**: the name of the trading pair (e.g. BTCUSDT).
  * **`symbol`**: the ticker for the former part of the pair (e.g. BTC).
  * **`asset`**: the ticker for the latter part of the pair (e.g. USDT).
  * **`symbol_id`**: a unique integer identifier for the symbol within the hedger's system.
  * **`price_precision`**: the number of decimal places an asset's price can be specified to.
  * **`quantity_precision`**: the number of decimal places a traded quantity can be specified to.
  * **`is_valid`**: whether the symbol is currently valid for trading.
  * **`min_acceptable_quote_value`**: the minimum quote value (in collateral tokens) accepted for a trade with this symbol.
  * **`min_acceptable_portion_lf`**: the minimum portion awarded to the liquidator on liquidation.
  * **`trading_fee`**: the fee rate charged for trading this symbol.
  * **`max_leverage`**: the maximum leverage available.
  * **`max_notional_value`**: the maximum notional value of a position.
  * **`rfq_allowed`**: whether Request for Quote (RFQ) is allowed.
  * **`max_funding_rate`**: the maximum funding rate allowed.
  * **`hedger_fee_open`**: the hedger fee for opening a position with this symbol.
  * **`hedger_fee_close`**: the hedger fee for closing a position with this symbol.

**Output schema:**

```json
{
  "count": int,
  "symbols": [
    {
      "name": "",
      "symbol": "",
      "asset": "",
      "symbol_id": int,
      "price_precision": int,
      "quantity_precision": int,
      "is_valid": bool,
      "min_acceptable_quote_value": int,
      "min_acceptable_portion_lf": float,
      "trading_fee": float,
      "max_leverage": int,
      "max_notional_value": int,
      "rfq_allowed": bool,
      "max_funding_rate": int,
      "hedger_fee_open": "",
      "hedger_fee_close": ""
    },
  ]
}
```

#### GET `open-interest`

Shows the cumulative open interest available to hedgers across all trading symbols, plus the used capacity.

```
api/open-interest/
```

**Returns:**

* **`total_cap`**: the total open interest cap.
* **`used`**: how much is currently in use.

**Output schema:**

```json
{ 
  total_cap: float, 
  used: float 
}
```

The `getOpenInterest` function for this query is in the core package at `src/state/hedger/thunks.ts`.

#### GET `notional_cap`

Shows the notional cap of a symbol provided by the hedger, which represents the value of outstanding positions not yet settled for that symbol.

```
api/notional_cap/${symbolId}/
```

**Parameters:**

* **`symbolId`**: the symbol ID of the pair (e.g. for `BTCUSDT`, `symbolId` = 1).

**Returns:**

* **`total_cap`**: the total open interest cap.
* **`used`**: how much is currently in use.

**Output schema:**

```json
{ 
total_cap: float, 
used: float 
}
```

#### GET `price-range`

Provides the maximum and minimum prices at which `partyA` can place a limit order for a pair, ensuring execution by the hedger.

```
api/price-range/${symbol}
```

**Parameters:**

* **`symbol`**: the symbol (e.g. BTCUSDT).

**Returns:**

* **`min_price`**: the minimum price for limit orders.
* **`max_price`**: the maximum price for limit orders.

**Output schema:**

```json
{ 
min_price: float,
max_price: float
}
```

#### GET `error_codes`

Fetches a list of potential error labels and their associated error codes that may arise while interacting with the hedger, which helps interpret the error codes returned when querying a position state. Leaving `error_code` blank returns all error codes.

```javascript
api/error_codes/{error_code}
```

**Parameters:**

**`error_code`**: the error code to query.

**Returns:**

```
{
"error_code":"reason"
}
```

#### GET `get_locked_params`

Returns values related to collateral requirements for a pair, based on the parameters provided. These are used when opening the quote.

```plaintext
api/get_locked_params/${symbol}?leverage=${leverage}
```

**Parameters:**

* **`symbol`**: the trading symbol (e.g. BTCUSDT).
* **`leverage`**: the leverage applied to the position, which affects the collateral calculation.

**Returns:**

* **`cva`**: Credit Valuation Adjustment. Either `partyA` (the user) or `partyB` (the hedger) can be liquidated, and `cva` is the penalty the liquidated side pays to the other.
* **`partyAmm`**: Maintenance Margin for `partyA`. The amount actually behind the position, considered in liquidation.
* **`lf`**: Liquidation Fee, awarded to the liquidator that liquidates the position.
* **`leverage`**: the leverage applied to the position.

**Output schema:**

```json
{
  cva: '',
  partyAmm: '',
  lf: '',
  leverage: '',
  partyBmm: ''
}
```

#### GET `get_market_info`

Retrieves market information for whitelisted trading pairs. It requires your frontend's AccountManager (affiliate) contract address as an endpoint parameter.

`api/get_market_info/`

**Returns:**

* **`price`**: the current price of the symbol.
* **`price_change_percent`**: the percentage change in price over the last 24 hours.
* **`trade_volume`**: the total trading volume in USD over the last 24 hours.
* **`notional_cap`**: the notional cap of the symbol.

**Output schema:**

```json
{
  "<Symbol>": {
    "price": float,
    "price_change_percent": float,
    "trade_volume": float,
    "notional_cap": float
    }
}
```

This query is used in the core package at `src/state/hedger/thunks.ts`, mostly to display data on the [Market Information](https://cloverfield.exchange/markets) page.

#### GET `partyA_upnl`

Returns the unrealized profit and loss for a `partyA`.

`/partyA_upnl/{address}`

**Parameters:**

**`address`**: the sub-account address to query.

**Returns:**

The current uPnL for the user, as a float.

#### GET `get_balance_info`

Retrieves balance information for a given address and multi-account address. It returns detailed financial data for both parties, useful for managing and analyzing account balances and their parameters.

**Endpoint**

`api/get_balance_info/${address}/${multi_account_address}`

**Parameters**

* `address`: the sub-account address.
* `multi_account_address`: the multi-account address.

**Returns**

* **party\_a**: information for party A (the user).
  * `upnl`: Unrealized Profit and Loss.
  * `notional`: notional value.
  * `timestamp`: timestamp of the data.
  * `available_balance`: available balance.
  * `allocated_balance`: allocated balance.
  * `cva`: Credit Valuation Adjustment.
  * `lf`: Liquidation Fee.
  * `party_a_mm`: Maintenance Margin for party A.
  * `party_b_mm`: Maintenance Margin for party B.
  * `pending_cva`: pending Credit Valuation Adjustment.
  * `pending_lf`: pending Liquidation Fee.
  * `pending_party_a_mm`: pending Maintenance Margin for party A.
  * `pending_party_b_mm`: pending Maintenance Margin for party B.
  * `address`: address of party A.
* **party\_b**: information for party B (the counterparty).
  * `upnl`: Unrealized Profit and Loss.
  * `notional`: notional value.
  * `timestamp`: timestamp of the data.
  * `available_balance`: available balance.
  * `allocated_balance`: allocated balance.
  * `cva`: Credit Valuation Adjustment.
  * `lf`: Liquidation Fee.
  * `party_a_mm`: Maintenance Margin for party A.
  * `party_b_mm`: Maintenance Margin for party B.
  * `pending_cva`: pending Credit Valuation Adjustment.
  * `pending_lf`: pending Liquidation Fee.
  * `pending_party_a_mm`: pending Maintenance Margin for party A.
  * `pending_party_b_mm`: pending Maintenance Margin for party B.
  * `address`: address of party B.

#### GET `get_funding_info`

Retrieves funding information for trading pairs: the next funding time and the funding rates for short and long positions for each pair.

`api/get_funding_info/`

**Parameters**

This endpoint takes no URL parameters.

**Returns**

The response contains funding information for multiple trading pairs. Each pair includes:

* `next_funding_time`: the timestamp of the next funding time.
* `next_funding_rate_short`: the next funding rate for short positions.
* `next_funding_rate_long`: the next funding rate for long positions.

**Output schema:**

```javascript
  "AEVOUSDT": {
    "next_funding_time": int,
    "next_funding_rate_short": "",
    "next_funding_rate_long": ""
  },
```

#### POST `position-state`

Returns information about the state of a position, including an `action_status` that flags any internal issue in processing the quote. Useful for surfacing errors tied to a specific position.

**Endpoint:**\
`api/position-state/${start}/${size}`

**Parameters:**

* `start` and `size` are used for pagination.

**Payload:**\
The payload for this POST request should be empty.

**Returns:**

* **`create_time`**: Unix timestamp for when the position was created.
* **`modify_time`**: Unix timestamp for the last modification of the position.
* **`counterparty_address`**: the address of the counterparty involved in the position (this is `partyA`).
* **`filled_amount_close`**: the filled amount for closing the position, or `null` if it hasn't been closed.
* **`action_status`**: the success or failure status of the action, e.g. `success` for successful processing.
* **`error_code`**: an error code if there was an issue, otherwise `null`.
* **`state_type`**: the type of state the position is in.
* **`id`**: a unique identifier for the position.
* **`quote_id`**: the identifier for the associated quote.
* **`filled_amount_open`**: the filled amount for opening the position.
* **`last_seen_action`**: the last action taken on the position.
* **`failure_type`**: the type of failure if the action wasn't successful, otherwise `null`.
* **`order_type`**: numeric code for the type of order.

**Output schema:**

```json
{
  "create_time": int,
  "modify_time": int,
  "counterparty_address": "",
  "filled_amount_close": int|null,
  "action_status": "",
  "error_code": int|null,
  "state_type": "",
  "id": "",
  "quote_id": int,
  "filled_amount_open": int,
  "last_seen_action": "",
  "failure_type": "string|null",
  "order_type": int
}
```

This API is useful for showing notifications about a user's positions. It's applied in the `getNotifications` function in the core package's `src/state/notifications/thunks.ts`.

### WebSockets

Use the hedger WebSockets to stream real-time data so the frontend shows the most current information. The most commonly used ones:

#### Funding Rate WebSocket

`api/ws/funding-rate-ws`

Streams real-time funding rates for trading symbols.

**Parameters:**

* `string[]`: an array of symbol names to get funding rate updates for (e.g. `["BTCUSDT", "ETHUSDT", "XRPUSDT"]`).

**Returns:**

* **`next_funding_time`**: when the next funding rate update will occur.
* **`next_funding_rate_short`**: the funding rate applied to short positions.
* **`next_funding_rate_long`**: the funding rate applied to long positions.

**Output schema:**

```
SYMBOL: {
    next_funding_time: int,
    next_funding_rate_short: '',
    next_funding_rate_long: ''
  },
```

The `getFundingRate` function implements this WebSocket and is in the core package at `src/state/hedger/thunks.ts`.

#### Unrealized PnL WebSocket

`api/ws/upnl-ws`

Streams real-time profit and loss for a user (this may be deprecated soon).

**Parameters:**

* **`string`**: address of the sub-account.

**Returns:**

* **`upnl`**: unrealized profit and loss for the account's open positions.
* **`notional`**: the total notional value of the account's open positions.
* **`timestamp`**: the current timestamp.
* **`available_balance`**: `(allocated_balance + unpl - (cva + lf))`
* **`allocated_balance`**: the balance allocated to the sub-account.
* **`cva`**: the penalty the liquidated entity pays to the other party.
* **`lf`**: Liquidation Fee, awarded to the liquidator that liquidates the position.
* **`party_a_mm`**: Maintenance Margin of `partyA`. The amount actually behind the position, considered in liquidation.
* **`party_b_mm`**: Maintenance Margin of `partyB`. The amount actually behind the position, considered in liquidation.
* **`pending_cva`**: the pending `cva`.
* **`pending_lf`**: the pending `lf`.
* **`pending_party_a_mm`**: the pending `mm` for `partyA`.
* **`pending_party_b_mm`**: the pending `mm` for `partyB`.

**Output schema:**

```json
{
  upnl: '',
  notional: '',
  timestamp: int,
  available_balance: '',
  allocated_balance: '',
  cva: '',
  lf: '',
  party_a_mm: '',
  party_b_mm: '',
  pending_cva: '',
  pending_lf: '',
  pending_party_a_mm: '',
  pending_party_b_mm: ''
}
```

This query is implemented in the `AccountUpdater` function in `src/state/user/AllAccountsUpdater.tsx`.

#### Notification WebSocket (position state)

`api/ws/position-state-ws3`

Streams real-time data on the state of trading positions, so the frontend can show the most current state of each.

**Parameters:**

* `address[]`: an array of counterparty addresses to get position state updates for.

**Returns:**

* `id`: identifier for the position state event.
* `create_time`: when the position was created.
* `modify_time`: when the position was last modified.
* `quote_id`: an identifier for the associated quote.
* `counterparty_address`: the address of the counterparty involved in the position.
* `filled_amount_open`: the amount filled for an open.
* `filled_amount_close`: the amount filled for a close.
* `last_seen_action`: the last action observed on the position.
* `action_status`: the status of the last action (e.g. success, failure).
* `failure_type`: the type of failure if the action was unsuccessful.
* `error_code`: the error code if applicable.
* `order_type`: the type of order associated with the position.
* `state_type`: the state type of the position (e.g. alert).
* `version`: the version of the position state data.

**Output schema:**

```json
{
    "id": "",
    "create_time": int,
    "modify_time": int,
    "quote_id": int,
    "counterparty_address": "",
    "filled_amount_open": "",
    "filled_amount_close": "",
    "last_seen_action": "",
    "action_status": "",
    "failure_type": null,
    "error_code": null,
    "order_type": int,
    "state_type": "",
    "version": int
}
```

**Input parameter:**

```json
{
  "address": ["0x0000000000000000000000000000000000000000"]
}
```


---

# 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-sdk.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.
