dydx

package module
v1.0.6 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 28, 2023 License: MIT Imports: 30 Imported by: 0

README

go-dydx

Documentation

See the documentation on the package page:

Go Reference

golang client for dydx.exchange, supports:

  • onboarding

    • create user.
    • deterministic recover api key and stark key.
  • private api

    • get user, accounts, positions, orders, withdrawals, fills, funding, and pnl.
    • create, cancel orders and active orders.
    • subscription to account updates.
  • public api

    • get markets, orderbooks, trades, candles, historical fundings.
    • subscription to markets, orderbooks, trades.

Prior Art

This is based on the work from go-numb at here with some go idiomatic modifications.

There is also another version from verichenn here.

Command Line Interface

A command line interface is provided in dydx-cli. To install:

go install github.com/fardream/go-dydx/dyx-cli@latest

A command line interface is provided to replay the orderbook updates dydx-replay-orderbook. To install:

go install github.com/fardream/go-dydx/dyx-replay-orderbook@latest

Documentation

Overview

go-dydx is a golang api for dydx.exchange

Apis are mapped directly to https://docs.dydx.exchange.

No authentication is necessary for public information on dydx.exchange. Api key and stark key are necessary to access the private apis and trade. Api key and stark key can be obtained through the LocalStorage tab of the browser development console.

Example

An example with subscriptions

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/fardream/go-dydx"
)

var _ = "keep"

// An example with subscriptions
func main() {
	const ethAddress = "<eth address>"
	client, err := dydx.NewClient(
		dydx.NewStarkKey(
			"<stark pubkey>",
			"<stark pubkey y coordinate>",
			"<stark private key>"),
		dydx.NewApiKey(
			"<api key>",
			"<api passphrase>",
			"<api secret>"),
		ethAddress,
		false)
	if err != nil {
		panic(err)
	}

	orderbook := make(chan *dydx.OrderbookChannelResponse)

	ctx, cancel := context.WithTimeout(context.Background(), time.Second*15)
	defer cancel()
	go func() {
		if err := client.SubscribeOrderbook(ctx, "BTC-USD", orderbook); err != nil {
			fmt.Printf("sub order error: %#v\n", err)
		}
		close(orderbook)
	}()

	for v := range orderbook {
		spew.Printf("%#v\n", v)
	}

	ctx, cancel = context.WithTimeout(context.Background(), time.Second*15)
	defer cancel()
	trades := make(chan *dydx.TradesChannelResponse)
	go func() {
		if err := client.SubscribeTrades(ctx, "BTC-USD", trades); err != nil {
			fmt.Printf("sub trades error: %v\n", err)
		}
		close(trades)
	}()

	for v := range trades {
		spew.Printf("%v\n", v)
	}

	markets := make(chan *dydx.MarketsChannelResponse)

	ctx, cancel = context.WithTimeout(context.Background(), time.Second*15)
	defer cancel()
	go func() {
		if err := client.SubscribeMarkets(ctx, markets); err != nil {
			fmt.Printf("sub order error: %#v\n", err)
		}
		close(markets)
	}()

	for v := range markets {
		spew.Printf("%#v\n", v)
	}

	ctx, cancel = context.WithTimeout(context.Background(), time.Second*15)
	defer cancel()
	accounts := make(chan *dydx.AccountChannelResponse)
	go func() {
		if err := client.SubscribeAccount(ctx, 0, accounts); err != nil {
			fmt.Printf("sub trades error: %v\n", err)
		}
		close(accounts)
	}()

	for v := range accounts {
		spew.Printf("%v\n", v)
	}
}
Output:

Index

Examples

Constants

View Source
const (
	ApiHostMainnet = "https://api.dydx.exchange"
	ApiHostRopsten = "https://api.stage.dydx.exchange"
	WsHostMainnet  = "wss://api.dydx.exchange/v3/ws"
	WsHostRopsten  = "wss://api.stage.dydx.exchange/v3/ws"
)
View Source
const (
	NetworkIdMainnet = 1
	NetworkIdRopsten = 3
)
View Source
const (
	Resolution1D     = "1DAY"
	Resolution4HOURS = "4HOURS"
	Resolution1HOUR  = "1HOUR"
	Resolution30MINS = "30MINS"
	Resolution15MINS = "15MINS"
	Resolution5MINS  = "5MINS"
	Resolution1MIN   = "1MIN"
)
View Source
const (
	PositionStatusOpen       = "OPEN"
	PositionStatusClosed     = "CLOSED"
	PositionStatusLiquidated = "LIQUIDATED"
)
View Source
const (
	AccountChannel   = "v3_accounts"
	MarketsChannel   = "v3_markets"
	OrderbookChannel = "v3_orderbook"
	TradesChannel    = "v3_trades"
)
View Source
const (
	ChannelResponseTypeSubscribe   = "subscribed"
	ChannelResponseTypeUnsubscribe = "unsubscribed" // unused
	ChannelResponseTypeError       = "error"
	ChannelResponseTypeConnected   = "connected"
	ChannelResponseTypeChannelData = "channel_data"
)

Variables

This section is empty.

Functions

func GetAccountIdFromEth

func GetAccountIdFromEth(ethAddress string) string

func GetIsoDateStr

func GetIsoDateStr(t time.Time) string

func GetUserId

func GetUserId(ethAddress string) string

func NewEcdsaPrivateKeySigner

func NewEcdsaPrivateKeySigner(key *ecdsa.PrivateKey) *ecdsaPrivateKeySigner

NewEcdsaPrivateKeySigner converts an *ecdsa.PrivateKey into a signer to EthSignTypedData

func ParseApiKeyMap

func ParseApiKeyMap(input []byte) (map[string]*ApiKey, error)

func ParseStarkKeyMap

func ParseStarkKeyMap(input []byte) (map[string]*StarkKey, error)

func SetClientEndpoint

func SetClientEndpoint(isMainnet bool) clientOption

func SetClientTimeout

func SetClientTimeout(timeout time.Duration) clientOption

Types

type Account

type Account struct {
	PositionId         int64               `json:"positionId,string"`
	ID                 string              `json:"id"`
	StarkKey           string              `json:"starkKey"`
	Equity             Decimal             `json:"equity"`
	FreeCollateral     Decimal             `json:"freeCollateral"`
	QuoteBalance       Decimal             `json:"quoteBalance"`
	PendingDeposits    string              `json:"pendingDeposits"`
	PendingWithdrawals string              `json:"pendingWithdrawals"`
	AccountNumber      JsonInt             `json:"accountNumber"`
	OpenPositions      map[string]Position `json:"openPositions,omitempty"`
	CreatedAt          time.Time           `json:"createdAt"`
}

