# Расширение Blockchain Updates
Blockchain Updates — расширение ноды, которое отправляет по gRPC сообщения об изменениях на блокчейне.
Blockchain Updates позволяет отслеживать изменения, которые внесла каждая транзакция и блок:
- изменения в балансах,
- изменения в количестве WAVES, переданных/полученных в лизинг,
- изменения в хранилищах данных аккаунтов,
- выпуск токенов и изменение параметров токенов (в том числе довыпуск/сжигание, настройка спонсирования, изменение скрипта).
Получать изменения можно по заданному диапазону высоты или в реальном времени.
Примеры применения расширения:
- Интеграция с мессенджером для отправки оповещений о событиях по аккаунту.
- Отслеживание платежей, поступающих в пользу dApp в транзакциях вызова скрипта.
- Расчет среднего баланса аккаунта за неделю.
- Сервисы поиска токенов по параметрам, поиска по хранилищам данных аккаунтов и др.
Blockchain Updates можно использовать на легкой ноде, однако в этом случае возвращаемые данные не будут содержать
state_changes
для транзакций вызова скрипта.
# Требования к оборудованию
Для ноды с расширением Blockchain Updates рекомендуется увеличить дисковое пространство на 70 Гбайт SSD (например, на высоте 3587641 для хранения данных расширения используется 63 Гбайт).
# Запуск ноды с расширением
Ноду с расширением можно установить двумя способами: из DEB-пакета и из JAR-файла. Расширение Blockchain Updates находится в том же пакете и архиве, что и gRPC Server. Использовать эти два расширения можно как вместе, так и по отдельности, отличаются только настройки в файле конфигурации ноды.
⚠️ Важно: Если у вас уже есть работающая нода, просто установить расширение недостаточно. Требуется заново получить актуальную базу данных блокчейна с историей изменений:
Удалите файлы базы данных: они находятся в каталоге, указанном в настройке waves.db.directory, по умолчанию — в подкаталоге
data
основного каталога ноды).Установите расширение из DEB-пакета или JAR-файла и включите расширение в настройках ноды, как описано ниже.
Загрузите или импортируйте блокчейн одним из следующих способов:
• Запустите ноду с расширением с нуля и дождитесь синхронизации блокчейна в обычном режиме работы ноды (см. раздел Синхронизировать блокчейн Waves).
• Импортируйте блокчейн из бинарного файла (см. раздел Импортировать и экспортировать блокчейн).
• Загрузите архивы баз данных
blockchain_last.tar
иblockchain-updates_last.tar
(см. раздел Загрузить актуальный блокчейн). Распакуйте архивblockchain_last.tar
в каталог, указанный в настройке waves.db.directory (по умолчанию — подкаталогdata
основного каталога ноды). Распакуйте архивblockchain-updates_last.tar
в подкаталогblockchain-updates
основного каталога ноды.
# Установка из DEB-пакета
Скачайте последнюю версию DEB-пакетов ноды и расширения со страницы Releases (секция Assets) на GitHub.
Имя пакета с расширением:
• для Mainnet:
grpc-server_{номер версии}_all.deb
• для Testnet:
grpc-server-testnet_{номер версии}_all.deb
• для Stagenet:
grpc-server-stagenet_{номер версии}_all.deb
Установите пакеты:
Для Mainnet:
sudo dpkg -i waves_{номер версии}_all.deb sudo dpkg -i grpc-server_{номер версии}_all.deb
Для Testnet:
sudo dpkg -i waves-testnet_{номер версии}_all.deb sudo dpkg -i grpc-server-testnet_{номер версии}_all.deb
Для Stagenet:
sudo dpkg -i waves-stagenet_{номер версии}_all.deb sudo dpkg -i grpc-server-stagenet_{номер версии}_all.deb
Отредактируйте файл конфигурации ноды (см. раздел Конфигурация ноды). Для Mainnet файл конфигурации находится по адресу
/etc/waves/waves.conf
, для Testnet —/etc/waves-testnet/waves.conf
, для Stagenet —/etc/waves-stagenet/waves.conf
.3.1. Добавьте Blockchain Updates в секцию
waves.extensions
:waves { ... extensions = [ com.wavesplatform.events.BlockchainUpdates ] }
3.2. Если требуется изменить порт для подключения клиента (по умолчанию 6881), добавьте настройку:
waves { ... blockchain-updates { grpc-port = 6888 # Укажите порт }
Запустите ноду.
Для Mainnet:
sudo systemctl start waves
Для Testnet:
sudo systemctl start waves-testnet
Для Stagenet:
sudo systemctl start waves-stagenet
Если расширение работает, в log-файле ноды появятся сообщения:
BlockchainUpdates extension starting with settings <...>
BlockchainUpdates startup check successful at height <...>
BlockchainUpdates extension started gRPC API on port <...>
# Установка из JAR-файла
Скачайте последнюю версию JAR-файла ноды и TGZ-архива с расширением со страницы Releases (секция Assets) на GitHub.
Имя TGZ-архива с расширением:
• для Mainnet:
grpc-server-{номер версии}.tgz
• для Testnet:
grpc-server-testnet-{номер версии}.tgz
• для Stagenet:
grpc-server-stagenet-{номер версии}.tgz
Распакуйте TGZ-архив в папку с JAR-файлом ноды.
Создайте новый файл конфигурации или откройте существующий (см. раздел Конфигурация ноды).
3.1. Добавьте Blockchain Updates в секцию
waves.extensions
:waves { ... extensions = [ com.wavesplatform.events.BlockchainUpdates ] }
3.2. Если требуется изменить порт для подключения клиента (по умолчанию 6881), добавьте настройку:
waves { ... blockchain-updates { grpc-port = 6888 # Укажите порт }
Выполните команду:
Для Mainnet:
java -cp 'waves-all-{номер версии}.jar:grpc-server-{номер версии}/lib/*' com.wavesplatform.Application {имя файла конфигурации}.conf
Для Testnet:
java -cp 'waves-all-{номер версии}.jar:grpc-server-testnet-{номер версии}/lib/*' com.wavesplatform.Application {имя файла конфигурации}.conf
Для Stagenet:
java -cp 'waves-all-{номер версии}.jar:grpc-server-stagenet-{номер версии}/lib/*' com.wavesplatform.Application {имя файла конфигурации}.conf
В Windows используйте
;
вместо:
, например:java -cp 'waves-all-{номер версии}.jar;grpc-server-{номер версии}/lib/*' com.wavesplatform.Application {имя файла конфигурации}.conf
Если расширение работает, в log-файле ноды появятся сообщения:
BlockchainUpdates extension starting with settings <...>
BlockchainUpdates startup check successful at height <...>
BlockchainUpdates extension started gRPC API on port <...>
# Генерация клиента
Склонируйте protobuf-схемы с помощью команды
git clone https://github.com/wavesplatform/protobuf-schemas/
На основе схемы blockchain_updates.proto сгенерируйте клиентский код для вашего языка программирования. Подробные инструкции приведены в разделе Supported languages and platforms документации gRPC.
Для создания TypeScript- или JavaScript-клиента рекомендуем использовать библиотеку node-api-grpc.
# Использование
API Blockchain Updates предоставляет три функции:
GetBlockUpdate
— возвращает изменения, порожденные блоком на указанной высоте.- GetBlockUpdatesRange — возвращает массив изменений в указанном диапазоне высоты.
- Subscribe — возвращает поток сообщений об изменениях по мере появления. Опционально можно указать начальную и/или конечную высоту.
Структуру запросов и ответов можно посмотреть в файле blockchain_updates.proto.
# Subscribe
Функция Subscribe
возвращает события по мере появления:
- до текущей высоты блокчейна — исторические данные, то есть сообщения о добавлении блока,
- затем текущие события в реальном времени: добавление блока, добавление микроблока, откат блока, откат микроблока (см. описание протокола Waves-NG).
В случае разрыва соединения рекомендуем откатить последний блок на клиенте и возобновить получение событий с предыдущего блока.
Параметры:
Имя | Тип | Описание |
---|---|---|
from_height | int32 | Начальная высота. Необязательный параметр, по умолчанию 1 |
to_height | int32 | Конечная высота. Необязательный параметр, по умолчанию высота не ограничена |
Функция возвращает поток (стрим) объектов SubscribeEvent
, содержащих по одному сообщению об изменениях BlockchainUpdated
.
Поля сообщения:
Имя | Тип | Описание |
---|---|---|
update.id | bytes | ID последнего блока или микроблока на блокчейне после события |
update.height | int32 | Высота |
update.update | Append или Rollback | Событие: добавление или откат блока или микроблока. См. Формат событий ниже |
referenced_assets | repeated StateUpdate.AssetInfo | Ассеты, участвующие в событии. См. AssetInfo ниже |
Пример подключения (Python):
import grpc
from waves.events.grpc.blockchain_updates_pb2_grpc import BlockchainUpdatesApiStub
from waves.events.grpc.blockchain_updates_pb2 import SubscribeRequest
with grpc.insecure_channel('<your_node_url>:<port>') as channel:
for block in BlockchainUpdatesApiStub(channel).Subscribe(SubscribeRequest(from_height=3000000)):
print(block)
# GetBlockUpdatesRange
Функция GetBlockUpdatesRange
возвращает изменения в указанном диапазоне высоты. Рекомендуем использовать ее для аналитических задач, для которых достаточно обновления, например, раз в час или раз в сутки. Конечную высоту диапазона лучше указывать на несколько блоков меньше текущей высоты блокчейна, чтобы избежать проблем в случае отката высоты.
Параметры:
Имя | Тип | Описание |
---|---|---|
from_height | int32 | Начальная высота. Обязательный параметр |
to_height | int32 | Конечная высота. Обязательный параметр |
Функция возвращает массив GetBlockUpdatesRangeResponse
, содержащий сообщения об изменениях BlockchainUpdated
. Если указана конечная высота больше текущей высоты блокчейна, функция вернет ответ только в момент, когда высота блокчейна достигнет указанной конечной высоты. До текущей высоты возвращаются сообщения о добавлении блока, на текущей высоте могут появиться сообщения о любых событиях.
# Формат событий
Структуру событий можно посмотреть в файле events.proto.
Некоторые изменения на блокчейне не привязаны ни к одной транзакции, а происходят на уровне блока. В частности, изменение баланса генератора блока: 40% комиссии за транзакцию, которые получает генератор текущего блока, привязаны к транзакции, а 60%, которые получает генератор следующего блока, ассоциированы только с этим блоком. Вознаграждение за создание блока также ассоциировано только с блоком.
Если комиссия за транзакцию указана в спонсорском ассете, то Blockchain Updates возвращает, кроме изменения балансов отправителя и генератора блока, изменение баланса спонсора: он получает сумму комиссии в спонсорском ассете и выплачивает эквивалентную сумму в WAVES. Подробнее о спонсировании
# Append: добавление блока
Сообщение о добавлении блока может содержать транзакции и порожденные ими изменения (создан ключевой блок + микроблок) либо транзакции могут отсутствовать (создан только ключевой блок).
Поля сообщения:
Имя поля | Тип | Описание |
---|---|---|
block | Block | Данные блока: заголовки и транзакции. См. также раздел Бинарный формат блока |
updated_waves_amount | int64 | Общее количество WAVES с учетом вознаграждения за создание блока |
activated_features | repeated int32 | Номера фич, активированных с этого блока |
vrf | bytes | Псевдослучайный криптографический хеш, используемый в протоколе Leased Proof of Stake для расчета времени, когда генератор получает право выпустить блок |
transaction_ids | repeated bytes | Идентификаторы транзакций в блоке |
transactions_metadata | repeated TransactionMetadata | Дополнительная информация о транзакциях. См. TransactionMetadata ниже |
state_update | StateUpdate | Изменения состояния блокчейна, привязанные к блоку. См. StateUpdate ниже |
transaction_state_updates | repeated StateUpdate | Изменения состояния блокчейна, привязанные к транзакциям. См. StateUpdate ниже |
transaction_ids
, transactions_metadata
, transaction_state_updates
— параллельные массивы: одному порядковому номеру соответствуют данные об одной и той же транзакции. Если дополнительная информация отсутствует, в массиве transactions_metadata
по этому индексу находится пустое значение.
Пример
{
"id" : "7gcuQwOgRC8Cz+wWquTieR15PA+kctdFcSf10E98l7inxH5NOY7+BRmMSbVi/jxcvpluywxSVM/uIAIKxbtkCA==",
"height" : 2,
"append" : {
"block" : {
"block" : {
"header" : {
"chainId" : 84,
"reference" : "8SKLHdB+1z/Pi99SOdhHyA4aL/GOOsdCXKaCADyGjG3mh4hIuzzeI7P1/1ePyyuMXnJoTHe9rpCoIS7RieKICw==",
"baseTarget" : "60",
"generationSignature" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"featureVotes" : [ ],
"timestamp" : "1614956693029",
"version" : 2,
"generator" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"rewardVote" : "-1",
"transactionsRoot" : ""
},
"signature" : "7gcuQwOgRC8Cz+wWquTieR15PA+kctdFcSf10E98l7inxH5NOY7+BRmMSbVi/jxcvpluywxSVM/uIAIKxbtkCA==",
"transactions" : [ {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "1000000"
},
"timestamp" : "1614956690976",
"version" : 1,
"transfer" : {
"recipient" : {
"publicKeyHash" : "PTrYhPoEKSe51sN99wr1wL2VFsU="
},
"amount" : {
"assetId" : "",
"amount" : "100000000"
},
"attachment" : ""
}
},
"proofs" : [ "WIkitBii4d0LjMCxRiC6i+9QPVXQyKJxvRLj/uIao6KDP9dnd4oCEPIcKJPXiVnrAp1xExti3levPAtK7lDqDw==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "1000000"
},
"timestamp" : "1614956690977",
"version" : 2,
"lease" : {
"recipient" : {
"publicKeyHash" : "PTrYhPoEKSe51sN99wr1wL2VFsU="
},
"amount" : "1000000000"
}
},
"proofs" : [ "VOdvKFrjMeq8YodWYsuMIlI2XuUB3hYP85l49pqKzDRL+s4+2OqeZWxNZAwynyrtD39woxy/mZaV01TKQSPYDw==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "100000000"
},
"timestamp" : "1614956690978",
"version" : 2,
"issue" : {
"name" : "test",
"description" : "",
"amount" : "1000",
"decimals" : 0,
"reissuable" : true,
"script" : ""
}
},
"proofs" : [ "6vyW+hzk5g5wgwJAjfdcSCCQxECjLa2tX+SDYm7b20/vzADqNXNjrcV6ra1Qvl/OLQcJdppcnUrVBpEjfxPKAA==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "1000000"
},
"timestamp" : "1614956690979",
"version" : 2,
"reissue" : {
"assetAmount" : {
"assetId" : "hsQkyz38InYtnW1muswEf7qEeAsRpc5SG4MC27K/mRc=",
"amount" : "1000"
},
"reissuable" : true
}
},
"proofs" : [ "5adqKEbN0OHdpBhrRtBgfGtXhWK8zFOkuNOrnUYTsU2wAjrdVJrG/xjHHBh0e0NBbg3WEpUeOl93WyqitIKpDA==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "3000000"
},
"timestamp" : "1614956690980",
"version" : 1,
"dataTransaction" : {
"data" : [ {
"key" : "test",
"stringValue" : "test"
} ]
}
},
"proofs" : [ "ZiR8Xy5rN5CZ/5sPQEAd3qQ9vdj4tenpD58T4Hla5TpCWi3va+o391X6bQ0evwfBMP6EVfJ8e5d0toFzStRrCQ==" ]
} ]
},
"updatedWavesAmount" : "10000000600000000"
},
"transactionIds" : [ "l7zm8/8YT753CHgPrsTJU4ol/luwt3rUM1xSob4vA6E=", "YXkv6kf4P+C8Hed93ouMQs9SQRRLF9+l+6S165ZQS3w=", "hsQkyz38InYtnW1muswEf7qEeAsRpc5SG4MC27K/mRc=", "1gevjcLmf8R6lqRP8iWmWvU8rTHyWGRVmj4aFLlvvXo=", "XOHOVbrsTJa9Kg0VjEZHY7ckqdUpKTP+aZ7KJZWGzVA=" ],
"transactionsMetadata" : [ {
"transfer" : {
"recipientAddress" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME="
}
}, {
"leaseMeta" : {
"recipientAddress" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME="
}
}, { }, { }, { } ],
"stateUpdate" : {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001242400000"
},
"amountBefore" : "10000000600000000"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ ],
"assets" : [ ],
"individualLeases" : [ ]
},
"transactionStateUpdates" : [ {
"balances" : [ {
"address" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"amountAfter" : {
"assetId" : "",
"amount" : "100000000"
},
"amountBefore" : "0"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001141400000"
},
"amountBefore" : "10000001242400000"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ ],
"assets" : [ ],
"individualLeases" : [ ]
}, {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001140400000"
},
"amountBefore" : "10000001141400000"
} ],
"leasingForAddress" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"inAfter" : "0",
"outAfter" : "1000000000",
"inBefore" : "0",
"outBefore" : "0"
}, {
"address" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"inAfter" : "1000000000",
"outAfter" : "0",
"inBefore" : "0",
"outBefore" : "0"
} ],
"dataEntries" : [ ],
"assets" : [ ],
"individualLeases" : [ {
"leaseId" : "YXkv6kf4P+C8Hed93ouMQs9SQRRLF9+l+6S165ZQS3w=",
"statusAfter" : "ACTIVE",
"amount" : "1000000000",
"sender" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"recipient" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"originTransactionId" : "YXkv6kf4P+C8Hed93ouMQs9SQRRLF9+l+6S165ZQS3w="
} ]
}, {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001040400000"
},
"amountBefore" : "10000001140400000"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "hsQkyz38InYtnW1muswEf7qEeAsRpc5SG4MC27K/mRc=",
"amount" : "1000"
},
"amountBefore" : "0"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ ],
"assets" : [ {
"after" : {
"assetId" : "hsQkyz38InYtnW1muswEf7qEeAsRpc5SG4MC27K/mRc=",
"issuer" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"decimals" : 0,
"name" : "test",
"description" : "",
"reissuable" : true,
"volume" : "1000",
"sponsorship" : "0",
"nft" : false,
"lastUpdated" : 2,
"safeVolume" : "A+g="
}
} ],
"individualLeases" : [ ]
}, {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001039400000"
},
"amountBefore" : "10000001040400000"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "hsQkyz38InYtnW1muswEf7qEeAsRpc5SG4MC27K/mRc=",
"amount" : "2000"
},
"amountBefore" : "1000"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ ],
"assets" : [ {
"before" : {
"assetId" : "hsQkyz38InYtnW1muswEf7qEeAsRpc5SG4MC27K/mRc=",
"issuer" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"decimals" : 0,
"name" : "test",
"description" : "",
"reissuable" : true,
"volume" : "1000",
"sponsorship" : "0",
"nft" : false,
"lastUpdated" : 2,
"safeVolume" : "A+g="
},
"after" : {
"assetId" : "hsQkyz38InYtnW1muswEf7qEeAsRpc5SG4MC27K/mRc=",
"issuer" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"decimals" : 0,
"name" : "test",
"description" : "",
"reissuable" : true,
"volume" : "2000",
"sponsorship" : "0",
"nft" : false,
"lastUpdated" : 2,
"safeVolume" : "B9A="
}
} ],
"individualLeases" : [ ]
}, {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001036400000"
},
"amountBefore" : "10000001039400000"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"dataEntry" : {
"key" : "test",
"stringValue" : "test"
},
"dataEntryBefore" : {
"key" : "test"
}
} ],
"assets" : [ ],
"individualLeases" : [ ]
} ]
},
"referencedAssets" : [ {
"id" : "hsQkyz38InYtnW1muswEf7qEeAsRpc5SG4MC27K/mRc=",
"decimals" : 0,
"name" : "test"
} ]
}
# Append: добавление микроблока
В сообщении о добавлении микроблока присутствуют только те транзакции и порожденные ими изменения, которых не было в предшествующем блоке/микроблоке.
Поля сообщения:
Имя поля | Тип | Описание |
---|---|---|
micro_block | SignedMicroBlock | Данные микроблока |
updated_transactions_root | int64 | Корневой хеш всех транзакций текущего блока |
transaction_ids | repeated bytes | Идентификаторы транзакций в микроблоке |
transactions_metadata | repeated TransactionMetadata | Дополнительная информация о транзакциях. См. TransactionMetadata ниже |
state_update | StateUpdate | Изменения состояния блокчейна, привязанные к блоку. См. StateUpdate ниже |
transaction_state_updates | repeated StateUpdate | Изменения состояния блокчейна, привязанные к транзакциям. См. StateUpdate |
transaction_ids
, transactions_metadata
, transaction_state_updates
— параллельные массивы: одному порядковому номеру соответствуют данные об одной и той же транзакции. Если дополнительная информация отсутствует, в массиве transactions_metadata
по этому индексу находится пустое значение.
Пример
{
"id" : "PM99HiRDmeepqQ9ezrTjs85WnjTavOuTfC84X7mdL9IHEI9dMdZ43JXQCYHFoy9ul9RLIsUL/vtwaFt1FeIODA==",
"height" : 2,
"append" : {
"microBlock" : {
"microBlock" : {
"microBlock" : {
"version" : 3,
"reference" : "kMZ1rAlt+eNoHqHfuM6R5MS1NslQXDUJ2R3AreDjYWHEU5YIaU9unXZTTRcOBq/8zQEeI57scSgF7zH94N21Bw==",
"updatedBlockSignature" : "PM99HiRDmeepqQ9ezrTjs85WnjTavOuTfC84X7mdL9IHEI9dMdZ43JXQCYHFoy9ul9RLIsUL/vtwaFt1FeIODA==",
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"transactions" : [ {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "1000000"
},
"timestamp" : "1614955693251",
"version" : 1,
"transfer" : {
"recipient" : {
"publicKeyHash" : "PTrYhPoEKSe51sN99wr1wL2VFsU="
},
"amount" : {
"assetId" : "",
"amount" : "100000000"
},
"attachment" : ""
}
},
"proofs" : [ "c7gEcrOqeKhyJgdY0HO6lmp9WCCHJTMjL0IZhehtTvRIFMZWGPb5YOTumytK3dGi1vORxvw1UmBNioLxJBdSAw==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "1000000"
},
"timestamp" : "1614955693252",
"version" : 2,
"lease" : {
"recipient" : {
"publicKeyHash" : "PTrYhPoEKSe51sN99wr1wL2VFsU="
},
"amount" : "1000000000"
}
},
"proofs" : [ "sTTAbbdtEFRbwqlly2fc16oWpu5+hJN5am2AQvz5gix162EEepo/SqoTkIjMJ3OgnGWSBKXstJcqYtwPTPEZBQ==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "100000000"
},
"timestamp" : "1614955693253",
"version" : 2,
"issue" : {
"name" : "test",
"description" : "",
"amount" : "1000",
"decimals" : 0,
"reissuable" : true,
"script" : ""
}
},
"proofs" : [ "iPmPbzPN9tff59mPowWT2zFocMVp4IKxZhGHQfisrQLrNw1zRmGBUuL34T6AgYmvKuPuL38TWd4VMBUPsSmWDQ==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "1000000"
},
"timestamp" : "1614955693254",
"version" : 2,
"reissue" : {
"assetAmount" : {
"assetId" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"amount" : "1000"
},
"reissuable" : true
}
},
"proofs" : [ "41dTNu6FK52a0aWIo0iHQ7F2qJteanKBVdyrD3PJC//xOr5zSWMv+JZ9BsJRs1INQGr0+nLVAnvoYq/aFdb1Cg==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "3000000"
},
"timestamp" : "1614955693255",
"version" : 1,
"dataTransaction" : {
"data" : [ {
"key" : "test",
"stringValue" : "test"
} ]
}
},
"proofs" : [ "ryDXoAbjbOvLZasQ6/QE+9ewT2D009y8NA5qJQbA/nxS+QHCSj6CVHvVaoagSwykAujIn9FiA3tY4nSqEjX3AA==" ]
} ]
},
"signature" : "GlRrocxMSmUugmNdtVXueL/5gKNxoLQEXVgrtTD8sXHAzM4s9lpiIGLJ0Kajwvq8jS1isxpgkBRPnCSo/t4cCw==",
"totalBlockId" : "PM99HiRDmeepqQ9ezrTjs85WnjTavOuTfC84X7mdL9IHEI9dMdZ43JXQCYHFoy9ul9RLIsUL/vtwaFt1FeIODA=="
},
"updatedTransactionsRoot" : ""
},
"transactionIds" : [ "pRhzG3hnik7QM0SBcSUJeUUASaqCrJoX+nFzY+qydE0=", "egBkLVBeTLm4tPaPhuo6SkAFYY35TWFIGQFn5K4EGp4=", "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=", "Ya9WrfvwSsxRzgmvrbf4t4S+k6SrTuesJ8MPJNf148w=", "Ht2ILo1jmsy1Do8AdwMtFb3rAzybI43bNP62e3nPkws=" ],
"transactionsMetadata" : [ {
"transfer" : {
"recipientAddress" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME="
}
}, {
"leaseMeta" : {
"recipientAddress" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME="
}
}, { }, { }, { } ],
"stateUpdate" : {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001242400000"
},
"amountBefore" : "10000001200000000"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ ],
"assets" : [ ],
"individualLeases" : [ ]
},
"transactionStateUpdates" : [ {
"balances" : [ {
"address" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"amountAfter" : {
"assetId" : "",
"amount" : "100000000"
},
"amountBefore" : "0"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001141400000"
},
"amountBefore" : "10000001242400000"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ ],
"assets" : [ ],
"individualLeases" : [ ]
}, {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001140400000"
},
"amountBefore" : "10000001141400000"
} ],
"leasingForAddress" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"inAfter" : "0",
"outAfter" : "1000000000",
"inBefore" : "0",
"outBefore" : "0"
}, {
"address" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"inAfter" : "1000000000",
"outAfter" : "0",
"inBefore" : "0",
"outBefore" : "0"
} ],
"dataEntries" : [ ],
"assets" : [ ],
"individualLeases" : [ {
"leaseId" : "egBkLVBeTLm4tPaPhuo6SkAFYY35TWFIGQFn5K4EGp4=",
"statusAfter" : "ACTIVE",
"amount" : "1000000000",
"sender" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"recipient" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"originTransactionId" : "egBkLVBeTLm4tPaPhuo6SkAFYY35TWFIGQFn5K4EGp4="
} ]
}, {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001040400000"
},
"amountBefore" : "10000001140400000"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"amount" : "1000"
},
"amountBefore" : "0"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ ],
"assets" : [ {
"after" : {
"assetId" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"issuer" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"decimals" : 0,
"name" : "test",
"description" : "",
"reissuable" : true,
"volume" : "1000",
"sponsorship" : "0",
"nft" : false,
"lastUpdated" : 2,
"safeVolume" : "A+g="
}
} ],
"individualLeases" : [ ]
}, {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001039400000"
},
"amountBefore" : "10000001040400000"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"amount" : "2000"
},
"amountBefore" : "1000"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ ],
"assets" : [ {
"before" : {
"assetId" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"issuer" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"decimals" : 0,
"name" : "test",
"description" : "",
"reissuable" : true,
"volume" : "1000",
"sponsorship" : "0",
"nft" : false,
"lastUpdated" : 2,
"safeVolume" : "A+g="
},
"after" : {
"assetId" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"issuer" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"decimals" : 0,
"name" : "test",
"description" : "",
"reissuable" : true,
"volume" : "2000",
"sponsorship" : "0",
"nft" : false,
"lastUpdated" : 2,
"safeVolume" : "B9A="
}
} ],
"individualLeases" : [ ]
}, {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001036400000"
},
"amountBefore" : "10000001039400000"
} ],
"leasingForAddress" : [ ],
"dataEntries" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"dataEntry" : {
"key" : "test",
"stringValue" : "test"
},
"dataEntryBefore" : {
"key" : "test"
}
} ],
"assets" : [ ],
"individualLeases" : [ ]
} ]
},
"referencedAssets" : [ {
"id" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"decimals" : 0,
"name" : "test"
} ]
}
# Rollback: откат блока или микроблока
Поля сообщения:
Имя поля | Тип | Описание |
---|---|---|
type | RollbackType | Тип сообщения: BLOCK — откат блока, MICROBLOCK — откат микроблока |
removed_transaction_ids | repeated bytes | ID транзакций, которые были удалены в результате отката |
removed_blocks | repeated Block | Блоки, которые были удалены в результате отката. В случае отката микроблока — пустой массив |
rollback_state_update | StateUpdate | Изменения состояния блокчейна, которые произошли в результате отката (обратные изменениям, порожденным транзакциями и блоками/микроблоками). См. StateUpdate ниже |
deactivated_features | repeated int32 | Номера фич, активация которых отменена в результате отката |
Примеры:
Откат блока
{
"id" : "fJP16HbHyQ2Bib7fEUoZAS9Hm/IjCprhYxa3XuYKdY+7No72rCHtoXgInd3Pn9WMS3k9KvJMRMZbJTeYDdz0AA==",
"height" : 1,
"rollback" : {
"type" : "BLOCK",
"removedTransactionIds" : [ "Ht2ILo1jmsy1Do8AdwMtFb3rAzybI43bNP62e3nPkws=", "Ya9WrfvwSsxRzgmvrbf4t4S+k6SrTuesJ8MPJNf148w=", "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=", "egBkLVBeTLm4tPaPhuo6SkAFYY35TWFIGQFn5K4EGp4=", "pRhzG3hnik7QM0SBcSUJeUUASaqCrJoX+nFzY+qydE0=" ],
"removedBlocks" : [ {
"header" : {
"chainId" : 84,
"reference" : "fJP16HbHyQ2Bib7fEUoZAS9Hm/IjCprhYxa3XuYKdY+7No72rCHtoXgInd3Pn9WMS3k9KvJMRMZbJTeYDdz0AA==",
"baseTarget" : "60",
"generationSignature" : "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
"featureVotes" : [ ],
"timestamp" : "1614955695404",
"version" : 3,
"generator" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"rewardVote" : "-1",
"transactionsRoot" : ""
},
"signature" : "PM99HiRDmeepqQ9ezrTjs85WnjTavOuTfC84X7mdL9IHEI9dMdZ43JXQCYHFoy9ul9RLIsUL/vtwaFt1FeIODA==",
"transactions" : [ {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "1000000"
},
"timestamp" : "1614955693251",
"version" : 1,
"transfer" : {
"recipient" : {
"publicKeyHash" : "PTrYhPoEKSe51sN99wr1wL2VFsU="
},
"amount" : {
"assetId" : "",
"amount" : "100000000"
},
"attachment" : ""
}
},
"proofs" : [ "c7gEcrOqeKhyJgdY0HO6lmp9WCCHJTMjL0IZhehtTvRIFMZWGPb5YOTumytK3dGi1vORxvw1UmBNioLxJBdSAw==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "1000000"
},
"timestamp" : "1614955693252",
"version" : 2,
"lease" : {
"recipient" : {
"publicKeyHash" : "PTrYhPoEKSe51sN99wr1wL2VFsU="
},
"amount" : "1000000000"
}
},
"proofs" : [ "sTTAbbdtEFRbwqlly2fc16oWpu5+hJN5am2AQvz5gix162EEepo/SqoTkIjMJ3OgnGWSBKXstJcqYtwPTPEZBQ==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "100000000"
},
"timestamp" : "1614955693253",
"version" : 2,
"issue" : {
"name" : "test",
"description" : "",
"amount" : "1000",
"decimals" : 0,
"reissuable" : true,
"script" : ""
}
},
"proofs" : [ "iPmPbzPN9tff59mPowWT2zFocMVp4IKxZhGHQfisrQLrNw1zRmGBUuL34T6AgYmvKuPuL38TWd4VMBUPsSmWDQ==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "1000000"
},
"timestamp" : "1614955693254",
"version" : 2,
"reissue" : {
"assetAmount" : {
"assetId" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"amount" : "1000"
},
"reissuable" : true
}
},
"proofs" : [ "41dTNu6FK52a0aWIo0iHQ7F2qJteanKBVdyrD3PJC//xOr5zSWMv+JZ9BsJRs1INQGr0+nLVAnvoYq/aFdb1Cg==" ]
}, {
"transaction" : {
"chainId" : 84,
"senderPublicKey" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"fee" : {
"assetId" : "",
"amount" : "3000000"
},
"timestamp" : "1614955693255",
"version" : 1,
"dataTransaction" : {
"data" : [ {
"key" : "test",
"stringValue" : "test"
} ]
}
},
"proofs" : [ "ryDXoAbjbOvLZasQ6/QE+9ewT2D009y8NA5qJQbA/nxS+QHCSj6CVHvVaoagSwykAujIn9FiA3tY4nSqEjX3AA==" ]
} ]
} ],
"rollbackStateUpdate" : {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000000600000000"
},
"amountBefore" : "10000001036400000"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"amount" : "0"
},
"amountBefore" : "2000"
}, {
"address" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"amountAfter" : {
"assetId" : "",
"amount" : "0"
},
"amountBefore" : "100000000"
} ],
"leasingForAddress" : [ {
"address" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"inAfter" : "0",
"outAfter" : "0",
"inBefore" : "1000000000",
"outBefore" : "0"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"inAfter" : "0",
"outAfter" : "0",
"inBefore" : "0",
"outBefore" : "1000000000"
} ],
"dataEntries" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"dataEntry" : {
"key" : "test"
},
"dataEntryBefore" : {
"key" : "test",
"stringValue" : "test"
}
} ],
"assets" : [ {
"before" : {
"assetId" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"issuer" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"decimals" : 0,
"name" : "test",
"description" : "",
"reissuable" : true,
"volume" : "2000",
"sponsorship" : "0",
"nft" : false,
"lastUpdated" : 2,
"safeVolume" : "B9A="
}
} ],
"individualLeases" : [ {
"leaseId" : "egBkLVBeTLm4tPaPhuo6SkAFYY35TWFIGQFn5K4EGp4=",
"statusAfter" : "INACTIVE",
"amount" : "1000000000",
"sender" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"recipient" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"originTransactionId" : "egBkLVBeTLm4tPaPhuo6SkAFYY35TWFIGQFn5K4EGp4="
} ]
}
},
"referencedAssets" : [ {
"id" : "OaYhGK7uhe44lfBbsNswXc3fmO0luXGwQjVmBAXvqDc=",
"decimals" : 0,
"name" : "test"
} ]
}
Откат микроблока
{
"id" : "EmnPnXsOTq90SzwR3Qa0IsWhw4CmZKdgLsbfEa9TbYv/FGCK7dHFn+j2V8raFpwIzawihhLO5WJRDN+8EP/jBg==",
"height" : 2,
"rollback" : {
"type" : "MICROBLOCK",
"removedTransactionIds" : [ "Hfg/QwbcdGzIOSl6U0FXj/aD4nDYUhJge7FrOo6H+yc=", "i7r7ySkIkiL6hiRIDuYAroH7sd8ottXj1dryf6n/vdI=", "Eg82h+UU/rRKorf8f08HeKeoN4W431XsEJcxxJK+ZNc=", "pdjI2EDDWvIUi/mCJOGtR4AGVOmfOqkPpuuwskJjR/I=", "UbF1cV8thQ7koJzBOAqslD4wrtq7sCJAoJjBI5srLyo=" ],
"removedBlocks" : [ ],
"rollbackStateUpdate" : {
"balances" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "",
"amount" : "10000001200000000"
},
"amountBefore" : "10000001036400000"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"amountAfter" : {
"assetId" : "Eg82h+UU/rRKorf8f08HeKeoN4W431XsEJcxxJK+ZNc=",
"amount" : "0"
},
"amountBefore" : "2000"
}, {
"address" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"amountAfter" : {
"assetId" : "",
"amount" : "0"
},
"amountBefore" : "100000000"
} ],
"leasingForAddress" : [ {
"address" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"inAfter" : "0",
"outAfter" : "0",
"inBefore" : "1000000000",
"outBefore" : "0"
}, {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"inAfter" : "0",
"outAfter" : "0",
"inBefore" : "0",
"outBefore" : "1000000000"
} ],
"dataEntries" : [ {
"address" : "AVQv1P2H4On4q9JvwDzjIpknHO4wLHCiOl4=",
"dataEntry" : {
"key" : "test"
},
"dataEntryBefore" : {
"key" : "test",
"stringValue" : "test"
}
} ],
"assets" : [ {
"before" : {
"assetId" : "Eg82h+UU/rRKorf8f08HeKeoN4W431XsEJcxxJK+ZNc=",
"issuer" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"decimals" : 0,
"name" : "test",
"description" : "",
"reissuable" : true,
"volume" : "2000",
"sponsorship" : "0",
"nft" : false,
"lastUpdated" : 2,
"safeVolume" : "B9A="
}
} ],
"individualLeases" : [ {
"leaseId" : "i7r7ySkIkiL6hiRIDuYAroH7sd8ottXj1dryf6n/vdI=",
"statusAfter" : "INACTIVE",
"amount" : "1000000000",
"sender" : "eYy9ZNeMSg+6M4sqY0ljSUDcTltgHbECngLEHg/gVnk=",
"recipient" : "AVQ9OtiE+gQpJ7nWw333CvXAvZUWxetoaME=",
"originTransactionId" : "i7r7ySkIkiL6hiRIDuYAroH7sd8ottXj1dryf6n/vdI="
} ]
}
},
"referencedAssets" : [ {
"id" : "Eg82h+UU/rRKorf8f08HeKeoN4W431XsEJcxxJK+ZNc=",
"decimals" : 0,
"name" : "test"
} ]
}
# StateUpdate
Изменения состояния блокчейна, порожденные транзакцией, блоком, микроблоком или откатом.
В отличие от транзакций, адреса аккаунтов в StateUpdate
представлены полностью, включая тип сущности, байт сети и контрольную сумму. См. раздел Бинарный формат адреса.
# Изменения балансов аккаунтов
Имя поля | Тип | Описание |
---|---|---|
balances.address | bytes | Адрес |
balances.amount_after | Amount | Новый баланс |
balances.amount_before | int64 | Прежний баланс |
# Изменения лизинговых балансов аккаунта
Имя поля | Тип | Описание |
---|---|---|
leasing_for_address.address | bytes | Адрес |
leasing_for_address.in_after | int64 | Новая сумма полученных лизингов |
leasing_for_address.out_after | int64 | Новая сумма отправленных лизингов |
leasing_for_address.in_before | int64 | Прежняя сумма полученных лизингов |
leasing_for_address.out_before | int64 | Прежняя сумма отправленных лизингов |
# Изменения записей в хранилищах данных
Имя поля | Тип | Описание |
---|---|---|
data_entries.address | bytes | Адрес |
data_entries.data_entry | DataTransactionData.DataEntry | Запись с новым значением |
data_entries.data_entry_before | DataTransactionData.DataEntry | Запись с прежним значением |
# Изменения лизингов
Имя поля | Тип | Описание |
---|---|---|
individual_leases.lease_id | bytes | Идентификатор лизинга |
individual_leases.status_after | LeaseStatus | Новый статус лизинга: ACTIVE или INACTIVE |
individual_leases.amount | int64 | Сумма лизинга |
individual_leases.sender | bytes | Адрес отправителя лизинга |
individual_leases.recipient | bytes | Адрес получателя лизинга |
individual_leases.origin_transaction_id | bytes | Транзакция, породившая создание, изменение или отмену лизинга |
# Изменения скриптов, установленных на аккаунтах
Имя поля | Тип | Описание |
---|---|---|
scripts.address | bytes | Адрес аккаунта |
scripts.before | bytes | Новый скрипт |
scripts.after | bytes | Прежний скрипт |
# Удаление псевдонимов
Имя поля | Тип | Описание |
---|---|---|
deleted_aliases | repeated string | Псевдонимы, удаленные в результате отката |
# Изменения параметров токена
Имя поля | Тип | Описание |
---|---|---|
assets.before | AssetDetails | Прежние параметры токена. В случае выпуска токена — пустое значение. См. AssetDetails ниже |
assets.after | AssetDetails | Новые параметры токена. В случае отката блока/микроблока, породившего выпуск токена, — пустое значение |
# AssetDetails
Имя поля | Тип | Описание |
---|---|---|
asset_id | bytes | ID токена |
issuer | bytes | Адрес, выпустивший токен |
decimals | int32 | Количество знаков после запятой |
name | string | Название токена |
description | string | Описание токена |
reissuable | bool | Флаг возможности довыпуска |
volume | int64 | Общее количество токена, в атомарных единицах |
script_info.script | bytes | Скомпилированный скрипт ассета |
script_info.complexity | int64 | Сложность скрипта ассета |
sponsorship | int64 | Если токен является спонсорским ассетом — количество ассета, эквивалентное 0,001 WAVES, в атомарных единицах. Иначе — пустое значение |
nft | bool | Признак того, что токен является NFT |
last_updated | int32 | Высота, на которой произошло последнее изменение параметров токена |
safe_volume | bytes | Поле связано с прошлым поведением в блокчейне, когда можно было довыпустить ассет таким образом, чтобы общее количество превысило максимальное значение int64. Содержит точное количество токена. Можно игнорировать, если клиент не нуждается в такой точности. Кодировка: как Java BigInteger, см. https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html#toByteArray() |
# AssetInfo
Имя поля | Тип | Описание |
---|---|---|
id | bytes | ID токена |
decimals | int32 | Количество знаков после запятой |
name | string | Название токена |
# TransactionMetadata
Дополнительная информация о транзакции.
В отличие от транзакций, адреса аккаунтов в TransactionMetadata
представлены полностью, включая тип сущности, байт сети и контрольную сумму. См. раздел Бинарный формат адреса.
# Для транзакции вызова скрипта
Имя поля | Тип | Описание |
---|---|---|
d_app_address | bytes | Адрес dApp |
function_name | string | Имя вызываемой функции |
arguments | repeated InvokeScriptResult.Call.Argument | Аргументы функции |
payments | repeated Amount | Приложенные к транзакции платежи |
result | InvokeScriptResult | Результаты действий, выполненных вызываемой функцией |
⚠️ Если вызываемая функция выполняет вызов dApp из dApp, InvokeScriptResult
содержит сообщение Invocation
с дополнительной информацией о вложенном вызове. Invocation
, в свою очередь, также содержит InvokeScriptResult
. Таким образом, если требуется извлечь дополнительную информацию о каждом действии, выполненном каждой из функций, вызываемых в транзакции, необходимо проанализировать все InvokeScriptResult
рекурсивно.
Пример обработки вложенных вызовов (TypeScript)
const processInvokeResult = ({
dApp,
call,
stateChanges,
payments,
}: _waves_InvokeScriptResult_Invocation__Output): InvokeScript[] => {
const script: InvokeScript = {
id,
timestamp,
dApp: crypto.base58Encode(dApp),
account,
arguments: call.args,
call: {
function: call.function,
},
sequence: this.sequence++,
payments: R.map(toAmount, payments),
transfers: R.map(toTransfer, stateChanges.transfers),
issues: R.map(toAmount, stateChanges.issues),
reissues: R.map(toAmount, stateChanges.reissues),
stateChanges: R.map(toStateChange, stateChanges.data),
assets,
};
return R.flatten([
script,
stateChanges.invokes.map(processInvokeResult),
]);
};
# Для транзакции перевода
Имя поля | Тип | Описание |
---|---|---|
recipient_address | bytes | Адрес получателя |
# Для транзакции массового перевода
Имя поля | Тип | Описание |
---|---|---|
recipient_addresses | repeated bytes | Адреса получателей |
# Для транзакции лизинга
Имя поля | Тип | Описание |
---|---|---|
recipient_address | bytes | Адрес получателя |
# Переход с предыдущих версий
Как правило, Blockchain Updates поддерживает обратную совместимость. Однако, чтобы начать использовать поля, добавленные в новой версии, необходимо выполнить миграцию:
Заново получите историю изменений:
1.1. Удалите файлы базы данных: они находятся в каталоге, указанном в настройке waves.db.directory (по умолчанию — в подкаталоге
data
основного каталога ноды).1.2. Удалите файлы расширения: они находятся в подкаталоге
blockchain-updates
основного каталога ноды.1.3. Загрузите или импортируйте блокчейн одним из способов, указанных в подразделе Запуск ноды с расширением выше.
Скачайте обновленные protobuf-схемы и сгенерируйте клиентские заглушки, см. Генерация клиента выше. Мигрируйте код своего приложения на новые заглушки.
# Отладка с помощью gRPCurl
gRPCurl — инструмент командной строки для взаимодействия с серверами gRPC, аналог curl
для gRPC. С помощью gRPCurl вы можете без написания кода сделать запрос к Blockchain Updates и получить данные в терминале.
Использование gRPCurl:
Получить список сервисов
Пример запроса:
grpcurl -plaintext 127.0.0.1:6881 list
Пример ответа:
grpc.reflection.v1alpha.ServerReflection waves.events.grpc.BlockchainUpdatesApi
Получить список функций сервиса
grpcurl -plaintext 127.0.0.1:6881 describe waves.events.grpc.BlockchainUpdatesApi
waves.events.grpc.BlockchainUpdatesApi is a service: service BlockchainUpdatesApi { rpc GetBlockUpdate ( .waves.events.grpc.GetBlockUpdateRequest ) returns ( .waves.events.grpc.GetBlockUpdateResponse ); rpc GetBlockUpdatesRange ( .waves.events.grpc.GetBlockUpdatesRangeRequest ) returns ( .waves.events.grpc.GetBlockUpdatesRangeResponse ); rpc Subscribe ( .waves.events.grpc.SubscribeRequest ) returns ( stream .waves.events.grpc.SubscribeEvent ); }
Получить описание сообщения
grpcurl -plaintext 127.0.0.1:6881 describe waves.events.grpc.GetBlockUpdatesRangeRequest
waves.events.grpc.GetBlockUpdatesRangeRequest is a message: message GetBlockUpdatesRangeRequest { int32 from_height = 1; int32 to_height = 2; }
Выполнить запрос к BlockchainUpdates
Укажите в запросе параметр
-d
и аргументы в формате JSON.grpcurl -plaintext \ -d '{ "from_height": 3685233, "to_height": 3685233 }'' \ 127.0.0.1:6881 waves.events.grpc.BlockchainUpdatesApi/GetBlockUpdatesRange
{ "update": { "id": "VQzjW9JuZTDIpxsw+bfeP3Aw038bdtJBsWYk6M9XgG8=", "height": 3685233, "append": { "block": { ... }
Если вызвать функцию Subscribe
без указания параметра to_height
, возвращается бесконечный поток сообщений об изменениях по мере их появления.
⚠️ Все массивы байтов в ответе представлены в кодировке base64, в том числе адреса, идентификаторы ассетов и другие данные, которые в REST API ноды представлены в base58.