Skip to content

Instantly share code, notes, and snippets.

@Erumite
Last active April 9, 2021 20:52
Show Gist options
  • Save Erumite/33d0685b72e767ee8c918ea6e3d2e36b to your computer and use it in GitHub Desktop.
Save Erumite/33d0685b72e767ee8c918ea6e3d2e36b to your computer and use it in GitHub Desktop.
restake_all_cro.sh
#! /bin/bash
# !!! Don't just run scripts you find from strangers on the internet !!!
# This is provided as-is for reference since running chain-maind commands
# is a lot of trial and error when getting started.
# This script will find all your CRO delegations and withdraw all rewards in a single transaction.
# It will then optionally restake to the pool with the lowest stake if it's not in an ignore list.
#
# It also seems to significantly reduce fees over using the desktop app:
# Claiming rewards:
# Manual : 0.0001000 CRO for each withdrawal : https://crypto.org/explorer/tx/B21EA9FD625A36B1B1E089009717A27E8EFEB32863DE1393455DF5033069C3AD
# Script : 0.0000552 CRO for 3 withdrawals : https://crypto.org/explorer/tx/719A867F5257BA6A3C0DEF6584E284F23101557070DC673647978BFC19FF6845
#
# Restaking:
# Manual : 0.00010000 CRO : https://crypto.org/explorer/tx/CDCB5EA57FFABF0123B01B9D40E879D34371DE5C05034331D13A1D3E3B5D3AEE
# Script : 0.00003809 CRO : https://crypto.org/explorer/tx/4700D178F78F9E3010EE945D95E492B250A427DECFA18CBBFEA282FD10299F49
# This sets the receiving address, but requires a password each time.
# Once you have the address, you can hard-code it instead to cut down on password entries.
# $(which) is in case people have it aliased to include --chain-id, since this errors out "keys show"
#address=$($(which chain-maind) keys show Eremite --address)
# Hard coding my address. Feel free to send a murder of CRO.
address='cro1ghlngrfrvjjf7r2h6ffpwaqcs630qxm509p2el'
# 1 CRO = 100000000 basecro
function basecro_to_cro(){
python -c "print('{}CRO'.format(${1}.0/100000000.0))"
}
# Optional regex to ignore some delegation pools for re-staking.
# Useful if you initially staked small amounts in high-fee pools, but don't want
# to unbond them for 28 days. This lets you collect the rewards from the smaller pools
# in one transaction and allocate those gains to a lower-fee pool:
export delegation_ignore_regex="(crocncl1ewgpxu7ec2kdeu9cyze0xaufnwkkqkpwq7rmst|crocncl1h6350mf68lg52ll44t7whcnffhf3qcycxrqfu7)"
delegations=$(chain-maind query staking delegations ${address} --output json |\
jq -r '."delegation_responses"[]|[.delegation.validator_address,.balance.amount]|@csv'|\
tr -d '"'|\
sed -r "/${delegation_ignore_regex}/d" )
unset delegation_ignore_regex
# This finds the pool with the lowest delegation for restaking to later.
# This eventually keeps delegations roughly balanced between your favorite pools.
# While mitigating the risk of a single pool going down or being jailed.
delegation_target=$(echo "${delegations}" | sort -t, -k2n | cut -d, -f1 | head -n 1)
# Just printing some stuff for debugging.
echo -e "${delegations}\n"
echo "Target: ${delegation_target}"
# I set fees to 0 basecro initially. If you get tired of entering the password many times as it
# tries to check output for suggested basefee, this could be edited with a higher value.
# Mine have pretty consistently been <6000basecro for withdrawing from 3 pools.
fees=0
done=0
# This will try to withdraw all, then re-try if the fee is too low. It will also auto-detect gas fees.
while [[ ${done} == 0 ]] ; do
response=$(chain-maind --chain-id crypto-org-chain-mainnet-1 tx distribution withdraw-all-rewards --from ${address} --gas auto --fees ${fees}basecro)
if [[ ${response} =~ "insufficient fees" ]] ; then
fees=$(echo "${response}" | jq -r '.raw_log' | grep -oP "(?<=required: )[0-9]*(?=basecro)")
read -p "[Failed] : Retry with ${fees} fee? : "
[[ $REPLY =~ ^[Yy] ]] && done=0 || done=1
echo
else
done=1
fi
done
# More debugging.
echo -e "${response}\n"
function get_stake_amount(){
bank_balance=$(chain-maind query bank balances ${address} --output json|jq -r '."balances"[]|[.amount,.denom]|@csv' | tr -d '"')
echo "Bank Balance: ${bank_balance//,} ($(basecro_to_cro ${bank_balance%,*}))"
# Keep .01 CRO for withdrawal fees later.
stake_amount=$((${bank_balance%,*}-1000000))${bank_balance#*,}
}
# Ask if we want to restake the balance to the current pool:
# N to exit without restaking
# Y to proceed
# R (or empty) reo refresh bank balance in case it doesn't update immediately.
get_stake_amount
until [[ ${proceed} =~ ^[Yy] ]]; do
read -p "Restake ${stake_amount} ($(basecro_to_cro ${stake_amount%basecro})) to lowest pool (${delegation_target})? [R/n/y]: " proceed
if [[ $REPLY =~ ^[nN] ]] ; then
exit
fi
get_stake_amount
done
# Same loop as above. Fees are usually <4000basecro for me.
fees=0
done=0
while [[ ${done} == 0 ]] ; do
response=$(chain-maind --chain-id crypto-org-chain-mainnet-1 tx staking delegate ${delegation_target} ${stake_amount} --from ${address} --gas auto --fees ${fees}basecro)
if [[ ${response} =~ "insufficient fees" ]] ; then
fees=$(echo "${response}" | jq -r '.raw_log' | grep -oP "(?<=required: )[0-9]*(?=basecro)")
read -p "[Failed] : Retry with ${fees} fee? : "
[[ $REPLY =~ ^[Yy] ]] && done=0 || done=1
echo
else
done=1
fi
done
@Erumite
Copy link
Author

Erumite commented Apr 9, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment