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 .
Learn what built-in APIs can be used when writing subgraph mappings. There are two kinds of APIs available out of the box:
You can also add other libraries as dependencies, as long as they are compatible with .
Since language mappings are written in AssemblyScript, it is useful to review the language and standard library features from the .
@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.9 | Adds new host functions & |
0.0.8 | Adds validation for existence of fields in the schema when saving an entity. |
0.0.7 | Ethereum タイプに TransactionReceipt と Log クラスを追加Ethereum Event オブジェクトに receipt フィールドを追加。 |
0.0.6 | Ethereum Transactionオブジェクトにnonce フィールドを追加Ethereum Blockオブジェクトに baseFeePerGas を追加。 |
0.0.5 | AssemblyScriptはバージョン0.19.10にアップグレードされました(このバージョンアップには変更点が含まれていますので Migration Guide ) をご覧ください)。 ethereum.transaction.gasUsed の名前がethereum.transaction.gasLimit に変更 |
0.0.4 | Ethereum SmartContractCall オブジェクトにfunctionSignatureフィールドを追加 |
0.0.3 | イーサリアムコールオブジェクトにfrom フィールドを追加etherem.call.address をethereum.call.to に変更。 |
0.0.2 | Ethereum Transaction オブジェクトに inputフィールドを追加 |
Documentation on the base types built into AssemblyScript can be found in the .
以下の追加型は@graphprotocol/graph-tsで提供されています。
'@graphprotocol/graph-ts'から{ ByteArray } をインポートします。
ByteArrayは、u8の配列を表します。
Construction
fromI32(x: i32): ByteArray
- Decomposesx
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
-this
にother
を直接続けたByteArray
を返します。concatI32(other: i32) : ByteArray
-this
にother
のバイト表現を直接続けたByteArray
を返します。
'@graphprotocol/graph-ts'から { BigDecimal } をインポートします。
BigDecimalは、任意の精度の小数を表現するために使用されます。
Note: BigDecimal
is stored in , 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 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
から uint256
と int64
から int256
型のイーサリアムの値が含まれます。uint32以下の値、例えば
int32、
uint24、
int8は全て
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
-BigInt
をi32
として返す。値が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
はキーと値のペアを格納するために使用することができます。この例](
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
は任意の長さのバイト配列を表現するために使用されます。これには bytes
、bytes32
型などのイーサリアム値が含まれます。
Bytes
クラスはAssemblyScriptのを拡張したもので、Uint8Array
のすべての機能に加え、以下の新しいメソッドをサポートしています:
Construction
fromHexString(hex: string) : Bytes
- 偶数桁の16進数からなる文字列hex
をByteArray
に変換します。文字列hex
はオプションで0x
から始めることができます。fromI32(i: i32): Bytes
-i
をバイト配列に変換します。
Type conversions
b.toHex()
- 配列のバイト数を16進数で表した文字列を返します。b.toString()
- 配列のバイト列をユニコード文字列に変換します。b.toBase58()
- イーサリアムバイトの値を base58 エンコーディングに変換します (IPFS ハッシュに使用)
Operators
b.concat(other: Bytes): Bytes
- -this
にother
を直接連結したBytes
を返します。b.concatI32(other: i32) : ByteArray
-this
にother
のバイト表現を直接続けた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 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 ABIimport { Transfer as TransferEvent } from '../generated/ERC20/ERC20'// Import the Transfer entity type generated from the GraphQL schemaimport { Transfer } from '../generated/schema'// Transfer event handlerexport function handleTransfer(event: TransferEvent): void {// Create a Transfer entity, using the transaction hash as the entity IDlet id = event.transaction.hashlet transfer = new Transfer(id)// Set properties on the entity, using the event parameterstransfer.from = event.params.fromtransfer.to = event.params.totransfer.amount = event.params.amount// Save the entity to the storetransfer.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 constructedlet 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 holderlet tokens = holder.tokens.load()
既存のエンティティを更新するには 2 つの方法があります。
- Transfer.load(id)などでエンティティをロードし、エンティティにプロパティを設定した後、.save()でストアに戻す。
- 単純に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 workentity.numbers.push(BigInt.fromI32(1))entity.save()// This will worklet numbers = entity.numbersnumbers.push(BigInt.fromI32(1))entity.numbers = numbersentity.save()
現在、生成された型を使ってエンティティを削除する方法はありません。 代わりに、エンティティを削除するには、エンティティタイプの名前とエンティティ ID をstore.removeに渡す必要があります。
mport { store } from '@graphprotocol/graph-ts'...let id = event.transaction.hashstore.remove('Transfer', id)
Ethereum API は、スマートコントラクト、パブリックステート変数、コントラクト関数、イベント、トランザクション、ブロック、および Ethereum データのエンコード/デコードへのアクセスを提供します。
エンティティと同様に、graph codegenは、サブグラフで使用されるすべてのスマートコントラクトとイベントのためのクラスを生成します。 このためには、コントラクト ABI がサブグラフマニフェストのデータソースの一部である必要があります。 通常、ABI ファイルはabis/フォルダに格納されています。
生成されたクラスでは、Ethereum Typeと間の変換が舞台裏で行われるため、サブグラフ作成者はそれらを気にする必要がありません。
以下の例で説明します。 以下のようなサブグラフのスキーマが与えられます。
type Transfer @entity {id: Bytes!from: Bytes!to: Bytes!amount: BigInt!}
イーサリアムの Transfer(address,address,uint256)
イベントシグネチャを使用すると、from
, to
, uint256
型の値は Address
と BigInt
に変換され、Transfer
エンティティの Bytes!
プロパティと BigInt!
プロパティに渡すことができます:
let id = event.transaction.hashlet transfer = new Transfer(id)transfer.from = event.params.fromtransfer.to = event.params.totransfer.amount = event.params.amounttransfer.save()
前述の例のTransferイベントのように、イベントハンドラに渡された Ethereum イベントは、イベントパラメータへのアクセスだけでなく、その親となるトランザクションや、それらが属するブロックへのアクセスも提供します。 event インスタンスからは、以下のデータを取得することができます(これらのクラスは、 graph-tsのethereumモジュールの一部です)。
class Event {address: AddresslogIndex: BigInttransactionLogIndex: BigIntlogType: string | nullblock: Blocktransaction: Transactionparameters: Array<EventParam>receipt: TransactionReceipt | null}class Block {hash: BytesparentHash: BytesunclesHash: Bytesauthor: AddressstateRoot: BytestransactionsRoot: BytesreceiptsRoot: Bytesnumber: BigIntgasUsed: BigIntgasLimit: BigInttimestamp: BigIntdifficulty: BigInttotalDifficulty: BigIntsize: BigInt | nullbaseFeePerGas: BigInt | null}class Transaction {hash: Bytesindex: BigIntfrom: Addressto: Address | nullvalue: BigIntgasLimit: BigIntgasPrice: BigIntinput: Bytesnonce: BigInt}class TransactionReceipt {transactionHash: BytestransactionIndex: BigIntblockHash: BytesblockNumber: BigIntcumulativeGasUsed: BigIntgasUsed: BigIntcontractAddress: Addresslogs: Array<Log>status: BigIntroot: ByteslogsBloom: Bytes}class Log {address: Addresstopics: Array<Bytes>data: BytesblockHash: BytesblockNumber: BytestransactionHash: BytestransactionIndex: BigIntlogIndex: BigInttransactionLogIndex: BigIntlogType: stringremoved: bool | null}
graph codegenが生成するコードには、サブグラフで使用されるスマートコントラクトのクラスも含まれています。 これらを使って、パブリックな状態変数にアクセスしたり、現在のブロックにあるコントラクトの関数を呼び出したりすることができます。
よくあるパターンは、イベントが発生したコントラクトにアクセスすることです。 これは以下のコードで実現できます。
// Import the generated contract class and generated Transfer event classimport { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract'// Import the generated entity classimport { Transfer } from '../generated/schema'export function handleTransfer(event: TransferEvent) {// Bind the contract to the address that emitted the eventlet contract = ERC20Contract.bind(event.address)// Access state variables and functions by calling themlet 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.
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.Tuplelet 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
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 truelet 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(), 'すでに文字列'])
以下の例では、文字列値 "A" を配列に渡して['A'] にしてからログに記録しています。
let myValue = 'A'export function handleSomeEvent(event: SomeEvent): void {// Displays : "My value is: A"log.info('My value is: {}', [myValue])}
以下の例では、配列に 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 mappinglet hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D'let data = ipfs.cat(hash)// Paths like `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile`// that include files in directories are also supportedlet 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 valueslet obj = value.toObject()let id = obj.get('id')let title = obj.get('title')if (!id || !title) {return}// Callbacks can also created entitieslet 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 mappingipfs.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-8String
から 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) | Destination | Conversion function |
---|---|---|
Address | Bytes | none |
Address | String | s.toHexString() |
BigDecimal | String | s.toString() |
BigInt | BigDecimal | s.toBigDecimal() |
BigInt | String (hexadecimal) | s.toHexString() or s.toHex() |
BigInt | String (unicode) | s.toString() |
BigInt | i32 | s.toI32() |
Boolean | Boolean | none |
Bytes (signed) | BigInt | BigInt.fromSignedBytes(s) |
Bytes (unsigned) | BigInt | BigInt.fromUnsignedBytes(s) |
Bytes | String (hexadecimal) | s.toHexString() or s.toHex() |
Bytes | String (unicode) | s.toString() |
Bytes | String (base58) | s.toBase58() |
Bytes | i32 | s.toI32() |
Bytes | u32 | s.toU32() |
Bytes | JSON | json.fromBytes(s) |
int8 | i32 | none |
int32 | i32 | none |
int32 | BigInt | Bigint.fromI32(s) |
uint24 | i32 | none |
int64 - int256 | BigInt | none |
uint32 - uint256 | BigInt | none |
JSON | boolean | s.toBool() |
JSON | i64 | s.toI64() |
JSON | u64 | s.toU64() |
JSON | f64 | s.toF64() |
JSON | BigInt | s.toBigInt() |
JSON | string | s.toString() |
JSON | Array | s.toArray() |
JSON | Object | s.toObject() |
String | Address | Address.fromString(s) |
Bytes | Address | Address.fromString(s) |
String | BigInt | BigDecimal.fromString(s) |
String | BigDecimal | BigDecimal.fromString(s) |
String (hexadecimal) | Bytes | ByteArray.fromHexString(s) |
String (UTF-8) | Bytes | ByteArray.fromUTF8(s) |
ハンドラを起動したデータソースのコントラクトアドレス、ネットワーク、コンテキストは、以下のようにして調べることができます。
dataSource.address(): Address
dataSource.network(): string
dataSource.context(): 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
DataSourcesの
contextセクションでは、サブグラフマッピング内でアクセス可能なキーと値のペアを定義することができます。使用可能な型は
Bool、
String、
Int、
Int8、
BigDecimal、
Bytes、
List、
BigInt` です。
以下は context
セクションのさまざまな型の使い方を示す YAML の例です:
dataSources:- kind: ethereum/contractname: ContractNamenetwork: mainnetcontext:bool_example:type: Booldata: truestring_example:type: Stringdata: 'hello'int_example:type: Intdata: 42int8_example:type: Int8data: 127big_decimal_example:type: BigDecimaldata: '10.99'bytes_example:type: Bytesdata: '0x68656c6c6f'list_example:type: Listdata:- type: Intdata: 1- type: Intdata: 2- type: Intdata: 3big_int_example:type: BigIntdata: '1000000000000000000000000'
Bool
: Specifies a Boolean value (true
orfalse
).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.
このコンテキストは、サブグラフのマッピング・ファイルからアクセスでき、よりダイナミックで設定可能なサブグラフを実現します。