Skip to content

Commit

Permalink
deploy: 23980fe
Browse files Browse the repository at this point in the history
  • Loading branch information
Tburm committed Sep 18, 2024
0 parents commit 1a40efa
Show file tree
Hide file tree
Showing 60 changed files with 8,906 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .buildinfo
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: aba93fa86f3be663ee9fd94ab01781fe
tags: 645f666f9bcd5a90fca523b33c5a78b7
Empty file added .nojekyll
Empty file.
109 changes: 109 additions & 0 deletions _sources/guides/advanced_perps.md.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Advanced Perps Trading

## Introduction

This guide will help you understand more advanced concepts related to trading Synthetix Perps using the `synthetix` library. Check the sidebar for the various topics covered in this guide. If you're just getting started, it is recommended to read the [Trade Perps](trade_perps.md) guide first.

## Managing Multiple Accounts

Synthetix V3 allows you to hold multiple accounts which each maintain their own balances and positions. Since all positions inside an account use the same collateral, it can be useful to manage multiple accounts to separate different trading strategies or risk profiles. A trader can even simulate "isolated margin" by using separate accounts for each position.

Your accounts are stored in the `account_ids` attribute, and can be refreshed using `get_accounts()`.
```python
# view all accounts
print(snx.perps.account_ids)

# refresh accounts
snx.perps.get_accounts()

# create an account
snx.perps.create_account(submit=True)
```

The default account is set at `snx.perps.default_account_id`. If no account is specified during some function calls, the default account will be used.
```python
>>> print(snx.perps.account_ids)
[1, 2]

>>> print(snx.perps.default_account_id)
1

>>> snx.perps.get_margin_info() # this will use account 1
>>> snx.perps.get_margin_info(account_id=2) # this will use account 2
```

To replicate isolated margin, you can use separate accounts for each position. This way, the margin and pnl of each position are isolated from each other. In this example, we will deposit 500 snxUSD to account 1 and 2, and open a position on different markets using different accounts. If one position fails to meet the margin requirements and gets liquidated, the other position will not be affected.
```python
snx.perps.modify_collateral(500, account_id=1, submit=True)
snx.perps.modify_collateral(500, account_id=2, submit=True)

snx.perps.commit_order(1, market_name="ETH", account_id=1, submit=True)
snx.perps.commit_order(0.1, market_name="BTC", account_id=2, submit=True)
```

## Fetching Order Quotes

Synthetix perps using a vAMM model, where orders are subject to price impact based on the size of the order. A premium or discount is applied to the index price based on the current skew of the market. For example, if a market is skewed long, there will be a premium applied to the index price, and vice versa.

When placing an order, you can fetch a quote to see the estimated fill price of the order. This fill price is an estimate based on the current index price, current skew, and the size of the order. The quote will also show exchange and settlement fees, and the estimated margin required for a position of that size.
```python
>>> snx.perps.get_quote(1, market_name="ETH")
{
'order_size': 1,
'index_price': 2995.72,
'fill_price': 2995.75,
'required_margin': 116.49,
'order_fees': 0.11649,
'settlement_reward_cost': 1.00137346
}
```

## Liquidations

Liquidations occur when an account fails to meet the margin requirements given the size of their positions. When an account is liquidated, their positions are all closed and their collateral is lost. Liquidations will usually be triggered by keepers who are incentivized to liquidate accounts that fall below the maintenance margin requirement. You can check your margin balance and requirements using `get_margin_info()`.
```python
>>> snx.perps.get_margin_info()
{
'total_collateral_value': 98.38,
'available_margin': 98.39,
'withdrawable_margin': 12.804,
'initial_margin_requirement': 85.59,
'maintenance_margin_requirement': 64.02,
'max_liquidation_reward': 5.634
}
```

If your `available_margin` falls below the `maintenance_margin_requirement`, your account is at risk of liquidation. You can also check the status of an account using `can_liquidate` and `can_liquidates`.
```python
>>> snx.perps.can_liquidate(1)
False

>>> snx.perps.can_liquidates([1, 2])
[(1, False), (2, False)]
```

## Order Settlement

Orders are usually settled onchain by a keeper, but you can also ensure your orders are settled by calling `settle_order`. This will check your order and settle it if it is ready to be settled. This function checks the order status before submission, so if an order has been settled by someone else, it will log this and not attempt to settle the order.

