subgraphs > Developing > Creating > AssemblyScript API > API för AssemblyScript

API för AssemblyScript

Reading time: 20 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-referens

Länk till detta avsnitt

The @graphprotocol/graph-ts library provides the following APIs:

  • An ethereum API for working with Ethereum smart contracts, events, blocks, transactions, and Ethereum values.
  • A store API to load and save entities from and to the Graph Node store.
  • A log API to log messages to the Graph Node output and Graph Explorer.
  • An ipfs API to load files from IPFS.
  • A json API to parse JSON data.
  • A crypto API to use cryptographic functions.
  • Primitiver på låg nivå för att översätta mellan olika typsystem som Ethereum, JSON, GraphQL och AssemblyScript.

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

VersionVersionsanteckningar
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.7Added TransactionReceipt and Log classes to the Ethereum types
Added receipt field to the Ethereum Event object
0.0.6Added nonce field to the Ethereum Transaction object
Added baseFeePerGas to the Ethereum Block object
0.0.5AssemblyScript upgraded to version 0.19.10 (this includes breaking changes, please see the Migration Guide)
ethereum.transaction.gasUsed renamed to ethereum.transaction.gasLimit
0.0.4Added functionSignature field to the Ethereum SmartContractCall object
0.0.3Added from field to the Ethereum Call object
etherem.call.address renamed to ethereum.call.to
0.0.2Added input field to the Ethereum Transaction object

Inbyggda typer

Länk till detta avsnitt

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

The following additional types are provided by @graphprotocol/graph-ts.

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

ByteArray represents an array of u8.

Construction

  • fromI32(x: i32): ByteArray - Decomposes x into bytes.
  • fromHexString(hex: string): ByteArray - Input length must be even. Prefixing with 0x is optional.

Type conversions

  • toHexString(): string - Converts to a hex string prefixed with 0x.
  • toString(): string - Interprets the bytes as a UTF-8 string.
  • toBase58(): string - Encodes the bytes into a base58 string.
  • toU32(): u32 - Interprets the bytes as a little-endian u32. Throws in case of overflow.
  • toI32(): i32 - Interprets the byte array as a little-endian i32. Throws in case of overflow.

Operators

  • equals(y: ByteArray): bool – can be written as x == y.
  • concat(other: ByteArray) : ByteArray - return a new ByteArray consisting of this directly followed by other
  • concatI32(other: i32) : ByteArray - return a new ByteArray consisting of this directly followed by the byte representation of other
import { BigDecimal } from '@graphprotocol/graph-ts'

BigDecimal is used to represent arbitrary precision decimals.

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) – creates a BigDecimal from an BigInt.
  • static fromString(s: string): BigDecimal – parses from a decimal string.

Type conversions

  • toString(): string – prints to a decimal string.

Math

  • plus(y: BigDecimal): BigDecimal – can be written as x + y.
  • minus(y: BigDecimal): BigDecimal – can be written as x - y.
  • times(y: BigDecimal): BigDecimal – can be written as x * y.
  • div(y: BigDecimal): BigDecimal – can be written as x / y.
  • equals(y: BigDecimal): bool – can be written as x == y.
  • notEqual(y: BigDecimal): bool – can be written as x != y.
  • lt(y: BigDecimal): bool – can be written as x < y.
  • le(y: BigDecimal): bool – can be written as x <= y.
  • gt(y: BigDecimal): bool – can be written as x > y.
  • ge(y: BigDecimal): bool – can be written as x >= y.
  • neg(): BigDecimal - can be written as -x.
import { BigInt } from '@graphprotocol/graph-ts'

BigInt is used to represent big integers. This includes Ethereum values of type uint32 to uint256 and int64 to int256. Everything below uint32, such as int32, uint24 or int8 is represented as i32.

The BigInt class has the following API:

Construction

  • BigInt.fromI32(x: i32): BigInt – creates a BigInt from an i32.

  • BigInt.fromString(s: string): BigInt– Parses a BigInt from a string.

  • BigInt.fromUnsignedBytes(x: Bytes): BigInt – Interprets bytes as an unsigned, little-endian integer. If your input is big-endian, call .reverse() first.

  • BigInt.fromSignedBytes(x: Bytes): BigInt – Interprets bytes as a signed, little-endian integer. If your input is big-endian, call .reverse() first.

    Type conversions

  • x.toHex(): string – turns BigInt into a string of hexadecimal characters.

  • x.toString(): string – turns BigInt into a decimal number string.

  • x.toI32(): i32 – returns the BigInt as an i32; fails if the value does not fit into i32. It's a good idea to first check x.isI32().

  • x.toBigDecimal(): BigDecimal - converts into a decimal with no fractional part.

