- Adding self restart when repeated error occurs with backend rpc connection - renamed package name to reflect correctly
143 lines
4.6 KiB
Go
143 lines
4.6 KiB
Go
package eth
|
|
|
|
import (
|
|
"math/big"
|
|
"os"
|
|
"strings"
|
|
|
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
"github.com/golang/glog"
|
|
"github.com/juju/errors"
|
|
"github.com/ranchimall/blockbook/bchain"
|
|
)
|
|
|
|
func (b *EthereumRPC) initStakingPools(coinShortcut string) error {
|
|
// for now only single staking pool
|
|
envVar := strings.ToUpper(coinShortcut) + "_STAKING_POOL_CONTRACT"
|
|
envValue := os.Getenv(envVar)
|
|
if envValue != "" {
|
|
parts := strings.Split(envValue, "/")
|
|
if len(parts) != 2 {
|
|
glog.Errorf("Wrong format of environment variable %s=%s, expecting value '<pool name>/<pool contract>', staking pools not enabled", envVar, envValue)
|
|
return nil
|
|
}
|
|
b.supportedStakingPools = []string{envValue}
|
|
b.stakingPoolNames = []string{parts[0]}
|
|
b.stakingPoolContracts = []string{parts[1]}
|
|
glog.Info("Support of staking pools enabled with these pools: ", b.supportedStakingPools)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (b *EthereumRPC) EthereumTypeGetSupportedStakingPools() []string {
|
|
return b.supportedStakingPools
|
|
}
|
|
|
|
func (b *EthereumRPC) EthereumTypeGetStakingPoolsData(addrDesc bchain.AddressDescriptor) ([]bchain.StakingPoolData, error) {
|
|
// for now only single staking pool - Everstake
|
|
addr := hexutil.Encode(addrDesc)[2:]
|
|
if len(b.supportedStakingPools) == 1 {
|
|
data, err := b.everstakePoolData(addr, b.stakingPoolContracts[0], b.stakingPoolNames[0])
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if data != nil {
|
|
return []bchain.StakingPoolData{*data}, nil
|
|
}
|
|
}
|
|
return nil, nil
|
|
}
|
|
|
|
const everstakePendingBalanceOfMethodSignature = "0x59b8c763" // pendingBalanceOf(address)
|
|
const everstakePendingDepositedBalanceOfMethodSignature = "0x80f14ecc" // pendingDepositedBalanceOf(address)
|
|
const everstakeDepositedBalanceOfMethodSignature = "0x68b48254" // depositedBalanceOf(address)
|
|
const everstakeWithdrawRequestMethodSignature = "0x14cbc46a" // withdrawRequest(address)
|
|
const everstakeRestakedRewardOfMethodSignature = "0x0c98929a" // restakedRewardOf(address)
|
|
const everstakeAutocompoundBalanceOfMethodSignature = "0x2fec7966" // autocompoundBalanceOf(address)
|
|
|
|
func isZeroBigInt(b *big.Int) bool {
|
|
return len(b.Bits()) == 0
|
|
}
|
|
|
|
func (b *EthereumRPC) everstakeBalanceTypeContractCall(signature, addr, contract string) (string, error) {
|
|
req := signature + "0000000000000000000000000000000000000000000000000000000000000000"[len(addr):] + addr
|
|
return b.ethCall(req, contract)
|
|
}
|
|
|
|
func (b *EthereumRPC) everstakeContractCallSimpleNumeric(signature, addr, contract string) (*big.Int, error) {
|
|
data, err := b.everstakeBalanceTypeContractCall(signature, addr, contract)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
r := parseSimpleNumericProperty(data)
|
|
if r == nil {
|
|
return nil, errors.New("Invalid balance")
|
|
}
|
|
return r, nil
|
|
}
|
|
|
|
func (b *EthereumRPC) everstakePoolData(addr, contract, name string) (*bchain.StakingPoolData, error) {
|
|
poolData := bchain.StakingPoolData{
|
|
Contract: contract,
|
|
Name: name,
|
|
}
|
|
allZeros := true
|
|
|
|
value, err := b.everstakeContractCallSimpleNumeric(everstakePendingBalanceOfMethodSignature, addr, contract)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
poolData.PendingBalance = *value
|
|
allZeros = allZeros && isZeroBigInt(value)
|
|
|
|
value, err = b.everstakeContractCallSimpleNumeric(everstakePendingDepositedBalanceOfMethodSignature, addr, contract)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
poolData.PendingDepositedBalance = *value
|
|
allZeros = allZeros && isZeroBigInt(value)
|
|
|
|
value, err = b.everstakeContractCallSimpleNumeric(everstakeDepositedBalanceOfMethodSignature, addr, contract)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
poolData.DepositedBalance = *value
|
|
allZeros = allZeros && isZeroBigInt(value)
|
|
|
|
data, err := b.everstakeBalanceTypeContractCall(everstakeWithdrawRequestMethodSignature, addr, contract)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
value = parseSimpleNumericProperty(data)
|
|
if value == nil {
|
|
return nil, errors.New("Invalid balance")
|
|
}
|
|
poolData.WithdrawTotalAmount = *value
|
|
allZeros = allZeros && isZeroBigInt(value)
|
|
value = parseSimpleNumericProperty(data[64+2:])
|
|
if value == nil {
|
|
return nil, errors.New("Invalid balance")
|
|
}
|
|
poolData.ClaimableAmount = *value
|
|
allZeros = allZeros && isZeroBigInt(value)
|
|
|
|
value, err = b.everstakeContractCallSimpleNumeric(everstakeRestakedRewardOfMethodSignature, addr, contract)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
poolData.RestakedReward = *value
|
|
allZeros = allZeros && isZeroBigInt(value)
|
|
|
|
value, err = b.everstakeContractCallSimpleNumeric(everstakeAutocompoundBalanceOfMethodSignature, addr, contract)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
poolData.AutocompoundBalance = *value
|
|
allZeros = allZeros && isZeroBigInt(value)
|
|
|
|
if allZeros {
|
|
return nil, nil
|
|
}
|
|
return &poolData, nil
|
|
}
|