```python
>>> snx.perps.settle_order() # settle order for the default account
INFO synthetix.synthetix:perps.py:1038 Waiting 0.3958 seconds to settle order
INFO synthetix.synthetix:pyth.py:99 Fetching Pyth data for 1 markets
INFO synthetix.synthetix:perps.py:1064 Settling order for account 1701411834604692328273631687329873105994
INFO synthetix.synthetix:perps.py:1065 settle tx: 0xB9153dbd4160f48f3259d0567fd75508afe8fcaa53ff328313a9654f10182742
INFO synthetix.synthetix:perps.py:1073 Order settlement successful for account 1701411834604692328273631687329873105994

>>> snx.perps.settle_order() # keeper settles order
INFO synthetix.synthetix:perps.py:1038 Order is ready to be settled
INFO synthetix.synthetix:pyth.py:99 Fetching Pyth data for 1 markets
INFO synthetix.synthetix:perps.py:1064 Settling order for account 1701411834604692328273631687329873105994
INFO synthetix.synthetix:perps.py:1073 Keeper settled ETH order committed by 1701411834604692328273631687329873105994

>>> snx.perps.settle_order(max_tx_tries=10, tx_delay=5) # increase retries and delay
```

Keep in mind the following:
- In some cases a decentralized keeper will submit their transaction in the same block as you. If this happens, your transaction will fail but your order will be settled.
- You may see some `ERROR` logs during order settlement. Since the order requires data from an offchain provider, sometimes this data is not available in time for the transaction to be submitted. This is normal and the order will be retried. You can use the `max_tx_tries` and `tx_delay` parameters to increase the number of retries and delay between retries.
- Orders expire after a specified duration. The function will throw an error if an order is part the expiration, or if the order has already been settled.
44 changes: 44 additions & 0 deletions _sources/guides/advanced_usage.md.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Advanced Usage

## Introduction

This guide will help you understand more advanced concepts for interacting with Synthetix V3 using the `synthetix` library. Check the sidebar for the various topics covered in this guide. If you're just getting started, it is recommended to read the [quickstart](quickstart.md) guide first.

## Contracts

The `synthetix` library provides functions with more simple inputs for interacting with Synthetix V3 contracts. However, you can also interact with the contracts directly using the `web3.py` library. This can be useful for more advanced use cases, debugging, or to access functions that haven't been implemented in a module yet.

The `contracts` module stores contract addresses and ABIs:
```python
# look up the PerpsMarketProxy contract
>>> snx.contracts['PerpsMarketProxy']
{
'address': '0xf53Ca60F031FAf0E347D44FbaA4870da68250c8d',
'abi': {...},
'contract': <web3 contract object>
}

# call a function on the contract
>>> perps_market_proxy = snx.contracts['PerpsMarketProxy']['contract']
>>> perps_market_proxy.functions.getMarkets().call()
(100, 200, ...)
```

## Fetching Cannon Deployments

