coinbasepro

package module
v1.0.1 Latest Latest
Warning

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

Go to latest
Published: Dec 30, 2021 License: MIT Imports: 16 Imported by: 0

README

Go Coinbase Pro GoDoc Build Status

Summary

Go client for Coinbase Pro formerly known as gdax

Installation

If using Go modules (Go version >= 11.1) simply import as needed.

go mod init github.com/yourusername/yourprojectname
Older Go versions
go get github.com/moonr-app/go-coinbasepro
Significant releases

Use dep to install previous releases

dep ensure --add github.com/moonr-app/go-gdax@0.5.7
  • 0.5.7, last release before rename package to: coinbasepro
  • 0.5, as of 0.5 this library uses strings and is not backwards compatible

Documentation

For full details on functionality, see GoDoc documentation.

Setup

Client will respect environment variables: COINBASE_PRO_BASEURL, COINBASE_PRO_PASSPHRASE, COINBASE_PRO_KEY, COINBASE_PRO_SECRET by default

import (
  coinbasepro "github.com/moonr-app/go-coinbasepro"
)

client, err := coinbasepro.NewClient(
    "coinbase pro key",
    "coinbase pro passphrase",
    "coinbase pro secret",
)
if err != nil {
    // handle error
}

// optional configuration can be provided using function options:
client, err := coinbasepro.NewClient(
    "coinbase pro key",
    "coinbase pro passphrase",
    "coinbase pro secret",
    coinbasepro.WithSandboxEnvironment(),
    coinbasepro.WithHTTPClient(&http.Client{}),
    coinbasepro.WithRetryCount(5),
    coinbasepro.WithRetryInterval(time.Second),
    coinbasepro.WithTimeOffsetSeconds(30),
)
if err != nil {
    // handle error
}
Sandbox

You can switch to the sandbox env by using the following functional option (will default to production if not provided):

coinbasepro.WithSandboxEnvironment()
HTTP Settings

You can use a custom http client by using the following functional option:

coinbasepro.WithHTTPClient(&http.Client{}),
Decimals

To manage precision correctly, this library sends all price values as strings. It is recommended to use a decimal library like Spring's Decimal if you are doing any manipulation of prices.

Example:

import (
  "github.com/shopspring/decimal"
)

book, err := client.GetBook("BTC-USD", 1)
if err != nil {
    println(err.Error())  
}

lastPrice, err := decimal.NewFromString(book.Bids[0].Price)
if err != nil {
    println(err.Error())  
}

order := coinbasepro.Order{
  Price: lastPrice.Add(decimal.NewFromFloat(1.00)).String(),
  Size: "2.00",
  Side: "buy",
  ProductID: "BTC-USD",
}

savedOrder, err := client.CreateOrder(&order)
if err != nil {
  println(err.Error())
}

println(savedOrder.ID)
Retry

You can set a retry count & interval which uses exponential backoff using functional options:

(2^(retry_attempt) - 1) / 2 * retryInterval

coinbasepro.WithRetryCount(3),
coinbasepro.WithRetryInterval(500 * time.Millisecond),

// retry count = 3: 500ms, 1500ms, 3500ms
Cursor

This library uses a cursor pattern so you don't have to keep track of pagination.

var orders []coinbasepro.Order
cursor = client.ListOrders()

for cursor.HasMore {
  if err := cursor.NextPage(ctx, &orders); err != nil {
    println(err.Error())
    return
  }

  for _, o := range orders {
    println(o.ID)
  }
}

Websockets

Listen for websocket messages

  client, err := coinbasepro.NewClient(
    "coinbase pro key", 
	"coinbase pro passphrase", 
	"coinbase pro secret",
  )
  if err != nil { 
    // handle error
  }

  subscribe := coinbasepro.Message{
    Type:      "subscribe",
    Channels: []coinbasepro.MessageChannel{
      coinbasepro.MessageChannel{
        Name: "heartbeat",
        ProductIds: []string{
          "BTC-USD",
        },
      },
      coinbasepro.MessageChannel{
        Name: "level2",
        ProductIds: []string{
          "BTC-USD",
        },
      },
    },
  }
  
  err := client.Subscribe(ctx, subscribe, func(msg coinbasepro.Message) error {
    println(message.Type)
    return nil
  })
Time