type AccountChannelResponseContents

type AccountChannelResponseContents struct {
	Account   *Account    `json:"account,omitempty"`
	Orders    []*Order    `json:"orders,omitempty"`
	Fills     []*Fill     `json:"fills,omitempty"`
	Accounts  []*Account  `json:"accounts,omitempty"`
	Transfers []*Transfer `json:"transfers,omitempty"`
	Positions []*Position `json:"positions,omitempty"`
}

type AccountInfoByMarket

type AccountInfoByMarket struct {
	Market string

	// OpenPosition currently active
	OpenPosition *Position
	// All Positions
	AllPositions []*Position
	// ActiveOrders
	ActiveOrders map[string]*Order
	// ClosedOrders
	ClosedOrders map[string]*Order
	// Fills
	Fills map[string]*FillList
}

AccountInfoByMarket contains market specific information.

func NewAccountInfoByMarket

func NewAccountInfoByMarket(market string) *AccountInfoByMarket

func (*AccountInfoByMarket) AddFill

func (info *AccountInfoByMarket) AddFill(fill *Fill)

func (*AccountInfoByMarket) AddOrder

func (info *AccountInfoByMarket) AddOrder(order *Order)

func (*AccountInfoByMarket) AddPosition

func (info *AccountInfoByMarket) AddPosition(position *Position)

type AccountProcessor

type AccountProcessor struct {
	Account *Account

	Info map[string]*AccountInfoByMarket
	// contains filtered or unexported fields
}

AccountProcessor can be used to process Account Channel Updates

func NewAccountProcessor

func NewAccountProcessor() *AccountProcessor

func (*AccountProcessor) ProcessChannelResponse

func (ap *AccountProcessor) ProcessChannelResponse(resp *AccountChannelResponse)

ProcessChannelResponse processes the channel responses in sequence.

type AccountResponse

type AccountResponse struct {
	Account Account `json:"account"`
}

type AccountsResponse

type AccountsResponse struct {
	Accounts []*Account `json:"accounts"`
}

type ActiveOrder

type ActiveOrder struct {
	ID            string    `json:"id"`
	AccountID     string    `json:"accountId"`
	Market        string    `json:"market"`
	Side          OrderSide `json:"side"`
	Price         Decimal   `json:"price"`
	RemainingSize Decimal   `json:"remainingSize"`
}

type ActiveOrdersResponse

type ActiveOrdersResponse struct {
	Orders []ActiveOrder `json:"orders"`
}

type ApiKey

type ApiKey struct {
	Secret     string `json:"secret"`
	Key        string `json:"key"`
	Passphrase string `json:"passphrase"`
}

ApiKey is the format from browser's local storage. Below are from browser but not necessary

- WalletAddress string `json:"walletAddress"` - LegacySigning bool `json:"legacySigning"` - WalletType string `json:"walletType"`

func NewApiKey

func NewApiKey(key, passphrase, secret string) *ApiKey

func RecoverDefaultApiKeyCredentials

func RecoverDefaultApiKeyCredentials(signer SignTypedData, isMainnet bool) (*ApiKey, error)

RecoverDefaultApiKeyCredentials recovers the default credentials.

Implementation is a carbon-copy of the code in python version of official dydx client: https://github.com/dydxprotocol/dydx-v3-python/blob/914fc66e542d82080702e03f6ad078ca2901bb46/dydx3/modules/onboarding.py#L147-L184

func (*ApiKey) Set

func (c *ApiKey) Set(filename string) error

Set reads the file containing the ApiKey, for cobra cli.

func (*ApiKey) Sign

func (a *ApiKey) Sign(requestPath, method, isoTimestamp string, body []byte) string

Sign a request for dydx

func (*ApiKey) String

func (c *ApiKey) String() string

String prints out the key, for cobra cli.

func (*ApiKey) Type

func (c *ApiKey) Type() string

Type is for cobra cli.

type Asks

type Asks struct {
	// contains filtered or unexported fields
}

Asks side of the book.

func (*Asks) Len

func (m *Asks) Len() int

func (*Asks) Less

func (a *Asks) Less(i, j int) bool

func (*Asks) Pop

func (m *Asks) Pop() *OrderbookOrder

func (*Asks) PrintBook

func (m *Asks) PrintBook() string

func (*Asks) Push

func (m *Asks) Push(order *OrderbookOrder)

func (*Asks) Swap

func (m *Asks) Swap(i, j int)

type Bids

type Bids struct {
	// contains filtered or unexported fields
}

Bids side of the book.

func (*Bids) Len

func (m *Bids) Len() int

func (*Bids) Less

func (b *Bids) Less(i, j int) bool

func (*Bids) Pop

func (m *Bids) Pop() *OrderbookOrder

func (*Bids) PrintBook

func (m *Bids) PrintBook() string

func (*Bids) Push

func (m *Bids) Push(order *OrderbookOrder)

func (*Bids) Swap

func (m *Bids) Swap(i, j int)

type CancelActiveOrdersParam

type CancelActiveOrdersParam struct {
	Market string    `url:"market,omitempty"`
	Side   OrderSide `url:"side,omitempty"`
	Id     string    `url:"id,omitempty"`
}

type CancelActiveOrdersResponse

type CancelActiveOrdersResponse struct {
	CancelOrders []ActiveOrder `json:"cancelOrders"`
}

type CancelOrderResponse

type CancelOrderResponse struct {
	CancelOrder Order `json:"cancelOrder"`
}

type CancelOrdersParam

type CancelOrdersParam struct {
	Market string `url:"market,omitempty"`
}

type CancelOrdersResponse

type CancelOrdersResponse struct {
	CancelOrders []Order `json:"cancelOrders"`
}

type CancelReason

type CancelReason string

CancelReason is the reason for order cancellation. See here https://docs.dydx.exchange/#get-orders (section "Cancel Reasons")

const (
	CancelReasonUndercollateralized CancelReason = "UNDERCOLLATERALIZED"   // Order would have led to an undercollateralized state for the user.
	CancelReasonExpired             CancelReason = "EXPIRED"               // Order expired.
	CancelReasonUserCancelled       CancelReason = "USER_CANCELED"         // Order was canceled by the user.
	CancelReasonSelfTrade           CancelReason = "SELF_TRADE"            // Order would have resulted in a self trade for the user.
	CancelReasonFailed              CancelReason = "FAILED"                // An internal issue caused the order to be canceled.
	CancelReasonCouldNotFill        CancelReason = "COULD_NOT_FILL"        // A FOK or IOC order could not be fully filled.
	CancelReasonPostOnlyWouldCross  CancelReason = "POST_ONLY_WOULD_CROSS" // A post-only order would cross the orderbook.
)