Synthetix manages smart contract deployments using [Cannon](https://usecannon.com/). During the deployment process, new contract ABIs and addresses will be published to Cannon, however the "hard-coded" versions in the `synthetix` library will not be updated. Note that the `synthetix` library only includes the most commonly used contracts. For other contracts, fetch the addresses and ABIs from Cannon. This can be done during initialization by providing a `cannon_config`:
```python
>>> snx = Synthetix(
provider_url=provider_url,
cannon_config={
'package': 'synthetix-omnibus',
'version': '12',
'preset': 'andromeda'
})
```

This will connect to the Cannon registry onchain and IPFS to fetch the contracts for the specified package, version, and preset. You can then access the contracts for all imported packages using the `contracts` attribute:
```python
>>> snx.contracts["packages"].keys()
dict_keys(['perps_gas_oracle_node', 'pyth_erc7412_wrapper', 'system', ...])
```
58 changes: 58 additions & 0 deletions _sources/guides/oracle_data.md.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Oracle Data

Synthetix V3 uses pull oracles from [Pyth](https://pyth.network/) to fetch the latest prices for assets using the [ERC-7412](https://erc7412.vercel.app/) pattern. The SDK helps handle the process of fetching the required price data for you, however this guide will help understand how the process works.

## ERC-7412 Overview

ERC-7412 is a standard that defines how a smart contract can prompt the user to fetch some offchain data and provide it in their transaction. The flow looks like this:
1. The user calls a function on the smart contract (e.g. `getMarketSummary`)
1. The call fails, providing the user with information about what data they need to provide
1. The user fetches the data from an offchain source and creates a multicall transaction: `[fullfillOracleQuery, getMarketSummary]`
1. The call succeeds after updating the oracle data, then calling the smart contract function again

## ERC-7412 in Synthetix

Synthetix V3 uses the ERC-7412 pattern to ensure that transactions only succeed when the contracts have access to price data within a certain tolerance. For example, some view functions require that prices are under 60 minutes old, otherwise they are considered stale. For more critical operations like order settlement on the perps markets, the contracts may require a price for a specific timestamp.

For the best user experience, it is recommended that users fetch this data "optimistically" before calling a smart contract function. This will ensure that the transaction uses the most recent data and avoids running into reverts during transaction simulation.

## SDK Integration

The `synthetix` library will handle this logic for you, including optimistic fetching of oracle data. When you call a function that is expected to require some oracle data, the SDK will automatically fetch the required data and include it in a multicall. If the contract requires additional oracle data, the ERC-7412 pattern will be used to fetch the data and prepare a transaction.

To better understand this process, we can look at the `snx.perps.get_market_summaries()` function. This function will fetch information about all of the available perps markets, including the open interest, funding rate, price, skew, and more. The function will optimistically fetch prices for all markets before requesting the market summary. You can see this in action by calling the function and inspecting the logs.

```python
>>> _, markets_by_name = snx.perps.get_markets()
2024-05-01 15:55:10,714 - INFO - Fetching Pyth data for 32 markets

>>> print(markets_by_name)
{
'ETH': {
'market_id': 100,
'feed_id': '0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace',
...
},
'BTC': {
...
},
}
```

As you can see from the logs, the SDK fetched prices for all available markets from a Pyth node before requesting the market summaries.

## Caching Oracle Data

For situations that require fresh prices but not a specific timestamp, the SDK will cache price data and reuse it for subsequent calls. This is useful for reducing the number of calls made to Pyth nodes. There is a "time to live" setting that determines how long the data is cached before it is considered stale. If you want to always fetch fresh data, you can set the `pyth_cache_ttl` setting to `0`. Otherwise, it represents the number of seconds that the data is considered fresh.

```python
>>> snx = Synthetix(
provider_url=provider_url,
pyth_cache_ttl=0, # Always fetch fresh data
)

>>> snx = Synthetix(
provider_url=provider_url,
pyth_cache_ttl=5, # Cache price data for 5 seconds
)
```
79 changes: 79 additions & 0 deletions _sources/guides/quickstart.md.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
# Quickstart

This library offers a way to interact with the [Synthetix](https://synthetix.io/) protocol using Python. This guide will teach you the basics: how to set up the client and use some of its functions.

If your use case requires a more in-depth understanding of the protocol, please refer to the [Synthetix documentation](https://docs.synthetix.io/).

## Requirements

This library requires Python 3.8 or higher. It makes heavy use of the [web3.py](https://github.com/ethereum/web3.py) library for interacting with smart contracts.

It is recommended to use a virtual environment to install the library and its dependencies. Use [venv](https://docs.python.org/3/library/venv.html) to create and manage this virtual environment:

```bash
python3 -m venv env
source env/bin/activate

# optionally upgrade pip
pip install --upgrade pip
```

## Installation

The library is available from the PyPI package repository and can be installed using `pip`:

```bash
pip install synthetix
```

## Initializing the client

To use the library, initialize the `Synthetix` object that can be used to interact with the protocol. At minimum, you must provide an RPC endpoint.

```python
from synthetix import Synthetix

# Base Mainnet
snx = Synthetix(
provider_url="https://base.llamarpc.com",
)
```

This creates an `snx` object that helps you interact with the protocol smart contracts. At minimum you need to provide the `provider_url` parameter, which is the RPC endpoint of the node you want to connect to. If there are any warnings or errors during initialization, they are logged to the console.

## Basic usage

Once set up, you can use the `snx` object to interact with the different modules in the protocol. Here are some common functions you may want to use:

```python
# basic functions
snx.get_susd_balance() # fetch the balance of sUSD
snx.get_eth_balance() # fetch the balance of ETH and WETH

# perps markets
snx.perps.get_markets() # fetch all perps market summaries
snx.perps.get_account_ids() # fetch all perps accounts for the specified address
snx.perps.get_margin_info(1) # get the margin balances for account_id 1
```

Let's see how to use the get_markets function with a sample output:
```python
>>> markets_by_id, markets_by_name = snx.perps.get_markets()
>>> markets_by_name
{
'ETH': {
'market_id': 100,
'market_name': 'ETH',
'skew': -3308.71,
'size': 14786.42
'max_open_interest': 100000,
'current_funding_rate': 0.00196
'current_funding_velocity': -0.02977
'index_price': 1560.37
},
'BTC': {
...
},
...
}
```
Loading

0 comments on commit 1a40efa

Please sign in to comment.