![Screenshot 2025-01-12 at 21.10.43.png](https://images.hive.blog/768x0/https://files.peakd.com/file/peakd-hive/emrebeyler/EogPHN4HpdHWhoxjhNDDNhRSoiFoq7iGr1V8iuUXnF9vYHxnqEHQsvZPRWxnv3bQRvT.png)
If you have some stake at Holozing, and tired about claiming your rewards, automation is your friend.
import json
import requests
import time
from beem import Hive
from beemgraphenebase.ecdsasig import sign_message
from beemgraphenebase.account import PrivateKey
from binascii import hexlify
from dotenv import load_dotenv
import os
import logging
load_dotenv()
# Set up logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
class HolozingClient:
def __init__(self, username: str, posting_key: str):
self.username = username
self.posting_key = posting_key
self.jwt_token = None
self.hive = Hive(keys=[posting_key])
def check_pending_rewards(self) -> dict:
"""Check if there are any pending rewards before attempting to claim"""
url = f"https://api.holozing.com/rewards/pending?user={self.username}"
headers = {
'accept': 'application/json, text/plain, */*',
'origin': 'https://holozing.com',
'referer': 'https://holozing.com/'
}
try:
response = requests.get(url, headers=headers)
data = response.json()
total_rewards = (
float(data.get('delegation', '0')) +
float(data.get('stakeZing', '0')) +
float(data.get('holdingRewards', '0'))
)
logger.info(f"Rewards check for {self.username}:")
logger.info(f"Delegation: {data.get('delegation')} ZING")
logger.info(f"Stake: {data.get('stakeZing')} ZING")
logger.info(f"Holding: {data.get('holdingRewards')} ZING")
logger.info(f"Total: {total_rewards} ZING")
return {'total': total_rewards, 'data': data}
except Exception as e:
logger.error(f"Failed to check rewards: {str(e)}")
return {'total': 0, 'data': None}
def login(self) -> bool:
try:
login_result = self._login_to_holozing()
self.jwt_token = login_result.get('jwt')
return bool(self.jwt_token)
except Exception as e:
logger.error(f"Login failed: {str(e)}")
return False
def _login_to_holozing(self):
expiry = int(time.time()) + 86400
message = {
"username": self.username,
"type": "login",
"app": "holozing",
"expiry": expiry
}
message_str = json.dumps(message)
private_key = PrivateKey(self.posting_key)
signature_bytes = sign_message(message_str, private_key)
signature = hexlify(signature_bytes).decode('ascii')
login_url = "https://api.holozing.com/login/hive"
headers = {
"accept": "application/json, text/plain, */*",
"content-type": "application/json",
"origin": "https://holozing.com",
"referer": "https://holozing.com/"
}
payload = {
"success": True,
"error": None,
"result": signature,
"data": {
"type": "signBuffer",
"username": self.username,
"message": message_str,
"method": "Posting",
"rpc": None,
"title": "Login to HoloZing",
"key": "posting"
},
"message": "Message signed successfully.",
"request_id": 2
}
response = requests.post(login_url, json=payload, headers=headers)
return response.json()
def claim_rewards(self) -> bool:
"""
Claim rewards using the JWT token
"""
if not self.jwt_token:
logger.error(f"No JWT token available for {self.username}")
return False
url = "https://api.holozing.com/rewards/pending"
headers = {
"accept": "application/json, text/plain, */*",
"content-type": "application/json",
"authorization": f"Bearer {self.jwt_token}",
"origin": "https://holozing.com",
"referer": "https://holozing.com/",
"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36"
}
try:
response = requests.post(url, json={}, headers=headers)
if response.status_code == 200:
logger.info(f"Successfully claimed rewards for {self.username}")
return True
else:
logger.error(f"Failed to claim rewards for {self.username}. Status: {response.status_code}")
logger.error(f"Response: {response.text}")
return False
except Exception as e:
logger.error(f"Error claiming rewards for {self.username}: {str(e)}")
return False
def main():
username = "emrebeyler"
posting_key = os.getenv('HOLOZING_ACCOUNT_POSTING_KEY')
if not all([username, posting_key]):
logger.error("Missing credentials in environment variables")
return
client = HolozingClient(username, posting_key)
# First check if there are any rewards
rewards = client.check_pending_rewards()
if rewards['total'] <= 0:
logger.info("No rewards available to claim")
return
# Only proceed with login and claim if there are rewards
logger.info("Found claimable rewards. Proceeding with claim process...")
if client.login():
client.claim_rewards()
else:
logger.error("Failed to login for claiming")
if __name__ == "__main__":
main()
Required packages:
beem>=0.24.26
requests>=2.31.0
python-dotenv>=1.0.0
create .env file in the script, put your posting key as HOLOZING_POSTING_KEY=...
, edut username with your username, then just run the script. Basic knowledge about running python scripts and python environments are required.
P.S: Most of the code is written by Cursor AI Editor, can only get credits by giving it correct and clear directions. :) .
![](https://images.hive.blog/768x0/https://i.imgur.com/u4KMAkM.png)
It's so good that I saw this post exactly after I did a manual claim haha. To be honest, unlike in the early days when the game was announced, I sometimes forget to claim rewards for days, so this will come in handy. Even if it does it once a day, it's enough 😂
Next days, when my new Raspi 5 16GB is arriving - i'll set up some DePin Projects and probably will take the chance to let a bunch of automation scripts running.
thanks for sharing!
Enjoy, a good use case for a RaspberryPI. :)
Useful contribution 👍 not sure if Holozing has legs but I'm always up for rewards 🙂
Hey this is awesome!
and then you can use pyinstaller to create an .exe file to execute it with one click and thats much easier, just double click on that and its done...
good idea, tho, I've added this to a cronjob, it works in the background. I do not trigger it.
i need to look up what a cronjob is and how it works...
That's pretty cool! Too bad I haven't learned to program yet, haha! But maybe soon. My luck is that I'm methodical and rarely forget to claim my zings ;)