func GetCancelReason

func GetCancelReason(input string) (CancelReason, error)

func (CancelReason) MarshalJSON

func (ot CancelReason) MarshalJSON() ([]byte, error)

func (*CancelReason) UnmarshalJSON

func (ot *CancelReason) UnmarshalJSON(input []byte) error

type Candle

type Candle struct {
	Market               string    `json:"market"`
	Resolution           string    `json:"resolution"`
	Low                  string    `json:"low"`
	High                 string    `json:"high"`
	Open                 string    `json:"open"`
	Close                string    `json:"close"`
	BaseTokenVolume      string    `json:"baseTokenVolume"`
	Trades               string    `json:"trades"`
	UsdVolume            string    `json:"usdVolume"`
	StartingOpenInterest string    `json:"startingOpenInterest"`
	StartedAt            time.Time `json:"startedAt"`
	UpdatedAt            time.Time `json:"updatedAt"`
}

type CandlesParam

type CandlesParam struct {
	Market     string `url:"-"`
	Resolution string `url:"resolution,omitempty"`
	FromISO    string `url:"fromISO,omitempty"`
	ToISO      string `url:"toISO,omitempty"`
	// Max:100
	Limit int `url:"limit,omitempty"`
}

type CandlesResponse

type CandlesResponse struct {
	Candles []Candle `json:"candles"`
}

https://docs.dydx.exchange/?json#get-candles-for-market

type ChannelResponse

type ChannelResponse[TContents any] struct {
	ChannelResponseHeader
	Contents *TContents `json:"contents,omitempty"`
}

type ChannelResponseHeader

type ChannelResponseHeader struct {
	// Type of the response (see ChannelResponseType*)
	Type string `json:"type"`

	// Channel
	Channel string `json:"channel"`

	// ConnectionId
	ConnectionID string `json:"connection_id,omitempty"`

	// MessageId
	MessageID int `json:"message_id,omitempty"`

	// Message contains the error message if there is an error
	Message string `json:"message,omitempty"`

	// Id is the subscribed to id, such as account, market (BTC-USD) etc.
	Id string `json:"id,omitempty"`
}

ChannelResponseHeader contains all the common information in the channel response.

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is a struct holding the information necessary to connect to dydx.

func NewClient

func NewClient(starkKey *StarkKey, apiKey *ApiKey, ethAddress string, isMainnet bool, clientOptions ...clientOption) (*Client, error)

NewClient creates a new Client, but doesn't connect to the dydx.exchange yet. If only public method is needed, keys and eth addersse can be empty/nil.

func (*Client) CancelActiveOrders

func (c *Client) CancelActiveOrders(ctx context.Context, params *CancelActiveOrdersParam) (*CancelActiveOrdersResponse, error)

CancelActiveOrders cancels mulitple orders at the same time, however, it utilizes the active order api. It implements https://docs.dydx.exchange/?json#cancel-active-orders

func (*Client) CancelOrder

func (c *Client) CancelOrder(ctx context.Context, id string) (*CancelOrderResponse, error)

CancelOrder

func (*Client) CancelOrders

func (c *Client) CancelOrders(ctx context.Context, params *CancelOrdersParam) (*CancelOrdersResponse, error)

CancelOrders cancels multiple orders at the same time. It implements https://docs.dydx.exchange/?json#cancel-orders

func (*Client) CreateUser

func (c *Client) CreateUser(ctx context.Context, signer SignTypedData, param *CreateUserParam) (*CreateUserResponse, error)

CreateUser creates a new user on dydx. See here: https://docs.dydx.exchange/#onboarding Note this is re-produced from python version https://github.com/dydxprotocol/dydx-v3-python/blob/914fc66e542d82080702e03f6ad078ca2901bb46/dydx3/modules/onboarding.py#L32-L112

Example

An example that generate a new private key for ethereum network, use the default stark key and api credentials, then create the user on the testnet, and request token airdrops.

package main

import (
	"context"
	"fmt"

	"github.com/davecgh/go-spew/spew"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/fardream/go-dydx"
)

const createUserIsMainnet = false

// An example that generate a new private key for ethereum network,
// use the default stark key and api credentials, then create the user on the
// testnet, and request token airdrops.
func main() {
	// create private key on the ethereum network
	privateKey, err := crypto.GenerateKey()
	if err != nil {
		panic(err)
	}

	fmt.Printf("testing private key: %s\n", hexutil.Encode(crypto.FromECDSA(privateKey)))

	// public key address
	ethAddress := crypto.PubkeyToAddress(privateKey.PublicKey)

	fmt.Printf("testing public key: %s\n", ethAddress.String())

	// signer
	signer := dydx.NewEcdsaPrivateKeySigner(privateKey)

	// stark key
	starkKey, err := dydx.DeriveStarkKey(signer, createUserIsMainnet)
	if err != nil {
		panic(err)
	}

	// api key
	apiKey, err := dydx.RecoverDefaultApiKeyCredentials(signer, false)
	if err != nil {
		panic(err)
	}

	// create a new client
	client, err := dydx.NewClient(starkKey, apiKey, ethAddress.String(), createUserIsMainnet)
	if err != nil {
		panic(err)
	}

	// create user on the dydx
	resp, err := client.CreateUser(context.Background(), signer, nil)
	if err != nil {
		panic(err)
	} else {
		spew.Dump(resp)
	}

	// request airdrop
	_, err = client.RequestTestnetTokens(context.Background())
	if err != nil {
		panic(err)
	}
}
Output:

func (*Client) GetAccount

func (c *Client) GetAccount(ctx context.Context, id string) (*AccountResponse, error)

GetAccount with a specific id, implements https://docs.dydx.exchange/#get-account

func (*Client) GetAccounts

func (c *Client) GetAccounts(ctx context.Context) (*AccountsResponse, error)

GetAccounts implements https://docs.dydx.exchange/#get-accounts, it gets all accounts

func (*Client) GetActiveOrders

func (c *Client) GetActiveOrders(ctx context.Context, params *QueryActiveOrdersParam) (*ActiveOrdersResponse, error)

GetActiveOrders implements https://docs.dydx.exchange/#cancel-active-orders

func (*Client) GetCandles

func (c *Client) GetCandles(ctx context.Context, params *CandlesParam) (*CandlesResponse, error)

func (*Client) GetFills

func (c *Client) GetFills(ctx context.Context, params *FillsParam) (*FillsResponse, error)

GetFills implements https://docs.dydx.exchange/#get-fills

func (*Client) GetFundingPayments

func (c *Client) GetFundingPayments(ctx context.Context, params *FundingPaymentsParam) (*FundingPaymentsResponse, error)

