Created
April 9, 2021 20:28
-
-
Save Erumite/98471f62e97d1f76981b01f2985ede25 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/bash | |
# -------- Config -------- | |
# WALLET_NAME should be the name of the wallet (chain-maind keys list) | |
WALLET_NAME="Default" | |
# If WALLET_ADDRESS is blank, it will try to pull your address. (chain-maind keys show ${WALLET_NAME} --address) | |
# This is my address, so replace it with your own. Feel free to send me a murder of CROs. | |
# NOTE: All transactions with my address will fail since you don't have my keys, of course. | |
WALLET_ADDRESS="cro1ghlngrfrvjjf7r2h6ffpwaqcs630qxm509p2el" | |
# VALIDATOR_IGNORE_REGEX is a Regular Expression that will ignore specific validators for re-delegating but | |
# will still withdraw rewards. This is useful if you accidentally staked to a high percentage validator and don't | |
# care to unstake/redelegate the CRO being held by them. These addresses will be listed in RED on the summary page. | |
VALIDATOR_IGNORE_REGEX="(crocncl1ewgpxu7ec2kdeu9cyze0xaufnwkkqkpwq7rmst|crocncl1h6350mf68lg52ll44t7whcnffhf3qcycxrqfu7)" | |
# GAS can be left at auto to detect required gas when performing mult-withdraw or staking operations. | |
# GAS_LIMIT is used when combining withdrawal + staking since it can't be auto-detected. Excess gas fees are returned. | |
GAS="auto" | |
GAS_LIMIT=350000 | |
# FEE_CLAIM and FEE_DELEGATE are fees to offer to the network when claiming rewards or delegating respectively. | |
# Values are in basecro (CRO/100000000) | |
# If the fee is insufficient, it asks to continue with the value suggested in the network response. | |
# I typically see below 6000 basecro fees per multi-withdraw and <4000 for delegation. | |
# This is considerably cheaper than 10000-20000basecro per withdrawal and delegation. | |
# If using combined withdraw+restake, these can't be 0 since it can't auto-detect. | |
FEE_CLAIM=5800 | |
FEE_DELEGATE=3900 | |
# Combine the above for a rough idea of the combined fees. This can be set manually as well. | |
FEE_COMBINED=$((${FEE_CLAIM} + ${FEE_DELEGATE})) | |
# If YES is --yes it will skip chain-maind confirmations when collecting rewards and redelegating. | |
#YES="--yes" | |
YES="" | |
# Optional Config | |
CHAIN="--chain-id crypto-org-chain-mainnet-1" | |
NODE="" # Use local full node. | |
NODE="--node https://mainnet.crypto.org:26657" # Use CDC's mainnet node (slower) | |
# -------- Shouldn't need editing below here. -------- | |
# Some colors because it helps me parse things visually. | |
RED=$(tput setaf 1) | |
GREEN=$(tput setaf 2) | |
YELLOW=$(tput setaf 3) | |
LIME_YELLOW=$(tput setaf 190) | |
POWDER_BLUE=$(tput setaf 153) | |
BLUE=$(tput setaf 4) | |
MAGENTA=$(tput setaf 5) | |
CYAN=$(tput setaf 6) | |
WHITE=$(tput setaf 7) | |
BOLD=$(tput bold) | |
NORMAL=$(tput sgr0) | |
UNDERLINE=$(tput smul) | |
# If the wallet address isn't configured, set it based on Wallet Name | |
[[ -z $WALLET_ADDRESS ]] && WALLET_ADDRESS=$($(which chain-maind) keys show ${WALLET_NAME} --address) | |
# Convert basecro to cro. Accepts raw numbers as well as "###basecro" "###,basecro" and "### basecro" | |
function basecro_to_cro() { | |
basecro=${*//\"/} | |
basecro=${basecro%% *} | |
basecro=${basecro%%,*} | |
echo ${basecro%basecro} | awk '{printf "%8f", $1/100000000}' | |
} | |
# Read current balance (Unstaked) | |
json=$(chain-maind ${CHAIN} ${NODE} query bank balances ${WALLET_ADDRESS} --output=json) | |
WALLET_BALANCE=$(echo "${json}"|jq -r ".balances[]|[.amount,.denom]|@tsv") | |
# Find Delegations to individual validators and do some math to get a total. | |
json=$(chain-maind ${CHAIN} ${NODE} query staking delegations ${WALLET_ADDRESS} --output json) | |
DELEGATIONS=$(echo "${json}" | \ | |
jq -r '.delegation_responses[]|[.delegation.validator_address,.delegation.shares,.balance.amount,.balance.denom]|@csv') | |
DELEGATIONS=${DELEGATIONS//\"/} | |
DELEGATION_TOTAL=$(echo "${DELEGATIONS}" | awk -F, '{t+=$2};END{printf "%d",t}') | |
# Get available rewards from each of the delegators and count up the total. | |
# Also generate a new total by combining withdrawable rewards with current balance. | |
# This is used to generate NEW_STAKE, which is what will be re-staked to the network. | |
unset rewards; declare -A rewards | |
unset REWARD_TOTAL; REWARD_TOTAL=0 | |
for d in ${DELEGATIONS}; do | |
v=${d%%,*} | |
r="$(chain-maind ${CHAIN} ${NODE} query distribution rewards ${WALLET_ADDRESS} ${v} --output=json |jq -r '.rewards[]|[.amount,.denom]|@tsv')" | |
rewards[${v}]=$r | |
done | |
REWARD_TOTAL=$(echo "${rewards[@]}" | awk '{ for (i=1; i<=NF; i++) t+=$i};END{printf "%d", t}') | |
NEW_TOTAL=$((${REWARD_TOTAL} + ${WALLET_BALANCE//basecro})) | |
NEW_STAKE=$(((${REWARD_TOTAL} + ${WALLET_BALANCE//basecro}) - 1000000)) | |
# Print off some information about the current wallet. | |
echo -e "\n${BOLD}${UNDERLINE}${YELLOW}${WALLET_NAME}${NORMAL} (${UNDERLINE}${WALLET_ADDRESS}${NORMAL})"; \ | |
echo -en "${GREEN}Bal: $(basecro_to_cro ${WALLET_BALANCE}) CRO${NORMAL}\t" ;\ | |
echo -en "${LIME_YELLOW}Stk: ${BOLD}$(basecro_to_cro ${DELEGATION_TOTAL}) CRO${NORMAL}\t" ;\ | |
echo -e "${CYAN}Rew: ${BOLD}$(basecro_to_cro ${REWARD_TOTAL})${NORMAL}\n" | |
# Find the smallest non-ignored validator which we'll delegate to later. | |
DELEGATION_TARGET=$(echo "${DELEGATIONS}"|sed -r "/${VALIDATOR_IGNORE_REGEX}/d"|sort -t, -k3n|head -n1|cut -d, -f1) | |
# Print off individual delegators, amount staked, and available rewards. | |
{ echo "${BOLD}${CYAN}Validator${NORMAL}@Staked Amount@${BOLD}Rewards${NORMAL}" | |
for d in ${DELEGATIONS} ; do | |
validator=${d%%,*} | |
[[ ${validator} =~ ${VALIDATOR_IGNORE_REGEX} ]] && validator="${BOLD}${RED}${validator}${NORMAL}" || validator="${BOLD}${GREEN}${validator}${NORMAL}" | |
staked=$(basecro_to_cro $(echo "${d}" | awk -F, '{printf "%d",$2}')) | |
reward="${BOLD}$(basecro_to_cro ${rewards[${d%%,*}]})${NORMAL}" | |
[[ ${d%%,*} == ${DELEGATION_TARGET} ]] && reward="${reward} ${BOLD}${POWDER_BLUE}<+> Delegation Target${NORMAL}" | |
echo ${validator}@${staked}@${reward} | |
done | sort -k2n -t@ ; } |column -t -s@ | |
# -------- Claim & Restake 1-TX -------- | |
# Print out some helpful info about what we'll be doing. | |
echo -e "\n\n${BOLD}${UNDERLINE}${CYAN}Claim all transactions and restake immediately?${NORMAL}" | |
echo -e "${BOLD}New Total: $(basecro_to_cro ${NEW_TOTAL})" | |
echo -e "${BOLD}New Stake: $(basecro_to_cro ${NEW_STAKE})" | |
echo -e "${BOLD}Stake To : ${DELEGATION_TARGET}\n" | |
# Set up some variables and confirm. Will continue to separeate withdraw/stake prompts if declined. | |
done=0 fee=$((${FEE_CLAIM}+${FEE_DELEGATE})) gas=${GAS_LIMIT} | |
read -p "Continue to withdraw and redelegate? [Y/n]: " | |
[[ ! $REPLY =~ ^[Yy] ]] && done=1 | |
# This is hacky since there's no real supported method of combining these that I know of. | |
# Essentially generate the message for staking based on the NEW_STAKE value and extract the relevant message. | |
# Then, generate a message for withdrawing all rewards, then append the message from the redelegation. | |
# Also, manually set the fee/gas limits in the json and save the transaction to a file. | |
# Finally, sign the transaction (password prompt) and broadcast the transaction to the network. | |
while [[ ${done} == 0 ]] ; do | |
json=$(chain-maind ${CHAIN} ${NODE} ${YES} tx staking delegate ${DELEGATION_TARGET} ${NEW_STAKE}basecro --from ${WALLET_ADDRESS} --generate-only) | |
delegation=$(echo "${json}" | jq '.body.messages[0]') | |
json=$(chain-maind ${CHAIN} ${NODE} ${YES} tx distribution withdraw-all-rewards --from ${WALLET_ADDRESS} --generate-only) | |
append_slot=$(echo "${json}"| jq ".body.messages|length") | |
tx=$(echo "${json}" | jq ".body.messages[${append_slot}]|=${delegation}|.auth_info.fee.amount[0]|={\"denom\":\"basecro\",\"amount\":\"${fee}\"}|.auth_info.fee.gas_limit|=${gas}") | |
tmpfile='/tmp/cro_restake.tx' | |
echo "${tx}" > ${tmpfile} | |
tx=$(chain-maind ${CHAIN} ${NODE} tx sign ${tmpfile} --from ${WALLET_ADDRESS}) | |
echo "${tx}" > ${tmpfile}.signed | |
chain-maind ${CHAIN} ${NODE} tx broadcast ${tmpfile}.signed | |
rm ${tmpfile} ${tmpfile}.signed | |
echo -e "${BOLD}${GREEN}Done broadcasting transaction. If you have a failure message, increase gas limit or fees.${NORMAL}" | |
exit 1 | |
done | |
# (If the combined withdraw/restake action wasn't taken, then offer to do them individually) | |
# ------- Withdraw all delegations -------- | |
# Withdraw all delegations in one transaction. | |
# If fee is empty, it will keep retrying with the value suggested in the response. | |
# This can take several attempts, so I tend to just set the fee to something slightly | |
# above the usual value I land on when doing the manual method. | |
# Gas can generally be left as auto in the config and it will auto-detect required. | |
echo | |
done=0 fee=${FEE_CLAIM} gas=${GAS} | |
read -p "Withdraw all delegations now? [Y/n]: " | |
[[ ! $REPLY =~ ^[Yy] ]] && done=1 | |
while [[ ${done} == 0 ]] ; do | |
response=$(chain-maind ${CHAIN} ${NODE} ${YES} tx distribution withdraw-all-rewards --from ${WALLET_ADDRESS} --gas ${gas} --fees ${fee}basecro) | |
if [[ ${response} =~ "insufficient fees" ]] ; then | |
fee=$(echo "${response}" | jq -r '.raw_log' | grep -oP "(?<=required: )[0-9]*(?=basecro)") | |
read -p "[Failed] : Retry with ${fee} fee? : " | |
[[ $REPLY =~ ^[Yy] ]] && done=0 || done=1 | |
echo | |
else | |
done=1 | |
fi | |
done | |
# ---- Redelegate balance of Wallet, keeping .01 CRO for later ---- | |
# Print off some info about the new balance and stake to be delegated. | |
json=$(chain-maind ${CHAIN} ${NODE} query bank balances ${WALLET_ADDRESS} --output=json) | |
WALLET_BALANCE=$(echo "${json}"|jq -r ".balances[]|[.amount,.denom]|@tsv") | |
NEW_STAKE=$((${WALLET_BALANCE//basecro/} - 1000000)) | |
echo -e "\n${BOLD}${UNDERLINE}${YELLOW}${WALLET_NAME}${NORMAL} [${UNDERLINE}${WALLET_ADDRESS}${NORMAL}]"; \ | |
echo -en "${GREEN}Bal: ${BOLD}$(basecro_to_cro ${WALLET_BALANCE}) CRO${NORMAL}\t" ;\ | |
echo -en "${LIME_YELLOW}Stk: ${BOLD}$(basecro_to_cro ${DELEGATION_TOTAL}) CRO${NORMAL}\t" ; \ | |
echo -e "${RED}NewStk: ${BOLD}$(basecro_to_cro ${NEW_STAKE}) CRO${NORMAL}\n" | |
# Confirm if we want to continue or not. | |
read -p "Redelegate ${BOLD}$(basecro_to_cro ${NEW_STAKE})${NORMAL} to ${UNDERLINE}${DELEGATION_TARGET}${NORMAL}? [Y/n]: " | |
[[ ! $REPLY =~ ^[Yy] ]] && exit 0 | |
# Pretty much the same as the claim function, though fees tend to be lower. | |
done=0 fee=${FEE_DELEGATE} gas=${GAS} | |
while [[ ${done} == 0 ]] ; do | |
response=$(chain-maind ${CHAIN} ${NODE} ${YES} tx staking delegate ${DELEGATION_TARGET} ${NEW_STAKE}basecro --from ${WALLET_ADDRESS} --gas ${gas} --fees ${fee}basecro) | |
if [[ ${response} =~ "insufficient fees" ]] ; then | |
fee=$(echo "${response}" | jq -r '.raw_log' | grep -oP "(?<=required: )[0-9]*(?=basecro)") | |
read -p "[Failed] : Retry with ${fee} fee? : " | |
[[ $REPLY =~ ^[Yy] ]] && done=0 || done=1 | |
echo | |
else | |
done=1 | |
fi | |
done | |
exit 0 |
Yes, I also use WSL and the test backend was the only way I found for it to work.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It's possible with the
--keyring-backend
flag shown here: https://crypto.org/docs/wallets/cli.html#the-keyring-keyring-backend-optionI usually run this on the linux subsystem for windows and it asks for a password every time, though if I try on Mac, it seems to store my password in the keyring and doesn't require a password.
It's supposed to work the same on Linux, but I couldn't get
libsecret
to work. :/ The other option is to use--keyring-backend test
but I don't like the fact that it stores the keys in an unencrypted file, though if it's a risk you're willing to take, that's an option.