BS / src / conf / network.go
network.go
Raw
package conf

import (
	"context"
	"sync"

	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/ethclient"

	"github.com/PiperFinance/BS/src/utils"
)

var (
	EthClientS           map[int64][]*ethclient.Client
	selectorMutex        sync.Mutex
	selectorIndex        map[int64]int
	clientCount          map[int64]int
	rpcs                 map[int64][]string
	MULTICALL_V3_ADDRESS = common.HexToAddress("0xca11bde05977b3631167028862be2a173976ca11")
)

func LoadNetwork() {
	selectorMutex = sync.Mutex{}
	rpcs = make(map[int64][]string, len(Config.SupportedChains))
	EthClientS = make(map[int64][]*ethclient.Client, len(Config.SupportedChains))
	clientCount = make(map[int64]int, len(Config.SupportedChains))
	selectorIndex = make(map[int64]int, len(Config.SupportedChains))
	for _, net := range SupportedNetworks {
		rpcs[net.ChainId] = utils.GetNetworkRpcUrls(net.GoodRpc)
		clientCount[net.ChainId] = len(net.GoodRpc)
		selectorIndex[net.ChainId] = 0
		EthClientS[net.ChainId] = make([]*ethclient.Client, len(net.GoodRpc))
		for i, _rpc := range net.GoodRpc {

			client, err := ethclient.Dial(_rpc.Url)
			if err != nil {
				Logger.Panicf("Client Connection %+v Error : %s  ", _rpc, err)
			}
			EthClientS[net.ChainId][i] = client
		}
	}
}

func EthClient(chain int64) *ethclient.Client {
	cl, _ := EthClientDebug(chain)
	return cl
}

func EthClientDebug(chain int64) (*ethclient.Client, string) {
	selectorMutex.Lock()
	defer func() {
		selectorIndex[chain]++
		if selectorIndex[chain] >= clientCount[chain] {
			selectorIndex[chain] = 0
		}
		selectorMutex.Unlock()
	}()
	// TODO:  Try to recover panic here !
	if clients, ok := EthClientS[chain]; ok {
		if index, ok := selectorIndex[chain]; ok {
			if len(clients) == 0 {
				Logger.Errorf("EthCLient Selector : No RPCs found for chain %d", chain)
			} else {
				return clients[index], rpcs[chain][index]
			}
		}
	}
	return nil, ""
}

// BatchLogMaxHeight statically returns block height set in Mainnets.json !
func BatchLogMaxHeight(chain int64) uint64 {
	// return 2
	r := SupportedNetworks[chain].BatchLogMaxHeight
	if r >= 2 {
		return uint64(r)
	}
	return 2
}

// BatchLogMaxHeight statically returns block height set in Mainnets.json !
func MulticallMaxSize(chain int64) uint64 {
	r := uint64(SupportedNetworks[chain].MulticallMaxSize)
	if r == 0 {
		// TODO: make this dynamic
		return 1
	} else {
		return r
	}
}

func MulticallAddress(chain int64) common.Address {
	return MULTICALL_V3_ADDRESS
}

// LatestBlock Last block mines head delay for safe data aggregation (uncle blocks!)
func LatestBlock(ctx context.Context, chain int64) (uint64, error) {
	CallCount.Add(chain)
	if b, err := EthClient(chain).BlockNumber(ctx); err != nil {
		return Config.StartingBlockNumber, err
	} else {
		return b - Config.BlockHeadDelay, nil
	}
}

func NetworkValueAddress(chain int64) common.Address {
	return common.HexToAddress("0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE")
}