func (*Client) GetHistoricalFunding

func (c *Client) GetHistoricalFunding(ctx context.Context, params *HistoricalFundingsParam) (*HistoricalFundingsResponse, error)

func (*Client) GetHistoricalPnL

func (c *Client) GetHistoricalPnL(ctx context.Context, params *HistoricalPnLParam) (*HistoricalPnLResponse, error)

func (*Client) GetMarkets

func (c *Client) GetMarkets(ctx context.Context) (*MarketsResponse, error)

func (*Client) GetOrderByClientId

func (c *Client) GetOrderByClientId(ctx context.Context, clientId string) (*OrderResponse, error)

func (*Client) GetOrderById

func (c *Client) GetOrderById(ctx context.Context, id string) (*OrderResponse, error)

func (*Client) GetOrderbook

func (c *Client) GetOrderbook(ctx context.Context, market string) (*OrderbookResponse, error)
Example

Get the orderbook for BTC-USD

package main

import (
	"context"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/fardream/go-dydx"
)

var _ = "keep"

// Get the orderbook for BTC-USD
func main() {
	// No private key necesary
	client, _ := dydx.NewClient(nil, nil, "", false)
	// Set 15 minutes timeout
	ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
	defer cancel()

	spew.Dump(getOrPanic(client.GetOrderbook(ctx, "BTC-USD")))
}
Output:

func (*Client) GetOrders

func (c *Client) GetOrders(ctx context.Context, params *OrderQueryParam) (*OrdersResponse, error)

func (*Client) GetPositions

func (c *Client) GetPositions(ctx context.Context, params *PositionParams) (*PositionResponse, error)

func (*Client) GetTrades

func (c *Client) GetTrades(ctx context.Context, params *TradesParam) (*TradesResponse, error)

func (*Client) GetTradingRewards

func (c *Client) GetTradingRewards(ctx context.Context, epoch int64) (*TradingRewardsResponse, error)

func (*Client) GetUser

func (c *Client) GetUser(ctx context.Context) (*UsersResponse, error)

func (*Client) NewOrder

func (c *Client) NewOrder(ctx context.Context, order *CreateOrderRequest, positionId int64) (*CreateOrderResponse, error)
Example

Place a new order for BTC at the price of 35000

package main

import (
	"context"
	"crypto/rand"
	"math/big"
	"time"

	"github.com/davecgh/go-spew/spew"
	"github.com/fardream/go-dydx"
)

func getOrPanic[T any](input T, err error) T {
	if err != nil {
		panic(err)
	}
	return input
}

// Place a new order for BTC at the price of 35000
func main() {
	const ethAddress = "<eth address>"
	client, err := dydx.NewClient(
		dydx.NewStarkKey(
			"<stark pubkey>",
			"<stark pubkey y coordinate>",
			"<stark private key>"),
		dydx.NewApiKey(
			"<api key>",
			"<api passphrase>",
			"<api secret>"),
		ethAddress,
		false)
	if err != nil {
		panic(err)
	}

	// generate a big id
	id, _ := rand.Int(rand.Reader, big.NewInt(10000))
	id.Add(id, big.NewInt(1000000))

	// create a new order
	order := dydx.NewCreateOrderRequest("BTC-USD", dydx.OrderSideSell, dydx.OrderTypeLimit, getOrPanic(dydx.NewDecimalFromString("0.001")), getOrPanic(dydx.NewDecimalFromString("35000")), id.String(), "", time.Now().Add(5*time.Minute), getOrPanic(dydx.NewDecimalFromString("0.125")), false)
	// place the order
	r := getOrPanic(client.NewOrder(context.Background(), order, 62681))
	spew.Dump(r)
	time.Sleep(5 * time.Second)

	// get the order
	spew.Dump(getOrPanic(
		client.GetOrderById(context.Background(), r.Order.ID)).Order)
	time.Sleep(2 * time.Second)

	// cancel all active orders
	spew.Dump(client.CancelActiveOrders(context.Background(), &dydx.CancelActiveOrdersParam{Market: "BTC-USD"}))
	time.Sleep(2 * time.Second)

	// get your positions
	spew.Dump(getOrPanic(client.GetPositions(context.Background(), &dydx.PositionParams{Market: "BTC-USD"})))
	time.Sleep(2 * time.Second)

	// get the active orders
	spew.Dump(getOrPanic(client.GetActiveOrders(context.Background(), &dydx.QueryActiveOrdersParam{Market: "BTC-USD"})))
}
Output:

func (*Client) RequestTestnetTokens

func (c *Client) RequestTestnetTokens(ctx context.Context) (*RequestTestnetTokensResponse, error)

RequestTestnetTokens implements https://docs.dydx.exchange/#request-testnet-tokens Obtain testnet tokens (USDC)

func (*Client) SubscribeAccount

func (c *Client) SubscribeAccount(ctx context.Context, accountNumber int, outputChan chan<- *AccountChannelResponse) error

SubscribeAccount gets the accounts update It will feed the account update in sequence into the channel provided. It returns after the subscription is done and closed.

func (*Client) SubscribeMarkets

func (c *Client) SubscribeMarkets(ctx context.Context, outputChan chan<- *MarketsChannelResponse) error

func (*Client) SubscribeOrderbook

func (c *Client) SubscribeOrderbook(ctx context.Context, market string, outputChan chan<- *OrderbookChannelResponse) error

func (*Client) SubscribeTrades

func (c *Client) SubscribeTrades(ctx context.Context, market string, outputChan chan<- *TradesChannelResponse) error

type CreateOrderRequest

type CreateOrderRequest struct {
	Signature       string      `json:"signature"`
	Expiration      time.Time   `json:"expiration"`
	Market          string      `json:"market"`
	Side            OrderSide   `json:"side"`
	Type            OrderType   `json:"type"`
	Size            *Decimal    `json:"size"`
	Price           *Decimal    `json:"price,omitempty"`
	ClientId        string      `json:"clientId"`
	TimeInForce     TimeInForce `json:"timeInForce"`
	LimitFee        *Decimal    `json:"limitFee"`
	CancelId        string      `json:"cancelId,omitempty"`
	TriggerPrice    string      `json:"triggerPrice,omitempty"`
	TrailingPercent string      `json:"trailingPercent,omitempty"`
	PostOnly        bool        `json:"postOnly"`
}

CreateOrderRequest is the post payload to create a new order https://docs.dydx.exchange/?json#create-a-new-order

func NewCreateOrderRequest

func NewCreateOrderRequest(market string, side OrderSide, order_type OrderType, size *Decimal, price *Decimal, clientid string, tif TimeInForce, expiration time.Time, limitfee *Decimal, postonly bool) *CreateOrderRequest

NewCreateOrderRequest

type CreateOrderResponse

type CreateOrderResponse struct {
	Order *Order `json:"order,omitempty"`
}

type CreateUserParam

type CreateUserParam struct {
	StarkPublicKey            string `json:"starkKey"`
	StarkPublicKeyYCoordinate string `json:"starkKeyYCoordinate"`
	// ethereumAddress, even though listed on the documentation, is not part of the request.
	EthereumAddress         string `json:"-"`
	ReferredByAffiliateLink string `json:"referredByAffiliateLink,omitempty"`
	Country                 string `json:"country,omitempty"`
}

CreateUserParam contains the parameters to create a new user. Note ethereumAddress is actually not part of the api according to python implementation: https://github.com/dydxprotocol/dydx-v3-python/blob/914fc66e542d82080702e03f6ad078ca2901bb46/dydx3/modules/onboarding.py#L103-L111

type CreateUserResponse

type CreateUserResponse struct {
	User    *User    `json:"user,omitempty"`
	ApiKey  *ApiKey  `json:"apiKey,omitempty"`
	Account *Account `json:"account,omitempty"`
}

type Decimal

type Decimal = decimal.Decimal

func NewDecimalFromString

func NewDecimalFromString(s string) (*Decimal, error)

type DydxError

type DydxError struct {
	HttpStatusCode int
	Body           []byte
	Message        string
}

DydxError represents a successful HTTP request with status code >= 400 This can indicates errors like failed authentication with api key or bad parameters.

func (*DydxError) Error

func (e *DydxError) Error() string

type FastWithdrawalParam

type FastWithdrawalParam struct {
	ClientID     string `json:"clientId"`
	ToAddress    string `json:"toAddress"`
	CreditAsset  string `json:"creditAsset"`
	CreditAmount string `json:"creditAmount"`
	DebitAmount  string `json:"debitAmount"`
	LpPositionId string `json:"lpPositionId"`
	Expiration   string `json:"expiration"`
	Signature    string `json:"signature"`
}

type Fill

type Fill struct {
	ID        string    `json:"id"`
	Side      OrderSide `json:"side"`
	Liquidity string    `json:"liquidity"`
	Type      OrderType `json:"type"`
	Market    string    `json:"market"`
	OrderID   string    `json:"orderId"`
	Price     Decimal   `json:"price"`
	Size      Decimal   `json:"size"`
	Fee       Decimal   `json:"fee"`
	CreatedAt time.Time `json:"createdAt"`
}

type FillList

type FillList []*Fill

type FillsParam

type FillsParam struct {
	Market            string `json:"market,omitempty"`
	OrderId           string `json:"order_id,omitempty"`
	Limit             string `json:"limit,omitempty"`
	CreatedBeforeOrAt string `json:"createdBeforeOrAt,omitempty"`
}

FillsParam: https://docs.dydx.exchange/#get-fills

type FillsResponse

type FillsResponse struct {
	Fills []*Fill `json:"fills"`
}

type FundingPayment

type FundingPayment struct {
	Market       string    `json:"market"`
	Payment      string    `json:"payment"`
	Rate         string    `json:"rate"`
	PositionSize string    `json:"positionSize"`
	Price        string    `json:"price"`
	EffectiveAt  time.Time `json:"effectiveAt"`
}

type FundingPaymentsParam

type FundingPaymentsParam struct {
	Market              string `url:"market,omitempty"`
	Limit               string `url:"limit,omitempty"`
	EffectiveBeforeOrAt string `url:"effectiveBeforeOrAt,omitempty"`
}

type FundingPaymentsResponse

type FundingPaymentsResponse struct {
	FundingPayments []FundingPayment `json:"fundingPayments"`
}

type HistoricalFunding

type HistoricalFunding struct {
	Market      string    `json:"-"`
	Rate        string    `json:"rate"`
	Price       string    `json:"price"`
	EffectiveAt time.Time `json:"effectiveAt"`
}

type HistoricalFundingsParam

type HistoricalFundingsParam struct {
	Market              string `url:"-"`
	EffectiveBeforeOrAt string `url:"effectiveBeforeOrAt,omitempty"`
}

type HistoricalFundingsResponse

type HistoricalFundingsResponse struct {
	HistoricalFundings []HistoricalFunding `json:"historicalFunding"`
}

type HistoricalPnL

type HistoricalPnL struct {
	AccountID    string    `json:"accountId"`
	Equity       string    `json:"equity"`
	TotalPnl     string    `json:"totalPnl"`
	NetTransfers string    `json:"netTransfers"`
	CreatedAt    time.Time `json:"createdAt"`
}

type HistoricalPnLParam

type HistoricalPnLParam struct {
	EffectiveBeforeOrAt string `url:"effectiveBeforeOrAt,omitempty"`
	EffectiveAtOrAfter  string `url:"effectiveAtOrAfter,omitempty"`
}

type HistoricalPnLResponse

type HistoricalPnLResponse struct {
	HistoricalPnLs []HistoricalPnL `json:"historicalPnl"`
}

type JsonInt

type JsonInt int

JsonInt is an int, but can be json-unmarshaled from either int or string, marshalled into string.

func (JsonInt) MarshalJSON

func (an JsonInt) MarshalJSON() ([]byte, error)

MarshalJSON converts JsonInt into string and marshal that.

func (*JsonInt) UnmarshalJSON

func (an *JsonInt) UnmarshalJSON(input []byte) error

type Logger

type Logger interface {
	Debugf(string, ...any)
	Infof(string, ...any)
	Warnf(string, ...any)
	Errorf(string, ...any)
	Fatalf(string, ...any)
}

Logger defines an interface to log. By default this is uber's zap.

func SetupLogger

func SetupLogger(defaultLevel, envName string) Logger

type Market

