-
-
Save apetresc/caaf222c31b02354dbc11a333cdb688e to your computer and use it in GitHub Desktop.
#!/bin/bash -e | |
# redelegate-cro.sh is a script that automatically claims all your delegation | |
# rewards (across any number of validators) in a single transaction (assuming a | |
# minimum reward threshold is met, to avoid spurious transactions). The rewards | |
# are then automatically redelegated to the provided validator address, leaving | |
# behind at least a 0.005 CRO buffer to ensure there is always enough for | |
# regular transaction fees. | |
# | |
# The idea is that it is safe to run this script on a fixed cron schedule and | |
# feel confident that you are minimizing fees and maximizing APY. | |
# | |
# TODO: Currently, the delegation only happens to a single validator (although | |
# rewards are claimed from all). In future, you will be able to specify | |
# multiple <validator-address>es to evenly split the stake across multiple. | |
# | |
# REQUIREMENTS: | |
# - chain-maind | |
# - jq | |
# | |
# Updates will be posted to the gist at: | |
# https://gist.github.com/apetresc/caaf222c31b02354dbc11a333cdb688e | |
if [[ "$1" == "-h" || "$1" == "" || "$2" == "" ]] | |
then | |
echo "Usage: $0 <wallet-address> <validator-address> [-y]" | |
exit | |
fi | |
# Arguments | |
WALLET=$1 | |
VALIDATOR=$2 | |
YES=$3 | |
# Global parameters | |
REWARDS_THRESHOLD=10 | |
RPC_NODE="https://mainnet.crypto.org:26657" | |
CHAIN_ID="crypto-org-chain-mainnet-1" | |
echo "Wallet is: $WALLET" | |
BALANCE=$(chain-maind --chain-id $CHAIN_ID query bank balances $WALLET --node $RPC_NODE --output json | jq -r '.balances[] | select(.denom == "basecro") .amount') | |
echo "Balance is: $BALANCE" | |
REWARDS=$(chain-maind --chain-id $CHAIN_ID query distribution rewards $WALLET --node $RPC_NODE --output json) | |
REWARDS_AMOUNT=$(echo $REWARDS | jq -r '.total[] | select(.denom == "basecro") .amount|tonumber/100000000') | |
echo "There are $REWARDS_AMOUNT CRO rewards across $(echo $REWARDS | jq -r '.rewards | length') validators to be claimed." | |
if awk 'BEGIN {exit !('$REWARDS_AMOUNT' >= '$REWARDS_THRESHOLD')}' | |
then | |
echo "Claiming rewards..." | |
chain-maind --chain-id $CHAIN_ID tx distribution withdraw-all-rewards \ | |
--from $WALLET \ | |
--gas=auto --gas-prices=0.1basecro --gas-adjustment=1.2 \ | |
--node $RPC_NODE $YES | |
NEW_BALANCE=$(chain-maind --chain-id $CHAIN_ID query bank balances $WALLET --node $RPC_NODE --output json | jq -r '.balances[] | select(.denom == "basecro") .amount') | |
while awk 'BEGIN {exit !('$NEW_BALANCE' <= '$BALANCE')}' | |
do | |
echo "Waiting for rewards to appear..." | |
NEW_BALANCE=$(chain-maind --chain-id $CHAIN_ID query bank balances $WALLET --node $RPC_NODE --output json | jq -r '.balances[] | select(.denom == "basecro") .amount') | |
done | |
BALANCE=$NEW_BALANCE | |
echo "New balance is: $BALANCE" | |
STAKING_AMOUNT=$(expr $BALANCE - 500000) | |
echo "Amount to stake: $STAKING_AMOUNT" | |
chain-maind --chain-id $CHAIN_ID tx staking delegate \ | |
$VALIDATOR \ | |
"${STAKING_AMOUNT}basecro" \ | |
--from $WALLET \ | |
--gas=auto --gas-prices=0.1basecro --gas-adjustment=1.2 \ | |
--node $RPC_NODE $YES | |
echo "Done!" | |
else | |
echo "Need at least $REWARDS_THRESHOLD CRO to claim, skipping claim..." | |
fi | |
@Nayruden Good idea; done!
Thank you for the script!
Unfortunately I run into an issue during staking the claimed rewards. Chain-maind asks me a second time for the keyring passphrase but fails with an error that decoding bech32 failed due to string not all lowercase or all uppercase. I'm not really sure why that happens because the first time entering the passphrase for claiming the rewards is no problem at all.
That's why I changed the script a bit. If there are no rewards to be claimed the script checks if there is a balance greater than the rewards threshold. So this can not only be used to redelegate but also to delegate.
Perhaps other users are also interested in the change. Best regards.
Greate script, thank you!!
Trying to run as a schedule but it keeps asking me for the passphrase. Is there a way to pass the passphrase to chain-maind or not to have to type it ever?
Can't run this on a schedule if passphrase needs to be typed in all the time.
@jlavos Yup, you can use a keyring backend that doesn't require a passphrase, as long as you understand the security implications. That's done on chain-maind directly, here's how: https://crypto.org/docs/wallets/cli.html#the-keyring-keyring-backend-option
Thanks @aptresc. The only option I see that does not require as passphrase is using the "test backend" method. Is that it?
got it working, ;), thanks.
Thank you for sharing this!
I get this error "Error: error unmarshalling: invalid character '<' looking for beginning of value" however the balance in the wallet I am testing with is below 10 CRO.
I get that on some calls (e.g. 1st time I run the script it fails, if I run it right after it works), haven't figured out why yet.
@jcdmacleod Yeah, that's a normal error that just means the public RPC node we're using (one of Crypto.com's) rejected our query for whatever reason, presumably due to congestion. As @jlavos points out, retrying immediately afterwards will usually solve it.
I suppose I should just add a little retry logic directly in the script, thanks for the idea 👍
Did the RPC_NODE change? I keep getting an error:
"Error: post failed: Post "https://mainnet.crypto.org:26657": dial tcp: lookup mainnet.crypto.org: no such host"
Thanks for the script! I suggest you put a URL in there linking to the Reddit post for this or to the gist itself. That way six months from now someone can remember where they got this from to check for updates.