Уважаемые пользователи Голос!
Сайт доступен в режиме «чтение» до сентября 2020 года. Операции с токенами Golos, Cyber можно проводить, используя альтернативные клиенты или через эксплорер Cyberway. Подробности здесь: https://golos.io/@goloscore/operacii-s-tokenami-golos-cyber-1594822432061
С уважением, команда “Голос”
GOLOS
RU
EN
UA
ksantoprotein
7 лет назад

ХФ17 get_accounts python

Сначала ты веришь в Деда Мороза, потом не веришь... а потом ты сам Дед Мороз. Так и с библиотеками питона для взаимодействия с голосом. После ХФ работоспособным пока является вариант от @vvk golos-piston и сегодня мы поговорим о том, как начинать писать свои api для более лучшей работы скриптов/ботов на питоне.

Очень неудобный модуль в оригинальном пистоне - это модуль Account, который предполагает работу с одним аккаунтом. Так что когда у тебя студботнет на 66 персон и ты хочешь понять кем можно апнуть, так как батарейка не просела, а кем не стоит... этот класс уже не есть лучшее решение. Поэтому напишем свою функцию, которая будет одновременно получать информацию по необходимым аккаунтам в удобоваримом виде.

from piston import Steem
from datetime import datetime

golos = Steem(node = 'wss://ws17.golos.io')

logins = ['ksantoprotein', 'sci-populi', 'vp-cosmos']

accounts = get_accounts(logins)

Вот такая предварительная магия питона. Мы задаем список логинов и вызываем нашу функцию get_accounts и получаем список словарей с необходимой информацией. Если же нас будет интересовать только один пользователь (а так и реализовано в оригинальном пистоне), то вызов будет такой.

login = 'ksantoprotein'
account = get_accounts([login])

Мы просто строковую переменную login запихаем при вызове сразу в список.

А теперь опишем нашу авторскую функцию get_accounts

def get_accounts(logins):
    accounts = golos.rpc.get_accounts(logins, api='database_api')

    info_golos = golos.rpc.get_dynamic_global_properties(api='database_api')

    feed = golos.rpc.get_feed_history(api='database_api')
    base = float(feed["current_median_history"]["base"].split()[0])
    quote = float(feed["current_median_history"]["quote"].split()[0])
    median_price = round(base / quote, 3)

    # Obtain STEEM/VESTS ratio
    total_vesting_fund_steem = float(str(info_golos["total_vesting_fund_steem"]).split()[0])
    total_vesting_shares = float(str(info_golos["total_vesting_shares"]).split()[0])
    total_reward_fund_steem = float(str(info_golos["total_reward_fund_steem"]).split()[0])
    total_reward_shares2 = int(info_golos["total_reward_shares2"])

    golos_per_vests = total_vesting_fund_steem / total_vesting_shares

    NOW = datetime.strptime(info_golos["time"], "%Y-%m-%dT%H:%M:%S")

Мы тут аж три раза обратимся к блокчейну. Сначала получим оригинальную информацию по аккаунтам в accounts и так как мы хотим посчитать таки реальную батарейку, то еще загрузим текущие динамические переменные и для довеска рассчитаем так называемую медиану, он же курс фидо или курс делегатов.

Так же нам понадобится golos_per_vests - это поможет рассчитать силу голоса аккаунта, и обязательно фиксируем текущее время блокчейна в переменной NOW без чего нам не высчитать реальное значение батарейки... ооооууууооо... простите, не сдержался и подпел.

Теперь мы готовы пройтись циклом по полученному списку и внести необходимые изменения

for account in accounts:
    # Определение ликвидных токенов
    account["GOLOS"] = float(str(account["balance"]).split()[0])
    account["GBG"] = float(str(account["sbd_balance"]).split()[0])

Меня реально сильно раздражает, что формат наших токенов представляется в формате amount, поэтому сразу отделяю числовое значение и уже далее буду оперировать типом переменной float, а так как account - это словарь, то можно с легкость добавить необходимые ключи GBG и GOLOS. Так что в дальнейшем скрипту будет проще оперировать, а главное понятнее для стороннего чтения питоновского текста.

# Определение реальной батарейки 1-10000
VP = float(account["voting_power"])
last_vote_time = datetime.strptime(account["last_vote_time"], "%Y-%m-%dT%H:%M:%S")
age = (NOW - last_vote_time).total_seconds() / 1
actualVP = VP + (10000 * age / 432000)
if actualVP > 10000:
    account["voting_power"] = 10000
else:
    account["voting_power"] = round(actualVP)

А таким образом считается реальная батарейка. Используя время последнего апвота и отсчитав сколько прошло до текущего момента по некой формуле считается реальный процент. Единственно я оставляю значение в формате int (от 1 до 10000), а не float (от 0.01 до 100.00%). Поверьте, так лучше. И если прошло более суток, то батарейка считается равной 100% в своей зарядке!

# Определение golos_power (SP)
vests = float(str(account["vesting_shares"]).split()[0])
account["golos_power"] = round(vests * golos_per_vests, 3)

В блокчейне наша сила голоса хранится в GEST или VEST. Я давно перестал пытаться вникнуть чем размерность одного отличается от другого (все-таки пистон наследовал стимит больше). Посему предпочитаю порядок цифр контролировать самостоятельно и заодно вписать в словарь новый ключ golos_power.

И раз Остапа понесло, то при переходе на линейку можно вычислить сколько же принесет ваш апвот куда-либо.

# Определение rshares
vesting_shares = int(1e6 * account["golos_power"] / golos_per_vests)

max_vote_denom = info_golos["vote_regeneration_per_day"] * (5 * 60 * 60 * 24) / (60 * 60 * 24)
used_power = int((account["voting_power"] + max_vote_denom - 1) / max_vote_denom)

rshares = ((vesting_shares * used_power) / 10000)
account["rshares"] = round(rshares)

# Определение стоимости апвота
value_golos = round(account["rshares"] * total_reward_fund_steem / total_reward_shares2, 3)
value_gbg = round(value_golos * median_price, 3)

account["value"] = {"GOLOS": value_golos, "GBG": value_gbg}

Так как покерное прошлое дает немного о себе знать, поэтому запихал полученные значения с учетом медианного курса в ключ value (валью бет, шоу даун вэлью)... "ценность"... прогнозируемая на текущий момент ценность вашего апвота (без учета кураторских само собой).

Осталось только вернуть обновленный список

return(accounts)

И пользоваться. Мне приглянулся такой подход, теперь данную функцию можно описать в виде класса, подключать к своим ботам и спокойно оперировать полученным в "один" проход. При этом если снова сменят линейку, то можно переписать код в одном месте или добавить что-то еще дополнительно. К примеру я так и не разобрался с бандвишем и формулами @vvk и пока еще не додумал как бы можно было бы их внедрить в эту функцию, чтобы потом можно было бы прогнозировать, а сможет ли тот или иной аккаунт совершить то или иное действие.

Меня радует, что в чатах появляется народ, кто осваивает питон для доступа к блокчейну, поэтому есть для кого постить подобную информацию. Если что здесь инструкция по установке golos-piston в связке с python 3.5.

2
297.324 GOLOS
На Golos с July 2017
Комментарии (11)
Сортировать по:
Сначала старые