Results return coinbase time type which handles different types of time parsing that coinbasepro returns. This wraps the native go time type

  import(
    "time"
    coinbasepro "github.com/moonr-app/go-coinbasepro"
  )

  coinbaseTime := coinbasepro.Time{}
  println(time.Time(coinbaseTime).Day())
Examples

This library supports all public and private endpoints

Get Accounts:

  accounts, err := client.GetAccounts(ctx)
  if err != nil {
    println(err.Error())
  }

  for _, a := range accounts {
    println(a.Balance)
  }

List Account Ledger:

  var ledgers []coinbasepro.LedgerEntry

  accounts, err := client.GetAccounts(ctx)
  if err != nil {
    println(err.Error())
  }

  for _, a := range accounts {
    cursor := client.ListAccountLedger(a.ID)
    for cursor.HasMore {
      if err := cursor.NextPage(ctx, &ledgers); err != nil {
        println(err.Error())
      }

      for _, e := range ledgers {
        println(e.Amount)
      }
    }
  }

Create an Order:

  order := coinbasepro.Order{
    Price: "1.00",
    Size: "1.00",
    Side: "buy",
    ProductID: "BTC-USD",
  }

  savedOrder, err := client.CreateOrder(ctx, order)
  if err != nil {
    println(err.Error())
  }

  println(savedOrder.ID)

Transfer funds:

  transfer := coinbasepro.Transfer {
    Type: "deposit",
    Amount: "1.00",
  }

  savedTransfer, err := client.CreateTransfer(ctx, transfer)
  if err != nil {
    println(err.Error())
  }

Get Trade history:

  var trades []coinbasepro.Trade
  cursor := client.ListTrades("BTC-USD")

  for cursor.HasMore {
    if err := cursor.NextPage(ctx, &trades); err != nil {
      for _, t := range trades {
        println(trade.CoinbaseID)
      }
    }
  }
Testing

To test with Coinbase's public sandbox set the following environment variables:

export COINBASE_PRO_KEY="sandbox key"
export COINBASE_PRO_PASSPHRASE="sandbox passphrase"
export COINBASE_PRO_SECRET="sandbox secret"

Then run go test

go test

Note that your sandbox account will need at least 2,000 USD and 2 BTC to run the tests.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNotFound     = Error{Message: "Route not found"}
	ErrUnauthorized = Error{Message: "Unauthorized."}

	ErrCloseWebsocket = errors.New("close webscoket connection")
)

Functions

func NewAnonymousClient added in v1.0.1

func NewAnonymousClient(opts ...ClientOption) (*client, error)

NewAnonymousClient creates a new instance of client without any credentials which can be used for public endpoints.

func NewClient

func NewClient(key, passphrase, secret string, opts ...ClientOption) (*client, error)

NewClient creates a new instance of client with credentials which can be used for both public & private endpoints.

Types

type Account

type Account struct {
	ID        string `json:"id"`
	Balance   string `json:"balance"`
	Hold      string `json:"hold"`
	Available string `json:"available"`
	Currency  string `json:"currency"`
}

type Book

type Book struct {
	Sequence int64       `json:"sequence"`
	Bids     []BookEntry `json:"bids"`
	Asks     []BookEntry `json:"asks"`
}

type BookEntry

type BookEntry struct {
	Price          string
	Size           string
	NumberOfOrders int
	OrderID        string
}

func (*BookEntry) UnmarshalJSON

func (e *BookEntry) UnmarshalJSON(data []byte) error

type CancelAllOrdersParams

type CancelAllOrdersParams struct {
	ProductID string
}

type ClientOption added in v1.0.1

type ClientOption func(*client) error

func WithHTTPClient

func WithHTTPClient(httpClient *http.Client) ClientOption

func WithRetryCount

func WithRetryCount(retryCount int) ClientOption

func WithRetryInterval

func WithRetryInterval(retryInterval time.Duration) ClientOption

func WithSandboxEnvironment

func WithSandboxEnvironment() ClientOption

func WithTimeOffsetSeconds

func WithTimeOffsetSeconds(offset int) ClientOption

WithTimeOffsetSeconds can be used to generate timestamps with offset to current time. Coinbase Pro sandbox time has been off in the past.

type CreateReportParams

type CreateReportParams struct {
	Start time.Time
	End   time.Time
}

type Currency