type Market struct {
	Market                           string     `json:"market,omitempty"`
	BaseAsset                        string     `json:"baseAsset,omitempty"`
	QuoteAsset                       string     `json:"quoteAsset,omitempty"`
	StepSize                         *Decimal   `json:"stepSize,omitempty"`
	TickSize                         *Decimal   `json:"tickSize,omitempty"`
	IndexPrice                       *Decimal   `json:"indexPrice,omitempty"`
	OraclePrice                      *Decimal   `json:"oraclePrice,omitempty"`
	PriceChange24H                   *Decimal   `json:"priceChange24H,omitempty"`
	NextFundingRate                  *Decimal   `json:"nextFundingRate,omitempty"`
	MinOrderSize                     *Decimal   `json:"minOrderSize,omitempty"`
	Type                             string     `json:"type,omitempty"`
	InitialMarginFraction            *Decimal   `json:"initialMarginFraction,omitempty"`
	MaintenanceMarginFraction        *Decimal   `json:"maintenanceMarginFraction,omitempty"`
	BaselinePositionSize             *Decimal   `json:"baselinePositionSize,omitempty"`
	IncrementalPositionSize          *Decimal   `json:"incrementalPositionSize,omitempty"`
	IncrementalInitialMarginFraction *Decimal   `json:"incrementalInitialMarginFraction,omitempty"`
	Volume24H                        *Decimal   `json:"volume24H,omitempty"`
	Trades24H                        *Decimal   `json:"trades24H,omitempty"`
	OpenInterest                     *Decimal   `json:"openInterest,omitempty"`
	MaxPositionSize                  *Decimal   `json:"maxPositionSize,omitempty"`
	AssetResolution                  string     `json:"assetResolution,omitempty"`
	SyntheticAssetID                 string     `json:"syntheticAssetId,omitempty"`
	Status                           string     `json:"status,omitempty"`
	NextFundingAt                    *time.Time `json:"nextFundingAt,omitempty"`
}

type MarketsChannelResponseContents

type MarketsChannelResponseContents = map[string]Market

type MarketsResponse

type MarketsResponse struct {
	Markets map[string]Market `json:"markets"`
}

Market contains the meta data for a market. https://docs.dydx.exchange/#get-markets

type Order

type Order struct {
	ID              string        `json:"id"`
	ClientID        string        `json:"clientId"`
	AccountID       string        `json:"accountId"`
	Market          string        `json:"market"`
	Side            OrderSide     `json:"side"`
	Price           Decimal       `json:"price"`
	TriggerPrice    *Decimal      `json:"triggerPrice,omitempty"`
	TrailingPercent *Decimal      `json:"trailingPercent,omitempty"`
	Size            Decimal       `json:"size"`
	RemainingSize   Decimal       `json:"remainingSize"`
	Type            OrderType     `json:"type"`
	UnfillableAt    *time.Time    `json:"unfillableAt,omitempty"`
	Status          OrderStatus   `json:"status"`
	TimeInForce     TimeInForce   `json:"timeInForce"`
	CancelReason    *CancelReason `json:"cancelReason,omitempty"`
	PostOnly        bool          `json:"postOnly"`
	CreatedAt       time.Time     `json:"createdAt"`
	ExpiresAt       time.Time     `json:"expiresAt"`
}

Order is the information returned from dydx

type OrderQueryParam

type OrderQueryParam struct {
	Limit              int    `url:"limit,omitempty"`
	Market             string `url:"market,omitempty"`
	Status             string `url:"status,omitempty"`
	Type               string `url:"type,omitempty"`
	Side               string `url:"side,omitempty"`
	CreatedBeforeOrAt  string `url:"createdAt,omitempty"`
	ReturnLatestOrders string `url:"returnLatestOrders,omitempty"`
}

type OrderResponse

type OrderResponse struct {
	Order Order `json:"order"`
}

type OrderSide

type OrderSide string
const (
	OrderSideBuy  OrderSide = "BUY"
	OrderSideSell OrderSide = "SELL"
)

func GetOrderSide

func GetOrderSide(input string) (OrderSide, error)

func (OrderSide) MarshalJSON

func (os OrderSide) MarshalJSON() ([]byte, error)

func (*OrderSide) UnmarshalJSON

func (os *OrderSide) UnmarshalJSON(input []byte) error

type OrderStatus

type OrderStatus string
const (
	OrderStatusPending     OrderStatus = "PENDING"
	OrderStatusOpen        OrderStatus = "OPEN"
	OrderStatusFilled      OrderStatus = "FILLED"
	OrderStatusCanceled    OrderStatus = "CANCELED"
	OrderStatusUntriggered OrderStatus = "UNTRIGGERED"
)

func GetOrderStatus

func GetOrderStatus(input string) (OrderStatus, error)

func (OrderStatus) MarshalJSON

func (ot OrderStatus) MarshalJSON() ([]byte, error)

func (*OrderStatus) UnmarshalJSON

func (ot *OrderStatus) UnmarshalJSON(input []byte) error

type OrderType

type OrderType string

OrderType indicates if the order is market, limit, stop, trailing stop or taking profit. See https://docs.dydx.exchange/#order-types

const (
	OrderTypeMarket       OrderType = "MARKET"
	OrderTypeLimit        OrderType = "LIMIT"
	OrderTypeStop         OrderType = "STOP"
	OrderTypeTrailingStop OrderType = "TRAILING_STOP"
	OrderTypeTakingProfit OrderType = "TAKE_PROFIT"
)

func GetOrderType

func GetOrderType(input string) (OrderType, error)

func (OrderType) MarshalJSON

func (ot OrderType) MarshalJSON() ([]byte, error)

func (*OrderType) UnmarshalJSON

func (ot *OrderType) UnmarshalJSON(input []byte) error

type OrderbookChannelResponseContents

type OrderbookChannelResponseContents = OrderbookResponse

type OrderbookOrder

type OrderbookOrder struct {
	Price  *Decimal `json:"price"`
	Size   *Decimal `json:"size"`
	Offset *int64   `json:"offset,omitempty"`

	PriceString string `json:"-"`
}

OrderbookOrder is an entry on the order book, it only contains price, quantity, and potentially an offset.

func (*OrderbookOrder) IsOtherNewerOffset

func (o *OrderbookOrder) IsOtherNewerOffset(other *OrderbookOrder) bool

func (*OrderbookOrder) UnmarshalJSON

func (p *OrderbookOrder) UnmarshalJSON(data []byte) error

UnmarshalJSON parse the content into an orderbook order. Right now the process first tries to parse the data with []string, if that failed, parse it with map[string]string

type OrderbookProcessor

type OrderbookProcessor struct {
	Market string

	Bids
	Asks

	Data []*OrderbookChannelResponse
	// contains filtered or unexported fields
}

OrderbookProcessor maintains the state of the order book

For now the bids and asks are maintained as a heap and it is easy to return top of the book. There doesn't look to be a difficult way to implement this as list as always sorted.

func NewOrderbookProcessor

func NewOrderbookProcessor(market string, dropData bool) *OrderbookProcessor

NewOrderbookProcessor creates a orderbook processor. - set `dropData` to true to drop the updates.

func (*OrderbookProcessor) BookTop

BookTop returns the best bid and ask of the book. nil if the side of the book is empty.

func (*OrderbookProcessor) Process

func (ob *OrderbookProcessor) Process(resp *OrderbookChannelResponse)

Process a update from the orderbook

type OrderbookResponse

