perpsv3-Go
This repository contains a Go library for interacting with smart contracts related to a Synthetix V3
DeFi protocol. It includes components to work with Core, Spot Market, and Perps Market contracts deployed on the Optimism
mainnet and Optimistic Goerli testnet.
Table of Contents
Getting started
To install a library use:
go get github.com/gateway-fm/perpsv3-Go
go mod tidy
A usage example:
package main
import (
"log"
perpsv3_Go "github.com/gateway-fm/perpsv3-Go"
"github.com/gateway-fm/perpsv3-Go/config"
)
func main() {
perpsLib, err := perpsv3_Go.Create(config.GetGoerliDefaultPerpsvConfig())
if err != nil {
log.Fatal(err)
}
//...
}
Configuration
You can use a default configurations. For now only two default configurations are available:
A configuration for Goerli Optimistic testnet:
func GetGoerliDefaultPerpsvConfig() *PerpsvConfig {
return &PerpsvConfig{
RPC: "https://rpc.goerli.optimism.gateway.fm",
ContractAddresses: &ContractAddresses{
Core: "0x76490713314fCEC173f44e99346F54c6e92a8E42",
SpotMarket: "0x5FF4b3aacdeC86782d8c757FAa638d8790799E83",
PerpsMarket: "0xf272382cB3BE898A8CdB1A23BE056fA2Fcf4513b",
},
FirstContractBlocks: &FirstContractBlocks{
Core: 11664658,
SpotMarket: 10875051,
PerpsMarket: 12708889,
},
ConnectionTimeout: time.Second * 30,
ReadTimeout: time.Second * 15,
}
}
And a configuration for Optimism mainnet. Be informed that mainnet configs will return an error at this version due to
the luck of Perps Market contract address on mainnnet.
func GetOptimismDefaultPerpsvConfig() *PerpsvConfig {
return &PerpsvConfig{
RPC: "https://rpc.optimism.gateway.fm",
ContractAddresses: &ContractAddresses{
Core: "0xffffffaEff0B96Ea8e4f94b2253f31abdD875847",
SpotMarket: "0x38908Ee087D7db73A1Bd1ecab9AAb8E8c9C74595",
PerpsMarket: "",
},
FirstContractBlocks: &FirstContractBlocks{
Core: 94847041,
SpotMarket: 94846457,
PerpsMarket: 0,
},
ConnectionTimeout: time.Second * 30,
ReadTimeout: time.Second * 15,
}
}
You can use you own configuration by creating a Config instance:
package main
import (
"log"
perpsv3_Go "github.com/gateway-fm/perpsv3-Go"
"github.com/gateway-fm/perpsv3-Go/config"
)
func main() {
conf := &config.PerpsvConfig{
RPC: "https://rpc.optimism.gateway.fm",
//...
}
perpsLib, err := perpsv3_Go.Create(conf)
if err != nil {
log.Fatal(err)
}
//...
}
API Reference
=== Trades ===
== Model ==
Using Trades services you operate with Trades model which represents a OrderSettled
event of Perps Market smart-contract
with some additional fields:
type Trade struct {
// Event fields:
MarketID uint64 // ID of the market used for the trade
AccountID uint64 // ID of the account used for the trade
FillPrice *big.Int // Price at which the order was settled
PnL *big.Int // PL of the previous closed position
AccruedFunding *big.Int // Accrued funding of the previous closed position
SizeDelta *big.Int // Size delta from the order
NewSize *big.Int // New size of the position after settlement
TotalFees *big.Int // Amount of fees collected by the protocol
ReferralFees *big.Int // Amount of fees collected by the referrer
CollectedFees *big.Int // Amount of fees collected by the fee collector
SettlementReward *big.Int // Amount of fees collected by the settler
TrackingCode [32]byte // Optional code for integrator tracking purposes
Settler common.Address // Address of the settler of the order
// Additional fields:
BlockNumber uint64 // Block number where the trade was settled
BlockTimestamp uint64 // Timestamp of the block where the trade was settled
TransactionHash string // Hash of the transaction where the trade was settled
}
== RetrieveTrades ==
To get trades for specific block range use the RetrieveTrades function:
func RetrieveTrades(fromBlock uint64, toBLock *uint64) ([]*models.Trade, error) {}
- Default value for
fromBlock
is a first contract block that you give in the configs
- Default value for
toBlock
is a latest blockchain block
- To use default values set
0
for fromBlock
and nil
for toBlock
- For specific block data use same values for
fromBlock
and toBlock
- For all contract data use default values
- For a range of blocks use required block IDs
Warning
If you want to query more than 20 000 block or query old block be sure you use a private PRC provider
== ListenTrades ==
To subscribe on the contract OrederSettled
event use the ListenTrades function.
func ListenTrades() (*events.TradeSubscription, error) {}
The goroutine will return events as a Trade
model on the TradesChan
chanel and errors on the ErrChan
chanel. To
close the subscription use the Close
function.
You can see an example of the usage here:
package main
import (
"fmt"
"log"
"time"
perpsv3_Go "github.com/gateway-fm/perpsv3-Go"
"github.com/gateway-fm/perpsv3-Go/config"
)
func main() {
lib, err := perpsv3_Go.Create(config.GetGoerliDefaultPerpsvConfig())
if err != nil {
log.Fatal(err)
}
subs, err := lib.ListenTrades()
if err != nil {
log.Fatal(err)
}
stopChan := make(chan struct{})
// handle events
go func() {
for {
select {
case <-stopChan:
subs.Close()
return
case err = <-subs.ErrChan:
log.Println(err.Error())
case trade := <-subs.TradesChan:
fmt.Println(trade.AccountID)
fmt.Println(trade.AccruedFunding)
}
}
}()
time.Sleep(10 * time.Second)
// stop listening
close(stopChan)
time.Sleep(5 * time.Second)
}
=== Orders ===
== Model ==
Using Orders services you operate with Orders model which represents a OrderCommitted
event of Perps Market smart-contract
with some additional fields:
type Order struct {
// Event fields:
MarketID uint64 // ID of the market used for the trade
AccountID uint64 // ID of the account used for the trade
OrderType uint8 // Represents the transaction type (0 at the time of writing)
SizeDelta *big.Int // Requested change in size of the order
AcceptablePrice *big.Int // Maximum or minimum accepted price to settle the order.
SettlementTime uint64 // Time at which the order can be settled.
ExpirationTime uint64 // Time at which the order expired.
TrackingCode [32]byte // Optional code for integrator tracking purposes.
Sender common.Address // Address of the sender of the order.
// Additional fields:
BlockNumber uint64 // Block number where the trade was settled
BlockTimestamp uint64 // Timestamp of the block where the trade was settled
}
== RetrieveOrders ==
To get orders for specific block range use the RetrieveOrders function:
func RetrieveOrders(fromBlock uint64, toBLock *uint64) ([]*models.Order, error) {}
- Default value for
fromBlock
is a first contract block that you give in the configs
- Default value for
toBlock
is a latest blockchain block
- To use default values set
0
for fromBlock
and nil
for toBlock
- For specific block data use same values for
fromBlock
and toBlock
- For all contract data use default values
- For a range of blocks use required block IDs
Warning
If you want to query more than 20 000 block or query old block be sure you use a private PRC provider
== ListenOrders ==
To subscribe on the contract OrederCommitted
event use the ListenOrders function.
func ListenOrders() (*events.OrderSubscription, error) {}
The goroutine will return events as a Order
model on the OrdersChan
chanel and errors on the ErrChan
chanel. To
close the subscription use the Close
function.
=== MarketUpdate ===
== Model ==
Using MarketData services you operate with MarketUpdate model which represents a MarketUpdated
event of Perps Market smart-contract
with some additional fields:
type MarketUpdate struct {
// Event fields
MarketID uint64 // ID of the market.
Price uint64 // Price at the time of the event.
Skew int64 // Market skew at the time of the event. Positive values indicate more longs.
Size uint64 // Size of the entire market after settlement.
SizeDelta int64 // Change in market size during the update.
CurrentFundingRate int64 // Current funding rate of the market.
CurrentFundingVelocity int64 // Current rate of change of the funding rate.
// Additional fields
BlockNumber uint64 // Block number at which the market data was fetched.
BlockTimestamp uint64 // Timestamp of the block at which the market data was fetched.
TransactionHash string // Hash of the transaction where the market update occurred.
}
== RetrieveMarketUpdate ==
To get market update data for specific block range use the RetrieveOrders function:
func RetrieveMarketUpdates(fromBlock uint64, toBLock *uint64) ([]*models.MarketUpdate, error) {}
- Default value for
fromBlock
is a first contract block that you give in the configs
- Default value for
toBlock
is a latest blockchain block
- To use default values set
0
for fromBlock
and nil
for toBlock
- For specific block data use same values for
fromBlock
and toBlock
- For all contract data use default values
- For a range of blocks use required block IDs
Warning
If you want to query more than 20 000 block or query old block be sure you use a private PRC provider
== ListenMarketUpdate ==
To subscribe on the contract MarketUpdated
event use the ListenMarketUpdates function.
func ListenMarketUpdates() (*events.MarketUpdateSubscription, error)
The goroutine will return events as a MarketUpdate
model on the MarketUpdateChan
chanel and errors on the ErrChan
chanel. To
close the subscription use the Close
function.
=== Positions ===
== Model ==
Using Positions services you operate with Position model which represents a OpenPosition
data struct of Perps Market
smart-contract with some additional fields:
type Position struct {
// Data from the contract
TotalPnl *big.Int // Represents the total profit and loss for the position
AccruedFunding *big.Int // Represents the accrued funding for the position
PositionSize *big.Int // Represents the size of the position
// Data from the latest block
BlockNumber uint64 // Represents the block number at which the position data was fetched
BlockTimestamp uint64 // Represents the timestamp of the block at which the position data was fetched
}
== GetPosition ==
To get Position
by reading contract with getOpenPosition
method use the GetPosition function:
func GetPosition(accountID *big.Int, marketID *big.Int) (*models.Position, error) {}
It will return data from the contract in the latest block. Function can return contract error if the market ID is invalid.
If account ID is invalid it will return model with blank fields.
License
This project is licensed under the MIT License.