type Currency struct {
	ID      string `json:"id"`
	Name    string `json:"name"`
	MinSize string `json:"min_size"`
}

type Cursor

type Cursor struct {
	HasMore bool
	// contains filtered or unexported fields
}

func (*Cursor) NextPage

func (c *Cursor) NextPage(ctx context.Context, i interface{}) error

func (*Cursor) PrevPage

func (c *Cursor) PrevPage(ctx context.Context, i interface{}) error

type Deposit

type Deposit struct {
	Currency string `json:"currency"`
	Amount   string `json:"amount"`
	// PaymentMethodID can be determined by calling GetPaymentMethods
	PaymentMethodID string `json:"payment_method_id"`
	// Response fields
	ID       string `json:"id,omitempty"`
	PayoutAt Time   `json:"payout_at,string,omitempty"`
}

type Error

type Error struct {
	Message string `json:"message"`
}

func (Error) Error

func (e Error) Error() string

type Fees

type Fees struct {
	MakerFeeRate string `json:"maker_fee_rate"`
	TakerFeeRate string `json:"taker_fee_rate"`
	USDVolume    string `json:"usd_volume"`
}

type Fill

type Fill struct {
	TradeID   int    `json:"trade_id,int"`
	ProductID string `json:"product_id"`
	Price     string `json:"price"`
	Size      string `json:"size"`
	FillID    string `json:"order_id"`
	CreatedAt Time   `json:"created_at,string"`
	Fee       string `json:"fee"`
	Settled   bool   `json:"settled"`
	Side      string `json:"side"`
	Liquidity string `json:"liquidity"`
}

type GetAccountLedgerParams

type GetAccountLedgerParams struct {
	Pagination PaginationParams
}

type GetHistoricRatesParams

type GetHistoricRatesParams struct {
	Start       time.Time
	End         time.Time
	Granularity int
}

type HistoricRate

type HistoricRate struct {
	Time   time.Time
	Low    float64
	High   float64
	Open   float64
	Close  float64
	Volume float64
}

func (*HistoricRate) UnmarshalJSON

func (e *HistoricRate) UnmarshalJSON(data []byte) error

type Hold

type Hold struct {
	AccountID string `json:"account_id"`
	CreatedAt Time   `json:"created_at,string"`
	UpdatedAt Time   `json:"updated_at,string"`
	Amount    string `json:"amount"`
	Type      string `json:"type"`
	Ref       string `json:"ref"`
}

type LedgerDetails

type LedgerDetails struct {
	OrderID   string `json:"order_id"`
	TradeID   string `json:"trade_id"`
	ProductID string `json:"product_id"`
}

type LedgerEntry

type LedgerEntry struct {
	ID        string        `json:"id,number"`
	CreatedAt Time          `json:"created_at,string"`
	Amount    string        `json:"amount"`
	Balance   string        `json:"balance"`
	Type      string        `json:"type"`
	Details   LedgerDetails `json:"details"`
}

type ListFillsParams

type ListFillsParams struct {
	OrderID    string
	ProductID  string
	Pagination PaginationParams
}

type ListHoldsParams

type ListHoldsParams struct {
	Pagination PaginationParams
}

type ListOrdersParams

type ListOrdersParams struct {
	Status     string
	ProductID  string
	Pagination PaginationParams
}

type ListTradesParams

type ListTradesParams struct {
	Pagination *PaginationParams
}

type Message

type Message struct {
	Type          string           `json:"type"`
	ProductID     string           `json:"product_id"`
	ProductIds    []string         `json:"product_ids"`
	Products      []Product        `json:"products"`
	Currencies    []Currency       `json:"currencies"`
	TradeID       int              `json:"trade_id,number"`
	OrderID       string           `json:"order_id"`
	ClientOID     string           `json:"client_oid"`
	Sequence      int64            `json:"sequence,number"`
	MakerOrderID  string           `json:"maker_order_id"`
	TakerOrderID  string           `json:"taker_order_id"`
	Time          Time             `json:"time,string"`
	RemainingSize string           `json:"remaining_size"`
	NewSize       string           `json:"new_size"`
	OldSize       string           `json:"old_size"`
	Size          string           `json:"size"`
	Price         string           `json:"price"`
	Side          string           `json:"side"`
	Reason        string           `json:"reason"`
	OrderType     string           `json:"order_type"`
	Funds         string           `json:"funds"`
	NewFunds      string           `json:"new_funds"`
	OldFunds      string           `json:"old_funds"`
	Message       string           `json:"message"`
	Bids          []SnapshotEntry  `json:"bids,omitempty"`
	Asks          []SnapshotEntry  `json:"asks,omitempty"`
	Changes       []SnapshotChange `json:"changes,omitempty"`
	LastSize      string           `json:"last_size"`
	BestBid       string           `json:"best_bid"`
	BestAsk       string           `json:"best_ask"`
	Channels      []MessageChannel `json:"channels"`
	UserID        string           `json:"user_id"`
	ProfileID     string           `json:"profile_id"`
	LastTradeID   int              `json:"last_trade_id"`
}

