🌐Sample Solver Docs
Documents are a work in progress and not yet complete technical documentation. Proprietary and confidential.
Glossary and Clarifications
The term "Solver" is referred to as a MarketMaker that provides Liquidity on IntentX.
Scope and Perspective: This documentation is curated from the perspective of an "example solver" that adopts a precise 1:1 hedging strategy. This Strategy ensures that this "example solver" remains delta neutral at every point in time, eliminating any directional exposure. This approach should be interpreted as an example and not as an absolute when interacting with the system, every MarketMaker has full control to, at any point when interacting with the core protocol, design his own hedging strategy, or not hedge at all. The protocol is specifically designed in a way that gives MarketMakers the time and ability to hedge their trades comfortably if they decide to do so.
Operational Context: When this "example solver" initiates a trade, they directly open a direct countertrade on their chosen broker platform (for instance, Binance) before filling the order onchain. A unique aspect of this strategy is its sequential nature: a trade is only filled onchain when its hedging counterpart is confirmed, and conversely, it's only closed after the hedging trade is conclusively settled.
Documentation Purpose: This liquidity provision strategy and the ensuing documentation serve as a template for what can be perceived as the lowest risk profile attainable in the hedging arena. However, a note of clarity: while this approach is streamlined and minimizes risks, we recognize it's somewhat rudimentary. Veteran market makers, armed with profound expertise, may devise intricate strategies that could potentially yield heightened profits, the system gives MarketMakers 100% over the hedging strategy they want to apply. Any segments of this documentation that could be interpreted differently should be perceived purely as guidelines. They document aims to explain how a basic strategy could be seamlessly implemented, but in no way restrict or limit the development of other strategic avenues one might pursue.
Additional Disclaimer - IntentX and Solver relationship
Educational Use: This Solver documentation is crafted with a singular goal in mind: to provide a fundamental understanding of the solver's role in the IntentX system to it's readers. (MarketMakers, investors and everyone who is interested in becoming a solver) The Solver documentation is educational and not a comprehensive reflection of the entire protocol. It is structured to provide an introductory grasp of what it means to be a solver and offers a primer on how one can undertake this role.
Misconceptions: Some readers might have concluded that the IntentX system depends on MarketMakers hedging themselves, leading to assumed trust dependencies on the MarketMaker side or that user funds and solver funds are somehow dependent on off-chain brokers or results of hedging strategies. However, this understanding needs to be revised and could lead to erroneous interpretations of the system's architecture.
Top-Down Relationship: To reiterate and clarify, the relationship between a solver and IntentX is top-down. That means whatever actions a solver takes off-chain have no bearing on the on-chain events. Thus, there are no trust assumptions regarding the solver side of things as they use off-chain systems to hedge themselves or the connection between these off-chain systems and IntentX itself.
Independent On-Chain Contracts: The SYMMIO contracts function independently of any off-chain actions a solver performs. They operate exclusively within the on-chain environment and are not influenced or impacted by external actions. The system is fully isolated from any issues that may or may not arise in combination with MarketMakers and the off-chain systems, centralized exchanges, trading desks, or any other forms of hedging they use. We strongly recommend readers to familiarize themselves with these points to understand Solvers's role and its interaction with the IntentX protocol.
Broker definition
Within the scope of the solver documentation, the term "Broker" holds a specific connotation, distinct from conventional interpretations. When the term "Broker" is mentioned in the context of being a Solver on IntentX, it is being referred to as a general "hedging strategy" that a MarketMaker (MM) can optionally design to hedge their IntentX trades. Importantly, it's vital to understand that our system doesn't necessitate a MarketMaker to hedge their trades. In fact, it's entirely optional. However, the architecture is such that if a MarketMaker decides to hedge, the system allows you to do so easily, it's entirely designed to make it simple and straightforward.
Broad Application of the Term The term "Broker" is expansive in our context. It can encompass:
Centralized Exchanges (CEX) Decentralized Exchanges (DEX) Over-The-Counter (OTC) Desks Spot holdings any other hedging strategies, whether they exist on-chain or off-chain.
A Note on Hedging Strategies: We don’t categorize or prioritize one method of hedging over another. All are viewed through the same lens, and are designed by MarketMakers themselves to be delta neutral or not, the system is designed to offer MarketMakers the potential to optimize their efficiency infinitely. Moreover, we acknowledge that the realm of hedging is vast, with potentially limitless strategies and methods for securing a position. Thus, when you come across "Broker" in our documentation, remember that it speaks to this broad, encompassing perspective.
How To Implement Your Own Solver
1. Introduction
IntentX offers traders the opportunity to engage in permission-less derivatives trading on the blockchain. There are two types of traders on this platform:
PartyA: They post requests for trades, also known as Intents.
PartyB (solvers, market makers): They respond to the requests made by PartyA, by claiming the Intent.
From now on we will refer to PartyB or MarketMaker as "Solver" as well as the Software to Market make as "hedging software", anything that offers quotes & accepts intents in the ecosystem is referred to "Solver", and the strategy to Market make on IntentX is referred to as "solving".
Each PartyB has the freedom to adopt their own hedging strategy, they can also choose to not hedge at all and be directionally exposed. However, certain rules are in place to ensure fairness within the system. In order to develop a customized MarketMaking approach, it is crucial to understand the timeline of Intents, the various requests made by PartyA, and the potential scenarios that may arise as a result of PartyA's actions. This document aims to focus on these aspects to assist you in building your own solver.
The main connection between PartyA and PartyB is based on onchain contracts provided by SYMMIO. Consequently, it is essential for each solvers to be able to monitor requests made by PartyA on the blockchain. This can be achieved by utilizing a subgraph or event-listener. Moreover, it is imperative for the solvers to respond to these requests via onchain calls to the core contracts.
Additional connections are established between PartyA and the solvers through the IntentX front-end interface, Solvers stream current quotes as Bid and Ask to IntentX as well as funding, collateral requirements but also simple notifications to enhance UX can be streamed via websocket connections. These connections aim to enhance the user experience by updating users on the status of their positions and intentions, as well as decreasing the time from request to execution by streaming quotes upfront. For example, a solver might notify the user when their request has been viewed, indicate the percentage of limit orders that have been filled, confirm if a transaction has been conducted in response to the user's request, or explain the reasons for rejecting the user's request. These types of connections are entirely optional. Each solver may choose whether or not to provide this kind of information, and the platform itself does not validate the contents of such communications.
In our current frontend architecture streaming quotes is not optional and every solver should stream his offers upfront to IntentX in order to enable fast executions and CEX like UX.
Figure1 shows how PartyAs and Solvers communicate.
Intents are the heart of the system so we need to get familiar with the lifecycle of an intent before going any further. Figure 2 illustrates the lifecycle of an intent. The dashed arrows represent actions taken by the solver, and the solid arrows represent actions taken by Party A or a third party. The circles indicate the state of the intent.
2. Send Intent (Send Quote)
Let's continue with how and where an intent gets created and see what arguments an intent in the current version 0.81 has. Please note that intents could be optimized to offer other products like Options, Expiring Swaps etc. (planned for future implementation) In the following table, we describe each field of a intent that is provided by a user during their request for a intent.
Table 1: Structure of an Intent
partyA
The address of the user who made the request
quoteId
The unique identifier of the quote, which must be referenced in all further requests
partyBsWhiteList
The whitelist of the solvers who are allowed to take action upon this intent. If it is empty, it means that all solvers are allowed
symbolId
The symbol identifier of the symbol that the user has sent ab intent for
positionType
The position type: LONG or SHORT (It would actually be 0 and 1 in the data)
orderType
The order type: Limit or Market (It would actually be 0 and 1 in the data)
price
The price that the user has requested
quantity
The quantity of the requested position
cva
In case of liquidation, this is a penalty that the liquidated side of the trade must pay to the other side
mm
The maintenance margin of this intent
lf
The liquidation fee which is going to be paid to the liquidator
deadline
Specifies the period in which solver is allowed to open this position
2.1. Limit request
The diagram below provides a detailed visualization of the potential steps a solver might undertake upon receiving notification of a Limit request dispatched by PartyA
Upon seeing a request made by PartyA, solvers should first check if they are whitelisted, meaning the user whitelisted the solvers address as intent parameter & they are therefore allowed to act upon the request. After this, there's a race among solvers to be the first to lock(claim) the Intent. The solver who locks the intent first will have the opportunity to open the position. Thus, the solver should to review the intent to ensure it aligns with their policies and is "interesting" enough to be opened, this is an additional security measure no onchain derivatives platform in crypto can offer market makers. If the intent is interesting and matches solver policies, and they have sufficient allocated balance with the corresponding PartyA, they should immediately lock it by calling the "lockQuote" function.
If they lack the necessary allocated balance, they should call the "AllocateAndLock" function to promptly execute both actions in a single transaction. Subsequently, the solver can hedge the position with a broker, any OTC desk or exchange and then use the "openPosition" function or simply wait until the price reaches the desired level before calling "openPosition"
2.2. Market request
The diagram below shows a solvers actions after spotting a market position
Market requests are similar to Limit ones. However, there are two differences in the actions taken by the solver for this type of Intent. Firstly, solvers must check the deadline of the Intent to determine if there is enough time to open a hedging position. Secondly, they can call "LockAndOpen" and "AllocateLockAndOpen" instead of "Lock" and "AllocateAndLock".
2.3. Opening the position
After the steps mentioned, the solver should call the 'openPosition' function with the specified parameters:
quoteId: The ID of the pending Intent that the solver wants to fill.
fillAmount: The solver has the option to open only a fraction of the specified Intent amount. Whatever quantity remains unfilled will be reposted as a new intent in the system.
openedPrice: The average fill price for the Intent which should not exceed the price specified by the user. The Unrealized Profit and Loss (UPNL) are determined based on this price.
Oracle Signature for Both Parties' UPNL: This signature is essential to evaluate the solvency of both parties after contract execution. The contract strictly forbids solvers from initiating a position if it would lead to the liquidation of either party. Consequently, solvers must carefully track the solvency ratio of parties with whom they have pending positions. If a pending inent appears to be no longer economically sustainable for any party, they should immediately cease the related processes to avoid further losses.
2.4. Expiration of an intent before being claimed and executed and becoming a position
An intent can become expired or cancelled before turning into a position.
2.4.1. Expiration
Each intent has an expiration time assigned. For limit orders, the expiration time is automatically set to infinite during payload creation in the front-end (good practice for frontends). If the solver fails to open a position within the specified time frame, they will no longer be able to open it, and a third party or partyA may choose to let the intent expire. If such a case happened the solver should cancel its corresponding hedging position on the broker side to avoid being directionally exposed.
2.4.2. Cancellation
If PartyA decides to cancel a pending intent that is not locked(claimed) by any solver, the intent will be immediately canceled. However, if PartyA chooses to cancel an already locked intent, the corresponding solver is given a specific period, known as the "forced cancellation cooldown." During this time, the solver must either accept the cancellation request or proceed with executing the intent, converting it into a position. The diagram below outlines the actions a solver should take upon receiving a cancellation request for a previously locked intent.
2.4.2.1. Forced Cancellation of Intent
If the solver doesn't respond to a cancellation request for an intent, either Party A or any third party can forcefully cancel the intent after the "forced cancellation cooldown" period expires. Should this occur, the solver must cancel the corresponding position on the broker side.
3 Closing the position
This section explains the different ways in which users can close a position and the steps required for solvers to respond to them respectively
3.1. Limit close request
Figure 5 depicts a flowchart detailing the sequential actions required by a solver upon receiving a limit close request from Party A.
Upon receiving a request from Party A to close a position at a limit, the corresponding solver should either submit this request to a broker or continuously monitor the price. When the price reaches the desired level or the close request from the broker's side is fulfilled, the Solver should proceed with the closure. It's vital to note that if the solver fails to fulfill the close request after the price hits the specified level, the position may be force-closed.
3.1.1. Force Close
To prevent Party B from neglecting to fulfill limit close requests, the contract has integrated the Force Close function. When the price of a limit close request is met, Party B is given a specific period (Force Close Cooldown) to act on the close request. If they don't, a third party will initiate a forced closure. As a result, the solver will face a penalty, payable to the party that triggers the force close. In such scenarios, if hedging activities are in place, Party B may close the corresponding position on the broker side.
3.2. Market close request
Market close requests operate in a manner similar to market intent requests, given their specific time frame leading up to expiration, with the requested price determined by the prevailing market price. Figure 6 depicts the procedures a solver should adhere to when handling a market request for closure.
3.3. Filling the close request
After the steps mentioned, the solver should call the 'fillCloseRequest' function with the specified parameters:
quoteId: The unique identifier of the respective position.
fillAmount: The solver can fill the close request in multiple steps, each with a fraction of the user's requested amount.
closedPrice: The average closing price of the position (cannot be lower than the user's requested price).
Oracle Signature for Both Parties' UPNL: This UPNL signature represents both parties and is used for solvency checks on the contract side. A solver cannot close a position if such closure would lead to either party facing liquidation. Although such situations, indicative of a problem with the liquidator, are rare, specific actions are in place. If Party A has a solvency issue, the solver is permitted to liquidate the user. Conversely, if the solvency challenge is on the solver's side, they must deposit additional funds into their account to avert liquidation.
3.4. Death of a close request
A close request can get expired or cancelled before actually getting filled by the solver.
3.4.1. Expiration
Close requests come with a designated time frame for fulfillment, as specified by the 'deadline' parameter. If not filled within this period, the close request becomes unfulfillable, and the position's status reverts to “open”.
3.4.2. Cancellation
If PartyA changes their mind after submitting a close request, they are allowed to cancel it by initiating a "cancel close request" action. The solver must respond within a certain timeframe by either fulfilling the close request or accepting the cancellation. Figure 7 illustrates the potential actions taken by the solver upon receiving a cancel close request.
3.4.2.1. Force Cancel Close Request
If the solver fails to respond to the cancel close request within the force cancel close cooldown period, any third party is authorized to perform a force cancel close. In this scenario, the position status reverts back to "open" and the solver must cancel and undo their close request on the broker's platform.
4. Parties' Liquidation
If any party is liquidated during the position, the position is no longer valid, and the solver has the option to close and cancel the corresponding solver's close request on the broker side.
5. Summary of different Type of Requests made by PartyA
Table 2 provides a comprehensive summary of various request types available for PartyA within the system and delineates how solvers should address them.
Table 2: Description of different requests of PartyA
Send Quote (limit)
When PartyA wishes to make a limit trade on a symbol, they can make a request for a Intent by calling sendQuote and providing the required information such as price, quantity, MM, CVA, LF.
Send Quote (Market)
Similar to limit orders, but in this type of trade, IntentX requests the price with a slippage based on the current market price and a limited expiration time. This gives the solver a specific deadline to fill such requests. Additionally, partial fills are not allowed in this type of request.
Request To Cancel
This type of request may occur when PartyA wants to cancel their unfilled quotes. If no solver has locked their request, the request to cancel will be immediately accepted. However, if their quote has been locked by a solver, the solver has a certain amount of time (force Cancel cool down) to either fill their quotes or accept their cancel requests.
Request To Close (limit)
When a user wants to close their request, they must make a close request and provide information such as the quantity they want to close and the price.
Request To Close(Market)
Similar to the market request for a quote, this type of request for closure is the same as requesting a close, but with a price that includes slippage and an expiration time. In this type of request, requesting a market close for a part of a quote and partial filling the close request is not meaningful.
Request To Cancel Close
After each PartyA makes a request to close, they are allowed to cancel their close request before the solver fills it. Similar to the request to cancel, the solver has a certain amount of time to respond to such requests, or the cancel close requests will be forced.
In addition, there are various other types of events that the solver must be mindful of, as they can have consequences on their business. Table 3 summarizes these additional events.
Table 3: additional type of events
Force Cancel
Any One
If the solver fails to respond to the user's cancel request within a certain time frame, any authorized individual is allowed to call for a force cancel, rendering the quote unavailable thereafter.
Force Cancel Close
Any One
Similar to force cancel, but applicable for close requests.
Force Close
Any One
If the solver does not fulfill the user's close request even after the price has been reached, any authorized individual can force close the request by providing a signature confirming the event.
Expire Quote
Any One
If the solver does not fill the market request, it will expire.
Liquidate User
Liquidator
If the solver or user's allocated balances are unable to cover their Unrealized Profit and Loss (UPNL), they will be subject to liquidation.
Liquidate Position
Liquidator
After liquidating the user, the liquidator will proceed to liquidate each position and facilitate a settlement between the parties involved.
6. Fee Structures
The platform incorporates multiple fees to manage and sustain its operations. Developers and organizations interfacing should familiarize themselves with these fees to ensure a seamless trading experience:
Platform Fee: This fee is charged to PartyA when a position is initiated on the platform. It contributes to the upkeep and management of the platform.
Liquidator Fee (LF): The LF is a specific charge designed to compensate for the risks associated with liquidation processes on the platform.
Counterparty Valuation Adjustment (CVA): This is a penalty levied during the liquidation phase. The party subjected to liquidation is required to remit this fee to their counterparty as compensation for potential losses or risks incurred.
Funding Rate: In the context of hedging, it is widely acknowledged that the majority of solvers opt to hedge their positions with a broker. Given that brokers may impose funding rates, during the intent request phase, both the solver and PartyA will negotiate and concur on a maximum funding rate. The contract administrator determines the period for each symbol. When this designated period arrives, the solver may either request or disburse the funding rate.
Spread Considerations: In the ecosystem, solvers may occasionally employ strategies that prevent them from placing orders with their broker at the exact price stipulated by PartyA. This discrepancy can manifest as a wider spread in the order book compared to the solver's broker orders. It's imperative for solvers to understand that Muon signatures do not consider these spreads. An exaggerated spread could deter user trading interest, increase the chances of forced position closures, and elevate potential loss risks. To maintain platform integrity and user trust, solvers are recommended to ensure their spread fees remain within a justifiable bracket.
7. Network's Solvency and Settlement Mechanism
In the current iteration, the system prohibits parties from initiating any actions if the solvency of either party is under scrutiny. This measure ensures the integrity and reliability of transactions within the network.
To achieve seamless settlements and maintain transparency, we rely on a trustworthy third party to procure signatures such as UPNLs and Prices. Detailed specifications of these signatures can be found in the contract's Application Binary Interface (ABI).
For a comprehensive understanding of the underlying mechanisms and operations of the Muon network, which forms an integral part of our system, please refer to the official documentation: Muon Network Documentation.
8. Off-Chain Communication between Solver and Party A
To optimize user experience, facilitate experimentation, and aid users in identifying the most suitable solver for their needs, SYMMIO provides a suite of off-chain information. This information is primarily classified into two categories: APIs and Web-Sockets.
It's important to emphasize that several of these APIs aim to reduce user request failures. They are often subject to the solver's policies. For example, if a solver doesn't mandate a whitelist, then the related APIs become superfluous.
8.1. List of APIs
This section delves into each API that a solver might offer to IntentX. It covers the API's description, URL, input parameters, and output structure. For an extensive examination and testing of these APIs, consult the Test Solver Documentation.
GET contract_symbols
Out put schema:
Description: Retrieves a list of available symbols from the solver with details like price precision, quantity precision, symbol name and ID, and the symbol's validity status.
GET add-sub-address-in-whitelist/{address}/{client}
Input Parameters:
address
: User's sub-address.client
: Given potential collaboration with multiple front-ends and contract versions of SYMMIO, this specifies the multi-account contract to be referenced.
Output: A 200 HTTP status code denotes successful whitelisting.
GET open-interest
out-put schema:
Description: This API discloses the cumulative available notional capacity of the solver (summing up the capacities across all symbols) alongside the used capacity.
POST position-state/{start}/{size}
Input Parameters:
Query Parameters:
start
andsize
are utilized for pagination.Request data:
Description: The position state mechanism notifies users of the reasons for request rejections and offers insights into activities on the solver's end. The current version of IntentX employs this route to fetch user notifications since the user's last active session. Comprehensive details on this mechanism will be elucidated in the web-socket section.
GET notional_cap/{symbol}
Response Schema:
Description: This API reveals the total and consumed capacity of the solver specific to a given symbol.
GET price-range/{symbol}
Response Schema:
Description: The API delineates the range of acceptable prices, indicating the minimum and maximum for a particular symbol.
GET check_in-whitelist/{address}/{client}
Description: Determines whether a user's wallet has previously been whitelisted.
GET error_codes
Description: Fetches a correspondence between all error codes and their associated messages.
GET error_codes/{error_code}
Description: Retrieves the message corresponding to a specific error code.
GET get_locked_params/{symbol}?leverage={leverage}
Response Schema:
Description: Solvers have the prerogative to request varied percentages for the CVA, MM, and LF based on different leverages. This route elucidates these percentages.
GET get_market_info
Response Schema:
Description: This API is integral to the market information page of IntentX
8.2. List of Web-Sockets
8.2.1. Notification Web-Socket
Due to a delay in contracts and various events such as the filling of a position or the rejection of a request by the solver, IntentX is capable of displaying these notifications to the user in real time. The following information describes the current types of notifications within the current notification system, but if any solver requires additional types of notifications, please feel free to inquire.
Table 4: Different Types of Notifications
Filling status of intent limit
report
*
filled_amount_open, quote_id, counterparty_address
Filling status of closing order limit
report
*
filled_amount_close, quote_id, counterparty_address
Notification when the solver has viewed a request
alert
seen
last_seen_action, quote_id, counterparty_address
Notification when the solver successfully responds to a request from PartyA
alert
success
last_seen_action, quote_id, counterparty_address
Notification when the solver rejects a request from PartyA
alert
failed
error_code, last_seen_action, quote_id, counterparty_address
8.2.2. uPNL Web-Socket
This web-socket caters to user experience, displaying Upnl and related information. Note that this data serves solely for frontend representation and holds no business significance.
9. Recommended Architecture for the Solver
In this section, we present a proposed architecture tailored for solver services and components. This architecture is designed for solvers intending to hedge their positions with a broker. Each micro-service in this architecture performs a specific function. The diagram below illustrates the architecture.
Figure 9: Recommended Architecture for the Solver
Each circle in the diagram represents a distinct micro-service within the solver system. The micro-services within containers act as backup services for one another. It is imperative to ensure maximum isolation between these micro-services, facilitating communication via message brokers like RabbitMQ and Redis. Employing a micro-service architecture offers a plethora of advantages. For instance, any malfunction in one service will minimally impact others. Moreover, modifications to any individual module will not affect others, provided there's no change in its input or output specifications. It's strongly advised to utilize separate Docker containers for each micro-service to enhance isolation and streamline resource management. This modular approach promotes superior scalability and fault tolerance. Each micro-service can scale autonomously, and a failure in one won't compromise the others. In essence, a micro-service architecture offers numerous advantages, such as enhanced isolation, scalability, fault tolerance, and efficient resource management.
A brief overview of each micro-service's function is as follows:
Solver Web-Server: This micro-service offers the APIs and web-sockets essential for IntentX, as discussed in the preceding section. It extracts data from the Solver database, processes it, and transmits it to IntentX.
SYMMIO Blockchain Input Module: This module's duty is to capture events from the blockchain. Given the critical nature of this information for the solver, three separate micro-services, performing identical functions, have been established. This redundancy ensures that if one service falters, the others remain operational. These micro-services function as event-listeners, procuring a real-time stream of blockchain events via a websocket RPC. The subgraph fetcher extracts data from the subgraph, while the event poller captures events using an HTTP RPC.
Web3 Agent: This module facilitates transactions and view calls required by other micro-services.
Balance Manager: This component manages the allocation of the solver's funds across its sub-accounts to virtually eliminate liquidation risks. For instance, if the solver's health ratio is disparate across sub-accounts, this module will reallocate funds accordingly to maintain equilibrium.
Position Manager: Serving as the solver's core service, the Position Manager handles pivotal actions and decisions. It processes events fetched from the blockchain and the status of pending broker positions. This module evaluates solver policies and executes appropriate actions such as initiating or terminating positions on either the broker or contract side. Given its significance, it's advisable to deploy multiple instances of this service.
Broker Order Monitoring: This module oversees the status of limit orders with the broker and notifies the Position Manager upon order execution. Two micro-services, one relying on a WebSocket and the other on an API call, fetch these orders to ensure uninterrupted solver availability.
Broker Order Maker: This module oversees necessary updates on the broker side, encompassing order creation, cancellation, and termination.
Position Validator: Every position is reflected across three platforms: the broker, the blockchain, and the solver database. This module's role is to ensure uniformity across these platforms and alert developers in case of discrepancies.
Monitoring and Developer Alerts: This system monitors all micro-services, raising alerts to developers if any anomalies arise.
Last updated