84 lines
3.0 KiB
Go
84 lines
3.0 KiB
Go
package polycat
|
|
|
|
import (
|
|
"context"
|
|
"math/big"
|
|
|
|
"git.lehouerou.net/laurent/evm"
|
|
"git.lehouerou.net/laurent/evm/polycat/contracts"
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
|
"github.com/ethereum/go-ethereum/common"
|
|
"github.com/ethereum/go-ethereum/core/types"
|
|
"github.com/pkg/errors"
|
|
"github.com/shopspring/decimal"
|
|
)
|
|
|
|
const RewardLockerAddress = "0xE0e44d4E7e61f2f4f990f5F4e2408D2187315C94"
|
|
|
|
type RewardLockerService struct {
|
|
client evm.Client
|
|
contract *contracts.RewardLocker
|
|
}
|
|
|
|
func NewRewardLockerService(c evm.Client) (*RewardLockerService, error) {
|
|
contract, err := contracts.NewRewardLocker(common.HexToAddress(RewardLockerAddress), c)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "init contract")
|
|
}
|
|
return &RewardLockerService{
|
|
contract: contract,
|
|
client: c,
|
|
}, nil
|
|
}
|
|
|
|
func (s *RewardLockerService) ClaimAll(ctx context.Context, token common.Address, opts ...evm.ExecutionOption) (evm.Transaction, error) {
|
|
schedcount, err := s.contract.NumVestingSchedules(&bind.CallOpts{}, s.client.PublicAddress(), token)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "getting schedule count")
|
|
}
|
|
return s.client.Execute(ctx, func(ctx context.Context, options *evm.TransactOpts) (*types.Transaction, error) {
|
|
return s.contract.VestSchedulesInRange(options.TransactOpts, token, big.NewInt(0), decimal.NewFromBigInt(schedcount, 0).Sub(decimal.NewFromInt(1)).BigInt())
|
|
}, opts...)
|
|
}
|
|
|
|
func (s *RewardLockerService) GetClaimableReward(ctx context.Context, token common.Address) (decimal.Decimal, error) {
|
|
scheds, err := s.contract.GetVestingSchedules(&bind.CallOpts{}, s.client.PublicAddress(), token)
|
|
if err != nil {
|
|
return decimal.Zero, errors.Wrap(err, "getting vesting schedules")
|
|
}
|
|
var tot decimal.Decimal
|
|
block, err := s.client.CurrentBlockNumber(ctx)
|
|
if err != nil {
|
|
return decimal.Zero, errors.Wrap(err, "getting current block")
|
|
}
|
|
for _, sched := range scheds {
|
|
tot = tot.Add(GetVestingQuantity(sched, block))
|
|
}
|
|
return tot, nil
|
|
}
|
|
|
|
func GetVestingQuantity(sched contracts.IRewardLockerVestingSchedule, block uint64) decimal.Decimal {
|
|
if block >= sched.EndBlock {
|
|
return decimal.NewFromBigInt(sched.Quantity, -18).Sub(decimal.NewFromBigInt(sched.VestedQuantity, -18))
|
|
}
|
|
if block <= sched.StartBlock {
|
|
return decimal.Zero
|
|
}
|
|
|
|
lockduration := sched.EndBlock - sched.StartBlock
|
|
passedDuration := block - sched.StartBlock
|
|
return decimal.NewFromBigInt(sched.Quantity, -18).Mul(decimal.NewFromInt(int64(passedDuration))).Div(decimal.NewFromInt(int64(lockduration))).Sub(decimal.NewFromBigInt(sched.VestedQuantity, -18))
|
|
}
|
|
|
|
func (s *RewardLockerService) GetLockedReward(token common.Address) (decimal.Decimal, error) {
|
|
scheds, err := s.contract.GetVestingSchedules(&bind.CallOpts{}, s.client.PublicAddress(), token)
|
|
if err != nil {
|
|
return decimal.Zero, errors.Wrap(err, "getting vesting schedules")
|
|
}
|
|
var tot decimal.Decimal
|
|
for _, sched := range scheds {
|
|
tot = tot.Add(decimal.NewFromBigInt(sched.Quantity, -18).Sub(decimal.NewFromBigInt(sched.VestedQuantity, -18)))
|
|
}
|
|
return tot, nil
|
|
}
|