func (Message) Sign

func (m Message) Sign(secret, key, passphrase string) (SignedMessage, error)

type MessageChannel

type MessageChannel struct {
	Name       string   `json:"name"`
	ProductIds []string `json:"product_ids"`
}

type Order

type Order struct {
	Type      string `json:"type"`
	Size      string `json:"size,omitempty"`
	Side      string `json:"side"`
	ProductID string `json:"product_id"`
	ClientOID string `json:"client_oid,omitempty"`
	Stp       string `json:"stp,omitempty"`
	Stop      string `json:"stop,omitempty"`
	StopPrice string `json:"stop_price,omitempty"`
	// Limit Order
	Price       string `json:"price,omitempty"`
	TimeInForce string `json:"time_in_force,omitempty"`
	PostOnly    bool   `json:"post_only,omitempty"`
	CancelAfter string `json:"cancel_after,omitempty"`
	// Market Order
	Funds          string `json:"funds,omitempty"`
	SpecifiedFunds string `json:"specified_funds,omitempty"`
	// Response Fields
	ID            string `json:"id"`
	Status        string `json:"status,omitempty"`
	Settled       bool   `json:"settled,omitempty"`
	DoneReason    string `json:"done_reason,omitempty"`
	DoneAt        Time   `json:"done_at,string,omitempty"`
	CreatedAt     Time   `json:"created_at,string,omitempty"`
	FillFees      string `json:"fill_fees,omitempty"`
	FilledSize    string `json:"filled_size,omitempty"`
	ExecutedValue string `json:"executed_value,omitempty"`
}

type PaginationParams

type PaginationParams struct {
	Limit  int
	Before string
	After  string
	Extra  map[string]string
}

func (*PaginationParams) AddExtraParam

func (p *PaginationParams) AddExtraParam(key, value string)

func (*PaginationParams) Done

func (p *PaginationParams) Done(direction string) bool

func (*PaginationParams) Encode

func (p *PaginationParams) Encode(direction string) string

type PaymentMethod

type PaymentMethod struct {
	Currency string `json:"currency"`
	Type     string `json:"type"`
	ID       string `json:"id"`
}

type Product

type Product struct {
	ID              string `json:"id"`
	BaseCurrency    string `json:"base_currency"`
	QuoteCurrency   string `json:"quote_currency"`
	BaseMinSize     string `json:"base_min_size"`
	BaseMaxSize     string `json:"base_max_size"`
	QuoteIncrement  string `json:"quote_increment"`
	BaseIncrement   string `json:"base_increment"`
	DisplayName     string `json:"display_name"`
	MinMarketFunds  string `json:"min_market_funds"`
	MaxMarketFunds  string `json:"max_market_funds"`
	MarginEnabled   bool   `json:"margin_enabled"`
	PostOnly        bool   `json:"post_only"`
	LimitOnly       bool   `json:"limit_only"`
	CancelOnly      bool   `json:"cancel_only"`
	TradingDisabled bool   `json:"trading_disabled"`
	Status          string `json:"status"`
	StatusMessage   string `json:"status_message"`
}

type Profile

type Profile struct {
	ID        string `json:"id"`
	UserID    string `json:"user_id"`
	Name      string `json:"name"`
	Active    bool   `json:"active"`
	IsDefault bool   `json:"is_default"`
	CreatedAt Time   `json:"created_at,string"`
}

type ProfileTransfer

type ProfileTransfer struct {
	From     string `json:"from"`
	To       string `json:"to"`
	Currency string `json:"currency"`
	Amount   string `json:"amount"`
}

type Report

