subgraphs > Developing > Creating > AssemblyScript API > AssemblyScript API

AssemblyScript API

Reading time: 30 min

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 library (graph-ts)
  • Code generated from subgraph files by graph codegen

You can also add other libraries as dependencies, as long as they are compatible with AssemblyScript.

Since language mappings are written in AssemblyScript, it is useful to review the language and standard library features from the AssemblyScript wiki.

API リファレンス

このセクションへのリンク

@graphprotocol/graph-tsライブラリは、以下の API を提供しています:

  • Ethereum スマートコントラクト、イベント、ブロック、トランザクション、Ethereum の値を扱うためのethereumAPI
  • エンティティをグラフノードのストアからロードしたり、ストアに保存したりするstoreAPI
  • A log API to log messages to the Graph Node output and Graph Explorer.
  • IPFS からファイルをロードするipfsAPI
  • JSON データを解析するためのjsonAPI
  • 暗号機能を使用するためのcryptoAPI
  • Ethereum、JSON、GraphQL、AssemblyScript など、異なるタイプのシステム間で変換するための低レベルプリミティブ

サブグラフマニフェストapiVersionは、特定のサブグラフのマッピングAPIバージョンを指定します。このバージョンは、Graph Nodeによって実行されます。

バージョンリリースノート
0.0.9Adds new host functions eth_get_balance & hasCode
0.0.8Adds validation for existence of fields in the schema when saving an entity.
0.0.7Ethereum タイプに TransactionReceiptLog クラスを追加
Ethereum Event オブジェクトに receipt フィールドを追加。
0.0.6Ethereum Transactionオブジェクトにnonceフィールドを追加
Ethereum BlockオブジェクトにbaseFeePerGasを追加。
0.0.5AssemblyScriptはバージョン0.19.10にアップグレードされました(このバージョンアップには変更点が含まれていますので Migration Guide) をご覧ください)。
ethereum.transaction.gasUsedの名前がethereum.transaction.gasLimitに変更
0.0.4Ethereum SmartContractCall オブジェクトにfunctionSignatureフィールドを追加
0.0.3イーサリアムコールオブジェクトにfromフィールドを追加
etherem.call.addressethereum.call.toに変更。
0.0.2Ethereum Transaction オブジェクトに inputフィールドを追加

Documentation on the base types built into AssemblyScript can be found in the AssemblyScript wiki.

以下の追加型は@graphprotocol/graph-tsで提供されています。

'@graphprotocol/graph-ts'から{ ByteArray } をインポートします。

ByteArrayは、u8の配列を表します。

Construction

  • fromI32(x: i32): ByteArray - Decomposes x into bytes.
  • fromHexString(hex:: 文字列): ByteArray - 入力長は偶数でなければなりません。0xのプレフィックスはオプションとなります。

Type conversions

  • toHexString(): string - 0x を先頭に持つ 16 進文字列に変換します。
  • toString(): string - バイトを UTF-8 文字列として解釈します。
  • toBase58(): string - バイトをbase58の文字列にエンコードします。
  • toU32(): u32 - バイトをリトルエンディアンの u32 として解釈し、オーバーフローした場合にスローします。
  • toI32(): i32 - バイト配列をリトルエンディアンの i32 として解釈し、オーバーフローした場合にスローします。

Operators

  • equals(y: ByteArray): bool-x == y` と書くことができます。
  • concat(other: ByteArray) : ByteArray - thisother を直接続けた ByteArray を返します。
  • concatI32(other: i32) : ByteArray - thisother のバイト表現を直接続けた ByteArray を返します。
'@graphprotocol/graph-ts'から { BigDecimal } をインポートします。

BigDecimalは、任意の精度の小数を表現するために使用されます。

Note: Internally BigDecimal is stored in IEEE-754 decimal128 floating-point format, which supports 34 decimal digits of significand. This makes BigDecimal unsuitable for representing fixed-point types that can span wider than 34 digits, such as a Solidity ufixed256x18 or equivalent.

Construction

  • constructor(bigInt: BigInt) - BigInt から BigDecimal を生成します。
  • static fromString(s: string): BigDecimal - 10進数の文字列をパースします。

Type conversions

  • toString(): string` - 10進数の文字列を表示します。

