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

steem.js - не все так просто с get_account_history - путь, от которого мы отказались

 Всем лучи добра, последнее время у меня очень много работы над @dobryj.kit. Времени писать статейки нет. Вот решил отвлечься и написать про один подводный камень, с которым мы столкнулись во время разработки.

 В основе кита лежит не один прочитанный исходник. Как уже говорил в прошлых статьях - документации перелопачено тоже не мало.

@dobryj.kit переписывался с нуля несколько раз, вот и совсем недавно, мы перепиливали очередной механизм.

 Для финансовой части, по началу, мы решили использовать функцию getAccountHistory из библиотеки steem.js. Функция идеально подходит для этого - ведь в ней отображаются все действий, когда либо произведенные с аккаунтом @dobryj.kit

 Функция возвращает максимально 2000 записей и принимает 4 параметра
steem.api.getAccountHistory (login, from, limit, callback)

  • login - соответственно login участника системы Голос, историю которого мы хотим получить
  • from - номер записи, от которой мы будем получать историю
  • limit - количество строк, которые будут в результате (но не более 2000)
  • callback - функция, которая будет запущена, после получения данных

 Важно понимать, что эта функция работает не совсем по стандартам логики. Мы указываем с какой записи мы будем отсчитывать limit записей к 0. То есть,
steem.api.getAccountHistory ('@dobryj.kit', 5, 5, function(err, history){}) означает, что мы будем с 5 строки получать 5 строк уменьшая шаг - итогом будет массив [0,1,2,3,4,5]. Опытный читатель заметил, что вернется 6 записей вместо 5. Но если limit указать 4.
steem.api.getAccountHistory ('@dobryj.kit', 5, 4, function(err, history){}) вернется 5 записей [1,2,3,4,5] - исчезнет 0 запись - это говорит о том, что в выборку не попадет запись о создании аккаунта, но она нам и не нужна.

 Итак, когда мы определились с логикой, и знаем ограничения - как же получить всю историю?
Во первых, нам нужно определить максимальный номер транзакции из истории нашего аккаунта. Для этого необходимо указать в from блок, который больше текущего блока и в limit указать 0.
Мы делаем такой запрос:
steem.api.getAccountHistory ('@dobryj.kit', 800000000000, 0, function(err, history){})
Это вернет нам последнюю транзакцию из истории.

 Теперь, нам необходимо - составить "очередь" для загрузки истории. Алгоритм такой

  1. получаем максимальный блок из истории
  2. если он меньше 2000, то получаем историю
  3. если больше 2000 будем получать по 2000 от максимального блока
var currentID = maxID;

var queue = []; //очередь

if (currentID > 2000) {
    var i = 0;
    while (currentID > 0) {
        currentID -= 2000;
        i += 2000;
        if (currentID >= 0) {
            ueue.push({
                from: i,
                limit: 1999
            })
        } else {
            queue.push({
                from: maxID,
                limit: currentID + 1999
             })
         }
     }
}

Итогом будет массив типа

[
    [{from:2000, limit:1999}],
    [{from:4000, limit 1999}],
    [{from 4124, limit 123}]
]

Вот она наша "очередь" запросов.

Далее, простым обходом массива запускаем "получатор"истории

queue.forEach(function(element){
    steem.api.getAccountHistory('@dobryj.kit', element.from, element.limit, function(err, history){
        //обработка транзакций истории
    })
});

 Выглядит не сложно. Но тут есть подводные камни. Как многие из нас знают - блоки, генерируемые блокчейном бывают нескольких типов. До того как делегат подпишет блок, данные в нем могут измениться. Поэтому в работе кита, мы используем только подписанные блоки.

Предупреждение - все что будет изложено дальше, всего лишь догадки автора, т.е. меня, если я в чем то не прав, прошу меня поправить.
 Вы когда нибудь использовали Golos Api Explorer? При изучении механики работы я частенько изучал блоки и натыкался на блоки, похожие на блок по ссылке выше.

 Видите, он фактически пустой и не несет в себе никакой информации - неужели в момент простоя генерируются подобные блоки?
 Если мы взглянем в инструмент от @ropox и @asuleymanov - Steem.js GUI то увидим подобную картину - результат блока - пустой массив.

 Итак, откуда эти блоки? Я поразмыслил и понял, что в момент подписания блока - подписываемый блок затирается, а вся информация, находившаяся в нем, переходит в новый блок. То есть, история, которую я только что получил - может изменить номер блока через несколько минут.
 Мои наблюдения подтвердились, когда у нас начала расходиться история, накопленная парсером и история, загруженная из истории (простите за тавтологию).
 Данную особенность можно контролировать с помощью функции getDynamicGlobalProperties, а точнее ее параметром last_irreversible_block_num, который возвращает номер максимального не редактируемого блока.
 Поэтому, мы используем другой подход в получении истории, о котором я расскажу в дальнейшем, если, конечно, вам будет интересно.

Спасибо за внимание
Подписывайтесь на мой блог и да прибудет с вами сила!

4
2.440 GOLOS
На Golos с May 2017
Комментарии (12)
Сортировать по:
Сначала старые