Tag Archives: Rewards

KAVA Autocompounder for Staking Crypto Rewards with Javascript NodeJS

kava.io bietet DeFI auf der BEP2 Chain an. KAVA Tokens können gestaked werden, aktuell gibt es um die 20% APR. Mit Wallets wie z.B. dem Trustwallet oder Ledger kann man KAVA staken. Möchte man jedoch vom Zinsenzinseffekt profitieren, so muss man derzeit manuell seine Staking-Rewards einsammeln und manuell wieder erneut delegieren.

Aber es handelt sich ja um eine Kryptowährung, welche sich bekanntlich programmieren lassen. Daher habe ich schnell mal das SDK gezogen, etwas gepatcht und folgenden Autocompounder gebaut:

autocompounder.js:
const Env = require("./env").env;
const kavaUtils = require("./src/utils").utils;

'use strict';

const KavaClient = require('./src/client').KavaClient;
const tx = require('./src/tx').tx;
const msg = require('./src/msg').msg;
const utils = require('./src/utils').utils;
const crypto = require('./src/crypto').crypto;

module.exports = {
  KavaClient,
  tx,
  msg,
  utils,
  crypto,
};



const KAVA_CONVERSION_FACTOR = 10 ** 6;
const COMPOUND_LIMIT = 0.2 ; // the amount of pending rewards at which we start autocompounding


var main = async () => {


    kavaClient = new KavaClient(Env.KavaEndpoints.Mainnet);
    kavaClient.setWallet(Env.KavaAccount.Mainnet.Mnemonic);
    kavaClient.setBroadcastMode("async");
    await kavaClient.initChain();


    unused_balance = 0;

    console.log("Account:", Env.KavaAccount.Mainnet.Address);
    let balances = await kavaClient.getBalances(Env.KavaAccount.Mainnet.Address);

    let kavaBalance = balances.find((item) => item.denom.toUpperCase() === "UKAVA");
    if(kavaBalance) {
        console.log("\tBalance (kava):", kavaBalance.amount / KAVA_CONVERSION_FACTOR);
        unused_balance = kavaBalance.amount / KAVA_CONVERSION_FACTOR ;
    }

    let kavaDelegations = await kavaClient.getDelegations(Env.KavaAccount.Mainnet.Address);
    let staked = 0 ; 
    let validators = [];
    let bal_before = 0; 
    for (let element of kavaDelegations) {
      let balance = element.balance; 
      validators.push(element.validator_address);
        staked = staked + (balance.amount / KAVA_CONVERSION_FACTOR);
        if (bal_before < staked ) {
          bal_before = staked; 
          next_val = element.validator_address; 
        }
        
    }
    console.log("\tStaked (kava):" , staked) ;
    console.log("\tnext validator: ", next_val); 

  
    if (unused_balance > COMPOUND_LIMIT) { 
      let new_stake_balance = unused_balance - 0.01 ; 
      console.log("new staking: ", new_stake_balance);
      denom_val = new_stake_balance.toFixed(5) * KAVA_CONVERSION_FACTOR;
        
        let txMsgs = [] ; 
                txMsgs.push ( {
        type: 'cosmos-sdk/MsgDelegate',
        value: {
            delegator_address: Env.KavaAccount.Mainnet.Address,
            validator_address: next_val,
            amount: {denom:'ukava', amount: denom_val.toString() }
        },
    });

	let txid = await kavaClient.sendTx(txMsgs, fee={amount: [{ denom: 'ukava', amount: "0" }], gas: String(300000)}, null);	
	console.log("stake kava, created TX ", txid) ;

    }



    let kavaRewards = await kavaClient.getDistributionRewards(Env.KavaAccount.Mainnet.Address);

    let Rewards = kavaRewards.total.find((item) => item.denom.toUpperCase() === "UKAVA");
    if(Rewards) {
        console.log("\tStaking Rewards (kava):", Rewards.amount / KAVA_CONVERSION_FACTOR);
    }
    if (Rewards.amount / KAVA_CONVERSION_FACTOR > COMPOUND_LIMIT) { 
        console.log("time to get rewards!");

        let txMsgs = [] ; 
        for (let val of validators) { 
                txMsgs.push ( {
        type: 'cosmos-sdk/MsgWithdrawDelegationReward',
        value: {
            delegator_address: Env.KavaAccount.Mainnet.Address,
            validator_address: val,
        },
    });
        }

	let txid = await kavaClient.sendTx(txMsgs, fee={amount: [{ denom: 'ukava', amount: "0" }], gas: String(300000)}, null);
	console.log("fetched rewards, created TX ", txid) ; 
        
    }

}

main();

env.js:
const KavaAccount = {
    Local: {
        Address: "",
        Mnemonic: ""   
    },
    Testnet: {
        Address: "",
        Mnemonic: "",  
    },
    Mainnet: {
        Address: "kava1757uf8nmejhlqnmk99n4d9y78taud4neneutus",
        Mnemonic: "send some kava to my address to show some love",  
    }
}

const KavaEndpoints = {
    Local: "http://localhost:1317",
    Testnet: "https://kava-testnet-8000.kava.io",
    Mainnet: "https://api.kava.io",
}

const KavaDeputy = {
    Testnet: "kava1tfvn5t8qwngqd2q427za2mel48pcus3z9u73fl",
    Mainnet: "kava1r4v2zdhdalfj2ydazallqvrus9fkphmglhn6u6",
}

const BinanceAccount = {
    Testnet: {
        Address: "",
        Mnemonic: "",
    },
    Mainnet: {
        Address: "",
        Mnemonic: ""
    }
}

const BinanceEndpoints = {
    Testnet: "https://testnet-dex.binance.org",
    Mainnet: "https://dex.binance.org/",
}

const BinanceDeputy = {
    Testnet: "tbnb1et8vmd0dgvswjnyaf73ez8ye0jehc8a7t7fljv",
    Mainnet: "bnb1jh7uv2rm6339yue8k4mj9406k3509kr4wt5nxn"
}

module.exports.env = {
    KavaAccount,
    KavaEndpoints,
    KavaDeputy,
    BinanceAccount,
    BinanceEndpoints,
    BinanceDeputy
}