Math

  • 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 と書くことができます。
  • ge(y: BigDecimal): boolと書くことができます。
  • neg(): BigDecimal - -x と書くことができます。
'@graphprotocol/graph-ts'から { BigInt } をインポートします。

BigInt は大きな整数を表現するために使用されます。これには uint32 から uint256int64 から int256 型のイーサリアムの値が含まれます。uint32以下の値、例えばint32uint24int8は全てi32` として表現されます。

BigIntクラスの API は以下の通りです。

Construction

  • BigInt.fromI32(x: i32): BigInt - i32 から BigInt を作成すします。

  • BigInt.fromString(s: string): BigInt- 文字列から BigInt をパースします。

  • BigInt.fromUnsignedBytes(x: Bytes): BigInt - bytes を符号なし、リトルエンディアンの整数として解釈します。入力がビッグエンディアンの場合は、最初に .reverse() を呼び出します。

  • BigInt.fromSignedBytes(x: Bytes): BigInt - bytes を符号付きのリトルエンディアン整数として解釈します。入力がビッグエンディアンの場合は、最初に .reverse() を呼び出します。

    Type conversions

  • x.toHex(): string - BigInt を16進数の文字列に変換します。

  • x.toString(): string - BigInt を10進数の文字列に変換します。

  • x.toI32(): i32 - BigInti32 として返す。値が i32 に収まらない場合は失敗します。まず x.isI32() をチェックするのが良いでしょう。

  • x.toBigDecimal(): BigDecimal - 小数部のない10進数に変換します。

Math

  • 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 - 小数点で割り、10進数の結果を返します。
  • 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 と書くことができます。
'@graphprotocol/graph-ts'から { TypedMap } をインポートします。

TypedMapはキーと値のペアを格納するために使用することができます。この例](https://github.com/graphprotocol/aragon-subgraph/blob/29dd38680c5e5104d9fdc2f90e740298c67e4a31/individual-dao-subgraph/mappings/constants.ts#L51)を参照してください。

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 のキーと値のペアを返します。
  • map.get(key: K): V | null - key の値を返して、key がマップに存在しない場合は null を返します。
  • map.isSet(key: K): bool - key がマップに存在すれば true を返し、存在しなければ false を返します。
'@graphprotocol/graph-ts'から { Bytes } をインポートします。

Bytesは任意の長さのバイト配列を表現するために使用されます。これには bytesbytes32 型などのイーサリアム値が含まれます。

BytesクラスはAssemblyScriptのUint8Arrayを拡張したもので、Uint8Arrayのすべての機能に加え、以下の新しいメソッドをサポートしています:

Construction

  • fromHexString(hex: string) : Bytes - 偶数桁の16進数からなる文字列 hexByteArray に変換します。文字列 hex はオプションで 0x から始めることができます。
  • fromI32(i: i32): Bytes - i をバイト配列に変換します。

Type conversions

  • b.toHex() - 配列のバイト数を16進数で表した文字列を返します。
  • b.toString() - 配列のバイト列をユニコード文字列に変換します。
  • b.toBase58() - イーサリアムバイトの値を base58 エンコーディングに変換します (IPFS ハッシュに使用)

Operators

  • b.concat(other: Bytes): Bytes - - thisother を直接連結した Bytes を返します。
  • b.concatI32(other: i32) : ByteArray - thisother のバイト表現を直接続けた Bytes を返します。
'@graphprotocol/graph-ts'から { Address } をインポートします。

アドレス Address はイーサリアムのアドレス address 値を表現するために Bytes を継承しています。

Bytesの API の上に以下のメソッドを追加しています。

  • Address.fromString(s: string): Address - 16進数文字列から Address を作成します。
  • Address.fromBytes(b: Bytes): Address - b から Address を生成します。これは正確に20バイト長でなければなりません。それ以下のバイト数の値を渡すとエラーになります。
'@graphprotocol/graph-ts'から { store } をインポートします。

Store API は、グラフノードのストアにエンティティを読み込んだり、保存したり、削除したりすることができます。

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 のイベントからエンティティを作成する際の一般的なパターンを以下に示します。

// Import the Transfer event class generated from the ERC20 ABI
import { Transfer as TransferEvent } from '../generated/ERC20/ERC20'
// Import the Transfer entity type generated from the GraphQL schema
import { Transfer } from '../generated/schema'
// Transfer event handler
export function handleTransfer(event: TransferEvent): void {
// Create a Transfer entity, using the transaction hash as the entity ID
let id = event.transaction.hash
let transfer = new Transfer(id)
// Set properties on the entity, using the event parameters
transfer.from = event.params.from
transfer.to = event.params.to
transfer.amount = event.params.amount
// Save the entity to the store
transfer.save()
}

チェーンの処理中に Transfer イベントが発生すると、生成された Transfer 型(エンティティ型との名前の衝突を避けるために、ここでは TransferEvent のエイリアス)を使用して handleTransfer イベントハンドラに渡されます。この型はイベントの親トランザクションやそのパラメータなどのデータにアクセスすることを可能にします。

Each entity must have a unique ID to avoid collisions with other entities. It is fairly common for event parameters to include a unique identifier that can be used.

Note: Using the transaction hash as the ID assumes that no other events in the same transaction create entities with this hash as the ID.

ストアからのエンティティの読み込み

このセクションへのリンク

エンティティがすでに存在する場合、以下の方法でストアからロードすることができます。

let id = event.transaction.hash // or however the ID is constructed
let transfer = Transfer.load(id)
if (transfer == null) {
transfer = new Transfer(id)
}
// Use the Transfer entity as before

As the entity may not exist in the store yet, the load method returns a value of type Transfer | null. It may be necessary to check for the null case before using the value.

Note: Loading entities is only necessary if the changes made in the mapping depend on the previous data of an entity. See the next section for the two ways of updating existing entities.

ブロック内で作成されたエンティティの検索

このセクションへのリンク

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 on-chain 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.
let id = event.transaction.hash // または ID が構築される方法
let transfer = Transfer.loadInBlock(id)
if (transfer == null) {
transfer = 新しい転送(id)
}
// 以前と同様に Transfer エンティティを使用します

注: 指定されたブロックにエンティティが作成されていない場合、ストア内に指定された ID を持つエンティティが存在する場合でも、loadInBlock は null を返します。

派生エンティティの検索

このセクションへのリンク

graph-node v0.31.0、@graphprotocol/graph-ts v0.31.0、および @graphprotocol/graph-cli v0.51.0 以降、loadMany メソッドが利用可能です。

これにより、イベント ハンドラー内から派生エンティティ フィールドをロードできるようになります。たとえば、次のスキーマがあるとします。

type Token @entity {
id: ID!
holder: Holder!
color: String
}
type Holder @entity {
id: ID!
tokens: [Token!]! @derivedFrom(field: "holder")
}

次のコードは、Holder エンティティの派生元である Token エンティティを読み込みます。

let holder = Holder.load('test-id')
// Load the Token entities associated with a given holder
let tokens = holder.tokens.load()

既存のエンティティの更新

このセクションへのリンク

既存のエンティティを更新するには 2 つの方法があります。

  1. Transfer.load(id)などでエンティティをロードし、エンティティにプロパティを設定した後、.save()でストアに戻す。
  2. 単純にnew Transfer(id)でエンティティを作成し、エンティティにプロパティを設定し、ストアに .save()します。 エンティティがすでに存在する場合は、変更内容がマージされます。

プロパティの変更は、生成されたプロパティセッターのおかげで、ほとんどの場合、簡単です。

let transfer = new Transfer(id)
transfer.from = ...
transfer.to = ...
transfer.amount = ...

また、次の 2 つの命令のいずれかで、プロパティの設定を解除することも可能です。

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

これは、オプションのプロパティ、つまり GraphQL で!を付けずに宣言されているプロパティでのみ機能します。 例としては、owner: Bytesやamount: BigIntです。

エンティティから配列を取得すると、その配列のコピーが作成されるため、配列のプロパティの更新には少し手間がかかります。 つまり、配列を変更した後は、明示的に配列のプロパティを設定し直す必要があります。 次の例では、entity が numbers: [BigInt!]! を持っていると仮定します。

// This won't work
entity.numbers.push(BigInt.fromI32(1))
entity.save()
// This will work
let numbers = entity.numbers
numbers.push(BigInt.fromI32(1))
entity.numbers = numbers
entity.save()

ストアからのエンティティの削除

このセクションへのリンク

現在、生成された型を使ってエンティティを削除する方法はありません。 代わりに、エンティティを削除するには、エンティティタイプの名前とエンティティ ID をstore.removeに渡す必要があります。

mport { store } from '@graphprotocol/graph-ts'
...
let id = event.transaction.hash
store.remove('Transfer', id)

Ethereum API は、スマートコントラクト、パブリックステート変数、コントラクト関数、イベント、トランザクション、ブロック、および Ethereum データのエンコード/デコードへのアクセスを提供します。

Ethereum タイプのサポート

このセクションへのリンク

エンティティと同様に、graph codegenは、サブグラフで使用されるすべてのスマートコントラクトとイベントのためのクラスを生成します。 このためには、コントラクト ABI がサブグラフマニフェストのデータソースの一部である必要があります。 通常、ABI ファイルはabis/フォルダに格納されています。

生成されたクラスでは、Ethereum Typeとbuilt-in types間の変換が舞台裏で行われるため、サブグラフ作成者はそれらを気にする必要がありません。

以下の例で説明します。 以下のようなサブグラフのスキーマが与えられます。

type Transfer @entity {
id: Bytes!
from: Bytes!
to: Bytes!
amount: BigInt!
}

イーサリアムの Transfer(address,address,uint256) イベントシグネチャを使用すると、from, to, uint256 型の値は AddressBigInt に変換され、Transfer エンティティの Bytes! プロパティと BigInt! プロパティに渡すことができます:

let id = event.transaction.hash
let transfer = new Transfer(id)
transfer.from = event.params.from
transfer.to = event.params.to
transfer.amount = event.params.amount
transfer.save()

イベントとブロック/トランザクションデータ

このセクションへのリンク

前述の例のTransferイベントのように、イベントハンドラに渡された Ethereum イベントは、イベントパラメータへのアクセスだけでなく、その親となるトランザクションや、それらが属するブロックへのアクセスも提供します。 event インスタンスからは、以下のデータを取得することができます(これらのクラスは、 graph-tsのethereumモジュールの一部です)。

class Event {
address: Address
logIndex: BigInt
transactionLogIndex: BigInt
logType: string | null
block: Block
transaction: Transaction
parameters: Array<EventParam>
receipt: TransactionReceipt | null
}
class Block {
hash: Bytes
parentHash: Bytes
unclesHash: Bytes
author: Address
stateRoot: Bytes
transactionsRoot: Bytes
receiptsRoot: Bytes
number: BigInt
gasUsed: BigInt
gasLimit: BigInt
timestamp: BigInt
difficulty: BigInt
totalDifficulty: BigInt
size: BigInt | null
baseFeePerGas: BigInt | null
}
class Transaction {
hash: Bytes
index: BigInt
from: Address
to: Address | null
value: BigInt
gasLimit: BigInt
gasPrice: BigInt
input: Bytes
nonce: BigInt
}
class TransactionReceipt {
transactionHash: Bytes
transactionIndex: BigInt
blockHash: Bytes
blockNumber: BigInt
cumulativeGasUsed: BigInt
gasUsed: BigInt
contractAddress: Address
logs: Array<Log>
status: BigInt
root: Bytes
logsBloom: Bytes
}
class Log {
address: Address
topics: Array<Bytes>
data: Bytes
blockHash: Bytes
blockNumber: Bytes
transactionHash: Bytes
transactionIndex: BigInt
logIndex: BigInt
transactionLogIndex: BigInt
logType: string
removed: bool | null
}

スマートコントラクトの状態へのアクセス

このセクションへのリンク

graph codegenが生成するコードには、サブグラフで使用されるスマートコントラクトのクラスも含まれています。 これらを使って、パブリックな状態変数にアクセスしたり、現在のブロックにあるコントラクトの関数を呼び出したりすることができます。

よくあるパターンは、イベントが発生したコントラクトにアクセスすることです。 これは以下のコードで実現できます。

// Import the generated contract class and generated Transfer event class
import { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract'
// Import the generated entity class
import { Transfer } from '../generated/schema'
export function handleTransfer(event: TransferEvent) {
// Bind the contract to the address that emitted the event
let contract = ERC20Contract.bind(event.address)
// Access state variables and functions by calling them
let erc20Symbol = contract.symbol()
}

Transferは、エンティティタイプとの名前の衝突を避けるために、ここではTransferEventにエイリアスされています。

Ethereum の ERC20Contractにsymbolというパブリックな読み取り専用の関数があれば、.symbol()で呼び出すことができます。 パブリックな状態変数については、同じ名前のメソッドが自動的に作成されます。

サブグラフの一部である他のコントラクトは、生成されたコードからインポートすることができ、有効なアドレスにバインドすることができます。

リバートされた呼び出しの処理

このセクションへのリンク

If the read-only methods of your contract may revert, then you should handle that by calling the generated contract method prefixed with try_.

  • For example, the Gravity contract exposes the gravatarToOwner method. This code would be able to handle a revert in that method:
let gravity = Gravity.bind(event.address)
let callResult = gravity.try_gravatarToOwner(gravatar)
if (callResult.reverted) {
log.info('getGravatar reverted', [])
} else {
let owner = callResult.value
}

Note: A Graph node connected to a Geth or Infura client may not detect all reverts. If you rely on this, we recommend using a Graph Node connected to a Parity client.

符号化/復号化 ABI

このセクションへのリンク

ethereumモジュールのencode/ decode関数を使用して、Ethereum の ABI エンコーディングフォーマットに従ってデータをエンコード/デコードすることができます。

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

その他の情報:

The native token balance of an address can be retrieved using the ethereum module. This feature is available from apiVersion: 0.0.9 which is defined subgraph.yaml. The getBalance() retrieves the balance of the specified address as of the end of the block in which the event is triggered.

import { ethereum } from '@graphprotocol/graph-ts'
let address = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')
let balance = ethereum.getBalance(address) // returns balance in BigInt

Check if an Address is a Contract or EOA

このセクションへのリンク

To check whether an address is a smart contract address or an externally owned address (EOA), use the hasCode() function from the ethereum module which will return boolean. This feature is available from apiVersion: 0.0.9 which is defined subgraph.yaml.

import { ethereum } from '@graphprotocol/graph-ts'
let contractAddr = Address.fromString('0x2E645469f354BB4F5c8a05B3b30A929361cf77eC')
let isContract = ethereum.hasCode(contractAddr).inner // returns true
let eoa = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')
let isContract = ethereum.hasCode(eoa).inner // returns false
'@graphprotocol/graph-ts'から{ log } をインポートします。

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.

log API には以下の機能があります:

  • 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 - クリティカル・メッセージを記録して、サブグラフを終了します。

log API は、フォーマット文字列と文字列値の配列を受け取ります。 そして、プレースホルダーを配列の文字列値で置き換えます。 最初のプレースホルダーは配列の最初の値に置き換えられ、2 番目のプレースホルダーは 2 番目の値に置き換えられ、以下のようになります。

log.info('表示されるメッセージ。{}, {}, {}', [value.toString(), anotherValue.toString(), 'すでに文字列'])

1 つまたは複数の値を記録する

このセクションへのリンク
1 つの値を記録する
このセクションへのリンク

以下の例では、文字列値 "A" を配列に渡して['A'] にしてからログに記録しています。

let myValue = 'A'
export function handleSomeEvent(event: SomeEvent): void {
// Displays : "My value is: A"
log.info('My value is: {}', [myValue])
}
既存の配列から 1 つのエントリをロギングする
このセクションへのリンク

以下の例では、配列に 3 つの値が含まれているにもかかわらず、引数の配列の最初の値だけがログに記録されます。

let myArray = ['A', 'B', 'C']
export function handleSomeEvent(event: SomeEvent): void {
// Displays : "My value is: A" (Even though three values are passed to `log.info`)
log.info('My value is: {}', myArray)
}

既存の配列から複数のエントリを記録する

このセクションへのリンク

引数配列の各エントリは、ログメッセージ文字列に独自のプレースホルダーを必要とします。 以下の例では、ログメッセージに 3 つのプレースホルダーが含まれています。 このため、myArrayの 3 つの値すべてがログに記録されます。

let myArray = ['A', 'B', 'C']
export function handleSomeEvent(event: SomeEvent): void {
// Displays : "My first value is: A, second value is: B, third value is: C"
log.info('My first value is: {}, second value is: {}, third value is: {}', myArray)
}
既存の配列から特定のエントリをロギングする
このセクションへのリンク

配列内の特定の値を表示するには、インデックス化された値を指定する必要があります。

export function handleSomeEvent(event: SomeEvent): void {
// Displays : "My third value is C"
log.info('My third value is: {}', [myArray[2]])
}
イベント情報の記録
このセクションへのリンク

以下の例では、イベントからブロック番号、ブロックハッシュ、トランザクションハッシュをログに記録しています。

'@graphprotocol/graph-ts'から { log } をインポートします。
export function handleSomeEvent(event: SomeEvent): void {
log.debug('Block number: {}, block hash: {}, transaction hash: {}', [
event.block.number.toString(), // "47596000"
event.block.hash.toHexString(), // "0x..."
event.transaction.hash.toHexString(), // "0x..."
])
}
'@graphprotocol/graph-ts'から { ipfs } をインポートします。

スマートコントラクトは時折、チェーン上の IPFS ファイルをアンカリングします。 これにより、マッピングはコントラクトから IPFS ハッシュを取得し、IPFS から対応するファイルを読み取ることができます。 ファイルのデータはBytesとして返されますが、通常は、このページで後述する json API などを使ってさらに処理する必要があります。

IPFS のハッシュやパスが与えられた場合、IPFS からのファイルの読み込みは以下のように行われます。

// Put this inside an event handler in the mapping
let hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D'
let data = ipfs.cat(hash)
// Paths like `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile`
// that include files in directories are also supported
let path = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile'
let data = ipfs.cat(path)

注: ipfs.cat は今のところ決定論的なものではありません。もし要求がタイムアウトする前にIPFSネットワーク上でファイルを取得できなければ、 nullを返します。このため、常に null の結果をチェックする価値があります。

また、ipfs.map.を使って、大きなファイルをストリーミングで処理することも可能です。 この関数は、IPFS ファイルのハッシュまたはパス、コールバックの名前、そして動作を変更するためのフラグを受け取ります。

import { JSONValue, Value } from '@graphprotocol/graph-ts'
export function processItem(value: JSONValue, userData: Value): void {
// See the JSONValue documentation for details on dealing
// with JSON values
let obj = value.toObject()
let id = obj.get('id')
let title = obj.get('title')
if (!id || !title) {
return
}
// Callbacks can also created entities
let newItem = new Item(id)
newItem.title = title.toString()
newitem.parent = userData.toString() // Set parent to "parentId"
newitem.save()
}
// Put this inside an event handler in the mapping
ipfs.map('Qm...', 'processItem', Value.fromString('parentId'), ['json'])
// Alternatively, use `ipfs.mapJSON`
ipfs.mapJSON('Qm...', 'processItem', Value.fromString('parentId'))

現在サポートされているフラグは json だけで、これは ipfs.map に渡さなければなりません。json フラグを指定すると、IPFS ファイルは一連の JSON 値で構成されます。ipfs.map を呼び出すと、ファイルの各行を読み込んで JSONValue にデシリアライズし、それぞれのコールバックを呼び出します。コールバックは JSONValue からデータを格納するためにエンティティ操作を使用することができます。エンティティの変更は、ipfs.map を呼び出したハンドラが正常に終了したときのみ保存されます。その間はメモリ上に保持されるので、ipfs.map が処理できるファイルのサイズは制限されます。

成功すると,ipfs.mapは voidを返します。 コールバックの呼び出しでエラーが発生した場合、ipfs.mapを呼び出したハンドラは中止され、サブグラフは失敗とマークされます。

'@graphprotocol/graph-ts'から { crypto } をインポートします。

crypto API は、マッピングで使用できる暗号化関数を提供します。 今のところ、1 つしかありません。

  • crypto.keccak256(input: ByteArray): ByteArray
'@graphprotocol/graph-ts'から{ json, JSONValueKind } をインポートします。

JSON データは、json API を使って解析することができます。

  • json.fromBytes(data: Bytes): JSONValue - 有効な UTF-8 シーケンスとして解釈され、 Bytes 配列から JSON データをパースします。
  • json.try_fromBytes(data: Bytes): Result<JSONValue, boolean> - json.fromBytes の安全バージョンで、パースに失敗した場合はエラーバリアントを返します。
  • json.fromString(data: string): JSONValue - 有効な UTF-8 String から JSON データをパースします。
  • json.try_fromString(data: string): Result<JSONValue, boolean> - json.fromString の安全バージョンで、パースに失敗した場合はエラーバリアントを返します。

JSONValue クラスは、任意の JSON ドキュメントから値を引き出す方法を提供します。 JSON の値には、ブーリアン、数値、配列などがあるため、JSONValueには、値の種類をチェックするためのkindプロパティが付属しています。

let value = json.fromBytes(...)
if (value.kind == JSONValueKind.BOOL) {
...
}

さらに、値がnullかどうかをチェックするメソッドもあります`:

  • value.isNull(): boolean

値の型が確実な場合は、以下のいずれかの方法で組み込み型に変換することができます:

  • value.toBool(): boolean
  • value.toI64(): i64
  • value.toF64(): f64
  • value.toBigInt(): BigInt
  • value.toString(): string
  • value.toArray(): Array<JSONValue> - (その後、上記の 5 つのメソッドのいずれかを使用して JSONValue を変換します)

タイプ 変換参照

このセクションへのリンク
Source(s)DestinationConversion function
AddressBytesnone
AddressStrings.toHexString()
BigDecimalStrings.toString()
BigIntBigDecimals.toBigDecimal()
BigIntString (hexadecimal)s.toHexString() or s.toHex()
BigIntString (unicode)s.toString()
BigInti32s.toI32()
BooleanBooleannone
Bytes (signed)BigIntBigInt.fromSignedBytes(s)
Bytes (unsigned)BigIntBigInt.fromUnsignedBytes(s)
BytesString (hexadecimal)s.toHexString() or s.toHex()
BytesString (unicode)s.toString()
BytesString (base58)s.toBase58()
Bytesi32s.toI32()
Bytesu32s.toU32()
BytesJSONjson.fromBytes(s)
int8i32none
int32i32none
int32BigIntBigint.fromI32(s)
uint24i32none
int64 - int256BigIntnone
uint32 - uint256BigIntnone
JSONbooleans.toBool()
JSONi64s.toI64()
JSONu64s.toU64()
JSONf64s.toF64()
JSONBigInts.toBigInt()
JSONstrings.toString()
JSONArrays.toArray()
JSONObjects.toObject()
StringAddressAddress.fromString(s)
BytesAddressAddress.fromString(s)
StringBigIntBigDecimal.fromString(s)
StringBigDecimalBigDecimal.fromString(s)
String (hexadecimal)BytesByteArray.fromHexString(s)
String (UTF-8)BytesByteArray.fromUTF8(s)

