DApp

Децентрализованные приложения в IZZZIO позволяют создавать добавочный функционал для ноды. Такие приложения имеют широкий функционал: 1. Взаимодействие с цепочкой блоков, предобработка, реакция на изменения цепочки 2. Взаимодействие со смарт контрактами, в том числе запуск новых 3. Взаимодействие с другими децентрализованными приложениями посредством встроенных протколов. См. StarWave, StarWaveCrypto 4. Интеграция централизованных приложений с децентрализованным.

Для написания децентрализованных приложений в IZZZIO используется класс DApp. Класс предоставляет все необходимые методы для работы с функционалом сети, и обеспечивает совместимость приложений с разными версиями узлов блокчейна IZZZIO.

DApp

При создании класса наследуемого от DApp рекомендуется не объявлять конструктор, и использовать вместо него встроенный метод init Для обработки состояния завершения используется метод terminate(cb)

Глобальные переменные

Для использования в DApp доступны следующие глобальные переменные:

  1. global.PATH.mainDir - путь до корневой директори файлов блокчейна IZZZIO
  2. global.PATH.configDir - путь до директории конфигурационного файла

Эти переменные обычно используются для включения файлов модулей ядра в проект.

const DApp = require(global.PATH.mainDir + '/app/DApp'); //Поиск DApp будет выполнен в корневой директории блокчейна

class TestDapp extends DApp {
    init(){
        console.log('DApp ready!');
    }

    terminate(cb){
        console.log('DApp terminated');
    }

}

Доступные объекты

logger

Внутренний путь: modules/logger

logger обеспечивает стандартизацию вывода сообщений в консоль.

Свойство: disable - true - отключение вывода сообщений; false - вывод включения

new Logger([prefix])
Аргументы:
  • prefix (string) – Префикс, с которым будет выводится сообщение
getPrefix()
Результат:Текущий установленный префикс
log(type, data)
Аргументы:
  • type (string) – Тип сообщения для вывода
  • data (string) – Сообщение
info(type, data)
Аргументы:
  • data (string) – Сообщение информационного типа
init(type, data)
Аргументы:
  • data (string) – Сообщение инициализации
error(type, data)
Аргументы:
  • data (string) – Сообщение об ошибке
fatal(type, data)
Аргументы:
  • data (string) – Сообщение о критической ошибке
warning(type, data)
Аргументы:
  • data (string) – Предупреждение
const DApp = require(global.PATH.mainDir + '/app/DApp');
const logger = new (require(global.PATH.mainDir + '/modules/logger'))("TestDApp");

class TestDApp extends DApp {
    init(){
        logger.info('Test DApp ready!'); //Выведет "Fri, 01 Feb 2019 14:12:48 GMT Info:  ECMAContract: Test DApp ready"
    }

}

assert

Внутренний путь: modules/testing/assert

Предоставляет функционал проверки каких - либо условий. Невыполнение этих условий ведёт к бросу исключения, и завершению вызова контракта с ошибкой. Состояние контракта откатывается до состояния до вызова.

Реализация идентична реализации для EcmaContract.

Перейти на описание assert

instanceStorage

Внутренний путь: modules/instanceStorage

Предоставляет доступ к созданным экземплярам объектов на основе ключей.

instanceStorage.get(objName)
Аргументы:
  • name (string) – Название сохранённой сущности
Результат:

Сохранённая сущность или null при отсутствии

instanceStorage.put(objName, value)
Аргументы:
  • name (string) – Название сохраняемой сущности
  • value – Объект сущности

По умолчанию instanceStorage содержит следующие сущности:

  1. Blockchain - главный экземпляр объекта сети
  2. config - экземпляр объекта конфигурации
  3. wallet - текущий кошёлёк
  4. blocks - хранилище данных блоков
  5. blockHandler - экземпляр объекта обработчика блоков
  6. frontend - экземпляр объекта RPC интерфейса и оболочки
  7. transactor - экземпляр объекта контроля траназкций
  8. cryptography - экземпляр объекта криптографии
  9. blockchainObject - алиас объекта Blockchain

Опциональные объекты и значения:

  1. ecmaContract - экземпляр объекта смарт контрактов (если включены)
  2. dapp - экземпляр объекта децентролизованного приложения (если включено)
  3. terminating - флаг завершения работы
const DApp = require(global.PATH.mainDir + '/app/DApp');
const storj = require(global.PATH.mainDir + '/modules/instanceStorage');

class TestDApp extends DApp {
    init(){
        console.log(storj.get('config').p2pPort); //6015
    }

}

StarWaveCrypto

См. раздел StarWaveCrypto

Коннекторы

Коннекторы DApp - классы-обёртки, реализующие упрощенный интерфейс взаимодействия с контрактами определённых типов.

DApp-ContractConnector

Внутренний путь: modules/smartContracts/connectors/ContractConnector

Базовый абстрактный класс для коннекторов. Позволяет регестрировать методы и их алиасы.

DApp-TokenContractConnector

Внутренний путь: modules/smartContracts/connectors/TokenContractConnector

