diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
deleted file mode 100644
index 3eea619e9d..0000000000
--- a/.gitlab-ci.yml
+++ /dev/null
@@ -1,193 +0,0 @@
-stages:
- - build
- - test
- - backend-deploy-and-test
-
-build:
- stage: build
- only:
- - master
- tags:
- - blockbook
- script: make build
-
-unit-test:
- stage: test
- only:
- - master
- tags:
- - blockbook
- script: make test
-
-integration-test:
- stage: test
- only:
- - schedules
- tags:
- - blockbook
- script: make test-integration ARGS="-run='TestIntegration/(bcash|bgold|bitcoin|dash|dogecoin|litecoin|vertcoin|zcash|syscoin)=main/'"
-
-backend-deploy-and-test-bcash:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/bcash.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh bcash
-
-backend-deploy-and-test-bgold:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/bgold.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh bgold
-
-backend-deploy-and-test-bitcoin:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/bitcoin.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh bitcoin
-
-backend-deploy-and-test-dash:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/dash.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh dash
-
-backend-deploy-and-test-digibyte:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/digibyte.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh digibyte
-
-backend-deploy-and-test-dogecoin:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/dogecoin.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh dogecoin
-
-backend-deploy-and-test-litecoin:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/litecoin.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh litecoin
-
-backend-deploy-and-test-namecoin:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/namecoin.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh namecoin
-
-backend-deploy-and-test-vertcoin:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/vertcoin.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh vertcoin
-
-backend-deploy-and-test-zcash:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/zcash.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh zcash
-
-backend-deploy-and-test-bitcoin_testnet:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/bitcoin_testnet.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh bitcoin_testnet bitcoin-testnet bitcoin=test testnet3/debug.log
-
-backend-deploy-and-test-zcash_testnet:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/zcash_testnet.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh zcash_testnet zcash-testnet zcash=test testnet3/debug.log
-
-backend-deploy-and-test-ethereum_testnet_ropsten:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/ethereum_testnet_ropsten.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh ethereum_testnet_ropsten ethereum-testnet-ropsten ethereum=test ethereum_testnet_ropsten.log
-
-backend-deploy-and-test-syscoin:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/syscoin.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh syscoin
-
-backend-deploy-and-test-syscoin_testnet:
- stage: backend-deploy-and-test
- only:
- refs:
- - master
- changes:
- - configs/coins/syscoin_testnet.json
- tags:
- - blockbook
- script: ./contrib/scripts/backend-deploy-and-test.sh syscoin_testnet syscoin-testnet syscoin=test testnet3/debug.log
diff --git a/bchain/coins/eth/erc20.go b/bchain/coins/eth/erc20.go
deleted file mode 100644
index 9870079c7e..0000000000
--- a/bchain/coins/eth/erc20.go
+++ /dev/null
@@ -1,245 +0,0 @@
-package eth
-
-import (
- "bytes"
- "context"
- "encoding/hex"
- "math/big"
- "strings"
- "sync"
- "unicode/utf8"
-
- ethcommon "github.com/ethereum/go-ethereum/common"
- "github.com/golang/glog"
- "github.com/juju/errors"
- "github.com/syscoin/blockbook/bchain"
-)
-
-var erc20abi = `[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","signature":"0x06fdde03"},
-{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","signature":"0x95d89b41"},
-{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint8"}],"payable":false,"type":"function","signature":"0x313ce567"},
-{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"type":"function","signature":"0x18160ddd"},
-{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"type":"function","signature":"0x70a08231"},
-{"constant":false,"inputs":[{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transfer","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function","signature":"0xa9059cbb"},
-{"constant":false,"inputs":[{"name":"_from","type":"address"},{"name":"_to","type":"address"},{"name":"_value","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function","signature":"0x23b872dd"},
-{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"}],"name":"approve","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function","signature":"0x095ea7b3"},
-{"constant":true,"inputs":[{"name":"_owner","type":"address"},{"name":"_spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"type":"function","signature":"0xdd62ed3e"},
-{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event","signature":"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"},
-{"anonymous":false,"inputs":[{"indexed":true,"name":"_owner","type":"address"},{"indexed":true,"name":"_spender","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Approval","type":"event","signature":"0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925"},
-{"inputs":[{"name":"_initialAmount","type":"uint256"},{"name":"_tokenName","type":"string"},{"name":"_decimalUnits","type":"uint8"},{"name":"_tokenSymbol","type":"string"}],"payable":false,"type":"constructor"},
-{"constant":false,"inputs":[{"name":"_spender","type":"address"},{"name":"_value","type":"uint256"},{"name":"_extraData","type":"bytes"}],"name":"approveAndCall","outputs":[{"name":"success","type":"bool"}],"payable":false,"type":"function","signature":"0xcae9ca51"},
-{"constant":true,"inputs":[],"name":"version","outputs":[{"name":"","type":"string"}],"payable":false,"type":"function","signature":"0x54fd4d50"}]`
-
-// doing the parsing/processing without using go-ethereum/accounts/abi library, it is simple to get data from Transfer event
-const erc20TransferMethodSignature = "0xa9059cbb"
-const erc20TransferEventSignature = "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef"
-const erc20NameSignature = "0x06fdde03"
-const erc20SymbolSignature = "0x95d89b41"
-const erc20DecimalsSignature = "0x313ce567"
-const erc20BalanceOf = "0x70a08231"
-
-var cachedContracts = make(map[string]*bchain.Erc20Contract)
-var cachedContractsMux sync.Mutex
-
-func addressFromPaddedHex(s string) (string, error) {
- var t big.Int
- var ok bool
- if has0xPrefix(s) {
- _, ok = t.SetString(s[2:], 16)
- } else {
- _, ok = t.SetString(s, 16)
- }
- if !ok {
- return "", errors.New("Data is not a number")
- }
- a := ethcommon.BigToAddress(&t)
- return a.String(), nil
-}
-
-func erc20GetTransfersFromLog(logs []*rpcLog) ([]bchain.Erc20Transfer, error) {
- var r []bchain.Erc20Transfer
- for _, l := range logs {
- if len(l.Topics) == 3 && l.Topics[0] == erc20TransferEventSignature {
- var t big.Int
- _, ok := t.SetString(l.Data, 0)
- if !ok {
- return nil, errors.New("Data is not a number")
- }
- from, err := addressFromPaddedHex(l.Topics[1])
- if err != nil {
- return nil, err
- }
- to, err := addressFromPaddedHex(l.Topics[2])
- if err != nil {
- return nil, err
- }
- r = append(r, bchain.Erc20Transfer{
- Contract: EIP55AddressFromAddress(l.Address),
- From: EIP55AddressFromAddress(from),
- To: EIP55AddressFromAddress(to),
- Tokens: t,
- })
- }
- }
- return r, nil
-}
-
-func erc20GetTransfersFromTx(tx *rpcTransaction) ([]bchain.Erc20Transfer, error) {
- var r []bchain.Erc20Transfer
- if len(tx.Payload) == 128+len(erc20TransferMethodSignature) && strings.HasPrefix(tx.Payload, erc20TransferMethodSignature) {
- to, err := addressFromPaddedHex(tx.Payload[len(erc20TransferMethodSignature) : 64+len(erc20TransferMethodSignature)])
- if err != nil {
- return nil, err
- }
- var t big.Int
- _, ok := t.SetString(tx.Payload[len(erc20TransferMethodSignature)+64:], 16)
- if !ok {
- return nil, errors.New("Data is not a number")
- }
- r = append(r, bchain.Erc20Transfer{
- Contract: EIP55AddressFromAddress(tx.To),
- From: EIP55AddressFromAddress(tx.From),
- To: EIP55AddressFromAddress(to),
- Tokens: t,
- })
- }
- return r, nil
-}
-
-func (b *EthereumRPC) ethCall(data, to string) (string, error) {
- ctx, cancel := context.WithTimeout(context.Background(), b.timeout)
- defer cancel()
- var r string
- err := b.rpc.CallContext(ctx, &r, "eth_call", map[string]interface{}{
- "data": data,
- "to": to,
- }, "latest")
- if err != nil {
- return "", err
- }
- return r, nil
-}
-
-func parseErc20NumericProperty(contractDesc bchain.AddressDescriptor, data string) *big.Int {
- if has0xPrefix(data) {
- data = data[2:]
- }
- if len(data) > 64 {
- data = data[:64]
- }
- if len(data) == 64 {
- var n big.Int
- _, ok := n.SetString(data, 16)
- if ok {
- return &n
- }
- }
- if glog.V(1) {
- glog.Warning("Cannot parse '", data, "' for contract ", contractDesc)
- }
- return nil
-}
-
-func parseErc20StringProperty(contractDesc bchain.AddressDescriptor, data string) string {
- if has0xPrefix(data) {
- data = data[2:]
- }
- if len(data) > 128 {
- n := parseErc20NumericProperty(contractDesc, data[64:128])
- if n != nil {
- l := n.Uint64()
- if l > 0 && 2*int(l) <= len(data)-128 {
- b, err := hex.DecodeString(data[128 : 128+2*l])
- if err == nil {
- return string(b)
- }
- }
- }
- }
- // allow string properties as UTF-8 data
- b, err := hex.DecodeString(data)
- if err == nil {
- i := bytes.Index(b, []byte{0})
- if i > 32 {
- i = 32
- }
- if i > 0 {
- b = b[:i]
- }
- if utf8.Valid(b) {
- return string(b)
- }
- }
- if glog.V(1) {
- glog.Warning("Cannot parse '", data, "' for contract ", contractDesc)
- }
- return ""
-}
-
-// EthereumTypeGetErc20ContractInfo returns information about ERC20 contract
-func (b *EthereumRPC) EthereumTypeGetErc20ContractInfo(contractDesc bchain.AddressDescriptor) (*bchain.Erc20Contract, error) {
- cds := string(contractDesc)
- cachedContractsMux.Lock()
- contract, found := cachedContracts[cds]
- cachedContractsMux.Unlock()
- if !found {
- address := EIP55Address(contractDesc)
- data, err := b.ethCall(erc20NameSignature, address)
- if err != nil {
- // ignore the error from the eth_call - since geth v1.9.15 they changed the behavior
- // and returning error "execution reverted" for some non contract addresses
- // https://github.com/ethereum/go-ethereum/issues/21249#issuecomment-648647672
- glog.Warning(errors.Annotatef(err, "erc20NameSignature %v", address))
- return nil, nil
- // return nil, errors.Annotatef(err, "erc20NameSignature %v", address)
- }
- name := parseErc20StringProperty(contractDesc, data)
- if name != "" {
- data, err = b.ethCall(erc20SymbolSignature, address)
- if err != nil {
- glog.Warning(errors.Annotatef(err, "erc20SymbolSignature %v", address))
- return nil, nil
- // return nil, errors.Annotatef(err, "erc20SymbolSignature %v", address)
- }
- symbol := parseErc20StringProperty(contractDesc, data)
- data, err = b.ethCall(erc20DecimalsSignature, address)
- if err != nil {
- glog.Warning(errors.Annotatef(err, "erc20DecimalsSignature %v", address))
- // return nil, errors.Annotatef(err, "erc20DecimalsSignature %v", address)
- }
- contract = &bchain.Erc20Contract{
- Contract: address,
- Name: name,
- Symbol: symbol,
- }
- d := parseErc20NumericProperty(contractDesc, data)
- if d != nil {
- contract.Decimals = int(uint8(d.Uint64()))
- } else {
- contract.Decimals = EtherAmountDecimalPoint
- }
- } else {
- contract = nil
- }
- cachedContractsMux.Lock()
- cachedContracts[cds] = contract
- cachedContractsMux.Unlock()
- }
- return contract, nil
-}
-
-// EthereumTypeGetErc20ContractBalance returns balance of ERC20 contract for given address
-func (b *EthereumRPC) EthereumTypeGetErc20ContractBalance(addrDesc, contractDesc bchain.AddressDescriptor) (*big.Int, error) {
- addr := EIP55Address(addrDesc)
- contract := EIP55Address(contractDesc)
- req := erc20BalanceOf + "0000000000000000000000000000000000000000000000000000000000000000"[len(addr)-2:] + addr[2:]
- data, err := b.ethCall(req, contract)
- if err != nil {
- return nil, err
- }
- r := parseErc20NumericProperty(contractDesc, data)
- if r == nil {
- return nil, errors.New("Invalid balance")
- }
- return r, nil
-}
diff --git a/bchain/coins/eth/erc20_test.go b/bchain/coins/eth/erc20_test.go
deleted file mode 100644
index 96879ff3fe..0000000000
--- a/bchain/coins/eth/erc20_test.go
+++ /dev/null
@@ -1,204 +0,0 @@
-//go:build unittest
-
-package eth
-
-import (
- "fmt"
- "math/big"
- "strings"
- "testing"
-
- "github.com/syscoin/blockbook/bchain"
- "github.com/syscoin/blockbook/tests/dbtestdata"
-)
-
-func TestErc20_erc20GetTransfersFromLog(t *testing.T) {
- tests := []struct {
- name string
- args []*rpcLog
- want []bchain.Erc20Transfer
- wantErr bool
- }{
- {
- name: "1",
- args: []*rpcLog{
- {
- Address: "0x76a45e8976499ab9ae223cc584019341d5a84e96",
- Topics: []string{
- "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
- "0x0000000000000000000000002aacf811ac1a60081ea39f7783c0d26c500871a8",
- "0x000000000000000000000000e9a5216ff992cfa01594d43501a56e12769eb9d2",
- },
- Data: "0x0000000000000000000000000000000000000000000000000000000000000123",
- },
- },
- want: []bchain.Erc20Transfer{
- {
- Contract: "0x76a45e8976499ab9ae223cc584019341d5a84e96",
- From: "0x2aacf811ac1a60081ea39f7783c0d26c500871a8",
- To: "0xe9a5216ff992cfa01594d43501a56e12769eb9d2",
- Tokens: *big.NewInt(0x123),
- },
- },
- },
- {
- name: "2",
- args: []*rpcLog{
- { // Transfer
- Address: "0x0d0f936ee4c93e25944694d6c121de94d9760f11",
- Topics: []string{
- "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
- "0x0000000000000000000000006f44cceb49b4a5812d54b6f494fc2febf25511ed",
- "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d",
- },
- Data: "0x0000000000000000000000000000000000000000000000006a8313d60b1f606b",
- },
- { // Transfer
- Address: "0xc778417e063141139fce010982780140aa0cd5ab",
- Topics: []string{
- "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
- "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d",
- "0x0000000000000000000000006f44cceb49b4a5812d54b6f494fc2febf25511ed",
- },
- Data: "0x000000000000000000000000000000000000000000000000000308fd0e798ac0",
- },
- { // not Transfer
- Address: "0x479cc461fecd078f766ecc58533d6f69580cf3ac",
- Topics: []string{
- "0x0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb3",
- "0x0000000000000000000000006f44cceb49b4a5812d54b6f494fc2febf25511ed",
- "0x0000000000000000000000000000000000000000000000000000000000000000",
- "0x5af266c0a89a07c1917deaa024414577e6c3c31c8907d079e13eb448c082594f",
- },
- Data: "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d0000000000000",
- },
- { // not Transfer
- Address: "0x0d0f936ee4c93e25944694d6c121de94d9760f11",
- Topics: []string{
- "0x0d0b9391970d9a25552f37d436d2aae2925e2bfe1b2a923754bada030c498cb3",
- "0x0000000000000000000000007b62eb7fe80350dc7ec945c0b73242cb9877fb1b",
- "0xb0b69dad58df6032c3b266e19b1045b19c87acd2c06fb0c598090f44b8e263aa",
- },
- Data: "0x0000000000000000000000004bda106325c335df99eab7fe363cac8a0ba2a24d000000000000000000000000c778417e063141139fce010982780140aa0cd5ab0000000000000000000000000d0f936ee4c93e25944694d6c121de94d9760f1100000000000000000000000000000000000000000000000000031855667df7a80000000000000000000000000000000000000000000000006a8313d60b1f800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- },
- },
- want: []bchain.Erc20Transfer{
- {
- Contract: "0x0d0f936ee4c93e25944694d6c121de94d9760f11",
- From: "0x6f44cceb49b4a5812d54b6f494fc2febf25511ed",
- To: "0x4bda106325c335df99eab7fe363cac8a0ba2a24d",
- Tokens: *big.NewInt(0x6a8313d60b1f606b),
- },
- {
- Contract: "0xc778417e063141139fce010982780140aa0cd5ab",
- From: "0x4bda106325c335df99eab7fe363cac8a0ba2a24d",
- To: "0x6f44cceb49b4a5812d54b6f494fc2febf25511ed",
- Tokens: *big.NewInt(0x308fd0e798ac0),
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := erc20GetTransfersFromLog(tt.args)
- if (err != nil) != tt.wantErr {
- t.Errorf("erc20GetTransfersFromLog error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- // the addresses could have different case
- if strings.ToLower(fmt.Sprint(got)) != strings.ToLower(fmt.Sprint(tt.want)) {
- t.Errorf("erc20GetTransfersFromLog = %+v, want %+v", got, tt.want)
- }
- })
- }
-}
-
-func TestErc20_parseErc20StringProperty(t *testing.T) {
- tests := []struct {
- name string
- args string
- want string
- }{
- {
- name: "1",
- args: "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000758504c4f44444500000000000000000000000000000000000000000000000000",
- want: "XPLODDE",
- },
- {
- name: "2",
- args: "0x00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000022426974436c617665202d20436f6e73756d657220416374697669747920546f6b656e00000000000000",
- want: "BitClave - Consumer Activity Token",
- },
- {
- name: "short",
- args: "0x44616920537461626c65636f696e2076312e3000000000000000000000000000",
- want: "Dai Stablecoin v1.0",
- },
- {
- name: "short2",
- args: "0x44616920537461626c65636f696e2076312e3020444444444444444444444444",
- want: "Dai Stablecoin v1.0 DDDDDDDDDDDD",
- },
- {
- name: "long",
- args: "0x556e6973776170205631000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
- want: "Uniswap V1",
- },
- {
- name: "garbage",
- args: "0x2234880850896048596206002535425366538144616734015984380565810000",
- want: "",
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got := parseErc20StringProperty(nil, tt.args)
- // the addresses could have different case
- if got != tt.want {
- t.Errorf("parseErc20StringProperty = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
-func TestErc20_erc20GetTransfersFromTx(t *testing.T) {
- p := NewEthereumParser(1)
- b := dbtestdata.GetTestEthereumTypeBlock1(p)
- bn, _ := new(big.Int).SetString("21e19e0c9bab2400000", 16)
- tests := []struct {
- name string
- args *rpcTransaction
- want []bchain.Erc20Transfer
- }{
- {
- name: "0",
- args: (b.Txs[0].CoinSpecificData.(completeTransaction)).Tx,
- want: []bchain.Erc20Transfer{},
- },
- {
- name: "1",
- args: (b.Txs[1].CoinSpecificData.(completeTransaction)).Tx,
- want: []bchain.Erc20Transfer{
- {
- Contract: "0x4af4114f73d1c1c903ac9e0361b379d1291808a2",
- From: "0x20cd153de35d469ba46127a0c8f18626b59a256a",
- To: "0x555ee11fbddc0e49a9bab358a8941ad95ffdb48f",
- Tokens: *bn,
- },
- },
- },
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := erc20GetTransfersFromTx(tt.args)
- if err != nil {
- t.Errorf("erc20GetTransfersFromTx error = %v", err)
- return
- }
- // the addresses could have different case
- if strings.ToLower(fmt.Sprint(got)) != strings.ToLower(fmt.Sprint(tt.want)) {
- t.Errorf("erc20GetTransfersFromTx = %+v, want %+v", got, tt.want)
- }
- })
- }
-}
diff --git a/build/docker/deb/gpg-keys/bitcoin-releases.asc b/build/docker/deb/gpg-keys/bitcoin-releases.asc
deleted file mode 100644
index 69fc13e838..0000000000
--- a/build/docker/deb/gpg-keys/bitcoin-releases.asc
+++ /dev/null
@@ -1,280 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-Version: GnuPG v1
-
-mQINBFWKlBcBEACgZJd/6LrSgNSVxiyq5N9h0E7zgSHG/ahuWAnWeFtxaxHeukH+
-Q2Zq6F8FLbq40PphyroRylMBpzPBcyxjee7mDj1DpJ9ayv6GGPTyQzOImhChEV8p
-bA42dvXnB5ju0rPh2GxctbiZZD1kiPH4jlmDIgomvupAj9OFntA5jfkuSFBekZrw
-QyZowz/paMBIe24YH2LyaZjC2DqLy8Znh78OfAZxZsWSdZxK5LsbkCE9l8Li3gQa
-rxm4aEMBHhvns+s8Ufa47sdJAYAfVnAWb5Dfe4oVFh70PvB8GSGFS9qeib0eEQBD
-71c9MN+REDTSOYO2VnUSFbu7IrKsPsClqwfT9KzI/uz5fpHSKdCp5AO7oDZiU36s
-LsSOBbukTmFQfVrAniFEZxHLCBufXCsAwp07xtUH9ytbW0Y/eHYlZojoWJJPT//1
-cQ/A2Ix/nxbSkSPq8wpCUhBxvTQoU9BXeQIbSy0yUmj5nS+3DR7IK2Q7ACyVClr7
-LVQOGxgZhHr9Kq87RDqc1wlvbCxb+KTJQhJySpOVoiaME6jLBzgE7G+5N6IXTK5u
-OriOsQwcLdeBu7TPgft79uBYnmYeaNVdovlBB//7H7UvY0kAxAg4NPgK6eYRdzn+
-8ZtbntNXi/23RJvzeZJVBqQ7bYt4fjmHmRYrbM4jWKJEoJOE6wzpmELUowARAQAB
-tFVXbGFkaW1pciBKLiB2YW4gZGVyIExhYW4gKEJpdGNvaW4gQ29yZSBiaW5hcnkg
-cmVsZWFzZSBzaWduaW5nIGtleSkgPGxhYW53akBnbWFpbC5jb20+iQI+BBMBAgAo
-BQJVipQXAhsDBQkDFwQABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRCQyAGe
-NsLpZOBRD/wLfujEC4ZYMFwPXnhvOGEWAPeuOg06iXhEqJ1biOvxhFfwwjPoXGMQ
-i/pdfGck5xZVFcxObpdHBp0p9ardos1aRXAS8JTnTQXTX0qs0QNxnLTBz+5DrIc4
-l7r5DAlr/FapUKNSbjobOrbv+F371b7XhLJ7oob5XXo+IS7kEY+Si5BXb0uVy8ms
-SaKDooO2RfByrFI3LTHW3VESuuNnXgH6309yeGORgBazKtnxZPPlD2raTNXe9q7U
-dF2Xv6Rr53iCGGN5xncL5A6nF3fou0tGvqLFBkrs4BqeNNwC6/jQLfpOfqiQ+XGR
-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
-oUudunjw+G1VG08DA3DMoougS9pC7x9k
-=BFsn
------END PGP PUBLIC KEY BLOCK-----
diff --git a/build/docker/deb/gpg-keys/groestlcoin-releases.asc b/build/docker/deb/gpg-keys/groestlcoin-releases.asc
deleted file mode 100644
index e59835d2ae..0000000000
--- a/build/docker/deb/gpg-keys/groestlcoin-releases.asc
+++ /dev/null
@@ -1,30 +0,0 @@
------BEGIN PGP PUBLIC KEY BLOCK-----
-
-mQENBFxOL0ABCACnC4Im0MjbJpfoxWxkIWC9zugsjckwHC2UbXu5gFjtPbE6bXwK
-IvhQeoHNPxuwm1dOWwWtJvoAoR+lOJqRMhvPM1DBcZe4Ht6XzzWnwx9WRP3lP99a
-J2xOhdwNKv+HCVJ4tbwTTtkWuNWCMiUEjigoULTjKr1mecwoSEnQIRR0ciwxIpG/
-mO1SQdS96sujr3+70LTThIjgdOD1CA5GrwZSMctIPXEGXKXEQ4NL9/Zc8I5G9//y
-8B+TiHTCpoIWfFbYw1GAUkLhswWV+rLNIYQzjxe3w9FD40+s1dU/1DzO2y2gib2n
-G57RnwQ5V6i4axi7buWNzhWqGBXR6xxVIfN1ABEBAAG0J2phY2tpZWxvdmU0dSA8
-amFja2llbG92ZTR1QGhvdG1haWwuY29tPokBVAQTAQgAPhYhBCh65MoRh8aMCLSc
-stEb1PM/HbSZBQJcTi9AAhsDBQkDwxhwBQsJCAcCBhUKCQgLAgQWAgMBAh4BAheA
-AAoJENEb1PM/HbSZFIgIAKaLGqXuahun8Nuds0c33ezqdT6vu4llAJSxX+dAg0Z0
-DKgski4jep1n94qvQXcoFhTcvXNxIv8YATzNx9JyM7SRVPQspr+g0hkzq75XfgsV
-VqW8vPqAB1pdQoaSoK6wFljTA5DKifp7T8sJeNtReCjjSptszhdFaNllHAotz9qj
-EoSHSnq8zlYKcVDnSqDEZozrbTohhWhc4V9VoNcYR8evNSdE8RCS+loVaPUIwANp
-YK39Wxs0uE0j30iC/BY4b1ORP/fP7W3y8bgHscdQ5tEJa53iOFK3AYMhjc4ULZIz
-i1z3rw1CcItWbuF5AbUTpnWRFG2uza6yRwZhcQyUBT+5AQ0EXE4vQAEIALv/X1oH
-8r4uHfzkoQDrVvsjiGeTOVLbwNAqJGHzxWi2brVjlOdffmJGMRWS89trrveXWAIT
-zjgFpkiZubOj/lS2+k5jE/IAakyX+eMUFULZt+6DF5oJBKTkdKaLi11dzJCPmaIv
-fkNz3g68J9RlDJBFVLJzlaFGq6xZ1itbYDPrNjx98f7VhR2XbG/bise9heUpm9YJ
-nJ8u5fjhbo10NNg6nwj7Huhwa+tuTHmQ/yPQ+dh8EeW78uwxrTRZ1DFTRTnFnBS6
-Q3jBI4cte8B0UWtcCZyXOXatShr/V5LTwH/Cxck2uu2X5tczhAWA1I3uZS5vUkJH
-2kl1wWs54Xb/zMkAEQEAAYkBPAQYAQgAJhYhBCh65MoRh8aMCLScstEb1PM/HbSZ
-BQJcTi9AAhsMBQkDwxhwAAoJENEb1PM/HbSZZ4gH/i3uRPk+x9ryedvADloY12uf
-uv4GiJsIu4ZRvTiMrffMfSXl4W5G1Sp8IO2dKUs9pujrzOPPeYnxF/bILuCyve5v
-kbbURwh7/gws6DOV75TmRDLyRhZktW1MWtKaF3ZQqndGgj2r8HWACCFJEYQCp2dN
-UcIerVH9ZgmtsiZja4Kp1cf3SXu6xWLpg1DYhKAWfaGeK59ytP/D7BeIomuFp57i
-lj0o/ThIqOunBQcaQaCSnpuXiPO6pOQZTaapj/xnGWlYcIowcKiUu/qgn4q/oh7P
-oaBLoyLR9Orz09BuwAcpg5PaxV1HiprSU/wNW0cvS2DgdcfUZkYLb0MW6GC/9GA=
-=7/m/
------END PGP PUBLIC KEY BLOCK-----
diff --git a/configs/coins/ethereum_testnet_ropsten.json b/configs/coins/ethereum_testnet_ropsten.json
deleted file mode 100644
index 6d58b5c375..0000000000
--- a/configs/coins/ethereum_testnet_ropsten.json
+++ /dev/null
@@ -1,61 +0,0 @@
-{
- "coin": {
- "name": "Ethereum Testnet Ropsten",
- "shortcut": "tROP",
- "label": "Ethereum Ropsten",
- "alias": "ethereum_testnet_ropsten"
- },
- "ports": {
- "backend_rpc": 18036,
- "backend_message_queue": 0,
- "backend_p2p": 48336,
- "blockbook_internal": 19036,
- "blockbook_public": 19136
- },
- "ipc": {
- "rpc_url_template": "ws://127.0.0.1:{{.Ports.BackendRPC}}",
- "rpc_timeout": 25
- },
- "backend": {
- "package_name": "backend-ethereum-testnet-ropsten",
- "package_revision": "satoshilabs-1",
- "system_user": "ethereum",
- "version": "1.9.24-cc05b050",
- "binary_url": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.24-cc05b050.tar.gz",
- "verification_type": "gpg",
- "verification_source": "https://gethstore.blob.core.windows.net/builds/geth-linux-amd64-1.9.24-cc05b050.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 127.0.0.1 --wsport {{.Ports.BackendRPC}} --wsorigins \"*\" 2>>{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log'",
- "logrotate_files_template": "{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/{{.Coin.Alias}}.log",
- "postinst_script_template": "",
- "service_type": "simple",
- "service_additional_params_template": "",
- "protect_memory": true,
- "mainnet": false,
- "server_config_file": "",
- "client_config_file": ""
- },
- "blockbook": {
- "package_name": "blockbook-ethereum-testnet-ropsten",
- "system_user": "blockbook-ethereum",
- "internal_binding_template": ":{{.Ports.BlockbookInternal}}",
- "public_binding_template": ":{{.Ports.BlockbookPublic}}",
- "explorer_url": "",
- "additional_params": "",
- "block_chain": {
- "parse": true,
- "mempool_workers": 8,
- "mempool_sub_workers": 2,
- "block_addresses_to_keep": 3000,
- "additional_params": {
- "mempoolTxTimeoutHours": 12,
- "queryBackendOnMempoolResync": false
- }
- }
- },
- "meta": {
- "package_maintainer": "IT",
- "package_maintainer_email": "it@satoshilabs.com"
- }
-}
diff --git a/configs/coins/zelcash.json b/configs/coins/zelcash.json
deleted file mode 100644
index c08cf2abd7..0000000000
--- a/configs/coins/zelcash.json
+++ /dev/null
@@ -1,70 +0,0 @@
-{
- "coin": {
- "name": "ZelCash",
- "shortcut": "ZEL",
- "label": "ZelCash",
- "alias": "zelcash"
- },
- "ports": {
- "backend_rpc": 8058,
- "backend_message_queue": 38358,
- "blockbook_internal": 9058,
- "blockbook_public": 9158
- },
- "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-zelcash",
- "package_revision": "satoshilabs-1",
- "system_user": "zelcash",
- "version": "4.0.0",
- "binary_url": "https://github.com/zelcash/zelcash/releases/download/v4.0.0/Zel-Linux.tar.gz",
- "verification_type": "sha256",
- "verification_source": "72fc8edaf5b222e384fd3430babaf13cada8186f1aff84df28984212bc5ea66e",
- "extract_command": "tar -C backend -xf",
- "exclude_files": [],
- "exec_command_template": "{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/zelcashd -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": "HOME={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/fetch-params.sh",
- "service_type": "forking",
- "service_additional_params_template": "Environment=\"HOME={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend\"",
- "protect_memory": false,
- "mainnet": true,
- "server_config_file": "bitcoin_like.conf",
- "client_config_file": "bitcoin_like_client.conf",
- "additional_params": {
- "addnode": [
- "explorer.zel.cash",
- "explorer2.zel.cash",
- "explorer.zelcash.online",
- "explorer-asia.zel.cash"
- ]
- }
- },
- "blockbook": {
- "package_name": "blockbook-zelcash",
- "system_user": "blockbook-zelcash",
- "internal_binding_template": ":{{.Ports.BlockbookInternal}}",
- "public_binding_template": ":{{.Ports.BlockbookPublic}}",
- "explorer_url": "",
- "additional_params": "",
- "block_chain": {
- "parse": true,
- "mempool_workers": 4,
- "mempool_sub_workers": 8,
- "block_addresses_to_keep": 300,
- "xpub_magic": 76067358,
- "slip44": 19167,
- "additional_params": {}
- }
- },
- "meta": {
- "package_maintainer": "Tadeas Kmenta",
- "package_maintainer_email": "tadeas.kmenta@zel.cash"
- }
-}
diff --git a/server/socketio.go b/server/socketio.go
deleted file mode 100644
index 4ce9889428..0000000000
--- a/server/socketio.go
+++ /dev/null
@@ -1,946 +0,0 @@
-package server
-
-import (
- "encoding/json"
- "math/big"
- "net/http"
- "runtime/debug"
- "strconv"
- "strings"
- "time"
- "fmt"
-
- "github.com/golang/glog"
- "github.com/juju/errors"
- gosocketio "github.com/martinboehm/golang-socketio"
- "github.com/martinboehm/golang-socketio/transport"
- "github.com/syscoin/blockbook/api"
- "github.com/syscoin/blockbook/bchain"
- "github.com/syscoin/blockbook/common"
- "github.com/syscoin/blockbook/db"
- ethcommon "github.com/ethereum/go-ethereum/common"
-)
-
-// SocketIoServer is handle to SocketIoServer
-type SocketIoServer struct {
- server *gosocketio.Server
- db *db.RocksDB
- txCache *db.TxCache
- chain bchain.BlockChain
- chainParser bchain.BlockChainParser
- mempool bchain.Mempool
- metrics *common.Metrics
- is *common.InternalState
- api *api.Worker
-}
-
-// NewSocketIoServer creates new SocketIo interface to blockbook and returns its handle
-func NewSocketIoServer(db *db.RocksDB, chain bchain.BlockChain, mempool bchain.Mempool, txCache *db.TxCache, metrics *common.Metrics, is *common.InternalState) (*SocketIoServer, error) {
- api, err := api.NewWorker(db, chain, mempool, txCache, metrics, is)
- if err != nil {
- return nil, err
- }
-
- server := gosocketio.NewServer(transport.GetDefaultWebsocketTransport())
-
- server.On(gosocketio.OnConnection, func(c *gosocketio.Channel) {
- glog.Info("Client connected ", c.Id())
- metrics.SocketIOClients.Inc()
- })
-
- server.On(gosocketio.OnDisconnection, func(c *gosocketio.Channel) {
- glog.Info("Client disconnected ", c.Id())
- metrics.SocketIOClients.Dec()
- })
-
- server.On(gosocketio.OnError, func(c *gosocketio.Channel) {
- glog.Error("Client error ", c.Id())
- })
-
- type Message struct {
- Name string `json:"name"`
- Message string `json:"message"`
- }
- s := &SocketIoServer{
- server: server,
- db: db,
- txCache: txCache,
- chain: chain,
- chainParser: chain.GetChainParser(),
- mempool: mempool,
- metrics: metrics,
- is: is,
- api: api,
- }
-
- server.On("message", s.onMessage)
- server.On("subscribe", s.onSubscribe)
-
- return s, nil
-}
-
-// GetHandler returns socket.io http handler
-func (s *SocketIoServer) GetHandler() http.Handler {
- return s.server
-}
-
-type addrOpts struct {
- Start int `json:"start"`
- End int `json:"end"`
- QueryMempoolOnly bool `json:"queryMempoolOnly"`
- From int `json:"from"`
- To int `json:"to"`
-}
-
-type assetOpts struct {
- Start int `json:"start"`
- End int `json:"end"`
- QueryMempoolOnly bool `json:"queryMempoolOnly"`
- From int `json:"from"`
- To int `json:"to"`
- AssetsMask bchain.AssetsMask
-}
-
-var onMessageHandlers = map[string]func(*SocketIoServer, json.RawMessage) (interface{}, error){
- "getAddressTxids": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- addr, opts, err := unmarshalGetAddressRequest(params)
- if err == nil {
- rv, err = s.getAddressTxids(addr, &opts)
- }
- return
- },
- "getAddressHistory": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- addr, opts, err := unmarshalGetAddressRequest(params)
- if err == nil {
- rv, err = s.getAddressHistory(addr, &opts)
- }
- return
- },
- "getAssetTxids": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- asset, opts, err := unmarshalGetAssetRequest(params)
- if err == nil {
- rv, err = s.getAssetTxids(asset, &opts)
- }
- return
- },
- "getAssetHistory": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- asset, opts, err := unmarshalGetAssetRequest(params)
- if err == nil {
- rv, err = s.getAssetHistory(asset, &opts)
- }
- return
- },
- "getBlockHeader": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- height, hash, err := unmarshalGetBlockHeader(params)
- if err == nil {
- rv, err = s.getBlockHeader(height, hash)
- }
- return
- },
- "estimateSmartFee": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- blocks, conservative, err := unmarshalEstimateSmartFee(params)
- if err == nil {
- rv, err = s.estimateSmartFee(blocks, conservative)
- }
- return
- },
- "estimateFee": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- blocks, err := unmarshalEstimateFee(params)
- if err == nil {
- rv, err = s.estimateFee(blocks)
- }
- return
- },
- "getInfo": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- return s.getInfo()
- },
- "getDetailedTransaction": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- txid, err := unmarshalGetDetailedTransaction(params)
- if err == nil {
- rv, err = s.getDetailedTransaction(txid)
- }
- return
- },
- "sendTransaction": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- tx, err := unmarshalStringParameter(params)
- if err == nil {
- rv, err = s.sendTransaction(tx)
- }
- return
- },
- "getMempoolEntry": func(s *SocketIoServer, params json.RawMessage) (rv interface{}, err error) {
- txid, err := unmarshalStringParameter(params)
- if err == nil {
- rv, err = s.getMempoolEntry(txid)
- }
- return
- },
-}
-
-type resultError struct {
- Error struct {
- Message string `json:"message"`
- } `json:"error"`
-}
-
-func (s *SocketIoServer) onMessage(c *gosocketio.Channel, req map[string]json.RawMessage) (rv interface{}) {
- var err error
- method := strings.Trim(string(req["method"]), "\"")
- defer func() {
- if r := recover(); r != nil {
- glog.Error(c.Id(), " onMessage ", method, " recovered from panic: ", r)
- debug.PrintStack()
- e := resultError{}
- e.Error.Message = "Internal error"
- rv = e
- }
- s.metrics.SocketIOPendingRequests.With((common.Labels{"method": method})).Dec()
- }()
- t := time.Now()
- params := req["params"]
- s.metrics.SocketIOPendingRequests.With((common.Labels{"method": method})).Inc()
- defer s.metrics.SocketIOReqDuration.With(common.Labels{"method": method}).Observe(float64(time.Since(t)) / 1e3) // in microseconds
- f, ok := onMessageHandlers[method]
- if ok {
- rv, err = f(s, params)
- } else {
- err = errors.New("unknown method")
- }
- if err == nil {
- glog.V(1).Info(c.Id(), " onMessage ", method, " success")
- s.metrics.SocketIORequests.With(common.Labels{"method": method, "status": "success"}).Inc()
- return rv
- }
- glog.Error(c.Id(), " onMessage ", method, ": ", errors.ErrorStack(err), ", data ", string(params))
- s.metrics.SocketIORequests.With(common.Labels{"method": method, "status": "failure"}).Inc()
- e := resultError{}
- e.Error.Message = err.Error()
- return e
-}
-
-func unmarshalGetAddressRequest(params []byte) (addr []string, opts addrOpts, err error) {
- var p []json.RawMessage
- err = json.Unmarshal(params, &p)
- if err != nil {
- return
- }
- if len(p) != 2 {
- err = errors.New("incorrect number of parameters")
- return
- }
- err = json.Unmarshal(p[0], &addr)
- if err != nil {
- return
- }
- err = json.Unmarshal(p[1], &opts)
- return
-}
-
-func unmarshalGetAssetRequest(params []byte) (asset string, opts assetOpts, err error) {
- var p []json.RawMessage
- err = json.Unmarshal(params, &p)
- if err != nil {
- return
- }
- if len(p) != 2 {
- err = errors.New("incorrect number of parameters")
- return
- }
- err = json.Unmarshal(p[0], &asset)
- if err != nil {
- return
- }
- err = json.Unmarshal(p[1], &opts)
- return
-}
-
-type resultAddressTxids struct {
- Result []string `json:"result"`
-}
-
-func (s *SocketIoServer) getAddressTxids(addr []string, opts *addrOpts) (res resultAddressTxids, err error) {
- txids := make([]string, 0, 8)
- lower, higher := uint32(opts.End), uint32(opts.Start)
- for _, address := range addr {
- if !opts.QueryMempoolOnly {
- err = s.db.GetTransactions(address, lower, higher, func(txid string, height uint32, assetGuid []uint64, indexes []int32) error {
- txids = append(txids, txid)
- return nil
- })
- if err != nil {
- return res, err
- }
- } else {
- o, err := s.mempool.GetTransactions(address)
- if err != nil {
- return res, err
- }
- for _, m := range o {
- txids = append(txids, m.Txid)
- }
- }
- }
- res.Result = api.GetUniqueTxids(txids)
- return res, nil
-}
-
-func (s *SocketIoServer) getAssetTxids(asset string, opts *assetOpts) (res resultAddressTxids, err error) {
- txids := make([]string, 0, 8)
- lower, higher := uint32(opts.End), uint32(opts.Start)
- assetBitMask := opts.AssetsMask
- assetGuid, err := strconv.ParseUint(asset, 10, 64)
- if err != nil {
- return res, err
- }
- if !opts.QueryMempoolOnly {
- err = s.db.GetTxAssets(assetGuid, lower, higher, assetBitMask, func(txidsIn []string) error {
- txids = append(txids, txidsIn...)
- return nil
- })
- if err != nil {
- return res, err
- }
- } else {
- o := s.mempool.GetTxAssets(assetGuid)
- for _, m := range o {
- txids = append(txids, m.Txid)
- }
- }
- res.Result = api.GetUniqueTxids(txids)
- return res, nil
-}
-
-type addressHistoryIndexes struct {
- InputIndexes []int `json:"inputIndexes"`
- OutputIndexes []int `json:"outputIndexes"`
-}
-
-type txInputs struct {
- Txid *string `json:"txid"`
- OutputIndex int `json:"outputIndex"`
- Script *string `json:"script"`
- // ScriptAsm *string `json:"scriptAsm"`
- Sequence int64 `json:"sequence"`
- Address *string `json:"address"`
- Satoshis int64 `json:"satoshis"`
-}
-
-type txOutputs struct {
- Satoshis int64 `json:"satoshis"`
- Script *string `json:"script"`
- // ScriptAsm *string `json:"scriptAsm"`
- // SpentTxID *string `json:"spentTxId,omitempty"`
- // SpentIndex int `json:"spentIndex,omitempty"`
- // SpentHeight int `json:"spentHeight,omitempty"`
- Address *string `json:"address"`
-}
-
-type resTx struct {
- Hex string `json:"hex"`
- // BlockHash string `json:"blockHash,omitempty"`
- Height int `json:"height"`
- BlockTimestamp int64 `json:"blockTimestamp,omitempty"`
- Version int `json:"version"`
- Hash string `json:"hash"`
- Locktime int `json:"locktime,omitempty"`
- // Size int `json:"size,omitempty"`
- Inputs []txInputs `json:"inputs"`
- InputSatoshis int64 `json:"inputSatoshis,omitempty"`
- Outputs []txOutputs `json:"outputs"`
- OutputSatoshis int64 `json:"outputSatoshis,omitempty"`
- FeeSatoshis int64 `json:"feeSatoshis,omitempty"`
- TokenTransferSummary []*bchain.TokenTransferSummary `json:"tokenTransfers,omitempty"`
-}
-
-type addressHistoryItem struct {
- Addresses map[string]*addressHistoryIndexes `json:"addresses"`
- Satoshis int64 `json:"satoshis"`
- Confirmations int `json:"confirmations"`
- Tx resTx `json:"tx"`
- Tokens map[string]*api.TokenBalanceHistory `json:"tokens,omitempty"`
-}
-
-type resultGetAddressHistory struct {
- Result struct {
- TotalCount int `json:"totalCount"`
- Items []addressHistoryItem `json:"items"`
- } `json:"result"`
-}
-type resultGetAssetHistory struct {
- Result struct {
- TotalCount int `json:"totalCount"`
- AssetDetails *api.AssetSpecific `json:"asset"`
- Items []addressHistoryItem `json:"items"`
- } `json:"result"`
-}
-func txToResTx(tx *api.Tx) resTx {
- var resultTx resTx
- inputs := make([]txInputs, len(tx.Vin))
- for i := range tx.Vin {
- vin := &tx.Vin[i]
- txid := vin.Txid
- script := vin.Hex
- input := txInputs{
- Txid: &txid,
- Script: &script,
- Sequence: int64(vin.Sequence),
- OutputIndex: int(vin.Vout),
- Satoshis: vin.ValueSat.AsInt64(),
- }
- if len(vin.Addresses) > 0 {
- a := vin.Addresses[0]
- input.Address = &a
- }
- inputs[i] = input
- }
- outputs := make([]txOutputs, len(tx.Vout))
- for i := range tx.Vout {
- vout := &tx.Vout[i]
- script := vout.Hex
- output := txOutputs{
- Satoshis: vout.ValueSat.AsInt64(),
- Script: &script,
- }
- if len(vout.Addresses) > 0 {
- a := vout.Addresses[0]
- output.Address = &a
- }
- outputs[i] = output
- }
- if len(tx.TokenTransferSummary) > 0 {
- resultTx.TokenTransferSummary = tx.TokenTransferSummary
- }
- var h int
- var blocktime int64
- if tx.Confirmations == 0 {
- h = -1
- } else {
- h = int(tx.Blockheight)
- blocktime = tx.Blocktime
- }
- resultTx.BlockTimestamp = blocktime
- resultTx.FeeSatoshis = tx.FeesSat.AsInt64()
- resultTx.Hash = tx.Txid
- resultTx.Height = h
- resultTx.Hex = tx.Hex
- resultTx.Inputs = inputs
- resultTx.InputSatoshis = tx.ValueInSat.AsInt64()
- resultTx.Locktime = int(tx.Locktime)
- resultTx.Outputs = outputs
- resultTx.OutputSatoshis = tx.ValueOutSat.AsInt64()
- resultTx.Version = int(tx.Version)
- return resultTx
-}
-
-func addressInSlice(s, t []string) string {
- for _, sa := range s {
- for _, ta := range t {
- if ta == sa {
- return sa
- }
- }
- }
- return ""
-}
-
-func (s *SocketIoServer) getAddressesFromVout(vout *bchain.Vout) ([]string, error) {
- addrDesc, err := s.chainParser.GetAddrDescFromVout(vout)
- if err != nil {
- return nil, err
- }
- voutAddr, _, err := s.chainParser.GetAddressesFromAddrDesc(addrDesc)
- if err != nil {
- return nil, err
- }
- return voutAddr, nil
-}
-
-func (s *SocketIoServer) getAddressHistory(addr []string, opts *addrOpts) (res resultGetAddressHistory, err error) {
- txr, err := s.getAddressTxids(addr, opts)
- if err != nil {
- return
- }
- txids := txr.Result
- res.Result.TotalCount = len(txids)
- res.Result.Items = make([]addressHistoryItem, 0, 8)
- to := len(txids)
- if to > opts.To {
- to = opts.To
- }
- ahi := addressHistoryItem{}
- for txi := opts.From; txi < to; txi++ {
- tx, err := s.api.GetTransaction(txids[txi], false, false)
- if err != nil {
- return res, err
- }
- ads := make(map[string]*addressHistoryIndexes)
- var totalSat big.Int
- for i := range tx.Vin {
- vin := &tx.Vin[i]
- a := addressInSlice(vin.Addresses, addr)
- if a != "" {
- hi := ads[a]
- if hi == nil {
- hi = &addressHistoryIndexes{OutputIndexes: []int{}}
- ads[a] = hi
- }
- hi.InputIndexes = append(hi.InputIndexes, int(vin.N))
- if vin.ValueSat != nil {
- totalSat.Sub(&totalSat, (*big.Int)(vin.ValueSat))
- }
- if vin.AssetInfo != nil {
- if ahi.Tokens == nil {
- ahi.Tokens = map[string]*api.TokenBalanceHistory{}
- }
- token, ok := ahi.Tokens[vin.AssetInfo.AssetGuid]
- if !ok {
- token = &api.TokenBalanceHistory{ReceivedSat: &bchain.Amount{}, SentSat: &bchain.Amount{}}
- ahi.Tokens[vin.AssetInfo.AssetGuid] = token
- }
- (*big.Int)(token.SentSat).Add((*big.Int)(token.SentSat), (*big.Int)(vin.AssetInfo.ValueSat))
- }
- }
- }
- for i := range tx.Vout {
- vout := &tx.Vout[i]
- a := addressInSlice(vout.Addresses, addr)
- if a != "" {
- hi := ads[a]
- if hi == nil {
- hi = &addressHistoryIndexes{InputIndexes: []int{}}
- ads[a] = hi
- }
- hi.OutputIndexes = append(hi.OutputIndexes, int(vout.N))
- if vout.ValueSat != nil {
- totalSat.Add(&totalSat, (*big.Int)(vout.ValueSat))
- }
- if vout.AssetInfo != nil {
- if ahi.Tokens == nil {
- ahi.Tokens = map[string]*api.TokenBalanceHistory{}
- }
- token, ok := ahi.Tokens[vout.AssetInfo.AssetGuid]
- if !ok {
- token = &api.TokenBalanceHistory{ReceivedSat: &bchain.Amount{}, SentSat: &bchain.Amount{}}
- ahi.Tokens[vout.AssetInfo.AssetGuid] = token
- }
- (*big.Int)(token.ReceivedSat).Add((*big.Int)(token.ReceivedSat), (*big.Int)(vout.AssetInfo.ValueSat))
- }
- }
- }
- ahi.Addresses = ads
- ahi.Confirmations = int(tx.Confirmations)
- ahi.Satoshis = totalSat.Int64()
- ahi.Tx = txToResTx(tx)
- res.Result.Items = append(res.Result.Items, ahi)
- // }
- }
- return
-}
-func (s *SocketIoServer) getAssetHistory(assetGuid string, opts *assetOpts) (res resultGetAssetHistory, err error) {
- txr, err := s.getAssetTxids(assetGuid, opts)
- if err != nil {
- return res, err
- }
- txids := txr.Result
- res.Result.TotalCount = len(txids)
- res.Result.Items = make([]addressHistoryItem, 0, 8)
- to := len(txids)
- if to > opts.To {
- to = opts.To
- }
- ahi := addressHistoryItem{}
- ahi.Tokens = map[string]*api.TokenBalanceHistory{}
- for txi := opts.From; txi < to; txi++ {
- tx, err := s.api.GetTransaction(txids[txi], false, false)
- if err != nil {
- return res, err
- }
- ads := make(map[string]*addressHistoryIndexes)
- var totalSat big.Int
- for i := range tx.Vin {
- vin := &tx.Vin[i]
- if vin.AssetInfo != nil && vin.AssetInfo.AssetGuid == assetGuid {
- a, _, err := s.chainParser.GetAddressesFromAddrDesc(vin.AddrDesc)
- if err != nil {
- return res, err
- }
- for _, addr := range a {
- hi := ads[addr]
- if hi == nil {
- hi = &addressHistoryIndexes{OutputIndexes: []int{}}
- ads[addr] = hi
- }
- hi.InputIndexes = append(hi.InputIndexes, int(vin.N))
- }
- if vin.ValueSat != nil {
- totalSat.Sub(&totalSat, (*big.Int)(vin.ValueSat))
- }
- token, ok := ahi.Tokens[vin.AssetInfo.AssetGuid]
- if !ok {
- token = &api.TokenBalanceHistory{ReceivedSat: &bchain.Amount{}, SentSat: &bchain.Amount{}}
- ahi.Tokens[vin.AssetInfo.AssetGuid] = token
- }
- (*big.Int)(token.SentSat).Add((*big.Int)(token.SentSat), (*big.Int)(vin.AssetInfo.ValueSat))
- }
- }
- for i := range tx.Vout {
- vout := &tx.Vout[i]
- if vout.AssetInfo != nil && vout.AssetInfo.AssetGuid == assetGuid {
- a, _, err := s.chainParser.GetAddressesFromAddrDesc(vout.AddrDesc)
- if err != nil {
- return res, err
- }
- for _, addr := range a {
- hi := ads[addr]
- if hi == nil {
- hi = &addressHistoryIndexes{InputIndexes: []int{}}
- ads[addr] = hi
- }
- hi.OutputIndexes = append(hi.OutputIndexes, int(vout.N))
- }
- if vout.ValueSat != nil {
- totalSat.Add(&totalSat, (*big.Int)(vout.ValueSat))
- }
-
- token, ok := ahi.Tokens[vout.AssetInfo.AssetGuid]
- if !ok {
- token = &api.TokenBalanceHistory{ReceivedSat: &bchain.Amount{}, SentSat: &bchain.Amount{}}
- ahi.Tokens[vout.AssetInfo.AssetGuid] = token
- }
- (*big.Int)(token.ReceivedSat).Add((*big.Int)(token.ReceivedSat), (*big.Int)(vout.AssetInfo.ValueSat))
-
- }
- }
- ahi.Addresses = ads
- assetGuidInt, err := strconv.ParseUint(assetGuid, 10, 64)
- if err != nil {
- return res, err
- }
- dbAsset, errAsset := s.db.GetAsset(assetGuidInt, nil)
- if errAsset != nil {
- return res, errors.New(fmt.Sprintf("getAssetHistory Asset not found err: %v", errAsset))
- }
- if len(ahi.Tokens) <= 0 {
- ahi.Tokens = nil
- }
- ahi.Confirmations = int(tx.Confirmations)
- ahi.Satoshis = totalSat.Int64()
- ahi.Tx = txToResTx(tx)
- res.Result.AssetDetails = &api.AssetSpecific{
- AssetGuid: assetGuid,
- Symbol: string(dbAsset.AssetObj.Symbol),
- Contract: ethcommon.BytesToAddress(dbAsset.AssetObj.Contract).Hex(),
- TotalSupply: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.TotalSupply)),
- MaxSupply: (*bchain.Amount)(big.NewInt(dbAsset.AssetObj.MaxSupply)),
- Decimals: int(dbAsset.AssetObj.Precision),
- }
- res.Result.Items = append(res.Result.Items, ahi)
- // }
- }
- return
-}
-
-func unmarshalArray(params []byte, np int) (p []interface{}, err error) {
- err = json.Unmarshal(params, &p)
- if err != nil {
- return
- }
- if len(p) != np {
- err = errors.New("incorrect number of parameters")
- return
- }
- return
-}
-
-func unmarshalGetBlockHeader(params []byte) (height uint32, hash string, err error) {
- p, err := unmarshalArray(params, 1)
- if err != nil {
- return
- }
- fheight, ok := p[0].(float64)
- if ok {
- return uint32(fheight), "", nil
- }
- hash, ok = p[0].(string)
- if ok {
- return
- }
- err = errors.New("incorrect parameter")
- return
-}
-
-type resultGetBlockHeader struct {
- Result struct {
- Hash string `json:"hash"`
- Version int `json:"version"`
- Confirmations int `json:"confirmations"`
- Height int `json:"height"`
- ChainWork string `json:"chainWork"`
- NextHash string `json:"nextHash"`
- MerkleRoot string `json:"merkleRoot"`
- Time int `json:"time"`
- MedianTime int `json:"medianTime"`
- Nonce int `json:"nonce"`
- Bits string `json:"bits"`
- Difficulty float64 `json:"difficulty"`
- } `json:"result"`
-}
-
-func (s *SocketIoServer) getBlockHeader(height uint32, hash string) (res resultGetBlockHeader, err error) {
- if hash == "" {
- // trezor is interested only in hash
- hash, err = s.db.GetBlockHash(height)
- if err != nil {
- return
- }
- res.Result.Hash = hash
- return
- }
- bh, err := s.chain.GetBlockHeader(hash)
- if err != nil {
- return
- }
- res.Result.Hash = bh.Hash
- res.Result.Confirmations = bh.Confirmations
- res.Result.Height = int(bh.Height)
- res.Result.NextHash = bh.Next
- return
-}
-
-func unmarshalEstimateSmartFee(params []byte) (blocks int, conservative bool, err error) {
- p, err := unmarshalArray(params, 2)
- if err != nil {
- return
- }
- fblocks, ok := p[0].(float64)
- if !ok {
- err = errors.New("Invalid parameter blocks")
- return
- }
- blocks = int(fblocks)
- conservative, ok = p[1].(bool)
- if !ok {
- err = errors.New("Invalid parameter conservative")
- return
- }
- return
-}
-
-type resultEstimateSmartFee struct {
- // for compatibility reasons use float64
- Result float64 `json:"result"`
-}
-
-func (s *SocketIoServer) estimateSmartFee(blocks int, conservative bool) (res resultEstimateSmartFee, err error) {
- fee, err := s.chain.EstimateSmartFee(blocks, conservative)
- if err != nil {
- return
- }
- res.Result, err = strconv.ParseFloat(s.chainParser.AmountToDecimalString(&fee), 64)
- return
-}
-
-func unmarshalEstimateFee(params []byte) (blocks int, err error) {
- p, err := unmarshalArray(params, 1)
- if err != nil {
- return
- }
- fblocks, ok := p[0].(float64)
- if !ok {
- err = errors.New("Invalid parameter nblocks")
- return
- }
- blocks = int(fblocks)
- return
-}
-
-type resultEstimateFee struct {
- // for compatibility reasons use float64
- Result float64 `json:"result"`
-}
-
-func (s *SocketIoServer) estimateFee(blocks int) (res resultEstimateFee, err error) {
- fee, err := s.chain.EstimateFee(blocks)
- if err != nil {
- return
- }
- res.Result, err = strconv.ParseFloat(s.chainParser.AmountToDecimalString(&fee), 64)
- return
-}
-
-type resultGetInfo struct {
- Result struct {
- Version int `json:"version,omitempty"`
- ProtocolVersion int `json:"protocolVersion,omitempty"`
- Blocks int `json:"blocks"`
- TimeOffset int `json:"timeOffset,omitempty"`
- Connections int `json:"connections,omitempty"`
- Proxy string `json:"proxy,omitempty"`
- Difficulty float64 `json:"difficulty,omitempty"`
- Testnet bool `json:"testnet"`
- RelayFee float64 `json:"relayFee,omitempty"`
- Errors string `json:"errors,omitempty"`
- Network string `json:"network,omitempty"`
- Subversion string `json:"subversion,omitempty"`
- LocalServices string `json:"localServices,omitempty"`
- CoinName string `json:"coin_name,omitempty"`
- About string `json:"about,omitempty"`
- } `json:"result"`
-}
-
-func (s *SocketIoServer) getInfo() (res resultGetInfo, err error) {
- _, height, _ := s.is.GetSyncState()
- res.Result.Blocks = int(height)
- res.Result.Testnet = s.chain.IsTestnet()
- res.Result.Network = s.chain.GetNetworkName()
- res.Result.Subversion = s.chain.GetSubversion()
- res.Result.CoinName = s.chain.GetCoinName()
- res.Result.About = api.Text.BlockbookAbout
- return
-}
-
-func unmarshalStringParameter(params []byte) (s string, err error) {
- p, err := unmarshalArray(params, 1)
- if err != nil {
- return
- }
- s, ok := p[0].(string)
- if ok {
- return
- }
- err = errors.New("incorrect parameter")
- return
-}
-
-func unmarshalGetDetailedTransaction(params []byte) (txid string, err error) {
- var p []json.RawMessage
- err = json.Unmarshal(params, &p)
- if err != nil {
- return
- }
- if len(p) != 1 {
- err = errors.New("incorrect number of parameters")
- return
- }
- err = json.Unmarshal(p[0], &txid)
- if err != nil {
- return
- }
- return
-}
-
-type resultGetDetailedTransaction struct {
- Result resTx `json:"result"`
-}
-
-func (s *SocketIoServer) getDetailedTransaction(txid string) (res resultGetDetailedTransaction, err error) {
- tx, err := s.api.GetTransaction(txid, false, false)
- if err != nil {
- return res, err
- }
- res.Result = txToResTx(tx)
- return
-}
-
-func (s *SocketIoServer) sendTransaction(tx string) (res resultSendTransaction, err error) {
- txid, err := s.chain.SendRawTransaction(tx)
- if err != nil {
- return res, err
- }
- res.Result = txid
- return
-}
-
-type resultGetMempoolEntry struct {
- Result *bchain.MempoolEntry `json:"result"`
-}
-
-func (s *SocketIoServer) getMempoolEntry(txid string) (res resultGetMempoolEntry, err error) {
- entry, err := s.chain.GetMempoolEntry(txid)
- if err != nil {
- return res, err
- }
- res.Result = entry
- return
-}
-
-// onSubscribe expects two event subscriptions based on the req parameter (including the doublequotes):
-// "bitcoind/hashblock"
-// "bitcoind/addresstxid",["2MzTmvPJLZaLzD9XdN3jMtQA5NexC3rAPww","2NAZRJKr63tSdcTxTN3WaE9ZNDyXy6PgGuv"]
-func (s *SocketIoServer) onSubscribe(c *gosocketio.Channel, req []byte) interface{} {
- defer func() {
- if r := recover(); r != nil {
- glog.Error(c.Id(), " onSubscribe recovered from panic: ", r)
- debug.PrintStack()
- }
- }()
-
- onError := func(id, sc, err, detail string) {
- glog.Error(id, " onSubscribe ", err, ": ", detail)
- s.metrics.SocketIOSubscribes.With(common.Labels{"channel": sc, "status": "failure"}).Inc()
- }
-
- r := string(req)
- glog.V(1).Info(c.Id(), " onSubscribe ", r)
- var sc string
- i := strings.Index(r, "\",[")
- if i > 0 {
- var addrs []string
- sc = r[1:i]
- if sc != "bitcoind/addresstxid" {
- onError(c.Id(), sc, "invalid data", "expecting bitcoind/addresstxid, req: "+r)
- return nil
- }
- err := json.Unmarshal([]byte(r[i+2:]), &addrs)
- if err != nil {
- onError(c.Id(), sc, "invalid data", err.Error()+", req: "+r)
- return nil
- }
- // normalize the addresses to AddressDescriptor
- descs := make([]bchain.AddressDescriptor, len(addrs))
- for i, a := range addrs {
- d, err := s.chainParser.GetAddrDescFromAddress(a)
- if err != nil {
- onError(c.Id(), sc, "invalid address "+a, err.Error()+", req: "+r)
- return nil
- }
- descs[i] = d
- }
- for _, d := range descs {
- c.Join("bitcoind/addresstxid-" + string(d))
- }
- } else {
- sc = r[1 : len(r)-1]
- if sc != "bitcoind/hashblock" {
- onError(c.Id(), sc, "invalid data", "expecting bitcoind/hashblock, req: "+r)
- return nil
- }
- c.Join(sc)
- }
- s.metrics.SocketIOSubscribes.With(common.Labels{"channel": sc, "status": "success"}).Inc()
- return nil
-}
-
-func (s *SocketIoServer) onNewBlockHashAsync(hash string) {
- c := s.server.BroadcastTo("bitcoind/hashblock", "bitcoind/hashblock", hash)
- glog.Info("broadcasting new block hash ", hash, " to ", c, " channels")
-}
-
-// OnNewBlockHash notifies users subscribed to bitcoind/hashblock about new block
-func (s *SocketIoServer) OnNewBlockHash(hash string) {
- go s.onNewBlockHashAsync(hash)
-}
-
-// OnNewTxAddr notifies users subscribed to bitcoind/addresstxid about new block
-func (s *SocketIoServer) OnNewTxAddr(txid string, desc bchain.AddressDescriptor) {
- addr, searchable, err := s.chainParser.GetAddressesFromAddrDesc(desc)
- if err != nil {
- glog.Error("GetAddressesFromAddrDesc error ", err, " for descriptor ", desc)
- } else if searchable && len(addr) == 1 {
- data := map[string]interface{}{"address": addr[0], "txid": txid}
- c := s.server.BroadcastTo("bitcoind/addresstxid-"+string(desc), "bitcoind/addresstxid", data)
- if c > 0 {
- glog.Info("broadcasting new txid ", txid, " for addr ", addr[0], " to ", c, " channels")
- }
- }
-}
diff --git a/static/templates/tx.html b/static/templates/tx.html
deleted file mode 100644
index fd1926c5f0..0000000000
--- a/static/templates/tx.html
+++ /dev/null
@@ -1,142 +0,0 @@
-{{define "specific"}}{{$cs := .CoinShortcut}}{{$tx := .Tx}}
-
Transaction
-
- {{$tx.Txid}}
-
-Summary
-
-
-
- {{- if $tx.Confirmations -}}
-
- | Mined Time |
- {{formatUnixTime $tx.Blocktime}} |
-
{{end -}}
-
- | In Block |
- {{if $tx.Confirmations}}{{$tx.Blockhash}}{{else}}Unconfirmed{{end}} |
-
- {{- if $tx.Confirmations -}}
-
- | In Block Height |
- {{$tx.Blockheight}} |
-
{{end}}
- {{- if $tx.EthereumSpecific -}}
-
- | Status |
- {{- if $tx.EthereumSpecific.Status -}}
- {{- if eq $tx.EthereumSpecific.Status 1 -}}
- Success |
- {{- else -}}
- {{- if eq $tx.EthereumSpecific.Status -1 -}}
- Pending |
- {{- else -}}
- Unknown |
- {{- end -}}
- {{- end -}}
- {{- else -}}
- Fail |
- {{- end -}}
-
-
- | Value |
- {{formatAmount $tx.ValueOutSat}} {{$cs}} |
-
-
- | Gas Used / Limit |
- {{if $tx.EthereumSpecific.GasUsed}}{{$tx.EthereumSpecific.GasUsed}}{{else}}pending{{end}} / {{$tx.EthereumSpecific.GasLimit}} |
-
-
- | Gas Price |
- {{formatAmount $tx.EthereumSpecific.GasPrice}} {{$cs}} |
-
- {{- else -}}
-
- | Total Input |
- {{formatAmount $tx.ValueInSat}} {{$cs}} |
-
-
- | Total Output |
- {{formatAmount $tx.ValueOutSat}} {{$cs}} |
-
- {{- end -}}
- {{- if $tx.FeesSat -}}
-
- | Fees |
- {{formatAmount $tx.FeesSat}} {{$cs}} |
-
{{end -}}
- {{if gt (len $tx.Memo) 0}}
-
- | Memo |
- {{formatEncodeBase64 $tx.Memo}} |
-
{{end}}
- {{- if $tx.TokenTransferSummary -}}
-
- | Tokens |
-
-
-
-
- | Asset |
- Total |
-
- {{- range $tokenTransfer := $tx.TokenTransferSummary -}}{{if $tokenTransfer}}
-
- | {{$tokenTransfer.Token}} {{$tokenTransfer.Symbol}} |
- {{formatAmountWithDecimals $tokenTransfer.Value $tokenTransfer.Decimals}} {{$tokenTransfer.Symbol}} |
-
- {{- end -}}{{- end -}}
-
-
- |
-
- {{- end -}}
- {{- if not $tx.Confirmations}}
-
- | RBF |
-
- {{- if $tx.Rbf}}
- ON
- {{- else -}}
- OFF️
- {{end -}}
- |
-
- {{end -}}
-
-
-
-Details
-
- {{template "txdetail" .}}
-
-
-{{end}}
diff --git a/static/test-socketio.html b/static/test-socketio.html
deleted file mode 100644
index 586525ad7f..0000000000
--- a/static/test-socketio.html
+++ /dev/null
@@ -1,522 +0,0 @@
-
-
-
-
-
-
-
-
-
- Blockbook Socket.io Test Page
-
-
-
-
-
-
-
Blockbook Socket.io Test Page
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/tests/rpc/testdata/zcoin.json b/tests/rpc/testdata/zcoin.json
deleted file mode 100644
index 1d5f224a88..0000000000
--- a/tests/rpc/testdata/zcoin.json
+++ /dev/null
@@ -1,104 +0,0 @@
-{
- "blockHeight": 126311,
- "blockHash": "4857051323dd6a10bc1c92facb00e7c8258adc9b8b680d0bcdd19034a777d72d",
- "blockTime": 1547120622,
- "blockTxs": [
- "5ee3ba91195adc9a22e61a570b168052764584305000450d04355ebcb9cc4be8",
- "2f831477d523ea717caf9a9520dd848b8fe932540207037fabf100a56d466e91",
- "347d7c8c1d77f2f835641be27d97900f88be71646bdaa14ffb11b37aaac72f79"
- ],
- "txDetails": {
- "2f831477d523ea717caf9a9520dd848b8fe932540207037fabf100a56d466e91": {
- "hex": "010000000106be6afc693eb158fa010f751c347982851108ea316d0685109caaa8ec4580c2000000006a473044022048dcdd1121148ecf495df74f563384d91db0635dae3c608666511ef8f24adc19022004af5384be1bce1531d0bf8498a8bfb150f797e63e348ca3865f0322203384aa012102d79d7e7f40e091517465c50ed3f5345c7b9a4611a98103ee1ca1f8e66686ad9fffffffff02e04d6cb3160000001976a914b923050a6542d70d6eb6546ba3275a2b6ea0eda588ac06d8c849000000001976a914c353c188620cb33a72d218c0d67fb3f92ad1b6b088ac00000000",
- "txid": "2f831477d523ea717caf9a9520dd848b8fe932540207037fabf100a56d466e91",
- "blocktime": 1547120622,
- "time": 1547120622,
- "locktime": 0,
- "version": 1,
- "vin": [
- {
- "txid": "c28045eca8aa9c1085066d31ea0811858279341c750f01fa58b13e69fc6abe06",
- "vout": 0,
- "sequence": 4294967295,
- "scriptSig": {
- "hex": "473044022048dcdd1121148ecf495df74f563384d91db0635dae3c608666511ef8f24adc19022004af5384be1bce1531d0bf8498a8bfb150f797e63e348ca3865f0322203384aa012102d79d7e7f40e091517465c50ed3f5345c7b9a4611a98103ee1ca1f8e66686ad9f"
- }
- }
- ],
- "vout": [
- {
- "value": 974.99500000,
- "n": 0,
- "scriptPubKey": {
- "hex": "76a914b923050a6542d70d6eb6546ba3275a2b6ea0eda588ac"
- }
- },
- {
- "value": 12.37899270,
- "n": 1,
- "scriptPubKey": {
- "hex": "76a914c353c188620cb33a72d218c0d67fb3f92ad1b6b088ac"
- }
- }
- ]
- },
- "347d7c8c1d77f2f835641be27d97900f88be71646bdaa14ffb11b37aaac72f79": {
- "hex": "0100000004bc566f299c27644851e70f8646f2ed642985897f488090f5bd5b152d891388a9000000006b483045022100cd5ca45783f836db65a47ba568f97f890155c27ccf0769c1edf231bf6bf49f9b022021d8493fae950bced2c417ce6c4a62aaad495c4d8675e4a4a3e9d86ab44f4b29012102d91223be36388a51cef618ec34c2a1d95f85b6d85d0e07e9e963d84893b5cc4dfefffffff117437f28af1665a002c8351e903de10bd40ab73d54932bbaae28caa6f49a42640000006b483045022100962a7c4b0a96b25fa418f92a69e9f37c5517740d50e996a92724f064bfadcf75022073f1c0475215bef70de392273360655a0b0d4f1f8afd3917614a5dfd1ddd1ca1012103bbfb869bf408cfdc237c63c1dcec226faf56cc141c42ef6bb8ef4d156df669eafeffffff0dd680cce849762fa7f3f117a1b0e3e7fb6493f2600152143502aa59ad7ca4ed4d0000006b483045022100a6b7befee6468f01e2b3813f05b81241dd5a4c0b04d97a783940c75d97b85ba502206c0dd2fa5cc5c153d359c55f24407c97aec32bf42b2723fc40374188443bd4b2012103bbfb869bf408cfdc237c63c1dcec226faf56cc141c42ef6bb8ef4d156df669eafeffffffd7e86128b28dcf2046c33f098cfcc2b7f08ea781cc119c0944b2fb23e378135d150000006a47304402204116539acc084920a86bf837ade9d938b517dfa0d346beb969cc97505e6f21520220069a9a33f798a6c1912e29568be2cef12d4db0ea1db751054db5e2311b761854012103bbfb869bf408cfdc237c63c1dcec226faf56cc141c42ef6bb8ef4d156df669eafeffffff0229b90000000000001976a914da8378d88cd781e0a6f9fdfa6668dd47a718cf6188ac80a35d06000000001976a914707077511db03836716dc01ce47442596264fd8a88acccea0100",
- "txid": "347d7c8c1d77f2f835641be27d97900f88be71646bdaa14ffb11b37aaac72f79",
- "blocktime": 1547120622,
- "time": 1547120622,
- "locktime": 125644,
- "version": 1,
- "vin": [
- {
- "txid": "a98813892d155bbdf59080487f89852964edf246860fe7514864279c296f56bc",
- "vout": 0,
- "sequence": 4294967294,
- "scriptSig": {
- "hex": "483045022100cd5ca45783f836db65a47ba568f97f890155c27ccf0769c1edf231bf6bf49f9b022021d8493fae950bced2c417ce6c4a62aaad495c4d8675e4a4a3e9d86ab44f4b29012102d91223be36388a51cef618ec34c2a1d95f85b6d85d0e07e9e963d84893b5cc4d"
- }
- },
- {
- "txid": "429af4a6ca28aeba2b93543db70ad40be13d901e35c802a06516af287f4317f1",
- "vout": 100,
- "sequence": 4294967294,
- "scriptSig": {
- "hex": "483045022100962a7c4b0a96b25fa418f92a69e9f37c5517740d50e996a92724f064bfadcf75022073f1c0475215bef70de392273360655a0b0d4f1f8afd3917614a5dfd1ddd1ca1012103bbfb869bf408cfdc237c63c1dcec226faf56cc141c42ef6bb8ef4d156df669ea"
- }
- },
- {
- "txid": "eda47cad59aa023514520160f29364fbe7e3b0a117f1f3a72f7649e8cc80d60d",
- "vout": 77,
- "sequence": 4294967294,
- "scriptSig": {
- "hex": "483045022100a6b7befee6468f01e2b3813f05b81241dd5a4c0b04d97a783940c75d97b85ba502206c0dd2fa5cc5c153d359c55f24407c97aec32bf42b2723fc40374188443bd4b2012103bbfb869bf408cfdc237c63c1dcec226faf56cc141c42ef6bb8ef4d156df669ea"
- }
- },
- {
- "txid": "5d1378e323fbb244099c11cc81a78ef0b7c2fc8c093fc34620cf8db22861e8d7",
- "vout": 21,
- "sequence": 4294967294,
- "scriptSig": {
- "hex": "47304402204116539acc084920a86bf837ade9d938b517dfa0d346beb969cc97505e6f21520220069a9a33f798a6c1912e29568be2cef12d4db0ea1db751054db5e2311b761854012103bbfb869bf408cfdc237c63c1dcec226faf56cc141c42ef6bb8ef4d156df669ea"
- }
- }
- ],
- "vout": [
- {
- "value": 0.00047401,
- "n": 0,
- "scriptPubKey": {
- "hex": "76a914da8378d88cd781e0a6f9fdfa6668dd47a718cf6188ac"
- }
- },
- {
- "value": 1.06800000,
- "n": 1,
- "scriptPubKey": {
- "hex": "76a914707077511db03836716dc01ce47442596264fd8a88ac"
- }
- }
- ]
- }
- }
-}
diff --git a/tests/sync/testdata/zcoin.json b/tests/sync/testdata/zcoin.json
deleted file mode 100644
index cbc8872890..0000000000
--- a/tests/sync/testdata/zcoin.json
+++ /dev/null
@@ -1,285 +0,0 @@
-{
- "connectBlocks": {
- "syncRanges": [
- { "lower": 10012, "upper": 10020 },
- { "lower": 121100, "upper": 121150 }
- ],
- "blocks": {
- "10012": {
- "height": 10012,
- "hash": "270364b0b441f4b5b4c98d073462c0f00e1200fec00410e27f4361e4695a8530",
- "noTxs": 2,
- "txDetails": [
- {
- "hex": "01000000010000000000000000000000000000000000000000000000000000000000000000ffffffff26021c27062f503253482f043c424258081000cd76000000000d2f6e6f64655374726174756d2f0000000006406a7aee000000001976a9146934fe23ac758cbc21953fadfab01dd3671c01b688ac00c2eb0b000000001976a9147d9ed014fc4e603fca7c2e3f9097fb7d0fb487fc88ac00c2eb0b000000001976a914dcf01f01f5655c10d4fa8149d71cfee36313c02e88ac00c2eb0b000000001976a914ff71b0c9c2a90c6164a50a2fb523eb54a8a6b55088ac00c2eb0b000000001976a9140654dd9b856f2ece1d56cb4ee5043cd9398d962c88ac00c2eb0b000000001976a9140b4bfb256ef4bfa360e3b9e66e53a0bd84d196bc88ac00000000",
- "txid": "ec09f614f427ac2553846d4e91bdbac34748502374bb981fc324f27f8c8683f6",
- "blocktime": 1480737340,
- "time": 1480737340,
- "version": 1,
- "vin": [
- {
- "coinbase": "021c27062f503253482f043c424258081000cd76000000000d2f6e6f64655374726174756d2f",
- "sequence": 0
- }
- ],
- "vout": [
- {
- "value": 40.01,
- "n": 0,
- "scriptPubKey": {
- "hex": "76a9146934fe23ac758cbc21953fadfab01dd3671c01b688ac"
- }
- },
- {
- "value": 2.0,
- "n": 1,
- "scriptPubKey": {
- "hex": "76a9147d9ed014fc4e603fca7c2e3f9097fb7d0fb487fc88ac"
- }
- },
- {
- "value": 2.0,
- "n": 2,
- "scriptPubKey": {
- "hex": "76a914dcf01f01f5655c10d4fa8149d71cfee36313c02e88ac"
- }
- },
- {
- "value": 2.0,
- "n": 3,
- "scriptPubKey": {
- "hex": "76a914ff71b0c9c2a90c6164a50a2fb523eb54a8a6b55088ac"
- }
- },
- {
- "value": 2.0,
- "n": 4,
- "scriptPubKey": {
- "hex": "76a9140654dd9b856f2ece1d56cb4ee5043cd9398d962c88ac"
- }
- },
- {
- "value": 2.0,
- "n": 5,
- "scriptPubKey": {
- "hex": "76a9140b4bfb256ef4bfa360e3b9e66e53a0bd84d196bc88ac"
- }
- }
- ]
- },
- {
- "hex": "0100000001a82d9bb9c02ad9eddfc9d760073b4fc2632b6c939a43d104a8ad08cebee12490000000006b483045022100ecadec884ee8e570bb77704672e223d5cfbaba0aa0957659b8efeabb71392587022076a17e47ac618bcf76c47f6a7fac739dad05f1efda3c61ec5d7cae7021088f370121021a1a3c0f862f7b757930d9654dce951175188eb49f659d9adce95113de5d05f2ffffffff02bc16367e000000001976a9149e694e14a690f487d2a42603dfa1e39e58adcb4688ac01a89721000000001976a914184f6e4e10fb4f1800d32537617528674b6afe0c88ac00000000",
- "txid": "c04be7747ef077477aedbec55f1cf6fd51ec2efd58ff978f08884eab3c6fdfbf",
- "time": 1480737340,
- "blocktime": 1480737340,
- "version": 1,
- "vin": [
- {
- "txid": "9024e1bece08ada804d1439a936c2b63c24f3b0760d7c9dfedd92ac0b99b2da8",
- "vout": 0,
- "sequence": 4294967295,
- "scriptSig": {
- "hex": "483045022100ecadec884ee8e570bb77704672e223d5cfbaba0aa0957659b8efeabb71392587022076a17e47ac618bcf76c47f6a7fac739dad05f1efda3c61ec5d7cae7021088f370121021a1a3c0f862f7b757930d9654dce951175188eb49f659d9adce95113de5d05f2"
- }
- }
- ],
- "vout": [
- {
- "value": 21.1747398,
- "n": 0,
- "scriptPubKey": {
- "hex": "76a9149e694e14a690f487d2a42603dfa1e39e58adcb4688ac"
- }
- },
- {
- "value": 5.63587073,
- "n": 1,
- "scriptPubKey": {
- "hex": "76a914184f6e4e10fb4f1800d32537617528674b6afe0c88ac"
- }
- }
- ]
- }
- ]
- },
- "10013": {
- "height": 10013,
- "hash": "8be1836104f7adefc0ac8067f56abd1d30725dc05ccb19236be6f538637ec213",
- "noTxs": 4,
- "txDetails": [
- {
- "hex": "0100000001e9f4e2d5180ae0aa5b1ef1fdc496118d6226b688c7986dd9b4215fb4ad59b729010000006a47304402206261d51bf92238e28432307e92fc58af641a15db3a72cfc3a21d5a2ddfdc4d2e022060cd1044cc0a1a2932eaf642f9a4d08b62abb82bde6e7332f65aa343aa204434012102038af35cb691fb64a5af8ae4f3739a3a834363436bb7a4a5d98d9d9eaf46704effffffff02e3c72c00000000001976a914d475cafdcf52e81ee0ed36fa5b1aacebc9cc436f88ac6b638506000000001976a914c8f06a3a16c1210ae30c95111b60c481e20dcc0088ac00000000",
- "txid": "01676407d835b8cb9a411136134efcfed3708ba123cb911532b63d9e464eae2e",
- "version": 1,
- "time": 1480737375,
- "blocktime": 1480737375,
- "vin": [
- {
- "txid": "29b759adb45f21b4d96d98c788b626628d1196c4fdf11e5baae00a18d5e2f4e9",
- "vout": 1,
- "scriptSig": {
- "hex": "47304402206261d51bf92238e28432307e92fc58af641a15db3a72cfc3a21d5a2ddfdc4d2e022060cd1044cc0a1a2932eaf642f9a4d08b62abb82bde6e7332f65aa343aa204434012102038af35cb691fb64a5af8ae4f3739a3a834363436bb7a4a5d98d9d9eaf46704e"
- },
- "sequence": 4294967295
- }
- ],
- "vout": [
- {
- "value": 0.02934755,
- "n": 0,
- "scriptPubKey": {
- "hex": "76a914d475cafdcf52e81ee0ed36fa5b1aacebc9cc436f88ac"
- }
- },
- {
- "value": 1.09405035,
- "n": 1,
- "scriptPubKey": {
- "hex": "76a914c8f06a3a16c1210ae30c95111b60c481e20dcc0088ac"
- }
- }
- ]
- }
- ]
- },
- "121100": {
- "height": 121100,
- "hash": "02bc0d5ae888024d95f1887712def2639c341c8fbb85c25cc3684e8b2b60081f",
- "noTxs": 30,
- "txDetails": [
- {
- "hex": "01000000017ce8aed3eec1d7891141857700287f431090c1f9466e65b4d0f6a751feafa23c000000006b483045022100b7934000466f52a2cbdb63ea099ad30685c82778890f9b06facc09e6e9b3cb5502204a44c5b9c48c2ba4e61b7af467b384fbea8e1efb63296326ca222c97642d61b901210257436124422382febf4003f5bff403aeccab2b6ad901ea1c4d4e08ebb26eadabfeffffff0200105e5f000000001976a914732cd1f18bc5455be4c5f04b120dc4f06ebb2fbc88ac8cd81e03000000001976a914cfcce1c68a8974b1410e971708839fb95c0afcd788ac0bd90100",
- "txid": "b71c6ed0b38c9a52fa02c25b79ba2b9f7da599fddae2fdf36dc2fa65bb127699",
- "version": 1,
- "vin": [
- {
- "txid": "3ca2affe51a7f6d0b4656e46f9c19010437f28007785411189d7c1eed3aee87c",
- "vout": 0,
- "scriptSig": {
- "hex": "483045022100b7934000466f52a2cbdb63ea099ad30685c82778890f9b06facc09e6e9b3cb5502204a44c5b9c48c2ba4e61b7af467b384fbea8e1efb63296326ca222c97642d61b901210257436124422382febf4003f5bff403aeccab2b6ad901ea1c4d4e08ebb26eadab"
- },
- "sequence": 4294967294
- }
- ],
- "vout": [
- {
- "value": 16.0,
- "n": 0,
- "scriptPubKey": {
- "hex": "76a914732cd1f18bc5455be4c5f04b120dc4f06ebb2fbc88ac"
- }
- },
- {
- "value": 0.52353164,
- "n": 1,
- "scriptPubKey": {
- "hex": "76a914cfcce1c68a8974b1410e971708839fb95c0afcd788ac"
- }
- }
- ],
- "time": 1545641453,
- "blocktime": 1545641453
- }
- ]
- }
- }
- },
- "handleFork": {
- "syncRanges": [
- { "lower": 10012, "upper": 10017 },
- { "lower": 121100, "upper": 121104 }
- ],
- "fakeBlocks": {
- "10012": {
- "height": 10012,
- "hash": "8a647ed7cbc02600775dd6a7fff874a394a9abdfe5d86d9c46aa3d9a4307e010"
- },
- "10013": {
- "height": 10013,
- "hash": "005b810a796c05359264f847f968132981b608138e42655ffd9261e2a2f8e6c8"
- },
- "10014": {
- "height": 10014,
- "hash": "b11ee0e2620bc1a37da725f3cd4a1db9faec2b88ae3e77c9c4d66bbf5106bc44"
- },
- "10015": {
- "height": 10015,
- "hash": "712819a7a0c669c2367660cc246c725de58b68b7f77b803b1964a7c4343a115f"
- },
- "10016": {
- "height": 10016,
- "hash": "69b3ba86607980063eb9a04b9701c8d94206148bae1e3a4324e0fb36ca2e5d11"
- },
- "10017": {
- "height": 10017,
- "hash": "e60984c79e2723a19ebbc37f8d0c10e1e6294f1088c9bed3e532254f68c1a199"
- },
- "121100": {
- "height": 121100,
- "hash": "7eda2cf4cefb5945dbe60fd7e62296ff04fc8a2007f735d574edbbd6e30fb829"
- },
- "121101": {
- "height": 121101,
- "hash": "66d76166f8655a0394e26643c06bea61e0b1d0bc73acca3a53e48d80c7dab4af"
- },
- "121102": {
- "height": 121102,
- "hash": "65e94ebede51ea311784676b0673546e398b882b333be86ed16a100774bed32a"
- },
- "121103": {
- "height": 121103,
- "hash": "2d00b3d85882295717141e9c900d43d3e7b0a7e3ecdeaa05d32ed56d20577a97"
- },
- "121104": {
- "height": 121104,
- "hash": "199220df07b03ddacc3ba0e18a2562c83cb57dff0d12d8953b8233d5a47d7bf3"
- }
- },
- "realBlocks": {
- "10012": {
- "height": 10012,
- "hash": "270364b0b441f4b5b4c98d073462c0f00e1200fec00410e27f4361e4695a8530"
- },
- "10013": {
- "height": 10013,
- "hash": "8be1836104f7adefc0ac8067f56abd1d30725dc05ccb19236be6f538637ec213"
- },
- "10014": {
- "height": 10014,
- "hash": "def841c7406526043da07f202d67a0b1fe18d10650cbb3661a56722ad814815f"
- },
- "10015": {
- "height": 10015,
- "hash": "4dfab32ae8abb08ecd02b83305606d5d154e57018ff4d12cc744f9cd0b2d47b7"
- },
- "10016": {
- "height": 10016,
- "hash": "e4d49fd46e9d5e7488678356c91e7f8b4d2c69a0dd39e52e107a2987d41e230c"
- },
- "10017": {
- "height": 10017,
- "hash": "713837605fd64f8458cace5b961b28d0f1104665a054a6dde4b3572d520270f5"
- },
- "121100": {
- "height": 121100,
- "hash": "02bc0d5ae888024d95f1887712def2639c341c8fbb85c25cc3684e8b2b60081f"
- },
- "121101": {
- "height": 121101,
- "hash": "aa30be2d62075ee4d147149ef48ad42cd4f6d0fef90c0ec67c117f1b7d7e192f"
- },
- "121102": {
- "height": 121102,
- "hash": "77f49fc80ad9bb5398832332f98f7535e53971fab2dc81f7f3e1fc1dfac8ac7f"
- },
- "121103": {
- "height": 121103,
- "hash": "ed5947e57d68528929d32846a6b7942a5b9db4c98b9eacbd72e8662121bb7971"
- },
- "121104": {
- "height": 121104,
- "hash": "bea29f4df145ea43fd4450aad21ad79388f1fff36b9ab62a1b394440bf47eaf8"
- }
- }
- }
-}