データソースのメタデータ

このセクションへのリンク

ハンドラを起動したデータソースのコントラクトアドレス、ネットワーク、コンテキストは、以下のようにして調べることができます。

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

エンティティと DataSourceContext

このセクションへのリンク

ベースとなるエンティティクラスと子クラスの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

このセクションへのリンク

DataSourcescontextセクションでは、サブグラフマッピング内でアクセス可能なキーと値のペアを定義することができます。使用可能な型はBoolStringIntInt8BigDecimalBytesListBigInt` です。

以下は context セクションのさまざまな型の使い方を示す YAML の例です:

dataSources:
- kind: ethereum/contract
name: ContractName
network: mainnet
context:
bool_example:
type: Bool
data: true
string_example:
type: String
data: 'hello'
int_example:
type: Int
data: 42
int8_example:
type: Int8
data: 127
big_decimal_example:
type: BigDecimal
data: '10.99'
bytes_example:
type: Bytes
data: '0x68656c6c6f'
list_example:
type: List
data:
- type: Int
data: 1
- type: Int
data: 2
- type: Int
data: 3
big_int_example:
type: BigInt
data: '1000000000000000000000000'
  • Bool: Specifies a Boolean value (true or false).
  • String: Specifies a String value.
  • Int: Specifies a 32-bit integer.
  • Int8: Specifies an 8-bit integer.
  • BigDecimal: Specifies a decimal number. Must be quoted.
  • Bytes: Specifies a hexadecimal string.
  • List: Specifies a list of items. Each item needs to specify its type and data.
  • BigInt: Specifies a large integer value. Must be quoted due to its large size.

このコンテキストは、サブグラフのマッピング・ファイルからアクセスでき、よりダイナミックで設定可能なサブグラフを実現します。

ページを編集

Advance Subgraph Features
AssemblyScriptのよくある問題
ページを編集