From 6cfb881a0418b05c173bdbde9f45c5144a848f57 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Mon, 4 Nov 2019 10:55:00 +0100 Subject: [PATCH 01/31] Add GetBalanceHistory for an address of bitcoin type --- api/types.go | 9 +++++ api/worker.go | 74 ++++++++++++++++++++++++++++++++++ api/xpub.go | 5 +++ db/rocksdb_test.go | 8 ++-- server/public.go | 21 ++++++++++ server/public_test.go | 40 +++++++++++++----- tests/dbtestdata/dbtestdata.go | 28 ++++++------- 7 files changed, 156 insertions(+), 29 deletions(-) diff --git a/api/types.go b/api/types.go index bb2988e3..5d739846 100644 --- a/api/types.go +++ b/api/types.go @@ -296,6 +296,15 @@ func (a Utxos) Less(i, j int) bool { return hi >= hj } +// BalanceHistory contains info about one point in time of balance history +type BalanceHistory struct { + Time int64 `json:"blockTime"` + Txs int `json:"txs"` + ReceivedSat *Amount `json:"received"` + SentSat *Amount `json:"sent"` + BalanceSat *Amount `json:"balance"` +} + // Blocks is list of blocks with paging information type Blocks struct { Paging diff --git a/api/worker.go b/api/worker.go index b2032c58..7ad85f4b 100644 --- a/api/worker.go +++ b/api/worker.go @@ -801,6 +801,80 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco return r, nil } +// GetBalanceHistory returns history of balance for given address +func (w *Worker) GetBalanceHistory(address string) ([]BalanceHistory, error) { + var bh []BalanceHistory + var b BalanceHistory + var bi *db.BlockInfo + var balance big.Int + start := time.Now() + addrDesc, _, err := w.getAddrDescAndNormalizeAddress(address) + if err != nil { + return nil, err + } + txs, err := w.getAddressTxids(addrDesc, false, &AddressFilter{Vout: AddressFilterVoutOff}, maxInt) + if err != nil { + return nil, err + } + for txi := len(txs) - 1; txi >= 0; txi-- { + ta, err := w.db.GetTxAddresses(txs[txi]) + if err != nil { + return nil, err + } + if ta == nil { + glog.Warning("DB inconsistency: tx ", txs[txi], ": not found in txAddresses") + continue + } + counted := false + if bi == nil || bi.Height != ta.Height { + bi, err = w.db.GetBlockInfo(ta.Height) + if err != nil { + return nil, err + } + } + hour := bi.Time - bi.Time%3600 + if b.Time != hour { + if b.Txs != 0 { + b.BalanceSat = (*Amount)(new(big.Int).Set(&balance)) + bh = append(bh, b) + } + b = BalanceHistory{ + Time: hour, + SentSat: &Amount{}, + ReceivedSat: &Amount{}, + } + } + for i := range ta.Inputs { + tai := &ta.Inputs[i] + if bytes.Equal(addrDesc, tai.AddrDesc) { + (*big.Int)(b.SentSat).Add((*big.Int)(b.SentSat), &tai.ValueSat) + balance.Sub(&balance, &tai.ValueSat) + if !counted { + counted = true + b.Txs++ + } + } + } + for i := range ta.Outputs { + tao := &ta.Outputs[i] + if bytes.Equal(addrDesc, tao.AddrDesc) { + (*big.Int)(b.ReceivedSat).Add((*big.Int)(b.ReceivedSat), &tao.ValueSat) + balance.Add(&balance, &tao.ValueSat) + if !counted { + counted = true + b.Txs++ + } + } + } + } + if b.Txs != 0 { + b.BalanceSat = (*Amount)(&balance) + bh = append(bh, b) + } + glog.Info("GetBalanceHistory ", address, ", count ", len(bh), " finished in ", time.Since(start)) + return bh, nil +} + func (w *Worker) waitForBackendSync() { // wait a short time if blockbook is synchronizing with backend inSync, _, _ := w.is.GetSyncState() diff --git a/api/xpub.go b/api/xpub.go index 5d2014cc..85522b3d 100644 --- a/api/xpub.go +++ b/api/xpub.go @@ -589,3 +589,8 @@ func (w *Worker) GetXpubUtxo(xpub string, onlyConfirmed bool, gap int) (Utxos, e glog.Info("GetXpubUtxo ", xpub[:16], ", ", len(r), " utxos, finished in ", time.Since(start)) return r, nil } + +// GetUtxoBalanceHistory returns history of balance for given xpub +func (w *Worker) GetUtxoBalanceHistory(xpub string, gap int) ([]BalanceHistory, error) { + return nil, errors.New("not implemented") +} diff --git a/db/rocksdb_test.go b/db/rocksdb_test.go index 5a6137e5..988a6749 100644 --- a/db/rocksdb_test.go +++ b/db/rocksdb_test.go @@ -180,7 +180,7 @@ func verifyAfterBitcoinTypeBlock1(t *testing.T, d *RocksDB, afterDisconnect bool if err := checkColumn(d, cfHeight, []keyPair{ { "000370d5", - "0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997" + uintToHex(1534858021) + varuintToHex(2) + varuintToHex(1234567), + "0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997" + uintToHex(1521515026) + varuintToHex(2) + varuintToHex(1234567), nil, }, }); err != nil { @@ -286,12 +286,12 @@ func verifyAfterBitcoinTypeBlock2(t *testing.T, d *RocksDB) { if err := checkColumn(d, cfHeight, []keyPair{ { "000370d5", - "0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997" + uintToHex(1534858021) + varuintToHex(2) + varuintToHex(1234567), + "0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997" + uintToHex(1521515026) + varuintToHex(2) + varuintToHex(1234567), nil, }, { "000370d6", - "00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6" + uintToHex(1534859123) + varuintToHex(4) + varuintToHex(2345678), + "00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6" + uintToHex(1521595678) + varuintToHex(4) + varuintToHex(2345678), nil, }, }); err != nil { @@ -606,7 +606,7 @@ func TestRocksDB_Index_BitcoinType(t *testing.T) { Hash: "00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6", Txs: 4, Size: 2345678, - Time: 1534859123, + Time: 1521595678, Height: 225494, } if !reflect.DeepEqual(info, iw) { diff --git a/server/public.go b/server/public.go index a966347b..49b728d9 100644 --- a/server/public.go +++ b/server/public.go @@ -175,6 +175,7 @@ func (s *PublicServer) ConnectFullPublicInterface() { serveMux.HandleFunc(path+"api/block/", s.jsonHandler(s.apiBlock, apiDefault)) serveMux.HandleFunc(path+"api/sendtx/", s.jsonHandler(s.apiSendTx, apiDefault)) serveMux.HandleFunc(path+"api/estimatefee/", s.jsonHandler(s.apiEstimateFee, apiDefault)) + serveMux.HandleFunc(path+"api/balancehistory/", s.jsonHandler(s.apiBalanceHistory, apiDefault)) // v2 format serveMux.HandleFunc(path+"api/v2/block-index/", s.jsonHandler(s.apiBlockIndex, apiV2)) serveMux.HandleFunc(path+"api/v2/tx-specific/", s.jsonHandler(s.apiTxSpecific, apiV2)) @@ -186,6 +187,7 @@ func (s *PublicServer) ConnectFullPublicInterface() { serveMux.HandleFunc(path+"api/v2/sendtx/", s.jsonHandler(s.apiSendTx, apiV2)) serveMux.HandleFunc(path+"api/v2/estimatefee/", s.jsonHandler(s.apiEstimateFee, apiV2)) serveMux.HandleFunc(path+"api/v2/feestats/", s.jsonHandler(s.apiFeeStats, apiV2)) + serveMux.HandleFunc(path+"api/v2/balancehistory/", s.jsonHandler(s.apiBalanceHistory, apiDefault)) // socket.io interface serveMux.Handle(path+"socket.io/", s.socketio.GetHandler()) // websocket interface @@ -1025,6 +1027,25 @@ func (s *PublicServer) apiUtxo(r *http.Request, apiVersion int) (interface{}, er return utxo, err } +func (s *PublicServer) apiBalanceHistory(r *http.Request, apiVersion int) (interface{}, error) { + var history []api.BalanceHistory + var err error + if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 { + gap, ec := strconv.Atoi(r.URL.Query().Get("gap")) + if ec != nil { + gap = 0 + } + history, err = s.api.GetUtxoBalanceHistory(r.URL.Path[i+1:], gap) + if err == nil { + s.metrics.ExplorerViews.With(common.Labels{"action": "api-xpub-balancehistory"}).Inc() + } else { + history, err = s.api.GetBalanceHistory(r.URL.Path[i+1:]) + s.metrics.ExplorerViews.With(common.Labels{"action": "api-address-balancehistory"}).Inc() + } + } + return history, err +} + func (s *PublicServer) apiBlock(r *http.Request, apiVersion int) (interface{}, error) { var block *api.Block var err error diff --git a/server/public_test.go b/server/public_test.go index 60afb45c..d25bbad3 100644 --- a/server/public_test.go +++ b/server/public_test.go @@ -412,7 +412,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"txid":"05e2e48aeabdd9b75def7b48d756ba304713c2aba7b522bf9dbc893fc4231b07","vin":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":2,"n":0,"scriptSig":{},"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"value":"0.00009876"}],"vout":[{"value":"0.00009","n":0,"scriptPubKey":{"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"]},"spent":false}],"blockhash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockheight":225494,"confirmations":1,"time":22549400002,"blocktime":22549400002,"valueOut":"0.00009","valueIn":"0.00009876","fees":"0.00000876","hex":""}`, + `{"txid":"05e2e48aeabdd9b75def7b48d756ba304713c2aba7b522bf9dbc893fc4231b07","vin":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":2,"n":0,"scriptSig":{},"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"value":"0.00009876"}],"vout":[{"value":"0.00009","n":0,"scriptPubKey":{"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"]},"spent":false}],"blockhash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockheight":225494,"confirmations":1,"time":1521595678,"blocktime":1521595678,"valueOut":"0.00009","valueIn":"0.00009876","fees":"0.00000876","hex":""}`, }, }, { @@ -430,7 +430,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"txid":"05e2e48aeabdd9b75def7b48d756ba304713c2aba7b522bf9dbc893fc4231b07","vin":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":2,"n":0,"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true,"value":"9876"}],"vout":[{"value":"9000","n":0,"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":22549400002,"value":"9000","valueIn":"9876","fees":"876"}`, + `{"txid":"05e2e48aeabdd9b75def7b48d756ba304713c2aba7b522bf9dbc893fc4231b07","vin":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":2,"n":0,"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true,"value":"9876"}],"vout":[{"value":"9000","n":0,"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":1521595678,"value":"9000","valueIn":"9876","fees":"876"}`, }, }, { @@ -448,7 +448,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"hex":"","txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","version":0,"locktime":0,"vin":[],"vout":[{"ValueSat":100000000,"value":0,"n":0,"scriptPubKey":{"hex":"76a914010d39800f86122416e28f485029acf77507169288ac","addresses":null}},{"ValueSat":12345,"value":0,"n":1,"scriptPubKey":{"hex":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","addresses":null}}],"confirmations":2,"time":22549300000,"blocktime":22549300000}`, + `{"hex":"","txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","version":0,"locktime":0,"vin":[],"vout":[{"ValueSat":100000000,"value":0,"n":0,"scriptPubKey":{"hex":"76a914010d39800f86122416e28f485029acf77507169288ac","addresses":null}},{"ValueSat":12345,"value":0,"n":1,"scriptPubKey":{"hex":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","addresses":null}}],"confirmations":2,"time":1521515026,"blocktime":1521515026}`, }, }, { @@ -493,7 +493,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"page":1,"totalPages":1,"itemsOnPage":1000,"address":"mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw","balance":"0","totalReceived":"1234567890123","totalSent":"1234567890123","unconfirmedBalance":"0","unconfirmedTxs":0,"txs":2,"transactions":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","vin":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","n":0,"addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true,"value":"1234567890123"},{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","vout":1,"n":1,"addresses":["mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"],"isAddress":true,"value":"12345"}],"vout":[{"value":"317283951061","n":0,"spent":true,"hex":"76a914ccaaaf374e1b06cb83118453d102587b4273d09588ac","addresses":["mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"],"isAddress":true},{"value":"917283951061","n":1,"hex":"76a9148d802c045445df49613f6a70ddd2e48526f3701f88ac","addresses":["mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL"],"isAddress":true},{"value":"0","n":2,"hex":"6a072020f1686f6a20","addresses":["OP_RETURN 2020f1686f6a20"],"isAddress":false}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":22549400000,"value":"1234567902122","valueIn":"1234567902468","fees":"346"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vin":[],"vout":[{"value":"1234567890123","n":0,"spent":true,"hex":"76a914a08eae93007f22668ab5e4a9c83c8cd1c325e3e088ac","addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true},{"value":"1","n":1,"spent":true,"hex":"a91452724c5178682f70e0ba31c6ec0633755a3b41d987","addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true},{"value":"9876","n":2,"spent":true,"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":22549300001,"value":"1234567900000","valueIn":"0","fees":"0"}]}`, + `{"page":1,"totalPages":1,"itemsOnPage":1000,"address":"mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw","balance":"0","totalReceived":"1234567890123","totalSent":"1234567890123","unconfirmedBalance":"0","unconfirmedTxs":0,"txs":2,"transactions":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","vin":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","n":0,"addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true,"value":"1234567890123"},{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","vout":1,"n":1,"addresses":["mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"],"isAddress":true,"value":"12345"}],"vout":[{"value":"317283951061","n":0,"spent":true,"hex":"76a914ccaaaf374e1b06cb83118453d102587b4273d09588ac","addresses":["mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"],"isAddress":true},{"value":"917283951061","n":1,"hex":"76a9148d802c045445df49613f6a70ddd2e48526f3701f88ac","addresses":["mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL"],"isAddress":true},{"value":"0","n":2,"hex":"6a072020f1686f6a20","addresses":["OP_RETURN 2020f1686f6a20"],"isAddress":false}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":1521595678,"value":"1234567902122","valueIn":"1234567902468","fees":"346"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vin":[],"vout":[{"value":"1234567890123","n":0,"spent":true,"hex":"76a914a08eae93007f22668ab5e4a9c83c8cd1c325e3e088ac","addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true},{"value":"1","n":1,"spent":true,"hex":"a91452724c5178682f70e0ba31c6ec0633755a3b41d987","addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true},{"value":"9876","n":2,"spent":true,"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1521515026,"value":"1234567900000","valueIn":"0","fees":"0"}]}`, }, }, { @@ -565,7 +565,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"page":1,"totalPages":1,"itemsOnPage":3,"address":"upub5E1xjDmZ7Hhej6LPpS8duATdKXnRYui7bDYj6ehfFGzWDZtmCmQkZhc3Zb7kgRLtHWd16QFxyP86JKL3ShZEBFX88aciJ3xyocuyhZZ8g6q","balance":"118641975500","totalReceived":"118641975501","totalSent":"1","unconfirmedBalance":"0","unconfirmedTxs":0,"txs":2,"transactions":[{"txid":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","vin":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","n":0,"addresses":["mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"],"isAddress":true,"value":"317283951061"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":1,"n":1,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true,"value":"1"}],"vout":[{"value":"118641975500","n":0,"hex":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","addresses":["2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu"],"isAddress":true},{"value":"198641975500","n":1,"hex":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","addresses":["mmJx9Y8ayz9h14yd9fgCW1bUKoEpkBAquP"],"isAddress":true}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":22549400001,"value":"317283951000","valueIn":"317283951062","fees":"62"}],"usedTokens":2,"tokens":[{"type":"XPUBAddress","name":"2MzmAKayJmja784jyHvRUW1bXPget1csRRG","path":"m/49'/1'/33'/0/0","transfers":2,"decimals":8,"balance":"0","totalReceived":"1","totalSent":"1"},{"type":"XPUBAddress","name":"2MsYfbi6ZdVXLDNrYAQ11ja9Sd3otMk4Pmj","path":"m/49'/1'/33'/0/1","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MuAZNAjLSo6RLFad2fvHSfgqBD7BoEVy4T","path":"m/49'/1'/33'/0/2","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NEqKzw3BosGnBE9by5uaDy5QgwjHac4Zbg","path":"m/49'/1'/33'/0/3","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mw7vJNC8zUK6VNN4CEjtoTYmuNPLewxZzV","path":"m/49'/1'/33'/0/4","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N1kvo97NFASPXiwephZUxE9PRXunjTxEc4","path":"m/49'/1'/33'/0/5","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MzSBtRWHbBjeUcu3H5VRDqkvz5sfmDxJKo","path":"m/49'/1'/33'/1/0","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MtShtAJYb1afWduUTwF1SixJjan7urZKke","path":"m/49'/1'/33'/1/1","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N3cP668SeqyBEr9gnB4yQEmU3VyxeRYith","path":"m/49'/1'/33'/1/2","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu","path":"m/49'/1'/33'/1/3","transfers":1,"decimals":8,"balance":"118641975500","totalReceived":"118641975500","totalSent":"0"},{"type":"XPUBAddress","name":"2NEzatauNhf9kPTwwj6ZfYKjUdy52j4hVUL","path":"m/49'/1'/33'/1/4","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N4RjsDp4LBpkNqyF91aNjgpF9CwDwBkJZq","path":"m/49'/1'/33'/1/5","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8XygTmQc4NoBBPEy3yybnfCYhsxFtzPDY","path":"m/49'/1'/33'/1/6","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N5BjBomZvb48sccK2vwLMiQ5ETKp1fdPVn","path":"m/49'/1'/33'/1/7","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MybMwbZRPCGU3SMWPwQCpDkbcQFw5Hbwen","path":"m/49'/1'/33'/1/8","transfers":0,"decimals":8}]}`, + `{"page":1,"totalPages":1,"itemsOnPage":3,"address":"upub5E1xjDmZ7Hhej6LPpS8duATdKXnRYui7bDYj6ehfFGzWDZtmCmQkZhc3Zb7kgRLtHWd16QFxyP86JKL3ShZEBFX88aciJ3xyocuyhZZ8g6q","balance":"118641975500","totalReceived":"118641975501","totalSent":"1","unconfirmedBalance":"0","unconfirmedTxs":0,"txs":2,"transactions":[{"txid":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","vin":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","n":0,"addresses":["mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"],"isAddress":true,"value":"317283951061"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":1,"n":1,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true,"value":"1"}],"vout":[{"value":"118641975500","n":0,"hex":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","addresses":["2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu"],"isAddress":true},{"value":"198641975500","n":1,"hex":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","addresses":["mmJx9Y8ayz9h14yd9fgCW1bUKoEpkBAquP"],"isAddress":true}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":1521595678,"value":"317283951000","valueIn":"317283951062","fees":"62"}],"usedTokens":2,"tokens":[{"type":"XPUBAddress","name":"2MzmAKayJmja784jyHvRUW1bXPget1csRRG","path":"m/49'/1'/33'/0/0","transfers":2,"decimals":8,"balance":"0","totalReceived":"1","totalSent":"1"},{"type":"XPUBAddress","name":"2MsYfbi6ZdVXLDNrYAQ11ja9Sd3otMk4Pmj","path":"m/49'/1'/33'/0/1","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MuAZNAjLSo6RLFad2fvHSfgqBD7BoEVy4T","path":"m/49'/1'/33'/0/2","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NEqKzw3BosGnBE9by5uaDy5QgwjHac4Zbg","path":"m/49'/1'/33'/0/3","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mw7vJNC8zUK6VNN4CEjtoTYmuNPLewxZzV","path":"m/49'/1'/33'/0/4","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N1kvo97NFASPXiwephZUxE9PRXunjTxEc4","path":"m/49'/1'/33'/0/5","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MzSBtRWHbBjeUcu3H5VRDqkvz5sfmDxJKo","path":"m/49'/1'/33'/1/0","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MtShtAJYb1afWduUTwF1SixJjan7urZKke","path":"m/49'/1'/33'/1/1","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N3cP668SeqyBEr9gnB4yQEmU3VyxeRYith","path":"m/49'/1'/33'/1/2","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu","path":"m/49'/1'/33'/1/3","transfers":1,"decimals":8,"balance":"118641975500","totalReceived":"118641975500","totalSent":"0"},{"type":"XPUBAddress","name":"2NEzatauNhf9kPTwwj6ZfYKjUdy52j4hVUL","path":"m/49'/1'/33'/1/4","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N4RjsDp4LBpkNqyF91aNjgpF9CwDwBkJZq","path":"m/49'/1'/33'/1/5","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8XygTmQc4NoBBPEy3yybnfCYhsxFtzPDY","path":"m/49'/1'/33'/1/6","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N5BjBomZvb48sccK2vwLMiQ5ETKp1fdPVn","path":"m/49'/1'/33'/1/7","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MybMwbZRPCGU3SMWPwQCpDkbcQFw5Hbwen","path":"m/49'/1'/33'/1/8","transfers":0,"decimals":8}]}`, }, }, { @@ -604,6 +604,24 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { `[{"txid":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","vout":0,"value":"118641975500","height":225494,"confirmations":1,"address":"2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu","path":"m/49'/1'/33'/1/3"}]`, }, }, + { + name: "apiBalanceHistory Addr2 v2", + r: newGetRequest(ts.URL + "/api/v2/balancehistory/mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"), + status: http.StatusOK, + contentType: "application/json; charset=utf-8", + body: []string{ + `[{"blockTime":1521514800,"txs":1,"received":"12345","sent":"0","balance":"12345"},{"blockTime":1521594000,"txs":1,"received":"0","sent":"12345","balance":"0"}]`, + }, + }, + { + name: "apiBalanceHistory Addr5 v2", + r: newGetRequest(ts.URL + "/api/v2/balancehistory/2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"), + status: http.StatusOK, + contentType: "application/json; charset=utf-8", + body: []string{ + `[{"blockTime":1521514800,"txs":1,"received":"9876","sent":"0","balance":"9876"},{"blockTime":1521594000,"txs":1,"received":"9000","sent":"9876","balance":"9000"}]`, + }, + }, { name: "apiSendTx", r: newGetRequest(ts.URL + "/api/v2/sendtx/1234567890"), @@ -646,7 +664,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `{"page":1,"totalPages":1,"itemsOnPage":1000,"hash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","nextBlockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","height":225493,"confirmations":2,"size":1234567,"time":1534858021,"version":0,"merkleRoot":"","nonce":"","bits":"","difficulty":"","txCount":2,"txs":[{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","vin":[],"vout":[{"value":"100000000","n":0,"addresses":["mfcWp7DB6NuaZsExybTTXpVgWz559Np4Ti"],"isAddress":true},{"value":"12345","n":1,"spent":true,"addresses":["mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1534858021,"value":"100012345","valueIn":"0","fees":"0"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vin":[],"vout":[{"value":"1234567890123","n":0,"spent":true,"addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true},{"value":"1","n":1,"spent":true,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true},{"value":"9876","n":2,"spent":true,"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1534858021,"value":"1234567900000","valueIn":"0","fees":"0"}]}`, + `{"page":1,"totalPages":1,"itemsOnPage":1000,"hash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","nextBlockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","height":225493,"confirmations":2,"size":1234567,"time":1521515026,"version":0,"merkleRoot":"","nonce":"","bits":"","difficulty":"","txCount":2,"txs":[{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","vin":[],"vout":[{"value":"100000000","n":0,"addresses":["mfcWp7DB6NuaZsExybTTXpVgWz559Np4Ti"],"isAddress":true},{"value":"12345","n":1,"spent":true,"addresses":["mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1521515026,"value":"100012345","valueIn":"0","fees":"0"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vin":[],"vout":[{"value":"1234567890123","n":0,"spent":true,"addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true},{"value":"1","n":1,"spent":true,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true},{"value":"9876","n":2,"spent":true,"addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1521515026,"value":"1234567900000","valueIn":"0","fees":"0"}]}`, }, }, } @@ -748,7 +766,7 @@ func socketioTestsBitcoinType(t *testing.T, ts *httptest.Server) { "to": 5, }, }}, - want: `{"result":{"totalCount":2,"items":[{"addresses":{"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz":{"inputIndexes":[1],"outputIndexes":[]}},"satoshis":-12345,"confirmations":1,"tx":{"hex":"","height":225494,"blockTimestamp":22549400000,"version":0,"hash":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","inputs":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","outputIndex":0,"script":"","sequence":0,"address":"mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw","satoshis":1234567890123},{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","outputIndex":1,"script":"","sequence":0,"address":"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz","satoshis":12345}],"inputSatoshis":1234567902468,"outputs":[{"satoshis":317283951061,"script":"76a914ccaaaf374e1b06cb83118453d102587b4273d09588ac","address":"mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"},{"satoshis":917283951061,"script":"76a9148d802c045445df49613f6a70ddd2e48526f3701f88ac","address":"mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL"},{"satoshis":0,"script":"6a072020f1686f6a20","address":"OP_RETURN 2020f1686f6a20"}],"outputSatoshis":1234567902122,"feeSatoshis":346}},{"addresses":{"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz":{"inputIndexes":[],"outputIndexes":[1]}},"satoshis":12345,"confirmations":2,"tx":{"hex":"","height":225493,"blockTimestamp":22549300000,"version":0,"hash":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","inputs":[],"outputs":[{"satoshis":100000000,"script":"76a914010d39800f86122416e28f485029acf77507169288ac","address":"mfcWp7DB6NuaZsExybTTXpVgWz559Np4Ti"},{"satoshis":12345,"script":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","address":"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"}],"outputSatoshis":100012345}}]}}`, + want: `{"result":{"totalCount":2,"items":[{"addresses":{"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz":{"inputIndexes":[1],"outputIndexes":[]}},"satoshis":-12345,"confirmations":1,"tx":{"hex":"","height":225494,"blockTimestamp":1521595678,"version":0,"hash":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","inputs":[{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","outputIndex":0,"script":"","sequence":0,"address":"mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw","satoshis":1234567890123},{"txid":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","outputIndex":1,"script":"","sequence":0,"address":"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz","satoshis":12345}],"inputSatoshis":1234567902468,"outputs":[{"satoshis":317283951061,"script":"76a914ccaaaf374e1b06cb83118453d102587b4273d09588ac","address":"mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"},{"satoshis":917283951061,"script":"76a9148d802c045445df49613f6a70ddd2e48526f3701f88ac","address":"mtR97eM2HPWVM6c8FGLGcukgaHHQv7THoL"},{"satoshis":0,"script":"6a072020f1686f6a20","address":"OP_RETURN 2020f1686f6a20"}],"outputSatoshis":1234567902122,"feeSatoshis":346}},{"addresses":{"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz":{"inputIndexes":[],"outputIndexes":[1]}},"satoshis":12345,"confirmations":2,"tx":{"hex":"","height":225493,"blockTimestamp":1521515026,"version":0,"hash":"00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840","inputs":[],"outputs":[{"satoshis":100000000,"script":"76a914010d39800f86122416e28f485029acf77507169288ac","address":"mfcWp7DB6NuaZsExybTTXpVgWz559Np4Ti"},{"satoshis":12345,"script":"76a9148bdf0aa3c567aa5975c2e61321b8bebbe7293df688ac","address":"mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz"}],"outputSatoshis":100012345}}]}}`, }, { name: "socketio getBlockHeader", @@ -758,7 +776,7 @@ func socketioTestsBitcoinType(t *testing.T, ts *httptest.Server) { { name: "socketio getDetailedTransaction", req: socketioReq{"getDetailedTransaction", []interface{}{"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71"}}, - want: `{"result":{"hex":"","height":225494,"blockTimestamp":22549400001,"version":0,"hash":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","inputs":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","outputIndex":0,"script":"","sequence":0,"address":"mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX","satoshis":317283951061},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","outputIndex":1,"script":"","sequence":0,"address":"2MzmAKayJmja784jyHvRUW1bXPget1csRRG","satoshis":1}],"inputSatoshis":317283951062,"outputs":[{"satoshis":118641975500,"script":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","address":"2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu"},{"satoshis":198641975500,"script":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","address":"mmJx9Y8ayz9h14yd9fgCW1bUKoEpkBAquP"}],"outputSatoshis":317283951000,"feeSatoshis":62}}`, + want: `{"result":{"hex":"","height":225494,"blockTimestamp":1521595678,"version":0,"hash":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","inputs":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","outputIndex":0,"script":"","sequence":0,"address":"mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX","satoshis":317283951061},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","outputIndex":1,"script":"","sequence":0,"address":"2MzmAKayJmja784jyHvRUW1bXPget1csRRG","satoshis":1}],"inputSatoshis":317283951062,"outputs":[{"satoshis":118641975500,"script":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","address":"2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu"},{"satoshis":198641975500,"script":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","address":"mmJx9Y8ayz9h14yd9fgCW1bUKoEpkBAquP"}],"outputSatoshis":317283951000,"feeSatoshis":62}}`, }, { name: "socketio sendTransaction", @@ -827,7 +845,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "details": "txs", }, }, - want: `{"id":"2","data":{"page":1,"totalPages":1,"itemsOnPage":25,"address":"upub5E1xjDmZ7Hhej6LPpS8duATdKXnRYui7bDYj6ehfFGzWDZtmCmQkZhc3Zb7kgRLtHWd16QFxyP86JKL3ShZEBFX88aciJ3xyocuyhZZ8g6q","balance":"118641975500","totalReceived":"118641975501","totalSent":"1","unconfirmedBalance":"0","unconfirmedTxs":0,"txs":2,"transactions":[{"txid":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","vin":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","n":0,"addresses":["mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"],"isAddress":true,"value":"317283951061"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":1,"n":1,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true,"value":"1"}],"vout":[{"value":"118641975500","n":0,"hex":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","addresses":["2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu"],"isAddress":true},{"value":"198641975500","n":1,"hex":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","addresses":["mmJx9Y8ayz9h14yd9fgCW1bUKoEpkBAquP"],"isAddress":true}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":22549400001,"value":"317283951000","valueIn":"317283951062","fees":"62"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vin":[],"vout":[{"value":"1234567890123","n":0,"spent":true,"hex":"76a914a08eae93007f22668ab5e4a9c83c8cd1c325e3e088ac","addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true},{"value":"1","n":1,"spent":true,"hex":"a91452724c5178682f70e0ba31c6ec0633755a3b41d987","addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true},{"value":"9876","n":2,"spent":true,"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":22549300001,"value":"1234567900000","valueIn":"0","fees":"0"}],"usedTokens":2,"tokens":[{"type":"XPUBAddress","name":"2MzmAKayJmja784jyHvRUW1bXPget1csRRG","path":"m/49'/1'/33'/0/0","transfers":2,"decimals":8,"balance":"0","totalReceived":"1","totalSent":"1"},{"type":"XPUBAddress","name":"2MsYfbi6ZdVXLDNrYAQ11ja9Sd3otMk4Pmj","path":"m/49'/1'/33'/0/1","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MuAZNAjLSo6RLFad2fvHSfgqBD7BoEVy4T","path":"m/49'/1'/33'/0/2","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NEqKzw3BosGnBE9by5uaDy5QgwjHac4Zbg","path":"m/49'/1'/33'/0/3","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mw7vJNC8zUK6VNN4CEjtoTYmuNPLewxZzV","path":"m/49'/1'/33'/0/4","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N1kvo97NFASPXiwephZUxE9PRXunjTxEc4","path":"m/49'/1'/33'/0/5","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MuWrWMzoBt8VDFNvPmpJf42M1GTUs85fPx","path":"m/49'/1'/33'/0/6","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MuVZ2Ca6Da9zmYynt49Rx7uikAgubGcymF","path":"m/49'/1'/33'/0/7","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MzRGWDUmrPP9HwYu4B43QGCTLwoop5cExa","path":"m/49'/1'/33'/0/8","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N5C9EEWJzyBXhpyPHqa3UNed73Amsi5b3L","path":"m/49'/1'/33'/0/9","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MzNawz2zjwq1L85GDE3YydEJGJYfXxaWkk","path":"m/49'/1'/33'/0/10","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N7NdeuAMgL57WE7QCeV2gTWi2Um8iAu5dA","path":"m/49'/1'/33'/0/11","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8JQEP6DSHEZHNsSDPA1gHMUq9YFndhkfV","path":"m/49'/1'/33'/0/12","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mvbn3YXqKZVpQKugaoQrfjSYPvz76RwZkC","path":"m/49'/1'/33'/0/13","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8MRNxCfwUY9TSW27X9ooGYtqgrGCfLRHx","path":"m/49'/1'/33'/0/14","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N6HvwrHC113KYZAmCtJ9XJNWgaTcnFunCM","path":"m/49'/1'/33'/0/15","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NEo3oNyHUoi7rmRWee7wki37jxPWsWCopJ","path":"m/49'/1'/33'/0/16","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mzm5KY8qdFbDHsQfy4akXbFvbR3FAwDuVo","path":"m/49'/1'/33'/0/17","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NGMwftmQCogp6XZNGvgiybz3WZysvsJzqC","path":"m/49'/1'/33'/0/18","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N3fJrrefndYjLGycvFFfYgevpZtcRKCkRD","path":"m/49'/1'/33'/0/19","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N1T7TnHBwfdpBoyw53EGUL7vuJmb2mU6jF","path":"m/49'/1'/33'/0/20","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MzSBtRWHbBjeUcu3H5VRDqkvz5sfmDxJKo","path":"m/49'/1'/33'/1/0","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MtShtAJYb1afWduUTwF1SixJjan7urZKke","path":"m/49'/1'/33'/1/1","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N3cP668SeqyBEr9gnB4yQEmU3VyxeRYith","path":"m/49'/1'/33'/1/2","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu","path":"m/49'/1'/33'/1/3","transfers":1,"decimals":8,"balance":"118641975500","totalReceived":"118641975500","totalSent":"0"},{"type":"XPUBAddress","name":"2NEzatauNhf9kPTwwj6ZfYKjUdy52j4hVUL","path":"m/49'/1'/33'/1/4","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N4RjsDp4LBpkNqyF91aNjgpF9CwDwBkJZq","path":"m/49'/1'/33'/1/5","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8XygTmQc4NoBBPEy3yybnfCYhsxFtzPDY","path":"m/49'/1'/33'/1/6","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N5BjBomZvb48sccK2vwLMiQ5ETKp1fdPVn","path":"m/49'/1'/33'/1/7","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MybMwbZRPCGU3SMWPwQCpDkbcQFw5Hbwen","path":"m/49'/1'/33'/1/8","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N7HexL4dyAQc7Th4iqcCW4hZuyiZsLWf74","path":"m/49'/1'/33'/1/9","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NF6X5FDGWrQj4nQrfP6hA77zB5WAc1DGup","path":"m/49'/1'/33'/1/10","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N4ZRPdvc7BVioBTohy4F6QtxreqcjNj26b","path":"m/49'/1'/33'/1/11","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mtfho1rLmevh4qTnkYWxZEFCWteDMtTcUF","path":"m/49'/1'/33'/1/12","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NFUCphKYvmMcNZRZrF261mRX6iADVB9Qms","path":"m/49'/1'/33'/1/13","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N5kBNMB8qgxE4Y4f8J19fScsE49J4aNvoJ","path":"m/49'/1'/33'/1/14","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NANWCaefhCKdXMcW8NbZnnrFRDvhJN2wPy","path":"m/49'/1'/33'/1/15","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NFHw7Yo2Bz8D2wGAYHW9qidbZFLpfJ72qB","path":"m/49'/1'/33'/1/16","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NBDSsBgy5PpFniLCb1eAFHcSxgxwPSDsZa","path":"m/49'/1'/33'/1/17","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NDWCSQHogc7sCuc2WoYt9PX2i2i6a5k6dX","path":"m/49'/1'/33'/1/18","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8vNyDP7iSDjm3BKpXrbDjAxyphqfvnJz8","path":"m/49'/1'/33'/1/19","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N4tFKLurSbMusAyq1tv4tzymVjveAFV1Vb","path":"m/49'/1'/33'/1/20","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NBx5WwjAr2cH6Yqrp3Vsf957HtRKwDUVdX","path":"m/49'/1'/33'/1/21","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NBu1seHTaFhQxbcW5L5BkZzqFLGmZqpxsa","path":"m/49'/1'/33'/1/22","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NCDLoea22jGsXuarfT1n2QyCUh6RFhAPnT","path":"m/49'/1'/33'/1/23","transfers":0,"decimals":8}]}}`, + want: `{"id":"2","data":{"page":1,"totalPages":1,"itemsOnPage":25,"address":"upub5E1xjDmZ7Hhej6LPpS8duATdKXnRYui7bDYj6ehfFGzWDZtmCmQkZhc3Zb7kgRLtHWd16QFxyP86JKL3ShZEBFX88aciJ3xyocuyhZZ8g6q","balance":"118641975500","totalReceived":"118641975501","totalSent":"1","unconfirmedBalance":"0","unconfirmedTxs":0,"txs":2,"transactions":[{"txid":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","vin":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","n":0,"addresses":["mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"],"isAddress":true,"value":"317283951061"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":1,"n":1,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true,"value":"1"}],"vout":[{"value":"118641975500","n":0,"hex":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","addresses":["2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu"],"isAddress":true},{"value":"198641975500","n":1,"hex":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","addresses":["mmJx9Y8ayz9h14yd9fgCW1bUKoEpkBAquP"],"isAddress":true}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":1521595678,"value":"317283951000","valueIn":"317283951062","fees":"62"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vin":[],"vout":[{"value":"1234567890123","n":0,"spent":true,"hex":"76a914a08eae93007f22668ab5e4a9c83c8cd1c325e3e088ac","addresses":["mv9uLThosiEnGRbVPS7Vhyw6VssbVRsiAw"],"isAddress":true},{"value":"1","n":1,"spent":true,"hex":"a91452724c5178682f70e0ba31c6ec0633755a3b41d987","addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true},{"value":"9876","n":2,"spent":true,"hex":"a914e921fc4912a315078f370d959f2c4f7b6d2a683c87","addresses":["2NEVv9LJmAnY99W1pFoc5UJjVdypBqdnvu1"],"isAddress":true}],"blockHash":"0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997","blockHeight":225493,"confirmations":2,"blockTime":1521515026,"value":"1234567900000","valueIn":"0","fees":"0"}],"usedTokens":2,"tokens":[{"type":"XPUBAddress","name":"2MzmAKayJmja784jyHvRUW1bXPget1csRRG","path":"m/49'/1'/33'/0/0","transfers":2,"decimals":8,"balance":"0","totalReceived":"1","totalSent":"1"},{"type":"XPUBAddress","name":"2MsYfbi6ZdVXLDNrYAQ11ja9Sd3otMk4Pmj","path":"m/49'/1'/33'/0/1","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MuAZNAjLSo6RLFad2fvHSfgqBD7BoEVy4T","path":"m/49'/1'/33'/0/2","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NEqKzw3BosGnBE9by5uaDy5QgwjHac4Zbg","path":"m/49'/1'/33'/0/3","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mw7vJNC8zUK6VNN4CEjtoTYmuNPLewxZzV","path":"m/49'/1'/33'/0/4","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N1kvo97NFASPXiwephZUxE9PRXunjTxEc4","path":"m/49'/1'/33'/0/5","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MuWrWMzoBt8VDFNvPmpJf42M1GTUs85fPx","path":"m/49'/1'/33'/0/6","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MuVZ2Ca6Da9zmYynt49Rx7uikAgubGcymF","path":"m/49'/1'/33'/0/7","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MzRGWDUmrPP9HwYu4B43QGCTLwoop5cExa","path":"m/49'/1'/33'/0/8","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N5C9EEWJzyBXhpyPHqa3UNed73Amsi5b3L","path":"m/49'/1'/33'/0/9","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MzNawz2zjwq1L85GDE3YydEJGJYfXxaWkk","path":"m/49'/1'/33'/0/10","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N7NdeuAMgL57WE7QCeV2gTWi2Um8iAu5dA","path":"m/49'/1'/33'/0/11","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8JQEP6DSHEZHNsSDPA1gHMUq9YFndhkfV","path":"m/49'/1'/33'/0/12","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mvbn3YXqKZVpQKugaoQrfjSYPvz76RwZkC","path":"m/49'/1'/33'/0/13","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8MRNxCfwUY9TSW27X9ooGYtqgrGCfLRHx","path":"m/49'/1'/33'/0/14","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N6HvwrHC113KYZAmCtJ9XJNWgaTcnFunCM","path":"m/49'/1'/33'/0/15","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NEo3oNyHUoi7rmRWee7wki37jxPWsWCopJ","path":"m/49'/1'/33'/0/16","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mzm5KY8qdFbDHsQfy4akXbFvbR3FAwDuVo","path":"m/49'/1'/33'/0/17","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NGMwftmQCogp6XZNGvgiybz3WZysvsJzqC","path":"m/49'/1'/33'/0/18","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N3fJrrefndYjLGycvFFfYgevpZtcRKCkRD","path":"m/49'/1'/33'/0/19","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N1T7TnHBwfdpBoyw53EGUL7vuJmb2mU6jF","path":"m/49'/1'/33'/0/20","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MzSBtRWHbBjeUcu3H5VRDqkvz5sfmDxJKo","path":"m/49'/1'/33'/1/0","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MtShtAJYb1afWduUTwF1SixJjan7urZKke","path":"m/49'/1'/33'/1/1","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N3cP668SeqyBEr9gnB4yQEmU3VyxeRYith","path":"m/49'/1'/33'/1/2","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu","path":"m/49'/1'/33'/1/3","transfers":1,"decimals":8,"balance":"118641975500","totalReceived":"118641975500","totalSent":"0"},{"type":"XPUBAddress","name":"2NEzatauNhf9kPTwwj6ZfYKjUdy52j4hVUL","path":"m/49'/1'/33'/1/4","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N4RjsDp4LBpkNqyF91aNjgpF9CwDwBkJZq","path":"m/49'/1'/33'/1/5","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8XygTmQc4NoBBPEy3yybnfCYhsxFtzPDY","path":"m/49'/1'/33'/1/6","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N5BjBomZvb48sccK2vwLMiQ5ETKp1fdPVn","path":"m/49'/1'/33'/1/7","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2MybMwbZRPCGU3SMWPwQCpDkbcQFw5Hbwen","path":"m/49'/1'/33'/1/8","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N7HexL4dyAQc7Th4iqcCW4hZuyiZsLWf74","path":"m/49'/1'/33'/1/9","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NF6X5FDGWrQj4nQrfP6hA77zB5WAc1DGup","path":"m/49'/1'/33'/1/10","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N4ZRPdvc7BVioBTohy4F6QtxreqcjNj26b","path":"m/49'/1'/33'/1/11","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2Mtfho1rLmevh4qTnkYWxZEFCWteDMtTcUF","path":"m/49'/1'/33'/1/12","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NFUCphKYvmMcNZRZrF261mRX6iADVB9Qms","path":"m/49'/1'/33'/1/13","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N5kBNMB8qgxE4Y4f8J19fScsE49J4aNvoJ","path":"m/49'/1'/33'/1/14","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NANWCaefhCKdXMcW8NbZnnrFRDvhJN2wPy","path":"m/49'/1'/33'/1/15","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NFHw7Yo2Bz8D2wGAYHW9qidbZFLpfJ72qB","path":"m/49'/1'/33'/1/16","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NBDSsBgy5PpFniLCb1eAFHcSxgxwPSDsZa","path":"m/49'/1'/33'/1/17","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NDWCSQHogc7sCuc2WoYt9PX2i2i6a5k6dX","path":"m/49'/1'/33'/1/18","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N8vNyDP7iSDjm3BKpXrbDjAxyphqfvnJz8","path":"m/49'/1'/33'/1/19","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2N4tFKLurSbMusAyq1tv4tzymVjveAFV1Vb","path":"m/49'/1'/33'/1/20","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NBx5WwjAr2cH6Yqrp3Vsf957HtRKwDUVdX","path":"m/49'/1'/33'/1/21","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NBu1seHTaFhQxbcW5L5BkZzqFLGmZqpxsa","path":"m/49'/1'/33'/1/22","transfers":0,"decimals":8},{"type":"XPUBAddress","name":"2NCDLoea22jGsXuarfT1n2QyCUh6RFhAPnT","path":"m/49'/1'/33'/1/23","transfers":0,"decimals":8}]}}`, }, { name: "websocket getAccountInfo", @@ -881,7 +899,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "txid": dbtestdata.TxidB2T2, }, }, - want: `{"id":"7","data":{"txid":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","vin":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","n":0,"addresses":["mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"],"isAddress":true,"value":"317283951061"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":1,"n":1,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true,"value":"1"}],"vout":[{"value":"118641975500","n":0,"hex":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","addresses":["2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu"],"isAddress":true},{"value":"198641975500","n":1,"hex":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","addresses":["mmJx9Y8ayz9h14yd9fgCW1bUKoEpkBAquP"],"isAddress":true}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":22549400001,"value":"317283951000","valueIn":"317283951062","fees":"62"}}`, + want: `{"id":"7","data":{"txid":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","vin":[{"txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","n":0,"addresses":["mzB8cYrfRwFRFAGTDzV8LkUQy5BQicxGhX"],"isAddress":true,"value":"317283951061"},{"txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":1,"n":1,"addresses":["2MzmAKayJmja784jyHvRUW1bXPget1csRRG"],"isAddress":true,"value":"1"}],"vout":[{"value":"118641975500","n":0,"hex":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","addresses":["2N6utyMZfPNUb1Bk8oz7p2JqJrXkq83gegu"],"isAddress":true},{"value":"198641975500","n":1,"hex":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","addresses":["mmJx9Y8ayz9h14yd9fgCW1bUKoEpkBAquP"],"isAddress":true}],"blockHash":"00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6","blockHeight":225494,"confirmations":1,"blockTime":1521595678,"value":"317283951000","valueIn":"317283951062","fees":"62"}}`, }, { name: "websocket getTransaction", @@ -901,7 +919,7 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { "txid": dbtestdata.TxidB2T2, }, }, - want: `{"id":"9","data":{"hex":"","txid":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","version":0,"locktime":0,"vin":[{"coinbase":"","txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","vout":0,"scriptSig":{"hex":""},"sequence":0,"addresses":null},{"coinbase":"","txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":1,"scriptSig":{"hex":""},"sequence":0,"addresses":null}],"vout":[{"ValueSat":118641975500,"value":0,"n":0,"scriptPubKey":{"hex":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","addresses":null}},{"ValueSat":198641975500,"value":0,"n":1,"scriptPubKey":{"hex":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","addresses":null}}],"confirmations":1,"time":22549400001,"blocktime":22549400001,"vsize":400}}`, + want: `{"id":"9","data":{"hex":"","txid":"3d90d15ed026dc45e19ffb52875ed18fa9e8012ad123d7f7212176e2b0ebdb71","version":0,"locktime":0,"vin":[{"coinbase":"","txid":"7c3be24063f268aaa1ed81b64776798f56088757641a34fb156c4f51ed2e9d25","vout":0,"scriptSig":{"hex":""},"sequence":0,"addresses":null},{"coinbase":"","txid":"effd9ef509383d536b1c8af5bf434c8efbf521a4f2befd4022bbd68694b4ac75","vout":1,"scriptSig":{"hex":""},"sequence":0,"addresses":null}],"vout":[{"ValueSat":118641975500,"value":0,"n":0,"scriptPubKey":{"hex":"a91495e9fbe306449c991d314afe3c3567d5bf78efd287","addresses":null}},{"ValueSat":198641975500,"value":0,"n":1,"scriptPubKey":{"hex":"76a9143f8ba3fda3ba7b69f5818086e12223c6dd25e3c888ac","addresses":null}}],"confirmations":1,"time":1521595678,"blocktime":1521595678,"vsize":400}}`, }, { name: "websocket estimateFee", diff --git a/tests/dbtestdata/dbtestdata.go b/tests/dbtestdata/dbtestdata.go index 4a12d85d..8f853df0 100644 --- a/tests/dbtestdata/dbtestdata.go +++ b/tests/dbtestdata/dbtestdata.go @@ -68,7 +68,7 @@ func GetTestBitcoinTypeBlock1(parser bchain.BlockChainParser) *bchain.Block { Height: 225493, Hash: "0000000076fbbed90fd75b0e18856aa35baa984e9c9d444cf746ad85e94e2997", Size: 1234567, - Time: 1534858021, + Time: 1521515026, Confirmations: 2, }, Txs: []bchain.Tx{ @@ -91,8 +91,8 @@ func GetTestBitcoinTypeBlock1(parser bchain.BlockChainParser) *bchain.Block { ValueSat: *SatB1T1A2, }, }, - Blocktime: 22549300000, - Time: 22549300000, + Blocktime: 1521515026, + Time: 1521515026, Confirmations: 2, }, { @@ -120,8 +120,8 @@ func GetTestBitcoinTypeBlock1(parser bchain.BlockChainParser) *bchain.Block { ValueSat: *SatB1T2A5, }, }, - Blocktime: 22549300001, - Time: 22549300001, + Blocktime: 1521515026, + Time: 1521515026, Confirmations: 2, }, }, @@ -135,7 +135,7 @@ func GetTestBitcoinTypeBlock2(parser bchain.BlockChainParser) *bchain.Block { Height: 225494, Hash: "00000000eb0443fd7dc4a1ed5c686a8e995057805f9a161d9a5a77a95e72b7b6", Size: 2345678, - Time: 1534859123, + Time: 1521595678, Confirmations: 1, }, Txs: []bchain.Tx{ @@ -176,8 +176,8 @@ func GetTestBitcoinTypeBlock2(parser bchain.BlockChainParser) *bchain.Block { ValueSat: *SatZero, }, }, - Blocktime: 22549400000, - Time: 22549400000, + Blocktime: 1521595678, + Time: 1521595678, Confirmations: 1, }, { @@ -210,8 +210,8 @@ func GetTestBitcoinTypeBlock2(parser bchain.BlockChainParser) *bchain.Block { ValueSat: *SatB2T2A9, }, }, - Blocktime: 22549400001, - Time: 22549400001, + Blocktime: 1521595678, + Time: 1521595678, Confirmations: 1, }, // transaction from the same address in the previous block @@ -233,8 +233,8 @@ func GetTestBitcoinTypeBlock2(parser bchain.BlockChainParser) *bchain.Block { ValueSat: *SatB2T3A5, }, }, - Blocktime: 22549400002, - Time: 22549400002, + Blocktime: 1521595678, + Time: 1521595678, Confirmations: 1, }, // mining transaction @@ -259,8 +259,8 @@ func GetTestBitcoinTypeBlock2(parser bchain.BlockChainParser) *bchain.Block { ValueSat: *SatZero, }, }, - Blocktime: 22549400003, - Time: 22549400003, + Blocktime: 1521595678, + Time: 1521595678, Confirmations: 1, }, }, From a7b42f1de0ab2e5752454639f8a484ee479eeae3 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Fri, 1 Nov 2019 16:52:13 +0100 Subject: [PATCH 02/31] bch (+testnet): Bump backend 0.20.4 -> 0.20.5 --- configs/coins/bcash.json | 8 ++++---- configs/coins/bcash_testnet.json | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/configs/coins/bcash.json b/configs/coins/bcash.json index 3cc6f240..4be65abe 100644 --- a/configs/coins/bcash.json +++ b/configs/coins/bcash.json @@ -22,10 +22,10 @@ "package_name": "backend-bcash", "package_revision": "satoshilabs-1", "system_user": "bcash", - "version": "0.20.4", - "binary_url": "https://download.bitcoinabc.org/0.20.4/linux/bitcoin-abc-0.20.4-x86_64-linux-gnu.tar.gz", + "version": "0.20.5", + "binary_url": "https://download.bitcoinabc.org/0.20.5/linux/bitcoin-abc-0.20.5-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "7bc8db6e3018f624a67e0824c08db58165d63d97de83294be0808610cbfa5d5b", + "verification_source": "8197c0c26553d0c1dd5bc5e033aaec9dd7324ceab8218f075f7d48f4889e3aef", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -49,7 +49,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Bitcoin ABC:0.20.4/", + "subversion": "/Bitcoin ABC:0.20.5/", "address_format": "cashaddr", "mempool_workers": 8, "mempool_sub_workers": 2, diff --git a/configs/coins/bcash_testnet.json b/configs/coins/bcash_testnet.json index 34e2dbca..eb011390 100644 --- a/configs/coins/bcash_testnet.json +++ b/configs/coins/bcash_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-bcash-testnet", "package_revision": "satoshilabs-1", "system_user": "bcash", - "version": "0.20.4", - "binary_url": "https://download.bitcoinabc.org/0.20.4/linux/bitcoin-abc-0.20.4-x86_64-linux-gnu.tar.gz", + "version": "0.20.5", + "binary_url": "https://download.bitcoinabc.org/0.20.5/linux/bitcoin-abc-0.20.5-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "7bc8db6e3018f624a67e0824c08db58165d63d97de83294be0808610cbfa5d5b", + "verification_source": "8197c0c26553d0c1dd5bc5e033aaec9dd7324ceab8218f075f7d48f4889e3aef", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -49,7 +49,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Bitcoin ABC:0.20.4/", + "subversion": "/Bitcoin ABC:0.20.5/", "address_format": "cashaddr", "mempool_workers": 8, "mempool_sub_workers": 2, From 0aadb241fb3b64f72390ef6886369381c8dd59ab Mon Sep 17 00:00:00 2001 From: WO Date: Wed, 6 Nov 2019 18:22:00 +0900 Subject: [PATCH 03/31] Bump Koto backend to 2.1.0 --- configs/coins/koto.json | 6 +++--- configs/coins/koto_testnet.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configs/coins/koto.json b/configs/coins/koto.json index 48327749..16f0a088 100644 --- a/configs/coins/koto.json +++ b/configs/coins/koto.json @@ -22,10 +22,10 @@ "package_name": "backend-koto", "package_revision": "satoshilabs-1", "system_user": "koto", - "version": "2.0.7", - "binary_url": "https://github.com/KotoDevelopers/koto/releases/download/v2.0.7/koto-2.0.7-linux64.tar.gz", + "version": "2.1.0", + "binary_url": "https://github.com/KotoDevelopers/koto/releases/download/v2.1.0/koto-2.1.0-linux64.tar.gz", "verification_type": "gpg", - "verification_source": "https://github.com/KotoDevelopers/koto/releases/download/v2.0.7/koto-2.0.7-linux64.tar.gz.asc", + "verification_source": "https://github.com/KotoDevelopers/koto/releases/download/v2.1.0/koto-2.1.0-linux64.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/koto-qt" diff --git a/configs/coins/koto_testnet.json b/configs/coins/koto_testnet.json index 52cfc5be..108e9f46 100644 --- a/configs/coins/koto_testnet.json +++ b/configs/coins/koto_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-koto-testnet", "package_revision": "satoshilabs-1", "system_user": "koto", - "version": "2.0.7", - "binary_url": "https://github.com/KotoDevelopers/koto/releases/download/v2.0.7/koto-2.0.7-linux64.tar.gz", + "version": "2.1.0", + "binary_url": "https://github.com/KotoDevelopers/koto/releases/download/v2.1.0/koto-2.1.0-linux64.tar.gz", "verification_type": "gpg", - "verification_source": "https://github.com/KotoDevelopers/koto/releases/download/v2.0.7/koto-2.0.7-linux64.tar.gz.asc", + "verification_source": "https://github.com/KotoDevelopers/koto/releases/download/v2.1.0/koto-2.1.0-linux64.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/koto-qt" From c3ba9a7b9520ec08d29f331a13f2f9d3b4affd3c Mon Sep 17 00:00:00 2001 From: thebevrishot Date: Tue, 5 Nov 2019 13:49:08 +0700 Subject: [PATCH 04/31] Bump Zcoin to 0.13.8.5 --- configs/coins/zcoin.json | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/configs/coins/zcoin.json b/configs/coins/zcoin.json index 8127ada0..c239f8a7 100644 --- a/configs/coins/zcoin.json +++ b/configs/coins/zcoin.json @@ -22,18 +22,25 @@ "package_name": "backend-zcoin", "package_revision": "satoshilabs-1", "system_user": "zcoin", - "version": "0.13.8.2", - "binary_url": "https://github.com/zcoinofficial/zcoin/releases/download/v0.13.8.2/zcoin-0.13.8.2-linux64.tar.gz", + "version": "0.13.8.5", + "binary_url": "https://github.com/zcoinofficial/zcoin/releases/download/v0.13.8.5/zcoin-0.13.8.5-linux64.tar.gz", "verification_type": "sha256", - "verification_source": "468a7b5c030a04e4c38ce23821d331f215ccf0665dec10c1001b357a8fbe196c", + "verification_source": "52f8a722bb1cc5c53e77edf81f6f1300f3b15d53f9cb4fcee90367f11ad84dd9", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ + "bin/tor", + "bin/tor-gencert", + "bin/tor-print-ed-signing-cert", + "bin/tor-resolve", "bin/zcoin-qt", "bin/zcoin-tx", + "etc/tor/torrc.sample", "include/bitcoinconsensus.h", "lib/libbitcoinconsensus.so", "lib/libbitcoinconsensus.so.0", - "lib/libbitcoinconsensus.so.0.0.0" + "lib/libbitcoinconsensus.so.0.0.0", + "share/tor/geoip", + "share/tor/geoip6" ], "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/zcoind -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", "logrotate_files_template": "{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/*.log", From fa2ee739c6e99b992c447377f0c6abd270b30934 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Thu, 7 Nov 2019 16:20:09 +0100 Subject: [PATCH 05/31] eth (+testnet): Bump backend 1.9.6 -> 1.9.7 --- configs/coins/ethereum.json | 6 +++--- configs/coins/ethereum_testnet_ropsten.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configs/coins/ethereum.json b/configs/coins/ethereum.json index 8bc4a47e..5c89ef26 100644 --- a/configs/coins/ethereum.json +++ b/configs/coins/ethereum.json @@ -21,10 +21,10 @@ "package_name": "backend-ethereum", "package_revision": "satoshilabs-1", "system_user": "ethereum", - "version": "1.9.6-bd059680", - "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.6-bd059680.tar.gz", + "version": "1.9.7-a718daa6", + "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.7-a718daa6.tar.gz", "verification_type": "gpg", - "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.6-bd059680.tar.gz.asc", + "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.7-a718daa6.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/geth --ipcdisable --syncmode full --cache 1024 --nat none --datadir {{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend --port 38336 --ws --wsaddr 0.0.0.0 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" --rpc --rpcport 8136 -rpcaddr 0.0.0.0 --rpccorsdomain \"*\" --rpcvhosts \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'", diff --git a/configs/coins/ethereum_testnet_ropsten.json b/configs/coins/ethereum_testnet_ropsten.json index 52f8a4c2..1d193182 100644 --- a/configs/coins/ethereum_testnet_ropsten.json +++ b/configs/coins/ethereum_testnet_ropsten.json @@ -20,10 +20,10 @@ "package_name": "backend-ethereum-testnet-ropsten", "package_revision": "satoshilabs-1", "system_user": "ethereum", - "version": "1.9.6-bd059680", - "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.6-bd059680.tar.gz", + "version": "1.9.7-a718daa6", + "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.7-a718daa6.tar.gz", "verification_type": "gpg", - "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.6-bd059680.tar.gz.asc", + "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.7-a718daa6.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/geth --testnet --syncmode full --ipcdisable --cache 1024 --nat none --datadir {{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend --port 48336 --ws --wsaddr 0.0.0.0 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'", From c44ce001146835910d159d7ed3cf0f6f09f93a26 Mon Sep 17 00:00:00 2001 From: Mykola Date: Sun, 10 Nov 2019 23:53:07 -0800 Subject: [PATCH 06/31] zcash (+testnet): Bump backend 2.0.7-3 -> 2.1.0-1 --- configs/coins/zcash.json | 4 ++-- configs/coins/zcash_testnet.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/coins/zcash.json b/configs/coins/zcash.json index f3b63620..f190aa37 100644 --- a/configs/coins/zcash.json +++ b/configs/coins/zcash.json @@ -23,9 +23,9 @@ "package_revision": "satoshilabs-1", "system_user": "zcash", "version": "2.0.7-3", - "binary_url": "https://z.cash/downloads/zcash-2.0.7-3-linux64-debian-stretch.tar.gz", + "binary_url": "https://z.cash/downloads/zcash-2.1.0-1-linux64-debian-stretch.tar.gz", "verification_type": "sha256", - "verification_source": "b6961c0073c968dc30ed10a752ba657cb76acb22265dbc5f4bae7cc0395b35e4", + "verification_source": "aec6b3c4178c5ceb4e7b7ed3aaa96078b88b872640c7bb38208d5bce48e3f75c", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/zcashd -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", diff --git a/configs/coins/zcash_testnet.json b/configs/coins/zcash_testnet.json index 48c32c77..38a2fa4a 100644 --- a/configs/coins/zcash_testnet.json +++ b/configs/coins/zcash_testnet.json @@ -23,9 +23,9 @@ "package_revision": "satoshilabs-1", "system_user": "zcash", "version": "2.0.7-3", - "binary_url": "https://z.cash/downloads/zcash-2.0.7-3-linux64-debian-stretch.tar.gz", + "binary_url": "https://z.cash/downloads/zcash-2.1.0-1-linux64-debian-stretch.tar.gz", "verification_type": "sha256", - "verification_source": "b6961c0073c968dc30ed10a752ba657cb76acb22265dbc5f4bae7cc0395b35e4", + "verification_source": "aec6b3c4178c5ceb4e7b7ed3aaa96078b88b872640c7bb38208d5bce48e3f75c", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bin/zcashd -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", From a400ca188ae83abf48387da2d17dd6a60fe5bd59 Mon Sep 17 00:00:00 2001 From: Mykola Date: Mon, 11 Nov 2019 13:04:39 -0800 Subject: [PATCH 07/31] Fix release number --- configs/coins/zcash.json | 2 +- configs/coins/zcash_testnet.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/coins/zcash.json b/configs/coins/zcash.json index f190aa37..99a31db3 100644 --- a/configs/coins/zcash.json +++ b/configs/coins/zcash.json @@ -23,7 +23,7 @@ "package_revision": "satoshilabs-1", "system_user": "zcash", "version": "2.0.7-3", - "binary_url": "https://z.cash/downloads/zcash-2.1.0-1-linux64-debian-stretch.tar.gz", + "binary_url": "https://z.cash/downloads/zcash-2.1.0-linux64-debian-stretch.tar.gz", "verification_type": "sha256", "verification_source": "aec6b3c4178c5ceb4e7b7ed3aaa96078b88b872640c7bb38208d5bce48e3f75c", "extract_command": "tar -C backend --strip 1 -xf", diff --git a/configs/coins/zcash_testnet.json b/configs/coins/zcash_testnet.json index 38a2fa4a..84850a11 100644 --- a/configs/coins/zcash_testnet.json +++ b/configs/coins/zcash_testnet.json @@ -23,7 +23,7 @@ "package_revision": "satoshilabs-1", "system_user": "zcash", "version": "2.0.7-3", - "binary_url": "https://z.cash/downloads/zcash-2.1.0-1-linux64-debian-stretch.tar.gz", + "binary_url": "https://z.cash/downloads/zcash-2.1.0-linux64-debian-stretch.tar.gz", "verification_type": "sha256", "verification_source": "aec6b3c4178c5ceb4e7b7ed3aaa96078b88b872640c7bb38208d5bce48e3f75c", "extract_command": "tar -C backend --strip 1 -xf", From c9b72b7aee80c89482dbc25142cddcd74cafa775 Mon Sep 17 00:00:00 2001 From: Mykola Date: Mon, 11 Nov 2019 13:12:18 -0800 Subject: [PATCH 08/31] Return to release tag 2.0.1-1 --- configs/coins/zcash.json | 2 +- configs/coins/zcash_testnet.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/coins/zcash.json b/configs/coins/zcash.json index 99a31db3..f190aa37 100644 --- a/configs/coins/zcash.json +++ b/configs/coins/zcash.json @@ -23,7 +23,7 @@ "package_revision": "satoshilabs-1", "system_user": "zcash", "version": "2.0.7-3", - "binary_url": "https://z.cash/downloads/zcash-2.1.0-linux64-debian-stretch.tar.gz", + "binary_url": "https://z.cash/downloads/zcash-2.1.0-1-linux64-debian-stretch.tar.gz", "verification_type": "sha256", "verification_source": "aec6b3c4178c5ceb4e7b7ed3aaa96078b88b872640c7bb38208d5bce48e3f75c", "extract_command": "tar -C backend --strip 1 -xf", diff --git a/configs/coins/zcash_testnet.json b/configs/coins/zcash_testnet.json index 84850a11..38a2fa4a 100644 --- a/configs/coins/zcash_testnet.json +++ b/configs/coins/zcash_testnet.json @@ -23,7 +23,7 @@ "package_revision": "satoshilabs-1", "system_user": "zcash", "version": "2.0.7-3", - "binary_url": "https://z.cash/downloads/zcash-2.1.0-linux64-debian-stretch.tar.gz", + "binary_url": "https://z.cash/downloads/zcash-2.1.0-1-linux64-debian-stretch.tar.gz", "verification_type": "sha256", "verification_source": "aec6b3c4178c5ceb4e7b7ed3aaa96078b88b872640c7bb38208d5bce48e3f75c", "extract_command": "tar -C backend --strip 1 -xf", From 7ae81a704bc81421d691e70df88f40c47b02e7c9 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Wed, 13 Nov 2019 13:43:06 +0100 Subject: [PATCH 09/31] Fix version in Zcash and Zcash-testnet configs --- configs/coins/zcash.json | 2 +- configs/coins/zcash_testnet.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/coins/zcash.json b/configs/coins/zcash.json index f190aa37..fecc9586 100644 --- a/configs/coins/zcash.json +++ b/configs/coins/zcash.json @@ -22,7 +22,7 @@ "package_name": "backend-zcash", "package_revision": "satoshilabs-1", "system_user": "zcash", - "version": "2.0.7-3", + "version": "2.1.0-1", "binary_url": "https://z.cash/downloads/zcash-2.1.0-1-linux64-debian-stretch.tar.gz", "verification_type": "sha256", "verification_source": "aec6b3c4178c5ceb4e7b7ed3aaa96078b88b872640c7bb38208d5bce48e3f75c", diff --git a/configs/coins/zcash_testnet.json b/configs/coins/zcash_testnet.json index 38a2fa4a..58d8a0cd 100644 --- a/configs/coins/zcash_testnet.json +++ b/configs/coins/zcash_testnet.json @@ -22,7 +22,7 @@ "package_name": "backend-zcash-testnet", "package_revision": "satoshilabs-1", "system_user": "zcash", - "version": "2.0.7-3", + "version": "2.1.0-1", "binary_url": "https://z.cash/downloads/zcash-2.1.0-1-linux64-debian-stretch.tar.gz", "verification_type": "sha256", "verification_source": "aec6b3c4178c5ceb4e7b7ed3aaa96078b88b872640c7bb38208d5bce48e3f75c", From f6ea86e52b127145d259932e1a3ce267b9bee228 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Thu, 14 Nov 2019 16:47:55 +0100 Subject: [PATCH 10/31] bch (+testnet): Bump backend 0.20.5 -> 0.20.6 --- configs/coins/bcash.json | 8 ++++---- configs/coins/bcash_testnet.json | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/configs/coins/bcash.json b/configs/coins/bcash.json index 4be65abe..35a2d8e5 100644 --- a/configs/coins/bcash.json +++ b/configs/coins/bcash.json @@ -22,10 +22,10 @@ "package_name": "backend-bcash", "package_revision": "satoshilabs-1", "system_user": "bcash", - "version": "0.20.5", - "binary_url": "https://download.bitcoinabc.org/0.20.5/linux/bitcoin-abc-0.20.5-x86_64-linux-gnu.tar.gz", + "version": "0.20.6", + "binary_url": "https://download.bitcoinabc.org/0.20.6/linux/bitcoin-abc-0.20.6-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "8197c0c26553d0c1dd5bc5e033aaec9dd7324ceab8218f075f7d48f4889e3aef", + "verification_source": "f5fb4a3dac6164709dbf0632f64adfe56414d260e4bf192effc0049da9c43bac", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -49,7 +49,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Bitcoin ABC:0.20.5/", + "subversion": "/Bitcoin ABC:0.20.6/", "address_format": "cashaddr", "mempool_workers": 8, "mempool_sub_workers": 2, diff --git a/configs/coins/bcash_testnet.json b/configs/coins/bcash_testnet.json index eb011390..a7c90fed 100644 --- a/configs/coins/bcash_testnet.json +++ b/configs/coins/bcash_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-bcash-testnet", "package_revision": "satoshilabs-1", "system_user": "bcash", - "version": "0.20.5", - "binary_url": "https://download.bitcoinabc.org/0.20.5/linux/bitcoin-abc-0.20.5-x86_64-linux-gnu.tar.gz", + "version": "0.20.6", + "binary_url": "https://download.bitcoinabc.org/0.20.6/linux/bitcoin-abc-0.20.6-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "8197c0c26553d0c1dd5bc5e033aaec9dd7324ceab8218f075f7d48f4889e3aef", + "verification_source": "f5fb4a3dac6164709dbf0632f64adfe56414d260e4bf192effc0049da9c43bac", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -49,7 +49,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Bitcoin ABC:0.20.5/", + "subversion": "/Bitcoin ABC:0.20.6/", "address_format": "cashaddr", "mempool_workers": 8, "mempool_sub_workers": 2, From 3853520a0fbf34bd69a3d7fae96ed917a9726d1b Mon Sep 17 00:00:00 2001 From: Liam Alford Date: Mon, 18 Nov 2019 16:51:45 +0000 Subject: [PATCH 11/31] Add DeepOnion (#298) * Add DeepOnion * Fix config bugs * Use base pack/unpck TX * Fix empty array causing test failure. * Fix config files and executable. * Fix sync issue * Fix integration tetsts --- bchain/coins/blockchain.go | 2 + bchain/coins/deeponion/deeponionparser.go | 68 ++++++ .../coins/deeponion/deeponionparser_test.go | 201 ++++++++++++++++++ bchain/coins/deeponion/deeponionrpc.go | 109 ++++++++++ build/templates/backend/config/deeponion.conf | 29 +++ configs/coins/deeponion.json | 67 ++++++ docs/ports.md | 3 +- tests/rpc/testdata/deeponion.json | 52 +++++ tests/sync/testdata/deeponion.json | 96 +++++++++ tests/tests.json | 5 + 10 files changed, 631 insertions(+), 1 deletion(-) create mode 100644 bchain/coins/deeponion/deeponionparser.go create mode 100644 bchain/coins/deeponion/deeponionparser_test.go create mode 100644 bchain/coins/deeponion/deeponionrpc.go create mode 100644 build/templates/backend/config/deeponion.conf create mode 100644 configs/coins/deeponion.json create mode 100644 tests/rpc/testdata/deeponion.json create mode 100644 tests/sync/testdata/deeponion.json diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index df1514bd..0ce5e626 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -9,6 +9,7 @@ import ( "blockbook/bchain/coins/cpuchain" "blockbook/bchain/coins/dash" "blockbook/bchain/coins/dcr" + "blockbook/bchain/coins/deeponion" "blockbook/bchain/coins/digibyte" "blockbook/bchain/coins/divi" "blockbook/bchain/coins/dogecoin" @@ -103,6 +104,7 @@ func init() { BlockChainFactories["Divi"] = divi.NewDiviRPC BlockChainFactories["CPUchain"] = cpuchain.NewCPUchainRPC BlockChainFactories["Unobtanium"] = unobtanium.NewUnobtaniumRPC + BlockChainFactories["DeepOnion"] = deeponion.NewDeepOnionRPC } // GetCoinNameFromConfig gets coin name and coin shortcut from config file diff --git a/bchain/coins/deeponion/deeponionparser.go b/bchain/coins/deeponion/deeponionparser.go new file mode 100644 index 00000000..7e63afe3 --- /dev/null +++ b/bchain/coins/deeponion/deeponionparser.go @@ -0,0 +1,68 @@ +package deeponion + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + + "github.com/martinboehm/btcd/wire" + "github.com/martinboehm/btcutil/chaincfg" +) + +// magic numbers +const ( + MainnetMagic wire.BitcoinNet = 0xf2dbf1d1 +) + +// chain parameters +var ( + MainNetParams chaincfg.Params +) + +func init() { + MainNetParams = chaincfg.MainNetParams + MainNetParams.Net = MainnetMagic + MainNetParams.PubKeyHashAddrID = []byte{31} + MainNetParams.ScriptHashAddrID = []byte{78} + MainNetParams.Bech32HRPSegwit = "dpn" +} + +// DeepOnionParser handle +type DeepOnionParser struct { + *btc.BitcoinParser + baseparser *bchain.BaseParser +} + +// NewDeepOnionParser returns new DeepOnionParser instance +func NewDeepOnionParser(params *chaincfg.Params, c *btc.Configuration) *DeepOnionParser { + return &DeepOnionParser{ + BitcoinParser: btc.NewBitcoinParser(params, c), + baseparser: &bchain.BaseParser{}, + } +} + +// GetChainParams contains network parameters for the main DeepOnion network, +func GetChainParams(chain string) *chaincfg.Params { + // register bitcoin parameters in addition to deeponion parameters + // deeponion has dual standard of addresses and we want to be able to + // parse both standards + if !chaincfg.IsRegistered(&chaincfg.MainNetParams) { + chaincfg.RegisterBitcoinParams() + } + if !chaincfg.IsRegistered(&MainNetParams) { + err := chaincfg.Register(&MainNetParams) + if err != nil { + panic(err) + } + } + return &MainNetParams +} + +// PackTx packs transaction to byte array using protobuf +func (p *DeepOnionParser) PackTx(tx *bchain.Tx, height uint32, blockTime int64) ([]byte, error) { + return p.baseparser.PackTx(tx, height, blockTime) +} + +// UnpackTx unpacks transaction from protobuf byte array +func (p *DeepOnionParser) UnpackTx(buf []byte) (*bchain.Tx, uint32, error) { + return p.baseparser.UnpackTx(buf) +} diff --git a/bchain/coins/deeponion/deeponionparser_test.go b/bchain/coins/deeponion/deeponionparser_test.go new file mode 100644 index 00000000..a19fb097 --- /dev/null +++ b/bchain/coins/deeponion/deeponionparser_test.go @@ -0,0 +1,201 @@ +// +build unittest + +package deeponion + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + "encoding/hex" + "math/big" + "os" + "reflect" + "testing" + + "github.com/martinboehm/btcutil/chaincfg" +) + +func TestMain(m *testing.M) { + c := m.Run() + chaincfg.ResetParams() + os.Exit(c) +} + + +func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) { + type args struct { + address string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "P2PKH1", + args: args{address: "DYPyxvq57iSRA5xUXzSVfsTENPz4DKFr5S"}, + want: "76a9142afc25b8b5d4ed490026d38b3b464c140a32dc7588ac", + wantErr: false, + }, + { + name: "P2PKH2", + args: args{address: "DshhBSub7vexDFNm45UtG2wBJFt8cm5Uwr"}, + want: "76a914fec0038b0db67c1b304f6c25b3e860277a96226188ac", + wantErr: false, + }, + { + name: "P2SH1", + args: args{address: "YYDTMNJmKqajnWjFPjenzs2awwE4cwYHtC"}, + want: "a91461190c0272b059b2c09b352da81b1712dd83305e87", + wantErr: false, + }, + { + name: "P2SH2", + args: args{address: "Yh1qpMEA4EFMTB4BmhkeyivJ92WiGr3ETX"}, + want: "a914c19ff0bfc8f4387bee48e2cd3628bf72f7053cd787", + wantErr: false, + }, + } + parser := NewDeepOnionParser(GetChainParams("main"), &btc.Configuration{}) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := parser.GetAddrDescFromAddress(tt.args.address) + if (err != nil) != tt.wantErr { + t.Errorf("GetAddrDescFromAddress() error = %v, wantErr %v", err, tt.wantErr) + return + } + h := hex.EncodeToString(got) + if !reflect.DeepEqual(h, tt.want) { + t.Errorf("GetAddrDescFromAddress() = %v, want %v", h, tt.want) + } + }) + } +} + +var ( + testTx1 bchain.Tx + + testTxPacked1 = "0a206ba18524d81af732d0226ffdb63d2bcdc0d58a35ac97b5ad731057932d324e1412b401010000001134415d0114caae2bf9a7808aee0798e6245a347405d46c8131dbf55cbbbc689bbee367e902000000484730440220280f3fa80b4e93834fe0a8d9884105310eaa8d36d77b9aff113b6c498138e5bb02204578409f0a14fa1950ea4951314fd495fd503b42a6325efb5c139a6c8253912401ffffffff0200000000000000000005f22f5904000000232102bdb95d89f07e3a29305f3c8de86ec211ed77b7e15cf314c85c532a6b71c2ce07ac000000001891e884ea05200028b88a5432760a001220e967e3be9b68bcbb5cf5db31816cd40574345a24e69807ee8a80a7f92baeca14180222484730440220280f3fa80b4e93834fe0a8d9884105310eaa8d36d77b9aff113b6c498138e5bb02204578409f0a14fa1950ea4951314fd495fd503b42a6325efb5c139a6c825391240128ffffffff0f3a0210003a520a0504583af7fb10011a232102bdb95d89f07e3a29305f3c8de86ec211ed77b7e15cf314c85c532a6b71c2ce07ac2222446d343835624e4a6169474a6d4556746832426e5a345931796763756644736934454001" +) + +func init() { + testTx1 = bchain.Tx{ + Hex: "010000001134415d0114caae2bf9a7808aee0798e6245a347405d46c8131dbf55cbbbc689bbee367e902000000484730440220280f3fa80b4e93834fe0a8d9884105310eaa8d36d77b9aff113b6c498138e5bb02204578409f0a14fa1950ea4951314fd495fd503b42a6325efb5c139a6c8253912401ffffffff0200000000000000000005f22f5904000000232102bdb95d89f07e3a29305f3c8de86ec211ed77b7e15cf314c85c532a6b71c2ce07ac00000000", + Blocktime: 1564554257, + Txid: "6ba18524d81af732d0226ffdb63d2bcdc0d58a35ac97b5ad731057932d324e14", + LockTime: 0, + Time: 1564554257, + Version: 1, + Vin: []bchain.Vin{ + { + ScriptSig: bchain.ScriptSig{ + Hex: "4730440220280f3fa80b4e93834fe0a8d9884105310eaa8d36d77b9aff113b6c498138e5bb02204578409f0a14fa1950ea4951314fd495fd503b42a6325efb5c139a6c8253912401", + }, + Txid: "e967e3be9b68bcbb5cf5db31816cd40574345a24e69807ee8a80a7f92baeca14", + Vout: 2, + Sequence: 4294967295, + }, + }, + Vout: []bchain.Vout{ + { + ValueSat: *big.NewInt(0), + N: 0, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "", + }, + }, + { + ValueSat: *big.NewInt(18660128763), + N: 1, + ScriptPubKey: bchain.ScriptPubKey{ + Hex: "2102bdb95d89f07e3a29305f3c8de86ec211ed77b7e15cf314c85c532a6b71c2ce07ac", + Addresses: []string{ + "Dm485bNJaiGJmEVth2BnZ4Y1ygcufDsi4E", + }, + }, + }, + }, + } +} + +func Test_PackTx(t *testing.T) { + type args struct { + tx bchain.Tx + height uint32 + blockTime int64 + parser *DeepOnionParser + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "deeponion-1", + args: args{ + tx: testTx1, + height: 1377592, + blockTime: 1564554257, + parser: NewDeepOnionParser(GetChainParams("main"), &btc.Configuration{}), + }, + want: testTxPacked1, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := tt.args.parser.PackTx(&tt.args.tx, tt.args.height, tt.args.blockTime) + if (err != nil) != tt.wantErr { + t.Errorf("packTx() error = %v, wantErr %v", err, tt.wantErr) + return + } + h := hex.EncodeToString(got) + if !reflect.DeepEqual(h, tt.want) { + t.Errorf("packTx() = %v, want %v", h, tt.want) + } + }) + } +} + +func Test_UnpackTx(t *testing.T) { + type args struct { + packedTx string + parser *DeepOnionParser + } + tests := []struct { + name string + args args + want *bchain.Tx + want1 uint32 + wantErr bool + }{ + { + name: "deeponion-1", + args: args{ + packedTx: testTxPacked1, + parser: NewDeepOnionParser(GetChainParams("main"), &btc.Configuration{}), + }, + want: &testTx1, + want1: 1377592, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + b, _ := hex.DecodeString(tt.args.packedTx) + got, got1, err := tt.args.parser.UnpackTx(b) + if (err != nil) != tt.wantErr { + t.Errorf("unpackTx(1) error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("unpackTx(2) got = %v, want %v", got, tt.want) + } + if got1 != tt.want1 { + t.Errorf("unpackTx(3) got1 = %v, want %v", got1, tt.want1) + } + }) + } +} diff --git a/bchain/coins/deeponion/deeponionrpc.go b/bchain/coins/deeponion/deeponionrpc.go new file mode 100644 index 00000000..6fab0c49 --- /dev/null +++ b/bchain/coins/deeponion/deeponionrpc.go @@ -0,0 +1,109 @@ +package deeponion + +import ( + "blockbook/bchain" + "blockbook/bchain/coins/btc" + "encoding/json" + + "github.com/golang/glog" + "github.com/juju/errors" +) + +// DeepOnionRPC is an interface to JSON-RPC bitcoind service. +type DeepOnionRPC struct { + *btc.BitcoinRPC +} + +// NewDeepOnionRPC returns new DeepOnionRPC instance. +func NewDeepOnionRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { + b, err := btc.NewBitcoinRPC(config, pushHandler) + if err != nil { + return nil, err + } + + s := &DeepOnionRPC{ + b.(*btc.BitcoinRPC), + } + s.RPCMarshaler = btc.JSONMarshalerV2{} + s.ChainConfig.SupportsEstimateFee = false + + return s, nil +} + +// Initialize initializes DeepOnionRPC instance. +func (b *DeepOnionRPC) Initialize() error { + ci, err := b.GetChainInfo() + if err != nil { + return err + } + chainName := ci.Chain + + glog.Info("Chain name ", chainName) + params := GetChainParams(chainName) + + // always create parser + b.Parser = NewDeepOnionParser(params, b.ChainConfig) + + // parameters for getInfo request + if params.Net == MainnetMagic { + b.Testnet = false + b.Network = "livenet" + } else { + b.Testnet = true + b.Network = "testnet" + } + + glog.Info("rpc: block chain ", params.Name) + + return nil +} + +// GetBlock returns block with given hash. +func (s *DeepOnionRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) { + var err error + if hash == "" && height > 0 { + hash, err = s.GetBlockHash(height) + if err != nil { + return nil, err + } + } + + glog.V(1).Info("rpc: getblock (verbosity=1) ", hash) + + res := btc.ResGetBlockThin{} + req := btc.CmdGetBlock{Method: "getblock"} + req.Params.BlockHash = hash + req.Params.Verbosity = 1 + err = s.Call(&req, &res) + + if err != nil { + return nil, errors.Annotatef(err, "hash %v", hash) + } + if res.Error != nil { + return nil, errors.Annotatef(res.Error, "hash %v", hash) + } + + txs := make([]bchain.Tx, 0, len(res.Result.Txids)) + for _, txid := range res.Result.Txids { + tx, err := s.GetTransaction(txid) + if err != nil { + if err == bchain.ErrTxNotFound { + glog.Errorf("rpc: getblock: skipping transanction in block %s due error: %s", hash, err) + continue + } + return nil, err + } + txs = append(txs, *tx) + } + block := &bchain.Block{ + BlockHeader: res.Result.BlockHeader, + Txs: txs, + } + return block, nil +} + +// GetTransactionForMempool returns a transaction by the transaction ID. +// It could be optimized for mempool, i.e. without block time and confirmations +func (s *DeepOnionRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) { + return s.GetTransaction(txid) +} diff --git a/build/templates/backend/config/deeponion.conf b/build/templates/backend/config/deeponion.conf new file mode 100644 index 00000000..ca92d14f --- /dev/null +++ b/build/templates/backend/config/deeponion.conf @@ -0,0 +1,29 @@ +{{define "main" -}} +daemon=1 +server=1 +{{if .Backend.Mainnet}}mainnet=1{{else}}testnet=1{{end}} +rpcuser={{.IPC.RPCUser}} +rpcpassword={{.IPC.RPCPass}} +rpcport={{.Ports.BackendRPC}} +txindex=1 + +zmqpubhashtx={{template "IPC.MessageQueueBindingTemplate" .}} +zmqpubhashblock={{template "IPC.MessageQueueBindingTemplate" .}} + +rpcworkqueue=1100 +maxmempool=2000 +dbcache=1000 + +{{- if .Backend.AdditionalParams}} +# generated from additional_params +{{- range $name, $value := .Backend.AdditionalParams}} +{{- if eq $name "addnode"}} +{{- range $index, $node := $value}} +addnode={{$node}} +{{- end}} +{{- else}} +{{$name}}={{$value}} +{{- end}} +{{- end}} +{{- end}} +{{end}} diff --git a/configs/coins/deeponion.json b/configs/coins/deeponion.json new file mode 100644 index 00000000..d5c42fd2 --- /dev/null +++ b/configs/coins/deeponion.json @@ -0,0 +1,67 @@ +{ + "coin": { + "name": "DeepOnion", + "shortcut": "ONION", + "label": "DeepOnion", + "alias": "deeponion" + }, + "ports": { + "backend_rpc": 8091, + "backend_message_queue": 38391, + "blockbook_internal": 9091, + "blockbook_public": 9191 + }, + "ipc": { + "rpc_url_template": "http://127.0.0.1:{{.Ports.BackendRPC}}", + "rpc_user": "rpc", + "rpc_pass": "rpc", + "rpc_timeout": 25, + "message_queue_binding_template": "tcp://127.0.0.1:{{.Ports.BackendMessageQueue}}" + }, + "backend": { + "package_name": "backend-deeponion", + "package_revision": "satoshilabs-1", + "system_user": "deeponion", + "version": "2.0.5", + "binary_url": "https://github.com/deeponion/deeponion/releases/download/v2.0.5/deeponion-2.0.5-x86_64-linux-gnu.tar.gz", + "extract_command": "tar -C backend --strip 1 -xpf", + "exclude_files": [ + ], + "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/DeepOniond -datadir={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend -conf={{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf -pid=/run/{{.Coin.Alias}}/{{.Coin.Alias}}.pid", + "logrotate_files_template": "{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/*.log", + "postinst_script_template": "", + "service_type": "forking", + "service_additional_params_template": "", + "protect_memory": true, + "mainnet": true, + "server_config_file": "deeponion.conf", + "client_config_file": "bitcoin_like_client.conf", + "additional_params": { + "whitelist": "127.0.0.1" + } + }, + "blockbook": { + "package_name": "blockbook-deeponion", + "system_user": "blockbook-deeponion", + "internal_binding_template": ":{{.Ports.BlockbookInternal}}", + "public_binding_template": ":{{.Ports.BlockbookPublic}}", + "explorer_url": "", + "additional_params": "", + "block_chain": { + "parse": true, + "subversion": "/DeepOnionCore:2.0.5/", + "mempool_workers": 8, + "mempool_sub_workers": 2, + "block_addresses_to_keep": 300, + "xpub_magic": 27108450, + "xpub_magic_segwit_p2sh": 28471030, + "xpub_magic_segwit_native": 78792518, + "slip44": 305, + "additional_params": {} + } + }, + "meta": { + "package_maintainer": "DeepOnion", + "package_maintainer_email": "info@deeponion.org" + } +} diff --git a/docs/ports.md b/docs/ports.md index 835d5e07..0c63c18b 100644 --- a/docs/ports.md +++ b/docs/ports.md @@ -8,7 +8,7 @@ | Dash | 9033 | 9133 | 8033 | 38333 | | Litecoin | 9034 | 9134 | 8034 | 38334 | | Bitcoin Gold | 9035 | 9135 | 8035 | 38335 | -| Ethereum | 9036 | 9136 | 8036 | 8136 http, 38336 p2p | +| Ethereum | 9036 | 9136 | 8036 | 38336 p2p, 8136 http | | Ethereum Classic | 9037 | 9137 | 8037 | | | Dogecoin | 9038 | 9138 | 8038 | 38338 | | Namecoin | 9039 | 9139 | 8039 | 38339 | @@ -38,6 +38,7 @@ | Qtum | 9088 | 9188 | 8088 | 38388 | | Divi Project | 9089 | 9189 | 8089 | 38389 | | CPUchain | 9090 | 9190 | 8090 | 38390 | +| DeepOnion | 9091 | 9191 | 8091 | 38391 | | Unobtanium | 9092 | 9192 | 65535 | 38392 | | Bitcoin Testnet | 19030 | 19130 | 18030 | 48330 | | Bitcoin Cash Testnet | 19031 | 19131 | 18031 | 48331 | diff --git a/tests/rpc/testdata/deeponion.json b/tests/rpc/testdata/deeponion.json new file mode 100644 index 00000000..4fe9943d --- /dev/null +++ b/tests/rpc/testdata/deeponion.json @@ -0,0 +1,52 @@ +{ + "blockHeight": 1377592, + "blockHash": "9993684c15a793130f43120839e5c2c711907631ef4ad7b43ba535322e4c6649", + "blockTime": 1564554257, + "blockTxs": [ + "200b681e57d19131a87c3aa4172b9e2e128cc48ecdf54cc91dcbc44e96e8f7cf", + "6ba18524d81af732d0226ffdb63d2bcdc0d58a35ac97b5ad731057932d324e14" + ], + "txDetails": { + "e967e3be9b68bcbb5cf5db31816cd40574345a24e69807ee8a80a7f92baeca14": { + "hex": "0100000015cc175d016012730925e8e7eaff1a7cbd18e255f749e936730c001ca4b900a9a93230abbd0100000048473044022066a828d9d7d3e03dba2ad028bfdcad4e989ab76f11a7a033702759c37525bd8502206480c14e3c39a1d244e00c4113557bd9651d8b2b944426d88f8d7f95f8957c5601ffffffff03000000000000000000c0be295804000000232102bdb95d89f07e3a29305f3c8de86ec211ed77b7e15cf314c85c532a6b71c2ce07acfbf73a5804000000232102bdb95d89f07e3a29305f3c8de86ec211ed77b7e15cf314c85c532a6b71c2ce07ac00000000", + "txid": "e967e3be9b68bcbb5cf5db31816cd40574345a24e69807ee8a80a7f92baeca14", + "blocktime": 1561840661, + "time": 1561840661, + "locktime": 0, + "version": 1, + "vin": [ + { + "txid": "bdab3032a9a900b9a41c000c7336e949f755e218bd7c1affeae7e82509731260", + "vout": 1, + "scriptSig": { + "hex": "473044022066a828d9d7d3e03dba2ad028bfdcad4e989ab76f11a7a033702759c37525bd8502206480c14e3c39a1d244e00c4113557bd9651d8b2b944426d88f8d7f95f8957c5601" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "hex": "" + } + }, + { + "value": 186.59, + "n": 1, + "scriptPubKey": { + "hex": "2102bdb95d89f07e3a29305f3c8de86ec211ed77b7e15cf314c85c532a6b71c2ce07ac" + } + }, + { + "value": 186.60128763, + "n": 2, + "scriptPubKey": { + "hex": "2102bdb95d89f07e3a29305f3c8de86ec211ed77b7e15cf314c85c532a6b71c2ce07ac" + } + } + ] + } + } +} diff --git a/tests/sync/testdata/deeponion.json b/tests/sync/testdata/deeponion.json new file mode 100644 index 00000000..b307dca7 --- /dev/null +++ b/tests/sync/testdata/deeponion.json @@ -0,0 +1,96 @@ +{ + "connectBlocks": { + "syncRanges": [ + {"lower": 1003776, "upper": 1003796} + ], + "blocks": { + "1003776": { + "height": 1003776, + "hash": "b9775282a6def6a186d29584af8907c991e27e91603ce461bf5c79890f020a45", + "noTxs": 2, + "txDetails": [ + { + "txid": "9f3400d241a594a5d7b039cad7c535226d481e486c8e54cf0e88d47149a53a79", + "version": 1, + "vin": [ + { + "txid": "c2b57977801b69472ac635e2d53cb53e652ff432caa91c47ae9c70bc8d4b27a6", + "vout": 0, + "scriptSig": { + "hex": "47304402203e68a85b0ae7fd4f6b4ab6abe44e091d08aba37dd787fc271467ffaee8c9733402205264badf478dbc18051331b2f53a43447f53f950ea98db5fdcca28ef179c122201" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "hex": "" + } + }, + { + "value": 118.27, + "n": 1, + "scriptPubKey": { + "hex": "2103fb4259bbe5c1e956a6b804ab19812f0cd0938cf6151be81aa14e3ffa955dfcd6ac" + } + }, + { + "value": 118.28219178, + "n": 2, + "scriptPubKey": { + "hex": "2103fb4259bbe5c1e956a6b804ab19812f0cd0938cf6151be81aa14e3ffa955dfcd6ac" + } + } + ], + "hex": "010000006eed435c01a6274b8dbc709cae471ca9ca32f42f653eb53cd5e235c62a47691b807779b5c2010000004847304402203e68a85b0ae7fd4f6b4ab6abe44e091d08aba37dd787fc271467ffaee8c9733402205264badf478dbc18051331b2f53a43447f53f950ea98db5fdcca28ef179c122201ffffffff03000000000000000000c0b2f1c002000000232103fb4259bbe5c1e956a6b804ab19812f0cd0938cf6151be81aa14e3ffa955dfcd6ac2a4d04c102000000232103fb4259bbe5c1e956a6b804ab19812f0cd0938cf6151be81aa14e3ffa955dfcd6ac00000000", + "time": 1547955566, + "blocktime": 1547955566 + } + ] + }, + "1003796": { + "height": 1003796, + "hash": "8ec7b5006dd4b6683c6b58185064e94ab0b87f083ed4e58706f6f928cb4f9d58", + "noTxs": 2, + "txDetails": [ + { + "txid": "1d8a926a59f64b0b5a5efcb3872801f74dfe30d0ed68330bd98295f05f6c0580", + "version": 1, + "vin": [ + { + "txid": "7807e471847d0f66616653601d02b2ea482e97385d2c03daec77e000b62c10a1", + "vout": 1, + "scriptSig": { + "hex": "473044022033a999110dcadb95223db2028f5fcbf3a5b37ec48498ec4678eaff0f6c8787b002207100681343a265c9995681702f3694cbbffaadaf1bc42a3b6fd69e3a79896f1701" + }, + "sequence": 4294967295 + } + ], + "vout": [ + { + "value": 0.00000000, + "n": 0, + "scriptPubKey": { + "hex": "" + } + }, + { + "value": 459.47739724, + "n": 1, + "scriptPubKey": { + "hex": "21025f48dc22185bc3f9428068600d779b9bbbe208a49ffbbe6af551000e70979cb7ac" + } + } + ], + "hex": "010000006eed435c01a6274b8dbc709cae471ca9ca32f42f653eb53cd5e235c62a47691b807779b5c2010000004847304402203e68a85b0ae7fd4f6b4ab6abe44e091d08aba37dd787fc271467ffaee8c9733402205264badf478dbc18051331b2f53a43447f53f950ea98db5fdcca28ef179c122201ffffffff03000000000000000000c0b2f1c002000000232103fb4259bbe5c1e956a6b804ab19812f0cd0938cf6151be81aa14e3ffa955dfcd6ac2a4d04c102000000232103fb4259bbe5c1e956a6b804ab19812f0cd0938cf6151be81aa14e3ffa955dfcd6ac00000000", + "time": 1547956478, + "blocktime": 1547956478 + } + ] + } + } + } +} diff --git a/tests/tests.json b/tests/tests.json index d555f383..7f935426 100644 --- a/tests/tests.json +++ b/tests/tests.json @@ -52,6 +52,11 @@ "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"], "sync": ["ConnectBlocksParallel", "ConnectBlocks"] }, + "deeponion": { + "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync", + "EstimateSmartFee", "EstimateFee"], + "sync": ["ConnectBlocksParallel", "ConnectBlocks"] + }, "digibyte": { "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync", "EstimateSmartFee", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"] From d26e1fbb3b85d170b8f8fd9b522f2ee870032c10 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Mon, 18 Nov 2019 19:43:02 +0100 Subject: [PATCH 12/31] doge: Bump backend 0.14.0 -> 0.14.2 --- configs/coins/dogecoin.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configs/coins/dogecoin.json b/configs/coins/dogecoin.json index 17f26379..7ed865c6 100644 --- a/configs/coins/dogecoin.json +++ b/configs/coins/dogecoin.json @@ -22,10 +22,10 @@ "package_name": "backend-dogecoin", "package_revision": "satoshilabs-1", "system_user": "dogecoin", - "version": "1.14.0", - "binary_url": "https://github.com/dogecoin/dogecoin/releases/download/v1.14.0/dogecoin-1.14.0-x86_64-linux-gnu.tar.gz", + "version": "1.14.2", + "binary_url": "https://github.com/dogecoin/dogecoin/releases/download/v1.14.2/dogecoin-1.14.2-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "ed7baccafab98b5ce452bd3fd2cf7ab5e757269105350283e2bab91e4ccb7366", + "verification_source": "10c400c8f2039b1f804b8a533266201a9e4e3b32a8854501e8a43792e1ee78e6", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/dogecoin-qt" From e754a6c0fdcb0e5c87768ba0b622340359064f62 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Tue, 19 Nov 2019 11:13:15 +0100 Subject: [PATCH 13/31] Fix incorrect registration of network params in unobtanium and viacoin --- bchain/coins/dogecoin/dogecoinparser_test.go | 81 ++++++++++++++++++++ bchain/coins/unobtanium/unobtaniumparser.go | 12 +-- bchain/coins/viacoin/viacoinparser.go | 19 +++-- 3 files changed, 99 insertions(+), 13 deletions(-) diff --git a/bchain/coins/dogecoin/dogecoinparser_test.go b/bchain/coins/dogecoin/dogecoinparser_test.go index 5738290a..e2803fd3 100644 --- a/bchain/coins/dogecoin/dogecoinparser_test.go +++ b/bchain/coins/dogecoin/dogecoinparser_test.go @@ -46,6 +46,12 @@ func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) { want: "76a914efb6158f75743c611858fdfd0f4aaec6cc6196bc88ac", wantErr: false, }, + { + name: "P2PKH3", + args: args{address: "DHobAps6DjZ5n4xMV75n7kJv299Zi85FCG"}, + want: "76a9148ae937291e72f7368421dbaa966c44950eb14db788ac", + wantErr: false, + }, { name: "P2SH1", args: args{address: "9tg1kVUk339Tk58ewu5T8QT82Z6cE4UvSU"}, @@ -76,6 +82,81 @@ func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) { } } +func Test_GetAddressesFromAddrDesc_Mainnet(t *testing.T) { + type args struct { + script string + } + tests := []struct { + name string + args args + want []string + want2 bool + wantErr bool + }{ + { + name: "P2PKH1", + args: args{script: "76a9148841590909747c0f97af158f22fadacb1652522088ac"}, + want: []string{"DHZYinsaM9nW5piCMN639ELRKbZomThPnZ"}, + want2: true, + wantErr: false, + }, + { + name: "P2PKH2", + args: args{script: "76a914efb6158f75743c611858fdfd0f4aaec6cc6196bc88ac"}, + want: []string{"DSzaAYEYyy9ngjoJ294r7jzFM3xhD6bKHK"}, + want2: true, + wantErr: false, + }, + { + name: "P2PKH3", + args: args{script: "76a91450e86eeac599ad023b8981296d01b50bdabcdd9788ac"}, + want: []string{"DCWu3MLz9xBGFuuLyNDf6QjuGp49f5tfc9"}, + want2: true, + wantErr: false, + }, + { + name: "P2SH1", + args: args{script: "a9141889a089400ea25d28694fd98aa7702b21eeeab187"}, + want: []string{"9tg1kVUk339Tk58ewu5T8QT82Z6cE4UvSU"}, + want2: true, + wantErr: false, + }, + { + name: "OP_RETURN ascii", + args: args{script: "6a0461686f6a"}, + want: []string{"OP_RETURN (ahoj)"}, + want2: false, + wantErr: false, + }, + { + name: "OP_RETURN hex", + args: args{script: "6a072020f1686f6a20"}, + want: []string{"OP_RETURN 2020f1686f6a20"}, + want2: false, + wantErr: false, + }, + } + + parser := NewDogecoinParser(GetChainParams("main"), &btc.Configuration{}) + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + b, _ := hex.DecodeString(tt.args.script) + got, got2, err := parser.GetAddressesFromAddrDesc(b) + if (err != nil) != tt.wantErr { + t.Errorf("GetAddressesFromAddrDesc() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got, tt.want) + } + if !reflect.DeepEqual(got2, tt.want2) { + t.Errorf("GetAddressesFromAddrDesc() = %v, want %v", got2, tt.want2) + } + }) + } +} + var ( testTx1 bchain.Tx testTxPacked1 = "00030e6d8ba8d7aa2001000000016b3c0c53267964120acf7f7e72217e3f463e52ce622f89659f6a6bb8e69a4d91000000006c493046022100a96454237e3a020994534583e28c04757881374bceac89f933ea9ff00b4db259022100fbb757ff7ea4f02c4e42556b2834c61eba1f1af605db089d836a0614d90a3b46012103cebdde6d1046e285df4f48497bc50dc20a4a258ca5b7308cb0a929c9fdadcd9dffffffff0217e823ca7f0200001976a914eef21768a546590993e313c7f3dfadf6a6efa1e888acaddf4cba010000001976a914e0fee2ea29dd9c6c759d8341bd0da4c4f738cced88ac00000000" diff --git a/bchain/coins/unobtanium/unobtaniumparser.go b/bchain/coins/unobtanium/unobtaniumparser.go index eac2cc95..aab02aa4 100644 --- a/bchain/coins/unobtanium/unobtaniumparser.go +++ b/bchain/coins/unobtanium/unobtaniumparser.go @@ -27,11 +27,6 @@ func init() { // Mainnet address encoding magics MainNetParams.PubKeyHashAddrID = []byte{130} MainNetParams.ScriptHashAddrID = []byte{30} - - err := chaincfg.Register(&MainNetParams) - if err != nil { - panic(err) - } } // UnobtaniumParser handle @@ -44,7 +39,14 @@ func NewUnobtaniumParser(params *chaincfg.Params, c *btc.Configuration) *Unobtan return &UnobtaniumParser{BitcoinParser: btc.NewBitcoinParser(params, c)} } +// GetChainParams returns network parameters func GetChainParams(chain string) *chaincfg.Params { + if !chaincfg.IsRegistered(&MainNetParams) { + err := chaincfg.Register(&MainNetParams) + if err != nil { + panic(err) + } + } switch chain { default: return &MainNetParams diff --git a/bchain/coins/viacoin/viacoinparser.go b/bchain/coins/viacoin/viacoinparser.go index d0583ecd..3617e90a 100644 --- a/bchain/coins/viacoin/viacoinparser.go +++ b/bchain/coins/viacoin/viacoinparser.go @@ -38,14 +38,6 @@ func init() { RegtestParams.PubKeyHashAddrID = []byte{111} // base58 prefix: m or n RegtestParams.ScriptHashAddrID = []byte{196} // base58 prefix: 2 RegtestParams.Bech32HRPSegwit = "tvia" - - err := chaincfg.Register(&MainNetParams) - if err == nil { - err = chaincfg.Register(&RegtestParams) - } - if err != nil { - panic(err) - } } // ViacoinParser handle @@ -58,7 +50,18 @@ func NewViacoinParser(params *chaincfg.Params, c *btc.Configuration) *ViacoinPar return &ViacoinParser{BitcoinParser: btc.NewBitcoinParser(params, c)} } +// GetChainParams returns network parameters func GetChainParams(chain string) *chaincfg.Params { + if !chaincfg.IsRegistered(&MainNetParams) { + err := chaincfg.Register(&MainNetParams) + if err == nil { + err = chaincfg.Register(&RegtestParams) + } + if err != nil { + panic(err) + } + } + switch chain { case "regtest": return &RegtestParams From 5600e0d30a35f61853a64020a9f394d7b85fde2d Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Tue, 19 Nov 2019 11:15:00 +0100 Subject: [PATCH 14/31] Fix formatting/linting issues --- bchain/coins/blockchain.go | 4 +- bchain/coins/deeponion/deeponionparser.go | 6 +- .../coins/deeponion/deeponionparser_test.go | 3 +- bchain/coins/deeponion/deeponionrpc.go | 74 +++++++++---------- 4 files changed, 43 insertions(+), 44 deletions(-) diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index 0ce5e626..328ddeb5 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -9,7 +9,7 @@ import ( "blockbook/bchain/coins/cpuchain" "blockbook/bchain/coins/dash" "blockbook/bchain/coins/dcr" - "blockbook/bchain/coins/deeponion" + "blockbook/bchain/coins/deeponion" "blockbook/bchain/coins/digibyte" "blockbook/bchain/coins/divi" "blockbook/bchain/coins/dogecoin" @@ -104,7 +104,7 @@ func init() { BlockChainFactories["Divi"] = divi.NewDiviRPC BlockChainFactories["CPUchain"] = cpuchain.NewCPUchainRPC BlockChainFactories["Unobtanium"] = unobtanium.NewUnobtaniumRPC - BlockChainFactories["DeepOnion"] = deeponion.NewDeepOnionRPC + BlockChainFactories["DeepOnion"] = deeponion.NewDeepOnionRPC } // GetCoinNameFromConfig gets coin name and coin shortcut from config file diff --git a/bchain/coins/deeponion/deeponionparser.go b/bchain/coins/deeponion/deeponionparser.go index 7e63afe3..fedfdeea 100644 --- a/bchain/coins/deeponion/deeponionparser.go +++ b/bchain/coins/deeponion/deeponionparser.go @@ -1,7 +1,7 @@ package deeponion import ( - "blockbook/bchain" + "blockbook/bchain" "blockbook/bchain/coins/btc" "github.com/martinboehm/btcd/wire" @@ -35,8 +35,8 @@ type DeepOnionParser struct { // NewDeepOnionParser returns new DeepOnionParser instance func NewDeepOnionParser(params *chaincfg.Params, c *btc.Configuration) *DeepOnionParser { return &DeepOnionParser{ - BitcoinParser: btc.NewBitcoinParser(params, c), - baseparser: &bchain.BaseParser{}, + BitcoinParser: btc.NewBitcoinParser(params, c), + baseparser: &bchain.BaseParser{}, } } diff --git a/bchain/coins/deeponion/deeponionparser_test.go b/bchain/coins/deeponion/deeponionparser_test.go index a19fb097..94c5594f 100644 --- a/bchain/coins/deeponion/deeponionparser_test.go +++ b/bchain/coins/deeponion/deeponionparser_test.go @@ -20,7 +20,6 @@ func TestMain(m *testing.M) { os.Exit(c) } - func Test_GetAddrDescFromAddress_Mainnet(t *testing.T) { type args struct { address string @@ -191,7 +190,7 @@ func Test_UnpackTx(t *testing.T) { return } if !reflect.DeepEqual(got, tt.want) { - t.Errorf("unpackTx(2) got = %v, want %v", got, tt.want) + t.Errorf("unpackTx(2) got = %v, want %v", got, tt.want) } if got1 != tt.want1 { t.Errorf("unpackTx(3) got1 = %v, want %v", got1, tt.want1) diff --git a/bchain/coins/deeponion/deeponionrpc.go b/bchain/coins/deeponion/deeponionrpc.go index 6fab0c49..b651f93b 100644 --- a/bchain/coins/deeponion/deeponionrpc.go +++ b/bchain/coins/deeponion/deeponionrpc.go @@ -60,50 +60,50 @@ func (b *DeepOnionRPC) Initialize() error { // GetBlock returns block with given hash. func (s *DeepOnionRPC) GetBlock(hash string, height uint32) (*bchain.Block, error) { - var err error - if hash == "" && height > 0 { - hash, err = s.GetBlockHash(height) - if err != nil { - return nil, err - } - } + var err error + if hash == "" && height > 0 { + hash, err = s.GetBlockHash(height) + if err != nil { + return nil, err + } + } - glog.V(1).Info("rpc: getblock (verbosity=1) ", hash) + glog.V(1).Info("rpc: getblock (verbosity=1) ", hash) - res := btc.ResGetBlockThin{} - req := btc.CmdGetBlock{Method: "getblock"} - req.Params.BlockHash = hash - req.Params.Verbosity = 1 - err = s.Call(&req, &res) + res := btc.ResGetBlockThin{} + req := btc.CmdGetBlock{Method: "getblock"} + req.Params.BlockHash = hash + req.Params.Verbosity = 1 + err = s.Call(&req, &res) - if err != nil { - return nil, errors.Annotatef(err, "hash %v", hash) - } - if res.Error != nil { - return nil, errors.Annotatef(res.Error, "hash %v", hash) - } + if err != nil { + return nil, errors.Annotatef(err, "hash %v", hash) + } + if res.Error != nil { + return nil, errors.Annotatef(res.Error, "hash %v", hash) + } - txs := make([]bchain.Tx, 0, len(res.Result.Txids)) - for _, txid := range res.Result.Txids { - tx, err := s.GetTransaction(txid) - if err != nil { - if err == bchain.ErrTxNotFound { - glog.Errorf("rpc: getblock: skipping transanction in block %s due error: %s", hash, err) - continue - } - return nil, err - } - txs = append(txs, *tx) - } - block := &bchain.Block{ - BlockHeader: res.Result.BlockHeader, - Txs: txs, - } - return block, nil + txs := make([]bchain.Tx, 0, len(res.Result.Txids)) + for _, txid := range res.Result.Txids { + tx, err := s.GetTransaction(txid) + if err != nil { + if err == bchain.ErrTxNotFound { + glog.Errorf("rpc: getblock: skipping transanction in block %s due error: %s", hash, err) + continue + } + return nil, err + } + txs = append(txs, *tx) + } + block := &bchain.Block{ + BlockHeader: res.Result.BlockHeader, + Txs: txs, + } + return block, nil } // GetTransactionForMempool returns a transaction by the transaction ID. // It could be optimized for mempool, i.e. without block time and confirmations func (s *DeepOnionRPC) GetTransactionForMempool(txid string) (*bchain.Tx, error) { - return s.GetTransaction(txid) + return s.GetTransaction(txid) } From da714b529911bd02eeca150a66e6397758c59153 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Tue, 19 Nov 2019 11:56:40 +0100 Subject: [PATCH 15/31] Fix error message informing about missing Ethereum xpub support #314 --- server/public.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/server/public.go b/server/public.go index 49b728d9..50cc3567 100644 --- a/server/public.go +++ b/server/public.go @@ -684,6 +684,9 @@ func (s *PublicServer) explorerXpub(w http.ResponseWriter, r *http.Request) (tpl // do not allow txsOnPage and details to be changed by query params address, err := s.api.GetXpubAddress(xpub, page, txsOnPage, api.AccountDetailsTxHistoryLight, filter, gap) if err != nil { + if err == api.ErrUnsupportedXpub { + err = api.NewAPIError("XPUB functionality is not supported", true) + } return errorTpl, nil, err } data := s.newTemplateData() @@ -994,6 +997,9 @@ func (s *PublicServer) apiXpub(r *http.Request, apiVersion int) (interface{}, er if err == nil && apiVersion == apiV1 { return s.api.AddressToV1(address), nil } + if err == api.ErrUnsupportedXpub { + err = api.NewAPIError("XPUB functionality is not supported", true) + } return address, err } From bf3d822b873a4b646152de3b30f306839b149486 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Tue, 19 Nov 2019 08:46:47 +0100 Subject: [PATCH 16/31] Add filter from-to to balance history --- api/types.go | 1 - api/worker.go | 58 ++++++++++++++++----------------- common/internalstate.go | 50 ++++++++++++++++++++++++++++ db/bulkconnect.go | 6 ++++ db/rocksdb.go | 38 +++++++++++++++++++-- db/rocksdb_ethereumtype.go | 1 + db/rocksdb_ethereumtype_test.go | 20 ++++++++++++ db/rocksdb_test.go | 28 ++++++++++++++++ server/public.go | 11 ++++++- server/public_test.go | 11 +++++-- 10 files changed, 188 insertions(+), 36 deletions(-) diff --git a/api/types.go b/api/types.go index 5d739846..4e9f22fa 100644 --- a/api/types.go +++ b/api/types.go @@ -302,7 +302,6 @@ type BalanceHistory struct { Txs int `json:"txs"` ReceivedSat *Amount `json:"received"` SentSat *Amount `json:"sent"` - BalanceSat *Amount `json:"balance"` } // Blocks is list of blocks with paging information diff --git a/api/worker.go b/api/worker.go index 7ad85f4b..71b87097 100644 --- a/api/worker.go +++ b/api/worker.go @@ -802,17 +802,26 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco } // GetBalanceHistory returns history of balance for given address -func (w *Worker) GetBalanceHistory(address string) ([]BalanceHistory, error) { - var bh []BalanceHistory - var b BalanceHistory - var bi *db.BlockInfo - var balance big.Int +func (w *Worker) GetBalanceHistory(address string, fromTime, toTime time.Time) ([]BalanceHistory, error) { + var bhs []BalanceHistory + bh := BalanceHistory{ + SentSat: &Amount{}, + ReceivedSat: &Amount{}, + } start := time.Now() addrDesc, _, err := w.getAddrDescAndNormalizeAddress(address) if err != nil { return nil, err } - txs, err := w.getAddressTxids(addrDesc, false, &AddressFilter{Vout: AddressFilterVoutOff}, maxInt) + fromHeight := uint32(0) + toHeight := maxInt + if !fromTime.IsZero() { + fromHeight = w.is.GetBlockHeightOfTime(uint32(fromTime.Unix())) + } + if !toTime.IsZero() { + toHeight = int(w.is.GetBlockHeightOfTime(uint32(toTime.Unix()))) + } + txs, err := w.getAddressTxids(addrDesc, false, &AddressFilter{Vout: AddressFilterVoutOff, FromHeight: fromHeight}, toHeight) if err != nil { return nil, err } @@ -826,19 +835,13 @@ func (w *Worker) GetBalanceHistory(address string) ([]BalanceHistory, error) { continue } counted := false - if bi == nil || bi.Height != ta.Height { - bi, err = w.db.GetBlockInfo(ta.Height) - if err != nil { - return nil, err + time := int64(w.is.GetBlockTime(ta.Height)) + hour := time - time%3600 + if bh.Time != hour { + if bh.Txs != 0 { + bhs = append(bhs, bh) } - } - hour := bi.Time - bi.Time%3600 - if b.Time != hour { - if b.Txs != 0 { - b.BalanceSat = (*Amount)(new(big.Int).Set(&balance)) - bh = append(bh, b) - } - b = BalanceHistory{ + bh = BalanceHistory{ Time: hour, SentSat: &Amount{}, ReceivedSat: &Amount{}, @@ -847,32 +850,29 @@ func (w *Worker) GetBalanceHistory(address string) ([]BalanceHistory, error) { for i := range ta.Inputs { tai := &ta.Inputs[i] if bytes.Equal(addrDesc, tai.AddrDesc) { - (*big.Int)(b.SentSat).Add((*big.Int)(b.SentSat), &tai.ValueSat) - balance.Sub(&balance, &tai.ValueSat) + (*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat) if !counted { counted = true - b.Txs++ + bh.Txs++ } } } for i := range ta.Outputs { tao := &ta.Outputs[i] if bytes.Equal(addrDesc, tao.AddrDesc) { - (*big.Int)(b.ReceivedSat).Add((*big.Int)(b.ReceivedSat), &tao.ValueSat) - balance.Add(&balance, &tao.ValueSat) + (*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &tao.ValueSat) if !counted { counted = true - b.Txs++ + bh.Txs++ } } } } - if b.Txs != 0 { - b.BalanceSat = (*Amount)(&balance) - bh = append(bh, b) + if bh.Txs != 0 { + bhs = append(bhs, bh) } - glog.Info("GetBalanceHistory ", address, ", count ", len(bh), " finished in ", time.Since(start)) - return bh, nil + glog.Info("GetBalanceHistory ", address, ", count ", len(bhs), " finished in ", time.Since(start)) + return bhs, nil } func (w *Worker) waitForBackendSync() { diff --git a/common/internalstate.go b/common/internalstate.go index 9419beaa..079b3b8c 100644 --- a/common/internalstate.go +++ b/common/internalstate.go @@ -2,6 +2,7 @@ package common import ( "encoding/json" + "sort" "sync" "time" ) @@ -45,6 +46,7 @@ type InternalState struct { IsSynchronized bool `json:"isSynchronized"` BestHeight uint32 `json:"bestHeight"` LastSync time.Time `json:"lastSync"` + BlockTimes []uint32 `json:"-"` IsMempoolSynchronized bool `json:"isMempoolSynchronized"` MempoolSize int `json:"mempoolSize"` @@ -164,6 +166,54 @@ func (is *InternalState) DBSizeTotal() int64 { return total } +// GetBlockTime returns block time if block found or 0 +func (is *InternalState) GetBlockTime(height uint32) uint32 { + is.mux.Lock() + defer is.mux.Unlock() + if int(height) < len(is.BlockTimes) { + return is.BlockTimes[height] + } + return 0 +} + +// AppendBlockTime appends block time to BlockTimes +func (is *InternalState) AppendBlockTime(time uint32) { + is.mux.Lock() + defer is.mux.Unlock() + is.BlockTimes = append(is.BlockTimes, time) +} + +// RemoveLastBlockTimes removes last times from BlockTimes +func (is *InternalState) RemoveLastBlockTimes(count int) { + is.mux.Lock() + defer is.mux.Unlock() + if len(is.BlockTimes) < count { + count = len(is.BlockTimes) + } + is.BlockTimes = is.BlockTimes[:len(is.BlockTimes)-count] +} + +// GetBlockHeightOfTime returns block height of the first block with time greater or equal to the given time or MaxUint32 if no such block +func (is *InternalState) GetBlockHeightOfTime(time uint32) uint32 { + is.mux.Lock() + defer is.mux.Unlock() + height := sort.Search(len(is.BlockTimes), func(i int) bool { return time <= is.BlockTimes[i] }) + if height == len(is.BlockTimes) { + return ^uint32(0) + } + // as the block times can sometimes be out of order try 20 blocks lower to locate a block with the time greater or equal to the given time + max, height := height, height-20 + if height < 0 { + height = 0 + } + for ; height <= max; height++ { + if time <= is.BlockTimes[height] { + break + } + } + return uint32(height) +} + // Pack marshals internal state to json func (is *InternalState) Pack() ([]byte, error) { is.mux.Lock() diff --git a/db/bulkconnect.go b/db/bulkconnect.go index 8fedd51e..025e7cb2 100644 --- a/db/bulkconnect.go +++ b/db/bulkconnect.go @@ -381,6 +381,12 @@ func (b *BulkConnect) Close() error { return err } } + var err error + b.d.is.BlockTimes, err = b.d.loadBlockTimes() + if err != nil { + return err + } + if err := b.d.SetInconsistentState(false); err != nil { return err } diff --git a/db/rocksdb.go b/db/rocksdb.go index 64a8815f..8dd73d9c 100644 --- a/db/rocksdb.go +++ b/db/rocksdb.go @@ -348,8 +348,11 @@ func (d *RocksDB) ConnectBlock(block *bchain.Block) error { if err := d.storeAddresses(wb, block.Height, addresses); err != nil { return err } - - return d.db.Write(d.wo, wb) + if err := d.db.Write(d.wo, wb); err != nil { + return err + } + d.is.AppendBlockTime(uint32(block.Time)) + return nil } // Addresses index @@ -1334,6 +1337,7 @@ func (d *RocksDB) DisconnectBlockRangeBitcoinType(lower uint32, higher uint32) e } err := d.db.Write(d.wo, wb) if err == nil { + d.is.RemoveLastBlockTimes(int(higher-lower) + 1) glog.Infof("rocksdb: blocks %d-%d disconnected", lower, higher) } return err @@ -1448,6 +1452,32 @@ func (d *RocksDB) internalDeleteTx(wb *gorocksdb.WriteBatch, key []byte) { // internal state const internalStateKey = "internalState" +func (d *RocksDB) loadBlockTimes() ([]uint32, error) { + var times []uint32 + it := d.db.NewIteratorCF(d.ro, d.cfh[cfHeight]) + defer it.Close() + counter := uint32(0) + time := uint32(0) + for it.SeekToFirst(); it.Valid(); it.Next() { + height := unpackUint(it.Key().Data()) + if height > counter { + glog.Warning("gap in cfHeight: expecting ", counter, ", got ", height) + for ; counter < height; counter++ { + times = append(times, time) + } + } + counter++ + info, err := d.unpackBlockInfo(it.Value().Data()) + if err != nil { + return nil, err + } + time = uint32(info.Time) + times = append(times, time) + } + glog.Info("loaded ", len(times), " block times") + return times, nil +} + // LoadInternalState loads from db internal state or initializes a new one if not yet stored func (d *RocksDB) LoadInternalState(rpcCoin string) (*common.InternalState, error) { val, err := d.db.GetCF(d.ro, d.cfh[cfDefault], []byte(internalStateKey)) @@ -1493,6 +1523,10 @@ func (d *RocksDB) LoadInternalState(rpcCoin string) (*common.InternalState, erro } } is.DbColumns = nc + is.BlockTimes, err = d.loadBlockTimes() + if err != nil { + return nil, err + } // after load, reset the synchronization data is.IsSynchronized = false is.IsMempoolSynchronized = false diff --git a/db/rocksdb_ethereumtype.go b/db/rocksdb_ethereumtype.go index e7cc5912..64b2eaa4 100644 --- a/db/rocksdb_ethereumtype.go +++ b/db/rocksdb_ethereumtype.go @@ -455,6 +455,7 @@ func (d *RocksDB) DisconnectBlockRangeEthereumType(lower uint32, higher uint32) d.storeAddressContracts(wb, contracts) err := d.db.Write(d.wo, wb) if err == nil { + d.is.RemoveLastBlockTimes(int(higher-lower) + 1) glog.Infof("rocksdb: blocks %d-%d disconnected", lower, higher) } return err diff --git a/db/rocksdb_ethereumtype_test.go b/db/rocksdb_ethereumtype_test.go index c40e6ad4..2c51a4bb 100644 --- a/db/rocksdb_ethereumtype_test.go +++ b/db/rocksdb_ethereumtype_test.go @@ -167,6 +167,10 @@ func TestRocksDB_Index_EthereumType(t *testing.T) { }) defer closeAndDestroyRocksDB(t, d) + if len(d.is.BlockTimes) != 0 { + t.Fatal("Expecting is.BlockTimes 0, got ", len(d.is.BlockTimes)) + } + // connect 1st block block1 := dbtestdata.GetTestEthereumTypeBlock1(d.chainParser) if err := d.ConnectBlock(block1); err != nil { @@ -174,6 +178,10 @@ func TestRocksDB_Index_EthereumType(t *testing.T) { } verifyAfterEthereumTypeBlock1(t, d, false) + if len(d.is.BlockTimes) != 1 { + t.Fatal("Expecting is.BlockTimes 1, got ", len(d.is.BlockTimes)) + } + // connect 2nd block block2 := dbtestdata.GetTestEthereumTypeBlock2(d.chainParser) if err := d.ConnectBlock(block2); err != nil { @@ -181,6 +189,10 @@ func TestRocksDB_Index_EthereumType(t *testing.T) { } verifyAfterEthereumTypeBlock2(t, d) + if len(d.is.BlockTimes) != 2 { + t.Fatal("Expecting is.BlockTimes 2, got ", len(d.is.BlockTimes)) + } + // get transactions for various addresses / low-high ranges verifyGetTransactions(t, d, "0x"+dbtestdata.EthAddr55, 0, 10000000, []txidIndex{ {"0x" + dbtestdata.EthTxidB2T2, ^2}, @@ -275,10 +287,18 @@ func TestRocksDB_Index_EthereumType(t *testing.T) { } } + if len(d.is.BlockTimes) != 1 { + t.Fatal("Expecting is.BlockTimes 1, got ", len(d.is.BlockTimes)) + } + // connect block again and verify the state of db if err := d.ConnectBlock(block2); err != nil { t.Fatal(err) } verifyAfterEthereumTypeBlock2(t, d) + if len(d.is.BlockTimes) != 2 { + t.Fatal("Expecting is.BlockTimes 2, got ", len(d.is.BlockTimes)) + } + } diff --git a/db/rocksdb_test.go b/db/rocksdb_test.go index 988a6749..2c9c5aca 100644 --- a/db/rocksdb_test.go +++ b/db/rocksdb_test.go @@ -532,6 +532,10 @@ func TestRocksDB_Index_BitcoinType(t *testing.T) { }) defer closeAndDestroyRocksDB(t, d) + if len(d.is.BlockTimes) != 0 { + t.Fatal("Expecting is.BlockTimes 0, got ", len(d.is.BlockTimes)) + } + // connect 1st block - will log warnings about missing UTXO transactions in txAddresses column block1 := dbtestdata.GetTestBitcoinTypeBlock1(d.chainParser) if err := d.ConnectBlock(block1); err != nil { @@ -539,6 +543,10 @@ func TestRocksDB_Index_BitcoinType(t *testing.T) { } verifyAfterBitcoinTypeBlock1(t, d, false) + if len(d.is.BlockTimes) != 1 { + t.Fatal("Expecting is.BlockTimes 1, got ", len(d.is.BlockTimes)) + } + // connect 2nd block - use some outputs from the 1st block as the inputs and 1 input uses tx from the same block block2 := dbtestdata.GetTestBitcoinTypeBlock2(d.chainParser) if err := d.ConnectBlock(block2); err != nil { @@ -546,6 +554,10 @@ func TestRocksDB_Index_BitcoinType(t *testing.T) { } verifyAfterBitcoinTypeBlock2(t, d) + if len(d.is.BlockTimes) != 2 { + t.Fatal("Expecting is.BlockTimes 1, got ", len(d.is.BlockTimes)) + } + // get transactions for various addresses / low-high ranges verifyGetTransactions(t, d, dbtestdata.Addr2, 0, 1000000, []txidIndex{ {dbtestdata.TxidB2T1, ^1}, @@ -649,12 +661,20 @@ func TestRocksDB_Index_BitcoinType(t *testing.T) { } } + if len(d.is.BlockTimes) != 1 { + t.Fatal("Expecting is.BlockTimes 1, got ", len(d.is.BlockTimes)) + } + // connect block again and verify the state of db if err := d.ConnectBlock(block2); err != nil { t.Fatal(err) } verifyAfterBitcoinTypeBlock2(t, d) + if len(d.is.BlockTimes) != 2 { + t.Fatal("Expecting is.BlockTimes 1, got ", len(d.is.BlockTimes)) + } + // test public methods for address balance and tx addresses ab, err := d.GetAddressBalance(dbtestdata.Addr5, AddressBalanceDetailUTXO) if err != nil { @@ -744,6 +764,10 @@ func Test_BulkConnect_BitcoinType(t *testing.T) { t.Fatal("DB not in DbStateInconsistent") } + if len(d.is.BlockTimes) != 0 { + t.Fatal("Expecting is.BlockTimes 0, got ", len(d.is.BlockTimes)) + } + if err := bc.ConnectBlock(dbtestdata.GetTestBitcoinTypeBlock1(d.chainParser), false); err != nil { t.Fatal(err) } @@ -766,6 +790,10 @@ func Test_BulkConnect_BitcoinType(t *testing.T) { } verifyAfterBitcoinTypeBlock2(t, d) + + if len(d.is.BlockTimes) != 225495 { + t.Fatal("Expecting is.BlockTimes 225495, got ", len(d.is.BlockTimes)) + } } func Test_packBigint_unpackBigint(t *testing.T) { diff --git a/server/public.go b/server/public.go index 50cc3567..eea858fb 100644 --- a/server/public.go +++ b/server/public.go @@ -1035,17 +1035,26 @@ func (s *PublicServer) apiUtxo(r *http.Request, apiVersion int) (interface{}, er func (s *PublicServer) apiBalanceHistory(r *http.Request, apiVersion int) (interface{}, error) { var history []api.BalanceHistory + var fromTime, toTime time.Time var err error if i := strings.LastIndexByte(r.URL.Path, '/'); i > 0 { gap, ec := strconv.Atoi(r.URL.Query().Get("gap")) if ec != nil { gap = 0 } + t := r.URL.Query().Get("from") + if t != "" { + fromTime, _ = time.Parse("2006-02-01", t) + } + t = r.URL.Query().Get("to") + if t != "" { + toTime, _ = time.Parse("2006-02-01", t) + } history, err = s.api.GetUtxoBalanceHistory(r.URL.Path[i+1:], gap) if err == nil { s.metrics.ExplorerViews.With(common.Labels{"action": "api-xpub-balancehistory"}).Inc() } else { - history, err = s.api.GetBalanceHistory(r.URL.Path[i+1:]) + history, err = s.api.GetBalanceHistory(r.URL.Path[i+1:], fromTime, toTime) s.metrics.ExplorerViews.With(common.Labels{"action": "api-address-balancehistory"}).Inc() } } diff --git a/server/public_test.go b/server/public_test.go index d25bbad3..1aa76e3c 100644 --- a/server/public_test.go +++ b/server/public_test.go @@ -50,8 +50,13 @@ func setupRocksDB(t *testing.T, parser bchain.BlockChainParser) (*db.RocksDB, *c t.Fatal(err) } d.SetInternalState(is) + block1 := dbtestdata.GetTestBitcoinTypeBlock1(parser) + // setup internal state BlockTimes + for i := uint32(0); i < block1.Height; i++ { + is.BlockTimes = append(is.BlockTimes, 0) + } // import data - if err := d.ConnectBlock(dbtestdata.GetTestBitcoinTypeBlock1(parser)); err != nil { + if err := d.ConnectBlock(block1); err != nil { t.Fatal(err) } block2 := dbtestdata.GetTestBitcoinTypeBlock2(parser) @@ -610,7 +615,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `[{"blockTime":1521514800,"txs":1,"received":"12345","sent":"0","balance":"12345"},{"blockTime":1521594000,"txs":1,"received":"0","sent":"12345","balance":"0"}]`, + `[{"blockTime":1521514800,"txs":1,"received":"12345","sent":"0"},{"blockTime":1521594000,"txs":1,"received":"0","sent":"12345"}]`, }, }, { @@ -619,7 +624,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `[{"blockTime":1521514800,"txs":1,"received":"9876","sent":"0","balance":"9876"},{"blockTime":1521594000,"txs":1,"received":"9000","sent":"9876","balance":"9000"}]`, + `[{"blockTime":1521514800,"txs":1,"received":"9876","sent":"0"},{"blockTime":1521594000,"txs":1,"received":"9000","sent":"9876"}]`, }, }, { From 62208b963450fefdbd03241d05955172eaea7fa8 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Fri, 29 Nov 2019 19:26:20 +0100 Subject: [PATCH 17/31] Add aggregation to balance history --- api/types.go | 59 +++++++++++++++++++++- api/types_test.go | 112 ++++++++++++++++++++++++++++++++++++++++++ api/worker.go | 60 ++++++++++------------ server/public.go | 5 +- server/public_test.go | 9 ++++ 5 files changed, 207 insertions(+), 38 deletions(-) diff --git a/api/types.go b/api/types.go index 4e9f22fa..e98634bd 100644 --- a/api/types.go +++ b/api/types.go @@ -7,6 +7,7 @@ import ( "encoding/json" "errors" "math/big" + "sort" "time" ) @@ -298,10 +299,64 @@ func (a Utxos) Less(i, j int) bool { // BalanceHistory contains info about one point in time of balance history type BalanceHistory struct { - Time int64 `json:"blockTime"` - Txs int `json:"txs"` + Time uint32 `json:"blockTime"` + Txs uint32 `json:"txs"` ReceivedSat *Amount `json:"received"` SentSat *Amount `json:"sent"` + Txid string `json:"txid,omitempty"` +} + +// BalanceHistories is array of BalanceHistory +type BalanceHistories []BalanceHistory + +func (a BalanceHistories) Len() int { return len(a) } +func (a BalanceHistories) Swap(i, j int) { a[i], a[j] = a[j], a[i] } +func (a BalanceHistories) Less(i, j int) bool { + ti := a[i].Time + tj := a[j].Time + if ti == tj { + return a[i].Txid < a[j].Txid + } + return ti < tj +} + +// SortAndAggregate sums BalanceHistories to groups defined by parameter groupByTime +func (a BalanceHistories) SortAndAggregate(groupByTime uint32) BalanceHistories { + bhs := make(BalanceHistories, 0) + if len(a) > 0 { + bha := BalanceHistory{ + SentSat: &Amount{}, + ReceivedSat: &Amount{}, + } + sort.Sort(a) + for i := range a { + bh := &a[i] + time := bh.Time - bh.Time%groupByTime + if bha.Time != time { + if bha.Time != 0 { + // in aggregate, do not return txid as it could multiple of them + bha.Txid = "" + bhs = append(bhs, bha) + } + bha = BalanceHistory{ + Time: time, + SentSat: &Amount{}, + ReceivedSat: &Amount{}, + } + } + if bha.Txid != bh.Txid { + bha.Txs += bh.Txs + bha.Txid = bh.Txid + } + (*big.Int)(bha.SentSat).Add((*big.Int)(bha.SentSat), (*big.Int)(bh.SentSat)) + (*big.Int)(bha.ReceivedSat).Add((*big.Int)(bha.ReceivedSat), (*big.Int)(bh.ReceivedSat)) + } + if bha.Txs > 0 { + bha.Txid = "" + bhs = append(bhs, bha) + } + } + return bhs } // Blocks is list of blocks with paging information diff --git a/api/types_test.go b/api/types_test.go index fe301eb5..f2f29791 100644 --- a/api/types_test.go +++ b/api/types_test.go @@ -49,3 +49,115 @@ func TestAmount_MarshalJSON(t *testing.T) { }) } } + +func TestBalanceHistories_SortAndAggregate(t *testing.T) { + tests := []struct { + name string + a BalanceHistories + groupByTime uint32 + want BalanceHistories + }{ + { + name: "empty", + a: []BalanceHistory{}, + groupByTime: 3600, + want: []BalanceHistory{}, + }, + { + name: "one", + a: []BalanceHistory{ + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(1)), + SentSat: (*Amount)(big.NewInt(2)), + Time: 1521514812, + Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840", + Txs: 1, + }, + }, + groupByTime: 3600, + want: []BalanceHistory{ + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(1)), + SentSat: (*Amount)(big.NewInt(2)), + Time: 1521514800, + Txs: 1, + }, + }, + }, + { + name: "aggregate", + a: []BalanceHistory{ + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(1)), + SentSat: (*Amount)(big.NewInt(2)), + Time: 1521504812, + Txid: "0011223344556677889900112233445566778899001122334455667788990011", + Txs: 1, + }, + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(3)), + SentSat: (*Amount)(big.NewInt(4)), + Time: 1521504812, + Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840", + Txs: 1, + }, + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(5)), + SentSat: (*Amount)(big.NewInt(6)), + Time: 1521514812, + Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840", + Txs: 1, + }, + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(7)), + SentSat: (*Amount)(big.NewInt(8)), + Time: 1521504812, + Txid: "00b2c06055e5e90e9c82bd4181fde310104391a7fa4f289b1704e5d90caa3840", + Txs: 1, + }, + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(9)), + SentSat: (*Amount)(big.NewInt(10)), + Time: 1521534812, + Txid: "0011223344556677889900112233445566778899001122334455667788990011", + Txs: 1, + }, + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(11)), + SentSat: (*Amount)(big.NewInt(12)), + Time: 1521534812, + Txid: "1122334455667788990011223344556677889900112233445566778899001100", + Txs: 1, + }, + }, + groupByTime: 3600, + want: []BalanceHistory{ + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(11)), + SentSat: (*Amount)(big.NewInt(14)), + Time: 1521504000, + Txs: 2, + }, + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(5)), + SentSat: (*Amount)(big.NewInt(6)), + Time: 1521514800, + Txs: 1, + }, + BalanceHistory{ + ReceivedSat: (*Amount)(big.NewInt(20)), + SentSat: (*Amount)(big.NewInt(22)), + Time: 1521532800, + Txs: 2, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := tt.a.SortAndAggregate(tt.groupByTime); !reflect.DeepEqual(got, tt.want) { + t.Errorf("BalanceHistories.SortAndAggregate() = %+v, want %+v", got, tt.want) + } + }) + } +} diff --git a/api/worker.go b/api/worker.go index 71b87097..d0888e27 100644 --- a/api/worker.go +++ b/api/worker.go @@ -802,26 +802,29 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco } // GetBalanceHistory returns history of balance for given address -func (w *Worker) GetBalanceHistory(address string, fromTime, toTime time.Time) ([]BalanceHistory, error) { - var bhs []BalanceHistory - bh := BalanceHistory{ - SentSat: &Amount{}, - ReceivedSat: &Amount{}, - } +func (w *Worker) GetBalanceHistory(address string, fromTime, toTime time.Time) (BalanceHistories, error) { + bhs := make(BalanceHistories, 0) start := time.Now() addrDesc, _, err := w.getAddrDescAndNormalizeAddress(address) if err != nil { return nil, err } + fromUnix := uint32(0) + toUnix := maxUint32 fromHeight := uint32(0) - toHeight := maxInt + toHeight := maxUint32 if !fromTime.IsZero() { - fromHeight = w.is.GetBlockHeightOfTime(uint32(fromTime.Unix())) + fromUnix = uint32(fromTime.Unix()) + fromHeight = w.is.GetBlockHeightOfTime(fromUnix) } if !toTime.IsZero() { - toHeight = int(w.is.GetBlockHeightOfTime(uint32(toTime.Unix()))) + toUnix = uint32(toTime.Unix()) + toHeight = w.is.GetBlockHeightOfTime(toUnix) } - txs, err := w.getAddressTxids(addrDesc, false, &AddressFilter{Vout: AddressFilterVoutOff, FromHeight: fromHeight}, toHeight) + if fromHeight >= toHeight { + return bhs, nil + } + txs, err := w.getAddressTxids(addrDesc, false, &AddressFilter{Vout: AddressFilterVoutOff, FromHeight: fromHeight, ToHeight: toHeight}, maxInt) if err != nil { return nil, err } @@ -834,45 +837,34 @@ func (w *Worker) GetBalanceHistory(address string, fromTime, toTime time.Time) ( glog.Warning("DB inconsistency: tx ", txs[txi], ": not found in txAddresses") continue } - counted := false - time := int64(w.is.GetBlockTime(ta.Height)) - hour := time - time%3600 - if bh.Time != hour { - if bh.Txs != 0 { - bhs = append(bhs, bh) - } - bh = BalanceHistory{ - Time: hour, - SentSat: &Amount{}, - ReceivedSat: &Amount{}, - } + time := w.is.GetBlockTime(ta.Height) + if time < fromUnix || time >= toUnix { + continue + } + bh := BalanceHistory{ + Time: time, + Txs: 1, + SentSat: &Amount{}, + ReceivedSat: &Amount{}, + Txid: txs[txi], } for i := range ta.Inputs { tai := &ta.Inputs[i] if bytes.Equal(addrDesc, tai.AddrDesc) { (*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat) - if !counted { - counted = true - bh.Txs++ - } } } for i := range ta.Outputs { tao := &ta.Outputs[i] if bytes.Equal(addrDesc, tao.AddrDesc) { (*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &tao.ValueSat) - if !counted { - counted = true - bh.Txs++ - } } } - } - if bh.Txs != 0 { bhs = append(bhs, bh) } - glog.Info("GetBalanceHistory ", address, ", count ", len(bhs), " finished in ", time.Since(start)) - return bhs, nil + bha := bhs.SortAndAggregate(3600) + glog.Info("GetBalanceHistory ", address, ", count ", len(bha), " finished in ", time.Since(start)) + return bha, nil } func (w *Worker) waitForBackendSync() { diff --git a/server/public.go b/server/public.go index eea858fb..44e53115 100644 --- a/server/public.go +++ b/server/public.go @@ -1044,11 +1044,12 @@ func (s *PublicServer) apiBalanceHistory(r *http.Request, apiVersion int) (inter } t := r.URL.Query().Get("from") if t != "" { - fromTime, _ = time.Parse("2006-02-01", t) + fromTime, _ = time.Parse("2006-01-02", t) } t = r.URL.Query().Get("to") if t != "" { - toTime, _ = time.Parse("2006-02-01", t) + // time.RFC3339 + toTime, _ = time.Parse("2006-01-02", t) } history, err = s.api.GetUtxoBalanceHistory(r.URL.Path[i+1:], gap) if err == nil { diff --git a/server/public_test.go b/server/public_test.go index 1aa76e3c..bbf7432a 100644 --- a/server/public_test.go +++ b/server/public_test.go @@ -627,6 +627,15 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { `[{"blockTime":1521514800,"txs":1,"received":"9876","sent":"0"},{"blockTime":1521594000,"txs":1,"received":"9000","sent":"9876"}]`, }, }, + { + name: "apiBalanceHistory Addr2 v2 from=2018-03-20&to=2018-03-21", + r: newGetRequest(ts.URL + "/api/v2/balancehistory/mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz?from=2018-03-20&to=2018-03-21"), + status: http.StatusOK, + contentType: "application/json; charset=utf-8", + body: []string{ + `[{"blockTime":1521514800,"txs":1,"received":"12345","sent":"0"}]`, + }, + }, { name: "apiSendTx", r: newGetRequest(ts.URL + "/api/v2/sendtx/1234567890"), From c913a022ef6dc049bfbaa7fc5736846cbe0d820a Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Tue, 3 Dec 2019 16:02:20 +0100 Subject: [PATCH 18/31] Add get balance history for xpub --- api/worker.go | 89 +++++++++++++++++++++++++------------------ api/xpub.go | 36 ++++++++++++++++- server/public.go | 2 +- server/public_test.go | 27 +++++++++++++ 4 files changed, 114 insertions(+), 40 deletions(-) diff --git a/api/worker.go b/api/worker.go index d0888e27..86396f8c 100644 --- a/api/worker.go +++ b/api/worker.go @@ -801,14 +801,7 @@ func (w *Worker) GetAddress(address string, page int, txsOnPage int, option Acco return r, nil } -// GetBalanceHistory returns history of balance for given address -func (w *Worker) GetBalanceHistory(address string, fromTime, toTime time.Time) (BalanceHistories, error) { - bhs := make(BalanceHistories, 0) - start := time.Now() - addrDesc, _, err := w.getAddrDescAndNormalizeAddress(address) - if err != nil { - return nil, err - } +func (w *Worker) balanceHistoryHeightsFromTo(fromTime, toTime time.Time) (uint32, uint32, uint32, uint32) { fromUnix := uint32(0) toUnix := maxUint32 fromHeight := uint32(0) @@ -821,6 +814,53 @@ func (w *Worker) GetBalanceHistory(address string, fromTime, toTime time.Time) ( toUnix = uint32(toTime.Unix()) toHeight = w.is.GetBlockHeightOfTime(toUnix) } + return fromUnix, fromHeight, toUnix, toHeight +} + +func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid string, fromUnix, toUnix uint32) (*BalanceHistory, error) { + ta, err := w.db.GetTxAddresses(txid) + if err != nil { + return nil, err + } + if ta == nil { + glog.Warning("DB inconsistency: tx ", txid, ": not found in txAddresses") + return nil, nil + } + time := w.is.GetBlockTime(ta.Height) + if time < fromUnix || time >= toUnix { + return nil, nil + } + bh := BalanceHistory{ + Time: time, + Txs: 1, + SentSat: &Amount{}, + ReceivedSat: &Amount{}, + Txid: txid, + } + for i := range ta.Inputs { + tai := &ta.Inputs[i] + if bytes.Equal(addrDesc, tai.AddrDesc) { + (*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat) + } + } + for i := range ta.Outputs { + tao := &ta.Outputs[i] + if bytes.Equal(addrDesc, tao.AddrDesc) { + (*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &tao.ValueSat) + } + } + return &bh, nil +} + +// GetBalanceHistory returns history of balance for given address +func (w *Worker) GetBalanceHistory(address string, fromTime, toTime time.Time) (BalanceHistories, error) { + bhs := make(BalanceHistories, 0) + start := time.Now() + addrDesc, _, err := w.getAddrDescAndNormalizeAddress(address) + if err != nil { + return nil, err + } + fromUnix, fromHeight, toUnix, toHeight := w.balanceHistoryHeightsFromTo(fromTime, toTime) if fromHeight >= toHeight { return bhs, nil } @@ -829,41 +869,16 @@ func (w *Worker) GetBalanceHistory(address string, fromTime, toTime time.Time) ( return nil, err } for txi := len(txs) - 1; txi >= 0; txi-- { - ta, err := w.db.GetTxAddresses(txs[txi]) + bh, err := w.balanceHistoryForTxid(addrDesc, txs[txi], fromUnix, toUnix) if err != nil { return nil, err } - if ta == nil { - glog.Warning("DB inconsistency: tx ", txs[txi], ": not found in txAddresses") - continue + if bh != nil { + bhs = append(bhs, *bh) } - time := w.is.GetBlockTime(ta.Height) - if time < fromUnix || time >= toUnix { - continue - } - bh := BalanceHistory{ - Time: time, - Txs: 1, - SentSat: &Amount{}, - ReceivedSat: &Amount{}, - Txid: txs[txi], - } - for i := range ta.Inputs { - tai := &ta.Inputs[i] - if bytes.Equal(addrDesc, tai.AddrDesc) { - (*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat) - } - } - for i := range ta.Outputs { - tao := &ta.Outputs[i] - if bytes.Equal(addrDesc, tao.AddrDesc) { - (*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &tao.ValueSat) - } - } - bhs = append(bhs, bh) } bha := bhs.SortAndAggregate(3600) - glog.Info("GetBalanceHistory ", address, ", count ", len(bha), " finished in ", time.Since(start)) + glog.Info("GetBalanceHistory ", address, ", blocks ", fromHeight, "-", toHeight, ", count ", len(bha), " finished in ", time.Since(start)) return bha, nil } diff --git a/api/xpub.go b/api/xpub.go index 85522b3d..5e014b96 100644 --- a/api/xpub.go +++ b/api/xpub.go @@ -591,6 +591,38 @@ func (w *Worker) GetXpubUtxo(xpub string, onlyConfirmed bool, gap int) (Utxos, e } // GetUtxoBalanceHistory returns history of balance for given xpub -func (w *Worker) GetUtxoBalanceHistory(xpub string, gap int) ([]BalanceHistory, error) { - return nil, errors.New("not implemented") +func (w *Worker) GetUtxoBalanceHistory(xpub string, fromTime, toTime time.Time, gap int) (BalanceHistories, error) { + bhs := make(BalanceHistories, 0) + start := time.Now() + fromUnix, fromHeight, toUnix, toHeight := w.balanceHistoryHeightsFromTo(fromTime, toTime) + if fromHeight >= toHeight { + return bhs, nil + } + data, _, err := w.getXpubData(xpub, 0, 1, AccountDetailsTxidHistory, &AddressFilter{ + Vout: AddressFilterVoutOff, + OnlyConfirmed: true, + FromHeight: fromHeight, + ToHeight: toHeight, + }, gap) + if err != nil { + return nil, err + } + for _, da := range [][]xpubAddress{data.addresses, data.changeAddresses} { + for i := range da { + ad := &da[i] + txids := ad.txids + for txi := len(txids) - 1; txi >= 0; txi-- { + bh, err := w.balanceHistoryForTxid(ad.addrDesc, txids[txi].txid, fromUnix, toUnix) + if err != nil { + return nil, err + } + if bh != nil { + bhs = append(bhs, *bh) + } + } + } + } + bha := bhs.SortAndAggregate(3600) + glog.Info("GetUtxoBalanceHistory ", xpub[:16], ", blocks ", fromHeight, "-", toHeight, ", count ", len(bha), ", finished in ", time.Since(start)) + return bha, nil } diff --git a/server/public.go b/server/public.go index 44e53115..c4fdc8c2 100644 --- a/server/public.go +++ b/server/public.go @@ -1051,7 +1051,7 @@ func (s *PublicServer) apiBalanceHistory(r *http.Request, apiVersion int) (inter // time.RFC3339 toTime, _ = time.Parse("2006-01-02", t) } - history, err = s.api.GetUtxoBalanceHistory(r.URL.Path[i+1:], gap) + history, err = s.api.GetUtxoBalanceHistory(r.URL.Path[i+1:], fromTime, toTime, gap) if err == nil { s.metrics.ExplorerViews.With(common.Labels{"action": "api-xpub-balancehistory"}).Inc() } else { diff --git a/server/public_test.go b/server/public_test.go index bbf7432a..fdeab6c7 100644 --- a/server/public_test.go +++ b/server/public_test.go @@ -636,6 +636,33 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { `[{"blockTime":1521514800,"txs":1,"received":"12345","sent":"0"}]`, }, }, + { + name: "apiBalanceHistory xpub v2", + r: newGetRequest(ts.URL + "/api/v2/balancehistory/" + dbtestdata.Xpub), + status: http.StatusOK, + contentType: "application/json; charset=utf-8", + body: []string{ + `[{"blockTime":1521514800,"txs":1,"received":"1","sent":"0"},{"blockTime":1521594000,"txs":1,"received":"118641975500","sent":"1"}]`, + }, + }, + { + name: "apiBalanceHistory xpub v2 from=2018-03-20&to=2018-03-21", + r: newGetRequest(ts.URL + "/api/v2/balancehistory/" + dbtestdata.Xpub + "?from=2018-03-20&to=2018-03-21"), + status: http.StatusOK, + contentType: "application/json; charset=utf-8", + body: []string{ + `[{"blockTime":1521514800,"txs":1,"received":"1","sent":"0"}]`, + }, + }, + { + name: "apiBalanceHistory xpub v2 from=2018-03-21", + r: newGetRequest(ts.URL + "/api/v2/balancehistory/" + dbtestdata.Xpub + "?from=2018-03-21"), + status: http.StatusOK, + contentType: "application/json; charset=utf-8", + body: []string{ + `[{"blockTime":1521594000,"txs":1,"received":"118641975500","sent":"1"}]`, + }, + }, { name: "apiSendTx", r: newGetRequest(ts.URL + "/api/v2/sendtx/1234567890"), From 6f294a6241312e3b3f33598bd461ab9594c95eb6 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Tue, 10 Dec 2019 21:08:27 +0100 Subject: [PATCH 19/31] Add get balance history for ethereum type coins --- api/worker.go | 95 ++++++++++++++++++++++++++++------- bchain/coins/eth/erc20.go | 12 ++--- bchain/coins/eth/ethparser.go | 9 ++++ 3 files changed, 93 insertions(+), 23 deletions(-) diff --git a/api/worker.go b/api/worker.go index 86396f8c..f92a5eea 100644 --- a/api/worker.go +++ b/api/worker.go @@ -818,15 +818,34 @@ func (w *Worker) balanceHistoryHeightsFromTo(fromTime, toTime time.Time) (uint32 } func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid string, fromUnix, toUnix uint32) (*BalanceHistory, error) { - ta, err := w.db.GetTxAddresses(txid) - if err != nil { - return nil, err + var time uint32 + var err error + var ta *db.TxAddresses + var bchainTx *bchain.Tx + var height uint32 + if w.chainType == bchain.ChainBitcoinType { + ta, err = w.db.GetTxAddresses(txid) + if err != nil { + return nil, err + } + if ta == nil { + glog.Warning("DB inconsistency: tx ", txid, ": not found in txAddresses") + return nil, nil + } + height = ta.Height + } else if w.chainType == bchain.ChainEthereumType { + var h int + bchainTx, h, err = w.txCache.GetTransaction(txid) + if err != nil { + return nil, err + } + if bchainTx == nil { + glog.Warning("Inconsistency: tx ", txid, ": not found in the blockchain") + return nil, nil + } + height = uint32(h) } - if ta == nil { - glog.Warning("DB inconsistency: tx ", txid, ": not found in txAddresses") - return nil, nil - } - time := w.is.GetBlockTime(ta.Height) + time = w.is.GetBlockTime(height) if time < fromUnix || time >= toUnix { return nil, nil } @@ -837,16 +856,58 @@ func (w *Worker) balanceHistoryForTxid(addrDesc bchain.AddressDescriptor, txid s ReceivedSat: &Amount{}, Txid: txid, } - for i := range ta.Inputs { - tai := &ta.Inputs[i] - if bytes.Equal(addrDesc, tai.AddrDesc) { - (*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat) + if w.chainType == bchain.ChainBitcoinType { + for i := range ta.Inputs { + tai := &ta.Inputs[i] + if bytes.Equal(addrDesc, tai.AddrDesc) { + (*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &tai.ValueSat) + } } - } - for i := range ta.Outputs { - tao := &ta.Outputs[i] - if bytes.Equal(addrDesc, tao.AddrDesc) { - (*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &tao.ValueSat) + for i := range ta.Outputs { + tao := &ta.Outputs[i] + if bytes.Equal(addrDesc, tao.AddrDesc) { + (*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &tao.ValueSat) + } + } + } else if w.chainType == bchain.ChainEthereumType { + var value big.Int + ethTxData := eth.GetEthereumTxData(bchainTx) + // add received amount only for OK transactions + if ethTxData.Status == 1 { + if len(bchainTx.Vout) > 0 { + bchainVout := &bchainTx.Vout[0] + value = bchainVout.ValueSat + if len(bchainVout.ScriptPubKey.Addresses) > 0 { + txAddrDesc, err := w.chainParser.GetAddrDescFromAddress(bchainVout.ScriptPubKey.Addresses[0]) + if err != nil { + return nil, err + } + if bytes.Equal(addrDesc, txAddrDesc) { + (*big.Int)(bh.ReceivedSat).Add((*big.Int)(bh.ReceivedSat), &value) + } + } + } + } + for i := range bchainTx.Vin { + bchainVin := &bchainTx.Vin[i] + if len(bchainVin.Addresses) > 0 { + txAddrDesc, err := w.chainParser.GetAddrDescFromAddress(bchainVin.Addresses[0]) + if err != nil { + return nil, err + } + if bytes.Equal(addrDesc, txAddrDesc) { + // add sent amount only for OK transactions, however fees always + if ethTxData.Status == 1 { + (*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &value) + } + var feesSat big.Int + // mempool txs do not have fees yet + if ethTxData.GasUsed != nil { + feesSat.Mul(ethTxData.GasPrice, ethTxData.GasUsed) + } + (*big.Int)(bh.SentSat).Add((*big.Int)(bh.SentSat), &feesSat) + } + } } } return &bh, nil diff --git a/bchain/coins/eth/erc20.go b/bchain/coins/eth/erc20.go index d001722d..6903d1e4 100644 --- a/bchain/coins/eth/erc20.go +++ b/bchain/coins/eth/erc20.go @@ -74,9 +74,9 @@ func erc20GetTransfersFromLog(logs []*rpcLog) ([]bchain.Erc20Transfer, error) { return nil, err } r = append(r, bchain.Erc20Transfer{ - Contract: strings.ToLower(l.Address), - From: strings.ToLower(from), - To: strings.ToLower(to), + Contract: EIP55AddressFromAddress(l.Address), + From: EIP55AddressFromAddress(from), + To: EIP55AddressFromAddress(to), Tokens: t, }) } @@ -97,9 +97,9 @@ func erc20GetTransfersFromTx(tx *rpcTransaction) ([]bchain.Erc20Transfer, error) return nil, errors.New("Data is not a number") } r = append(r, bchain.Erc20Transfer{ - Contract: strings.ToLower(tx.To), - From: strings.ToLower(tx.From), - To: strings.ToLower(to), + Contract: EIP55AddressFromAddress(tx.To), + From: EIP55AddressFromAddress(tx.From), + To: EIP55AddressFromAddress(to), Tokens: t, }) } diff --git a/bchain/coins/eth/ethparser.go b/bchain/coins/eth/ethparser.go index f3790699..49cea1fa 100644 --- a/bchain/coins/eth/ethparser.go +++ b/bchain/coins/eth/ethparser.go @@ -202,6 +202,15 @@ func EIP55Address(addrDesc bchain.AddressDescriptor) string { return string(result) } +// EIP55AddressFromAddress returns an EIP55-compliant hex string representation of the address +func EIP55AddressFromAddress(address string) string { + b, err := hex.DecodeString(address) + if err != nil { + return address + } + return EIP55Address(b) +} + // GetAddressesFromAddrDesc returns addresses for given address descriptor with flag if the addresses are searchable func (p *EthereumParser) GetAddressesFromAddrDesc(addrDesc bchain.AddressDescriptor) ([]string, bool, error) { return []string{EIP55Address(addrDesc)}, true, nil From 5c7b1c9a0c69c6ba31b65423b1f6d414eca6f06d Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Fri, 22 Nov 2019 19:07:35 +0100 Subject: [PATCH 20/31] dash (+testnet): Bump backend 0.14.0.3 -> 0.14.0.4 --- configs/coins/dash.json | 8 ++++---- configs/coins/dash_testnet.json | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/configs/coins/dash.json b/configs/coins/dash.json index b9eb8f1f..a08da006 100644 --- a/configs/coins/dash.json +++ b/configs/coins/dash.json @@ -22,10 +22,10 @@ "package_name": "backend-dash", "package_revision": "satoshilabs-1", "system_user": "dash", - "version": "0.14.0.3", - "binary_url": "https://github.com/dashpay/dash/releases/download/v0.14.0.3/dashcore-0.14.0.3-x86_64-linux-gnu.tar.gz", + "version": "0.14.0.4", + "binary_url": "https://github.com/dashpay/dash/releases/download/v0.14.0.4/dashcore-0.14.0.4-x86_64-linux-gnu.tar.gz", "verification_type": "gpg-sha256", - "verification_source": "https://github.com/dashpay/dash/releases/download/v0.14.0.3/SHA256SUMS.asc", + "verification_source": "https://github.com/dashpay/dash/releases/download/v0.14.0.4/SHA256SUMS.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/dash-qt" @@ -52,7 +52,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Dash Core:0.14.0.3/", + "subversion": "/Dash Core:0.14.0.4/", "mempool_workers": 8, "mempool_sub_workers": 2, "block_addresses_to_keep": 300, diff --git a/configs/coins/dash_testnet.json b/configs/coins/dash_testnet.json index ba60b887..32ae5f07 100644 --- a/configs/coins/dash_testnet.json +++ b/configs/coins/dash_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-dash-testnet", "package_revision": "satoshilabs-1", "system_user": "dash", - "version": "0.14.0.3", - "binary_url": "https://github.com/dashpay/dash/releases/download/v0.14.0.3/dashcore-0.14.0.3-x86_64-linux-gnu.tar.gz", + "version": "0.14.0.4", + "binary_url": "https://github.com/dashpay/dash/releases/download/v0.14.0.4/dashcore-0.14.0.4-x86_64-linux-gnu.tar.gz", "verification_type": "gpg-sha256", - "verification_source": "https://github.com/dashpay/dash/releases/download/v0.14.0.3/SHA256SUMS.asc", + "verification_source": "https://github.com/dashpay/dash/releases/download/v0.14.0.4/SHA256SUMS.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/dash-qt" @@ -52,7 +52,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Dash Core:0.14.0.3/", + "subversion": "/Dash Core:0.14.0.4/", "mempool_workers": 8, "mempool_sub_workers": 2, "block_addresses_to_keep": 300, From 684712680fd69ae379799bd642b24fde3241ca01 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Sun, 24 Nov 2019 23:09:42 +0100 Subject: [PATCH 21/31] btc (+testnet): Bump backend 0.18.1 -> 0.19.0.1 --- configs/coins/bitcoin.json | 10 +++++----- configs/coins/bitcoin_testnet.json | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/configs/coins/bitcoin.json b/configs/coins/bitcoin.json index ef6e2f3d..c9096f75 100644 --- a/configs/coins/bitcoin.json +++ b/configs/coins/bitcoin.json @@ -22,10 +22,10 @@ "package_name": "backend-bitcoin", "package_revision": "satoshilabs-1", "system_user": "bitcoin", - "version": "0.18.1", - "binary_url": "https://bitcoin.org/bin/bitcoin-core-0.18.1/bitcoin-0.18.1-x86_64-linux-gnu.tar.gz", + "version": "0.19.0.1", + "binary_url": "https://bitcoin.org/bin/bitcoin-core-0.19.0.1/bitcoin-0.19.0.1-x86_64-linux-gnu.tar.gz", "verification_type": "gpg-sha256", - "verification_source": "https://bitcoin.org/bin/bitcoin-core-0.18.1/SHA256SUMS.asc", + "verification_source": "https://bitcoin.org/bin/bitcoin-core-0.19.0.1/SHA256SUMS.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -65,7 +65,7 @@ } }, "meta": { - "package_maintainer": "Martin Bohm", - "package_maintainer_email": "martin.bohm@satoshilabs.com" + "package_maintainer": "IT", + "package_maintainer_email": "it@satoshilabs.com" } } diff --git a/configs/coins/bitcoin_testnet.json b/configs/coins/bitcoin_testnet.json index 8a86a1f1..2fa70af7 100644 --- a/configs/coins/bitcoin_testnet.json +++ b/configs/coins/bitcoin_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-bitcoin-testnet", "package_revision": "satoshilabs-1", "system_user": "bitcoin", - "version": "0.18.1", - "binary_url": "https://bitcoin.org/bin/bitcoin-core-0.18.1/bitcoin-0.18.1-x86_64-linux-gnu.tar.gz", + "version": "0.19.0.1", + "binary_url": "https://bitcoin.org/bin/bitcoin-core-0.19.0.1/bitcoin-0.19.0.1-x86_64-linux-gnu.tar.gz", "verification_type": "gpg-sha256", - "verification_source": "https://bitcoin.org/bin/bitcoin-core-0.18.1/SHA256SUMS.asc", + "verification_source": "https://bitcoin.org/bin/bitcoin-core-0.19.0.1/SHA256SUMS.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -63,7 +63,7 @@ } }, "meta": { - "package_maintainer": "Martin Bohm", - "package_maintainer_email": "martin.bohm@satoshilabs.com" + "package_maintainer": "IT", + "package_maintainer_email": "it@satoshilabs.com" } } From 5c4f1d26743cc4e10572dab679f026590466105e Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Wed, 27 Nov 2019 09:59:42 +0100 Subject: [PATCH 22/31] eth (+testnet): Bump backend 1.9.7 -> 1.9.8 --- configs/coins/ethereum.json | 6 +++--- configs/coins/ethereum_testnet_ropsten.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configs/coins/ethereum.json b/configs/coins/ethereum.json index 5c89ef26..9af6568c 100644 --- a/configs/coins/ethereum.json +++ b/configs/coins/ethereum.json @@ -21,10 +21,10 @@ "package_name": "backend-ethereum", "package_revision": "satoshilabs-1", "system_user": "ethereum", - "version": "1.9.7-a718daa6", - "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.7-a718daa6.tar.gz", + "version": "1.9.8-d62e9b28", + "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.8-d62e9b28.tar.gz", "verification_type": "gpg", - "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.7-a718daa6.tar.gz.asc", + "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.8-d62e9b28.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/geth --ipcdisable --syncmode full --cache 1024 --nat none --datadir {{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend --port 38336 --ws --wsaddr 0.0.0.0 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" --rpc --rpcport 8136 -rpcaddr 0.0.0.0 --rpccorsdomain \"*\" --rpcvhosts \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'", diff --git a/configs/coins/ethereum_testnet_ropsten.json b/configs/coins/ethereum_testnet_ropsten.json index 1d193182..00b796dd 100644 --- a/configs/coins/ethereum_testnet_ropsten.json +++ b/configs/coins/ethereum_testnet_ropsten.json @@ -20,10 +20,10 @@ "package_name": "backend-ethereum-testnet-ropsten", "package_revision": "satoshilabs-1", "system_user": "ethereum", - "version": "1.9.7-a718daa6", - "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.7-a718daa6.tar.gz", + "version": "1.9.8-d62e9b28", + "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.8-d62e9b28.tar.gz", "verification_type": "gpg", - "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.7-a718daa6.tar.gz.asc", + "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.8-d62e9b28.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/geth --testnet --syncmode full --ipcdisable --cache 1024 --nat none --datadir {{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend --port 48336 --ws --wsaddr 0.0.0.0 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'", From 0a177d554c3b9f27f7703e95521f5066b52d6b41 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Fri, 29 Nov 2019 10:41:16 +0100 Subject: [PATCH 23/31] bch (+testnet): Bump backend 0.20.6 -> 0.20.7 --- configs/coins/bcash.json | 8 ++++---- configs/coins/bcash_testnet.json | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/configs/coins/bcash.json b/configs/coins/bcash.json index 35a2d8e5..5e5d29e2 100644 --- a/configs/coins/bcash.json +++ b/configs/coins/bcash.json @@ -22,10 +22,10 @@ "package_name": "backend-bcash", "package_revision": "satoshilabs-1", "system_user": "bcash", - "version": "0.20.6", - "binary_url": "https://download.bitcoinabc.org/0.20.6/linux/bitcoin-abc-0.20.6-x86_64-linux-gnu.tar.gz", + "version": "0.20.7", + "binary_url": "https://download.bitcoinabc.org/0.20.7/linux/bitcoin-abc-0.20.7-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "f5fb4a3dac6164709dbf0632f64adfe56414d260e4bf192effc0049da9c43bac", + "verification_source": "a8ccb15b2eb37e7dc0790fb72e5f31fba9c7df5134df2110eaf59724636b64ef", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -49,7 +49,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Bitcoin ABC:0.20.6/", + "subversion": "/Bitcoin ABC:0.20.7/", "address_format": "cashaddr", "mempool_workers": 8, "mempool_sub_workers": 2, diff --git a/configs/coins/bcash_testnet.json b/configs/coins/bcash_testnet.json index a7c90fed..471fed14 100644 --- a/configs/coins/bcash_testnet.json +++ b/configs/coins/bcash_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-bcash-testnet", "package_revision": "satoshilabs-1", "system_user": "bcash", - "version": "0.20.6", - "binary_url": "https://download.bitcoinabc.org/0.20.6/linux/bitcoin-abc-0.20.6-x86_64-linux-gnu.tar.gz", + "version": "0.20.7", + "binary_url": "https://download.bitcoinabc.org/0.20.7/linux/bitcoin-abc-0.20.7-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "f5fb4a3dac6164709dbf0632f64adfe56414d260e4bf192effc0049da9c43bac", + "verification_source": "a8ccb15b2eb37e7dc0790fb72e5f31fba9c7df5134df2110eaf59724636b64ef", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/bitcoin-qt" @@ -49,7 +49,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Bitcoin ABC:0.20.6/", + "subversion": "/Bitcoin ABC:0.20.7/", "address_format": "cashaddr", "mempool_workers": 8, "mempool_sub_workers": 2, From 76beadef8bdb0f6d27410683b0ce3b7c7e169482 Mon Sep 17 00:00:00 2001 From: thebevrishot Date: Tue, 3 Dec 2019 13:11:46 +0700 Subject: [PATCH 24/31] Bump Zcoin to 0.13.8.8 --- configs/coins/zcoin.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/configs/coins/zcoin.json b/configs/coins/zcoin.json index c239f8a7..420dcdd1 100644 --- a/configs/coins/zcoin.json +++ b/configs/coins/zcoin.json @@ -22,15 +22,16 @@ "package_name": "backend-zcoin", "package_revision": "satoshilabs-1", "system_user": "zcoin", - "version": "0.13.8.5", - "binary_url": "https://github.com/zcoinofficial/zcoin/releases/download/v0.13.8.5/zcoin-0.13.8.5-linux64.tar.gz", + "version": "0.13.8.8", + "binary_url": "https://github.com/zcoinofficial/zcoin/releases/download/v0.13.8.8/zcoin-0.13.8.8-linux64.tar.gz", "verification_type": "sha256", - "verification_source": "52f8a722bb1cc5c53e77edf81f6f1300f3b15d53f9cb4fcee90367f11ad84dd9", + "verification_source": "badab4c7e42cb7ce567c1e02a700b52f7ea3f55780e4e180b89596ad940f7189", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/tor", "bin/tor-gencert", "bin/tor-print-ed-signing-cert", + "bin/torify", "bin/tor-resolve", "bin/zcoin-qt", "bin/zcoin-tx", From 3ac22a7571d256ccfbd9ae7c4b49713d23da6873 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Fri, 6 Dec 2019 13:20:55 +0100 Subject: [PATCH 25/31] eth (+testnet): Bump backend 1.9.8 -> 1.9.9 --- configs/coins/ethereum.json | 6 +++--- configs/coins/ethereum_testnet_ropsten.json | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/configs/coins/ethereum.json b/configs/coins/ethereum.json index 9af6568c..cafac864 100644 --- a/configs/coins/ethereum.json +++ b/configs/coins/ethereum.json @@ -21,10 +21,10 @@ "package_name": "backend-ethereum", "package_revision": "satoshilabs-1", "system_user": "ethereum", - "version": "1.9.8-d62e9b28", - "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.8-d62e9b28.tar.gz", + "version": "1.9.9-01744997", + "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.9-01744997.tar.gz", "verification_type": "gpg", - "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.8-d62e9b28.tar.gz.asc", + "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.9-01744997.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/geth --ipcdisable --syncmode full --cache 1024 --nat none --datadir {{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend --port 38336 --ws --wsaddr 0.0.0.0 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" --rpc --rpcport 8136 -rpcaddr 0.0.0.0 --rpccorsdomain \"*\" --rpcvhosts \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'", diff --git a/configs/coins/ethereum_testnet_ropsten.json b/configs/coins/ethereum_testnet_ropsten.json index 00b796dd..9ed31ec8 100644 --- a/configs/coins/ethereum_testnet_ropsten.json +++ b/configs/coins/ethereum_testnet_ropsten.json @@ -20,10 +20,10 @@ "package_name": "backend-ethereum-testnet-ropsten", "package_revision": "satoshilabs-1", "system_user": "ethereum", - "version": "1.9.8-d62e9b28", - "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.8-d62e9b28.tar.gz", + "version": "1.9.9-01744997", + "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.9-01744997.tar.gz", "verification_type": "gpg", - "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.8-d62e9b28.tar.gz.asc", + "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.9-01744997.tar.gz.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [], "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/geth --testnet --syncmode full --ipcdisable --cache 1024 --nat none --datadir {{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend --port 48336 --ws --wsaddr 0.0.0.0 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'", From cd3cad423a84008b98c4329ebd92857b9e9cf423 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Sat, 7 Dec 2019 11:30:00 +0100 Subject: [PATCH 26/31] nmc: Bump backend 0.18.0 -> 0.19.0 --- configs/coins/namecoin.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configs/coins/namecoin.json b/configs/coins/namecoin.json index 5e73cae7..d77ba27e 100644 --- a/configs/coins/namecoin.json +++ b/configs/coins/namecoin.json @@ -22,10 +22,10 @@ "package_name": "backend-namecoin", "package_revision": "satoshilabs-1", "system_user": "namecoin", - "version": "0.18.0", - "binary_url": "https://beta.namecoin.org/files/namecoin-core/namecoin-core-0.18.0/namecoin-0.18.0-x86_64-linux-gnu.tar.gz", + "version": "0.19.0", + "binary_url": "https://www.namecoin.org/files/namecoin-core/namecoin-core-0.19.0/namecoin-0.19.0-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "27a1bbe2fe89bd60519adf48c08058f7b572ebc158a91454541d3f6174ab7256", + "verification_source": "43d3a0084a5cffce819911162a3191165942db9fcd5da8783fe48ca21327c1bb", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/namecoin-qt" From beeddef239362db7cb0b71007977b3e771d7f120 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Tue, 10 Dec 2019 19:59:13 +0100 Subject: [PATCH 27/31] nmc: Bump backend 0.19.0 -> 0.19.0.1 --- configs/coins/namecoin.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/configs/coins/namecoin.json b/configs/coins/namecoin.json index d77ba27e..7c2bc93b 100644 --- a/configs/coins/namecoin.json +++ b/configs/coins/namecoin.json @@ -22,10 +22,10 @@ "package_name": "backend-namecoin", "package_revision": "satoshilabs-1", "system_user": "namecoin", - "version": "0.19.0", - "binary_url": "https://www.namecoin.org/files/namecoin-core/namecoin-core-0.19.0/namecoin-0.19.0-x86_64-linux-gnu.tar.gz", + "version": "0.19.0.1", + "binary_url": "https://www.namecoin.org/files/namecoin-core/namecoin-core-0.19.0.1/namecoin-0.19.0.1-x86_64-linux-gnu.tar.gz", "verification_type": "sha256", - "verification_source": "43d3a0084a5cffce819911162a3191165942db9fcd5da8783fe48ca21327c1bb", + "verification_source": "16acef267c5458ea3f5a7fdfd3482bb32102143ce24a94951a044dc53bc7021b", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/namecoin-qt" From 81ca37e51f04bd0f029367d1a9878de541c931a5 Mon Sep 17 00:00:00 2001 From: Jan Hrnko Date: Tue, 10 Dec 2019 20:22:08 +0100 Subject: [PATCH 28/31] dash (+testnet): Bump backend 0.14.0.4 -> 0.14.0.5 --- configs/coins/dash.json | 8 ++++---- configs/coins/dash_testnet.json | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/configs/coins/dash.json b/configs/coins/dash.json index a08da006..b4e8ba65 100644 --- a/configs/coins/dash.json +++ b/configs/coins/dash.json @@ -22,10 +22,10 @@ "package_name": "backend-dash", "package_revision": "satoshilabs-1", "system_user": "dash", - "version": "0.14.0.4", - "binary_url": "https://github.com/dashpay/dash/releases/download/v0.14.0.4/dashcore-0.14.0.4-x86_64-linux-gnu.tar.gz", + "version": "0.14.0.5", + "binary_url": "https://github.com/dashpay/dash/releases/download/v0.14.0.5/dashcore-0.14.0.5-x86_64-linux-gnu.tar.gz", "verification_type": "gpg-sha256", - "verification_source": "https://github.com/dashpay/dash/releases/download/v0.14.0.4/SHA256SUMS.asc", + "verification_source": "https://github.com/dashpay/dash/releases/download/v0.14.0.5/SHA256SUMS.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/dash-qt" @@ -52,7 +52,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Dash Core:0.14.0.4/", + "subversion": "/Dash Core:0.14.0.5/", "mempool_workers": 8, "mempool_sub_workers": 2, "block_addresses_to_keep": 300, diff --git a/configs/coins/dash_testnet.json b/configs/coins/dash_testnet.json index 32ae5f07..7fbb63ae 100644 --- a/configs/coins/dash_testnet.json +++ b/configs/coins/dash_testnet.json @@ -22,10 +22,10 @@ "package_name": "backend-dash-testnet", "package_revision": "satoshilabs-1", "system_user": "dash", - "version": "0.14.0.4", - "binary_url": "https://github.com/dashpay/dash/releases/download/v0.14.0.4/dashcore-0.14.0.4-x86_64-linux-gnu.tar.gz", + "version": "0.14.0.5", + "binary_url": "https://github.com/dashpay/dash/releases/download/v0.14.0.5/dashcore-0.14.0.5-x86_64-linux-gnu.tar.gz", "verification_type": "gpg-sha256", - "verification_source": "https://github.com/dashpay/dash/releases/download/v0.14.0.4/SHA256SUMS.asc", + "verification_source": "https://github.com/dashpay/dash/releases/download/v0.14.0.5/SHA256SUMS.asc", "extract_command": "tar -C backend --strip 1 -xf", "exclude_files": [ "bin/dash-qt" @@ -52,7 +52,7 @@ "additional_params": "", "block_chain": { "parse": true, - "subversion": "/Dash Core:0.14.0.4/", + "subversion": "/Dash Core:0.14.0.5/", "mempool_workers": 8, "mempool_sub_workers": 2, "block_addresses_to_keep": 300, From 15e2c0bf4165f4f87d2a7894a6077f20cb9fa4c0 Mon Sep 17 00:00:00 2001 From: Martin Boehm Date: Tue, 17 Dec 2019 14:37:24 +0100 Subject: [PATCH 29/31] Add websocket method getBalanceHistory --- api/types.go | 3 +- api/xpub.go | 4 +- server/public.go | 2 +- server/public_test.go | 44 ++++++++++++-- server/websocket.go | 30 ++++++++++ static/test-websocket.html | 120 ++++++++++++++++++++++++------------- 6 files changed, 153 insertions(+), 50 deletions(-) diff --git a/api/types.go b/api/types.go index e98634bd..66acb903 100644 --- a/api/types.go +++ b/api/types.go @@ -299,10 +299,11 @@ func (a Utxos) Less(i, j int) bool { // BalanceHistory contains info about one point in time of balance history type BalanceHistory struct { - Time uint32 `json:"blockTime"` + Time uint32 `json:"time"` Txs uint32 `json:"txs"` ReceivedSat *Amount `json:"received"` SentSat *Amount `json:"sent"` + FiatRate string `json:"fiatrate,omitempty"` Txid string `json:"txid,omitempty"` } diff --git a/api/xpub.go b/api/xpub.go index 5e014b96..f33af72f 100644 --- a/api/xpub.go +++ b/api/xpub.go @@ -590,8 +590,8 @@ func (w *Worker) GetXpubUtxo(xpub string, onlyConfirmed bool, gap int) (Utxos, e return r, nil } -// GetUtxoBalanceHistory returns history of balance for given xpub -func (w *Worker) GetUtxoBalanceHistory(xpub string, fromTime, toTime time.Time, gap int) (BalanceHistories, error) { +// GetXpubBalanceHistory returns history of balance for given xpub +func (w *Worker) GetXpubBalanceHistory(xpub string, fromTime, toTime time.Time, gap int) (BalanceHistories, error) { bhs := make(BalanceHistories, 0) start := time.Now() fromUnix, fromHeight, toUnix, toHeight := w.balanceHistoryHeightsFromTo(fromTime, toTime) diff --git a/server/public.go b/server/public.go index 535f178e..e128cdb3 100644 --- a/server/public.go +++ b/server/public.go @@ -1058,7 +1058,7 @@ func (s *PublicServer) apiBalanceHistory(r *http.Request, apiVersion int) (inter // time.RFC3339 toTime, _ = time.Parse("2006-01-02", t) } - history, err = s.api.GetUtxoBalanceHistory(r.URL.Path[i+1:], fromTime, toTime, gap) + history, err = s.api.GetXpubBalanceHistory(r.URL.Path[i+1:], fromTime, toTime, gap) if err == nil { s.metrics.ExplorerViews.With(common.Labels{"action": "api-xpub-balancehistory"}).Inc() } else { diff --git a/server/public_test.go b/server/public_test.go index 014f4b83..f609bce1 100644 --- a/server/public_test.go +++ b/server/public_test.go @@ -752,7 +752,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `[{"blockTime":1521514800,"txs":1,"received":"12345","sent":"0"},{"blockTime":1521594000,"txs":1,"received":"0","sent":"12345"}]`, + `[{"time":1521514800,"txs":1,"received":"12345","sent":"0"},{"time":1521594000,"txs":1,"received":"0","sent":"12345"}]`, }, }, { @@ -761,7 +761,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `[{"blockTime":1521514800,"txs":1,"received":"9876","sent":"0"},{"blockTime":1521594000,"txs":1,"received":"9000","sent":"9876"}]`, + `[{"time":1521514800,"txs":1,"received":"9876","sent":"0"},{"time":1521594000,"txs":1,"received":"9000","sent":"9876"}]`, }, }, { @@ -770,7 +770,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `[{"blockTime":1521514800,"txs":1,"received":"12345","sent":"0"}]`, + `[{"time":1521514800,"txs":1,"received":"12345","sent":"0"}]`, }, }, { @@ -779,7 +779,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `[{"blockTime":1521514800,"txs":1,"received":"1","sent":"0"},{"blockTime":1521594000,"txs":1,"received":"118641975500","sent":"1"}]`, + `[{"time":1521514800,"txs":1,"received":"1","sent":"0"},{"time":1521594000,"txs":1,"received":"118641975500","sent":"1"}]`, }, }, { @@ -788,7 +788,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `[{"blockTime":1521514800,"txs":1,"received":"1","sent":"0"}]`, + `[{"time":1521514800,"txs":1,"received":"1","sent":"0"}]`, }, }, { @@ -797,7 +797,7 @@ func httpTestsBitcoinType(t *testing.T, ts *httptest.Server) { status: http.StatusOK, contentType: "application/json; charset=utf-8", body: []string{ - `[{"blockTime":1521594000,"txs":1,"received":"118641975500","sent":"1"}]`, + `[{"time":1521594000,"txs":1,"received":"118641975500","sent":"1"}]`, }, }, { @@ -1309,6 +1309,38 @@ func websocketTestsBitcoinType(t *testing.T, ts *httptest.Server) { }, want: `{"id":"30","data":{"data_timestamp":"20191121140000","available_currencies":["eur","usd"]}}`, }, + { + name: "websocket getBalanceHistory Addr2", + req: websocketReq{ + Method: "getBalanceHistory", + Params: map[string]interface{}{ + "descriptor": "mtGXQvBowMkBpnhLckhxhbwYK44Gs9eEtz", + }, + }, + want: `{"id":"31","data":[{"time":1521514800,"txs":1,"received":"12345","sent":"0"},{"time":1521594000,"txs":1,"received":"0","sent":"12345"}]}`, + }, + { + name: "websocket getBalanceHistory xpub", + req: websocketReq{ + Method: "getBalanceHistory", + Params: map[string]interface{}{ + "descriptor": dbtestdata.Xpub, + }, + }, + want: `{"id":"32","data":[{"time":1521514800,"txs":1,"received":"1","sent":"0"},{"time":1521594000,"txs":1,"received":"118641975500","sent":"1"}]}`, + }, + { + name: "websocket getBalanceHistory xpub from=2018-03-20&to=2018-03-21", + req: websocketReq{ + Method: "getBalanceHistory", + Params: map[string]interface{}{ + "descriptor": dbtestdata.Xpub, + "from": "2018-03-20", + "to": "2018-03-21", + }, + }, + want: `{"id":"33","data":[{"time":1521514800,"txs":1,"received":"1","sent":"0"}]}`, + }, } // send all requests at once diff --git a/server/websocket.go b/server/websocket.go index fa47835b..112fde63 100644 --- a/server/websocket.go +++ b/server/websocket.go @@ -253,6 +253,36 @@ var requestHandlers = map[string]func(*WebsocketServer, *websocketChannel, *webs } return }, + "getBalanceHistory": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { + r := struct { + Descriptor string `json:"descriptor"` + From string `json:"from"` + To string `json:"to"` + Fiat string `json:"fiat"` + Gap int `json:"gap"` + }{} + err = json.Unmarshal(req.Params, &r) + if err == nil { + var fromTime, toTime time.Time + if r.From != "" { + fromTime, err = time.Parse("2006-01-02", r.From) + if err != nil { + return + } + } + if r.To != "" { + toTime, err = time.Parse("2006-01-02", r.To) + if err != nil { + return + } + } + rv, err = s.api.GetXpubBalanceHistory(r.Descriptor, fromTime, toTime, r.Gap) + if err != nil { + rv, err = s.api.GetBalanceHistory(r.Descriptor, fromTime, toTime) + } + } + return + }, "getTransaction": func(s *WebsocketServer, c *websocketChannel, req *websocketReq) (rv interface{}, err error) { r := struct { Txid string `json:"txid"` diff --git a/static/test-websocket.html b/static/test-websocket.html index ae9c2504..efe27efd 100644 --- a/static/test-websocket.html +++ b/static/test-websocket.html @@ -161,6 +161,25 @@ }); } + function getBalanceHistory() { + const descriptor = document.getElementById('getBalanceHistoryDescriptor').value.trim(); + const from = parseInt(document.getElementById("getBalanceHistoryFrom").value); + const to = parseInt(document.getElementById("getBalanceHistoryTo").value); + const fiat = document.getElementById("getBalanceHistoryFiat").value.trim(); + const method = 'getBalanceHistory'; + const params = { + descriptor, + from, + to, + fiat + // default gap=20 + }; + send(method, params, function (result) { + document.getElementById('getBalanceHistoryResult').innerText = JSON.stringify(result).replace(/,/g, ", "); + }); + } + + function getTransaction() { const txid = document.getElementById('getTransactionTxid').value.trim(); const method = 'getTransaction'; @@ -431,6 +450,26 @@
+
+
+ +
+
+
+ +
+
+ + + +
+
+
+
+
+
+
+
@@ -492,6 +531,42 @@
+
+
+ +
+
+ +
+
+ +
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
+
+
+ +
+
+ +
+
+
+
+
@@ -524,52 +599,16 @@
-
- -
-
- -
-
- -
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
-
- -
-
- -
-
-
-
-
-
-
+
-
+
-
+
-
+
@@ -577,6 +616,7 @@
+