forked from BlackBeard085/x1console
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmanagestake.sh
executable file
·517 lines (433 loc) · 19.2 KB
/
managestake.sh
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
#!/bin/bash
# Create allstakes.json if it doesn't exist
if [[ ! -f allstakes.json ]]; then
echo "[]" > allstakes.json
fi
# Function to load vote address from wallets.json
get_vote_address() {
local vote_address
vote_address=$(jq -r '.[] | select(.name == "Vote") | .address' wallets.json)
echo "$vote_address"
}
# Function to display current stake account information for all stake accounts
display_all_stake_info() {
echo -e "\n--- Current Stake Account Info for All Wallets ---"
# List all stake wallet files in ~/.config/solana/
stake_wallets=("$HOME/.config/solana/stake.json" "$HOME/.config/solana/stake1.json" "$HOME/.config/solana/stake2.json" "$HOME/.config/solana/stake3.json" "$HOME/.config/solana/stake4.json")
# Create an array to hold addresses of existing wallets for updating or deletion
existing_addresses=()
# Clear allstakes.json temporarily
echo "[]" > allstakes.json
for wallet in "${stake_wallets[@]}"; do
if [[ -f "$wallet" ]]; then
# Get the public key for the stake account
address=$(solana-keygen pubkey "$wallet")
stake_info=$(solana stake-account "$address" 2>/dev/null)
if [[ $? -eq 0 ]]; then
balance=$(echo "$stake_info" | grep 'Balance:' | awk '{print $2}')
active_stake=$(echo "$stake_info" | grep 'Active Stake:' | awk '{print $3}')
# Conditional statement to handle blank active stake
if [[ -z "$active_stake" ]]; then
unstaked_balance=$balance
active_stake="Stake Not Active"
else
# Calculate Unstaked Balance
unstaked_balance=$(echo "$balance - $active_stake" | bc)
fi
# Extract wallet name from file path and capitalize first letter
wallet_name=$(basename "$wallet" .json)
capitalized_name=$(echo "$wallet_name" | sed 's/^\(.\)/\U\1/')
echo "Wallet Name: $capitalized_name"
echo "Address: $address"
echo "Balance: $balance"
echo "Unstaked Balance: $unstaked_balance"
echo "Active Stake Balance: $active_stake"
echo -e "------------------------------------"
# Add the address to existing addresses
existing_addresses+=("$address")
# Update allstakes.json with the wallet name and address
jq --arg name "$capitalized_name" --arg address "$address" \
'. += [{"name": $name, "address": $address}] | unique_by(.address)' allstakes.json \
| jq 'sort_by(.name)' > tmp.$$.json && mv tmp.$$.json allstakes.json
else
# Suppress the actual error output
wallet_name=$(basename "$wallet" .json)
echo "$wallet_name - Account for repurposing."
fi
else
wallet_name=$(basename "$wallet" .json)
echo "$wallet_name - Account for repurposing."
fi
done
# Remove addresses not found in existing wallets from allstakes.json
jq --argjson existing_addresses "$(printf '%s\n' "${existing_addresses[@]}" | jq -R . | jq -s .)" \
'map(select(.address as $addr | $existing_addresses | index($addr)))' allstakes.json > tmp.$$.json && mv tmp.$$.json allstakes.json
echo -e "------------------------------------\n"
}
# Function to add a new stake account
add_new_stake_account() {
# Array of existing stake wallet filenames
stake_wallets=("stake.json" "stake1.json" "stake2.json" "stake3.json" "stake4.json")
# Count existing stake wallet files
wallet_count=0
for wallet in "${stake_wallets[@]}"; do
if [[ -f "$HOME/.config/solana/$wallet" ]]; then
wallet_count=$((wallet_count + 1))
fi
done
# Check if the maximum limit of 5 stake wallets has been reached
if (( wallet_count >= 5 )); then
echo "Maximum stake wallet count reached. Please merge existing stake accounts to repurpose stake accounts"
return
fi
# Check for the next available stake wallet name
base_name="stake"
new_name="$base_name"
count=0
# Search for the next available name if base name already exists
while [[ -e "$HOME/.config/solana/$new_name.json" ]]; do
((count++))
new_name="${base_name}${count}"
done
# Generate a new keypair and store it
secret_key_file="$HOME/.config/solana/$new_name.json"
solana-keygen new --no-bip39-passphrase --silent -o "$secret_key_file"
# Get the public key of the newly created wallet
new_address=$(solana-keygen pubkey "$secret_key_file")
# Capitalize the first letter of the new name
capitalized_name=$(echo "$new_name" | sed 's/^\(.\)/\U\1/')
# Add new wallet to allstakes.json
jq --arg name "$capitalized_name" --arg address "$new_address" \
'. += [{"name": $name, "address": $address}] | unique_by(.address)' allstakes.json \
| jq 'sort_by(.name)' > tmp.$$.json && mv tmp.$$.json allstakes.json
echo "New stake account created: $capitalized_name with address $new_address"
# Ask the user for the amount to stake
stake_amount=""
while true; do
read -rp "How much XN would you like to stake in $capitalized_name (2 - 1000000): " stake_amount
# Validate the input
if [[ "$stake_amount" =~ ^[0-9]+$ ]] && [ "$stake_amount" -ge 2 ] && [ "$stake_amount" -le 1000000 ]; then
break
else
echo "Invalid input. Please enter a number between 2 and 1,000,000."
fi
done
# Create the stake account with the specified amount
echo "Creating stake account with $stake_amount XN..."
if solana create-stake-account "$secret_key_file" "$stake_amount"; then
echo "Successfully created stake account in $capitalized_name with $stake_amount XN staked."
# Get the vote address and delegate the stake
vote_address=$(get_vote_address)
if [[ -n "$vote_address" ]]; then
echo "Delegating stake to vote account: $vote_address"
solana delegate-stake "$secret_key_file" "$vote_address"
if [[ $? -eq 0 ]]; then
echo "Successfully delegated stake to $vote_address."
else
echo "Failed to delegate stake."
fi
else
echo "No valid vote address found in wallets.json."
fi
else
echo "Failed to create stake account."
fi
}
# Function to merge stake accounts
merge_stake() {
echo -e "\n--- Merge Stake Accounts ---"
# Load allstakes.json into an array
stake_info=$(jq -c '.[]' allstakes.json)
mapfile -t stake_accounts < <(echo "$stake_info")
# Display the stake accounts in table format
echo -e "Select a stake account to merge to:\n"
for i in "${!stake_accounts[@]}"; do
name=$(echo "${stake_accounts[$i]}" | jq -r '.name')
address=$(echo "${stake_accounts[$i]}" | jq -r '.address')
echo "$((i + 1)). $name - $address"
done
# User selects the account to merge to
read -rp "Which stake account would you like to merge to (1-$((${#stake_accounts[@]}))): " merge_to_choice
merge_to_index=$((merge_to_choice - 1))
# Validate user input
if [[ ! $merge_to_choice =~ ^[1-5]$ ]]; then
echo "Invalid selection. Please select a number between 1 and 5."
return
fi
# Get the chosen merge_to account details
merge_to_account=$(echo "${stake_accounts[$merge_to_index]}")
merge_to_address=$(echo "$merge_to_account" | jq -r '.address')
merge_to_name=$(echo "$merge_to_account" | jq -r '.name')
echo -e "\nYou chose to merge to: $merge_to_name - $merge_to_address"
# Display stake accounts again excluding the merge_to choice
echo -e "\nSelect a stake account to merge from:\n"
for i in "${!stake_accounts[@]}"; do
if [[ $i -ne $merge_to_index ]]; then
name=$(echo "${stake_accounts[$i]}" | jq -r '.name')
address=$(echo "${stake_accounts[$i]}" | jq -r '.address')
echo "$((i + 1)). $name - $address"
fi
done
# User selects the account to merge from
read -rp "Which stake account would you like to merge from remaining options: " merging_choice
# read -rp "Which stake account would you like to merge from (1-$((${#stake_accounts[@]} - 1))): " merging_choice
merging_index=$((merging_choice - 1))
# Validate user input
if [[ ! $merging_choice =~ ^[1-5]$ ]] || [[ $merging_index -eq $merge_to_index ]]; then
echo "Invalid selection. You cannot select the same account to merge from."
return
fi
# Get the chosen merging account details
merging_account=$(echo "${stake_accounts[$merging_index]}")
merging_address=$(echo "$merging_account" | jq -r '.address')
merging_name=$(echo "$merging_account" | jq -r '.name')
echo -e "\nYou chose to merge from: $merging_name - $merging_address"
# Execute the merge command
echo "Running command: solana merge-stake $merge_to_address $merging_address"
# Run the merge command
if solana merge-stake "$merge_to_address" "$merging_address"; then
echo "Successfully merged $merging_name into $merge_to_name."
echo "The $merging_name can now be repurposed as a new stake account. Please run 'Repurpose Old Stake Account'."
else
echo "Failed to merge stakes."
fi
}
# Function to create a new stake account from accounts with no stake info
create_stake_account() {
echo -e "\n--- Available Accounts To Repurpose ---"
stake_wallets=("$HOME/.config/solana/stake.json" "$HOME/.config/solana/stake1.json" "$HOME/.config/solana/stake2.json" "$HOME/.config/solana/stake3.json" "$HOME/.config/solana/stake4.json")
available_accounts=()
for wallet in "${stake_wallets[@]}"; do
address=$(solana-keygen pubkey "$wallet")
stake_info=$(solana stake-account "$address" 2>/dev/null)
# Check if there's no stake information
if [[ $? -ne 0 ]]; then
wallet_name=$(basename "$wallet" .json)
capitalized_name=$(echo "$wallet_name" | sed 's/^\(.\)/\U\1/')
echo "$(( ${#available_accounts[@]} + 1 )). $capitalized_name - $address"
available_accounts+=("$wallet")
fi
done
# Ensure we have available accounts to create from
if [[ ${#available_accounts[@]} -eq 0 ]]; then
echo "No available accounts to repurpose."
return
fi
# User selects from available accounts by number
read -rp "Select an account number to repurpose: " chosen_account
# Validate user input
chosen_index=$((chosen_account - 1))
if [[ $chosen_index -lt 0 || $chosen_index -ge ${#available_accounts[@]} ]]; then
echo "Invalid account number. Please select from the displayed accounts."
return
fi
chosen_key_file="${available_accounts[$chosen_index]}"
# Ask for the amount to stake
stake_amount=""
while true; do
read -rp "How much XN would you like to stake in the new account (2 - 1000000): " stake_amount
# Validate the input
if [[ "$stake_amount" =~ ^[0-9]+$ ]] && [ "$stake_amount" -ge 2 ] && [ "$stake_amount" -le 1000000 ]; then
break
else
echo "Invalid input. Please enter a number between 2 and 1,000,000."
fi
done
# Create the stake account with the specified amount using the chosen available account
echo "Creating stake account with $stake_amount XN using $chosen_key_file..."
if solana create-stake-account "$chosen_key_file" "$stake_amount"; then
echo "Successfully created a new stake account using $chosen_key_file with $stake_amount XN staked."
# Get the vote address and delegate the stake
vote_address=$(get_vote_address)
if [[ -n "$vote_address" ]]; then
echo "Delegating stake to vote account: $vote_address"
solana delegate-stake "$chosen_key_file" "$vote_address"
if [[ $? -eq 0 ]]; then
echo "Successfully delegated stake to $vote_address."
else
echo "Failed to delegate stake."
fi
else
echo "No valid vote address found in wallets.json."
fi
else
echo "Failed to create a new stake account."
fi
}
# Function to activate stake for a chosen account
activate_stake() {
echo -e "\n--- Activate Stake for Stake Accounts ---"
# Load allstakes.json into an array
stake_info=$(jq -c '.[]' allstakes.json)
mapfile -t stake_accounts < <(echo "$stake_info")
# Filter for accounts with no active stake
active_stake_accounts=()
for account in "${stake_accounts[@]}"; do
address=$(echo "$account" | jq -r '.address')
stake_info=$(solana stake-account "$address" 2>/dev/null)
if [[ $? -eq 0 ]]; then
active_stake=$(echo "$stake_info" | grep 'Active Stake:' | awk '{print $3}')
if [[ -z "$active_stake" ]]; then
active_stake_accounts+=("$account")
fi
fi
done
# Display the stake accounts that can be activated
if [[ ${#active_stake_accounts[@]} -eq 0 ]]; then
echo "No available stake accounts to activate."
return
fi
echo -e "Select a stake account to activate:\n"
for i in "${!active_stake_accounts[@]}"; do
name=$(echo "${active_stake_accounts[$i]}" | jq -r '.name')
address=$(echo "${active_stake_accounts[$i]}" | jq -r '.address')
echo "$((i + 1)). $name - $address"
done
# User selects the account to activate
read -rp "Which stake account would you like to activate (1-$((${#active_stake_accounts[@]}))): " activate_choice
activate_index=$((activate_choice - 1))
# Validate user input
if [[ ! $activate_choice =~ ^[1-$((${#active_stake_accounts[@]}))]$ ]]; then
echo "Invalid selection. Please select a valid stake account."
return
fi
# Get the chosen account details
chosen_account=$(echo "${active_stake_accounts[$activate_index]}")
chosen_address=$(echo "$chosen_account" | jq -r '.address')
# Get the vote address
vote_address=$(get_vote_address)
if [[ -z "$vote_address" ]]; then
echo "No valid vote address found in wallets.json."
return
fi
# Execute the delegate-stake command
echo "Running command: solana delegate-stake $chosen_address $vote_address"
if solana delegate-stake "$chosen_address" "$vote_address"; then
echo -e "\nSuccessfully activated stake for $chosen_address with vote account $vote_address."
# Run the stake-account command and filter the output
echo "Running command: solana stake-account $chosen_address"
stake_account_info=$(solana stake-account "$chosen_address")
# Print the relevant output
echo -e "\n--- Stake Account Information ---"
echo "$stake_account_info" | grep 'Stake activates starting from epoch:'
echo -e "------------------------------------\n"
else
echo "Failed to activate stake."
fi
}
# Function to deactivate stake for a chosen account
deactivate_stake() {
echo -e "\n--- Deactivate Stake for Stake Accounts ---"
# Load allstakes.json into an array
stake_info=$(jq -c '.[]' allstakes.json)
mapfile -t stake_accounts < <(echo "$stake_info")
# Filter for accounts with active stake
active_stake_accounts=()
for account in "${stake_accounts[@]}"; do
address=$(echo "$account" | jq -r '.address')
stake_info=$(solana stake-account "$address" 2>/dev/null)
if [[ $? -eq 0 ]]; then
active_stake=$(echo "$stake_info" | grep 'Active Stake:' | awk '{print $3}')
if [[ -n "$active_stake" ]]; then
active_stake_accounts+=("$account")
fi
fi
done
# Display the stake accounts that can be deactivated
if [[ ${#active_stake_accounts[@]} -eq 0 ]]; then
echo "No available stake accounts to deactivate."
return
fi
echo -e "Select a stake account to deactivate:\n"
for i in "${!active_stake_accounts[@]}"; do
name=$(echo "${active_stake_accounts[$i]}" | jq -r '.name')
address=$(echo "${active_stake_accounts[$i]}" | jq -r '.address')
echo "$((i + 1)). $name - $address"
done
# User selects the account to deactivate
read -rp "Which stake account would you like to deactivate (1-$((${#active_stake_accounts[@]}))): " deactivate_choice
deactivate_index=$((deactivate_choice - 1))
# Validate user input
if [[ ! $deactivate_choice =~ ^[1-$((${#active_stake_accounts[@]}))]$ ]]; then
echo "Invalid selection. Please select a valid stake account."
return
fi
# Get the chosen account details
chosen_account=$(echo "${active_stake_accounts[$deactivate_index]}")
chosen_address=$(echo "$chosen_account" | jq -r '.address')
# Execute the deactivate-stake command
echo "Running command: solana deactivate-stake $chosen_address"
if solana deactivate-stake "$chosen_address"; then
echo -e "\nSuccessfully deactivated stake for $chosen_address."
# Run the stake-account command and filter the output
echo "Running command: solana stake-account $chosen_address"
stake_account_info=$(solana stake-account "$chosen_address")
# Print the relevant output
echo -e "\n--- Stake Account Information ---"
echo "$stake_account_info" | grep 'Stake deactivates starting from epoch:'
echo -e "------------------------------------\n"
else
echo "Failed to deactivate stake."
fi
}
# Function to display the menu
show_menu() {
echo "Please select an option:"
echo "1. Activate Stake"
echo "2. Deactivate Stake"
echo "3. Epoch Info"
echo "4. Add New Stake Account"
echo "5. Merge Stake"
echo "6. Repurpose Old Stake Account"
echo "7. Exit"
}
# Function to pause and wait for user input
pause() {
read -rp "Press any button to continue... " -n1
echo -e "\n"
}
# Function to execute commands based on user input
execute_option() {
case $1 in
1)
activate_stake # Call the function for activating stake
pause
;;
2)
deactivate_stake # Call the function for deactivating stake
pause
;;
3)
echo -e "\nFetching epoch info...\n"
solana epoch-info
pause
;;
4)
add_new_stake_account # Call the function to add a new stake account
pause
;;
5)
merge_stake # Call the function to merge stake accounts
pause
;;
6)
create_stake_account # Call the function to create a new stake account from available accounts
pause
;;
7)
echo -e "\nExiting.\n"
exit 0
;;
*)
echo -e "\nInvalid option. Please try again.\n"
pause
;;
esac
}
# Main loop for the menu
while true; do
display_all_stake_info # Display all stake account info at each loop
show_menu
read -rp "Enter your choice [1-7]: " choice
execute_option "$choice"
done