From 1ab38429bb801b01b5ceeb912204aa5f7f84a046 Mon Sep 17 00:00:00 2001 From: Options Vamp Date: Tue, 14 May 2024 22:51:29 -0400 Subject: [PATCH] Crypto and warrants added --- crypto.go | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ crypto_test.go | 55 +++++++++++++++++++++++++++++++ warrants.go | 75 ++++++++++++++++++++++++++++++++++++++++++ warrants_test.go | 55 +++++++++++++++++++++++++++++++ 4 files changed, 269 insertions(+) create mode 100644 crypto.go create mode 100644 crypto_test.go create mode 100644 warrants.go create mode 100644 warrants_test.go diff --git a/crypto.go b/crypto.go new file mode 100644 index 0000000..656c501 --- /dev/null +++ b/crypto.go @@ -0,0 +1,84 @@ +package tastytrade + +import ( + "encoding/json" + "fmt" +) + +type DestinationVenueSymbols struct { + Id int `json:"id"` + Symbol string `json:"symbol"` + DestinationVenue string `json:"destination-venue"` + MaxQuantityPrecision int `json:"max-quantity-precision"` + MaxPricePrecision int `json:"max-price-precision"` + Routable bool `json:"routable"` +} + +type Cryptocurrency struct { + Id int `json:"id"` + Symbol string `json:"symbol"` + InstrumentType string `json:"instrument-type"` + ShortDescription string `json:"short-description"` + Description string `json:"description"` + IsClosingOnly bool `json:"is-closing-only"` + Active bool `json:"active"` + TickSize string `json:"tick-size"` + StreamerSymbol string `json:"streamer-symbol"` + DestinationVenueSymbols []DestinationVenueSymbols `json:"destination-venue-symbols"` +} + +type ListCryptocurrenciesResult struct { + Data struct { + Items []Cryptocurrency `json:"items"` + } `json:"data"` + Context string `json:"context"` +} + +type GetCryptocurrencyResult struct { + Data Cryptocurrency `json:"data"` + Context string `json:"context"` +} + +// ListCryptocurrencies retrieves list of cryptocurrencies +func (api *TastytradeAPI) ListCryptocurrencies() (ListCryptocurrenciesResult, error) { + url := fmt.Sprintf("%s/instruments/cryptocurrencies", api.host) + data, err := api.fetchData(url) + if err != nil { + return ListCryptocurrenciesResult{}, err + } + + var response ListCryptocurrenciesResult + jsonData, err := json.Marshal(data) + if err != nil { + return ListCryptocurrenciesResult{}, err + } + + err = json.Unmarshal(jsonData, &response) + if err != nil { + return ListCryptocurrenciesResult{}, err + } + + return response, nil +} + +// GetCryptocurrency retrieves a specific cryptocurrency +func (api *TastytradeAPI) GetCryptocurrency(symbol string) (GetCryptocurrencyResult, error) { + url := fmt.Sprintf("%s/instruments/cryptocurrencies/%s", api.host, symbol) + data, err := api.fetchData(url) + if err != nil { + return GetCryptocurrencyResult{}, err + } + + var response GetCryptocurrencyResult + jsonData, err := json.Marshal(data) + if err != nil { + return GetCryptocurrencyResult{}, err + } + + err = json.Unmarshal(jsonData, &response) + if err != nil { + return GetCryptocurrencyResult{}, err + } + + return response, nil +} diff --git a/crypto_test.go b/crypto_test.go new file mode 100644 index 0000000..c7f6697 --- /dev/null +++ b/crypto_test.go @@ -0,0 +1,55 @@ +package tastytrade + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestListCryptocurrencies(t *testing.T) { + // Create a test server that returns a dummy response + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{"data": {"items": []}, "context": "/instruments/cryptocurrencies"}`)) + })) + defer ts.Close() + + // Create a new TastytradeAPI instance with the test server URL + api := NewTastytradeAPI(ts.URL) + + // Call the ListCryptocurrencies function + result, err := api.ListCryptocurrencies() + + // Check for errors + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + // Check the result + if result.Context != "/instruments/cryptocurrencies" { + t.Errorf("Expected context to be /instruments/cryptocurrencies, got %v", result.Context) + } +} + +func TestGetCryptocurrency(t *testing.T) { + // Create a test server that returns a dummy response + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{"data": {"symbol": "BTC/USD"}, "context": "/instruments/cryptocurrencies/BTC%2FUSD"}`)) + })) + defer ts.Close() + + // Create a new TastytradeAPI instance with the test server URL + api := NewTastytradeAPI(ts.URL) + + // Call the GetCryptocurrency function + result, err := api.GetCryptocurrency("BTC/USD") + + // Check for errors + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + // Check the result + if result.Data.Symbol != "BTC/USD" { + t.Errorf("Expected symbol to be BTC/USD, got %v", result.Data.Symbol) + } +} diff --git a/warrants.go b/warrants.go new file mode 100644 index 0000000..39c35f2 --- /dev/null +++ b/warrants.go @@ -0,0 +1,75 @@ +package tastytrade + +import ( + "encoding/json" + "fmt" + "strings" +) + +type Warrant struct { + Symbol string `json:"symbol"` + InstrumentType string `json:"instrument-type"` + ListedMarket string `json:"listed-market"` + Description string `json:"description"` + IsClosingOnly bool `json:"is-closing-only"` + Active bool `json:"active"` +} + +type ListWarrantsResult struct { + Data struct { + Items []Warrant `json:"items"` + } `json:"data"` + Context string `json:"context"` +} + +type GetWarrantResult struct { + Data Warrant `json:"data"` + Context string `json:"context"` +} + +// ListWarrants retrieves list of warrants +func (api *TastytradeAPI) ListWarrants(symbols ...string) (ListWarrantsResult, error) { + url := fmt.Sprintf("%s/instruments/warrants", api.host) + if len(symbols) > 0 { + url = fmt.Sprintf("%s?symbols=%s", url, strings.Join(symbols, ",")) + } + data, err := api.fetchData(url) + if err != nil { + return ListWarrantsResult{}, err + } + + var response ListWarrantsResult + jsonData, err := json.Marshal(data) + if err != nil { + return ListWarrantsResult{}, err + } + + err = json.Unmarshal(jsonData, &response) + if err != nil { + return ListWarrantsResult{}, err + } + + return response, nil +} + +// GetWarrant retrieves a specific warrant +func (api *TastytradeAPI) GetWarrant(symbol string) (GetWarrantResult, error) { + url := fmt.Sprintf("%s/instruments/warrants/%s", api.host, symbol) + data, err := api.fetchData(url) + if err != nil { + return GetWarrantResult{}, err + } + + var response GetWarrantResult + jsonData, err := json.Marshal(data) + if err != nil { + return GetWarrantResult{}, err + } + + err = json.Unmarshal(jsonData, &response) + if err != nil { + return GetWarrantResult{}, err + } + + return response, nil +} diff --git a/warrants_test.go b/warrants_test.go new file mode 100644 index 0000000..5d0aea1 --- /dev/null +++ b/warrants_test.go @@ -0,0 +1,55 @@ +package tastytrade + +import ( + "net/http" + "net/http/httptest" + "testing" +) + +func TestListWarrants(t *testing.T) { + // Create a test server that returns a dummy response + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{"data": {"items": []}, "context": "/instruments/warrants"}`)) + })) + defer ts.Close() + + // Create a new TastytradeAPI instance with the test server URL + api := NewTastytradeAPI(ts.URL) + + // Call the ListWarrants function + result, err := api.ListWarrants() + + // Check for errors + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + // Check the result + if result.Context != "/instruments/warrants" { + t.Errorf("Expected context to be /instruments/warrants, got %v", result.Context) + } +} + +func TestGetWarrant(t *testing.T) { + // Create a test server that returns a dummy response + ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Write([]byte(`{"data": {"symbol": "SEPAW"}, "context": "/instruments/warrants/SEPAW"}`)) + })) + defer ts.Close() + + // Create a new TastytradeAPI instance with the test server URL + api := NewTastytradeAPI(ts.URL) + + // Call the GetWarrant function + result, err := api.GetWarrant("SEPAW") + + // Check for errors + if err != nil { + t.Fatalf("Expected no error, got %v", err) + } + + // Check the result + if result.Data.Symbol != "SEPAW" { + t.Errorf("Expected symbol to be SEPAW, got %v", result.Data.Symbol) + } +}