ХФ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 запихаем при вызове сразу в список.

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

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_pervests - это поможет рассчитать силу голоса аккаунта, и обязательно фиксируем текущее время блокчейна в переменной 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. Я давно перестал пытаться вникнуть чем размерность одного отличается от другого (все-таки пистон наследовал стимит больше). Посему предпочитаю порядок цифр контролировать самостоятельно и заодно вписать в словарь новый ключ _golospower.

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

# Определение 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.


Comments 11


В upper-case принято определять константы, а переменные - в down-case.

15.04.2018 07:16
0

когда кодил в конце 90-х вроде такого не было. но тут случай с ассетами, удобно их капслоком ибо golos уже используется. в след раз буду иметь в виду

15.04.2018 11:52
0

@ksantoprotein
thallid:
Отсутствует подключение к нодам голоса

15.04.2018 11:24
0

скучаем по таллиду?

15.04.2018 11:52
0

а то, я тут ежемесячный пост выпустила же -:)

15.04.2018 12:08
0

Thallid's dead baby, thallid's dead.

18.04.2018 06:11
0

?!

18.04.2018 07:04
0

Шутка на тарантиновской волне "Криминального чтива" о затянувшейся реорганизации сервиса. Самого лучшего сервиса по продаже апвоутов.

18.04.2018 12:09
0

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

А я не понял, кому подпел.. и связано ли это с реальным значением батарейки.

16.04.2018 16:41
0

видимо это тест на возраст

16.04.2018 19:46
0