Skip to content

Commit

Permalink
eta added for withdraw
Browse files Browse the repository at this point in the history
  • Loading branch information
shekhar2807 committed Mar 14, 2022
1 parent 8f1d8ab commit b27552c
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 79 deletions.
1 change: 0 additions & 1 deletion cmd/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ var osUtils OSInterface
type UtilsInterface interface {
GetConfigFilePath() (string, error)
GetEpoch(*ethclient.Client) (uint32, error)
GetUpdatedEpoch(*ethclient.Client) (uint32, error)
GetOptions() bind.CallOpts
CalculateBlockTime(*ethclient.Client) int64
GetTxnOpts(types.TransactionOptions) *bind.TransactOpts
Expand Down
21 changes: 0 additions & 21 deletions cmd/mocks/utils_interface.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 0 additions & 4 deletions cmd/struct-utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@ func (u Utils) GetEpoch(client *ethclient.Client) (uint32, error) {
return utilsInterface.GetEpoch(client)
}

func (u Utils) GetUpdatedEpoch(client *ethclient.Client) (uint32, error) {
return utilsInterface.GetEpoch(client)
}

func (u Utils) GetOptions() bind.CallOpts {
return utilsInterface.GetOptions()
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/unstake.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ func (*UtilsStruct) Unstake(config types.Configurations, client *ethclient.Clien
log.Error("Error in un-staking: ", err)
return core.NilHash, err
}
log.Info("Transaction hash: ", txn)
log.Info("Transaction hash: ", transactionUtils.Hash(txn))
return transactionUtils.Hash(txn), nil
}

Expand Down
81 changes: 63 additions & 18 deletions cmd/withdraw.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package cmd

import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"math"
"math/big"
"razor/core"
"razor/core/types"
"razor/logger"
"razor/pkg/bindings"
"razor/utils"
"strconv"
"time"

"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

var withdrawCmd = &cobra.Command{
Expand Down Expand Up @@ -99,21 +100,23 @@ func (*UtilsStruct) WithdrawFunds(client *ethclient.Client, account types.Accoun
return core.NilHash, nil
}

txnArgs.Parameters = []interface{}{stakerId}
txnOpts := razorUtils.GetTxnOpts(txnArgs)

for i := epoch; big.NewInt(int64(i)).Cmp(withdrawBefore) < 0; {
if big.NewInt(int64(epoch)).Cmp(lock.WithdrawAfter) >= 0 && big.NewInt(int64(epoch)).Cmp(withdrawBefore) <= 0 {
return cmdUtils.Withdraw(client, txnOpts, stakerId)
}
log.Debug("Waiting for lock period to get over....")
// Wait for 30 seconds if lock period isn't over
timeUtils.Sleep(30 * time.Second)
epoch, err = razorUtils.GetUpdatedEpoch(client)
waitFor := big.NewInt(0).Sub(lock.WithdrawAfter, big.NewInt(int64(epoch)))
if waitFor.Cmp(big.NewInt(0)) > 0 {
log.Info("Withdrawal period not reached. Cannot withdraw now, please wait for", waitFor, "epochs!")
timeRemaining := (time.Duration(int64(uint32(waitFor.Int64()))*core.EpochLength*razorUtils.CalculateBlockTime(client)) * time.Second) / (1000000000)
value, err := strconv.Atoi(big.NewInt(int64(timeRemaining)).String())
if err != nil {
log.Error("Error in fetching epoch")
return core.NilHash, err
}
log.Info("Time Remaining to withdraw : ", secondsToHuman(value))
return core.NilHash, nil
}

txnArgs.Parameters = []interface{}{stakerId}
txnOpts := razorUtils.GetTxnOpts(txnArgs)

if big.NewInt(int64(epoch)).Cmp(lock.WithdrawAfter) >= 0 && big.NewInt(int64(epoch)).Cmp(withdrawBefore) <= 0 {
return cmdUtils.Withdraw(client, txnOpts, stakerId)
}
return core.NilHash, nil
}
Expand All @@ -132,6 +135,48 @@ func (*UtilsStruct) Withdraw(client *ethclient.Client, txnOpts *bind.TransactOpt
return transactionUtils.Hash(txn), nil
}

func plural(count int, singular string) (result string) {
if (count == 1) || (count == 0) {
result = strconv.Itoa(count) + " " + singular + " "
} else {
result = strconv.Itoa(count) + " " + singular + "s "
}
return
}

func secondsToHuman(input int) (result string) {
years := math.Floor(float64(input) / 60 / 60 / 24 / 7 / 30 / 12)
seconds := input % (60 * 60 * 24 * 7 * 30 * 12)
months := math.Floor(float64(seconds) / 60 / 60 / 24 / 7 / 30)
seconds = input % (60 * 60 * 24 * 7 * 30)
weeks := math.Floor(float64(seconds) / 60 / 60 / 24 / 7)
seconds = input % (60 * 60 * 24 * 7)
days := math.Floor(float64(seconds) / 60 / 60 / 24)
seconds = input % (60 * 60 * 24)
hours := math.Floor(float64(seconds) / 60 / 60)
seconds = input % (60 * 60)
minutes := math.Floor(float64(seconds) / 60)
seconds = input % 60

if years > 0 {
result = plural(int(years), "year") + plural(int(months), "month") + plural(int(weeks), "week") + plural(int(days), "day") + plural(int(hours), "hour") + plural(int(minutes), "minute") + plural(int(seconds), "second")
} else if months > 0 {
result = plural(int(months), "month") + plural(int(weeks), "week") + plural(int(days), "day") + plural(int(hours), "hour") + plural(int(minutes), "minute") + plural(int(seconds), "second")
} else if weeks > 0 {
result = plural(int(weeks), "week") + plural(int(days), "day") + plural(int(hours), "hour") + plural(int(minutes), "minute") + plural(int(seconds), "second")
} else if days > 0 {
result = plural(int(days), "day") + plural(int(hours), "hour") + plural(int(minutes), "minute") + plural(int(seconds), "second")
} else if hours > 0 {
result = plural(int(hours), "hour") + plural(int(minutes), "minute") + plural(int(seconds), "second")
} else if minutes > 0 {
result = plural(int(minutes), "minute") + plural(int(seconds), "second")
} else {
result = plural(int(seconds), "second")
}

return
}

func init() {
rootCmd.AddCommand(withdrawCmd)

Expand Down
104 changes: 70 additions & 34 deletions cmd/withdraw_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ func TestWithdrawFunds(t *testing.T) {
var account types.Account
var configurations types.Configurations
var stakerId uint32
var blockTime int64

type args struct {
lock types.Locks
Expand All @@ -35,8 +36,6 @@ func TestWithdrawFunds(t *testing.T) {
txnOpts *bind.TransactOpts
epoch uint32
epochErr error
updatedEpoch uint32
updatedEpochErr error
withdrawHash common.Hash
withdrawErr error
}
Expand Down Expand Up @@ -150,25 +149,7 @@ func TestWithdrawFunds(t *testing.T) {
wantErr: nil,
},
{
name: "Test 7: When withdraw function is not being called",
args: args{
lock: types.Locks{
WithdrawAfter: big.NewInt(4),
},
lockErr: nil,
withdrawReleasePeriod: 1,
withdrawReleasePeriodErr: nil,
txnOpts: txnOpts,
epoch: 5,
epochErr: nil,
withdrawHash: common.BigToHash(big.NewInt(1)),
withdrawErr: nil,
},
want: core.NilHash,
wantErr: nil,
},
{
name: "Test 8: When there is a need to wait till withdrawAfter and withdraw function executes successfully",
name: "Test 7: When staker tries to withdraw when withdrawal period has not reached",
args: args{
lock: types.Locks{
WithdrawAfter: big.NewInt(4),
Expand All @@ -179,31 +160,28 @@ func TestWithdrawFunds(t *testing.T) {
txnOpts: txnOpts,
epoch: 3,
epochErr: nil,
updatedEpoch: 5,
withdrawHash: common.BigToHash(big.NewInt(1)),
withdrawErr: nil,
},
want: common.BigToHash(big.NewInt(1)),
want: core.NilHash,
wantErr: nil,
},
{
name: "Test 9: When there is a need to wait till withdrawAfter but there is an error in getting updated Epoch ",
name: "Test 8: When there is an error in executing withdraw function",
args: args{
lock: types.Locks{
WithdrawAfter: big.NewInt(4),
},
lockErr: nil,
withdrawReleasePeriod: 4,
withdrawReleasePeriod: 1,
withdrawReleasePeriodErr: nil,
txnOpts: txnOpts,
epoch: 3,
epoch: 5,
epochErr: nil,
updatedEpochErr: errors.New("updatedEpoch error"),
withdrawHash: common.BigToHash(big.NewInt(1)),
withdrawErr: nil,
withdrawErr: errors.New("withdraw error"),
},
want: core.NilHash,
wantErr: errors.New("updatedEpoch error"),
wantErr: errors.New("withdraw error"),
},
}
for _, tt := range tests {
Expand All @@ -212,21 +190,18 @@ func TestWithdrawFunds(t *testing.T) {
stakeManagerUtilsMock := new(mocks.StakeManagerInterface)
cmdUtilsMock := new(mocks.UtilsCmdInterface)
transactionUtilsMock := new(mocks.TransactionInterface)
timeMock := new(mocks.TimeInterface)

razorUtils = utilsMock
stakeManagerUtils = stakeManagerUtilsMock
cmdUtils = cmdUtilsMock
transactionUtils = transactionUtilsMock
timeUtils = timeMock

utilsMock.On("GetLock", mock.AnythingOfType("*ethclient.Client"), mock.AnythingOfType("string"), mock.AnythingOfType("uint32")).Return(tt.args.lock, tt.args.lockErr)
utilsMock.On("GetWithdrawReleasePeriod", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.withdrawReleasePeriod, tt.args.withdrawReleasePeriodErr)
utilsMock.On("GetTxnOpts", mock.AnythingOfType("types.TransactionOptions")).Return(txnOpts)
utilsMock.On("GetEpoch", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.epoch, tt.args.epochErr)
utilsMock.On("GetUpdatedEpoch", mock.AnythingOfType("*ethclient.Client")).Return(tt.args.updatedEpoch, tt.args.updatedEpochErr)
utilsMock.On("CalculateBlockTime", mock.AnythingOfType("*ethclient.Client")).Return(blockTime)
cmdUtilsMock.On("Withdraw", mock.Anything, mock.Anything, mock.Anything).Return(tt.args.withdrawHash, tt.args.withdrawErr)
timeMock.On("Sleep", mock.Anything).Return()

utils := &UtilsStruct{}
got, err := utils.WithdrawFunds(client, account, configurations, stakerId)
Expand Down Expand Up @@ -434,3 +409,64 @@ func TestExecuteWithdraw(t *testing.T) {
})
}
}

func TestSecondsToHuman(t *testing.T) {
type args struct {
input int
}
tests := []struct {
name string
args args
wantResult string
}{
{
name: "Test 1",
args: args{
input: 100,
},
wantResult: "1 minute 40 seconds ",
},
{
name: "Test 2",
args: args{
input: 10000000000,
},
wantResult: "45 years 11 months 4 weeks 2 days 17 hours 46 minutes 40 seconds ",
},
{
name: "Test 3",
args: args{
input: 100000000,
},
wantResult: "5 months 15 weeks 2 days 9 hours 46 minutes 40 seconds ",
},
{
name: "Test 4",
args: args{
input: 1000000,
},
wantResult: "1 week 4 days 13 hours 46 minutes 40 seconds ",
},
{
name: "Test 5",
args: args{
input: 100000,
},
wantResult: "1 day 3 hours 46 minutes 40 seconds ",
},
{
name: "Test 6",
args: args{
input: 10000,
},
wantResult: "2 hours 46 minutes 40 seconds ",
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if gotResult := secondsToHuman(tt.args.input); gotResult != tt.wantResult {
t.Errorf("secondsToHuman() = %v, want %v", gotResult, tt.wantResult)
}
})
}
}

0 comments on commit b27552c

Please sign in to comment.