Узнайте, насколько легко можно взаимодействовать с блокчейном с помощью библиотеки.
Вступление
В своей прошлой статье я писал о вызове смарт-контракта, развернутого на блокчейне, из Java с помощью Eclipse. Пришло время перейти на мобильные устройства! В этом руководстве показано, как вызывать смарт-контракты прямо из среды разработки Android - Android Studio.
Требования
Мы собираемся использовать блокчейн Tezos. А чтобы заставить наш код Android Java взаимодействовать с существующим развернутым смарт-контрактом, нам понадобится библиотека TezosJ от TezosRio . Существует две версии этой библиотеки: одна написана специально для общих приложений Java, созданных с помощью Eclipse IDE (TezosJ_plainJava), а другая предназначена для разработки приложений для Android (TezosJ_SDK), которые мы собираемся использовать. здесь. Нет необходимости загружать весь исходный код библиотеки. Нам просто нужно вставить одну строку в раздел dependencies нашего файла build.gradle и voilà, мы готовы к работе. В качестве нашей IDE для разработки лучшим выбором будет Android Studio.
Цель
Контракт, который мы собираемся назвать, представляет собой простой реестр базы клиентов, который можно найти в тестовой сети 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 Массив, содержащий параметры ожидаемой точки входа (которые должны быть известны перед вызовом).
Пожалуйста, пошагово!
Если вы еще этого не сделали, скачайте и установите Android Studio. Открой это. Первый шаг - создать новый проект Android Studio, например:
Выберите Телефон и планшет в качестве типа проекта, затем нажмите Пустое действие:
Назовите свой проект smartContractCall и измените Язык на Java. Затем нажмите Готово:
Первое, что нам нужно сделать, это удалить android: allowBackup = ”true” из тега приложения в файле AndroidManifest.xml. Это очень важно, и если мы пропустим этот шаг, TezosJ_SDK не будет работать:
Пришло время добавить TezosJ_SDK в наш проект. Откройте файл build.gradle (Module: app). Перейдите в раздел зависимости и добавьте: реализацию ‘com.milfont.tezos: tezosj_android: 0.9.998’. Затем нажмите Синхронизировать сейчас (в правом верхнем углу окна):
Что касается конфигурации, мы почти закончили. Последний шаг - изменить minSdkVersion на 26 в том же файле. Затем снова Sync:
Все сделано! А теперь, когда у нас все подготовлено, давайте сначала создадим кошелек Tezos. В файле MainActivity метод onCreate поместите объявление, как показано ниже (не забудьте блок try-catch):
Теперь добавьте вывод Logcat, чтобы проверить, успешно ли создается наш кошелек. Мы собираемся распечатать некоторую информацию о нем: хэш открытого ключа кошелька (адрес Tezos), его мнемонические слова и текущий баланс:
После добавления команд Log.i () запустите проект, и вы получите что-то вроде этого (проверьте Logcat):
Мы смогли сгенерировать новый кошелек и получить его мнемонические слова. Но у нас произошла ошибка при попытке получить баланс кошелька из блокчейна. Это потому, что мы пытались получить доступ к Интернету напрямую в классе MainActivity, что запрещено в среде Android. Для этого урока давайте просто воспользуемся небольшим обходным путем. Поместите метод ниже в свой класс MainActivity:
public void enableStrictMode() { StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build(); StrictMode.setThreadPolicy(policy); }
И вызовите его из метода onCreate:
enableStrictMode();
Здесь строгий режим используется только в иллюстративных целях. Не рекомендуется напрямую выходить в Интернет через класс MainActivity (сделайте это в новом потоке):
Запустите проект еще раз, и теперь все будет работать правильно, и вы сможете правильно увидеть баланс кошелька в Logcat:
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
И… Действие!
Теперь у нас есть все, что нужно для вызова контракта с Android. Во-первых, мы собираемся добавить нового клиента, используя точку входа «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"); Log.i("output", "OpHash : " + opHash);
Скопируйте код и вставьте его в наш класс MainActivity, чтобы он оставался таким:
Обратите внимание, что для того, чтобы этот звонок сработал, вам сначала нужно внести средства и раскрыть свой аккаунт Tezos. Или вы можете получить такую ошибку:
There were errors: kind ‘branch’ id ‘proto.005-PsBabyM1.implicit.empty_implicit_contract’
Запускаем проект! Если все было настроено нормально, в результате вы получите хэш транзакции (здесь onuvzSRu9GiUBtPxEVf958jPUkG8NTxo7UHCYvFXKB8Chtci3Jm), показанный в LogCat:
Это означает, что мы успешно отправили транзакцию callContract в блокчейн тестовой сети Tezos (поскольку у нас есть хэш операции). Теперь давайте проверим, была ли транзакция принята блокчейном Tezos. Для этого мы воспользуемся проводником TezBlock. Откройте https://tezblock.io в предпочитаемом вами браузере и, прежде всего, в правом верхнем углу экрана смените mainnet на balylonnet (то же самое с тестовой сетью). Затем вставьте хэш операции, полученный в результате выполнения Java, в поле поиска и нажмите клавишу Ввод:
Это покажет результаты нашего вызова контракта с деталями операции. Нажав «показать», вы сможете проверить параметры, которые были переданы из нашего кода Java в цепочку блоков Tezos:
Параметры:
Left (Left (Left (Pair (Pair (Pair 1000000 "98765") "Bob") 99876787)))
Это параметры в формате Micheline, которые сгенерировал наш вызов из приложения Android. Смарт-контракты Tezos при развертывании написаны на языке Майкельсона, и они ожидают, что параметры ввода будут отправлены в этом формате. Одним из преимуществ использования библиотеки TezosJ является то, что она генерирует параметры в формате Micheline на лету, и вам не нужно беспокоиться о том, как это делается.
Le Grand Finale
Теперь мы можем гарантировать, что контракт был правильно вызван, параметры были переданы и операция была принята блокчейном Tezos. Теперь последнее, что нам нужно сделать, это проверить, был ли новый клиент, Боб, помещен в хранилище контракта. Для этого воспользуемся инструментом better-call.dev. Просто откройте свой браузер и укажите его на https://better-call.dev. Введите адрес нашего клиентского договора (KT18pK2MGrnTZqyTafUe1sWp2ubJ75eYT86t) в поле поиска, измените сеть на babylonnet и нажмите ввод:
Результатом будет список всех операций, когда-либо отправленных на адрес контракта, а также текущее состояние хранилища контракта. Здесь вы сможете проверить параметры, которые вы передали с Java, и правильно ли они сохранены в хранилище:
Идти дальше
Вы можете попробовать другие точки входа в контракт, такие как removeCustomer, transfer и updateBalance. Не забывайте всегда проверять количество параметров, необходимых для каждой точки входа.
Если при запуске кода вы получите ошибку Java, это означает, что транзакция не была отправлена. В этом случае вам необходимо повторно проверить свои параметры, порядок, баланс вашего счета, комиссию и сеть (основная или тестовая), в которой вы работаете. Также проверьте параметры gasLimit и storageLimit.
С другой стороны, если вы когда-нибудь получите хэш операции, это означает, что ваше приложение Android успешно отправило транзакцию в цепочку блоков. Но, тем не менее, вы должны проверить возможные ошибки, связанные с блокчейном. В этом случае, когда вы проверяете с помощью TezBlock explorer, он покажет ошибки с фоном цвета лосося, что означает, что в контексте блокчейна произошло что-то не так (например, неправильное количество переданных параметров, неправильное форматирование параметра Micheline или даже контракт неприемлемых условий - например, : вы позвонили в точку входа перевода, но у «от» клиента недостаточно средств для отправки).
Заключение
Разработчикам еще никогда не было так просто работать со смарт-контрактами на блокчейне. Tezos, в частности, предлагает множество отличных инструментов и огромное количество библиотек компьютерных языков, которые облегчают интеграцию с большинством систем. Библиотека TezosJ является новаторской, предлагая простой в использовании метод callContractEntryPoint, который на лету создает параметры в формате Micheline. В нем есть все инструменты, необходимые разработчикам Android для успешной разработки приложений, которые беспрепятственно взаимодействуют с блокчейном.
Скачать полный код
Вы можете скачать здесь полный проект Android Studio, представленный в этой статье.