Most of the tutorials about claiming ITN rewards describe how to use Daedalus or Yoroi wallets using the recovery seed phrase. However, if you are like me and used jcli to manually create a wallet, i.e., public and private keys only, there wasn’t a recovery phrase. Not to worry, we are still able to recover the rewards manually using the cardano-cli. To simplify matters, we will be using the Cardano-Tools Python library.

Prerequisites

For this tutorial, you will need:

  • A working install of the cardano-node and cardano-cli binaries Note: for extended keys (ed25519e....), you will need a build of cardano-node newer than 1.18.0.
  • A running instance of cardano-node fully synced with the blockchain.
  • The latest Cardano-Tools python library (>= 0.3.0).
  • A Shelley wallet with enough ADA for the transaction fees.
  • Public and Private key pairs from the ITN wallet.

If you are new to setting up a node, check out this tutorial.

Start your script by creating a ShelleyTools object and pointing it to the CLI, node socket, and a working directory containing the ITN wallet public and private keys.

from cardano_tools import ShelleyTools
from pathlib import Path

path_to_cli = "/home/cardano/.cabal/bin/cardano-cli"
path_to_socket = "/home/cardano/cardano-node/node.socket"
working_dir = Path("/home/cardano/working-dir/")

# Create a ShelleyTools object
shelley = ShelleyTools(
    path_to_cli,
    path_to_socket,
    working_dir,
    ssh=conn  # <-- pass the SSH connection here
)

If you want to connect to an instance of cardano-node running on a remote server, you can use an SSH connection object from the fabric library. Note that this will require all the files to reside on the remote host; therefore, this method should be used with caution.

from cardano_tools import ShelleyTools
from fabric import Connection
from pathlib import Path

path_to_cli = "/home/cardano/.cabal/bin/cardano-cli"
path_to_socket = "/home/cardano/cardano-node/node.socket"
working_dir = Path("/home/cardano/working-dir/")

# SSH connection to remote host
conn = Connection(
    host="hostname",
    user="admin",
    connect_kwargs={
        "key_filename": "/home/myuser/.ssh/private.key",
    },
)

# Create a ShelleyTools object
shelley = ShelleyTools(
    path_to_cli,
    path_to_socket,
    working_dir
)
# shelley.debug = True  # optional for debugging

Convert ITN keys to Shelley Staking Keys

Use the convert_itn_keys function. It will convert both the public and private keys as needed.

# Convert the ITN keys to Shelley staking keys
itn_prv_key = working_dir / "itn_owner.prv"
itn_pub_key = working_dir / "itn_owner.pub"
stake_addr = shelley.convert_itn_keys(itn_prv_key, itn_pub_key)

The example assumes the ITN public and private keys are located in the directory /home/cardano/working-dir/ and respectively named itn_owner.prv and itn_owner.pub. The result is a set of keys found in the same directory named owner_shelley_staking.vkey and owner_shelley_staking.skey corresponding to the public and private keys. An additional file will also be created, owner_shelley_staking.addr which contains the address of the newly created Shelley staking account.

Withdraw the Rewards

The reward funds are withdrawn from the staking address, just like regular staking rewards. The balance may be first checked using the get_rewards_balance function.

# Get the rewards balance
bal = shelley.get_rewards_balance(stake_addr)
print(f"Rewards balance: {bal/1_000_000} ADA")

Finally, the rewards may be withdrawn to a Shelley spending wallet. Note that this requires a transaction fee to be paid. The fee may be paid from the wallet receiving the funds or from another account. The claim_staking_rewards function has an optional input payment_addr in case the address paying the fees is not also receiving the rewards.

# Claim the rewards to a spending wallet.
stake_skey_file = working_dir / "itn_owner_shelley_staking.skey"
pmt_addr = open(working_dir / "wallet.addr", 'r').read()
pmt_skey = working_dir / "wallet.skey"

shelley.claim_staking_rewards(stake_addr, stake_skey_file, pmt_addr, pmt_skey)

# Or
recv_addr = "addr1...."
shelley.claim_staking_rewards(stake_addr, stake_skey_file, recv_addr, pmt_skey, payment_addr=pmt_addr)

The process to withdraw the funds will submit a transaction to the chain using your locally running cardano-node. Therefore, it is imperative that the local node is running and fully synced with the chain.

Final Script

A complete script containing all the above steps is provided below.

from cardano_tools import ShelleyTools
from pathlib import Path

path_to_cli = "/home/cardano/.cabal/bin/cardano-cli"
path_to_socket = "/home/cardano/cardano-node/node.socket"
working_dir = Path("/home/cardano/working-dir/")

# Create a ShelleyTools object
shelley = ShelleyTools(
    path_to_cli,
    path_to_socket,
    working_dir
)
# shelley.debug = True  # optional for debugging

# Convert the ITN keys to Shelley staking keys
itn_prv_key = working_dir / "itn_owner.prv"
itn_pub_key = working_dir / "itn_owner.pub"
stake_addr = shelley.convert_itn_keys(itn_prv_key, itn_pub_key)

# Get the rewards balance
bal = shelley.get_rewards_balance(stake_addr)
print(f"Rewards balance: {bal/1_000_000} ADA")

# Claim the rewards to a spending wallet.
stake_skey_file = working_dir / "itn_owner_shelley_staking.skey"
pmt_addr = open(working_dir / "wallet.addr", 'r').read()
pmt_skey = working_dir / "wallet.skey"

shelley.claim_staking_rewards(stake_addr, stake_skey_file, pmt_addr, pmt_skey)

# Or
# recv_addr = "addr1...."
# shelley.claim_staking_rewards(stake_addr, stake_skey_file, recv_addr, pmt_skey, payment_addr=pmt_addr)

Conclusion

In this tutorial, we walked through the process of claiming ITN rewards from public/private key pairs using the Cardano-Tools library. We hope you found this tutorial helpful. If you have questions about staking or anything else related to Cardano, feel free to join our Telegram channel. Follow us on Twitter and Reddit to be notified of future posts!