type Report struct {
	ID     string `json:"id"`
	Type   string `json:"type"`
	Status string `json:"status"`
	// ProductID is required for fills type reports.
	// Use 'ALL' to get all products.
	ProductID string `json:"product_id"`
	// AccountID is required for account type reports.
	AccountID   string       `json:"account_id"`
	CreatedAt   Time         `json:"created_at,string"`
	CompletedAt Time         `json:"completed_at,string,"`
	ExpiresAt   Time         `json:"expires_at,string"`
	FileURL     string       `json:"file_url"`
	Params      ReportParams `json:"params"`
	StartDate   time.Time
	EndDate     time.Time
}

type ReportParams

type ReportParams struct {
	StartDate time.Time
	EndDate   time.Time
}

type ServerTime

type ServerTime struct {
	ISO   string  `json:"iso"`
	Epoch float64 `json:"epoch,number"`
}

type SignedMessage

type SignedMessage struct {
	Message
	Key        string `json:"key"`
	Passphrase string `json:"passphrase"`
	Timestamp  string `json:"timestamp"`
	Signature  string `json:"signature"`
}

type SnapshotChange

type SnapshotChange struct {
	Side  string
	Price string
	Size  string
}

func (*SnapshotChange) UnmarshalJSON

func (e *SnapshotChange) UnmarshalJSON(data []byte) error

type SnapshotEntry

type SnapshotEntry struct {
	Price string
	Size  string
}

func (*SnapshotEntry) UnmarshalJSON

func (e *SnapshotEntry) UnmarshalJSON(data []byte) error

type Stats

type Stats struct {
	Low         string `json:"low"`
	High        string `json:"high"`
	Open        string `json:"open"`
	Volume      string `json:"volume"`
	Last        string `json:"last"`
	Volume30Day string `json:"volume_30day"`
}

type StringNumber

type StringNumber string

func (*StringNumber) UnmarshalJSON

func (s *StringNumber) UnmarshalJSON(data []byte) error

type Ticker

type Ticker struct {
	TradeID int          `json:"trade_id,number"`
	Price   string       `json:"price"`
	Size    string       `json:"size"`
	Time    Time         `json:"time,string"`
	Bid     string       `json:"bid"`
	Ask     string       `json:"ask"`
	Volume  StringNumber `json:"volume"`
}

type Time

type Time time.Time

func (Time) MarshalJSON

func (t Time) MarshalJSON() ([]byte, error)

MarshalJSON marshal time back to time.Time for json encoding

func (*Time) Scan

func (t *Time) Scan(value interface{}) error

Scan implements the sql.Scanner interface for database deserialization.

func (*Time) Time

func (t *Time) Time() time.Time

func (*Time) UnmarshalJSON

func (t *Time) UnmarshalJSON(data []byte) error

func (Time) Value

func (t Time) Value() (driver.Value, error)

Value implements the driver.Valuer interface for database serialization.

type Trade

type Trade struct {
	TradeID int    `json:"trade_id,number"`
	Price   string `json:"price"`
	Size    string `json:"size"`
	Time    Time   `json:"time,string"`
	Side    string `json:"side"`
}

type Transfer

type Transfer struct {
	Type              string `json:"type"`
	Amount            string `json:"amount"`
	CoinbaseAccountID string `json:"coinbase_account_id,string"`
}

type WithdrawalCoinbase

type WithdrawalCoinbase struct {
	Currency          string `json:"currency"`
	Amount            string `json:"amount"`
	CoinbaseAccountID string `json:"coinbase_account_id"`
}

type WithdrawalCrypto

type WithdrawalCrypto struct {
	Currency      string `json:"currency"`
	Amount        string `json:"amount"`
	CryptoAddress string `json:"crypto_address"`
}

type WithdrawalPaymentMethod

type WithdrawalPaymentMethod struct {
	ProfileID string `json:"profile_id"`
	Currency  string `json:"currency"`
	Amount    string `json:"amount"`
	// PaymentMethodID can be determined by calling GetPaymentMethods
	PaymentMethodID string `json:"payment_method_id"`
	// Response fields
	ID       string `json:"id,omitempty"`
	PayoutAt Time   `json:"payout_at,string,omitempty"`
	Fee      string `json:"fee,omitempty"`
	Subtotal string `json:"subtotal,omitempty"`
}

Jump to

Keyboard shortcuts

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