price pipeline
Signed-off-by: GnomeZworc <nicolas.boufidjeline@g3e.fr>
This commit is contained in:
parent
d7ec1fb355
commit
d9581d7f7e
16 changed files with 790 additions and 10 deletions
88
internal/pipeline/coingecko.go
Normal file
88
internal/pipeline/coingecko.go
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
package pipeline
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ResolveCryptoID résout un ticker crypto (ex: "BTC") en ID CoinGecko (ex: "bitcoin").
|
||||
func ResolveCryptoID(ctx context.Context, apiKey, ticker string) (string, error) {
|
||||
url := fmt.Sprintf("https://api.coingecko.com/api/v3/search?query=%s", ticker)
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if apiKey != "" {
|
||||
req.Header.Set("x-cg-pro-api-key", apiKey)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
var result struct {
|
||||
Coins []struct {
|
||||
ID string `json:"id"`
|
||||
Symbol string `json:"symbol"`
|
||||
} `json:"coins"`
|
||||
}
|
||||
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
||||
return "", fmt.Errorf("decode coingecko search: %w", err)
|
||||
}
|
||||
|
||||
// Le premier résultat dont le symbol correspond exactement est le bon
|
||||
upper := strings.ToUpper(ticker)
|
||||
for _, coin := range result.Coins {
|
||||
if strings.ToUpper(coin.Symbol) == upper {
|
||||
return coin.ID, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no coingecko match for ticker %s", ticker)
|
||||
}
|
||||
|
||||
// FetchCoinGeckoPrices récupère les prix EUR pour une liste d'IDs CoinGecko.
|
||||
// Le ticker stocké dans instrument_ticker_cache doit être l'ID CoinGecko (ex: "bitcoin", "ethereum").
|
||||
func FetchCoinGeckoPrices(ctx context.Context, apiKey string, coinIDs []string) (map[string]float64, error) {
|
||||
if len(coinIDs) == 0 {
|
||||
return map[string]float64{}, nil
|
||||
}
|
||||
|
||||
baseURL := "https://api.coingecko.com/api/v3/simple/price"
|
||||
if apiKey != "" {
|
||||
baseURL = "https://pro-api.coingecko.com/api/v3/simple/price"
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("%s?ids=%s&vs_currencies=eur", baseURL, strings.Join(coinIDs, ","))
|
||||
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if apiKey != "" {
|
||||
req.Header.Set("x-cg-pro-api-key", apiKey)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
// Réponse : {"bitcoin": {"eur": 45000.0}, "ethereum": {"eur": 2500.0}}
|
||||
var raw map[string]map[string]float64
|
||||
if err := json.NewDecoder(resp.Body).Decode(&raw); err != nil {
|
||||
return nil, fmt.Errorf("decode coingecko response: %w", err)
|
||||
}
|
||||
|
||||
prices := make(map[string]float64, len(raw))
|
||||
for id, currencies := range raw {
|
||||
prices[id] = currencies["eur"]
|
||||
}
|
||||
return prices, nil
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue