A potential STEEM challenge

I am thinking lately of running, in the near future, my own, not so big challenge, where I ask people around to do a STEEM power up above a minimum threshold and then I'll be supporting some of those users with an upvote (or more upvotes if I like their content in general) to their active post/s or comment/s.

The second requirement would be for those applying to have not made any power down in the last year.

As I am not a developer and I couldn't find how to easily query the STEEM blockchain for that, I had to spend a few hours "interacting" with AI and doing the so called "Vibe Coding".

Firstly, I had to communicate with AI to establish what is the fastest way to query the blockchain as at first it was suggesting I use the legacy API methods and fetching info dated one year ago is very slow.

Then the AI suggested I use the SDS by @steemchiller.

After iterating with AI for another couple of hours, I finally got to this Python script.

Strangely, the scripts AI generates never, really never work from the first time, at least for me, and I have to return the errors to it, then it says "you're right, this has to be changed to..." and I have to make more iterations. Thinking more of it, this has its economical logic - people need to make more /paid/ calls to AI. Anyway. Still, vibe coding is fun. Saves so much time. Poor entry-level developers!

I'm tagging @moecki here too, I trust you both, guys, please take a look at the script if I can rely on it to take those decision about who qualifies. I realize it is the season where people go on well deserved long holidays so there isn't any urgency, whenever you guys have time, or just ignore this, if you're too busy. I tested it with several accounts I follow, and to my observations, the results are accurate.

I saw in the posts of steemchiller about the SDS two URLs mentioned - sds.steemworld.org and sds0.steemworld.org and I guess I should use sds.steemworld.org ? I tried both, couldn't see any difference in the results or the execution speed.

To test how fast the power ups are counted for, I did a symbolic power up of 11.111 STEEM and it virtually took seconds before the script printed this in my console:


2025-06-15 21:45:15+00:00 --> 3.814 STEEM (Power Up) from du-finanzbot
2025-06-26 15:21:30+00:00 --> 1.268 STEEM (Power Up) from lifetrail
2025-08-13 10:08:39+00:00 --> 11.111 STEEM (Power Up) from lifetrail


No power downs for the last year, actually, I haven't powered down at all so far.

Here the full script:


import requests
from datetime import datetime, timedelta, timezone

def get_global_properties():
    url = "https://api.steemit.com"
    payload = {
        "jsonrpc": "2.0",
        "method": "condenser_api.get_dynamic_global_properties",
        "params": [],
        "id": 1
    }
    response = requests.post(url, json=payload)
    result = response.json()['result']
    fund_steem = float(result['total_vesting_fund_steem'].split()[0])
    total_vests = float(result['total_vesting_shares'].split()[0])
    return fund_steem, total_vests

def convert_vests_to_steem(vesting_shares, fund_steem, total_vests):
    vests = float(vesting_shares.split()[0])
    return (vests / total_vests) * fund_steem

def fetch_power_downs(account, start_ts, end_ts, fund_steem, total_vests):
    url = f"https://sds.steemworld.org/account_history_api/getHistoryByOpTypesTime/{account}/withdraw_vesting/{start_ts}-{end_ts}"
    response = requests.get(url)
    data = response.json()

    rows = data['result']['rows']
    power_downs = []

    for row in rows:
        timestamp = row[1]
        op_data = row[6][1]
        vesting_shares = op_data['vesting_shares']

        dt = datetime.fromtimestamp(timestamp, timezone.utc)
        steem_amount = convert_vests_to_steem(vesting_shares, fund_steem, total_vests)
        power_downs.append((dt, steem_amount))

    return power_downs

def fetch_power_ups(account, start_ts, end_ts):
    url = f"https://sds.steemworld.org/account_history_api/getHistoryByOpTypesTime/{account}/transfer_to_vesting/{start_ts}-{end_ts}"
    response = requests.get(url)
    data = response.json()

    rows = data['result']['rows']
    power_ups = []

    for row in rows:
        timestamp = row[1]
        op_data = row[6][1]
        steem_amount = float(op_data['amount'].split()[0])
        sender = op_data['from']

        dt = datetime.fromtimestamp(timestamp, timezone.utc)
        power_ups.append((dt, steem_amount, sender))

    return power_ups

# Main execution
account = 'lifetrail'
now_ts = int(datetime.now().timestamp())
one_year_ago_ts = int((datetime.now() - timedelta(days=365)).timestamp())

fund_steem, total_vests = get_global_properties()
power_downs = fetch_power_downs(account, one_year_ago_ts, now_ts, fund_steem, total_vests)
power_ups = fetch_power_ups(account, one_year_ago_ts, now_ts)

# Combine and sort all events
all_events = [(dt, steem, 'Power Down', None) for dt, steem in power_downs] + \
             [(dt, steem, 'Power Up', sender) for dt, steem, sender in power_ups]
all_events.sort(key=lambda x: x[0])

# Print results
for dt, steem, label, sender in all_events:
    if label == 'Power Up':
        print(f"{dt} --> {steem:.3f} STEEM ({label}) from {sender}")
    else:
        print(f"{dt} --> {steem:.3f} STEEM ({label})")



1230.png

divider-gold-ge2e85de6e_640.png

Here are some of our favorite quotes to motivate you to not give up and keep up the good work!

"Success isn't always about greatness. It's about consistency. Consistent hard work leads to success. Greatness will come."

By Dwayne Johnson


"Success seems to be connected with action. Successful people keep moving. They make mistakes, but they don't quit."

By Conrad Hilton


"Character cannot be developed in ease and quiet. Only through experience of trial and suffering can the soul be strengthened, vision cleared, ambition inspired and success achieved."

By Helen Keller


"I've come to believe that each of us has a personal calling that's as unique as a fingerprint and that the best way to succeed is to discover what you love and then find a way to offer it to others in the form of service, working hard and also allowing the energy of the universe to lead you."

By Oprah Winfrey


"Most of the important things in the world have been accomplished by people who have kept on trying when there seemed to be no hope at all."

By Dale Carnegie

divider-gold-ge2e85de6e_640.png

Our journey here continues and we hope to find lots of new friends and interesting content and accounts on Steemit!

If you got up to this point, please receive some positive vibes and thoughts from us. Have a great day!

divider-gold-ge2e85de6e_640.png

Copyright LifeTrail 2023

Divider by Rebecca Read from Pixabay

Sort:  

I don't have much time for details at the moment, so here are just my brief thoughts:

Your input is very helpful!

The ways you suggest to change it will optimize it and make the script dependable on one service instead of two, ergo faster and better. I'll have it modified in the next days and I'll share the result.

Do you recommend I use sds0. over just sds.? Any difference you aware of?

Thanks so much!

Do you recommend I use sds0. over just sds.? Any difference you aware of?

There are no differences at the moment.
sds and sds1 are the stable versions. I think sds is primarily used for steemworld.
Changes are installed on sds0 first. If everything goes well, it goes live on sds and sds1. As there are currently no new changes, all instances have the same status.

In addition to Moecki's comment, I played around with the query syntax:

For Power-Up:
https://sds0.steemworld.org/transfers_api/getTransfers/{"type":"transfer_to_vesting","to":"lifetrail","fromTime":"1723593324","orderDir":"ASC"}/800 - direct call via URL

For Power-Down:
https://sds0.steemworld.org/transfers_api/getTransfers/{"type":"withdraw_vesting","from":"upvu","fromTime":"1723593324","orderDir":"ASC"}/800 - direct call via URL

To convert VESTS to STEEM, you can use steem_per_share from this call: https://sds0.steemworld.org/steem_requests_api/getSteemProps

Maybe that's useful for you.