Give info about fiat rates in status page and API
This commit is contained in:
parent
f485de5e35
commit
91c4675a53
41
api/types.go
41
api/types.go
@ -431,24 +431,29 @@ type BlockRaw struct {
|
|||||||
|
|
||||||
// BlockbookInfo contains information about the running blockbook instance
|
// BlockbookInfo contains information about the running blockbook instance
|
||||||
type BlockbookInfo struct {
|
type BlockbookInfo struct {
|
||||||
Coin string `json:"coin"`
|
Coin string `json:"coin"`
|
||||||
Host string `json:"host"`
|
Host string `json:"host"`
|
||||||
Version string `json:"version"`
|
Version string `json:"version"`
|
||||||
GitCommit string `json:"gitCommit"`
|
GitCommit string `json:"gitCommit"`
|
||||||
BuildTime string `json:"buildTime"`
|
BuildTime string `json:"buildTime"`
|
||||||
SyncMode bool `json:"syncMode"`
|
SyncMode bool `json:"syncMode"`
|
||||||
InitialSync bool `json:"initialSync"`
|
InitialSync bool `json:"initialSync"`
|
||||||
InSync bool `json:"inSync"`
|
InSync bool `json:"inSync"`
|
||||||
BestHeight uint32 `json:"bestHeight"`
|
BestHeight uint32 `json:"bestHeight"`
|
||||||
LastBlockTime time.Time `json:"lastBlockTime"`
|
LastBlockTime time.Time `json:"lastBlockTime"`
|
||||||
InSyncMempool bool `json:"inSyncMempool"`
|
InSyncMempool bool `json:"inSyncMempool"`
|
||||||
LastMempoolTime time.Time `json:"lastMempoolTime"`
|
LastMempoolTime time.Time `json:"lastMempoolTime"`
|
||||||
MempoolSize int `json:"mempoolSize"`
|
MempoolSize int `json:"mempoolSize"`
|
||||||
Decimals int `json:"decimals"`
|
Decimals int `json:"decimals"`
|
||||||
DbSize int64 `json:"dbSize"`
|
DbSize int64 `json:"dbSize"`
|
||||||
DbSizeFromColumns int64 `json:"dbSizeFromColumns,omitempty"`
|
HasFiatRates bool `json:"hasFiatRates,omitempty"`
|
||||||
DbColumns []common.InternalStateColumn `json:"dbColumns,omitempty"`
|
HasTokenFiatRates bool `json:"hasTokenFiatRates,omitempty"`
|
||||||
About string `json:"about"`
|
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
|
// SystemInfo contains information about the running blockbook and backend instance
|
||||||
|
|||||||
@ -134,9 +134,11 @@ func aggregateAddresses(m map[string]struct{}, addresses []string, isAddress boo
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (w *Worker) newAddressesMapForAliases() map[string]struct{} {
|
func (w *Worker) newAddressesMapForAliases() map[string]struct{} {
|
||||||
|
// return non nil map only if the chain supports address aliases
|
||||||
if w.useAddressAliases {
|
if w.useAddressAliases {
|
||||||
return make(map[string]struct{})
|
return make(map[string]struct{})
|
||||||
}
|
}
|
||||||
|
// returning nil disables the processing of the address aliases
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2034,6 +2036,13 @@ func (w *Worker) ComputeFeeStats(blockFrom, blockTo int, stopCompute chan os.Sig
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func nonZeroTime(t time.Time) *time.Time {
|
||||||
|
if t.IsZero() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return &t
|
||||||
|
}
|
||||||
|
|
||||||
// GetSystemInfo returns information about system
|
// GetSystemInfo returns information about system
|
||||||
func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
||||||
start := time.Now()
|
start := time.Now()
|
||||||
@ -2057,24 +2066,29 @@ func (w *Worker) GetSystemInfo(internal bool) (*SystemInfo, error) {
|
|||||||
internalDBSize = w.is.DBSizeTotal()
|
internalDBSize = w.is.DBSizeTotal()
|
||||||
}
|
}
|
||||||
blockbookInfo := &BlockbookInfo{
|
blockbookInfo := &BlockbookInfo{
|
||||||
Coin: w.is.Coin,
|
Coin: w.is.Coin,
|
||||||
Host: w.is.Host,
|
Host: w.is.Host,
|
||||||
Version: vi.Version,
|
Version: vi.Version,
|
||||||
GitCommit: vi.GitCommit,
|
GitCommit: vi.GitCommit,
|
||||||
BuildTime: vi.BuildTime,
|
BuildTime: vi.BuildTime,
|
||||||
SyncMode: w.is.SyncMode,
|
SyncMode: w.is.SyncMode,
|
||||||
InitialSync: w.is.InitialSync,
|
InitialSync: w.is.InitialSync,
|
||||||
InSync: inSync,
|
InSync: inSync,
|
||||||
BestHeight: bestHeight,
|
BestHeight: bestHeight,
|
||||||
LastBlockTime: lastBlockTime,
|
LastBlockTime: lastBlockTime,
|
||||||
InSyncMempool: inSyncMempool,
|
InSyncMempool: inSyncMempool,
|
||||||
LastMempoolTime: lastMempoolTime,
|
LastMempoolTime: lastMempoolTime,
|
||||||
MempoolSize: mempoolSize,
|
MempoolSize: mempoolSize,
|
||||||
Decimals: w.chainParser.AmountDecimals(),
|
Decimals: w.chainParser.AmountDecimals(),
|
||||||
DbSize: w.db.DatabaseSizeOnDisk(),
|
HasFiatRates: w.is.HasFiatRates,
|
||||||
DbSizeFromColumns: internalDBSize,
|
HasTokenFiatRates: w.is.HasTokenFiatRates,
|
||||||
DbColumns: columnStats,
|
CurrentFiatRatesTime: nonZeroTime(w.is.CurrentFiatRatesTime),
|
||||||
About: Text.BlockbookAbout,
|
HistoricalFiatRatesTime: nonZeroTime(w.is.HistoricalFiatRatesTime),
|
||||||
|
HistoricalTokenFiatRatesTime: nonZeroTime(w.is.HistoricalTokenFiatRatesTime),
|
||||||
|
DbSize: w.db.DatabaseSizeOnDisk(),
|
||||||
|
DbSizeFromColumns: internalDBSize,
|
||||||
|
DbColumns: columnStats,
|
||||||
|
About: Text.BlockbookAbout,
|
||||||
}
|
}
|
||||||
backendInfo := &common.BackendInfo{
|
backendInfo := &common.BackendInfo{
|
||||||
BackendError: backendError,
|
BackendError: backendError,
|
||||||
|
|||||||
@ -77,6 +77,13 @@ type InternalState struct {
|
|||||||
|
|
||||||
UtxoChecked bool `json:"utxoChecked"`
|
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:"-"`
|
BackendInfo BackendInfo `json:"-"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1740,6 +1740,11 @@ func (d *RocksDB) SetInternalState(is *common.InternalState) {
|
|||||||
d.is = is
|
d.is = is
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetInternalState gets the InternalState
|
||||||
|
func (d *RocksDB) GetInternalState() *common.InternalState {
|
||||||
|
return d.is
|
||||||
|
}
|
||||||
|
|
||||||
// StoreInternalState stores the internal state to db
|
// StoreInternalState stores the internal state to db
|
||||||
func (d *RocksDB) StoreInternalState(is *common.InternalState) error {
|
func (d *RocksDB) StoreInternalState(is *common.InternalState) error {
|
||||||
if d.metrics != nil {
|
if d.metrics != nil {
|
||||||
|
|||||||
@ -28,6 +28,7 @@ type RatesDownloader struct {
|
|||||||
timeFormat string
|
timeFormat string
|
||||||
callbackOnNewTicker OnNewFiatRatesTicker
|
callbackOnNewTicker OnNewFiatRatesTicker
|
||||||
downloader RatesDownloaderInterface
|
downloader RatesDownloaderInterface
|
||||||
|
downloadTokens bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFiatRatesDownloader initializes the downloader for FiatRates API.
|
// 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.db = db
|
||||||
rd.callbackOnNewTicker = callback
|
rd.callbackOnNewTicker = callback
|
||||||
|
rd.downloadTokens = rdParams.PlatformIdentifier != "" && rdParams.PlatformVsCurrency != ""
|
||||||
|
is := rd.db.GetInternalState()
|
||||||
if apiType == "coingecko" {
|
if apiType == "coingecko" {
|
||||||
throttle := true
|
throttle := true
|
||||||
if callback == nil {
|
if callback == nil {
|
||||||
@ -62,6 +65,11 @@ func NewFiatRatesDownloader(db *db.RocksDB, apiType string, params string, callb
|
|||||||
throttle = false
|
throttle = false
|
||||||
}
|
}
|
||||||
rd.downloader = NewCoinGeckoDownloader(db, rdParams.URL, rdParams.Coin, rdParams.PlatformIdentifier, rdParams.PlatformVsCurrency, rd.timeFormat, throttle)
|
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 {
|
} else {
|
||||||
return nil, fmt.Errorf("NewFiatRatesDownloader: incorrect API type %q", apiType)
|
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
|
// Run periodically downloads current (every 15 minutes) and historical (once a day) tickers
|
||||||
func (rd *RatesDownloader) Run() error {
|
func (rd *RatesDownloader) Run() error {
|
||||||
var lastHistoricalTickers time.Time
|
var lastHistoricalTickers time.Time
|
||||||
|
is := rd.db.GetInternalState()
|
||||||
|
|
||||||
for {
|
for {
|
||||||
tickers, err := rd.downloader.CurrentTickers()
|
tickers, err := rd.downloader.CurrentTickers()
|
||||||
@ -79,6 +88,9 @@ func (rd *RatesDownloader) Run() error {
|
|||||||
} else {
|
} else {
|
||||||
rd.db.FiatRatesSetCurrentTicker(tickers)
|
rd.db.FiatRatesSetCurrentTicker(tickers)
|
||||||
glog.Info("FiatRatesDownloader: CurrentTickers updated")
|
glog.Info("FiatRatesDownloader: CurrentTickers updated")
|
||||||
|
if is != nil {
|
||||||
|
is.CurrentFiatRatesTime = time.Now()
|
||||||
|
}
|
||||||
if rd.callbackOnNewTicker != nil {
|
if rd.callbackOnNewTicker != nil {
|
||||||
rd.callbackOnNewTicker(tickers)
|
rd.callbackOnNewTicker(tickers)
|
||||||
}
|
}
|
||||||
@ -94,16 +106,24 @@ func (rd *RatesDownloader) Run() error {
|
|||||||
glog.Error("FiatRatesDownloader: FiatRatesFindLastTicker error ", err)
|
glog.Error("FiatRatesDownloader: FiatRatesFindLastTicker error ", err)
|
||||||
} else {
|
} else {
|
||||||
glog.Infof("FiatRatesDownloader: UpdateHistoricalTickers finished, last ticker from %v", ticker.Timestamp)
|
glog.Infof("FiatRatesDownloader: UpdateHistoricalTickers finished, last ticker from %v", ticker.Timestamp)
|
||||||
}
|
if is != nil {
|
||||||
// UpdateHistoricalTokenTickers in a goroutine, it can take quite some time as there may be many tokens
|
is.HistoricalFiatRatesTime = ticker.Timestamp
|
||||||
go func() {
|
|
||||||
err := rd.downloader.UpdateHistoricalTokenTickers()
|
|
||||||
if err != nil {
|
|
||||||
glog.Error("FiatRatesDownloader: UpdateHistoricalTokenTickers error ", err)
|
|
||||||
} else {
|
|
||||||
glog.Info("FiatRatesDownloader: UpdateHistoricalTokenTickers finished")
|
|
||||||
}
|
}
|
||||||
}()
|
}
|
||||||
|
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
|
// wait for the next run with a slight random value to avoid too many request at the same time
|
||||||
|
|||||||
@ -520,10 +520,14 @@ func (s *PublicServer) parseTemplates() []*template.Template {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func formatUnixTime(ut int64) string {
|
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)
|
return t.Format(time.RFC1123)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -47,6 +47,16 @@
|
|||||||
<td>Transactions in Mempool</td>
|
<td>Transactions in Mempool</td>
|
||||||
<td class="data">{{if .InternalExplorer}}<a href="/mempool">{{$bb.MempoolSize}}</a>{{else}}{{$bb.MempoolSize}}{{end}}</td>
|
<td class="data">{{if .InternalExplorer}}<a href="/mempool">{{$bb.MempoolSize}}</a>{{else}}{{$bb.MempoolSize}}{{end}}</td>
|
||||||
</tr>
|
</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>
|
<tr>
|
||||||
<td>Size On Disk</td>
|
<td>Size On Disk</td>
|
||||||
<td class="data">{{$bb.DbSize}}</td>
|
<td class="data">{{$bb.DbSize}}</td>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user