From 9ecfdfe11dfbddecb024a764e50d6320371e03e0 Mon Sep 17 00:00:00 2001 From: kevin <35275952+kaladinlight@users.noreply.github.com> Date: Thu, 9 Mar 2023 02:54:38 -0700 Subject: [PATCH] Add BNB Smart Chain (#869) --- bchain/coins/blockchain.go | 3 + bchain/coins/bsc/bscrpc.go | 91 +++++++++++ bchain/coins/eth/evm.go | 10 ++ bchain/types.go | 6 +- bchain/types_ethereum_type.go | 8 +- build/templates/backend/debian/install | 1 + build/templates/backend/scripts/bsc.sh | 40 +++++ .../templates/backend/scripts/bsc_archive.sh | 43 ++++++ build/tools/templates.go | 34 +++- configs/coins/bsc.json | 71 +++++++++ configs/coins/bsc_archive.json | 74 +++++++++ docs/ports.md | 146 +++++++++--------- server/public.go | 8 + static/templates/address.html | 30 ++-- static/templates/txdetail_ethereumtype.html | 18 +-- tests/rpc/testdata/bsc.json | 56 +++++++ tests/rpc/testdata/bsc_archive.json | 56 +++++++ tests/tests.json | 8 +- 18 files changed, 596 insertions(+), 107 deletions(-) create mode 100644 bchain/coins/bsc/bscrpc.go create mode 100644 build/templates/backend/scripts/bsc.sh create mode 100644 build/templates/backend/scripts/bsc_archive.sh create mode 100644 configs/coins/bsc.json create mode 100644 configs/coins/bsc_archive.json create mode 100644 tests/rpc/testdata/bsc.json create mode 100644 tests/rpc/testdata/bsc_archive.json diff --git a/bchain/coins/blockchain.go b/bchain/coins/blockchain.go index b70fa235..32eba742 100644 --- a/bchain/coins/blockchain.go +++ b/bchain/coins/blockchain.go @@ -16,6 +16,7 @@ import ( "github.com/trezor/blockbook/bchain/coins/bellcoin" "github.com/trezor/blockbook/bchain/coins/bitcore" "github.com/trezor/blockbook/bchain/coins/bitzeny" + "github.com/trezor/blockbook/bchain/coins/bsc" "github.com/trezor/blockbook/bchain/coins/btc" "github.com/trezor/blockbook/bchain/coins/btg" "github.com/trezor/blockbook/bchain/coins/cpuchain" @@ -134,6 +135,8 @@ func init() { BlockChainFactories["ECash"] = ecash.NewECashRPC BlockChainFactories["Avalanche"] = avalanche.NewAvalancheRPC BlockChainFactories["Avalanche Archive"] = avalanche.NewAvalancheRPC + BlockChainFactories["BNB Smart Chain"] = bsc.NewBNBSmartChainRPC + BlockChainFactories["BNB Smart Chain Archive"] = bsc.NewBNBSmartChainRPC } // GetCoinNameFromConfig gets coin name and coin shortcut from config file diff --git a/bchain/coins/bsc/bscrpc.go b/bchain/coins/bsc/bscrpc.go new file mode 100644 index 00000000..13690576 --- /dev/null +++ b/bchain/coins/bsc/bscrpc.go @@ -0,0 +1,91 @@ +package bsc + +import ( + "context" + "encoding/json" + + "github.com/ethereum/go-ethereum/ethclient" + "github.com/ethereum/go-ethereum/rpc" + "github.com/golang/glog" + "github.com/juju/errors" + "github.com/trezor/blockbook/bchain" + "github.com/trezor/blockbook/bchain/coins/eth" +) + +const ( + // MainNet is production network + MainNet eth.Network = 56 + + // bsc token type names + BEP20TokenType bchain.TokenTypeName = "BEP20" + BEP721TokenType bchain.TokenTypeName = "BEP721" + BEP1155TokenType bchain.TokenTypeName = "BEP1155" +) + +// BNBSmartChainRPC is an interface to JSON-RPC bsc service. +type BNBSmartChainRPC struct { + *eth.EthereumRPC +} + +// NewBNBSmartChainRPC returns new BNBSmartChainRPC instance. +func NewBNBSmartChainRPC(config json.RawMessage, pushHandler func(bchain.NotificationType)) (bchain.BlockChain, error) { + c, err := eth.NewEthereumRPC(config, pushHandler) + if err != nil { + return nil, err + } + + // overwrite EthereumTokenTypeMap with bsc specific token type names + bchain.EthereumTokenTypeMap = []bchain.TokenTypeName{BEP20TokenType, BEP721TokenType, BEP1155TokenType} + + s := &BNBSmartChainRPC{ + EthereumRPC: c.(*eth.EthereumRPC), + } + + return s, nil +} + +// Initialize bnb smart chain rpc interface +func (b *BNBSmartChainRPC) Initialize() error { + b.OpenRPC = func(url string) (bchain.EVMRPCClient, bchain.EVMClient, error) { + r, err := rpc.Dial(url) + if err != nil { + return nil, nil, err + } + rc := ð.EthereumRPCClient{Client: r} + ec := ð.EthereumClient{Client: ethclient.NewClient(r)} + return rc, ec, nil + } + + rc, ec, err := b.OpenRPC(b.ChainConfig.RPCURL) + if err != nil { + return err + } + + // set chain specific + b.Client = ec + b.RPC = rc + b.MainNetChainID = MainNet + b.NewBlock = eth.NewEthereumNewBlock() + b.NewTx = eth.NewEthereumNewTx() + + ctx, cancel := context.WithTimeout(context.Background(), b.Timeout) + defer cancel() + + id, err := b.Client.NetworkID(ctx) + if err != nil { + return err + } + + // parameters for getInfo request + switch eth.Network(id.Uint64()) { + case MainNet: + b.Testnet = false + b.Network = "livenet" + default: + return errors.Errorf("Unknown network id %v", id) + } + + glog.Info("rpc: block chain ", b.Network) + + return nil +} diff --git a/bchain/coins/eth/evm.go b/bchain/coins/eth/evm.go index 1304b243..6276a9c2 100644 --- a/bchain/coins/eth/evm.go +++ b/bchain/coins/eth/evm.go @@ -92,6 +92,11 @@ type EthereumNewBlock struct { channel chan *types.Header } +// NewEthereumNewBlock returns an initialized EthereumNewBlock struct +func NewEthereumNewBlock() *EthereumNewBlock { + return &EthereumNewBlock{channel: make(chan *types.Header)} +} + // Channel returns the underlying channel as an empty interface func (s *EthereumNewBlock) Channel() interface{} { return s.channel @@ -113,6 +118,11 @@ type EthereumNewTx struct { channel chan common.Hash } +// NewEthereumNewTx returns an initialized EthereumNewTx struct +func NewEthereumNewTx() *EthereumNewTx { + return &EthereumNewTx{channel: make(chan common.Hash)} +} + // Channel returns the underlying channel as an empty interface func (s *EthereumNewTx) Channel() interface{} { return s.channel diff --git a/bchain/types.go b/bchain/types.go index cdabf935..7d2948e5 100644 --- a/bchain/types.go +++ b/bchain/types.go @@ -120,9 +120,9 @@ type TokenType int // TokenType enumeration const ( - FungibleToken = TokenType(iota) // ERC20 - NonFungibleToken // ERC721 - MultiToken // ERC1155 + FungibleToken = TokenType(iota) // ERC20/BEP20 + NonFungibleToken // ERC721/BEP721 + MultiToken // ERC1155/BEP1155 ) // TokenTypeName specifies type of token diff --git a/bchain/types_ethereum_type.go b/bchain/types_ethereum_type.go index adceec3b..2a8ef6e0 100644 --- a/bchain/types_ethereum_type.go +++ b/bchain/types_ethereum_type.go @@ -6,8 +6,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi" ) -// EthereumType specific - // EthereumInternalTransfer contains data about internal transfer type EthereumInternalTransfer struct { Type EthereumInternalTransactionType `json:"type"` @@ -16,6 +14,7 @@ type EthereumInternalTransfer struct { Value big.Int `json:"value"` } +// FourByteSignature contains data about about a contract function signature type FourByteSignature struct { // stored in DB Name string @@ -26,10 +25,13 @@ type FourByteSignature struct { ParsedParameters []abi.Type } +// EthereumParsedInputParam contains data about a contract function parameter type EthereumParsedInputParam struct { Type string `json:"type"` Values []string `json:"values,omitempty"` } + +// EthereumParsedInputData contains the parsed data for an input data hex payload type EthereumParsedInputData struct { MethodId string `json:"methodId"` Name string `json:"name"` @@ -75,7 +77,7 @@ const ( // EthereumTokenTypeMap maps bchain.TokenType to TokenTypeName // the map must match all bchain.TokenType to avoid index out of range panic -var EthereumTokenTypeMap []TokenTypeName = []TokenTypeName{ERC20TokenType, ERC771TokenType, ERC1155TokenType} +var EthereumTokenTypeMap = []TokenTypeName{ERC20TokenType, ERC771TokenType, ERC1155TokenType} type MultiTokenValue struct { Id big.Int diff --git a/build/templates/backend/debian/install b/build/templates/backend/debian/install index 27e68661..950633bb 100755 --- a/build/templates/backend/debian/install +++ b/build/templates/backend/debian/install @@ -3,4 +3,5 @@ backend/* {{.Env.BackendInstallPath}}/{{.Coin.Alias}} server.conf => {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}.conf client.conf => {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}_client.conf +{{if .Backend.ExecScript }}exec.sh => {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/{{.Coin.Alias}}_exec.sh{{end}} {{end}} diff --git a/build/templates/backend/scripts/bsc.sh b/build/templates/backend/scripts/bsc.sh new file mode 100644 index 00000000..75a1d844 --- /dev/null +++ b/build/templates/backend/scripts/bsc.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +{{define "main" -}} + +set -e + +INSTALL_DIR={{.Env.BackendInstallPath}}/{{.Coin.Alias}} +DATA_DIR={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend + +GETH_BIN=$INSTALL_DIR/geth_linux +CHAINDATA_DIR=$DATA_DIR/geth/chaindata + +if [ ! -d "$CHAINDATA_DIR" ]; then + $GETH_BIN init --datadir $DATA_DIR $INSTALL_DIR/genesis.json +fi + +$GETH_BIN \ + --config $INSTALL_DIR/config.toml \ + --datadir $DATA_DIR \ + --port {{.Ports.BackendP2P}} \ + --http \ + --http.addr 127.0.0.1 \ + --http.port {{.Ports.BackendHttp}} \ + --http.api eth,net,web3,debug,txpool \ + --http.vhosts '*' \ + --http.corsdomain '*' \ + --ws \ + --ws.addr 127.0.0.1 \ + --ws.port {{.Ports.BackendRPC}} \ + --ws.api eth,net,web3,debug,txpool \ + --ws.origins '*' \ + --syncmode full \ + --maxpeers 100 \ + --rpc.allow-unprotected-txs \ + --txlookuplimit 0 \ + --cache 8000 \ + --ipcdisable \ + --nat none + +{{end}} \ No newline at end of file diff --git a/build/templates/backend/scripts/bsc_archive.sh b/build/templates/backend/scripts/bsc_archive.sh new file mode 100644 index 00000000..40c46aff --- /dev/null +++ b/build/templates/backend/scripts/bsc_archive.sh @@ -0,0 +1,43 @@ +#!/bin/sh + +{{define "main" -}} + +set -e + +INSTALL_DIR={{.Env.BackendInstallPath}}/{{.Coin.Alias}} +DATA_DIR={{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend + +GETH_BIN=$INSTALL_DIR/geth_linux +CHAINDATA_DIR=$DATA_DIR/geth/chaindata + +if [ ! -d "$CHAINDATA_DIR" ]; then + $GETH_BIN init --datadir $DATA_DIR $INSTALL_DIR/genesis.json +fi + +$GETH_BIN \ + --config $INSTALL_DIR/config.toml \ + --datadir $DATA_DIR \ + --port {{.Ports.BackendP2P}} \ + --http \ + --http.addr 127.0.0.1 \ + --http.port {{.Ports.BackendHttp}} \ + --http.api eth,net,web3,debug,txpool \ + --http.vhosts '*' \ + --http.corsdomain '*' \ + --ws \ + --ws.addr 127.0.0.1 \ + --ws.port {{.Ports.BackendRPC}} \ + --ws.api eth,net,web3,debug,txpool \ + --ws.origins '*' \ + --gcmode archive \ + --cache.gc 0 \ + --cache.trie 30 \ + --syncmode full \ + --maxpeers 100 \ + --rpc.allow-unprotected-txs \ + --txlookuplimit 0 \ + --cache 8000 \ + --ipcdisable \ + --nat none + +{{end}} \ No newline at end of file diff --git a/build/tools/templates.go b/build/tools/templates.go index 42b16c03..f414e5e1 100644 --- a/build/tools/templates.go +++ b/build/tools/templates.go @@ -26,6 +26,7 @@ type Backend struct { ExtractCommand string `json:"extract_command"` ExcludeFiles []string `json:"exclude_files"` ExecCommandTemplate string `json:"exec_command_template"` + ExecScript string `json:"exec_script"` LogrotateFilesTemplate string `json:"logrotate_files_template"` PostinstScriptTemplate string `json:"postinst_script_template"` ServiceType string `json:"service_type"` @@ -280,11 +281,15 @@ func GeneratePackageDefinitions(config *Config, templateDir, outputDir string) e } if !isEmpty(config, "backend") { - err = writeBackendServerConfigFile(config, outputDir) - if err == nil { - err = writeBackendClientConfigFile(config, outputDir) + if err := writeBackendServerConfigFile(config, outputDir); err != nil { + return err } - if err != nil { + + if err := writeBackendClientConfigFile(config, outputDir); err != nil { + return err + } + + if err := writeBackendExecScript(config, outputDir); err != nil { return err } } @@ -354,3 +359,24 @@ func writeBackendClientConfigFile(config *Config, outputDir string) error { _, err = io.Copy(out, in) return err } + +func writeBackendExecScript(config *Config, outputDir string) error { + if config.Backend.ExecScript == "" { + return nil + } + + out, err := os.OpenFile(filepath.Join(outputDir, "backend/exec.sh"), os.O_CREATE|os.O_WRONLY, 0777) + if err != nil { + return err + } + defer out.Close() + + in, err := os.Open(filepath.Join(outputDir, "backend/scripts", config.Backend.ExecScript)) + if err != nil { + return err + } + defer in.Close() + + _, err = io.Copy(out, in) + return err +} diff --git a/configs/coins/bsc.json b/configs/coins/bsc.json new file mode 100644 index 00000000..5a5e6292 --- /dev/null +++ b/configs/coins/bsc.json @@ -0,0 +1,71 @@ +{ + "coin": { + "name": "BNB Smart Chain", + "shortcut": "BNB", + "label": "BNB Smart Chain", + "alias": "bsc" + }, + "ports": { + "backend_rpc": 8064, + "backend_p2p": 38364, + "backend_http": 8164, + "blockbook_internal": 9064, + "blockbook_public": 9164 + }, + "ipc": { + "rpc_url_template": "ws://127.0.0.1:{{.Ports.BackendRPC}}", + "rpc_timeout": 25 + }, + "backend": { + "package_name": "backend-bsc", + "package_revision": "satoshilabs-1", + "system_user": "bsc", + "version": "1.1.19", + "binary_url": "https://github.com/bnb-chain/bsc/releases/download/v1.1.19/geth_linux", + "verification_type": "sha256", + "verification_source": "ad49b00a5df44fb67e0dc166a7cf02a02c67ab296d25e4ac3d56134567577c41", + "extract_command": "mv ${ARCHIVE} backend/geth_linux && chmod +x backend/geth_linux && echo", + "exclude_files": [], + "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bsc_exec.sh'", + "exec_script": "bsc.sh", + "logrotate_files_template": "{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/bsc.log*", + "postinst_script_template": "wget https://github.com/bnb-chain/bsc/releases/download/v1.1.19/mainnet.zip -O {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/mainnet.zip && unzip -o -d {{.Env.BackendInstallPath}}/{{.Coin.Alias}} {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/mainnet.zip && rm -f {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/mainnet.zip", + "service_type": "simple", + "service_additional_params_template": "", + "protect_memory": true, + "mainnet": true, + "server_config_file": "", + "client_config_file": "", + "platforms": { + "arm64": { + "binary_url": "https://github.com/bnb-chain/bsc/releases/download/v1.1.19/geth-linux-arm64", + "verification_source": "50aae5defb41cb5f4da462b5f86097c2daf945672ce9fb1c1e4393f6e038610f" + } + } + }, + "blockbook": { + "package_name": "blockbook-bsc", + "system_user": "blockbook-bsc", + "internal_binding_template": ":{{.Ports.BlockbookInternal}}", + "public_binding_template": ":{{.Ports.BlockbookPublic}}", + "explorer_url": "", + "additional_params": "-workers=16", + "block_chain": { + "parse": true, + "mempool_workers": 8, + "mempool_sub_workers": 2, + "block_addresses_to_keep": 300, + "additional_params": { + "mempoolTxTimeoutHours": 48, + "queryBackendOnMempoolResync": false, + "fiat_rates": "coingecko", + "fiat_rates_vs_currencies": "AED,ARS,AUD,BDT,BHD,BMD,BRL,CAD,CHF,CLP,CNY,CZK,DKK,EUR,GBP,HKD,HUF,IDR,ILS,INR,JPY,KRW,KWD,LKR,MMK,MXN,MYR,NGN,NOK,NZD,PHP,PKR,PLN,RUB,SAR,SEK,SGD,THB,TRY,TWD,UAH,USD,VEF,VND,ZAR,BTC,ETH", + "fiat_rates_params": "{\"url\": \"https://api.coingecko.com/api/v3\", \"coin\": \"binancecoin\",\"platformIdentifier\": \"binance-smart-chain\",\"platformVsCurrency\": \"bnb\",\"periodSeconds\": 900}" + } + } + }, + "meta": { + "package_maintainer": "IT", + "package_maintainer_email": "it@satoshilabs.com" + } +} \ No newline at end of file diff --git a/configs/coins/bsc_archive.json b/configs/coins/bsc_archive.json new file mode 100644 index 00000000..4f8a30af --- /dev/null +++ b/configs/coins/bsc_archive.json @@ -0,0 +1,74 @@ +{ + "coin": { + "name": "BNB Smart Chain Archive", + "shortcut": "BNB", + "label": "BNB Smart Chain", + "alias": "bsc_archive" + }, + "ports": { + "backend_rpc": 8065, + "backend_p2p": 38365, + "backend_http": 8165, + "blockbook_internal": 9065, + "blockbook_public": 9165 + }, + "ipc": { + "rpc_url_template": "ws://127.0.0.1:{{.Ports.BackendRPC}}", + "rpc_timeout": 25 + }, + "backend": { + "package_name": "backend-bsc-archive", + "package_revision": "satoshilabs-1", + "system_user": "bsc", + "version": "1.1.19", + "binary_url": "https://github.com/bnb-chain/bsc/releases/download/v1.1.19/geth_linux", + "verification_type": "sha256", + "verification_source": "ad49b00a5df44fb67e0dc166a7cf02a02c67ab296d25e4ac3d56134567577c41", + "extract_command": "mv ${ARCHIVE} backend/geth_linux && chmod +x backend/geth_linux && echo", + "exclude_files": [], + "exec_command_template": "/bin/sh -c '{{.Env.BackendInstallPath}}/{{.Coin.Alias}}/bsc_archive_exec.sh'", + "exec_script": "bsc_archive.sh", + "logrotate_files_template": "{{.Env.BackendDataPath}}/{{.Coin.Alias}}/backend/bsc.log*", + "postinst_script_template": "wget https://github.com/bnb-chain/bsc/releases/download/v1.1.19/mainnet.zip -O {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/mainnet.zip && unzip -o -d {{.Env.BackendInstallPath}}/{{.Coin.Alias}} {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/mainnet.zip && rm -f {{.Env.BackendInstallPath}}/{{.Coin.Alias}}/mainnet.zip", + "service_type": "simple", + "service_additional_params_template": "", + "protect_memory": true, + "mainnet": true, + "server_config_file": "", + "client_config_file": "", + "platforms": { + "arm64": { + "binary_url": "https://github.com/bnb-chain/bsc/releases/download/v1.1.19/geth-linux-arm64", + "verification_source": "50aae5defb41cb5f4da462b5f86097c2daf945672ce9fb1c1e4393f6e038610f" + } + } + }, + "blockbook": { + "package_name": "blockbook-bsc-archive", + "system_user": "blockbook-bsc", + "internal_binding_template": ":{{.Ports.BlockbookInternal}}", + "public_binding_template": ":{{.Ports.BlockbookPublic}}", + "explorer_url": "", + "additional_params": "-workers=16", + "block_chain": { + "parse": true, + "mempool_workers": 8, + "mempool_sub_workers": 2, + "block_addresses_to_keep": 600, + "additional_params": { + "address_aliases": true, + "mempoolTxTimeoutHours": 48, + "processInternalTransactions": true, + "queryBackendOnMempoolResync": false, + "fiat_rates": "coingecko", + "fiat_rates_vs_currencies": "AED,ARS,AUD,BDT,BHD,BMD,BRL,CAD,CHF,CLP,CNY,CZK,DKK,EUR,GBP,HKD,HUF,IDR,ILS,INR,JPY,KRW,KWD,LKR,MMK,MXN,MYR,NGN,NOK,NZD,PHP,PKR,PLN,RUB,SAR,SEK,SGD,THB,TRY,TWD,UAH,USD,VEF,VND,ZAR,BTC,ETH", + "fiat_rates_params": "{\"url\": \"https://api.coingecko.com/api/v3\", \"coin\": \"binancecoin\",\"platformIdentifier\": \"binance-smart-chain\",\"platformVsCurrency\": \"bnb\",\"periodSeconds\": 900}", + "fourByteSignatures": "https://www.4byte.directory/api/v1/signatures/" + } + } + }, + "meta": { + "package_maintainer": "IT", + "package_maintainer_email": "it@satoshilabs.com" + } +} \ No newline at end of file diff --git a/docs/ports.md b/docs/ports.md index 9b010b39..02b8fc20 100644 --- a/docs/ports.md +++ b/docs/ports.md @@ -1,76 +1,78 @@ # Registry of ports -| coin | blockbook internal port | blockbook public port | backend rpc port | backend service ports (zmq) | -|------------------------|-------------------------|-----------------------|------------------|-----------------------------| -| Bitcoin | 9030 | 9130 | 8030 | 38330 | -| Bitcoin Cash | 9031 | 9131 | 8031 | 38331 | -| Zcash | 9032 | 9132 | 8032 | 38332 | -| Dash | 9033 | 9133 | 8033 | 38333 | -| Litecoin | 9034 | 9134 | 8034 | 38334 | -| Bitcoin Gold | 9035 | 9135 | 8035 | 38335 | -| Ethereum | 9036 | 9136 | 8036 | 38336 p2p, 8136 http | -| Ethereum Classic | 9037 | 9137 | 8037 | | -| Dogecoin | 9038 | 9138 | 8038 | 38338 | -| Namecoin | 9039 | 9139 | 8039 | 38339 | -| Vertcoin | 9040 | 9140 | 8040 | 38340 | -| Monacoin | 9041 | 9141 | 8041 | 38341 | -| DigiByte | 9042 | 9142 | 8042 | 38342 | -| Myriad | 9043 | 9143 | 8043 | 38343 | -| GameCredits | 9044 | 9144 | 8044 | 38344 | -| Groestlcoin | 9045 | 9145 | 8045 | 38345 | -| Bitcoin Cash SV | 9046 | 9146 | 8046 | 38346 | -| Liquid | 9047 | 9147 | 8047 | 38347 | -| Fujicoin | 9048 | 9148 | 8048 | 38348 | -| PIVX | 9049 | 9149 | 8049 | 38349 | -| Firo | 9050 | 9150 | 8050 | 38350 | -| Koto | 9051 | 9151 | 8051 | 38351 | -| Bellcoin | 9052 | 9152 | 8052 | 38352 | -| NULS | 9053 | 9153 | 8053 | 38353 | -| Bitcore | 9054 | 9154 | 8054 | 38354 | -| Viacoin | 9055 | 9155 | 8055 | 38355 | -| VIPSTARCOIN | 9056 | 9156 | 8056 | 38356 | -| MonetaryUnit | 9057 | 9157 | 8057 | 38357 | -| Flux | 9058 | 9158 | 8058 | 38358 | -| Ravencoin | 9059 | 9159 | 8059 | 38359 | -| Ritocoin | 9060 | 9160 | 8060 | 38360 | -| Decred | 9061 | 9161 | 8061 | 38361 | -| SnowGem | 9062 | 9162 | 8062 | 38362 | -| Flo | 9066 | 9166 | 8066 | 38366 | -| Polis | 9067 | 9167 | 8067 | 38367 | -| 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 | -| Omotenashicoin | 9094 | 9194 | 8094 | 38394 | -| BitZeny | 9095 | 9195 | 8095 | 38395 | -| Trezarcoin | 9096 | 9196 | 8096 | 38396 | -| eCash | 9097 | 9197 | 8097 | 38397 | -| Avalanche | 9098 | 9198 | 8098 | 38398 p2p | -| Avalanche Archive | 9099 | 9199 | 8099 | 38399 p2p | -| Bitcoin Signet | 19020 | 19120 | 18020 | 48320 | -| Bitcoin Regtest | 19021 | 19121 | 18021 | 48321 | -| Ethereum Goerli | 19026 | 19126 | 18026 | 48326 p2p | -| Ethereum Sepolia | 19176 | 19176 | 18076 | 48376 p2p | -| Bitcoin Testnet | 19030 | 19130 | 18030 | 48330 | -| Bitcoin Cash Testnet | 19031 | 19131 | 18031 | 48331 | -| Zcash Testnet | 19032 | 19132 | 18032 | 48332 | -| Dash Testnet | 19033 | 19133 | 18033 | 48333 | -| Litecoin Testnet | 19034 | 19134 | 18034 | 48334 | -| Bitcoin Gold Testnet | 19035 | 19135 | 18035 | 48335 | -| Ethereum Ropsten | 19036 | 19136 | 18036 | 48336 p2p | -| Dogecoin Testnet | 19038 | 19138 | 18038 | 48338 | -| Vertcoin Testnet | 19040 | 19140 | 18040 | 48340 | -| Monacoin Testnet | 19041 | 19141 | 18041 | 48341 | -| DigiByte Testnet | 19042 | 19142 | 18042 | 48342 | -| Groestlcoin Testnet | 19045 | 19145 | 18045 | 48345 | -| Groestlcoin Regtest | 19046 | 19146 | 18046 | 48346 | -| Groestlcoin Signet | 19047 | 19147 | 18047 | 48347 | -| PIVX Testnet | 19049 | 19149 | 18049 | 48349 | -| Koto Testnet | 19051 | 19151 | 18051 | 48351 | -| Decred Testnet | 19061 | 19161 | 18061 | 48361 | -| Flo Testnet | 19066 | 19166 | 18066 | 48366 | -| Qtum Testnet | 19088 | 19188 | 18088 | 48388 | -| Omotenashicoin Testnet | 19089 | 19189 | 18089 | 48389 | +| coin | blockbook internal port | blockbook public port | backend rpc port | backend service ports (zmq) | +|-------------------------|-------------------------|-----------------------|------------------|-----------------------------| +| Bitcoin | 9030 | 9130 | 8030 | 38330 | +| Bitcoin Cash | 9031 | 9131 | 8031 | 38331 | +| Zcash | 9032 | 9132 | 8032 | 38332 | +| Dash | 9033 | 9133 | 8033 | 38333 | +| Litecoin | 9034 | 9134 | 8034 | 38334 | +| Bitcoin Gold | 9035 | 9135 | 8035 | 38335 | +| Ethereum | 9036 | 9136 | 8036 | 38336 p2p, 8136 http | +| Ethereum Classic | 9037 | 9137 | 8037 | | +| Dogecoin | 9038 | 9138 | 8038 | 38338 | +| Namecoin | 9039 | 9139 | 8039 | 38339 | +| Vertcoin | 9040 | 9140 | 8040 | 38340 | +| Monacoin | 9041 | 9141 | 8041 | 38341 | +| DigiByte | 9042 | 9142 | 8042 | 38342 | +| Myriad | 9043 | 9143 | 8043 | 38343 | +| GameCredits | 9044 | 9144 | 8044 | 38344 | +| Groestlcoin | 9045 | 9145 | 8045 | 38345 | +| Bitcoin Cash SV | 9046 | 9146 | 8046 | 38346 | +| Liquid | 9047 | 9147 | 8047 | 38347 | +| Fujicoin | 9048 | 9148 | 8048 | 38348 | +| PIVX | 9049 | 9149 | 8049 | 38349 | +| Firo | 9050 | 9150 | 8050 | 38350 | +| Koto | 9051 | 9151 | 8051 | 38351 | +| Bellcoin | 9052 | 9152 | 8052 | 38352 | +| NULS | 9053 | 9153 | 8053 | 38353 | +| Bitcore | 9054 | 9154 | 8054 | 38354 | +| Viacoin | 9055 | 9155 | 8055 | 38355 | +| VIPSTARCOIN | 9056 | 9156 | 8056 | 38356 | +| MonetaryUnit | 9057 | 9157 | 8057 | 38357 | +| Flux | 9058 | 9158 | 8058 | 38358 | +| Ravencoin | 9059 | 9159 | 8059 | 38359 | +| Ritocoin | 9060 | 9160 | 8060 | 38360 | +| Decred | 9061 | 9161 | 8061 | 38361 | +| SnowGem | 9062 | 9162 | 8062 | 38362 | +| BNB Smart Chain | 9064 | 9164 | 8064 | 38364 p2p, 8164 http | +| BNB Smart Chain Archive | 9065 | 9165 | 8065 | 38365 p2p, 8165 http | +| Flo | 9066 | 9166 | 8066 | 38366 | +| Polis | 9067 | 9167 | 8067 | 38367 | +| 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 | +| Omotenashicoin | 9094 | 9194 | 8094 | 38394 | +| BitZeny | 9095 | 9195 | 8095 | 38395 | +| Trezarcoin | 9096 | 9196 | 8096 | 38396 | +| eCash | 9097 | 9197 | 8097 | 38397 | +| Avalanche | 9098 | 9198 | 8098 | 38398 p2p | +| Avalanche Archive | 9099 | 9199 | 8099 | 38399 p2p | +| Bitcoin Signet | 19020 | 19120 | 18020 | 48320 | +| Bitcoin Regtest | 19021 | 19121 | 18021 | 48321 | +| Ethereum Goerli | 19026 | 19126 | 18026 | 48326 p2p | +| Ethereum Sepolia | 19176 | 19176 | 18076 | 48376 p2p | +| Bitcoin Testnet | 19030 | 19130 | 18030 | 48330 | +| Bitcoin Cash Testnet | 19031 | 19131 | 18031 | 48331 | +| Zcash Testnet | 19032 | 19132 | 18032 | 48332 | +| Dash Testnet | 19033 | 19133 | 18033 | 48333 | +| Litecoin Testnet | 19034 | 19134 | 18034 | 48334 | +| Bitcoin Gold Testnet | 19035 | 19135 | 18035 | 48335 | +| Ethereum Ropsten | 19036 | 19136 | 18036 | 48336 p2p | +| Dogecoin Testnet | 19038 | 19138 | 18038 | 48338 | +| Vertcoin Testnet | 19040 | 19140 | 18040 | 48340 | +| Monacoin Testnet | 19041 | 19141 | 18041 | 48341 | +| DigiByte Testnet | 19042 | 19142 | 18042 | 48342 | +| Groestlcoin Testnet | 19045 | 19145 | 18045 | 48345 | +| Groestlcoin Regtest | 19046 | 19146 | 18046 | 48346 | +| Groestlcoin Signet | 19047 | 19147 | 18047 | 48347 | +| PIVX Testnet | 19049 | 19149 | 18049 | 48349 | +| Koto Testnet | 19051 | 19151 | 18051 | 48351 | +| Decred Testnet | 19061 | 19161 | 18061 | 48361 | +| Flo Testnet | 19066 | 19166 | 18066 | 48366 | +| Qtum Testnet | 19088 | 19188 | 18088 | 48388 | +| Omotenashicoin Testnet | 19089 | 19189 | 18089 | 48389 | > NOTE: This document is generated from coin definitions in `configs/coins`. diff --git a/server/public.go b/server/public.go index fb6c9118..73936c74 100644 --- a/server/public.go +++ b/server/public.go @@ -343,6 +343,11 @@ func (s *PublicServer) newTemplateData(r *http.Request) *TemplateData { InternalExplorer: s.internalExplorer && !s.is.InitialSync, TOSLink: api.Text.TOSLink, } + if t.ChainType == bchain.ChainEthereumType { + t.FungibleTokenName = bchain.EthereumTokenTypeMap[bchain.FungibleToken] + t.NonFungibleTokenName = bchain.EthereumTokenTypeMap[bchain.NonFungibleToken] + t.MultiTokenName = bchain.EthereumTokenTypeMap[bchain.MultiToken] + } if !s.debug { t.Minified = ".min.2" } @@ -486,6 +491,9 @@ type TemplateData struct { CoinLabel string InternalExplorer bool ChainType bchain.ChainType + FungibleTokenName bchain.TokenTypeName + NonFungibleTokenName bchain.TokenTypeName + MultiTokenName bchain.TokenTypeName Address *api.Address AddrStr string Tx *api.Tx diff --git a/static/templates/address.html b/static/templates/address.html index 2ae5bb30..21a3e1e3 100644 --- a/static/templates/address.html +++ b/static/templates/address.html @@ -109,13 +109,13 @@ {{end}} {{if eq .ChainType 1}} -{{if tokenCount $addr.Tokens "ERC20"}} +{{if tokenCount $addr.Tokens .FungibleTokenName}}
@@ -131,7 +131,7 @@ Transfers# {{range $t := $addr.Tokens}} - {{if eq $t.Type "ERC20"}} + {{if eq $t.Type $.FungibleTokenName}} {{if $t.Name}}{{$t.Name}}{{else}}{{$t.Contract}}{{end}} {{formattedAmountSpan $t.BalanceSat $t.Decimals $t.Symbol $data "copyable"}} @@ -147,13 +147,13 @@
{{end}} -{{if tokenCount $addr.Tokens "ERC721"}} +{{if tokenCount $addr.Tokens .NonFungibleTokenName}}
@@ -167,7 +167,7 @@ Transfers# {{range $t := $addr.Tokens}} - {{if eq $t.Type "ERC721"}} + {{if eq $t.Type $.NonFungibleTokenName}} {{if $t.Name}}{{$t.Name}}{{else}}{{$t.Contract}}{{end}} @@ -184,13 +184,13 @@
{{end}} -{{if tokenCount $addr.Tokens "ERC1155"}} +{{if tokenCount $addr.Tokens .MultiTokenName}}
@@ -204,7 +204,7 @@ Transfers# {{range $t := $addr.Tokens}} - {{if eq $t.Type "ERC1155"}} + {{if eq $t.Type $.MultiTokenName}} {{if $t.Name}}{{$t.Name}}{{else}}{{$t.Contract}}{{end}} @@ -234,18 +234,18 @@ {{range $t := $addr.Tokens}} - {{if eq $t.Type "ERC20"}} - + {{if eq $t.Type $.FungibleTokenName}} + {{end}} {{end}} {{range $t := $addr.Tokens}} - {{if eq $t.Type "ERC721"}} - + {{if eq $t.Type $.NonFungibleTokenName}} + {{end}} {{end}} {{range $t := $addr.Tokens}} - {{if eq $t.Type "ERC1155"}} - + {{if eq $t.Type $.MultiTokenName}} + {{end}} {{end}} {{end}} diff --git a/static/templates/txdetail_ethereumtype.html b/static/templates/txdetail_ethereumtype.html index 3d2281c1..e2acaa60 100644 --- a/static/templates/txdetail_ethereumtype.html +++ b/static/templates/txdetail_ethereumtype.html @@ -95,12 +95,12 @@ {{end}} {{end}} - {{if tokenTransfersCount $tx "ERC20"}} + {{if tokenTransfersCount $tx .FungibleTokenName}}
- ERC20 Token Transfers + {{.FungibleTokenName}} Token Transfers
{{range $tt := $tx.TokenTransfers}} - {{if eq $tt.Type "ERC20"}} + {{if eq $tt.Type $.FungibleTokenName}}
@@ -123,12 +123,12 @@ {{end}} {{end}} - {{if tokenTransfersCount $tx "ERC721"}} + {{if tokenTransfersCount $tx .NonFungibleTokenName}}
- ERC721 Token Transfers + {{.NonFungibleTokenName}} Token Transfers
{{range $tt := $tx.TokenTransfers}} - {{if eq $tt.Type "ERC721"}} + {{if eq $tt.Type $.NonFungibleTokenName}}
@@ -151,12 +151,12 @@ {{end}} {{end}} - {{if tokenTransfersCount $tx "ERC1155"}} + {{if tokenTransfersCount $tx .MultiTokenName}}
- ERC1155 Token Transfers + {{.MultiTokenName}} Token Transfers
{{range $tt := $tx.TokenTransfers}} - {{if eq $tt.Type "ERC1155"}} + {{if eq $tt.Type $.MultiTokenName}}
diff --git a/tests/rpc/testdata/bsc.json b/tests/rpc/testdata/bsc.json new file mode 100644 index 00000000..eae2bd09 --- /dev/null +++ b/tests/rpc/testdata/bsc.json @@ -0,0 +1,56 @@ +{ + "blockHeight": 12823819, + "blockHash": "0x13a36aea55df099a02f777980840fc82dd0a6748fd1245a5185ec4401fdc196c", + "blockTime": 1637466737, + "blockSize": 945, + "blockTxs": [ + "0x970fec39c96e92669d68ac2366ffe9dab7314eefc075f1db760a9792a8bffa12", + "0x05618ba2e7e98c6cb3a9d05e6e62c0983b430103c69f1045608e812730bd61fc" + ], + "txDetails": { + "0x970fec39c96e92669d68ac2366ffe9dab7314eefc075f1db760a9792a8bffa12": { + "txid": "0x970fec39c96e92669d68ac2366ffe9dab7314eefc075f1db760a9792a8bffa12", + "blockTime": 1637466737, + "time": 1637466737, + "vin": [ + { + "addresses": [ + "0xd6f2815c885f3c628b99873cb0feb3b96df63163" + ] + } + ], + "vout": [ + { + "value": 4, + "scriptPubKey": { + "addresses": [ + "0xfd53b1b4af84d59b20bf2c20ca89a6beeaa2c628" + ] + } + } + ] + }, + "0x05618ba2e7e98c6cb3a9d05e6e62c0983b430103c69f1045608e812730bd61fc": { + "txid": "0x05618ba2e7e98c6cb3a9d05e6e62c0983b430103c69f1045608e812730bd61fc", + "blockTime": 1637466737, + "time": 1637466737, + "vin": [ + { + "addresses": [ + "0x295e26495cef6f69dfa69911d9d8e4f3bbadb89b" + ] + } + ], + "vout": [ + { + "value": 0.00206658, + "scriptPubKey": { + "addresses": [ + "0x0000000000000000000000000000000000001000" + ] + } + } + ] + } + } +} \ No newline at end of file diff --git a/tests/rpc/testdata/bsc_archive.json b/tests/rpc/testdata/bsc_archive.json new file mode 100644 index 00000000..eae2bd09 --- /dev/null +++ b/tests/rpc/testdata/bsc_archive.json @@ -0,0 +1,56 @@ +{ + "blockHeight": 12823819, + "blockHash": "0x13a36aea55df099a02f777980840fc82dd0a6748fd1245a5185ec4401fdc196c", + "blockTime": 1637466737, + "blockSize": 945, + "blockTxs": [ + "0x970fec39c96e92669d68ac2366ffe9dab7314eefc075f1db760a9792a8bffa12", + "0x05618ba2e7e98c6cb3a9d05e6e62c0983b430103c69f1045608e812730bd61fc" + ], + "txDetails": { + "0x970fec39c96e92669d68ac2366ffe9dab7314eefc075f1db760a9792a8bffa12": { + "txid": "0x970fec39c96e92669d68ac2366ffe9dab7314eefc075f1db760a9792a8bffa12", + "blockTime": 1637466737, + "time": 1637466737, + "vin": [ + { + "addresses": [ + "0xd6f2815c885f3c628b99873cb0feb3b96df63163" + ] + } + ], + "vout": [ + { + "value": 4, + "scriptPubKey": { + "addresses": [ + "0xfd53b1b4af84d59b20bf2c20ca89a6beeaa2c628" + ] + } + } + ] + }, + "0x05618ba2e7e98c6cb3a9d05e6e62c0983b430103c69f1045608e812730bd61fc": { + "txid": "0x05618ba2e7e98c6cb3a9d05e6e62c0983b430103c69f1045608e812730bd61fc", + "blockTime": 1637466737, + "time": 1637466737, + "vin": [ + { + "addresses": [ + "0x295e26495cef6f69dfa69911d9d8e4f3bbadb89b" + ] + } + ], + "vout": [ + { + "value": 0.00206658, + "scriptPubKey": { + "addresses": [ + "0x0000000000000000000000000000000000001000" + ] + } + } + ] + } + } +} \ No newline at end of file diff --git a/tests/tests.json b/tests/tests.json index cb5cc1ac..a53cd23e 100644 --- a/tests/tests.json +++ b/tests/tests.json @@ -44,7 +44,13 @@ "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync", "EstimateSmartFee", "EstimateFee", "GetBestBlockHash", "GetBestBlockHeight", "GetBlockHeader"], "sync": ["ConnectBlocksParallel", "ConnectBlocks", "HandleFork"] - }, + }, + "bsc": { + "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "EstimateFee", "GetBlockHeader"] + }, + "bsc_archive": { + "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "EstimateFee", "GetBlockHeader"] + }, "cpuchain": { "rpc": ["GetBlock", "GetBlockHash", "GetTransaction", "GetTransactionForMempool", "MempoolSync", "EstimateSmartFee", "EstimateFee"],