type OrderbookResponse struct {
	Offset *int64            `json:"offset,string,omitempty"`
	Bids   []*OrderbookOrder `json:"bids"`
	Asks   []*OrderbookOrder `json:"asks"`
}

OrderbookResponse is from https://docs.dydx.exchange/?json#get-orderbook

type OrdersResponse

type OrdersResponse struct {
	Orders []Order `json:"orders"`
}

type Position

type Position struct {
	Market        string     `json:"market,omitempty"`
	Status        string     `json:"status,omitempty"`
	Side          string     `json:"side,omitempty"`
	Size          Decimal    `json:"size,omitempty"`
	MaxSize       Decimal    `json:"maxSize,omitempty"`
	EntryPrice    Decimal    `json:"entryPrice,omitempty"`
	ExitPrice     *Decimal   `json:"exitPrice,omitempty"`
	UnrealizedPnl Decimal    `json:"unrealizedPnl,omitempty"`
	RealizedPnl   Decimal    `json:"realizedPnl,omitempty"`
	CreatedAt     time.Time  `json:"createdAt,omitempty"`
	ClosedAt      *time.Time `json:"closedAt,omitempty"`
	NetFunding    Decimal    `json:"netFunding,omitempty"`
	SumOpen       Decimal    `json:"sumOpen,omitempty"`
	SumClose      Decimal    `json:"sumClose,omitempty"`
}

type PositionParams

type PositionParams struct {
	Market            string    `url:"market,omitempty"`
	Status            string    `url:"status,omitempty"`
	Limit             int       `url:"limit,omitempty"`
	CreatedBeforeOrAt time.Time `url:"createdBeforeOrAt,omitempty"`
}

type PositionResponse

type PositionResponse struct {
	Positions []Position `json:"positions"`
}

type QueryActiveOrdersParam

type QueryActiveOrdersParam struct {
	Market string    `url:"market,omitempty"`
	Side   OrderSide `url:"side,omitempty"`
	Id     string    `url:"id,omitempty"`
}

type RequestTestnetTokensResponse

type RequestTestnetTokensResponse struct {
	*Transfer `json:"transfer,omitempty"`
}

type SignTypedData

type SignTypedData interface {
	EthSignTypedData(typedData apitypes.TypedData) ([]byte, error)
}

SignTypedData is an interface to sign apitypes.TypedData on ethereum network. For a reference implementation, see: https://pkg.go.dev/github.com/ethereum/go-ethereum@v1.10.18/signer/core#SignerAPI.SignTypedData

type StarkKey

type StarkKey struct {
	PublicKey            string `json:"publicKey"`
	PublicKeyYCoordinate string `json:"publicKeyYCoordinate"`
	PrivateKey           string `json:"privateKey"`
}

StarkKey is the private key on the Stark L2. Below fields are from the browser cache but unused. - WalletAddress string `json:"walletAddress"` - LegacySigning bool `json:"legacySigning"` - WalletType string `json:"walletType"`

func DeriveStarkKey

func DeriveStarkKey(signer SignTypedData, isMainnet bool) (*StarkKey, error)

DeriveStarkKey gets the default deterministic stark key.

Derived from the python implementation of official dydx client: https://github.com/dydxprotocol/dydx-v3-python/blob/914fc66e542d82080702e03f6ad078ca2901bb46/dydx3/modules/onboarding.py#L116-L145

- sign the typed data for key derivation.

- append 0 to the signature.

- crypto.keccak hash the signature bytes. in python implementation, it convert the siganture to a big int. and the resulting big int is crypto.keccak hashed as an uint256 - note uint256 is 32 bytes. however, in reality, it takes the whole 66 bytes and hashes it.

- convert the resulted signature bytes into a big int.

- right shift the big int by 5 - this is our private key.

- `starkex.PrivateKeyToEcPointOnStarkCurv` to get the x and y big ints.

- convert private key, x, y into hex encoded strings (without the 0x).

Function requires a signer to sign typed data

Example
package main

import (
	"fmt"
	"log"

	"github.com/ethereum/go-ethereum/crypto"
	"github.com/fardream/go-dydx"
)

var _ = "keep"

func main() {
	key, err := crypto.GenerateKey()
	if err != nil {
		log.Fatalf("failed to generate an ethereum key: %#v", err)
	}

	stark_key, err := dydx.DeriveStarkKey(dydx.NewEcdsaPrivateKeySigner(key), false)
	if err != nil {
		log.Fatalf("failed to derivate stark key: %#v", err)
	}

	fmt.Println(stark_key)
}
Output:

func NewStarkKey

func NewStarkKey(publicKey, publicKeyYCoordinate, privateKey string) *StarkKey

func (*StarkKey) Set

func (c *StarkKey) Set(filename string) error

Set reads in the file, for cobra cli

func (*StarkKey) String

func (c *StarkKey) String() string

String prints out the key, for cobra cli

func (*StarkKey) Type

func (c *StarkKey) Type() string

Type is for cobra cli

type TimeInForce

type TimeInForce string
const (
	TimeInForceGtt TimeInForce = "GTT" // Good til time
	TimeInForceFok TimeInForce = "FOK" // Fill or Kill
	TimeInForceIoc TimeInForce = "IOC" // Immediate or Cancel
)

func GetTimeInForce

func GetTimeInForce(input string) (TimeInForce, error)

func (TimeInForce) MarshalJSON

func (ot TimeInForce) MarshalJSON() ([]byte, error)

func (*TimeInForce) UnmarshalJSON

func (ot *TimeInForce) UnmarshalJSON(input []byte) error

type Trade

type Trade struct {
	Side      string    `json:"side"`
	Size      Decimal   `json:"size"`
	Price     Decimal   `json:"price"`
	CreatedAt time.Time `json:"createdAt"`
}

type TradesChannelResponseContents

type TradesChannelResponseContents = TradesResponse

type TradesParam

type TradesParam struct {
	MarketID           string `url:"-"`
	Limit              int    `url:"limit,omitempty"`
	StartingBeforeOrAt string `url:"startingBeforeOrAt,omitempty"`
}

type TradesResponse

type TradesResponse struct {
	Trades []Trade `json:"trades"`
}

https://docs.dydx.exchange/?json#get-trades

type TradingReward

