Узнайте, насколько легко можно взаимодействовать с блокчейном с помощью библиотеки.
Вступление
Эта статья представляет собой очень прагматичное пошаговое руководство, цель которого - показать (в частности) Java-разработчикам очень простой способ взаимодействия со смарт-контрактом блокчейна.
Требования
Мы собираемся использовать блокчейн Tezos. И, чтобы заставить наш Java-код взаимодействовать с существующим, развернутым смарт-контрактом, нам понадобится библиотека TezosJ от TezosRio . Существует две версии этой библиотеки: одна написана специально для разработки приложений для Android (TezosJ_SDK), а другая предназначена для общих приложений Java, написанных с помощью Eclipse IDE (TezosJ_plainJava), которые мы собираемся здесь использовать. . Нет необходимости загружать весь исходный код библиотеки. Достаточно просто JAR-файла v1.1.0. В качестве нашей IDE разработки будет выбрано Eclipse.
Цель
Контракт, который мы собираемся назвать, представляет собой простой реестр базы клиентов, который можно найти в тестовой сети Tezos по следующему адресу:
KT18pK2MGrnTZqyTafUe1sWp2ubJ75eYT86t
Вы можете легко проверить детали контракта через один из обозревателей блоков Tezos, например, Tezblock. Или с помощью инструмента better-call.dev. Еще один вариант - проверить договор с SmartPy explorer. Не забудьте указать сервер testnet, например https://tezos-dev.cryptonomic-infra.tech.
Наш смарт-контракт называется «Клиенты» и имеет четыре точки входа (или метода): addCustomer, removeCustomer, transfer и updateBalance. В основном вставляйте, удаляйте, переводите средства и обновляйте. Ничего особенного. Это было создано только в образовательных целях. Что он делает, так это поддерживает список «клиентов» в хранилище блокчейна Tezos.
Звонок
TezosJ, вероятно, является одним из самых простых способов вызова смарт-контракта Tezos, доступных в настоящее время. По сути, наш вызов может быть выполнен с помощью одной команды:
JSONObject jsonObject = wallet.callContractEntryPoint(wallet.getPublicKeyHash(), "KT18pK2MGrnTZqyTafUe1sWp2ubJ75eYT86t", amount, fee, "", "", "addCustomer", new String[]{"1000000", "123456789","Bob","98769985"});
Приведенный выше код добавляет нового клиента в базу, Боба, с балансом 10 центов, 123456789 в качестве идентификатора и 98769985 в качестве номера телефона. Это делается путем вызова метода callContractEntryPoint, который в основном требует тех же параметров, что и обычный метод Tezos .send (), но имеет некоторые дополнения: имя точки входа в контракт и String Массив, содержащий параметры ожидаемой точки входа (которые должны быть известны перед вызовом).
Пожалуйста, пошагово!
Если вы еще этого не сделали, скачайте и установите Eclipse. Открой это. Первый шаг - создать новый проект, выбрав опцию File- ›New-› Project, например:
Следующим шагом является выбор типа проекта: Выберите Gradle Project:
Задайте имя нового проекта «callSmartContract» и нажмите кнопку «Готово». Подождите, пока Eclipse построит файловую структуру проекта. Теперь мы собираемся создать класс Main, чтобы мы могли запустить и протестировать проект. Щелкните правой кнопкой мыши имя проекта callSmartContract и выберите New- ›Class:
Затем укажите «Main» в качестве имени нового класса и обязательно установите флажок создания «public void static Main (String args [])». Затем нажмите кнопку «Готово»:
Вы заметите, что был создан основной класс. Щелкните правой кнопкой мыши по основному классу и выберите «Запуск от имени› Java-приложение ». Это просто для настройки того, как запускается проект, когда мы нажимаем кнопку воспроизведения с этого момента:
В консоли вы увидите, что проект успешно запустился, но, конечно же, пока ничего не произошло. Вы увидите сообщение «прекращено»:
Теперь мы собираемся добавить файл JAR библиотеки TezosJ. Зайдите в репозиторий Tezos.Rio на github и скачайте файл tezosj-sdk-plain-java-1.1.0.jar
В проводнике файлов скопируйте файл tezosj-sdk-plain-java-1.1.0.jar (CTRL + C).
Вернитесь в Eclipse, щелкните имя проекта и Вставьте с помощью CTRL + V.
Файл будет добавлен в структуру проекта:
Следующим шагом является добавление JAR в путь сборки проекта. Щелкните правой кнопкой мыши файл библиотеки в проводнике проекта и выберите опцию Build Path- ›Add to Build Path (или Build Path -› Configure Build Path):
Выберите файл библиотеки и нажмите кнопку «Применить и закрыть»:
Теперь, когда у нас все подготовлено, давайте сначала создадим кошелек Tezos:
Красный значок «X» выше (слева) напоминает нам, что нам нужно импортировать классы, чтобы наш код понимал, что такое TezosWallet:
Теперь добавьте вывод консоли, чтобы проверить, успешно ли создается наш кошелек. Мы собираемся распечатать некоторую информацию о нем: хэш открытого ключа кошелька (адрес Tezos), его мнемонические слова и текущий баланс. После добавления команд System.out.println запустите проект, и вы получите что-то вроде этого (проверьте консоль):
Ok! У нас есть функциональный кошелек Tezos. Теперь мы можем позвонить в смарт-контракт клиентов Tezos.
Немного о контракте
Смарт-контракт Клиенты, который мы собираемся использовать, был создан и развернут в тестовой сети блокчейна Tezos с использованием онлайн-среды IDE SmartPy.io. Проверьте исходный код контракта ниже:
# Imports the SmartPy library. import smartpy as sp # Defines the Customer class and its constructor. class Customer(sp.Contract): def __init__(self): self.init(customers = sp.map()) # Defines the addCustomer entry point. @sp.entry_point def addCustomer(self, params): # Verifies if mandatory fields have values. sp.verify(params.id != "") sp.verify(params.name != "") sp.verify(params.phoneNumber > 0) # Declare the parameter types. sp.set_type(params.id, sp.TString) sp.set_type(params.name, sp.TString) sp.set_type(params.phoneNumber, sp.TNat) sp.set_type(params.balance, sp.TMutez) # Defines a customer record, so we can add to a Map. customer = sp.record(name=params.name, phoneNumber=params.phoneNumber, balance=params.balance) # Adds the new customer record to a Map (that will reside in the contract's storage). self.data.customers[params.id] = customer # Defines the removeCustomer entry point. @sp.entry_point def removeCustomer(self, params): # Verifies if mandatory fields have values. sp.verify(params.id != "") # Declare the parameter types. sp.set_type(params.id, sp.TString) # Remove the customer from the Map. del self.data.customers[params.id] # Defines the updateBalance entry point. @sp.entry_point def updateBalance(self, params): # Verifies if mandatory fields have values. sp.verify(params.id != "") # Declare the parameter types. sp.set_type(params.id, sp.TString) sp.set_type(params.amount, sp.TMutez) # Updates the balance. self.data.customers[params.id].balance = params.amount # Defines the transfer entry point. @sp.entry_point def transfer(self, params): # Verifies if mandatory fields have values. sp.verify(params.idFrom != "") sp.verify(params.idTo != "") sp.verify(params.amount > sp.mutez(0) ) # Verifies if customer has enough funds to be transfered. sp.verify(params.amount <= self.data.customers[params.idFrom].balance ) # Declare the parameter types. sp.set_type(params.idFrom, sp.TString) sp.set_type(params.idTo, sp.TString) sp.set_type(params.amount, sp.TMutez) # Updates the balance. self.data.customers[params.idFrom].balance = self.data.customers[params.idFrom].balance - params.amount self.data.customers[params.idTo].balance = self.data.customers[params.idTo].balance + params.amount # Creates the test scenario, to simulate a contract call in SmartPy.io IDE. @sp.add_test(name = "Customers") def test(): # Instantiate a contract inherited from the Customer Class. myCustomersContract = Customer() # Defines a test scenario. scenario = sp.test_scenario() # Adds the contract to the test scenario. scenario += myCustomersContract # Inserts the customers, calling the contract's addCustomer entry point. # This customers will reside in the contract's storage. scenario += myCustomersContract.addCustomer(id="123456",name="Daniel",phoneNumber=99984537,balance=sp.mutez(0)) scenario += myCustomersContract.addCustomer(id="345678",name="Eleonor",phoneNumber=85375677,balance=sp.mutez(0)) scenario += myCustomersContract.addCustomer(id="678905",name="Fabian",phoneNumber=78655567,balance=sp.mutez(0)) # Removes a customer through its id number. scenario += myCustomersContract.removeCustomer(id="678905") # Updates a customer's balance. scenario += myCustomersContract.updateBalance(id="123456",amount=sp.mutez(10000000)) # Transfers funds from a customer to another. scenario += myCustomersContract.transfer(idFrom="123456", idTo="345678", amount=sp.mutez(5000000))
Исходный код контракта SmartPy был показан здесь только в иллюстративных целях, и нам не нужно компилировать и развертывать его снова. Он уже находится в тестовой сети блокчейна Tezos по адресу:
KT18pK2MGrnTZqyTafUe1sWp2ubJ75eYT86t
И… Действие!
Теперь у нас есть все, что нужно для вызова контракта из Java. Во-первых, мы собираемся добавить нового клиента, используя точку входа «addCustomer» в контракте. Давайте рассмотрим имя клиента «Боб», его идентификатор «98765» и номер телефона «99876787». У Боба будет баланс 10ꜩ (10.000.000 мутезов). Итак, наша команда вызова контракта будет такой:
JSONObject jsonObject = wallet.callContractEntryPoint(wallet.getPublicKeyHash(), "KT18pK2MGrnTZqyTafUe1sWp2ubJ75eYT86t", amount, fee, "", "", "addCustomer", new String[]{"1000000", "98765","Bob","99876787"});
Прежде всего, нам нужно сообщить TezosJ, что мы будем использовать тестовую сеть Tezos (где фактически публикуется контракт). Также нам нужно указать сумму транзакции и комиссию. Это делается с помощью кода Java ниже:
// Change wallet provider to use testnet. wallet.setProvider(“https://tezos-dev.cryptonomic-infra.tech"); // Sets amount and fee for the transaction. BigDecimal amount = new BigDecimal(“0”); BigDecimal fee = new BigDecimal(“0.1”); // Calls the contract entry point. JSONObject jsonObject = wallet.callContractEntryPoint(wallet.getPublicKeyHash(), “KT18pK2MGrnTZqyTafUe1sWp2ubJ75eYT86t”, amount, fee, “”, “”, “addCustomer”, new String[]{“1000000”, “98765”,”Bob”,”99876787"}); // Prints the operation hash in the console. String opHash = (String) jsonObject.get("result"); System.out.println("OpHash : " + opHash);
Скопируйте код и вставьте в наш основной класс, чтобы он оставался таким:
Обратите внимание, что для того, чтобы этот звонок сработал, вам сначала нужно пополнить и раскрыть свою учетную запись Tezos. Или вы можете получить такую ошибку:
There were errors: kind ‘branch’ id ‘proto.005-PsBabyM1.implicit.empty_implicit_contract’
Запускаем проект! Если все было настроено нормально, вы получите хэш операции, отображаемый в консоли:
Это означает, что мы успешно отправили транзакцию callContract в блокчейн тестовой сети Tezos (поскольку у нас есть хэш операции). Теперь давайте проверим, была ли транзакция принята блокчейном Tezos. Для этого мы воспользуемся проводником TezBlock. Откройте https://tezblock.io в предпочитаемом вами браузере и, прежде всего, в правом верхнем углу экрана смените mainnet на balylonnet (то же самое с тестовой сетью). Затем вставьте хэш операции, полученный в результате выполнения java, в поле поиска и нажмите клавишу Ввод:
Это покажет результаты нашего вызова контракта с деталями операции. Нажав «показать», вы сможете проверить параметры, которые были переданы из нашего кода Java в цепочку блоков Tezos:
Параметры:
Left (Left (Left (Pair (Pair (Pair 1000000 "98765") "Bob") 99876787)))
Это параметры в формате Micheline, сгенерированные нашим вызовом из приложения Java. Смарт-контракты Tezos при развертывании написаны на языке Майкельсона, и они ожидают, что параметры ввода будут отправлены в этом формате. Одним из преимуществ использования библиотеки TezosJ является то, что она генерирует параметры в формате Micheline на лету, и вам не нужно беспокоиться о том, как это делается.
Le Grand Finale
Теперь мы можем гарантировать, что контракт был правильно вызван, параметры были переданы и операция была принята блокчейном Tezos. Теперь последнее, что нам нужно сделать, это проверить, был ли новый клиент, Боб, помещен в хранилище контракта. Для этого воспользуемся инструментом better-call.dev. Просто откройте свой браузер и укажите его на https://better-call.dev. Введите адрес нашего клиентского договора (KT18pK2MGrnTZqyTafUe1sWp2ubJ75eYT86t) в поле поиска, измените сеть на babylonnet и нажмите ввод:
Результатом будет список всех операций, когда-либо отправленных на адрес контракта, а также текущее состояние хранилища контракта. Здесь вы сможете проверить параметры, которые вы передали с Java, и правильно ли они сохранены в хранилище:
Идти дальше
Вы можете попробовать другие точки входа контракта, такие как removeCustomer, transfer и updateBalance. Не забывайте всегда проверять количество параметров, необходимых для каждой точки входа.
Если при запуске кода вы получите ошибку Java, это означает, что транзакция не была отправлена. В этом случае вам необходимо повторно проверить свои параметры, порядок, баланс вашего счета, комиссию и сеть (основная или тестовая), в которой вы работаете. Также проверьте параметры gasLimit и storageLimit.
С другой стороны, если вы когда-нибудь получите хэш операции, это означает, что ваше приложение Java успешно отправило транзакцию в цепочку блоков. Но, тем не менее, вы должны проверить возможные ошибки, связанные с блокчейном. В этом случае, когда вы проверяете с помощью TezBlock explorer, он покажет ошибки с фоном цвета лосося, что означает, что в контексте блокчейна произошло что-то не так (например, неправильное количество переданных параметров, неправильное форматирование параметра Micheline или даже недопустимые условия контракта - например, : вы позвонили в точку входа перевода, но у «от» клиента недостаточно средств для отправки).
Заключение
Разработчикам еще никогда не было так просто работать со смарт-контрактами на блокчейне. Tezos, в частности, предлагает множество отличных инструментов и огромное количество библиотек компьютерных языков, которые облегчают интеграцию с большинством систем. Библиотека TezosJ является новаторской, предлагая простой в использовании метод callContractEntryPoint, который на лету создает параметры в формате Micheline. В нем есть все инструменты, необходимые Java-разработчикам для успешной разработки приложений, которые беспрепятственно взаимодействуют с блокчейном.
Скачать полный код
Вы можете скачать здесь полный проект Eclipse, представленный в этой статье.