Math

  • x.plus(y: BigInt): BigInt – can be written as x + y.
  • x.minus(y: BigInt): BigInt – can be written as x - y.
  • x.times(y: BigInt): BigInt – can be written as x * y.
  • x.div(y: BigInt): BigInt – can be written as x / y.
  • x.mod(y: BigInt): BigInt – can be written as x % y.
  • x.equals(y: BigInt): bool – can be written as x == y.
  • x.notEqual(y: BigInt): bool – can be written as x != y.
  • x.lt(y: BigInt): bool – can be written as x < y.
  • x.le(y: BigInt): bool – can be written as x <= y.
  • x.gt(y: BigInt): bool – can be written as x > y.
  • x.ge(y: BigInt): bool – can be written as x >= y.
  • x.neg(): BigInt – can be written as -x.
  • x.divDecimal(y: BigDecimal): BigDecimal – divides by a decimal, giving a decimal result.
  • x.isZero(): bool – Convenience for checking if the number is zero.
  • x.isI32(): bool – Check if the number fits in an i32.
  • x.abs(): BigInt – Absolute value.
  • x.pow(exp: u8): BigInt – Exponentiation.
  • bitOr(x: BigInt, y: BigInt): BigInt – can be written as x | y.
  • bitAnd(x: BigInt, y: BigInt): BigInt – can be written as x & y.
  • leftShift(x: BigInt, bits: u8): BigInt – can be written as x << y.
  • rightShift(x: BigInt, bits: u8): BigInt – can be written as x >> y.
import { TypedMap } from '@graphprotocol/graph-ts'

TypedMap can be used to store key-value pairs. See this example.

The TypedMap class has the following API:

  • new TypedMap<K, V>() – creates an empty map with keys of type K and values of type V
  • map.set(key: K, value: V): void – sets the value of key to value
  • map.getEntry(key: K): TypedMapEntry<K, V> | null – returns the key-value pair for a key or null if the key does not exist in the map
  • map.get(key: K): V | null – returns the value for a key or null if the key does not exist in the map
  • map.isSet(key: K): bool – returns true if the key exists in the map and false if it does not
import { Bytes } from '@graphprotocol/graph-ts'

Bytes is used to represent arbitrary-length arrays of bytes. This includes Ethereum values of type bytes, bytes32, etc.

The Bytes class extends AssemblyScript's Uint8Array and this supports all the Uint8Array functionality, plus the following new methods:

Construction

  • fromHexString(hex: string) : Bytes - Convert the string hex which must consist of an even number of hexadecimal digits to a ByteArray. The string hex can optionally start with 0x
  • fromI32(i: i32) : Bytes - Convert i to an array of bytes

Type conversions

  • b.toHex() – returns a hexadecimal string representing the bytes in the array
  • b.toString() – converts the bytes in the array to a string of unicode characters
  • b.toBase58() – turns an Ethereum Bytes value to base58 encoding (used for IPFS hashes)

Operators

  • b.concat(other: Bytes) : Bytes - - return new Bytes consisting of this directly followed by other
  • b.concatI32(other: i32) : ByteArray - return new Bytes consisting of this directly follow by the byte representation of other
import { Address } from '@graphprotocol/graph-ts'

Address extends Bytes to represent Ethereum address values.

It adds the following method on top of the Bytes API:

  • Address.fromString(s: string): Address – creates an Address from a hexadecimal string
  • Address.fromBytes(b: Bytes): Address – create an Address from b which must be exactly 20 bytes long. Passing in a value with fewer or more bytes will result in an error
import { store } from '@graphprotocol/graph-ts'

The store API allows to load, save and remove entities from and to the Graph Node store.

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.

Skapa entiteter

Länk till detta avsnitt

Följande är ett vanligt mönster för att skapa entiteter från Ethereum-händelser.

// Importera händelseklassen Transfer som genererats från ERC20 ABI
import { Transfer as TransferEvent } from '../generated/ERC20/ERC20'
// Importera entitetstypen Transfer som genererats från GraphQL-schemat
import { Transfer } from '../generated/schema'
// Händelsehanterare för överföring
export function handleTransfer(event: TransferEvent): void {
// Skapa en Transfer-entitet, med transaktionshash som enhets-ID
let id = event.transaction.hash
let transfer = new Transfer(id)
// Ange egenskaper för entiteten med hjälp av händelseparametrarna
transfer.from = event.params.from
transfer.to = event.params.to
transfer.amount = event.params.amount
// Spara entiteten till lagret
transfer.save()
}

When a Transfer event is encountered while processing the chain, it is passed to the handleTransfer event handler using the generated Transfer type (aliased to TransferEvent here to avoid a naming conflict with the entity type). This type allows accessing data such as the event's parent transaction and its parameters.

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.

Ladda entiteter från lagret

Länk till detta avsnitt

Om en entitet redan finns kan den laddas från lagret med följande:

let id = event.transaction.hash // eller hur ID konstrueras
let transfer = Transfer.load(id)
if (transfer == null) {
transfer = new Transfer(id)
}
// Använd överföringsenheten som tidigare

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.

Sökning av entiteter skapade inom ett block

Länk till detta avsnitt

As of graph-node v0.31.0, @graphprotocol/graph-ts v0.30.0 and @graphprotocol/graph-cli v0.49.0 the loadInBlock method is available on all entity types.

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 // eller hur ID konstrueras
let transfer = Transfer.loadInBlock(id)
if (transfer == null) {
transfer = new Transfer(id)
}
// Använd överföringsenheten som tidigare

Note: If there is no entity created in the given block, loadInBlock will return null even if there is an entity with the given ID in the store.

Sökning av härledda entiteter

Länk till detta avsnitt

As of graph-node v0.31.0, @graphprotocol/graph-ts v0.31.0 and @graphprotocol/graph-cli v0.51.0 the loadRelated method is available.

Detta möjliggör laddning av härledda entitetsfält från inom en händelsehanterare. Till exempel, med följande schema:

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

The following code will load the Token entity that the Holder entity was derived from:

let holder = Holder.load('test-id')
// Ladda de Token-enheter som är associerade med en given innehavare
let tokens = holder.tokens.load()

Uppdatering av befintliga entiteter

Länk till detta avsnitt

Det finns två sätt att uppdatera en befintlig entitet:

  1. Load the entity with e.g. Transfer.load(id), set properties on the entity, then .save() it back to the store.
  2. Simply create the entity with e.g. new Transfer(id), set properties on the entity, then .save() it to the store. If the entity already exists, the changes are merged into it.

Att ändra egenskaper är rakt fram i de flesta fall, tack vare de genererade egenskapsinställarna:

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

Det är också möjligt att avaktivera egenskaper med en av följande två instruktioner:

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

This only works with optional properties, i.e. properties that are declared without a ! in GraphQL. Two examples would be owner: Bytes or amount: BigInt.

Updating array properties is a little more involved, as the getting an array from an entity creates a copy of that array. This means array properties have to be set again explicitly after changing the array. The following assumes entity has a numbers: [BigInt!]! field.

// Detta kommer inte att fungera
entity.numbers.push(BigInt.fromI32(1))
entity.save()
// Detta kommer att fungera
let numbers = entity.numbers
numbers.push(BigInt.fromI32(1))
entity.numbers = numbers
entity.save()

Ta bort entiteter från lagret

Länk till detta avsnitt

There is currently no way to remove an entity via the generated types. Instead, removing an entity requires passing the name of the entity type and the entity ID to store.remove:

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

Ethereum API ger tillgång till smarta kontrakt, offentliga tillståndsvariabler, kontrakt funktioner, händelser, transaktioner, block och kodning/avkodning av Ethereum data.

Stöd för Ethereum-typer

Länk till detta avsnitt

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

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

Följande exempel illustrerar detta. Med en subgraph-schema som

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

and a Transfer(address,address,uint256) event signature on Ethereum, the from, to and amount values of type address, address and uint256 are converted to Address and BigInt, allowing them to be passed on to the Bytes! and BigInt! properties of the Transfer entity:

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()

Händelser och Block/Transaktionsdata

Länk till detta avsnitt

Ethereum events passed to event handlers, such as the Transfer event in the previous examples, not only provide access to the event parameters but also to their parent transaction and the block they are part of. The following data can be obtained from event instances (these classes are a part of the ethereum module in graph-ts):

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
}

Åtkomst till Smart Contract-tillstånd

Länk till detta avsnitt

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

En vanlig mönster är att komma åt kontraktet från vilket en händelse härstammar. Detta uppnås med följande kod:

// Importera den genererade kontraktsklassen och den genererade klassen för överföringshändelser
import { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract'
// Importera den genererade entitetsklassen
import { Transfer } from '../generated/schema'
export function handleTransfer(event: TransferEvent) {
// Bind kontraktet till den adress som skickade händelsen
let contract = ERC20Contract.bind(event.address)
// Åtkomst till tillståndsvariabler och funktioner genom att anropa dem
let erc20Symbol = contract.symbol()
}

Transfer is aliased to TransferEvent here to avoid a naming conflict with the entity type

As long as the ERC20Contract on Ethereum has a public read-only function called symbol, it can be called with .symbol(). For public state variables a method with the same name is created automatically.

Andra kontrakt som är en del av subgraphen kan importeras från den genererade koden och bindas till en giltig adress.

Hantering av återkallade anrop

Länk till detta avsnitt

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 gravitera = gravitera.bind(event.address)
let callResult = gravitera_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.

Kodning/Dekodning av ABI

Länk till detta avsnitt

Data can be encoded and decoded according to Ethereum's ABI encoding format using the encode and decode functions in the ethereum module.

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)

För ytterligare information:

Balance of an Address

Länk till detta avsnitt

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

Länk till detta avsnitt

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

API för loggning

Länk till detta avsnitt
import { log } from '@graphprotocol/graph-ts'

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

The log API includes the following functions:

  • log.debug(fmt: string, args: Array<string>): void - logs a debug message.
  • log.info(fmt: string, args: Array<string>): void - logs an informational message.
  • log.warning(fmt: string, args: Array<string>): void - logs a warning.
  • log.error(fmt: string, args: Array<string>): void - logs an error message.
  • log.critical(fmt: string, args: Array<string>): void – logs a critical message and terminates the subgraph.

The log API takes a format string and an array of string values. It then replaces placeholders with the string values from the array. The first {} placeholder gets replaced by the first value in the array, the second {} placeholder gets replaced by the second value and so on.

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

Loggning av ett eller flera värden

Länk till detta avsnitt
Logga ett enskilt värde
Länk till detta avsnitt

In the example below, the string value "A" is passed into an array to become['A'] before being logged:

let myValue = 'A'
export function handleSomeEvent(event: SomeEvent): void {
// Displays : "My value is: A"
log.info('My value is: {}', [myValue])
}
Logga en enskild post från en befintlig array
Länk till detta avsnitt

I exemplet nedan loggas endast det första värdet i argument arrayen, trots att arrayen innehåller tre värden.

let myArray = ['A', 'B', 'C']
export function handleSomeEvent(event: SomeEvent): void {
// Visar : "Mitt värde är: A" (Även om tre värden skickas till `log.info`)
log.info('Mitt värde är: {}', myArray)
}

Logga flera poster från en befintlig array

Länk till detta avsnitt

Each entry in the arguments array requires its own placeholder {} in the log message string. The below example contains three placeholders {} in the log message. Because of this, all three values in myArray are logged.

let myArray = ['A', 'B', 'C']
export function handleSomeEvent(event: SomeEvent): void {
// Visar: "Mitt första värde är: A, andra värdet är: B, tredje värdet är: C"
log.info('My first value is: {}, second value is: {}, third value is: {}', myArray)
}
Logga en specifik post från en befintlig array
Länk till detta avsnitt

För att visa ett specifikt värde i arrayen måste det indexeras och tillhandahållas.

export function handleSomeEvent(event: SomeEvent): void {
// Visar : "Mitt tredje värde är C"
log.info('My third value is: {}', [myArray[2]])
}
Loggning av händelseinformation
Länk till detta avsnitt

I exemplet nedan loggas blocknummer, blockhash och transaktionshash från en händelse:

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..."
])
}
import { ipfs } from '@graphprotocol/graph-ts'

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

För att läsa en fil från IPFS med en given IPFS-hash eller sökväg görs följande:

// Placera detta i en händelsehanterare i mappningen
let hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D'
let data = ipfs.cat(hash)
// Sökvägar som `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile`
// som inkluderar filer i kataloger stöds också
let path = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile'
let data = ipfs.cat(path)

Note: ipfs.cat is not deterministic at the moment. If the file cannot be retrieved over the IPFS network before the request times out, it will return null. Due to this, it's always worth checking the result for null.

It is also possible to process larger files in a streaming fashion with ipfs.map. The function expects the hash or path for an IPFS file, the name of a callback, and flags to modify its behavior:

import { JSONValue, Value } from '@graphprotocol/graph-ts'
export function processItem(value: JSONValue, userData: Value): void {
// Se JSONValue-dokumentationen för mer information om hur man hanterar
// med JSON-värden
let obj = value.toObject()
let id = obj.get('id')
let title = obj.get('title')
if (!id || !title) {
return
}
// Callbacks kan också skapa enheter
let newItem = new Item(id)
newItem.title = title.toString()
newitem.parent = userData.toString() // Ange parent till "parentId"
newitem.save()
}
// Placera detta i en händelsehanterare i mappningen
ipfs.map('Qm...', 'processItem', Value.fromString('parentId'), ['json'])
// Alternativt kan du använda `ipfs.mapJSON`.
ipfs.mapJSON('Qm...', 'processItem', Value.fromString('parentId'))

The only flag currently supported is json, which must be passed to ipfs.map. With the json flag, the IPFS file must consist of a series of JSON values, one value per line. The call to ipfs.map will read each line in the file, deserialize it into a JSONValue and call the callback for each of them. The callback can then use entity operations to store data from the JSONValue. Entity changes are stored only when the handler that called ipfs.map finishes successfully; in the meantime, they are kept in memory, and the size of the file that ipfs.map can process is therefore limited.

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

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

The crypto API makes a cryptographic functions available for use in mappings. Right now, there is only one:

  • crypto.keccak256(input: ByteArray): ByteArray
import { json, JSONValueKind } from '@graphprotocol/graph-ts'

JSON data can be parsed using the json API:

  • json.fromBytes(data: Bytes): JSONValue – parses JSON data from a Bytes array interpreted as a valid UTF-8 sequence
  • json.try_fromBytes(data: Bytes): Result<JSONValue, boolean> – safe version of json.fromBytes, it returns an error variant if the parsing failed
  • json.fromString(data: string): JSONValue – parses JSON data from a valid UTF-8 String
  • json.try_fromString(data: string): Result<JSONValue, boolean> – safe version of json.fromString, it returns an error variant if the parsing failed

The JSONValue class provides a way to pull values out of an arbitrary JSON document. Since JSON values can be booleans, numbers, arrays and more, JSONValue comes with a kind property to check the type of a value:

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

In addition, there is a method to check if the value is null:

  • value.isNull(): boolean

When the type of a value is certain, it can be converted to a built-in type using one of the following methods:

  • value.toBool(): boolean
  • value.toI64(): i64
  • value.toF64(): f64
  • value.toBigInt(): BigInt
  • value.toString(): string
  • value.toArray(): Array<JSONValue> - (and then convert JSONValue with one of the 5 methods above)

Typkonverteringsreferens

Länk till detta avsnitt
Source(s)DestinationConversion function
AddressBytesnone
AddressStrings.toHexString()
BigDecimalStrings.toString()
BigIntBigDecimals.toBigDecimal()
BigIntSträng (hexadecimal)s.toHexString() eller s.toHex()
BigIntString (unicode)s.toString()
BigInti32s.toI32()
BooleanBooleannone
Bytes (signed)BigIntBigInt.fromSignedBytes(s)
Bytes (unsigned)BigIntBigInt.fromUnsignedBytes(s)
BytesSträng (hexadecimal)s.toHexString() eller 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.fromBytes(s)
StringBigIntBigInt.fromString(s)
StringBigDecimalBigDecimal.fromString(s)
Sträng (hexadecimal)BytesByteArray.fromHexString(s)
String (UTF-8)BytesByteArray.fromUTF8(s)

Metadata för datakälla

Länk till detta avsnitt

You can inspect the contract address, network and context of the data source that invoked the handler through the dataSource namespace:

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

Entitet och DataSourceContext

Länk till detta avsnitt

The base Entity class and the child DataSourceContext class have helpers to dynamically set and get fields:

  • 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 in Manifest

Länk till detta avsnitt

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

Here is a YAML example illustrating the usage of various types in the context section:

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.

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

Redigera sida

Tidigare
Advance Subgraph Features
Nästa
Vanliga problem med AssemblyScript
Redigera sida