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 }