func MergeMessageConfig(base, conf *MessageConfig) (*MessageConfig, error) {
	merged := *base
	if conf != nil {
		err := mergo.Merge(&merged, conf, mergo.WithOverride)
		if err != nil {
			return nil, err
		}
	}
	return &merged, nil
}
MergeMessageConfig merges a given message config with the default message
config recursively. Any non zero value fields will override the default
config.
package nkn
import (
	"math/rand"
	"time"
	"github.com/imdario/mergo"
	ncp "github.com/nknorg/ncp-go"
)
func init() {
	rand.Seed(time.Now().UnixNano())
}
var DefaultSeedRPCServerAddr = []string{
	"http://seed.nkn.org:30003",
}
type ClientConfig struct {
	SeedRPCServerAddr       *StringArray    
	RPCTimeout              int32           
	RPCConcurrency          int32           
	MsgChanLen              int32           
	ConnectRetries          int32           
	MsgCacheExpiration      int32           
	MsgCacheCleanupInterval int32           
	WsHandshakeTimeout      int32           
	WsWriteTimeout          int32           
	MinReconnectInterval    int32           
	MaxReconnectInterval    int32           
	MessageConfig           *MessageConfig  
	SessionConfig           *ncp.Config     
}
var DefaultClientConfig = ClientConfig{
	SeedRPCServerAddr:       nil,
	RPCTimeout:              10000,
	RPCConcurrency:          1,
	MsgChanLen:              1024,
	ConnectRetries:          3,
	MsgCacheExpiration:      300000,
	MsgCacheCleanupInterval: 60000,
	WsHandshakeTimeout:      5000,
	WsWriteTimeout:          10000,
	MinReconnectInterval:    1000,
	MaxReconnectInterval:    64000,
	MessageConfig:           nil,
	SessionConfig:           nil,
}
func GetDefaultClientConfig() *ClientConfig {
	clientConf := DefaultClientConfig
	clientConf.SeedRPCServerAddr = NewStringArray(DefaultSeedRPCServerAddr...)
	clientConf.MessageConfig = GetDefaultMessageConfig()
	clientConf.SessionConfig = GetDefaultSessionConfig()
	return &clientConf
}
func (c *ClientConfig) RPCGetSeedRPCServerAddr() *StringArray {
	return c.SeedRPCServerAddr
}
func (c *ClientConfig) RPCGetRPCTimeout() int32 {
	return c.RPCTimeout
}
func (c *ClientConfig) RPCGetConcurrency() int32 {
	return c.RPCConcurrency
}
type MessageConfig struct {
	Unencrypted       bool    
	NoReply           bool    
	MaxHoldingSeconds int32   
	MessageID         []byte  
	TxPool bool   
	Offset int32  
	Limit  int32  
}
var DefaultMessageConfig = MessageConfig{
	Unencrypted:       false,
	NoReply:           false,
	MaxHoldingSeconds: 0,
	MessageID:         nil,
	TxPool:            false,
	Offset:            0,
	Limit:             1000,
}
func GetDefaultMessageConfig() *MessageConfig {
	messageConf := DefaultMessageConfig
	return &messageConf
}
var DefaultSessionConfig = ncp.Config{
	MTU: 1024,
}
func GetDefaultSessionConfig() *ncp.Config {
	sessionConf := DefaultSessionConfig
	return &sessionConf
}
type DialConfig struct {
	DialTimeout   int32        
	SessionConfig *ncp.Config  
}
var DefaultDialConfig = DialConfig{
	DialTimeout:   0,
	SessionConfig: nil,
}
func GetDefaultDialConfig(baseSessionConfig *ncp.Config) *DialConfig {
	dialConf := DefaultDialConfig
	sessionConfig := *baseSessionConfig
	dialConf.SessionConfig = &sessionConfig
	return &dialConf
}
type ScryptConfig struct {
	Salt []byte
	N    int
	R    int
	P    int
}
type WalletConfig struct {
	SeedRPCServerAddr *StringArray
	RPCTimeout        int32  
	RPCConcurrency    int32  
	Password          string
	IV                []byte
	MasterKey         []byte
	ScryptConfig      *ScryptConfig
}
var DefaultWalletConfig = WalletConfig{
	SeedRPCServerAddr: nil,
	RPCTimeout:        10000,
	RPCConcurrency:    1,
	IV:                nil,
	MasterKey:         nil,
	ScryptConfig:      nil,
}
func GetDefaultWalletConfig() *WalletConfig {
	walletConf := DefaultWalletConfig
	walletConf.SeedRPCServerAddr = NewStringArray(DefaultSeedRPCServerAddr...)
	walletConf.ScryptConfig = &ScryptConfig{}
	return &walletConf
}
func (c *WalletConfig) RPCGetSeedRPCServerAddr() *StringArray {
	return c.SeedRPCServerAddr
}
func (c *WalletConfig) RPCGetRPCTimeout() int32 {
	return c.RPCTimeout
}
func (c *WalletConfig) RPCGetConcurrency() int32 {
	return c.RPCConcurrency
}
type RPCConfig struct {
	SeedRPCServerAddr *StringArray
	RPCTimeout        int32  
	RPCConcurrency    int32  
}
var DefaultRPCConfig = RPCConfig{
	SeedRPCServerAddr: nil,
	RPCTimeout:        10000,
	RPCConcurrency:    1,
}
func GetDefaultRPCConfig() *RPCConfig {
	rpcConf := DefaultRPCConfig
	rpcConf.SeedRPCServerAddr = NewStringArray(DefaultSeedRPCServerAddr...)
	return &rpcConf
}
func (c *RPCConfig) RPCGetSeedRPCServerAddr() *StringArray {
	return c.SeedRPCServerAddr
}
func (c *RPCConfig) RPCGetRPCTimeout() int32 {
	return c.RPCTimeout
}
func (c *RPCConfig) RPCGetConcurrency() int32 {
	return c.RPCConcurrency
}
type TransactionConfig struct {
	Fee        string
	Nonce      int64  
	Attributes []byte
}
var DefaultTransactionConfig = TransactionConfig{
	Fee:        "0",
	Nonce:      0,
	Attributes: nil,
}
func GetDefaultTransactionConfig() *TransactionConfig {
	txnConf := DefaultTransactionConfig
	return &txnConf
}
func MergeClientConfig(conf *ClientConfig) (*ClientConfig, error) {
	merged := GetDefaultClientConfig()
	if conf != nil {
		err := mergo.Merge(merged, conf, mergo.WithOverride)
		if err != nil {
			return nil, err
		}
	}
	if merged.SeedRPCServerAddr.Len() == 0 {
		merged.SeedRPCServerAddr = NewStringArray(DefaultSeedRPCServerAddr...)
	}
	return merged, nil
}