7 Создание встроенных вызовов для действий
В этом разделе приведены инструкции по созданию в контракте встроенных вызовов (inline) для действий - операций вида action
. Операция (action) может быть вызвана другой операцией этого же контракта. Примеры выполнения данных инструкций показаны на контракте адресной книги addressbook
, создание которого изложено в разделе 5 настоящего руководства.
7.1 Добавить cyber.code для разрешения на действие Чтобы действие, находящееся в контракте адресной книги могло вызывать другое действие, необходимо аккаунту контракта дать на это разрешение. Для этого необходимо добавить cyber.code, исполнив:
Полномочия cyber.code
позволяют контракту выполнять встроенные вызовы операций вида action
.
7.2 Отправить уведомление Открыть контракт addressbook.cpp и создать дополнительное действие, которое будет вести себя как транзакция, которая получает уведомление. Для этого можно создать вспомогательную функцию в классе адресной книги.
Эта функция будет принимать только имя и строку.
7.3 Создать копию операции и переслать ее отправителю в качестве уведомления
Создать копию транзакции, в которой загружено действие, и отправить эту копию пользователю, чтобы ее можно было считать принятой. Для этого можно использовать метод require_recipient
. Вызов require_recipient
добавляет аккаунт в набор require_recipient
и гарантирует, что данные аккаунты получают уведомление о выполняемом действии. Уведомление похоже на отправку аккаунтам «точной копии» действия.
Чтобы исключить возможность несанкционированного вызова этой функции сторонним пользователем, необходимо требовать авторизацию для выполнения действия. При этом авторизация должна предоставляться самим контрактом. Для этого нужно добавить метод get_self()
для авторизации самого себя.
При попытке вызова этой функции кем-либо, кроме самого контракта, будет сгенерировано исключение.
7.4 Уведомить вспомогательную функцию об отправке вызываемого действия Поскольку с помощью встроенного вызова операция (action) может вызываться неоднократно, требуется создание вспомогательной функции для повторного использования кода с целью уменьшения создания дублирующего кода.
Внутри этого помощника необходимо создать действие и отправить его.
7.5 Создать действие-конструктор
7.5.1 Изменить контракт addressbook
, чтобы отправлять квитанции пользователю при каждом вызове действия контракта. При этом нужно учитывать случай отсутствия записи в таблице.
Сохранить этот объект в качестве уведомления notification
для действия.
Требуется, чтобы в действии-конструкторе были следующие параметры:
структура уровня разрешения
permission_level
;контракт для вызова (инициализируется с использованием типа
eosio::name
);действие (инициализируется с использованием типа
eosio::name
);данные, передаваемые действию.
7.5.2 Инициализировать структуру разрешения.
В контракте разрешение должно быть авторизовано аккаунтом active
контракта с помощью get_self()
. Для использования встроенных «активных» полномочий необходимо, чтобы контракт предоставил активные полномочия коду cyber.code
.
7.5.3 Задействовать get_self()
.
Поскольку вызываемое действие находится непосредственно в контракте, необходимо использовать get_self()
. Также в нем будет работать адресная книга "addressbook"_n
. Использование get_self()
является наиболее приемлемым вариантом, так как контракт не будет работать в случае развертывания его под другим именем аккаунта.
7.5.4 Задействовать оператор _n
. Действие notify
было предварительно определено для вызова этого встроенного действия. Поэтому здесь необходимо использовать оператор _n
.
7.5.5 Определить данные для передачи действию. Функция notify
принимает два параметра — имя и строку. Действие-конструктор ожидает данные как тип bytes
, поэтому необходимо использовать метод make_tuple
, доступный через библиотеку std C++
. Передаваемые данные зависят от их позиций и определяются порядком параметров, принимаемых вызываемым действием.
Передать переменную user
, указанную в качестве параметра действия upsert()
. Объединить строку, содержащую имя пользователя, и включить сообщение message
для передачи уведомления notify
в действие.
7.5.6 Отправить действие, используя метод send
.
7.6 Вызвать вспомогательную функцию и ввести соответствующее сообщение
К этому моменту помощник вспомогательная функция определена и может быть вызвана. Есть три события, когда может быть вызван новый помощник уведомлений notify
:
После добавления контрактом новой записи:
send_summary (user, «успешно добавлена запись в адресную книгу»)
.После изменения контрактом существующей записи:
send_summary (user, «успешно изменена запись в адресной книге»)
.После удаления контрактом существующей записи:
send_summary (user, «успешно удалена запись из адресной книги»)
.
7.7 Внести изменение в макрос EOSIO_DISPATCH
Новое действие уведомления notify
было добавлено в контракт, поэтому необходимо обновить макрос EOSIO_DISPATCH, чтобы включить это действие стало доступным для его выполнения извне (например, внешней транзакцией, вызовом операции (метода, действия). Это гарантирует, что действие notify
не будет исключено оптимизатором eosio.cdt
.
Контракт addressbook
будет иметь следующий вид:
7.8 Перекомпилировать и отредактировать ABI-файл
Перекомпилировать контракт с флагом --abigen
, поскольку в контракт были внесены изменения, влияющие на ABI.
Контракты на EOSIO могут быть обновлены, поэтому данный контракт может быть перенесен с изменениями.
В результате выполнения команды должна появиться информация вида:
7.9 Тестирование
В предыдущем разделе запись адресной книги пользователя alice
была удалена на этапе тестирования, поэтому при вызове upsert
будет запущено встроенное действие.
Исполнить:
В результате выполнения команды должна появиться информация вида:
Текст (внизу выдачи) сообщает, что адресная книга уведомляет (addressbook::notify
) пользователя alice
о транзакции.
Для просмотра выполненных действий, относящихся к пользователю alice
можно использовать cleos get actions
.
Результатом выполнения команды будет информация вида:
Last updated