Узнайте, насколько легко можно взаимодействовать с блокчейном с помощью библиотеки.

Вступление

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