type TradingReward struct {
	Epoch      int       `json:"epoch"`
	EpochStart time.Time `json:"epochStart"`
	EpochEnd   time.Time `json:"epochEnd"`
	Fees       struct {
		FeesPaid      string `json:"feesPaid"`
		TotalFeesPaid string `json:"totalFeesPaid"`
	} `json:"fees"`
	OpenInterest struct {
		AverageOpenInterest      string `json:"averageOpenInterest"`
		TotalAverageOpenInterest string `json:"totalAverageOpenInterest"`
	} `json:"openInterest"`
	StakedDYDX struct {
		AverageStakedDYDX          string `json:"averageStakedDYDX"`
		AverageStakedDYDXWithFloor string `json:"averageStakedDYDXWithFloor"`
		TotalAverageStakedDYDX     string `json:"totalAverageStakedDYDX"`
	} `json:"stakedDYDX"`
	Weight struct {
		Weight      string `json:"weight"`
		TotalWeight string `json:"totalWeight"`
	} `json:"weight"`
	TotalRewards     string `json:"totalRewards"`
	EstimatedRewards string `json:"estimatedRewards"`
}

type TradingRewardsResponse

type TradingRewardsResponse TradingReward

type Transfer

type Transfer struct {
	Type            string     `json:"type"`
	ID              string     `json:"id"`
	ClientID        string     `json:"clientId"`
	CreditAmount    *Decimal   `json:"creditAmount,omitempty"`
	CreditAsset     string     `json:"creditAsset,omitempty"`
	DebitAmount     *Decimal   `json:"debitAmount,omitempty"`
	DebitAsset      string     `json:"debitAsset,omitempty"`
	FromAddress     string     `json:"fromAddress"`
	Status          string     `json:"status"`
	ToAddress       string     `json:"toAddress,omitempty"`
	TransactionHash string     `json:"transactionHash,omitempty"`
	ConfirmedAt     *time.Time `json:"confirmedAt,omitempty"`
	CreatedAt       time.Time  `json:"createdAt"`
}

type TransfersParam

type TransfersParam struct{}

type TransfersResponse

type TransfersResponse struct {
	Transfers []Transfer `json:"transfers"`
}

type User

type User struct {
	PublicID        string `json:"publicId"`
	EthereumAddress string `json:"ethereumAddress"`
	IsRegistered    bool   `json:"isRegistered"`
	Email           string `json:"email"`
	Username        string `json:"username"`
	UserData        struct {
		WalletType  string `json:"walletType"`
		Preferences struct {
			SaveOrderAmount  bool `json:"saveOrderAmount"`
			UserTradeOptions struct {
				Limit struct {
					PostOnlyChecked           bool   `json:"postOnlyChecked"`
					GoodTilTimeInput          string `json:"goodTilTimeInput"`
					GoodTilTimeTimescale      string `json:"goodTilTimeTimescale"`
					SelectedTimeInForceOption string `json:"selectedTimeInForceOption"`
				} `json:"LIMIT"`
				Market struct {
					PostOnlyChecked           bool   `json:"postOnlyChecked"`
					GoodTilTimeInput          string `json:"goodTilTimeInput"`
					GoodTilTimeTimescale      string `json:"goodTilTimeTimescale"`
					SelectedTimeInForceOption string `json:"selectedTimeInForceOption"`
				} `json:"MARKET"`
				StopLimit struct {
					PostOnlyChecked           bool   `json:"postOnlyChecked"`
					GoodTilTimeInput          string `json:"goodTilTimeInput"`
					GoodTilTimeTimescale      string `json:"goodTilTimeTimescale"`
					SelectedTimeInForceOption string `json:"selectedTimeInForceOption"`
				} `json:"STOP_LIMIT"`
				TakeProfit struct {
					PostOnlyChecked           bool   `json:"postOnlyChecked"`
					GoodTilTimeInput          string `json:"goodTilTimeInput"`
					GoodTilTimeTimescale      string `json:"goodTilTimeTimescale"`
					SelectedTimeInForceOption string `json:"selectedTimeInForceOption"`
				} `json:"TAKE_PROFIT"`
				LastPlacedTradeType string `json:"lastPlacedTradeType"`
			} `json:"userTradeOptions"`
			PopUpNotifications      bool      `json:"popUpNotifications"`
			OrderbookAnimations     bool      `json:"orderbookAnimations"`
			OneTimeNotifications    []string  `json:"oneTimeNotifications"`
			LeaguesCurrentStartDate time.Time `json:"leaguesCurrentStartDate"`
		} `json:"preferences"`
		Notifications struct {
			Trade struct {
				Email bool `json:"email"`
			} `json:"trade"`
			Deposit struct {
				Email bool `json:"email"`
			} `json:"deposit"`
			Transfer struct {
				Email bool `json:"email"`
			} `json:"transfer"`
			Marketing struct {
				Email bool `json:"email"`
			} `json:"marketing"`
			Withdrawal struct {
				Email bool `json:"email"`
			} `json:"withdrawal"`
			Liquidation struct {
				Email bool `json:"email"`
			} `json:"liquidation"`
			FundingPayment struct {
				Email bool `json:"email"`
			} `json:"funding_payment"`
		} `json:"notifications"`
		StarredMarkets []interface{} `json:"starredMarkets"`
	} `json:"userData"`
	MakerFeeRate                 string `json:"makerFeeRate"`
	TakerFeeRate                 string `json:"takerFeeRate"`
	MakerVolume30D               string `json:"makerVolume30D"`
	TakerVolume30D               string `json:"takerVolume30D"`
	Fees30D                      string `json:"fees30D"`
	ReferredByAffiliateLink      string `json:"referredByAffiliateLink"`
	IsSharingUsername            bool   `json:"isSharingUsername"`
	IsSharingAddress             bool   `json:"isSharingAddress"`
	DydxTokenBalance             string `json:"dydxTokenBalance"`
	StakedDydxTokenBalance       string `json:"stakedDydxTokenBalance"`
	ActiveStakedDydxTokenBalance string `json:"activeStakedDydxTokenBalance"`
	IsEmailVerified              bool   `json:"isEmailVerified"`
	Country                      any    `json:"country"`
	HedgiesHeld                  []any  `json:"hedgiesHeld"`
}

type UsersResponse

type UsersResponse struct {
	User User `json:"user"`
}

type WithdrawResponse

type WithdrawResponse struct {
	Withdrawal []Withdrawal `json:"withdrawal"`
}

type Withdrawal

type Withdrawal = Transfer

Withdrawal is one type of transfer: https://docs.dydx.exchange/#create-withdrawal

Directories

Path Synopsis
dydx-cli is a command line interface for dydx.exchange
dydx-cli is a command line interface for dydx.exchange
dydx-replay-orderbook is a cli to replay orderbook updates from dydx websocket subscription.
dydx-replay-orderbook is a cli to replay orderbook updates from dydx websocket subscription.
Package heap provides heap operations for any type that implements heap.Interface.
Package heap provides heap operations for any type that implements heap.Interface.
starkex provides signing and other algorithms for starkex (https://starkware.co/starkex/).
starkex provides signing and other algorithms for starkex (https://starkware.co/starkex/).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL