Skip to content

Commit 9ff6ec3

Browse files
committed
Deduplicate/refactor node-deposit and create-vacant-minipool
1 parent b219e63 commit 9ff6ec3

File tree

3 files changed

+113
-150
lines changed

3 files changed

+113
-150
lines changed

rocketpool-cli/commands/node/create-vacant-minipool.go

Lines changed: 22 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
package node
22

33
import (
4-
"crypto/rand"
54
"fmt"
6-
"math/big"
7-
"strconv"
85

96
"github.com/ethereum/go-ethereum/common"
107
"github.com/rocket-pool/node-manager-core/beacon"
@@ -29,117 +26,20 @@ func createVacantMinipool(c *cli.Context, pubkey beacon.ValidatorPubkey) error {
2926
return err
3027
}
3128

32-
// Make sure Beacon is on the correct chain
33-
depositContractInfo, err := rp.Api.Network.GetDepositContractInfo(true)
29+
d, err := newDepositPrompts(c, rp, &pubkey)
3430
if err != nil {
3531
return err
3632
}
37-
if depositContractInfo.Data.PrintMismatch() {
33+
if d == nil {
3834
return nil
3935
}
4036

41-
// Check if the fee distributor has been initialized
42-
feeDistributorResponse, err := rp.Api.Node.InitializeFeeDistributor()
43-
if err != nil {
44-
return err
45-
}
46-
if !feeDistributorResponse.Data.IsInitialized {
47-
fmt.Println("Your fee distributor has not been initialized yet so you cannot create a new minipool.\nPlease run `rocketpool node initialize-fee-distributor` to initialize it first.")
48-
return nil
49-
}
50-
51-
// Post a warning about fee distribution
52-
if !(c.Bool("yes") || utils.Confirm(fmt.Sprintf("%sNOTE: by creating a new minipool, your node will automatically claim and distribute any balance you have in your fee distributor contract. If you don't want to claim your balance at this time, you should not create a new minipool.%s\nWould you like to continue?", terminal.ColorYellow, terminal.ColorReset))) {
53-
fmt.Println("Cancelled.")
54-
return nil
55-
}
56-
57-
// Print a notification about the pubkey
58-
fmt.Printf("You are about to convert the solo staker %s into a Rocket Pool minipool. This will convert your 32 ETH deposit into either an 8 ETH or 16 ETH deposit (your choice), and convert the remaining 24 or 16 ETH into a deposit from the Rocket Pool staking pool. The staking pool portion will be credited to your node's account, allowing you to create more validators without depositing additional ETH onto the Beacon Chain. Your excess balance (your existing Beacon rewards) will be preserved and not shared with the pool stakers.\n\nPlease thoroughly read our documentation at https://docs.rocketpool.net/guides/atlas/solo-staker-migration.html to learn about the process and its implications.\n\n1. First, we'll create the new minipool.\n2. Next, we'll ask whether you want to import the validator's private key into your Smartnode's Validator Client, or keep running your own externally-managed validator.\n3. Finally, we'll help you migrate your validator's withdrawal credentials to the minipool address.\n\n%sNOTE: If you intend to use the credit balance to create additional validators, you will need to have enough RPL staked to support them.%s\n\n", pubkey.Hex(), terminal.ColorYellow, terminal.ColorReset)
59-
60-
// Get deposit amount
61-
var amount float64
62-
if c.String(amountFlag) != "" {
63-
// Parse amount
64-
depositAmount, err := strconv.ParseFloat(c.String(amountFlag), 64)
65-
if err != nil {
66-
return fmt.Errorf("invalid deposit amount '%s': %w", c.String(amountFlag), err)
67-
}
68-
amount = depositAmount
69-
} else {
70-
// Get deposit amount options
71-
amountOptions := []string{
72-
"8 ETH",
73-
"16 ETH",
74-
}
75-
76-
// Prompt for amount
77-
selected, _ := utils.Select("Please choose an amount of ETH you want to use as your deposit for the new minipool (this will become your share of the balance, and the remainder will become the pool stakers' share):", amountOptions)
78-
switch selected {
79-
case 0:
80-
amount = 8
81-
case 1:
82-
amount = 16
83-
}
84-
}
85-
amountWei := eth.EthToWei(amount)
86-
87-
// Get network node fees
88-
nodeFeeResponse, err := rp.Api.Network.NodeFee()
89-
if err != nil {
90-
return err
91-
}
92-
93-
// Get minimum node fee
94-
var minNodeFee float64
95-
if c.String("max-slippage") == "auto" {
96-
// Use default max slippage
97-
minNodeFee = eth.WeiToEth(nodeFeeResponse.Data.NodeFee) - DefaultMaxNodeFeeSlippage
98-
if minNodeFee < eth.WeiToEth(nodeFeeResponse.Data.MinNodeFee) {
99-
minNodeFee = eth.WeiToEth(nodeFeeResponse.Data.MinNodeFee)
100-
}
101-
} else if c.String("max-slippage") != "" {
102-
// Parse max slippage
103-
maxNodeFeeSlippagePerc, err := strconv.ParseFloat(c.String("max-slippage"), 64)
104-
if err != nil {
105-
return fmt.Errorf("invalid maximum commission rate slippage '%s': %w", c.String("max-slippage"), err)
106-
}
107-
maxNodeFeeSlippage := maxNodeFeeSlippagePerc / 100
108-
109-
// Calculate min node fee
110-
minNodeFee = eth.WeiToEth(nodeFeeResponse.Data.NodeFee) - maxNodeFeeSlippage
111-
if minNodeFee < eth.WeiToEth(nodeFeeResponse.Data.MinNodeFee) {
112-
minNodeFee = eth.WeiToEth(nodeFeeResponse.Data.MinNodeFee)
113-
}
114-
} else {
115-
// Prompt for min node fee
116-
if nodeFeeResponse.Data.MinNodeFee == nodeFeeResponse.Data.MaxNodeFee {
117-
fmt.Printf("Your minipool will use the current fixed commission rate of %.2f%%.\n", eth.WeiToEth(nodeFeeResponse.Data.MinNodeFee)*100)
118-
minNodeFee = eth.WeiToEth(nodeFeeResponse.Data.MinNodeFee)
119-
} else {
120-
minNodeFee = promptMinNodeFee(eth.WeiToEth(nodeFeeResponse.Data.NodeFee), eth.WeiToEth(nodeFeeResponse.Data.MinNodeFee))
121-
}
122-
}
123-
124-
// Get minipool salt
125-
var salt *big.Int
126-
if c.String(saltFlag) != "" {
127-
var success bool
128-
salt, success = big.NewInt(0).SetString(c.String(saltFlag), 0)
129-
if !success {
130-
return fmt.Errorf("invalid minipool salt: %s", c.String(saltFlag))
131-
}
132-
} else {
133-
buffer := make([]byte, 32)
134-
_, err = rand.Read(buffer)
135-
if err != nil {
136-
return fmt.Errorf("error generating random salt: %w", err)
137-
}
138-
salt = big.NewInt(0).SetBytes(buffer)
139-
}
37+
minNodeFee := d.minNodeFee
38+
amountWei := d.amountWei
39+
amount := eth.WeiToEth(amountWei)
14040

14141
// Build the TX
142-
response, err := rp.Api.Node.CreateVacantMinipool(amountWei, minNodeFee, salt, pubkey)
42+
response, err := rp.Api.Node.CreateVacantMinipool(amountWei, minNodeFee, d.salt, pubkey)
14343
if err != nil {
14444
return err
14545
}
@@ -168,20 +68,25 @@ func createVacantMinipool(c *cli.Context, pubkey beacon.ValidatorPubkey) error {
16868
syncResponse, err := rp.Api.Service.ClientStatus()
16969
if err != nil {
17070
return fmt.Errorf("error checking if your clients are in sync: %w", err)
171-
} else {
172-
if syncResponse.Data.BcManagerStatus.PrimaryClientStatus.IsSynced {
173-
fmt.Printf("Your consensus client is synced, you may safely create a minipool.\n")
174-
} else if syncResponse.Data.BcManagerStatus.FallbackEnabled {
175-
if syncResponse.Data.BcManagerStatus.FallbackClientStatus.IsSynced {
176-
fmt.Printf("Your fallback consensus client is synced, you may safely create a minipool.\n")
177-
} else {
178-
fmt.Printf("%s**WARNING**: neither your primary nor fallback consensus clients are fully synced.\nYou cannot migrate until they've finished syncing.\n%s", terminal.ColorRed, terminal.ColorReset)
179-
return nil
180-
}
71+
}
72+
if syncResponse.Data.BcManagerStatus.PrimaryClientStatus.IsSynced {
73+
fmt.Println("Your consensus client is synced, you may safely create a minipool.")
74+
} else if syncResponse.Data.BcManagerStatus.FallbackEnabled {
75+
if syncResponse.Data.BcManagerStatus.FallbackClientStatus.IsSynced {
76+
fmt.Println("Your fallback consensus client is synced, you may safely create a minipool.")
18177
} else {
182-
fmt.Printf("%s**WARNING**: your primary consensus client is either not fully synced or offline and you do not have a fallback client configured.\nYou cannot migrate until you have a synced consensus client.\n%s", terminal.ColorRed, terminal.ColorReset)
78+
fmt.Print(terminal.ColorRed)
79+
fmt.Println("**WARNING**: neither your primary nor fallback consensus clients are fully synced.")
80+
fmt.Println("You cannot migrate until they've finished syncing.")
81+
fmt.Print(terminal.ColorReset)
18382
return nil
18483
}
84+
} else {
85+
fmt.Print(terminal.ColorRed)
86+
fmt.Println("**WARNING**: your primary consensus client is either not fully synced or offline and you do not have a fallback client configured.")
87+
fmt.Println("You cannot migrate until you have a synced consensus client.")
88+
fmt.Print(terminal.ColorReset)
89+
return nil
18590
}
18691

18792
// Run the TX

0 commit comments

Comments
 (0)