Docs
搜索⌘ K
  • 主页
  • 关于 The Graph
  • 支持的网络
  • 协议合约
  • 子图
    • 子流
      • 代币 API
        • Hypergraph
          • AI Suite
            • 索引
              • 资源
                子图 > 开发 > 创建 > 汇编脚本API

                28 分钟

                汇编脚本API

                注意:如果您在 graph-cli/graph-ts 版本 0.22.0 之前创建了子图,那么您正在使用较旧版本的 AssemblyScript,我们建议查看迁移指南。

                此页面记录了编写子图映射时可以使用的内置 API。有两种开箱即用的 API:

                • Graph TypeScript库⁠ (graph-ts)
                • 通过 graph codegen 生成的子图文件中的代码

                您还可以添加其他库作为依赖项,只要它们与AssemblyScript⁠兼容。

                由于语言映射是用AssemblyScript编写的,因此从AssemblyScript wiki⁠查看语言和标准库功能非常有用。

                API 参考

                @graphprotocol/graph-ts 库提供以下 API:

                • 用于处理以太坊智能合约、事件、区块、交易和以太坊价值的以太坊 API。
                • 用于与图形节点交互,存储和加载实体的 存储 API。
                • 用于将消息记录Graph Node输出和Graph Explorer的log API。
                • 用于从 IPFS 加载文件的ipfs API。
                • 用于解析 JSON 数据的json API。
                • 使用加密功能的crypto API。
                • 用于在不同类型系统(例如 Ethereum、JSON、GraphQL 和 AssemblyScript)之间进行转换的低级原语。

                版本

                子图清单中的 apiVersion 指定了由 Graph Node 运行的特定子图的映射 API 版本。

                版本Release 说明
                0.0.9添加新的主机函数eth_get_balance 和 hasCode
                0.0.8在保存实体时添加对模式中是否存在字段的验证。
                0.0.7添加了 TransactionReceipt 和 Log 类到以太坊类型。
                已将 receipt 字段添加到Ethereum Event对象。
                0.0.6向Ethereum Transaction对象添加了 nonce 字段 向 Etherum Block对象添加
                baseFeePerGas字段
                0.0.5AssemblyScript 升级到版本 0.19.10(这包括重大更改,参阅迁移指南)
                ethereum.transaction.gasUsed 重命名为 ethereum.transaction.gasLimit`
                0.0.4已向 Ethereum SmartContractCall对象添加了 functionSignature 字段。
                0.0.3已向Ethereum Call 对象添加了 from 字段。
                ethereum.call.address 被重命名为 ethereum.call.to。
                0.0.2已向Ethereum Transaction对象添加了 input 字段。

                内置类型

                关于内置于 AssemblyScript 中的基本类型的文档可以在AssemblyScript wiki⁠中找到。

                以下额外的类型由 @graphprotocol/graph-ts 提供。

                字节数组

                1从'@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 的字节表示构成。

                BigDecimal

                1从“@Graphprotocol/graph-ts”导入{ BigDecimal }

                BigDecimal 用于表示任意精度的小数。

                注意:内部⁠BigDecimal以IEEE-754 decimal128浮点格式⁠存储,支持34位十进制有效位。这使得BigDecimal不适合表示跨度超过34位的定点类型,例如Solidity ufixed256x18⁠或等效类型。

                结构

                • 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。

                BigInt

                1从'@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.

                类型化映射

                1从'@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 的键值对,如果映射中不存在该键,则返回 null。
                • map.get(key: K): V | null – 返回键为 key 的值,如果映射中不存在该键,则返回 null。
                • map.isSet(key: K): bool – 如果映射中存在 key 则返回 true,否则返回 false。

                字节

                1从 '@graphprotocol/graph-ts'导入{ Bytes }

                字节用于表示任意长度的字节数组,包括字节类型的以太坊值、 bytes32等。

                Bytes 类扩展了 AssemblyScript 的 Uint8Array⁠,支持所有 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 的字节表示组成。

                地址

                1从 '@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 字节的值将导致错误。

                商店API

                1从 '@graphprotocol/graph-ts'导入 { store }

                store API 允许从和到 Graph Node 存储加载、保存和删除实体。

                写入存储的实体与子图的 GraphQL 模式中定义的 @entity 类型一一对应。为了方便处理这些实体,由 Graph CLI⁠ 提供的 graph codegen 命令会生成实体类,这些类是内置 Entity 类的子类,具有模式中字段的属性 getter 和 setter,以及加载和保存这些实体的方法。

                创建实体

                以下是从以太坊事件创建实体的常见模式。

                1/ Import the Transfer event class generated from the ERC20 ABI2import { Transfer as TransferEvent } from '../generated/ERC20/ERC20'34// Import the Transfer entity type generated from the GraphQL schema5import { Transfer } from '../generated/schema'67// Transfer event handler8export function handleTransfer(event: TransferEvent): void {9  // Create a Transfer entity, using the transaction hash as the entity ID10  let id = event.transaction.hash11  let transfer = new Transfer(id)1213  // Set properties on the entity, using the event parameters14  transfer.from = event.params.from15  transfer.to = event.params.to16  transfer.amount = event.params.amount1718  // Save the entity to the store19  transfer.save()20}

                如果在处理链时遇到 Transfer 事件,它会使用生成的 Transfer 类型(别名为 TransferEvent 以避免与实体类型的命名冲突) 传递给 handleTransfer 事件处理器。 此类型允许访问事件的母交易及其参数等数据。

                每个实体都必须有一个唯一的ID,以避免与其他实体发生冲突。事件参数中包含可使用的唯一标识符是相当常见的。

                注意:使用交易hash作为ID假设同一交易中没有其他事件创建具有此hash作为ID的实体。

                从存储中加载实体

                如果实体已经存在,则可以使用以下内容从存储中加载它:

                1let id = event.transaction.hash // or however the ID is constructed2let transfer = Transfer.load(id)3if (transfer == null) {4  transfer = new Transfer(id)5}67// Use the Transfer entity as before

                由于实体可能尚未存在于存储中,因此 load 方法返回一个类型为 Transfer | null 的值。因此,在使用该值之前可能需要检查 null 情况。

                注意: 仅当映射中所做的更改依赖于实体的先前数据时,才需要加载实体。 有关更新现有实体的两种方法,请参阅下一节。

                查找在区块中创建的实体

                截至 graph-node v0.31.0、@graphprotocol/graph-ts v0.30.0 和 @graphprotocol/graph-cli v0.49.0,所有实体类型上都提供了 loadInBlock 方法。

                存储API便于检索在当前块中创建或更新的实体。一个典型的情况是,一个处理程序从某个链上事件创建一个交易,如果该交易存在,则稍后的处理程序希望访问该交易。

                • 在交易不存在的情况下,子图将不得不访问数据库,以发现实体不存在。如果子图作者已经知道实体必须是在同一块中创建的,那么使用loadInBlock可以避免这种数据库往返。
                • 对于某些子图,这些遗漏的查找可能会大大增加索引时间。
                1let id = event.transaction.hash // or however the ID is constructed2let transfer = Transfer.loadInBlock(id)3if (transfer == null) {4  transfer = new Transfer(id)5}67// 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 方法。

                这允许从事件处理程序中加载派生实体字段。例如,给定以下模式:

                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}

                以下代码将加载Holder实体来源的Token实体:

                1let holder = Holder.load('test-id')2// 加载与给定持有人相关联的 Token 实体。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// This won't work2entity.numbers.push(BigInt.fromI32(1))3entity.save()45// This will work6let numbers = entity.numbers7numbers.push(BigInt.fromI32(1))8entity.numbers = numbers9entity.save()

                从存储中删除实体

                目前无法通过生成的类型来删除实体。相反,要删除实体,需要将实体类型的名称和实体ID传递给 store.remove 方法:

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

                以太坊 API

                以太坊 API 提供对智能合约、公共状态变量、合约函数、事件、交易、区块和编码/解码以太坊数据的访问。

                对以太坊类型的支持

                与实体一样,graph codegen 为子图中使用的所有智能合约和事件生成类。为此,合约 ABI 需要作为子图清单中数据源的一部分。通常,ABI 文件存储在一个名为 abis/ 的文件夹中。

                通过生成的类,以太坊类型和内置类型 之间的转换在幕后进行,这样子图作者就不必担心它们。

                以下示例说明了这一点。 给定一个子图模式,如

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

                对于以太坊上的 Transfer(address,address,uint256) 事件签名,类型为 address、address 和 uint256 的 from、to 和 amount 值被转换为 Address 和 BigInt,从而允许它们传递给 Transfer 实体的 Bytes! 和 BigInt! 属性:

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

                事件和区块/交易数据

                传递给事件处理程序的以太坊事件(例如前面示例中的 Transfer 事件)不仅提供对事件参数的访问,还提供对其父事务和它们所在的区块的访问。以下数据可以从 event 实例中获取(这些类是 graph-ts 中的 ethereum 模块的一部分):

                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}

                访问智能合约状态

                由 graph codegen 生成的代码还包括用于子图中使用的智能合约的类。这些类可以用于访问智能合约在当前区块上的公共状态变量和调用函数。

                一种常见的模式是访问事件起源的合约。 这是通过以下代码实现的:

                1// Import the generated contract class and generated Transfer event class2import { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract'3// Import the generated entity class4import { Transfer } from '../generated/schema'56export function handleTransfer(event: TransferEvent) {7  // Bind the contract to the address that emitted the event8  let contract = ERC20Contract.bind(event.address)910  // Access state variables and functions by calling them11  let erc20Symbol = contract.symbol()12}

                这里将 Transfer 别名为 TransferEvent,以避免与实体类型产生命名冲突。

                只要以太坊上的 ERC20Contract 有一个名为 symbol 的公共只读函数,就可以使用 .symbol() 来调用它。对于公共状态变量,将自动生成一个同名的方法。

                作为子图一部分的任何其他合约都可以从生成的代码中导入,并且可以绑定到一个有效地址。

                处理重复调用

                如果你的合约的只读方法可能会恢复,那么你应该通过调用以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}

                请注意,连接到 Geth 或 Infura 客户端的 Graph 节点可能无法检测到所有重复使用,如果您依赖于此,我们建议使用连接到 Parity 客户端的 Graph 节点。

                编码/解码 ABI

                数据可以按照以太坊的 ABI 编码格式使用 ethereum 模块中的 encode 和 decode 函数进行编码和解码。

                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 Ethereum ABI 库/CLI⁠来进行编码和解码。
                • 更复杂的示例可以在这里⁠找到。

                地址余额

                可以使用以太坊模块检索地址的本地代币余额。此功能可从apiVersion:0.0.9中获得,其定义为subgraph.yaml。getBalance()检索指定地址在触发事件的块结束时的余额。

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

                检查地址是合约还是EOA

                要检查地址是智能合约地址还是外部所有地址(EOA),请使用以太坊模块中的hasCode()函数,该函数将返回boolean。此功能可从apiVersion:0.0.9中获得,该版本定义为subgraph.yaml。

                1import { ethereum } from '@graphprotocol/graph-ts'23let contractAddr = Address.fromString('0x2E645469f354BB4F5c8a05B3b30A929361cf77eC')4let isContract = ethereum.hasCode(contractAddr).inner // returns true56let eoa = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')7let isContract = ethereum.hasCode(eoa).inner // returns false

                日志记录 API

                1从 '@graphprotocol/graph-ts'导入 { log }

                log API 允许子图将信息记录到 Graph Node 的标准输出以及 Graph Explorer。可以使用不同的日志级别记录消息。提供了一种基本的格式字符串语法来从参数组成日志消息。

                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 接受一个格式字符串和一个字符串值数组。然后,它用数组中的字符串值替换占位符。第一个 {} 占位符会被数组中的第一个值替换,第二个 {} 占位符会被第二个值替换,依此类推。

                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  // Displays : "My value is: A"5  log.info('My value is: {}', [myValue])6}
                从现有数组记录单个条目

                在下面的示例中,尽管参数数组包含三个值,只有该数组的第一个值被记录了。

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

                从现有数组记录多个条目

                在日志消息字符串中,参数数组中的每个条目都需要自己的占位符 。下面的示例包含了日志消息中的三个占位符 。因此,myArray 中的所有三个值都被记录。

                1let myArray = ['A', 'B', 'C']23export function handleSomeEvent(event: SomeEvent): void {4  // Displays : "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  // Displays : "My third value is C"3  log.info('My third value is: {}', [myArray[2]])4}
                记录事件信息

                下面的例子记录了一个事件的区块号、区块hash和交易hash:

                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

                1从 '@graphprotocol/graph-ts'导入{ ipfs }

                智能合约偶尔会在链上固定 IPFS 文件。这允许映射从合约获取 IPFS 哈希并从 IPFS 读取相应的文件。文件数据将作为 Bytes 返回,通常需要进一步处理,例如使用稍后在本页面中记录的 json API。

                给定一个 IPFS hash或路径,从 IPFS 读取文件的过程如下:

                1// Put this inside an event handler in the mapping2let hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D'3let data = ipfs.cat(hash)45// Paths like `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile`6// that include files in directories are also supported7let path = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile'8let data = ipfs.cat(path)

                注意: 目前 ipfs.cat 不是确定性的。如果在请求超时之前无法从 IPFS 网络检索到文件,则会返回 null。因此,始终值得检查结果是否为 null。

                还可以使用 ipfs.map 以流式处理的方式处理较大的文件。该函数需要 IPFS 文件的哈希或路径、回调函数的名称以及修改其行为的标志:

                1import { JSONValue, Value } from '@graphprotocol/graph-ts'23export function processItem(value: JSONValue, userData: Value): void {4  // See the JSONValue documentation for details on dealing5  // with JSON values6  let obj = value.toObject()7  let id = obj.get('id')8  let title = obj.get('title')910  if (!id || !title) {11    return12  }1314  // Callbacks can also created entities15  let newItem = new Item(id)16  newItem.title = title.toString()17  newitem.parent = userData.toString() // Set parent to "parentId"18  newitem.save()19}2021// Put this inside an event handler in the mapping22ipfs.map('Qm...', 'processItem', Value.fromString('parentId'), ['json'])2324// Alternatively, use `ipfs.mapJSON`25ipfs.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 的处理程序将被中止,并且子图被标记为失败。

                加密API

                1从'@graphprotocol/graph-ts'导入{ crypto }

                crypto API 为映射中的使用提供了加密函数。目前,只有一个函数可用:

                • crypto.keccak256(input: ByteArray): ByteArray

                JSON API

                1从'@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 属性用于检查值的类型:

                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> - (然后使用上述 5 种方法之一将 JSONValue 转换)

                类型转换参考

                源类型目标类型转换函数
                AddressBytesnone
                AddressStrings.toHexString()
                BigDecimalStrings.toString()
                BigIntBigDecimals.toBigDecimal()
                BigIntString (hexadecimal)s.toHexString() 或 s.toHex()
                BigIntString (unicode)s.toString()
                BigInti32s.toI32()
                BooleanBooleannone
                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)
                int8i32none
                int32i32none
                int32BigIntBigInt.fromI32(s)
                uint24i32none
                int64 - int256BigIntnone
                uint32 - uint256BigIntnone
                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

                Entity 和 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

                清单文件中的 DataSourceContext

                dataSources 内的 context 部分允许您定义在子图映射中可访问的键值对。可用的类型包括 Bool、String、Int、Int8、BigDecimal、Bytes、List 和 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:指定一个大整数值。由于其较大,必须用引号括起来。

                该上下文可以在您的子图映射文件中访问,从而实现更加动态和可配置的子图。

                ⁠在GitHub上编辑⁠

                介绍常见问题
                在此页面上
                • API 参考
                • 版本
                • 内置类型
                • 商店API
                • 以太坊 API
                • 日志记录 API
                • IPFS API
                • 加密API
                • JSON API
                • 类型转换参考
                • 数据源元数据
                • Entity 和 DataSourceContext
                • 清单文件中的 DataSourceContext
                The GraphStatusTestnetBrand AssetsForum安全Privacy PolicyTerms of Service