Give info about fiat rates in status page and API

This commit is contained in:
Martin Boehm 2022-09-10 12:16:25 +02:00 committed by Martin
parent f485de5e35
commit 91c4675a53
7 changed files with 112 additions and 47 deletions

View File

@ -431,24 +431,29 @@ type BlockRaw struct {
// BlockbookInfo contains information about the running blockbook instance
type BlockbookInfo struct {
Coin string `json:"coin"`
Host string `json:"host"`
Version string `json:"version"`
GitCommit string `json:"gitCommit"`
BuildTime string `json:"buildTime"`
SyncMode bool `json:"syncMode"`
InitialSync bool `json:"initialSync"`
InSync bool `json:"inSync"`
BestHeight uint32 `json:"bestHeight"`
LastBlockTime time.Time `json:"lastBlockTime"`
InSyncMempool bool `json:"inSyncMempool"`
LastMempoolTime time.Time `json:"lastMempoolTime"`
MempoolSize int `json:"mempoolSize"`
Decimals int `json:"decimals"`
DbSize int64 `json:"dbSize"`
DbSizeFromColumns int64 `json:"dbSizeFromColumns,omitempty"`
DbColumns []common.InternalStateColumn `json:"dbColumns,omitempty"`
About string `json:"about"`
Coin string `json:"coin"`
Host string `json:"host"`
Version string `json:"version"`
GitCommit string `json:"gitCommit"`
BuildTime string `json:"buildTime"`
SyncMode bool `json:"syncMode"`
InitialSync bool `json:"initialSync"`
InSync bool `json:"inSync"`
BestHeight uint32 `json:"bestHeight"`
LastBlockTime time.Time `json:"lastBlockTime"`
InSyncMempool bool `json:"inSyncMempool"`
LastMempoolTime time.Time `json:"lastMempoolTime"`
MempoolSize int `json:"mempoolSize"`
Decimals int `json:"decimals"`
DbSize int64 `json:"dbSize"`
HasFiatRates bool `json:"hasFiatRates,omitempty"`
HasTokenFiatRates bool `json:"hasTokenFiatRates,omitempty"`
CurrentFiatRatesTime *time.Time `json:"currentFiatRatesTime,omitempty"`
HistoricalFiatRatesTime *time.Time `json:"historicalFiatRatesTime,omitempty"`
HistoricalTokenFiatRatesTime *time.Time `json:"historicalTokenFiatRatesTime,omitempty"`
DbSizeFromColumns int64 `json:"dbSizeFromColumns,omitempty"`
DbColumns []common.InternalStateColumn `json:"dbColumns,omitempty"`
About string `json:"about"`
}
// SystemInfo contains information about the running blockbook and backend instance

View File

@ -134,9 +134,11 @@ func aggregateAddresses(m map[string]struct{}, addresses []string, isAddress boo
}
func (w *Worker) newAddressesMapForAliases() map[string]struct{} {
// return non nil map only if the chain supports address aliases
if w.useAddressAliases {
return make(map[string]struct{})
}
// returning nil disables the processing of the address aliases
return nil
}
@ -2034,6 +2036,13 @@ func (w *Worker) ComputeFeeStats(blockFrom, blockTo int, stopCompute chan os.Sig
return nil
}
func nonZeroTime(t time.Time) *time.Time {
if t.IsZero() {
return nil
}
return &t
}
// GetSystemInfo returns information about system
func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
start := time.Now()
@ -2057,24 +2066,29 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
internalDBSize = w.is.DBSizeTotal()
}
blockbookInfo := &BlockbookInfo{
Coin: w.is.Coin,
Host: w.is.Host,
Version: vi.Version,
GitCommit: vi.GitCommit,
BuildTime: vi.BuildTime,
SyncMode: w.is.SyncMode,
InitialSync: w.is.InitialSync,
InSync: inSync,
BestHeight: bestHeight,
LastBlockTime: lastBlockTime,
InSyncMempool: inSyncMempool,
LastMempoolTime: lastMempoolTime,
MempoolSize: mempoolSize,
Decimals: w.chainParser.AmountDecimals(),
DbSize: w.db.DatabaseSizeOnDisk(),
DbSizeFromColumns: internalDBSize,
DbColumns: columnStats,
About: Text.BlockbookAbout,
Coin: w.is.Coin,
Host: w.is.Host,
Version: vi.Version,
GitCommit: vi.GitCommit,
BuildTime: vi.BuildTime,
SyncMode: w.is.SyncMode,
InitialSync: w.is.InitialSync,
InSync: inSync,
BestHeight: bestHeight,
LastBlockTime: lastBlockTime,
InSyncMempool: inSyncMempool,
LastMempoolTime: lastMempoolTime,
MempoolSize: mempoolSize,
Decimals: w.chainParser.AmountDecimals(),
HasFiatRates: w.is.HasFiatRates,
HasTokenFiatRates: w.is.HasTokenFiatRates,
CurrentFiatRatesTime: nonZeroTime(w.is.CurrentFiatRatesTime),
HistoricalFiatRatesTime: nonZeroTime(w.is.HistoricalFiatRatesTime),
HistoricalTokenFiatRatesTime: nonZeroTime(w.is.HistoricalTokenFiatRatesTime),
DbSize: w.db.DatabaseSizeOnDisk(),
DbSizeFromColumns: internalDBSize,
DbColumns: columnStats,
About: Text.BlockbookAbout,
}
backendInfo := &common.BackendInfo{
BackendError: backendError,

View File

@ -77,6 +77,13 @@ type InternalState struct {
UtxoChecked bool `json:"utxoChecked"`
// store only the historical state, not the current state of the fiat rates in DB
HasFiatRates bool `json:"-"`
HasTokenFiatRates bool `json:"-"`
CurrentFiatRatesTime time.Time `json:"-"`
HistoricalFiatRatesTime time.Time `json:"historicalFiatRatesTime"`
HistoricalTokenFiatRatesTime time.Time `json:"historicalTokenFiatRatesTime"`
BackendInfo BackendInfo `json:"-"`
}

View File

@ -1740,6 +1740,11 @@ func (d *RocksDB) SetInternalState(is *common.InternalState) {
d.is = is
}
// GetInternalState gets the InternalState
func (d *RocksDB) GetInternalState() *common.InternalState {
return d.is
}
// StoreInternalState stores the internal state to db
func (d *RocksDB) StoreInternalState(is *common.InternalState) error {
if d.metrics != nil {

View File

@ -28,6 +28,7 @@ type RatesDownloader struct {
timeFormat string
callbackOnNewTicker OnNewFiatRatesTicker
downloader RatesDownloaderInterface
downloadTokens bool
}
// NewFiatRatesDownloader initializes the downloader for FiatRates API.
@ -55,6 +56,8 @@ func NewFiatRatesDownloader(db *db.RocksDB, apiType string, params string, callb
}
rd.db = db
rd.callbackOnNewTicker = callback
rd.downloadTokens = rdParams.PlatformIdentifier != "" && rdParams.PlatformVsCurrency != ""
is := rd.db.GetInternalState()
if apiType == "coingecko" {
throttle := true
if callback == nil {
@ -62,6 +65,11 @@ func NewFiatRatesDownloader(db *db.RocksDB, apiType string, params string, callb
throttle = false
}
rd.downloader = NewCoinGeckoDownloader(db, rdParams.URL, rdParams.Coin, rdParams.PlatformIdentifier, rdParams.PlatformVsCurrency, rd.timeFormat, throttle)
if is != nil {
is.HasFiatRates = true
is.HasTokenFiatRates = rd.downloadTokens
}
} else {
return nil, fmt.Errorf("NewFiatRatesDownloader: incorrect API type %q", apiType)
}
@ -71,6 +79,7 @@ func NewFiatRatesDownloader(db *db.RocksDB, apiType string, params string, callb
// Run periodically downloads current (every 15 minutes) and historical (once a day) tickers
func (rd *RatesDownloader) Run() error {
var lastHistoricalTickers time.Time
is := rd.db.GetInternalState()
for {
tickers, err := rd.downloader.CurrentTickers()
@ -79,6 +88,9 @@ func (rd *RatesDownloader) Run() error {
} else {
rd.db.FiatRatesSetCurrentTicker(tickers)
glog.Info("FiatRatesDownloader: CurrentTickers updated")
if is != nil {
is.CurrentFiatRatesTime = time.Now()
}
if rd.callbackOnNewTicker != nil {
rd.callbackOnNewTicker(tickers)
}
@ -94,16 +106,24 @@ func (rd *RatesDownloader) Run() error {
glog.Error("FiatRatesDownloader: FiatRatesFindLastTicker error ", err)
} else {
glog.Infof("FiatRatesDownloader: UpdateHistoricalTickers finished, last ticker from %v", ticker.Timestamp)
}
// UpdateHistoricalTokenTickers in a goroutine, it can take quite some time as there may be many tokens
go func() {
err := rd.downloader.UpdateHistoricalTokenTickers()
if err != nil {
glog.Error("FiatRatesDownloader: UpdateHistoricalTokenTickers error ", err)
} else {
glog.Info("FiatRatesDownloader: UpdateHistoricalTokenTickers finished")
if is != nil {
is.HistoricalFiatRatesTime = ticker.Timestamp
}
}()
}
if rd.downloadTokens {
// UpdateHistoricalTokenTickers in a goroutine, it can take quite some time as there are many tokens
go func() {
err := rd.downloader.UpdateHistoricalTokenTickers()
if err != nil {
glog.Error("FiatRatesDownloader: UpdateHistoricalTokenTickers error ", err)
} else {
glog.Info("FiatRatesDownloader: UpdateHistoricalTokenTickers finished")
if is != nil {
is.HistoricalTokenFiatRatesTime = time.Now()
}
}
}()
}
}
}
// wait for the next run with a slight random value to avoid too many request at the same time

View File

@ -520,10 +520,14 @@ func (s *PublicServer) parseTemplates() []*template.Template {
}
func formatUnixTime(ut int64) string {
return formatTime(time.Unix(ut, 0))
t := time.Unix(ut, 0)
return formatTime(&t)
}
func formatTime(t time.Time) string {
func formatTime(t *time.Time) string {
if t == nil {
return ""
}
return t.Format(time.RFC1123)
}

View File

@ -47,6 +47,16 @@
<td>Transactions in Mempool</td>
<td class="data">{{if .InternalExplorer}}<a href="/mempool">{{$bb.MempoolSize}}</a>{{else}}{{$bb.MempoolSize}}{{end}}</td>
</tr>
{{- if $bb.HasFiatRates -}}
<tr>
<td>Current Fiat rates</td>
<td class="data">{{formatTime $bb.CurrentFiatRatesTime}}</td>
</tr>
<tr>
<td>Historical Fiat rates</td>
<td class="data">{{formatTime $bb.HistoricalFiatRatesTime}}{{if $bb.HasTokenFiatRates}}<br>tokens {{formatTime $bb.HistoricalTokenFiatRatesTime}}{{end}}</td>
</tr>
{{- end -}}
<tr>
<td>Size On Disk</td>
<td class="data">{{$bb.DbSize}}</td>