Класс коннектора, реализующий взаимодействие с контрактом-токеном для DApp

new TokenContractConnector(EcmaContractsInstance, contractAddress)
Аргументы:
  • EcmaContractsInstance – Экзмпляр объекта EcmaContracts
  • contractAddress (string) – Адрес контракта, к которому происходит подключение
async balanceOf(address)
Аргументы:
  • address (string) – Адрес владельца токенов
Returns string:

Баланс токенов

async totalSupply()
Returns string:Количество всего выпущеных токенов
async transfer(to, amount)
Аргументы:
  • to (string) – Получатель токенов
  • amount (string) – Количество токенов
async burn(amount)
Аргументы:
  • amount (string) – Количество сжигаемых токенов
async mint(amount)
Аргументы:
  • amount (string) – Количество выпускаемых токенов
async contract()
Returns string:Свойство contract из контракта. Данные о контракте

Выполнение метода из другого контракта с оплатой

async pay(address, method, txAmount, args)
Аргументы:
  • address (string) – Адрес контракта для вызова метода
  • method (string) – Метод
  • txAmount (string) – Сумма перевода
  • args (array) – Аргументы вызова
Результат:

Новый созданный блок

const DApp = require(global.PATH.mainDir + '/app/DApp');
const TokenContractConnector = require(global.PATH.mainDir + '/modules/smartContracts/connectors/TokenContractConnector');

class TestDApp extends DApp {
    async init(){
        let mainToken = new TokenContractConnector(this.ecmaContract, this.getMasterContractAddress());

        console.log(await mainToken.balanceOf(this.getCurrentWallet().id)); //Выведет баланс текущего кошелька

        //Вызовет метод processPayment из контракта SOME_CONTRACT_ADDRESS с параметром 'Hello', передав состояние проведения оплаты на 1 токен с текущего кошелька
        await mainToken.pay(SOME_CONTRACT_ADDRESS, "processPayment", '1', ['Hello']);
    }

}

Внутренние объекты DApp

DApp.network

Предоставляет базовый функционал взаимодействия с сетевым интерфейсом, а также регистрацию RPC и обрбаотчиков интерфейса.

  1. Возвращает массив текущих пиров в формате ws://address:port
getCurrentPeers()
Результат:пиры
  1. Получение сокета по адресу шины (адрес внешней ноды)
getSocketByBusAdress(address)
Аргументы:
  • address (string) – адрес шины
Результат:

объект сокета или false, если адрес не был найден.

  1. Прямая отправка сообщения в сокет
socketSend(ws, message)
Аргументы:
  • ws – сокет.
  • message (string) – сообщение.
  1. Регистрация метода обратного вызова для get запроса
rpc.registerGetHandler(url, callback)
Аргументы:
  • url (string) – Обрабочтик ссылки
  • callback (function) – Метод обратного вызова
  1. Регистрация метода обратного вызова для post запроса
rpc.registerPostHandler(url, callback)
Аргументы:
  • url (string) – Обрабочтик ссылки
  • callback (function) – Метод обратного вызова

Методы rpc.registerGetHandler и rpc.registerPostHandler основаны на использовании фреймворка Express.js. Подробнее об обработчиках в документации Express.js

DApp.messaging

Устаревший функционал Предоставляет базовый функционал обмена собщениями между узлами сети.

1.Регистрация обработчика сообщений

registerMessageHandler(message, handler)
Аргументы:
  • message (string) – идентификатор сообщения
  • handler (function) – функция - обработчик сообщений
  1. Метод широковещательной передачи сообщений по сети
broadcastMessage(data, message, receiver)
Аргументы:
  • data – передаваемый объект
  • message (string) – идентификатор сообщения
  • receiver (string) – получатель сообщения
  1. Метод передачи сообщения близжайшему получателю
sendMessage(data, message, receiver)
Аргументы:
  • data – объект, содержащий само сообщение.
  • message (string) – идентификатор сообщения.
  • receiver (string) – получатель сообщения.

Методы DApp.messaging.starwave описаны в разделе StarWave

DApp.blocks

Предоставляет доступ к функционалу генерации и добавления блоков, обработчику событий.

Генерирует блок без добавления в цепочку блоков

generateBlock(blockData, cb, cancelCondition)
Аргументы:
  • blockData (Block) – Подписанный блок Block
  • cb (function) – функция обратного вызова function(newBlock)
  • cancelCondition – Функция условия отмены генерации блока

Генерация блока с добавлением в цепочку блоков и уведомлением узлов о новом блоке

generateAndAddBlock(blockData, cb, cancelCondition)
Аргументы:
  • blockData (Block) – Подписанный блок Block
  • cb (function) – функция обратного вызова function(newBlock)
  • cancelCondition – Функция условия отмены генерации блока

Добавление сгенерированного блока

addBlock(newBlock, cb)
Аргументы:
  • newBlock – Готовый блок
  • cb – callback - обратного вызова

Методы обработчика блоков

Возвращает экземпляр текущего обработчика блоков

handler.get()
Результат:объект обработчика (ловца) блоков.

Регистрация обработчика блока по типу

handler.registerHandler(type, handler)
Аргументы:
  • type (string) – Тип блока
  • handler (function) – функция - обработчик блоков function(blockData, blockSource, callback)

Предупреждение

Вызов callback в обработчике блоков обязателен. Отсутствие обратного вызова приведёт к зависанию обработчика блоков.

DApp.contracts

Предоставляет функционал доступа к модулю EcmaContracts.

contracts.ecma - предоставляет прямой доступ к объекту EcmaContracts. См. EcmaContracts

contracts.ecmaPromise - предоставляет основные методы EcmaContracts для использования с асинхронным режимом (async-await)

Выполняет запуск контракта в сети

ecmaPromise.deployContract(source, resourceRent)
Аргументы:
  • source (string) – Исходнй код контракта
  • resourceRent (number) – Количество токенов, выделяемых на аренду ресурсов контракта
Результат:

объект нового блока

Выполняет запуск метода из контракта

ecmaPromise.deployMethod(address, method, args, state)
Аргументы:
  • address (string) – Адрес контракта
  • method (string) – Метод контракта
  • args (array) – Массив с аргументами вызова
  • state (object) – Объект передаваемого состояния
Результат:

объект нового блока

Выполняет запуск метода из контракта с откатом состояния

ecmaPromise.callMethodRollback(address, method, args, state)
Аргументы:
  • address (string) – Адрес контракта
  • method (string) – Метод контракта
  • args (array) – Массив с аргументами вызова
  • state (object) – Объект передаваемого состояния
Результат:

Результат выполнения метода контракта

Внутренние методы DApp

DApp.getConfig()
Результат:объект конфигурации
DApp.getBlockHandler()
Результат:объект обработчика блоков
DApp.getCurrentWallet()
Результат:объект текущего кошелька
DApp.getMasterContractAddress()
Результат:адрес мастер-контракта или false если не существует

StarWave

StarWave - протокол высокоскоростной передачи данных внутри децентрализованной сети IZZZIO. Протокол автоматически составляет кратчайший маршрут доставки сообщения до получателя. В случае нарушения маршрута, происходит его перестроение по такому-же принципу.

Методы StarWave доступны в DApp DApp.messaging.starwave

Методы messaging.starwave

Регистрация обработчика сообщений

starwave.registerMessageHandler(message, handler)
Аргументы:
  • message (string) – идентификатор сообщения
  • handler (function) – функция - обработчик сообщений

Метод передачи сообщения близжайшему получателю

starwave.sendMessage(data, message, receiver)
Аргументы:
  • data – объект, содержащий само сообщение.
  • message (string) – идентификатор сообщения.
  • receiver (string) – получатель сообщения.

Метод создания структуры сообщения

starwave.createMessage(data, reciver, sender = undefined, id, timestamp = undefined, TTL = undefined, relevancyTime = undefined, route = undefined, type = undefined, timestampOfStart)
Аргументы:
  • data – объект, содержащий само сообщение.
  • reciver (string) – получатель сообщения
  • sender (string) – отправитель сообщения; undefined - используются системное инфо об отправителе
  • id (string) – Идентификатор сообщения
  • timestamp (number) – Метка времени сообщения; undefined - автоматически
  • TTL (number) – Возможное количество скачков сообщения; undefined - автоматически
  • relevancyTime (number) – время актуальности сообщения; undefined - автоматически
  • timestamp – Метка времени сообщения; undefined - автоматически
  • route (array) – Маршрут сообщения; undefined - автоматически
  • type (string) – Тип сообщения; undefined - автоматически
  • timestampOfStart (number) – Метка времени отправки сообщения; undefined - автоматически
Результат:

Объект структуры сообщения

StarWaveCrypto

Внутренний путь: modules/starwaveCrypto

StarWaveCrypto - модуль, реализующий создание шифрованного канала для обмена данными между узлами сети. При создании подключения, между узлами просходит генерация и обмен ключами по протоколу Диффи - Хеллмана (DH).

Для cоздания шифрованного канала используется метод, осуществляющий «рукопожатие». Таким образом, принимающая сторона, используя метод обработки получаемых сообщений, сразу создаст новое защищеное соъединение, или использует существующее. Пример установки соединения:

const DApp = require(global.PATH.mainDir + '/app/DApp');
const StarwaveCrypto = require(global.PATH.mainDir + '/modules/starwaveCrypto');

class TestDApp extends DApp {

    init() {

        let that = this;

        starwave.registerMessageHandler('SW_TEST', function (message) {
            console.log('New message', message);
        });

        let crypto =  new StarwaveCrypto(this.starwave, this.blockchain.secretKeys).makeConnection(RECIVER_ADDRESS, function(who, secretKey){
            console.log('Connected!');
            let message = that.starwave.createMessage('Hello Node Two' + Math.random(), 'RECIVER_ADDRESS', undefined, 'SW_TEST');
            crypto.sendMessage(m);
        });
    };
}