---
title: AssemblyScript API
---

> 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](https://github.com/graphprotocol/graph-tooling/tree/main/packages/ts) (`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](https://github.com/AssemblyScript/assemblyscript).

Since language mappings are written in AssemblyScript, it is useful to review the language and standard library features from the [AssemblyScript wiki](https://github.com/AssemblyScript/assemblyscript/wiki).

## API Reference

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.
- Low-level primitives to translate between different type systems such as Ethereum, JSON, GraphQL and AssemblyScript.

### Versions

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

| Version | Release notes |
| :-: | --- |
| 0.0.9 | Adds new host functions [`eth_get_balance`](#balance-of-an-address) & [`hasCode`](#check-if-an-address-is-a-contract-or-eoa) |
| 0.0.8 | Adds validation for existence of fields in the schema when saving an entity. |
| 0.0.7 | Added `TransactionReceipt` and `Log` classes to the Ethereum types<br />Added `receipt` field to the Ethereum Event object |
| 0.0.6 | Added `nonce` field to the Ethereum Transaction object<br />Added `baseFeePerGas` to the Ethereum Block object |
| 0.0.5 | AssemblyScript upgraded to version 0.19.10 (this includes breaking changes, please see the `Migration Guide`)<br />`ethereum.transaction.gasUsed` renamed to `ethereum.transaction.gasLimit` |
| 0.0.4 | Added `functionSignature` field to the Ethereum SmartContractCall object |
| 0.0.3 | Added `from` field to the Ethereum Call object<br />`ethereum.call.address` renamed to `ethereum.call.to` |
| 0.0.2 | Added `input` field to the Ethereum Transaction object |

### Built-in Types

Documentation on the base types built into AssemblyScript can be found in the [AssemblyScript wiki](https://www.assemblyscript.org/types.html).

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

#### ByteArray

```typescript
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`

#### BigDecimal

```typescript
import { BigDecimal } from '@graphprotocol/graph-ts'
```

`BigDecimal` is used to represent arbitrary precision decimals.

> Note: [Internally](https://github.com/graphprotocol/graph-node/blob/master/graph/src/data/store/scalar/bigdecimal.rs) `BigDecimal` is stored in [IEEE-754 decimal128 floating-point format](https://en.wikipedia.org/wiki/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`](https://docs.soliditylang.org/en/latest/types.html#fixed-point-numbers) 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`.

#### BigInt

```typescript
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`.

#### TypedMap

```typescript
import { TypedMap } from '@graphprotocol/graph-ts'
```

`TypedMap` can be used to store key-value pairs. See [this example](https://github.com/graphprotocol/aragon-subgraph/blob/29dd38680c5e5104d9fdc2f90e740298c67e4a31/individual-dao-subgraph/mappings/constants.ts#L51).

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

#### Bytes

```typescript
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](https://github.com/AssemblyScript/assemblyscript/blob/3b1852bc376ae799d9ebca888e6413afac7b572f/std/assembly/typedarray.ts#L64) 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`

#### Address

```typescript
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

### Store API

```typescript
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](https://github.com/graphprotocol/graph-tooling/tree/main/packages/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.

#### Creating entities

The following is a common pattern for creating entities from Ethereum events.

```typescript
// Import the Transfer event class generated from the ERC20 ABI
import { Transfer as TransferEvent } from '../generated/ERC20/ERC20'

// Import the Transfer entity type generated from the GraphQL schema
import { Transfer } from '../generated/schema'

// Transfer event handler
export function handleTransfer(event: TransferEvent): void {
  // Create a Transfer entity, using the transaction hash as the entity ID
  let id = event.transaction.hash
  let transfer = new Transfer(id)

  // Set properties on the entity, using the event parameters
  transfer.from = event.params.from
  transfer.to = event.params.to
  transfer.amount = event.params.amount

  // Save the entity to the store
  transfer.save()
}
```

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.

#### Loading entities from the store

If an entity already exists, it can be loaded from the store with the following:

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

// Use the Transfer entity as before
```

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

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

#### Looking up entities created within a block

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 onchain 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.

```typescript
let id = event.transaction.hash // or however the ID is constructed
let transfer = Transfer.loadInBlock(id)
if (transfer == null) {
  transfer = new Transfer(id)
}

// Use the Transfer entity as before
```

> 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.

#### Looking up derived entities

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.

This enables loading derived entity fields from within an event handler. For example, given the following schema:

```graphql
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:

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

#### Updating existing entities

There are two ways to update an existing entity:

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.

Changing properties is straight forward in most cases, thanks to the generated property setters:

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

It is also possible to unset properties with one of the following two instructions:

```typescript
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.

```typescript
// This won't work
entity.numbers.push(BigInt.fromI32(1))
entity.save()

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

#### Removing entities from the store

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`:

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

### Ethereum API

The Ethereum API provides access to smart contracts, public state variables, contract functions, events, transactions, blocks and the encoding/decoding Ethereum data.

#### Ethereum JSON‑RPC Schema Changes & Execution Client Compatibility

Following Ethereum's [transition to Proof of Stake](https://ethereum.org/en/roadmap/merge/), the Execution Layer JSON-RPC schema was updated to reflect changes in block metadata.

The `totalDifficulty` field was [officially removed](https://github.com/ethereum/execution-apis/pull/570) from the `eth_getBlockByNumber` response. Additionally, the `difficulty` field—previously used in Proof of Work—was retained as **optional** but is now considered obsolete and typically returned as `"0x0"` by spec-compliant clients. While some clients continue to include these fields for backward compatibility, developers relying on them should update their subgraphs and tooling to accommodate these schema changes. Full schema details are available in the [Ethereum Execution APIs documentation](https://ethereum.github.io/execution-apis/). We've added a chart with the current client compatibility with these updates as of July 17, 2025. **Please check for specific client updates as needed**.

**Ethereum JSON‑RPC Schema Changes Post-Merge**

| Field             | JSON‑RPC Schema Status (Post-Merge)                                         |
| ----------------- | --------------------------------------------------------------------------- |
| `totalDifficulty` | ❌ Removed from `eth_getBlockByNumber` response                             |
| `difficulty`      | ⚠️ Optional, expected to be `0x0` post-Merge, but many clients still return |
| `size`            | ⚠️ Optional; may be omitted depending on client                             |

**Execution Client Compatibility**

| Client | totalDifficulty | difficulty | size | Notes |
| --- | --- | --- | --- | --- |
| **Erigon v3** | Not returned | Non-zero | Usually present | Strict spec compliance, noted [here](https://github.com/erigontech/erigon/issues/13012) |
| **Geth** | Returned | Non-zero | Returned | Maintains legacy behavior, noted [here](https://ethereum.org/developers/docs/apis/json-rpc/#eth_getblockbyhash) |
| **Nethermind** | Returned | Non-zero | Returned | Maintains legacy behavior, noted [here](https://docs.nethermind.io/interacting/json-rpc-ns/eth/#eth_getblockbynumber) |
| **Besu** | Returns `0` for an uncle block | Non-zero | Returned | Returns deprecated fields with valid values, noted [here](https://besu.hyperledger.org/public-networks/reference/api/objects) |
| **Reth** | Not Returned | `"0x0"` | Returned | Highly spec-compliant, aligns with post-Merge schema |

#### Support for Ethereum Types

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](#built-in-types) take place behind the scenes so that Subgraph authors do not have to worry about them.

The following example illustrates this. Given a Subgraph schema like

```graphql
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:

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

#### Events and Block/Transaction Data

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`):

```typescript
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
}
```

#### Access to Smart Contract State

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.

A common pattern is to access the contract from which an event originates. This is achieved with the following code:

```typescript
// Import the generated contract class and generated Transfer event class
import { ERC20Contract, Transfer as TransferEvent } from '../generated/ERC20Contract/ERC20Contract'
// Import the generated entity class
import { Transfer } from '../generated/schema'

export function handleTransfer(event: TransferEvent) {
  // Bind the contract to the address that emitted the event
  let contract = ERC20Contract.bind(event.address)

  // Access state variables and functions by calling them
  let erc20Symbol = contract.symbol()
}
```

`Transfer` 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.

Any other contract that is part of the subgraph can be imported from the generated code and can be bound to a valid address. An example of that is presented within the steps below:

- Extend `subgraph.yaml` file with desired ABI file:

```yaml
mapping:
  kind: ethereum/events
  apiVersion: 0.0.6
  language: wasm/assemblyscript
  entities:
    - Gravatar
  abis:
    - name: Gravity
      file: ./abis/Gravity.json
    - name: OtherContract
      file: ./abis/OtherContract.json
```

- Import and bind to the contract using its address

#### Handling Reverted Calls

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:

```typescript
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.

#### Encoding/Decoding ABI

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

```typescript
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)
```

For more information:

- [ABI Spec](https://docs.soliditylang.org/en/v0.7.4/abi-spec.html#types)
- Encoding/decoding [Rust library/CLI](https://github.com/rust-ethereum/ethabi)
- More [complex example](https://github.com/graphprotocol/graph-node/blob/08da7cb46ddc8c09f448c5ea4b210c9021ea05ad/tests/integration-tests/host-exports/src/mapping.ts#L86).

#### Balance of an Address

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.

```typescript
import { ethereum } from '@graphprotocol/graph-ts'

let address = Address.fromString('0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045')
let balance = ethereum.getBalance(address) // returns balance in BigInt
```

#### Check if an Address is a Contract or EOA

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

```typescript
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
```

### Logging API

```typescript
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.

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

#### Logging one or more values

##### Logging a single value

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

```typescript
let myValue = 'A'

export function handleSomeEvent(event: SomeEvent): void {
  // Displays : "My value is: A"
  log.info('My value is: {}', [myValue])
}
```

##### Logging a single entry from an existing array

In the example below, only the first value of the argument array is logged, despite the array containing three values.

```typescript
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)
}
```

#### Logging multiple entries from an existing array

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.

```typescript
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)
}
```

##### Logging a specific entry from an existing array

To display a specific value in the array, the indexed value must be provided.

```typescript
export function handleSomeEvent(event: SomeEvent): void {
  // Displays : "My third value is C"
  log.info('My third value is: {}', [myArray[2]])
}
```

##### Logging event information

The example below logs the block number, block hash and transaction hash from an event:

```typescript
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..."
  ])
}
```

<VideoEmbed title="How to Use Logging to Debug a Subgraph Mappins Error" youtube="7H3bm87u5Jw" />

### IPFS API

```typescript
import { ipfs } from '@graphprotocol/graph-ts'
```

Smart contracts occasionally anchor IPFS files onchain. 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.

Given an IPFS hash or path, reading a file from IPFS is done as follows:

```typescript
// Put this inside an event handler in the mapping
let hash = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D'
let data = ipfs.cat(hash)

// Paths like `QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile`
// that include files in directories are also supported
let path = 'QmTkzDwWqPbnAh5YiV5VwcTLnGdwSNsNTn2aDxdXBFca7D/Makefile'
let data = ipfs.cat(path)
```

**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:

```typescript
import { JSONValue, Value } from '@graphprotocol/graph-ts'

export function processItem(value: JSONValue, userData: Value): void {
  // See the JSONValue documentation for details on dealing
  // with JSON values
  let obj = value.toObject()
  let id = obj.get('id')
  let title = obj.get('title')

  if (!id || !title) {
    return
  }

  // Callbacks can also created entities
  let newItem = new Item(id)
  newItem.title = title.toString()
  newitem.parent = userData.toString() // Set parent to "parentId"
  newitem.save()
}

// Put this inside an event handler in the mapping
ipfs.map('Qm...', 'processItem', Value.fromString('parentId'), ['json'])

// Alternatively, use `ipfs.mapJSON`
ipfs.mapJSON('Qm...', 'processItem', Value.fromString('parentId'))
```

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.

### Crypto API

```typescript
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`

### JSON API

```typescript
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:

```typescript
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](#built-in-types) 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)

### Type Conversions Reference

| 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               | Bytes                | s.fromBigInt()               |
| 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.fromBytes(s)         |
| String               | BigInt               | BigInt.fromString(s)         |
| String               | BigDecimal           | BigDecimal.fromString(s)     |
| String (hexadecimal) | Bytes                | Bytes.fromHexString(s)       |
| String (UTF-8)       | Bytes                | Bytes.fromUTF8(s)            |

### Data Source Metadata

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`

### Entity and DataSourceContext

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

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:

```yaml
dataSources:
  - kind: ethereum/contract
    name: ContractName
    network: mainnet
    context:
      bool_example:
        type: Bool
        data: true
      string_example:
        type: String
        data: 'hello'
      int_example:
        type: Int
        data: 42
      int8_example:
        type: Int8
        data: 127
      big_decimal_example:
        type: BigDecimal
        data: '10.99'
      bytes_example:
        type: Bytes
        data: '0x68656c6c6f'
      list_example:
        type: List
        data:
          - type: Int
            data: 1
          - type: Int
            data: 2
          - type: Int
            data: 3
      big_int_example:
        type: BigInt
        data: '1000000000000000000000000'
```

- `Bool`: Specifies a Boolean value (`true` or `false`).
- `String`: Specifies a String value.
- `Int`: Specifies a 32-bit integer.
- `Int8`: Specifies an 8-bit integer.
- `BigDecimal`: Specifies a decimal number. Must be quoted.
- `Bytes`: Specifies a hexadecimal string.
- `List`: Specifies a list of items. Each item needs to specify its type and data.
- `BigInt`: Specifies a large integer value. Must be quoted due to its large size.

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