moonmath/coindesk/model.go

113 lines
2.8 KiB
Go

package coindesk
import (
"encoding/json"
"strconv"
"strings"
"time"
)
// Asset is a cryptocurrency, like Bitcoin, Ethereum, etc.
type Asset string
const (
// BTC is the Bitcoin asset.
BTC Asset = "BTC"
// ETH is the Ethereum asset.
ETH Asset = "ETH"
)
// Response represents the general top-level format of Coindesk API responses.
type Response[T any] struct {
StatusCode int `json:"statusCode"`
Message string `json:"message"`
Data T `json:"data"`
}
// PriceValues contains a series of timestamped prices for a particular asset.
type PriceValues struct {
ISO Asset `json:"iso"`
Name string `json:"name"`
Slug string `json:"slug"`
IngestionStart Date `json:"ingestionStart"`
Entries []TimestampPrice `json:"entries"`
}
// AssetTickers is a map from an asset to its ticker data.
type AssetTickers map[Asset]AssetTicker
// AssetTicker is a snapshot of pricing data for an asset.
type AssetTicker struct {
ISO Asset `json:"iso"`
Name string `json:"name"`
Slug string `json:"slug"`
Change struct {
Percent float64 `json:"percent"`
Value float64 `json:"value"`
} `json:"change"`
OHLC struct {
Opening Price `json:"o"`
High Price `json:"h"`
Low Price `json:"l"`
Closing Price `json:"c"`
} `json:"ohlc"`
CirculatingSupply float64 `json:"circulatingSupply"`
MarketCap Price `json:"marketCap"`
Timestamp Timestamp `json:"ts"`
}
// TimestampPrice represents a JSON array with two elements: an integer Unix
// timestamp expressed in milliseconds, and a floating-point USD price.
type TimestampPrice struct {
Timestamp Timestamp
Price Price
}
func (t *TimestampPrice) UnmarshalJSON(b []byte) error {
a := []interface{}{&t.Timestamp, &t.Price}
return json.Unmarshal(b, &a)
}
// Timestamp represents an integer Unix timestamp expressed in milliseconds
// which has been converted into a Golang time.Time object.
type Timestamp time.Time
func (t *Timestamp) UnmarshalJSON(b []byte) error {
s := string(b)
n := len(s)
secsStr := s[0 : n-3]
millisStr := s[n-3:]
secs, err := strconv.ParseInt(secsStr, 10, 64)
if err != nil {
return err
}
millis, err := strconv.ParseInt(millisStr, 10, 64)
if err != nil {
return err
}
converted := time.Unix(secs, millis*1e6)
*t = Timestamp(converted)
return nil
}
// Price represents the USD price of an asset.
type Price float64
// Date represents a date-only string which has been converted into a Golang
// time.Time object.
type Date time.Time
func (d *Date) UnmarshalJSON(b []byte) error {
s := string(b)
s, _ = strings.CutPrefix(s, "\"")
s, _ = strings.CutSuffix(s, "\"")
t, err := time.Parse(time.DateOnly, s)
if err != nil {
return err
}
*d = Date(t)
return nil
}