Docs
Поиск⌘ K
  • Главная страница
  • О The Graph
  • Поддерживаемые сети
  • Protocol Contracts
  • Субграфы
    • Субпотоки
      • Token API
        • AI Suite
          • Индексирование
            • Ресурсы
              Субграфы > Разработка > Создание > AssemblyScript API

              19 минуты

              AssemblyScript API

              Note: If you created a Subgraph prior to graph-cli/graph-ts version 0.22.0, then you’re using an older version of AssemblyScript. It is recommended to review the Migration Guide.

              Learn what built-in APIs can be used when writing Subgraph mappings. There are two kinds of APIs available out of the box:

              • Библиотека The Graph TypeScript⁠ (graph-ts)
              • Code generated from Subgraph files by graph codegen

              Вы также можете добавлять другие библиотеки в качестве зависимостей, если они совместимы с AssemblyScript⁠.

              Поскольку мэппинги языков написаны на AssemblyScript, полезно ознакомиться с функциями языка и стандартной библиотеки на вики-странице AssemblyScript⁠.

              Референс API

              Библиотека @graphprotocol/graph-ts предоставляет следующие API:

              • API ethereum для работы со смарт-контактами Ethereum, событиями, блоками, транзакциями и значениями Ethereum.
              • API store для загрузки и сохранения объектов из хранилища the Graph Node и в него.
              • API log для регистрации сообщений в выходных данных the Graph Node и Graph Explorer.
              • API ipfs для загрузки файлов из IPFS.
              • API json для выполнения разбора данных в формате JSON.
              • API crypto для использования криптографических функций.
              • Низкоуровневые примитивы для перевода между системами различных типов, таких как Ethereum, JSON, GraphQL и AssemblyScript.

              Версии

              The apiVersion in the Subgraph manifest specifies the mapping API version which is run by Graph Node for a given Subgraph.

              ВерсияПримечания к релизу
              0.0.9Добавлены новые функции хоста eth_get_balance и hasCode
              0.0.8Добавлена проверка наличия полей в схеме при сохранении объекта.
              0.0.7К типам Ethereum добавлены классы TransactionReceipt и Log
              К объекту Ethereum Event добавлено поле receipt
              0.0.6В объект Ethereum Transaction добавлено поле nonce
              В объект Ethereum Block добавлено поле baseFeePerGas
              0.0.5AssemblyScript upgraded to version 0.19.10 (this includes breaking changes, please see the Migration Guide)
              ethereum.transaction.gasUsed renamed to ethereum.transaction.gasLimit
              0.0.4В объект Ethereum SmartContractCall добавлено поле functionSignature
              0.0.3Added from field to the Ethereum Call object
              ethereum.call.address renamed to ethereum.call.to
              0.0.2В объект Ethereum Transaction добавлено поле input

              Встроенные типы

              Документацию по базовым типам, встроенным в AssemblyScript, можно найти в AssemblyScript wiki⁠.

              Дополнительные типы, предоставляемые @graphprotocol/graph-ts.

              ByteArray

              1import { ByteArray } from '@graphprotocol/graph-ts'

              ByteArray представляет собой массив u8.

              Конструкция

              • fromI32(x: i32): ByteArray — Разбивает x на байты.
              • fromHexString(hex: string): ByteArray - Длина ввода должна быть четной. Префикс 0x необязателен.

              Преобразования типов

              • toHexString(): string - Преобразуется в шестнадцатеричную строку с префиксом 0x.
              • toString(): string - Интерпретирует байты как строку UTF-8.
              • to Base 58(): string - Кодирует байты в строку base58.
              • to U32(): u32 - Интерпретирует байты как little-endian u32. Выбрасывает в случае переполнения.
              • to I32(): i32 - Интерпретирует массив байтов как little-endian i32. Выбрасывает в случае переполнения.

              Операторы

              • equals(y: ByteArray): bool – может быть записано как x == y.
              • concat(other: ByteArray) : ByteArray - возвращает новый ByteArray, состоящий из this, за которым непосредственно следует other
              • concatI32(other: i32) : ByteArray - возвращает новый ByteArray, состоящий из this, за которым непосредственно следует байтовое представление other

              BigDecimal

              1import { BigDecimal } from '@graphprotocol/graph-ts'

              BigDecimal используется для представления десятичных знаков произвольной точности.

              Примечание: Внутренне⁠ BigDecimal хранится в формате с плавающей точкой IEEE-754 decimal128⁠, который поддерживает 34 десятичных знака после запятой. Это делает BigDecimal непригодным для представления типов с фиксированной точкой, которые могут охватывать более 34 знаков, таких как Solidity ufixed256x18⁠ или его эквивалентов.

              Конструкция

              • constructor(bigInt: BigInt) — создает BigDecimal из BigInt.
              • static fromString(s: string): BigDecimal – выполняет синтаксический разбор из десятичной строки.

              Преобразования типов

              • toString(): string – выводит в виде десятичной строки.

              Математика

              • plus(y: BigDecimal): BigDecimal – может быть записано как x + y.
              • minus(y: BigDecimal): BigDecimal – может быть записано как x - y.
              • times(y: BigDecimal): BigDecimal – может быть записано как x * y.
              • div(y: BigDecimal): BigDecimal – может быть записано как x / y.
              • equals(y: BigDecimal): bool – может быть записано как x == y.
              • notEqual(y: BigDecimal): bool – может быть записано как x != y.
              • lt(y: BigDecimal): bool – может быть записано как x < y.
              • le(y: BigDecimal): bool – может быть записано как x <= y.
              • gt(y: BigDecimal): bool – может быть записано как x > y.
              • ge(y: BigDecimal): bool – может быть записано как x >= y.
              • neg(): BigDecimal - может быть записано как -x.

              BigInt

              1import { BigInt } from '@graphprotocol/graph-ts'

              BigInt используется для представления больших целых чисел. Сюда входят значения Ethereum типа от uint32 до uint256 и от int64 до int256. Все, что находится ниже uint32, например int32, uint24 или int8, представлено как i32.

              Класс BigInt имеет следующий API:

              Конструкция

              • BigInt.fromI32(x: i32): BigInt – создает BigInt из i32.

              • BigInt.fromString(s:string): BigInt– Выполняет разбор BigInt из строки.

              • BigInt.fromUnsignedBytes(x: Bytes): BigInt — Интерпретирует bytes беззнаковое целое число в формате little-endian (младшие байты идут первыми). Если Ваши входные данные в формате big-endian (старшие байты идут первыми), сначала вызовите .reverse().

              • BigInt.fromSignedBytes(x: Bytes): BigInt — Интерпретирует bytes как знаковое целое число в формате little-endian (младшие байты идут первыми). Если Ваши входные данные в формате big-endian (старшие байты идут первыми), сначала вызовите .reverse().

                Преобразования типов

              • x.toHex(): string – преобразует BigInt в строку шестнадцатеричных символов.

              • x.toString(): string – преобразует BigInt в строку десятичных чисел.

              • x.toI32(): i32 – возвращает BigInt в виде i32; завершается с ошибкой, если значение не соответствует i32. Рекомендуется сначала проверить x.is I32().

              • x.to BigDecimal(): BigDecimal - преобразует в десятичное число без дробной части.

              Математика

              • x.plus(y: BigInt): BigInt – может быть записано как x + y.
              • x.minus(y: BigInt): BigInt – может быть записано как x - y.
              • x.times(y: BigInt): BigInt – может быть записано как x * y.
              • x.div(y: BigInt): BigInt – может быть записано как x / y.
              • x.mod(y: BigInt): BigInt – может быть записано как x % y.
              • x.equals(y: BigInt): bool – может быть записано как x == y.
              • x.notEqual(y: BigInt): bool – может быть записано как x != y.
              • x.lt(y: BigInt): bool – может быть записано как x < y.
              • x.le(y: BigInt): bool – может быть записано как x <= y.
              • x.gt(y: BigInt): bool – может быть записано как x > y.
              • x.ge(y: BigInt): bool – может быть записано как x >= y.
              • x.neg(): BigInt – может быть записано как -x.
              • x.divDecimal(y: BigDecimal): BigDecimal – делит на десятичное число, что дает десятичный результат.
              • x.isZero(): bool – Удобство для проверки, равно ли число нулю.
              • x.isI32(): bool – Проверяет, соответствует ли число i32.
              • x.abs(): BigInt – Абсолютное значение.
              • x.pow(exp: u8): BigInt – Возведение в степень.
              • bitOr(x: BigInt, y: BigInt): BigInt – может быть записан как x | y.
              • bitAnd(x: BigInt, y: BigInt): BigInt – может быть записан как x & y.
              • leftShift(x: BigInt, bits: u8): BigInt – может быть записан как x << y.
              • rightShift(x: BigInt, bits: u8): BigInt – может быть записан как x >> y.

              TypedMap

              1import { TypedMap } from '@graphprotocol/graph-ts'

              TypedMap можно использовать для хранения пар ключ-значение. Смотрите этот пример⁠.

              Класс TypedMap имеет следующий API:

              • new TypedMap<K, V>() создает пустую карту с ключами типа K и значениями типа V
              • map.set(key: K, value: V): void – устанавливает значение key в value
              • map.getEntry(key: K): TypedMapEntry<K, V> | null – возвращает пару ключ-значение для key или null, если key не существует на карте
              • map.get(key: K): V | null – возвращает значение для key или null, если key не существует на карте
              • map.isSet(key: K): bool – возвращает true, если key существует на карте, и false, если его нет

              Bytes

              1import { Bytes } from '@graphprotocol/graph-ts'

              Bytes используется для представления массивов байтов произвольной длины. Сюда входят значения Ethereum типа bytes, bytes32 и т. д.

              Класс Bytes расширяет [Uint8Array] из AssemblyScript (https://github.com/AssemblyScript/assemblyscript/blob/3b1852bc376ae799d9ebca888e6413afac7b572f/std/assembly/typedarray.ts#L64⁠) и поддерживает все функциональные возможности Uint8Array, а также следующие новые методы:

              Конструкция

              • fromHexString(hex: string) : Bytes - Преобразует строку hex, которая должна состоять из четного числа шестнадцатеричных цифр, в ByteArray. Строка hex может опционально начинаться с 0x
              • fromI32(i: i32) : Bytes - Преобразовывает i в массив байтов

              Преобразования типов

              • b.toHex() – возвращает шестнадцатеричную строку, представляющую байты в массиве
              • b.toString() – преобразует байты в массиве в строку символов Unicode
              • b.toBase58() – преобразует значение Ethereum Bytes в кодировку base58 (используется для хэшей IPFS)

              Операторы

              • b.concat(other: Bytes) : Bytes - - возвращает новые Bytes, состоящие из this, за которым непосредственно следует other
              • b.concatI32(other: i32) : ByteArray - возвращает новые Bytes, состоящие из this, за которым непосредственно следует байтовое представление other

              Address

              1import { Address } from '@graphprotocol/graph-ts'

              Address расширяет Bytes для представления значений Ethereum address.

              Поверх Bytes API добавляется следующий метод:

              • Address.fromString(s: string): Address – создает Address из шестнадцатеричной строки
              • Address.fromBytes(b: Bytes): Address — создайте Address из b длиной ровно 20 байт. Передача значения с меньшим или большим количеством байт приведет к ошибке

              Store API

              1import { store } from '@graphprotocol/graph-ts'

              API store позволяет загружать, сохранять и удалять объекты из хранилища the Graph Node и в него.

              Entities written to the store map one-to-one to the @entity types defined in the Subgraph’s GraphQL schema. To make working with these entities convenient, the graph codegen command provided by the Graph CLI⁠ generates entity classes, which are subclasses of the built-in Entity type, with property getters and setters for the fields in the schema as well as methods to load and save these entities.

              Создание объектов

              Ниже приведен общий шаблон для создания объектов из событий Ethereum.

              1// Импорт класса событий Transfer, сгенерированного из ERC20 ABI2import { Transfer as TransferEvent } from '../generated/ERC20/ERC20'34// Импорт типа объекта Transfer, сгенерированного из схемы GraphQL5import { Transfer } from '../generated/schema'6событие7// Обработчик события передачи8экспортирует функцию handleTransfer(event: TransferEvent): void {9  // Создание объекта Transfer, с использованием хеша транзакции в качестве идентификатора объекта10let id = event.transaction.hash11  let transfer = new Transfer(id)1213  // Установка свойства объекта, с использованием параметров события14transfer.from = event.params.from15  transfer.to = event.params.to16  transfer.amount = event.params.amount1718  // Сохранение объекта в хранилище19transfer.save()20}

              Когда при обработке чейна возникает событие Transfer, оно передается обработчику события handleTransfer, используя сгенерированный тип Transfer (здесь используется псевдоним TransferEvent, чтобы избежать конфликта наименования с типом объекта). Этот тип позволяет получить доступ к таким данным, как материнская транзакция события и ее параметры.

              Каждый объект должен иметь уникальный идентификатор, чтобы избежать конфликтов с другими объектами. Параметры событий довольно часто включают уникальный идентификатор, который можно использовать.

              Примечание: Использование хэша транзакции в качестве идентификатора предполагает, что никакие другие события в той же транзакции не создают объекты с этим хэшем в качестве идентификатора.

              Загрузка объектов из хранилища

              Если объект уже существует, его можно загрузить из хранилища следующим образом:

              1let id = event.transaction.hash // или некоторым образом создается идентификатор2let transfer = Transfer.load(id)3if (transfer == null) {4  transfer = new Transfer(id)5}67// Используйте объект Transfer, как и раньше

              Поскольку объект может еще не существовать в хранилище, метод load возвращает значение типа Transfer | null. Таким образом, перед использованием значения может потребоваться проверка на наличие null.

              Примечание: Загрузка объектов необходима только в том случае, если изменения, внесенные в мэппинг, зависят от предыдущих данных объекта. В следующем разделе описаны два способа обновления существующих объектов.

              Поиск объектов, созданных внутри блока

              Начиная с graph-node v0.31.0, @graphprotocol/graph-ts v0.30.0 и @graphprotocol/graph-cli v0.49.0 метод loadInBlock доступен для всех типов объектов.

              The store API facilitates the retrieval of entities that were created or updated in the current block. A typical situation for this is that one handler creates a transaction from some onchain event, and a later handler wants to access this transaction if it exists.

              • In the case where the transaction does not exist, the Subgraph will have to go to the database simply to find out that the entity does not exist. If the Subgraph author already knows that the entity must have been created in the same block, using loadInBlock avoids this database roundtrip.
              • For some Subgraphs, these missed lookups can contribute significantly to the indexing time.
              1let id = event.transaction.hash // или некоторым образом создается идентификатор2let transfer = Transfer.loadInBlock(id)3if (transfer == null) {4  transfer = new Transfer(id)5}67// Используйте объект Transfer, как и раньше

              Примечание: Если в данном блоке не создан объект, loadInBlock вернет null, даже если в хранилище есть объект с данным идентификатором.

              Поиск производных объектов

              Начиная с graph-node v0.31.0, @graphprotocol/graph-ts v0.31.0 и @graphprotocol/graph-cli v0.51.0 метод loadRelated доступен.

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

              1type Token @entity {2  id: ID!3  holder: Holder!4  color: String5}67type Holder @entity {8  id: ID!9  tokens: [Token!]! @derivedFrom(field: "holder")10}

              Следующий код загрузит объект Token, из которого был получен объект Holder:

              1let holder = Holder.load('test-id')2// Загрузите объекты токена, связанные с данным держателем3let tokens = holder.tokens.load()

              Обновление существующих объектов

              Существует два способа обновить существующий объект:

              1. Загрузите объект, например, с помощью Transfer.load(id), установите свойства объекта, затем с помощью .save() верните его обратно в хранилище.
              2. Просто создайте объект, например, с помощью new Transfer(id), установите свойства объекта, затем с помощью .save() сохраните его в хранилище. Если объект уже существует, изменения будут объединены с ним.

              Изменение свойств в большинстве случаев не вызывает затруднений благодаря сгенерированным установщикам свойств:

              1let transfer = new Transfer(id)2transfer.from = ...3transfer.to = ...4transfer.amount = ...

              Также можно сбросить свойства с помощью одной из следующих двух инструкций:

              1transfer.from.unset()2transfer.from = null

              Это работает только с необязательными свойствами, то есть свойствами, объявленными без ! в GraphQL. Два примера: owner: Bytes или amount: BigInt.

              Обновление свойств массива немного сложнее, поскольку получение массива из объекта создает копию этого массива. Это означает, что после изменения массива необходимо снова точно задать его свойства. В следующем примере предполагается, что entity имеет поле numbers: [BigInt!]!.

              1// Это не сработает2entity.numbers.push(BigInt.fromI32(1))3entity.save()45// Это сработает6let numbers = entity.numbers7numbers.push(BigInt.fromI32(1))8entity.numbers = numbers9entity.save()

              Удаление объектов из хранилища

              В настоящее время нет способа удалить объект с помощью сгенерированных типов. Вместо этого для удаления объекта требуется передать имя типа объекта и идентификатор объекта в store.remove:

              1import { store } from '@graphprotocol/graph-ts'2...3let id = event.transaction.hash4store.remove('Transfer', id)

              Ethereum API

              Ethereum API предоставляет доступ к смарт-контрактам, общедоступным переменным состояния, функциям контрактов, событиям, транзакциям, блокам и кодированию/декодированию данных Ethereum.

              Поддержка типов Ethereum

              As with entities, graph codegen generates classes for all smart contracts and events used in a Subgraph. For this, the contract ABIs need to be part of the data source in the Subgraph manifest. Typically, the ABI files are stored in an abis/ folder.

              With the generated classes, conversions between Ethereum types and the built-in types take place behind the scenes so that Subgraph authors do not have to worry about them.

              The following example illustrates this. Given a Subgraph schema like

              1type Transfer @entity {2  id: Bytes!3  from: Bytes!4  to: Bytes!5  amount: BigInt!6}

              и сигнатура события Transfer(address,address,uint256) на Ethereum, значения from, to и amount типа address, address и uint256 преобразуются в Address и BigInt, что позволяет передавать их в свойства Bytes! и BigInt! объекта Transfer:

              1let id = event.transaction.hash2let transfer = new Transfer(id)3transfer.from = event.params.from4transfer.to = event.params.to5transfer.amount = event.params.amount6transfer.save()

              События и данные о блоках/транзакциях

              События Ethereum, передаваемые обработчикам событий, такие как событие Transfer в предыдущих примерах, предоставляют доступ не только к параметрам события, но и к их материнской транзакции и блоку, частью которого они являются. Следующие данные могут быть получены из экземпляров event (эти классы являются частью модуля ethereum в graph-ts):

              1class Event {2  address: Address3  logIndex: BigInt4  transactionLogIndex: BigInt5  logType: string | null6  block: Block7  transaction: Transaction8  parameters: Array<EventParam>9  receipt: TransactionReceipt | null10}1112class Block {13  hash: Bytes14  parentHash: Bytes15  unclesHash: Bytes16  author: Address17  stateRoot: Bytes18  transactionsRoot: Bytes19  receiptsRoot: Bytes20  number: BigInt21  gasUsed: BigInt22  gasLimit: BigInt23  timestamp: BigInt24  difficulty: BigInt25  totalDifficulty: BigInt26  size: BigInt | null27  baseFeePerGas: BigInt | null28}2930class Transaction {31  hash: Bytes32  index: BigInt33  from: Address34  to: Address | null35  value: BigInt36  gasLimit: BigInt37  gasPrice: BigInt38  input: Bytes39  nonce: BigInt40}4142class TransactionReceipt {43  transactionHash: Bytes44  transactionIndex: BigInt45  blockHash: Bytes46  blockNumber: BigInt47  cumulativeGasUsed: BigInt48  gasUsed: BigInt49  contractAddress: Address50  logs: Array<Log>51  status: BigInt52  root: Bytes53  logsBloom: Bytes54}5556class Log {57  address: Address58  topics: Array<Bytes>59  data: Bytes60  blockHash: Bytes61  blockNumber: Bytes62  transactionHash: Bytes63  transactionIndex: BigInt64  logIndex: BigInt65  transactionLogIndex: BigInt66  logType: string67  removed: bool | null68}

              Доступ к состоянию смарт-контракта

              The code generated by graph codegen also includes classes for the smart contracts used in the Subgraph. These can be used to access public state variables and call functions of the contract at the current block.

              Распространенным шаблоном является доступ к контракту, из которого исходит событие. Это достигается с помощью следующего кода:

              1// Импорт сгенерированного класса контракта и сгенерированного класса события Transfer2import { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract'3// Импорт созданного класса объекта4import { Transfer } from '../generated/schema'56export function handleTransfer(event: TransferEvent) {7  // Привязка контракта к адресу, сгенерировавшему событие8  let contract = ERC20Contract.bind(event.address)910   // Доступ к переменным состояния и функциям путем их вызова11   пусть erc20Symbol = контракт.символ()12}

              Transfer связывается с TransferEvent, чтобы избежать конфликта наименований с типом объекта

              Пока ERC20Contract в Ethereum имеет общедоступную функцию только для чтения, называемую symbol, ее можно вызвать с помощью .symbol(). Для общедоступных переменных состояния автоматически создается метод с таким же именем.

              Any other contract that is part of the Subgraph can be imported from the generated code and can be bound to a valid address.

              Обработка возвращенных вызовов

              Если методы Вашего контракта, доступные только для чтения, могут вернуться к предыдущему состоянию, то Вам следует решить эту проблему, вызвав сгенерированный метод контракта с префиксом try_.

              • Например, контракт Gravity предоставляет метод gravatarToOwner. Этот код сможет выполнить возврат в этом методе:
              1let gravity = Gravity.bind(event.address)2let callResult = gravity.try_gravatarToOwner(gravatar)3if (callResult.reverted) {4  log.info('getGravatar reverted', [])5} else {6  let owner = callResult.value7}

              Примечание: Graph Node, подключенный к клиенту Geth или Infura, может обнаружить не все откаты. Если Вы полагаетесь на это, мы рекомендуем использовать Graph Node, подключенный к клиенту Parity.

              Кодирование/декодирование ABI

              Данные могут быть закодированы и декодированы в соответствии с форматом кодирования ABI Ethereum с использованием функций encode и decode в модуле ethereum.

              1import { Address, BigInt, ethereum } from '@graphprotocol/graph-ts'23let tupleArray: Array<ethereum.Value> = [4  ethereum.Value.fromAddress(Address.fromString('0x0000000000000000000000000000000000000420')),5  ethereum.Value.fromUnsignedBigInt(BigInt.fromI32(62)),6]78let tuple = tupleArray as ethereum.Tuple910let encoded = ethereum.encode(ethereum.Value.fromTuple(tuple))!1112let decoded = ethereum.decode('(address,uint256)', encoded)

              Для получения дополнительной информации:

              • Спецификация ABI⁠
              • Кодирование/декодирование библиотека Rust/CLI⁠
              • Более [сложный пример] (https://github.com/graphprotocol/graph-node/blob/08da7cb46ddc8c09f448c5ea4b210c9021ea05ad/tests/integration-tests/host-exports/src/mapping.ts#L86⁠).

              Баланс адреса

              Баланс нативного токена адреса можно получить с помощью модуля ethereum. Эта функция доступна начиная с apiVersion: 0.0.9, которая определена subgraph.yaml. getBalance() извлекает баланс указанного адреса на конец блока, в котором инициировано событие.

              1import { ethereum } from '@graphprotocol/graph-ts'23let address = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')4let balance = ethereum.getBalance(address) // возвращает баланс в BigInt

              Проверьте, является ли адрес контрактом или EOA

              Чтобы проверить, является ли адрес адресом смарт-контракта или внешним адресом (EOA), используйте функцию hasCode() из модуля ethereum, которая вернет boolean. Эта функция доступна начиная с apiVersion: 0.0.9, которая определена subgraph.yaml.

              1import { ethereum } from '@graphprotocol/graph-ts'23let contractAddr = Address.fromString('0x2E645469f354BB4F5c8a05B3b30A929361cf77eC')4let isContract = ethereum.hasCode(contractAddr).inner // возвращает ложное значение56let eoa = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')7let isContract = ethereum.hasCode(eoa).inner // возвращает ложное значение

              Регистрация API

              1import { log } from '@graphprotocol/graph-ts'

              The log API allows Subgraphs to log information to the Graph Node standard output as well as Graph Explorer. Messages can be logged using different log levels. A basic format string syntax is provided to compose log messages from argument.

              API log включает в себя следующие функции:

              • log.debug(fmt: string, args: Array<string>): void - регистрирует сообщение об отладке.
              • log.info (fmt: string, args: Array<string>): void - регистрирует информационное сообщение.
              • log.warning(fmt: string, args: Array<string>): void - регистрирует предупреждение.
              • log.error(fmt: string, args: Array<string>): void - регистрирует сообщение об ошибке.
              • log.critical(fmt: string, args: Array<string>): void – logs a critical message and terminates the Subgraph.

              API log принимает строку формата и массив строковых значений. Затем он заменяет заполнители строковыми значениями из массива. Первый {} заполнитель заменяется первым значением в массиве, второй {} заполнитель заменяется вторым значением и так далее.

              1log.info('Message to be displayed: {}, {}, {}', [value.toString(), anotherValue.toString(), 'already a string'])

              Регистрация одного или нескольких значений

              Регистрация одного значения

              В приведенном ниже примере строковое значение “A” передается в массив, чтобы стать ['A'] перед тем как будет записано в лог:

              1let myValue = 'A'23export function handleSomeEvent(event: SomeEvent): void {4  // Отображает: "My value is: A"5  log.info('My value is: {}', [myValue])6}
              Регистрация одной записи из существующего массива

              В приведенном ниже примере регистрируется только первое значение массива аргументов, несмотря на то, что массив содержит три значения.

              1let myArray = ['A', 'B', 'C']23export function handleSomeEvent(event: SomeEvent): void {4  // Отображает : "My value is: A" (Несмотря на то, что в `log.info` передаются три значения)5  log.info('My value is: {}', myArray)6}

              Регистрация нескольких записей из существующего массива

              Для каждой записи в массиве arguments требуется свой собственный заполнитель {} в строке сообщения лога. В приведенном ниже примере в сообщении лога содержатся три заполнителя {}. По этой причине в myArray регистрируются все три значения.

              1let myArray = ['A', 'B', 'C']23export function handleSomeEvent(event: SomeEvent): void {4  // Отображает : "My first value is: A, second value is: B, third value is: C"5  log.info('My first value is: {}, second value is: {}, third value is: {}', myArray)6}
              Регистрация конкретной записи из существующего массива

              Чтобы отобразить определенное значение в массиве, необходимо указать индексированное значение.

              1export function handleSomeEvent(event: SomeEvent): void {2  // Отображает : "My third value is C"3  log.info('My third value is: {}', [myArray[2]])4}
              Регистрация информации о событии

              В приведенном ниже примере регистрируется номер блока, хэш блока и хэш транзакции из события:

              1import { log } from '@graphprotocol/graph-ts'23export function handleSomeEvent(event: SomeEvent): void {4  log.debug('Block number: {}, block hash: {}, transaction hash: {}', [5    event.block.number.toString(), // "47596000"6    event.block.hash.toHexString(), // "0x..."7    event.transaction.hash.toHexString(), // "0x..."8  ])9}

              IPFS API

              1import { ipfs } from '@graphprotocol/graph-ts'

              Smart contracts occasionally anchor IPFS files onchain. This allows mappings to obtain the IPFS hashes from the contract and read the corresponding files from IPFS. The file data will be returned as Bytes, which usually requires further processing, e.g. with the json API documented later on this page.

              При наличии хеша или пути IPFS чтение файла из IPFS выполняется следующим образом:

              1// Поместите это в обработчик события в мэппинге2let hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D'3let data = ipfs.cat(hash)45// Пути, подобные `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile`,6// которые включают файлы в директориях, также поддерживаются7let path = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile'8let data = ipfs.cat(path)

              Примечание: pfs.cat на данный момент не является детерминированным. Если файл не может быть получен по сети IPFS до истечения времени ожидания запроса, он вернет null. В связи с этим всегда стоит проверять результат на наличие null.

              С помощью ipfs.map можно также обрабатывать файлы большего размера в потоковом режиме. Функция ожидает, что хэш или путь к файлу IPFS, имя обратного вызова и флаги изменят его поведение:

              1import { JSONValue, Value } from '@graphprotocol/graph-ts'23export function processItem(value: JSONValue, userData: Value): void {4  // Смотрите документацию по JsonValue для получения подробной информации о работе5  // со значениями JSON6  let obj = value.toObject()7  let id = obj.get('id')8  let title = obj.get('title')910  if (!id || !title) {11    return12  }1314  // Обратные вызовы также могут создавать объекты15  let newItem = new Item(id)16  newItem.title = title.toString()17  newitem.parent = userData.toString() // Установите для родителя значение "parentId"18  newitem.save()19}2021// Поместите это внутри обработчика событий в мэппинге22ipfs.map('Qm...', 'processItem', Value.fromString('parentId'), ['json'])2324// В качестве альтернативы, используйте `ipfs.mapJSON`25ipfs.mapJSON('Qm...', 'processItem', Value.fromString('parentId'))

              Единственным поддерживаемым в настоящее время флагом является json, который должен быть передан в ipfs.map. С флагом json файл IPFS должен состоять из серии значений JSON, по одному значению в строке. Вызов ipfs.map прочитает каждую строку в файле, десериализует ее в JSONValue и совершит обратный вызов для каждой из них. Затем обратный вызов может использовать операции с объектами для хранения данных из JSONValue. Изменения объекта сохраняются только после успешного завершения обработчика, вызвавшего ipfs.map; в то же время они хранятся в памяти, и поэтому размер файла, который может обработать ipfs.map, ограничен.

              On success, ipfs.map returns void. If any invocation of the callback causes an error, the handler that invoked ipfs.map is aborted, and the Subgraph is marked as failed.

              Crypto API

              1import { crypto } from '@graphprotocol/graph-ts'

              API crypto делает криптографические функции доступными для использования в мэппингах. На данный момент есть только один:

              • crypto.keccak256(input: ByteArray): ByteArray

              JSON API

              1import { json, JSONValueKind } from '@graphprotocol/graph-ts'

              Данные JSON могут быть разобраны с помощью json API:

              • json.fromBytes(data: Bytes): JSONValue – выполняет разбор данных JSON из массива Bytes, интерпретируемого как допустимая последовательность UTF-8
              • json.try_fromBytes(data: Bytes): Result<JSONValue, boolean> – безопасная версия json.fromBytes, возвращает вариант ошибки, если выполнение разбора не удалось
              • json.fromString(data: string): JSONValue – выполняет разбор данных JSON из допустимой UTF-8 String
              • json.try_fromString(data: string): Result<JSONValue, boolean> – безопасная версия json.fromString, возвращает вариант ошибки, если выполнение разбора не удалось

              Класс JSONValue предоставляет способ извлечения значений из произвольного документа JSON. Поскольку значениями JSON могут быть логические значения, числа, массивы и многое другое, JSONValue поставляется со свойством kind для проверки типа значения:

              1let value = json.fromBytes(...)2if (value.kind == JSONValueKind.BOOL) {3  ...4}

              Кроме того, существует способ проверить, является ли значение null:

              • value.isNull(): boolean

              Когда тип значения определен, его можно преобразовать во встроенный тип, используя один из следующих методов:

              • value.toBool(): boolean
              • value.toI64(): i64
              • value.toF64(): f64
              • value.toBigInt(): BigInt
              • value.toString(): string
              • value.toArray(): Array<JSONValue> - (а затем преобразовать JSONValue одним из 5 методов, описанных выше)

              Справка по преобразованию типов

              Источник(и)Место назначенияФункция преобразования
              AddressBytesотсутствует
              AddressStrings.toHexString()
              BigDecimalStrings.toString()
              BigIntBigDecimals.toBigDecimal()
              BigIntString (hexadecimal)s.toHexString() или s.toHex()
              BigIntString (unicode)s.toString()
              BigInti32s.toI32()
              BooleanBooleanотсутствует
              Bytes (signed)BigIntBigInt.fromSignedBytes(s)
              Bytes (unsigned)BigIntBigInt.fromUnsignedBytes(s)
              BytesString (hexadecimal)s.toHexString() или s.toHex()
              BytesString (unicode)s.toString()
              BytesString (base58)s.toBase58()
              Bytesi32s.toI32()
              Bytesu32s.toU32()
              BytesJSONjson.fromBytes(s)
              int8i32отсутствует
              int32i32отсутствует
              int32BigIntBigInt.fromI32(s)
              uint24i32отсутствует
              int64 - int256BigIntотсутствует
              uint32 - uint256BigIntотсутствует
              JSONbooleans.toBool()
              JSONi64s.toU64()
              JSONu64s.toU64()
              JSONf64s.toF64()
              JSONBigInts.toBigInt()
              JSONstrings.toString()
              JSONArrays.toArray()
              JSONObjects.toObject()
              StringAddressAddress.fromString(s)
              BytesAddressAddress.fromBytes(s)
              StringBigIntBigInt.fromString(s)
              StringBigDecimalBigDecimal.fromString(s)
              String (hexadecimal)BytesByteArray.fromHexString(s)
              String (UTF-8)BytesByteArray.fromUTF8(s)

              Метаданные источника данных

              Вы можете проверить адрес контракта, сеть и контекст источника данных, который вызвал обработчик, через пространство имен DataSource:

              • dataSource.address(): Address
              • dataSource.network(): string
              • dataSource.context(): DataSourceContext

              Объект и DataSourceContext

              Базовый класс Entity и дочерний класс DataSourceContext имеют помощников для динамической установки и получения полей:

              • setString(key: string, value: string): void
              • setI32(key: string, value: i32): void
              • setBigInt(key: string, value: BigInt): void
              • setBytes(key: string, value: Bytes): void
              • setBoolean(key: string, value: bool): void
              • setBigDecimal(key, value: BigDecimal): void
              • getString(key: string): string
              • getI32(key: string): i32
              • getBigInt(key: string): BigInt
              • getBytes(key: string): Bytes
              • getBoolean(key: string): boolean
              • getBigDecimal(key: string): BigDecimal

              DataSourceContext в манифесте

              The context section within dataSources allows you to define key-value pairs that are accessible within your Subgraph mappings. The available types are Bool, String, Int, Int8, BigDecimal, Bytes, List, and BigInt.

              Ниже приведен пример YAML, иллюстрирующий использование различных типов в разделе context:

              1dataSources:2  - kind: ethereum/contract3    name: ContractName4    network: mainnet5    context:6      bool_example:7        type: Bool8        data: true9      string_example:10        type: String11        data: 'hello'12      int_example:13        type: Int14        data: 4215      int8_example:16        type: Int817        data: 12718      big_decimal_example:19        type: BigDecimal20        data: '10.99'21      bytes_example:22        type: Bytes23        data: '0x68656c6c6f'24      list_example:25        type: List26        data:27          - type: Int28            data: 129          - type: Int30            data: 231          - type: Int32            data: 333      big_int_example:34        type: BigInt35        data: '1000000000000000000000000'
              • Bool: Определяет логическое значение (true или false).
              • String: Определяет строковое значение.
              • Int: Определяет 32-разрядное целое число.
              • Int8: Определяет 8-разрядное целое число.
              • BigDecimal: Определяет десятичное число. Необходимо заключить в кавычки.
              • Bytes: Определяет шестнадцатеричную строку.
              • List: Определяет список элементов. Для каждого элемента необходимо указать его тип и данные.
              • BigInt: Определяет большое целочисленное значение. Необходимо заключить в кавычки из-за большого размера.

              This context is then accessible in your Subgraph mapping files, enabling more dynamic and configurable Subgraphs.

              ⁠Редактировать на GitHub⁠

              ВведениеCommon Issues
              На этой странице
              • Референс API
              • Версии
              • Встроенные типы
              • Store API
              • Ethereum API
              • Регистрация API
              • IPFS API
              • Crypto API
              • JSON API
              • Справка по преобразованию типов
              • Метаданные источника данных
              • Объект и DataSourceContext
              • DataSourceContext в манифесте
              The GraphСтатусТестовая сетьБрундовые ресурсыФорумБезопасностьПолитика конфиденциальностиУсловия обслуживания