github.com/diadata-org/diadata@v1.4.593/pkg/dia/ApiClient.go (about)

     1  package dia
     2  
     3  import (
     4  	"bytes"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net/http"
     9  	"os/user"
    10  	"time"
    11  
    12  	"github.com/diadata-org/diadata/pkg/utils"
    13  	log "github.com/sirupsen/logrus"
    14  	"github.com/tkanos/gonfig"
    15  )
    16  
    17  type Client struct {
    18  	config                *ConfigApi
    19  	token                 string
    20  	lastSupplyUpdateTime  time.Time
    21  	lastSupplyUpdateValue float64
    22  	url                   string
    23  }
    24  
    25  type Symbols struct {
    26  	Symbols []string
    27  }
    28  
    29  const BaseUrl string = "https://api.diadata.org/"
    30  
    31  type response struct {
    32  	Token string
    33  }
    34  
    35  func (c *Client) refresh() error {
    36  
    37  	url := c.url + "auth/refresh_token"
    38  
    39  	req, err := http.NewRequest("GET", url, nil) //nolint:noctx
    40  	if err != nil {
    41  		return err
    42  	}
    43  
    44  	bytes, err := c.DoRequest(req, false)
    45  	if err != nil {
    46  		return err
    47  	}
    48  	var r response
    49  	err = json.Unmarshal(bytes, &r)
    50  	if err != nil {
    51  		fmt.Println("error:", err)
    52  		return err
    53  	}
    54  	c.token = r.Token
    55  	return nil
    56  }
    57  
    58  func (c *Client) login() error {
    59  
    60  	client := &http.Client{}
    61  
    62  	type login struct {
    63  		Username string
    64  		Password string
    65  	}
    66  	url := c.url + "login"
    67  
    68  	jsonStr, err := json.Marshal(&login{
    69  		Username: c.config.ApiKey,
    70  		Password: c.config.SecretKey,
    71  	})
    72  
    73  	if err != nil {
    74  		log.Println(err)
    75  		return err
    76  	}
    77  
    78  	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr)) //nolint:noctx
    79  	if err != nil {
    80  		return err
    81  	}
    82  
    83  	req.Header.Set("Content-Type", "application/json")
    84  
    85  	resp, err := client.Do(req)
    86  	if err != nil {
    87  		log.Println(err)
    88  		return err
    89  	}
    90  	defer func() {
    91  		err = resp.Body.Close()
    92  		if err != nil {
    93  			log.Error(err)
    94  		}
    95  	}()
    96  
    97  	body, _ := ioutil.ReadAll(resp.Body)
    98  
    99  	var r response
   100  	err = json.Unmarshal(body, &r)
   101  	if err != nil {
   102  		log.Println(err)
   103  		return err
   104  	}
   105  
   106  	c.token = r.Token
   107  
   108  	return nil
   109  }
   110  
   111  func GetSupply(symbol string) (*Supply, error) {
   112  	url := BaseUrl + "/v1/supply/" + symbol
   113  	log.Println("Checking supply for", symbol, "on", url)
   114  
   115  	contents, _, err := utils.GetRequest(url)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	log.Debugf("%s\n", string(contents))
   121  	var b Supply
   122  	err = b.UnmarshalBinary(contents)
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	log.Debug("got", b)
   128  	return &b, nil
   129  
   130  }
   131  
   132  // TODO remove URL
   133  func GetSymbolsList(url string) ([]string, error) {
   134  	log.Println("getSymbolList")
   135  
   136  	contents, _, err := utils.GetRequest(url + "/v1/symbols")
   137  	if err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	log.Debugf("%s\n", string(contents))
   142  	var b Symbols
   143  
   144  	err = json.Unmarshal(contents, &b)
   145  
   146  	if err != nil {
   147  		return nil, err
   148  	}
   149  
   150  	return b.Symbols, nil
   151  }
   152  
   153  func GetConfigApi() *ConfigApi {
   154  	var c ConfigApi
   155  	if utils.Getenv("USE_ENV","false") == "true" {
   156  		c = ConfigApi{
   157  			ApiKey:    utils.Getenv("DIADATA_API_KEY", ""),
   158  			SecretKey: utils.Getenv("DIADATA_SECRET_KEY", ""),
   159  		}
   160  	} else {
   161  		configFile := "/run/secrets/api_diadata"
   162  		err := gonfig.GetConf(configFile, &c)
   163  		if err != nil {
   164  			log.Errorln("GetConfigApi", err)
   165  			usr, _ := user.Current()
   166  			dir := usr.HomeDir
   167  			configFile = dir + "/secrets/api_diadata.json"
   168  			err = gonfig.GetConf(configFile, &c)
   169  		}
   170  		if err != nil {
   171  			log.Println(err)
   172  			return nil
   173  		} else {
   174  			log.Println("Loaded secret in", configFile)
   175  		}
   176  	}
   177  	return &c
   178  }
   179  
   180  func NewClientWithUrl(config *ConfigApi, url string) *Client {
   181  	c := &Client{
   182  		config: config,
   183  		token:  "",
   184  		url:    url,
   185  	}
   186  	err := c.login()
   187  	if err != nil {
   188  		log.Println(err)
   189  		return nil
   190  	}
   191  	return c
   192  }
   193  
   194  func NewClient(config *ConfigApi) *Client {
   195  	c := &Client{
   196  		config: config,
   197  		token:  "",
   198  		url:    BaseUrl,
   199  	}
   200  	err := c.login()
   201  	if err != nil {
   202  		log.Println(err)
   203  		return nil
   204  	}
   205  	return c
   206  }
   207  
   208  func (c *Client) DoRequest(req *http.Request, refresh bool) ([]byte, error) {
   209  
   210  	req.Header.Set("Content-Type", "application/json")
   211  	req.Header.Set("Authorization", "Bearer "+c.token)
   212  
   213  	client := &http.Client{}
   214  	resp, err := client.Do(req)
   215  	if err != nil {
   216  		return nil, err
   217  	}
   218  	defer func() {
   219  		err = resp.Body.Close()
   220  		if err != nil {
   221  			log.Error(err)
   222  		}
   223  	}()
   224  
   225  	body, err := ioutil.ReadAll(resp.Body)
   226  	if err != nil {
   227  		return nil, err
   228  	}
   229  
   230  	log.Debug("StatusCode", resp.StatusCode)
   231  
   232  	if resp.StatusCode != 200 {
   233  
   234  		if refresh {
   235  			if resp.StatusCode == 401 {
   236  				err = c.refresh()
   237  				if err != nil {
   238  					err = c.login()
   239  					if err == nil {
   240  						return c.DoRequest(req, true)
   241  					}
   242  				}
   243  			}
   244  		}
   245  		return nil, fmt.Errorf("%s", body)
   246  	}
   247  	return body, nil
   248  }
   249  
   250  func (c *Client) SendSupplyWithForceOption(s *Supply, force bool) error {
   251  	lastUpdate := time.Since(c.lastSupplyUpdateTime)
   252  	if lastUpdate.Hours() >= 1.0 || c.lastSupplyUpdateValue != s.CirculatingSupply || force {
   253  		c.lastSupplyUpdateTime = s.Time
   254  		c.lastSupplyUpdateValue = s.CirculatingSupply
   255  		return c.sendSupply(s)
   256  	} else {
   257  		log.Println("Skipping sending to API", s, "last update:", lastUpdate)
   258  		return nil
   259  	}
   260  }
   261  
   262  func (c *Client) SendSupply(s *Supply) error {
   263  	return c.SendSupplyWithForceOption(s, false)
   264  }
   265  
   266  func (c *Client) sendSupply(s *Supply) error {
   267  
   268  	jsonStr, err := json.Marshal(s)
   269  	if err != nil {
   270  		return err
   271  	}
   272  
   273  	url := c.url + "v1/supply"
   274  
   275  	req, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr)) //nolint:noctx
   276  	if err != nil {
   277  		return err
   278  	}
   279  
   280  	_, err = c.DoRequest(req, true)
   281  	if err != nil {
   282  		log.Println("Error: SendSupply", err)
   283  		return err
   284  	}
   285  
   286  	return nil
   287  }