280 lines
8.0 KiB
Go
280 lines
8.0 KiB
Go
//go:build unittest
|
|
|
|
package fiat
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"os"
|
|
"reflect"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/golang/glog"
|
|
"github.com/martinboehm/btcutil/chaincfg"
|
|
"github.com/trezor/blockbook/bchain"
|
|
"github.com/trezor/blockbook/bchain/coins/btc"
|
|
"github.com/trezor/blockbook/common"
|
|
"github.com/trezor/blockbook/db"
|
|
)
|
|
|
|
func TestMain(m *testing.M) {
|
|
// set the current directory to blockbook root so that ./static/ works
|
|
if err := os.Chdir(".."); err != nil {
|
|
glog.Fatal("Chdir error:", err)
|
|
}
|
|
c := m.Run()
|
|
chaincfg.ResetParams()
|
|
os.Exit(c)
|
|
}
|
|
|
|
func setupRocksDB(t *testing.T, parser bchain.BlockChainParser) (*db.RocksDB, *common.InternalState, string) {
|
|
tmp, err := os.MkdirTemp("", "testdb")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
d, err := db.NewRocksDB(tmp, 100000, -1, parser, nil, false)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
is, err := d.LoadInternalState("fakecoin")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
d.SetInternalState(is)
|
|
return d, is, tmp
|
|
}
|
|
|
|
func closeAndDestroyRocksDB(t *testing.T, db *db.RocksDB, dbpath string) {
|
|
// destroy db
|
|
if err := db.Close(); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
os.RemoveAll(dbpath)
|
|
}
|
|
|
|
type testBitcoinParser struct {
|
|
*btc.BitcoinParser
|
|
}
|
|
|
|
func bitcoinTestnetParser() *btc.BitcoinParser {
|
|
return btc.NewBitcoinParser(
|
|
btc.GetChainParams("test"),
|
|
&btc.Configuration{BlockAddressesToKeep: 1})
|
|
}
|
|
|
|
// getFiatRatesMockData reads a stub JSON response from a file and returns its content as string
|
|
func getFiatRatesMockData(name string) (string, error) {
|
|
var filename string
|
|
filename = "fiat/mock_data/" + name + ".json"
|
|
mockFile, err := os.Open(filename)
|
|
if err != nil {
|
|
glog.Errorf("Cannot open file %v", filename)
|
|
return "", err
|
|
}
|
|
b, err := io.ReadAll(mockFile)
|
|
if err != nil {
|
|
glog.Errorf("Cannot read file %v", filename)
|
|
return "", err
|
|
}
|
|
return string(b), nil
|
|
}
|
|
|
|
func TestFiatRates(t *testing.T) {
|
|
d, _, tmp := setupRocksDB(t, &testBitcoinParser{
|
|
BitcoinParser: bitcoinTestnetParser(),
|
|
})
|
|
defer closeAndDestroyRocksDB(t, d, tmp)
|
|
|
|
mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
|
var err error
|
|
var mockData string
|
|
|
|
if r.URL.Path == "/ping" {
|
|
w.WriteHeader(200)
|
|
} else if r.URL.Path == "/coins/list" {
|
|
mockData, err = getFiatRatesMockData("coinlist")
|
|
} else if r.URL.Path == "/simple/supported_vs_currencies" {
|
|
mockData, err = getFiatRatesMockData("vs_currencies")
|
|
} else if r.URL.Path == "/simple/price" {
|
|
if r.URL.Query().Get("ids") == "ethereum" {
|
|
mockData, err = getFiatRatesMockData("simpleprice_base")
|
|
} else {
|
|
mockData, err = getFiatRatesMockData("simpleprice_tokens")
|
|
}
|
|
} else if r.URL.Path == "/coins/ethereum/market_chart" {
|
|
vsCurrency := r.URL.Query().Get("vs_currency")
|
|
if vsCurrency == "usd" {
|
|
days := r.URL.Query().Get("days")
|
|
if days == "max" {
|
|
mockData, err = getFiatRatesMockData("market_chart_eth_usd_max")
|
|
} else {
|
|
mockData, err = getFiatRatesMockData("market_chart_eth_usd_1")
|
|
}
|
|
} else {
|
|
mockData, err = getFiatRatesMockData("market_chart_eth_other")
|
|
}
|
|
} else if r.URL.Path == "/coins/vendit/market_chart" || r.URL.Path == "/coins/ethereum-cash-token/market_chart" {
|
|
mockData, err = getFiatRatesMockData("market_chart_token_other")
|
|
} else {
|
|
t.Fatalf("Unknown URL path: %v", r.URL.Path)
|
|
}
|
|
|
|
if err != nil {
|
|
t.Fatalf("Error loading stub data: %v", err)
|
|
}
|
|
fmt.Fprintln(w, mockData)
|
|
}))
|
|
defer mockServer.Close()
|
|
|
|
// mocked CoinGecko API
|
|
configJSON := `{"fiat_rates": "coingecko", "fiat_rates_params": "{\"url\": \"` + mockServer.URL + `\", \"coin\": \"ethereum\",\"platformIdentifier\":\"ethereum\",\"platformVsCurrency\": \"eth\",\"periodSeconds\": 60}"}`
|
|
|
|
fiatRates, err := NewFiatRates(d, []byte(configJSON), nil)
|
|
if err != nil {
|
|
t.Fatalf("FiatRates init error: %v", err)
|
|
}
|
|
|
|
// get current tickers
|
|
currentTickers, err := fiatRates.downloader.CurrentTickers()
|
|
if err != nil {
|
|
t.Fatalf("Error in CurrentTickers: %v", err)
|
|
return
|
|
}
|
|
if currentTickers == nil {
|
|
t.Fatalf("CurrentTickers returned nil value")
|
|
return
|
|
}
|
|
|
|
wantCurrentTickers := common.CurrencyRatesTicker{
|
|
Rates: map[string]float32{
|
|
"aed": 8447.1,
|
|
"ars": 268901,
|
|
"aud": 3314.36,
|
|
"btc": 0.07531005,
|
|
"eth": 1,
|
|
"eur": 2182.99,
|
|
"ltc": 29.097696,
|
|
"usd": 2299.72,
|
|
},
|
|
TokenRates: map[string]float32{
|
|
"0x5e9997684d061269564f94e5d11ba6ce6fa9528c": 5.58195e-07,
|
|
"0x906710835d1ae85275eb770f06873340ca54274b": 1.39852e-10,
|
|
},
|
|
Timestamp: currentTickers.Timestamp,
|
|
}
|
|
if !reflect.DeepEqual(currentTickers, &wantCurrentTickers) {
|
|
t.Fatalf("CurrentTickers() = %v, want %v", *currentTickers, wantCurrentTickers)
|
|
}
|
|
|
|
ticker, err := fiatRates.db.FiatRatesFindLastTicker("usd", "")
|
|
if err != nil {
|
|
t.Fatalf("FiatRatesFindLastTicker failed with error: %v", err)
|
|
}
|
|
if ticker != nil {
|
|
t.Fatalf("FiatRatesFindLastTicker found unexpected data")
|
|
}
|
|
|
|
// update historical tickers for the first time
|
|
err = fiatRates.downloader.UpdateHistoricalTickers()
|
|
if err != nil {
|
|
t.Fatalf("UpdateHistoricalTickers 1st pass failed with error: %v", err)
|
|
}
|
|
err = fiatRates.downloader.UpdateHistoricalTokenTickers()
|
|
if err != nil {
|
|
t.Fatalf("UpdateHistoricalTokenTickers 1st pass failed with error: %v", err)
|
|
}
|
|
|
|
ticker, err = fiatRates.db.FiatRatesFindLastTicker("usd", "")
|
|
if err != nil || ticker == nil {
|
|
t.Fatalf("FiatRatesFindLastTicker failed with error: %v", err)
|
|
}
|
|
wantTicker := common.CurrencyRatesTicker{
|
|
Rates: map[string]float32{
|
|
"aed": 241272.48,
|
|
"ars": 241272.48,
|
|
"aud": 241272.48,
|
|
"btc": 241272.48,
|
|
"eth": 241272.48,
|
|
"eur": 241272.48,
|
|
"ltc": 241272.48,
|
|
"usd": 1794.5397,
|
|
},
|
|
TokenRates: map[string]float32{
|
|
"0x5e9997684d061269564f94e5d11ba6ce6fa9528c": 4.161734e+07,
|
|
"0x906710835d1ae85275eb770f06873340ca54274b": 4.161734e+07,
|
|
},
|
|
Timestamp: time.Unix(1654732800, 0).UTC(),
|
|
}
|
|
if !reflect.DeepEqual(ticker, &wantTicker) {
|
|
t.Fatalf("UpdateHistoricalTickers(usd) 1st pass = %v, want %v", *ticker, wantTicker)
|
|
}
|
|
|
|
ticker, err = fiatRates.db.FiatRatesFindLastTicker("eur", "")
|
|
if err != nil || ticker == nil {
|
|
t.Fatalf("FiatRatesFindLastTicker failed with error: %v", err)
|
|
}
|
|
wantTicker = common.CurrencyRatesTicker{
|
|
Rates: map[string]float32{
|
|
"aed": 240402.97,
|
|
"ars": 240402.97,
|
|
"aud": 240402.97,
|
|
"btc": 240402.97,
|
|
"eth": 240402.97,
|
|
"eur": 240402.97,
|
|
"ltc": 240402.97,
|
|
},
|
|
TokenRates: map[string]float32{
|
|
"0x5e9997684d061269564f94e5d11ba6ce6fa9528c": 4.1464476e+07,
|
|
"0x906710835d1ae85275eb770f06873340ca54274b": 4.1464476e+07,
|
|
},
|
|
Timestamp: time.Unix(1654819200, 0).UTC(),
|
|
}
|
|
if !reflect.DeepEqual(ticker, &wantTicker) {
|
|
t.Fatalf("UpdateHistoricalTickers(eur) 1st pass = %v, want %v", *ticker, wantTicker)
|
|
}
|
|
|
|
// update historical tickers for the second time
|
|
err = fiatRates.downloader.UpdateHistoricalTickers()
|
|
if err != nil {
|
|
t.Fatalf("UpdateHistoricalTickers 2nd pass failed with error: %v", err)
|
|
}
|
|
err = fiatRates.downloader.UpdateHistoricalTokenTickers()
|
|
if err != nil {
|
|
t.Fatalf("UpdateHistoricalTokenTickers 2nd pass failed with error: %v", err)
|
|
}
|
|
ticker, err = fiatRates.db.FiatRatesFindLastTicker("usd", "")
|
|
if err != nil || ticker == nil {
|
|
t.Fatalf("FiatRatesFindLastTicker failed with error: %v", err)
|
|
}
|
|
wantTicker = common.CurrencyRatesTicker{
|
|
Rates: map[string]float32{
|
|
"aed": 240402.97,
|
|
"ars": 240402.97,
|
|
"aud": 240402.97,
|
|
"btc": 240402.97,
|
|
"eth": 240402.97,
|
|
"eur": 240402.97,
|
|
"ltc": 240402.97,
|
|
"usd": 1788.4183,
|
|
},
|
|
TokenRates: map[string]float32{
|
|
"0x5e9997684d061269564f94e5d11ba6ce6fa9528c": 4.1464476e+07,
|
|
"0x906710835d1ae85275eb770f06873340ca54274b": 4.1464476e+07,
|
|
},
|
|
Timestamp: time.Unix(1654819200, 0).UTC(),
|
|
}
|
|
if !reflect.DeepEqual(ticker, &wantTicker) {
|
|
t.Fatalf("UpdateHistoricalTickers(usd) 2nd pass = %v, want %v", *ticker, wantTicker)
|
|
}
|
|
ticker, err = fiatRates.db.FiatRatesFindLastTicker("eur", "")
|
|
if err != nil || ticker == nil {
|
|
t.Fatalf("FiatRatesFindLastTicker failed with error: %v", err)
|
|
}
|
|
if !reflect.DeepEqual(ticker, &wantTicker) {
|
|
t.Fatalf("UpdateHistoricalTickers(eur) 2nd pass = %v, want %v", *ticker, wantTicker)
|
|
}
|
|
}
|