-
Notifications
You must be signed in to change notification settings - Fork 105
/
execute-proposal.go
153 lines (128 loc) · 4.03 KB
/
execute-proposal.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
144
145
146
147
148
149
150
151
152
153
package security
import (
"fmt"
"strconv"
"github.com/rocket-pool/rocketpool-go/dao"
rocketpoolapi "github.com/rocket-pool/rocketpool-go/rocketpool"
"github.com/rocket-pool/rocketpool-go/types"
"github.com/urfave/cli"
"github.com/rocket-pool/smartnode/shared/services/gas"
"github.com/rocket-pool/smartnode/shared/services/rocketpool"
cliutils "github.com/rocket-pool/smartnode/shared/utils/cli"
)
func executeProposal(c *cli.Context) error {
// Get RP client
rp, err := rocketpool.NewClientFromCtx(c).WithReady()
if err != nil {
return err
}
defer rp.Close()
// Check for Houston
houston, err := rp.IsHoustonDeployed()
if err != nil {
return fmt.Errorf("error checking if Houston has been deployed: %w", err)
}
if !houston.IsHoustonDeployed {
fmt.Println("This command cannot be used until Houston has been deployed.")
return nil
}
// Get security council proposals
proposals, err := rp.SecurityProposals()
if err != nil {
return err
}
// Get executable proposals
executableProposals := []dao.ProposalDetails{}
for _, proposal := range proposals.Proposals {
if proposal.State == types.Succeeded {
executableProposals = append(executableProposals, proposal)
}
}
// Check for executable proposals
if len(executableProposals) == 0 {
fmt.Println("No proposals can be executed.")
return nil
}
// Get selected proposal
var selectedProposals []dao.ProposalDetails
if c.String("proposal") == "all" {
// Select all proposals
selectedProposals = executableProposals
} else if c.String("proposal") != "" {
// Get selected proposal ID
selectedId, err := strconv.ParseUint(c.String("proposal"), 10, 64)
if err != nil {
return fmt.Errorf("Invalid proposal ID '%s': %w", c.String("proposal"), err)
}
// Get matching proposal
found := false
for _, proposal := range executableProposals {
if proposal.ID == selectedId {
selectedProposals = []dao.ProposalDetails{proposal}
found = true
break
}
}
if !found {
return fmt.Errorf("Proposal %d can not be executed.", selectedId)
}
} else {
// Prompt for proposal selection
options := make([]string, len(executableProposals)+1)
options[0] = "All available proposals"
for pi, proposal := range executableProposals {
options[pi+1] = fmt.Sprintf("proposal %d (message: '%s', payload: %s)", proposal.ID, proposal.Message, proposal.PayloadStr)
}
selected, _ := cliutils.Select("Please select a proposal to execute:", options)
// Get proposals
if selected == 0 {
selectedProposals = executableProposals
} else {
selectedProposals = []dao.ProposalDetails{executableProposals[selected-1]}
}
}
// Get the total gas limit estimate
var totalGas uint64 = 0
var totalSafeGas uint64 = 0
var gasInfo rocketpoolapi.GasInfo
for _, proposal := range selectedProposals {
canResponse, err := rp.SecurityCanExecuteProposal(proposal.ID)
if err != nil {
fmt.Printf("WARNING: Couldn't get gas price for execute transaction (%s)", err)
break
} else {
gasInfo = canResponse.GasInfo
totalGas += canResponse.GasInfo.EstGasLimit
totalSafeGas += canResponse.GasInfo.SafeGasLimit
}
}
gasInfo.EstGasLimit = totalGas
gasInfo.SafeGasLimit = totalSafeGas
// Assign max fees
err = gas.AssignMaxFeeAndLimit(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 execute %d proposals?", len(selectedProposals)))) {
fmt.Println("Cancelled.")
return nil
}
// Execute proposals
for _, proposal := range selectedProposals {
response, err := rp.SecurityExecuteProposal(proposal.ID)
if err != nil {
fmt.Printf("Could not execute proposal %d: %s.\n", proposal.ID, err)
continue
}
fmt.Printf("Executing proposal...\n")
cliutils.PrintTransactionHash(rp, response.TxHash)
if _, err = rp.WaitForTransaction(response.TxHash); err != nil {
fmt.Printf("Could not execute proposal %d: %s.\n", proposal.ID, err)
} else {
fmt.Printf("Successfully executed proposal %d.\n", proposal.ID)
}
}
// Return
return nil
}