package tastytrade import ( "bytes" "encoding/json" "fmt" "net/http" "time" ) type User struct { Email string `json:"email"` Username string `json:"username"` ExternalID string `json:"external-id"` IsConfirmed bool `json:"is-confirmed"` } type AuthData struct { User User `json:"user"` SessionToken string `json:"session-token"` SessionExpire time.Time `json:"session-expiration"` RememberToken string `json:"remember-token"` } type AuthResponse struct { Data AuthData `json:"data"` Context string `json:"context"` } // Authenticate authenticates the client with the Tastytrade API func (api *TastytradeAPI) Authenticate2(username, password string, remember bool) error { var remStr string if remember { remStr = "true" } else { remStr = "false" } authURL := fmt.Sprintf("%s/sessions", api.host) authData := map[string]string{ "login": username, "password": password, "remember-me": remStr, } authBody, err := json.Marshal(authData) if err != nil { return err } resp, err := api.httpClient.Post(authURL, "application/json", bytes.NewReader(authBody)) if err != nil { return err } defer func() { _ = resp.Body.Close() }() if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { return fmt.Errorf("authentication failed: status code %d", resp.StatusCode) } authResponse := AuthResponse{} if err := json.NewDecoder(resp.Body).Decode(&authResponse); err != nil { return err } api.authToken = authResponse.Data.SessionToken api.authExpire = authResponse.Data.SessionExpire if (remember) { api.remToken = authResponse.Data.RememberToken } return nil } func (api *TastytradeAPI) Authenticate(username, password string) error { return api.Authenticate2(username, password, false) } // Redeem a remember token to get a session func (api *TastytradeAPI) AuthRemember(remember bool) error { var remStr string if remember { remStr = "true" } else { remStr = "false" } authURL := fmt.Sprintf("%s/sessions", api.host) authData := map[string]string{ "login": api.user, "remember-token": api.remToken, "remember-me": remStr, } authBody, err := json.Marshal(authData) if err != nil { return err } resp, err := api.httpClient.Post(authURL, "application/json", bytes.NewReader(authBody)) if err != nil { return err } defer func() { _ = resp.Body.Close() }() if resp.StatusCode != http.StatusOK && resp.StatusCode != http.StatusCreated { return fmt.Errorf("authentication failed: status code %d", resp.StatusCode) } authResponse := AuthResponse{} if err := json.NewDecoder(resp.Body).Decode(&authResponse); err != nil { return err } api.authToken = authResponse.Data.SessionToken if (remember) { api.remToken = authResponse.Data.RememberToken } else { api.remToken = "" } return nil }