AssemblyScript API
Reading time: 27 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:
- 用于处理以太坊智能合约、事件、区块、交易和以太坊价值的以太坊 API。
- 用于与图形节点交互,存储和加载实体的 存储 API。
- A
log
API to log messages to the Graph Node output and Graph Explorer. - 用于从 IPFS 加载文件的ipfs API。
- 用于解析 JSON 数据的json API。
- 使用加密功能的crypto API。
- 用于在不同类型系统(例如 Ethereum、JSON、GraphQL 和 AssemblyScript)之间进行转换的低级原语。
子图清单中的 apiVersion
指定了由 Graph Node 运行的特定子图的映射 API 版本。
Documentation on the base types built into AssemblyScript can be found in the .
以下额外的类型由 @graphprotocol/graph-ts
提供。
从'@graphprotocol/graph-ts'导入{ ByteArray }
ByteArray
表示一个 u8
类型的数组。
结构
fromI32(x: i32): ByteArray
- 将x
分解为字节。fromHexString(hex: string): ByteArray
- 输入长度必须是偶数。在十六进制字符串中添加0x
前缀是可选的。
类型转换
toHexString(): string
- 转换为以0x
前缀的十六进制字符串。toString(): string
- 将字节解释为 UTF-8 字符串。toBase58(): string
- 将字节编码为 base58 字符串。toU32(): u32
- 将字节解释为小端u32
。在溢出的情况下会抛出异常。toI32(): i32
- 将字节数组解释为小端i32
。在溢出的情况下会抛出异常。
操作符
equals(y: ByteArray): bool
– 可以写成x == y
。concat(other: ByteArray) : ByteArray
- 返回一个新的ByteArray
,由this
直接跟随other
构成。concatI32(other: i32) : ByteArray
- 返回一个新的ByteArray
,由this
直接跟随other
的字节表示构成。
从“@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.
结构
constructor(bigInt: BigInt)
– 从一个BigInt
创建一个BigDecimal
。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
。
从'@graphprotocol/graph-ts'导入{ BigInt }
BigInt
用于表示大整数。这包括以太坊中的类型 uint32
到 uint256
和 int64
到 int256
的数值。所有小于 uint32
的数值,比如 int32
、uint24
或 int8
都被表示为 i32
。
BigInt 类具有以下 API:
结构
-
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()。类型转换
-
x.toHex(): string
– 将 BigInt 转换为十六进制字符的字符串。 -
x.toString(): string
– 将 BigInt 转换为十进制数字字符串。 -
x.toI32(): i32
– 将 BigInt 作为 i32 返回;如果值不适合 i32,则失败。最好先检查 x.isI32()。 -
x.toBigDecimal(): 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
.
从'@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
。map.get(key: K): V | null
– 返回键为key
的值,如果映射中不存在该键,则返回null
。map.isSet(key: K): bool
– 如果映射中存在key
则返回true
,否则返回false
。
从 '@graphprotocol/graph-ts'导入{ Bytes }
字节用于表示任意长度的字节数组,包括字节类型的以太坊值、 bytes32等。
Bytes
类扩展了 AssemblyScript 的 ,支持所有 Uint8Array
的功能,以及以下新方法:
结构
fromHexString(hex: string): Bytes
- 将字符串hex
转换为一个ByteArray
。字符串hex
必须由偶数个十六进制数字组成,并且可选地以0x
开头。fromI32(i: i32): Bytes
- 将i
转换为一个字节数组。
类型转换
b.toHex()
– 返回表示数组中字节的十六进制字符串。b.toString()
– 将数组中的字节转换为 Unicode 字符串。b.toBase58()
– 将以太坊的字节数值转换为 base58 编码(用于 IPFS 哈希)。
操作符
b.concat(other: Bytes): Bytes
- 返回一个新的Bytes
,由this
直接跟随other
组成。b.concatI32(other: i32): ByteArray
- 返回一个新的Bytes
,由this
直接跟随other
的字节表示组成。
从 '@graphprotocol/graph-ts'导入{ Address }
Address
扩展了 Bytes
,用于表示以太坊的 address
值。
除了 Bytes
API 之外,它还添加了以下方法:
Address.fromString(s: string): Address
– 从十六进制字符串创建一个Address
。Address.fromBytes(b: Bytes): Address
– 从b
创建一个Address
,b
必须恰好为 20 个字节长。传入长度不足或超过 20 字节的值将导致错误。
从 '@graphprotocol/graph-ts'导入 { store }
store
API 允许从和到 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 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.
以下是从以太坊事件创建实体的常见模式。
/ 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 // or however the ID is constructedlet transfer = Transfer.loadInBlock(id)if (transfer == null) {transfer = new Transfer(id)}// Use the Transfer entity as before
注意: 如果在给定的区块中没有创建实体,则 loadInBlock
将返回 null
,即使存储中存在具有给定 ID 的实体也是如此。
在 graph-node
v0.31.0、@graphprotocol/graph-ts
v0.31.0 和 @graphprotocol/graph-cli
v0.51.0 中引入了 loadRelated
方法。
这允许从事件处理程序中加载派生实体字段。例如,给定以下模式:
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')// 加载与给定持有人相关联的 Token 实体。let tokens = holder.tokens.load()
有两种方法可以更新现有实体:
- 利用 Transfer.load(id)加载实体,在实体上设置属性,然后调用.save() 将其返回到存储。
- 使用 new Transfer(id)创建实体,在实体上设置属性,然后调用.save()将其保存到存储。 如果实体已经存在,则将更改合并到其中。
由于生成的属性设置器,在大多数情况下更改属性是直截了当的:
let transfer = new Transfer(id)transfer.from = ...transfer.to = ...transfer.amount = ...
也可以使用以下两条指令之一取消设置属性:
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
方法:
import { store } from '@graphprotocol/graph-ts'...let id = event.transaction.hashstore.remove('Transfer', id)
以太坊 API 提供对智能合约、公共状态变量、合约函数、事件、交易、区块和编码/解码以太坊数据的访问。
与实体一样,graph codegen
为子图中使用的所有智能合约和事件生成类。为此,合约 ABI 需要作为子图清单中数据源的一部分。通常,ABI 文件存储在一个名为 abis/
的文件夹中。
通过生成的类,以太坊类型和内置类型之间的转换在幕后进行,这样子图作者就不必担心它们。
以下示例说明了这一点。 给定一个子图模式,如
type Transfer @entity {from: Bytes!to: Bytes!amount: BigInt!}
对于以太坊上的 Transfer(address,address,uint256)
事件签名,类型为 address
、address
和 uint256
的 from
、to
和 amount
值被转换为 Address
和 BigInt
,从而允许它们传递给 Transfer
实体的 Bytes!
和 BigInt!
属性:
let id = event.transaction.hash.toHex()let transfer = new Transfer(id)transfer.from = event.params.fromtransfer.to = event.params.totransfer.amount = event.params.amounttransfer.save()
传递给事件处理程序的以太坊事件(例如前面示例中的 Transfer
事件)不仅提供对事件参数的访问,还提供对其父事务和它们所在的区块的访问。以下数据可以从 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
,以避免与实体类型产生命名冲突。
只要以太坊上的 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
函数进行编码和解码。
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 接受一个格式字符串和一个字符串值数组。然后,它用数组中的字符串值替换占位符。第一个 {}
占位符会被数组中的第一个值替换,第二个 {}
占位符会被第二个值替换,依此类推。
log.info('Message to be displayed: {}, {}, {}', [value.toString(), anotherValue.toString(), 'already a string'])
在下面的示例中,字符串值 "A" 被传入一个数组中成为 ['A']
,然后被记录:
let myValue = 'A'export function handleSomeEvent(event: SomeEvent): void {// Displays : "My value is: A"log.info('My value is: {}', [myValue])}
在下面的示例中,尽管参数数组包含三个值,只有该数组的第一个值被记录了。
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)}
在日志消息字符串中,参数数组中的每个条目都需要自己的占位符 。下面的示例包含了日志消息中的三个占位符 。因此,myArray 中的所有三个值都被记录。
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]])}
下面的例子记录了一个事件的区块号、区块hash和交易hash:
import { log } from '@graphprotocol/graph-ts'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 hash或路径,从 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 为映射中的使用提供了加密函数。目前,只有一个函数可用:
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
转换)
源类型 | 目标类型 | 转换函数 |
---|---|---|
Address | Bytes | none |
Address | String | s.toHexString() |
BigDecimal | String | s.toString() |
BigInt | BigDecimal | s.toBigDecimal() |
BigInt | String (hexadecimal) | s.toHexString() 或 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() 或 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.toU64() |
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.fromBytes(s) |
String | BigInt | BigInt.fromString(s) |
String | BigDecimal | BigDecimal.fromString(s) |
String (hexadecimal) | Bytes | ByteArray.fromHexString(s) |
String (UTF-8) | Bytes | ByteArray.fromUTF8(s) |
您可以通过 dataSource
命名空间检查调用处理程序的数据源的合约地址、网络和上下文:
dataSource.address(): Address
dataSource.network(): string
dataSource.context(): DataSourceContext
基础的 Entity
类和子类 DataSourceContext
类都有助于动态设置和获取字段的帮助函数:
setString(key: string, value: string): void
setI32(key: string, value: i32): void
setI32(key: string, value: i32): 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
。
以下是一个 YAML 示例,说明了在 context 部分使用各种类型的情况:
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
:指定一个布尔值(true
或false
)。String
:指定一个字符串值。Int
:指定一个32位整数。Int8
:指定一个8位整数。BigDecimal
:指定一个十进制数。必须用引号括起来。Bytes
:指定一个十六进制字符串。List
:指定一个项目列表。每个项目都需要指定其类型和数据。BigInt
:指定一个大整数值。由于其较大,必须用引号括起来。
该上下文可以在您的子图映射文件中访问,从而实现更加动态和可配置的子图。