/
withdraw-rpl.go
143 lines (119 loc) · 3.94 KB
/
withdraw-rpl.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
package node
import (
"fmt"
"math/big"
"strconv"
"github.com/Seb369888/poolsea-go/utils/eth"
"github.com/urfave/cli"
"github.com/Seb369888/smartnode/shared/services/gas"
"github.com/Seb369888/smartnode/shared/services/rocketpool"
cliutils "github.com/Seb369888/smartnode/shared/utils/cli"
"github.com/Seb369888/smartnode/shared/utils/math"
)
func nodeWithdrawRpl(c *cli.Context) error {
// Get RP client
rp, err := rocketpool.NewClientFromCtx(c)
if err != nil {
return err
}
defer rp.Close()
// Check and assign the EC status
err = cliutils.CheckClientStatus(rp)
if err != nil {
return err
}
// Get withdrawal mount
var amountWei *big.Int
if c.String("amount") == "max" {
// Get node status
status, err := rp.NodeStatus()
if err != nil {
return err
}
// Set amount to maximum withdrawable amount
var maxAmount big.Int
if status.RplStake.Cmp(status.MinimumRplStake) > 0 {
maxAmount.Sub(status.RplStake, status.MinimumRplStake)
}
amountWei = &maxAmount
} else if c.String("amount") != "" {
// Parse amount
withdrawalAmount, err := strconv.ParseFloat(c.String("amount"), 64)
if err != nil {
return fmt.Errorf("Invalid withdrawal amount '%s': %w", c.String("amount"), err)
}
amountWei = eth.EthToWei(withdrawalAmount)
} else {
// Get node status
status, err := rp.NodeStatus()
if err != nil {
return err
}
// Get maximum withdrawable amount
var maxAmount big.Int
maxAmount.Sub(status.RplStake, status.MaximumRplStake)
if maxAmount.Sign() == 1 {
// Prompt for maximum amount
if cliutils.Confirm(fmt.Sprintf("Would you like to withdraw the maximum amount of staked RPL (%.6f RPL)?", math.RoundDown(eth.WeiToEth(&maxAmount), 6))) {
amountWei = &maxAmount
} else {
// Prompt for custom amount
inputAmount := cliutils.Prompt("Please enter an amount of staked RPL to withdraw:", "^\\d+(\\.\\d+)?$", "Invalid amount")
withdrawalAmount, err := strconv.ParseFloat(inputAmount, 64)
if err != nil {
return fmt.Errorf("Invalid withdrawal amount '%s': %w", inputAmount, err)
}
amountWei = eth.EthToWei(withdrawalAmount)
}
} else {
fmt.Printf("Cannot withdraw staked RPL - you have %.6f RPL staked, but are not allowed to withdraw below %.6f RPL (150%% collateral).\n",
math.RoundDown(eth.WeiToEth(status.RplStake), 6),
math.RoundDown(eth.WeiToEth(status.MaximumRplStake), 6))
return nil
}
}
// Check RPL can be withdrawn
canWithdraw, err := rp.CanNodeWithdrawRpl(amountWei)
if err != nil {
return err
}
if !canWithdraw.CanWithdraw {
fmt.Println("Cannot withdraw staked RPL:")
if canWithdraw.InsufficientBalance {
fmt.Println("The node's staked RPL balance is insufficient.")
}
if canWithdraw.MinipoolsUndercollateralized {
fmt.Println("Remaining staked RPL is not enough to collateralize the node's minipools.")
}
if canWithdraw.WithdrawalDelayActive {
fmt.Println("The withdrawal delay period has not passed.")
}
if !canWithdraw.IsAtlasDeployed && !canWithdraw.InConsensus {
fmt.Println("The RPL price and total effective staked RPL of the network are still being voted on by the Oracle DAO.\nPlease try again in a few minutes.")
}
return nil
}
// Assign max fees
err = gas.AssignMaxFeeAndLimit(canWithdraw.GasInfo, rp, c.Bool("yes"))
if err != nil {
return err
}
// Prompt for confirmation
if !(c.Bool("yes") || cliutils.Confirm(fmt.Sprintf("Are you sure you want to withdraw %.6f staked RPL? This may decrease your node's RPL rewards.", math.RoundDown(eth.WeiToEth(amountWei), 6)))) {
fmt.Println("Cancelled.")
return nil
}
// Withdraw RPL
response, err := rp.NodeWithdrawRpl(amountWei)
if err != nil {
return err
}
fmt.Printf("Withdrawing RPL...\n")
cliutils.PrintTransactionHash(rp, response.TxHash)
if _, err = rp.WaitForTransaction(response.TxHash); err != nil {
return err
}
// Log & return
fmt.Printf("Successfully withdrew %.6f staked RPL.\n", math.RoundDown(eth.WeiToEth(amountWei), 6))
return nil
}