Rework tx link formatting
This commit is contained in:
parent
9c45cb2918
commit
69e992f06e
|
@ -82,13 +82,7 @@ WHERE not exists(SELECT *
|
|||
}
|
||||
client, ok := clients[bt.ChainID]
|
||||
if !ok {
|
||||
var chainCfg *config.ChainConfig
|
||||
for _, c := range cfg.Chains {
|
||||
if c.ChainID == bt.ChainID {
|
||||
chainCfg = c
|
||||
break
|
||||
}
|
||||
}
|
||||
chainCfg := cfg.GetChainConfig(bt.ChainID)
|
||||
if chainCfg == nil {
|
||||
logger.WithFields(fields).Fatal("can't find chain config")
|
||||
}
|
||||
|
|
|
@ -42,6 +42,9 @@
|
|||
},
|
||||
"safe_logs_request": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"explorer_tx_link_format": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
|
|
15
config.yml
15
config.yml
|
@ -7,6 +7,7 @@ chains:
|
|||
chain_id: 1
|
||||
block_time: 15s
|
||||
block_index_interval: 60s
|
||||
explorer_tx_link_format: 'https://etherscan.io/tx/%s'
|
||||
bsc:
|
||||
rpc:
|
||||
host: https://bsc-dataseed2.defibit.io
|
||||
|
@ -16,6 +17,7 @@ chains:
|
|||
block_time: 3s
|
||||
block_index_interval: 60s
|
||||
safe_logs_request: true
|
||||
explorer_tx_link_format: 'https://bscscan.com/tx/%s'
|
||||
kovan:
|
||||
rpc:
|
||||
host: https://kovan.infura.io/v3/${INFURA_PROJECT_KEY}
|
||||
|
@ -24,15 +26,17 @@ chains:
|
|||
chain_id: 42
|
||||
block_time: 5s
|
||||
block_index_interval: 60s
|
||||
explorer_tx_link_format: 'https://kovan.etherscan.io/tx/%s'
|
||||
xdai:
|
||||
rpc:
|
||||
host: https://rpc.xdaichain.com/oe-only
|
||||
host: https://rpc.ankr.com/gnosis
|
||||
timeout: 20s
|
||||
rps: 10
|
||||
chain_id: 100
|
||||
block_time: 5s
|
||||
block_index_interval: 30s
|
||||
safe_logs_request: true
|
||||
explorer_tx_link_format: 'https://blockscout.com/xdai/mainnet/tx/%s'
|
||||
poa:
|
||||
rpc:
|
||||
host: https://core.poanetwork.dev
|
||||
|
@ -41,6 +45,7 @@ chains:
|
|||
chain_id: 99
|
||||
block_time: 5s
|
||||
block_index_interval: 30s
|
||||
explorer_tx_link_format: 'https://blockscout.com/poa/core/tx/%s'
|
||||
sokol:
|
||||
rpc:
|
||||
host: https://sokol.poa.network
|
||||
|
@ -49,6 +54,7 @@ chains:
|
|||
chain_id: 77
|
||||
block_time: 5s
|
||||
block_index_interval: 30s
|
||||
explorer_tx_link_format: 'https://blockscout.com/poa/sokol/tx/%s'
|
||||
rinkeby:
|
||||
rpc:
|
||||
host: https://rinkeby.infura.io/v3/${INFURA_PROJECT_KEY}
|
||||
|
@ -57,6 +63,7 @@ chains:
|
|||
chain_id: 4
|
||||
block_time: 15s
|
||||
block_index_interval: 60s
|
||||
explorer_tx_link_format: 'https://rinkeby.etherscan.io/tx/%s'
|
||||
bridges:
|
||||
xdai:
|
||||
bridge_mode: ERC_TO_NATIVE
|
||||
|
@ -158,7 +165,7 @@ bridges:
|
|||
validator_contract_address: 0x6f00218e7D985FE1211f5d47B350708fF915A842
|
||||
start_block: 14496719
|
||||
required_block_confirmations: 12
|
||||
max_block_range_size: 10000
|
||||
max_block_range_size: 2000
|
||||
foreign:
|
||||
chain: bsc
|
||||
address: 0x05185872898b6f94AA600177EF41B9334B1FA48B
|
||||
|
@ -186,7 +193,7 @@ bridges:
|
|||
validator_contract_address: 0xAC91dfb485ED2B96381686D3d299e3D041dB4051
|
||||
start_block: 10030209
|
||||
required_block_confirmations: 12
|
||||
max_block_range_size: 20000
|
||||
max_block_range_size: 2000
|
||||
foreign:
|
||||
chain: rinkeby
|
||||
address: 0xD4075FB57fCf038bFc702c915Ef9592534bED5c1
|
||||
|
@ -212,7 +219,7 @@ bridges:
|
|||
validator_contract_address: 0x72C5E5f2C905f9b57FD433a58d6215AC8109991C
|
||||
start_block: 17976494
|
||||
required_block_confirmations: 12
|
||||
max_block_range_size: 10000
|
||||
max_block_range_size: 2000
|
||||
foreign:
|
||||
chain: poa
|
||||
address: 0xB2218bdEbe8e90f80D04286772B0968ead666942
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
|
@ -10,7 +9,6 @@ import (
|
|||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/sirupsen/logrus"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var (
|
||||
|
@ -31,6 +29,7 @@ type ChainConfig struct {
|
|||
BlockTime time.Duration `yaml:"block_time"`
|
||||
BlockIndexInterval time.Duration `yaml:"block_index_interval"`
|
||||
SafeLogsRequest bool `yaml:"safe_logs_request"`
|
||||
ExplorerTxLinkFormat string `yaml:"explorer_tx_link_format"`
|
||||
}
|
||||
|
||||
type TokenConfig struct {
|
||||
|
@ -94,11 +93,21 @@ type Config struct {
|
|||
Presenter *PresenterConfig `yaml:"presenter"`
|
||||
}
|
||||
|
||||
func parseYaml(out *Config, blob []byte) error {
|
||||
dec := yaml.NewDecoder(bytes.NewReader(blob))
|
||||
dec.KnownFields(true)
|
||||
if err := dec.Decode(out); err != nil {
|
||||
return fmt.Errorf("can't parse yaml: %w", err)
|
||||
func (cfg *ChainConfig) FormatTxLink(txHash fmt.Stringer) string {
|
||||
if cfg == nil || cfg.ExplorerTxLinkFormat == "" {
|
||||
return txHash.String()
|
||||
}
|
||||
return fmt.Sprintf(cfg.ExplorerTxLinkFormat, txHash)
|
||||
}
|
||||
|
||||
func (cfg *Config) GetChainConfig(chainID string) *ChainConfig {
|
||||
if chainCfg, ok := cfg.Chains[chainID]; ok {
|
||||
return chainCfg
|
||||
}
|
||||
for _, chainCfg := range cfg.Chains {
|
||||
if chainCfg.ChainID == chainID {
|
||||
return chainCfg
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ chains:
|
|||
chain_id: 1
|
||||
block_time: 15s
|
||||
block_index_interval: 60s
|
||||
explorer_tx_link_format: 'https://etherscan.io/tx/%s'
|
||||
xdai:
|
||||
rpc:
|
||||
host: https://rpc.ankr.com/gnosis
|
||||
|
@ -109,6 +110,7 @@ func TestReadConfigWithEnv(t *testing.T) {
|
|||
BlockTime: 15 * time.Second,
|
||||
BlockIndexInterval: 60 * time.Second,
|
||||
SafeLogsRequest: false,
|
||||
ExplorerTxLinkFormat: "https://etherscan.io/tx/%s",
|
||||
}
|
||||
xdaiChainCfg := &config.ChainConfig{
|
||||
RPC: &config.RPCConfig{
|
||||
|
@ -222,18 +224,18 @@ func TestBridgeSideConfig_ErcToNativeTokenAddresses(t *testing.T) {
|
|||
cfg, err := config.ReadConfig([]byte(testCfg))
|
||||
require.NoError(t, err)
|
||||
tokenAddresses := cfg.Bridges["xdai"].Foreign.ErcToNativeTokenAddresses(7000000, 11000000)
|
||||
require.Equal(t, tokenAddresses, []common.Address{
|
||||
require.Equal(t, []common.Address{
|
||||
common.HexToAddress("0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359"),
|
||||
common.HexToAddress("0x6B175474E89094C44Da98b954EedeAC495271d0F"),
|
||||
})
|
||||
}, tokenAddresses)
|
||||
tokenAddresses = cfg.Bridges["xdai"].Foreign.ErcToNativeTokenAddresses(7000000, 8000000)
|
||||
require.Equal(t, tokenAddresses, []common.Address{
|
||||
require.Equal(t, []common.Address{
|
||||
common.HexToAddress("0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359"),
|
||||
})
|
||||
}, tokenAddresses)
|
||||
tokenAddresses = cfg.Bridges["xdai"].Foreign.ErcToNativeTokenAddresses(10000000, 11000000)
|
||||
require.Equal(t, tokenAddresses, []common.Address{
|
||||
require.Equal(t, []common.Address{
|
||||
common.HexToAddress("0x6B175474E89094C44Da98b954EedeAC495271d0F"),
|
||||
})
|
||||
}, tokenAddresses)
|
||||
}
|
||||
|
||||
func TestBridgeSideConfig_ContractAddresses(t *testing.T) {
|
||||
|
@ -241,10 +243,34 @@ func TestBridgeSideConfig_ContractAddresses(t *testing.T) {
|
|||
cfg, err := config.ReadConfig([]byte(testCfg))
|
||||
require.NoError(t, err)
|
||||
tokenAddresses := cfg.Bridges["xdai"].Foreign.ContractAddresses(7000000, 11000000)
|
||||
require.Equal(t, tokenAddresses, []common.Address{
|
||||
require.Equal(t, []common.Address{
|
||||
common.HexToAddress("0x89d24A6b4CcB1B6fAA2625fE562bDD9a23260359"),
|
||||
common.HexToAddress("0x6B175474E89094C44Da98b954EedeAC495271d0F"),
|
||||
common.HexToAddress("0x4aa42145Aa6Ebf72e164C9bBC74fbD3788045016"),
|
||||
common.HexToAddress("0xe1579dEbdD2DF16Ebdb9db8694391fa74EeA201E"),
|
||||
})
|
||||
}, tokenAddresses)
|
||||
}
|
||||
|
||||
func TestConfig_GetChainConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg, err := config.ReadConfig([]byte(testCfg))
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NotNil(t, cfg.GetChainConfig("xdai"))
|
||||
require.Equal(t, "100", cfg.GetChainConfig("xdai").ChainID)
|
||||
require.NotNil(t, cfg.GetChainConfig("100"))
|
||||
require.Equal(t, "100", cfg.GetChainConfig("100").ChainID)
|
||||
require.Nil(t, cfg.GetChainConfig("123"))
|
||||
}
|
||||
|
||||
func TestChainConfig_FormatTxLink(t *testing.T) {
|
||||
t.Parallel()
|
||||
cfg, err := config.ReadConfig([]byte(testCfg))
|
||||
require.NoError(t, err)
|
||||
|
||||
txHash := "0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
link := "https://etherscan.io/tx/0x0000000000000000000000000000000000000000000000000000000000000000"
|
||||
require.Equal(t, link, cfg.GetChainConfig("mainnet").FormatTxLink(common.Hash{}))
|
||||
require.Equal(t, link, cfg.GetChainConfig("1").FormatTxLink(common.Hash{}))
|
||||
require.Equal(t, txHash, cfg.GetChainConfig("123").FormatTxLink(common.Hash{}))
|
||||
}
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
func parseYaml(out interface{}, blob []byte) error {
|
||||
dec := yaml.NewDecoder(bytes.NewReader(blob))
|
||||
dec.KnownFields(true)
|
||||
if err := dec.Decode(out); err != nil {
|
||||
return fmt.Errorf("can't parse yaml: %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -71,13 +71,7 @@ func GetChainConfigMiddleware(cfg *config.Config) func(http.Handler) http.Handle
|
|||
}
|
||||
}
|
||||
|
||||
var chainCfg *config.ChainConfig
|
||||
for _, c := range cfg.Chains {
|
||||
if c.ChainID == chainID {
|
||||
chainCfg = c
|
||||
break
|
||||
}
|
||||
}
|
||||
chainCfg := cfg.GetChainConfig(chainID)
|
||||
if chainCfg == nil {
|
||||
render.JSON(w, r, http.StatusNotFound, fmt.Sprintf("chain with id %s not found", chainID))
|
||||
return
|
||||
|
|
|
@ -529,6 +529,6 @@ func (p *Presenter) getTxInfo(ctx context.Context, logID uint) (*TxInfo, error)
|
|||
return &TxInfo{
|
||||
BlockNumber: log.BlockNumber,
|
||||
Timestamp: bt.Timestamp,
|
||||
Link: FormatLogTxLinkURL(log),
|
||||
Link: p.cfg.GetChainConfig(log.ChainID).FormatTxLink(log.TransactionHash),
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -101,3 +101,36 @@ type TxInfo struct {
|
|||
Timestamp time.Time
|
||||
Link string
|
||||
}
|
||||
|
||||
func NewMessageInfo(msg *entity.Message) *MessageInfo {
|
||||
return &MessageInfo{
|
||||
BridgeID: msg.BridgeID,
|
||||
MsgHash: msg.MsgHash,
|
||||
MessageID: msg.MessageID,
|
||||
Direction: msg.Direction,
|
||||
Sender: msg.Sender,
|
||||
Executor: msg.Executor,
|
||||
DataType: msg.DataType,
|
||||
}
|
||||
}
|
||||
|
||||
func NewInformationRequestInfo(req *entity.InformationRequest) *InformationRequestInfo {
|
||||
return &InformationRequestInfo{
|
||||
BridgeID: req.BridgeID,
|
||||
MessageID: req.MessageID,
|
||||
Direction: req.Direction,
|
||||
Sender: req.Sender,
|
||||
Executor: req.Executor,
|
||||
}
|
||||
}
|
||||
|
||||
func NewErcToNativeMessageInfo(req *entity.ErcToNativeMessage) *ErcToNativeMessageInfo {
|
||||
return &ErcToNativeMessageInfo{
|
||||
BridgeID: req.BridgeID,
|
||||
MsgHash: req.MsgHash,
|
||||
Direction: req.Direction,
|
||||
Sender: req.Sender,
|
||||
Receiver: req.Receiver,
|
||||
Value: req.Value,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
package presenter
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/poanetwork/tokenbridge-monitor/entity"
|
||||
)
|
||||
|
||||
var formats = map[string]string{
|
||||
"1": "https://etherscan.io/tx/%s",
|
||||
"4": "https://rinkeby.etherscan.io/tx/%s",
|
||||
"42": "https://kovan.etherscan.io/tx/%s",
|
||||
"56": "https://bscscan.com/tx/%s",
|
||||
"77": "https://blockscout.com/poa/sokol/tx/%s",
|
||||
"99": "https://blockscout.com/poa/core/tx/%s",
|
||||
"100": "https://blockscout.com/xdai/mainnet/tx/%s",
|
||||
}
|
||||
|
||||
func FormatLogTxLinkURL(log *entity.Log) string {
|
||||
if format, ok := formats[log.ChainID]; ok {
|
||||
return fmt.Sprintf(format, log.TransactionHash)
|
||||
}
|
||||
return log.TransactionHash.String()
|
||||
}
|
||||
|
||||
func NewMessageInfo(msg *entity.Message) *MessageInfo {
|
||||
return &MessageInfo{
|
||||
BridgeID: msg.BridgeID,
|
||||
MsgHash: msg.MsgHash,
|
||||
MessageID: msg.MessageID,
|
||||
Direction: msg.Direction,
|
||||
Sender: msg.Sender,
|
||||
Executor: msg.Executor,
|
||||
DataType: msg.DataType,
|
||||
}
|
||||
}
|
||||
|
||||
func NewInformationRequestInfo(req *entity.InformationRequest) *InformationRequestInfo {
|
||||
return &InformationRequestInfo{
|
||||
BridgeID: req.BridgeID,
|
||||
MessageID: req.MessageID,
|
||||
Direction: req.Direction,
|
||||
Sender: req.Sender,
|
||||
Executor: req.Executor,
|
||||
}
|
||||
}
|
||||
|
||||
func NewErcToNativeMessageInfo(req *entity.ErcToNativeMessage) *ErcToNativeMessageInfo {
|
||||
return &ErcToNativeMessageInfo{
|
||||
BridgeID: req.BridgeID,
|
||||
MsgHash: req.MsgHash,
|
||||
Direction: req.Direction,
|
||||
Sender: req.Sender,
|
||||
Receiver: req.Receiver,
|
||||
Value: req.Value,
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue