За последний год было все больше и больше проектов, которые позволяют разработчикам использовать GraphQL для запроса смарт-контрактов Ethereum. Хотя это здорово, их один большой недостаток заключается в том, что от разработчика требуется написать схему и преобразователь GraphQL. Это означает, что каждый раз при обновлении Solidity должен обновляться весь стек. Чтобы упростить эти процессы, мы используем открытый исходный код ethereum-to-graphql, библиотеку, которая автоматически генерирует схему и преобразователь для любого смарт-контракта Ethereum.

Проблема: ETH → Процесс разработки GraphQL

Чтобы использовать GraphQL со своим смарт-контрактом Ethereum, вы должны сделать следующее:

  1. Компиляция контрактов Solidity
  2. Создать схему GraphQL
  3. Создать резолвер GraphQL
  4. Запустить GraphQL Server
  5. Отправить запрос GraphQL

Схема GraphQL определяет типы, разрешенные для вашего запроса. Решатель GraphQL - это функция, которая запускается при запросе для выборки данных. Вы можете заставить его делать все, что хотите, если он возвращает запрошенные данные.

Что является громоздким во всем процессе, так это то, что вы вынуждены переписывать схему и преобразователь каждый раз, когда вы меняете что-либо в своем смарт-контракте. Это увеличивает время разработки и увеличивает сложность. Чтобы проиллюстрировать процесс, взгляните на пример ниже:

// (1) Solidity
function getBalanceInEth(address addr) public returns(uint) {
  return ConvertLib.convert(getBalance(addr), 2);
}
// (2) GraphQL Schema
type getBalanceInEth {
  balance: Int
}
// (3) GraphQL Resolver
Query: {
  async getBalanceInEth() {
    let balance = 0;
    await contractInstance.getBalanceInEth.call()
      .then(bal => (balance = bal / wie)) // convert to ETH
      .catch(err => console.log(err));
    return {
      balance
    };
  }
}
// (4) Start server --> npm run start
// (5a) GraphQL Query
{
  query {
    getBalanceInEth(addr: "0x7b2c6c6e9026bcef8d...a") {
      balance
    }
  }
}
// (5b) Result
{
  'getBalanceInEth': {
    'balance': 5
  }
}

Решение: автоматическое создание схемы и распознавателя

Наш пакет Ethereum-to-GraphQL использует ABI (Application Binary Interface), созданный при компиляции Solidity, и генерирует необходимую схему и преобразователь для ЛЮБОГО смарт-контракта. Это означает, что приведенные выше шаги сводятся к:

  1. Компиляция контрактов Solidity
  2. Запустить GraphQL Server
  3. Отправить запрос GraphQL

Этот процесс был значительно улучшен и рационализирован. Это означает, что разработчик может напрямую перейти с Solidity на GraphQL.

Представьте, что вы добавляете это в Etherscan и получаете возможность исследовать данные в любом смарт-контракте. Пока у вас есть доступ к правильному ABI, все будет доступно для запросов. Вы только посмотрите, насколько просто процесс удара по сравнению с приведенным выше примером:

// (1) Solidity
function getBalanceInEth(address addr) public returns(uint) {
  return ConvertLib.convert(getBalance(addr), 2);
}
// (2) Start server --> npm run start
// (3a) GraphQL Query
{
  query {
    getBalanceInEth(addr: "0x7b2c6c6e9026bcef8d...a") {
      uint256_0 {
        string
        int
      }
    }
  }
}

// (3b) Result
{
  'getBalanceInEth': {
    'uint256_0': {
      'string': '5',
      'int': 5
    }
  }
}

Подробности: Как работают внутренние компоненты (короткометражка)

Когда Solidity компилируется, создается ABI. Он описывает все входы и выходы смарт-контракта. Например, ABI для getBalanceInEth показан ниже:

[{
  "constant": false,
  "inputs": [{
    "name": "addr",
    "type": "address"
  }],
  "name": "getBalanceInEth",
  "outputs": [{
    "name": "",
    "type": "uint256"
  }],
  "payable": false,
  "stateMutability": "nonpayable",
  "type": "function"
  }]

Учитывая этот ABI, у нас достаточно информации, чтобы сгенерировать правильную схему GraphQL.

type Value {
  string: String
  int: Number
}
type getBalanceInEth {
  uint256_0: Value
}

Поскольку мы автоматически генерируем все, мы решили определить несколько полезных типов, таких как тип Value. Вы можете выбрать для просмотра string или int версию результата. У нас также есть тип для bytes, где вы можете выбрать raw или decoded.

После того, как схема сгенерирована, все, что осталось создать, - это преобразователь. Для этого требуются 2 функции: функция, которая получает данные из Ethereum (sourceFn), и функция для обработки результата (outputMapper). По мере прохождения итерации мы создаем функцию-оболочку, которая связывает их вместе.

Обратите внимание, как SourceFn принимает outputMapper. Этот выходной преобразователь получает данные и преобразует их в необходимый формат GraphQL, который позволяет выполнять запросы.

Эти два метода объединены и прикреплены и возвращены как преобразователь для использования GraphQL. Все, что вам нужно сделать, это передать свой контрактный ABI нашему пакету, а затем передать его на выбранный вами сервер GraphQL. Ниже приведен пример Metacoin Truffle:

Заключение: призыв к действию

Мы очень рады открытому исходному коду внутреннего проекта для всего мира. Мы видим, что этот пакет помогает многим людям, поскольку он снижает барьер для GraphQL и Ethereum. Мы очень открыты для принятия запросов на вытягивание и имеем несколько предложений о том, как внести свой вклад.

Чтобы быть в курсе последних новостей HelloSugoi, мы приглашаем вас присоединиться к нашему списку рассылки, написать нам в Discord, подписаться на нас в Twitter @HelloSugoi и посетить наш веб-сайт hellosugoi.