SDK Reference: EVM Client

This page provides a reference for the EVMClient, the low-level tool for all interactions with EVM-compatible blockchains. The client includes a comprehensive set of read, write, and utility methods for building chain-aware workflows.

Client instantiation

To use the client, you must instantiate it with the numeric ChainSelector ID for the blockchain you intend to interact with.

import { cre, getNetwork } from "@chainlink/cre-sdk"

// Get network information by chain selector name
const network = getNetwork({
  chainFamily: "evm",
  chainSelectorName: "ethereum-testnet-sepolia",
  isTestnet: true,
})

if (!network) {
  throw new Error("Network not found")
}

// Instantiate a client for Ethereum Sepolia
const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector)

Using getNetwork() helper

The getNetwork() utility function allows you to look up network information by chain selector name or numeric ID. This is the recommended approach as it provides type-safe access to chain metadata and validates network configurations.

import { getNetwork } from "@chainlink/cre-sdk"

const network = getNetwork({
  chainFamily: "evm",
  chainSelectorName: "ethereum-testnet-sepolia",
  isTestnet: true,
})

// Access network properties
console.log(network.chainSelector.selector) // 16015286601757825753n (bigint)
console.log(network.chainSelector.name) // "ethereum-testnet-sepolia"
console.log(network.family) // "evm"

Read & query methods

These methods are used to read data from the blockchain without creating a transaction.

callContract()

Executes a view or pure function on a smart contract. This method returns an object with a .result() method that blocks until the call completes.

Signature:

callContract(
  runtime: Runtime<unknown>,
  input: CallContractRequest | CallContractRequestJson
): { result: () => CallContractReply }

CallContractRequest / CallContractRequestJson

This is the main input object for the callContract() method.

Field
Type
RequiredDescription
callCallMsgJsonYesContains the actual details of the function call you want to make.
blockNumberstringNoThe block number to query. Use LAST_FINALIZED_BLOCK_NUMBER for finalized blocks or LATEST_BLOCK_NUMBER for the most recent block. Defaults to "latest".

CallMsg / CallMsgJson

This struct contains the core details of your onchain call.

Field
Type
RequiredDescription
fromstringYesThe 20-byte address of the sender (hex string). For view/pure functions, use zeroAddress from viem as the sender doesn't typically matter.
tostringYesThe 20-byte address of the target contract (hex string).
datastringYesThe ABI-encoded function call data (hex string), including the function selector and arguments.

CallContractReply

This is the object returned by .result() when the callContract() method successfully completes.

Field
Type
Description
dataUint8ArrayThe ABI-encoded data returned by the contract call.

Usage example

import { cre, getNetwork, encodeCallMsg, bytesToHex, LAST_FINALIZED_BLOCK_NUMBER } from "@chainlink/cre-sdk"
import { encodeFunctionData, decodeFunctionResult, zeroAddress } from "viem"
import { Storage } from "../contracts/abi"

// Get network and instantiate client
const network = getNetwork({
  chainFamily: "evm",
  chainSelectorName: "ethereum-testnet-sepolia",
  isTestnet: true,
})
const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector)

// Encode the contract call data
const callData = encodeFunctionData({
  abi: Storage,
  functionName: "get",
})

// Call the contract
const contractCall = evmClient
  .callContract(runtime, {
    call: encodeCallMsg({
      from: zeroAddress, // Required by encodeCallMsg. For view/pure functions, the sender doesn't matter.
      to: "0x1234567890123456789012345678901234567890",
      data: callData,
    }),
    blockNumber: LAST_FINALIZED_BLOCK_NUMBER,
  })
  .result()

// Decode the result
const value = decodeFunctionResult({
  abi: Storage,
  functionName: "get",
  data: bytesToHex(contractCall.data),
})

filterLogs()

Queries historical event logs that match a specific set of filter criteria. This method returns an object with a .result() method that blocks until the query completes.

Signature:

filterLogs(
  runtime: Runtime<unknown>,
  input: FilterLogsRequest | FilterLogsRequestJson
): { result: () => FilterLogsReply }

FilterLogsRequest / FilterLogsRequestJson

Field
Type
RequiredDescription
filterQueryFilterQueryJsonYesA struct defining the filters for the log query, such as block range, addresses, and topics.

FilterLogsReply

FieldTypeDescription
logsLog[]An array of log objects that match the filter query.

Log type

FieldTypeDescription
addressUint8ArrayThe 20-byte address of the contract that emitted the log.
topicsUint8Array[]An array of indexed log fields (32-byte arrays).
dataUint8ArrayNon-indexed log data.
blockNumberbigintThe block number where the log was emitted (optional).
txHashUint8ArrayThe 32-byte transaction hash.
txIndexnumberThe index of the transaction within the block.
blockHashUint8ArrayThe 32-byte block hash.
indexnumberThe index of the log within the transaction.
removedbooleantrue if the log was removed due to a chain reorganization.

balanceAt()

Retrieves the native token balance for a specific account. This method returns an object with a .result() method that blocks until the balance is retrieved.

Signature:

balanceAt(
  runtime: Runtime<unknown>,
  input: BalanceAtRequest | BalanceAtRequestJson
): { result: () => BalanceAtReply }

BalanceAtRequest / BalanceAtRequestJson

FieldTypeRequiredDescription
accountstringYesThe 20-byte address of the account to query (hex string).
blockNumberstringNoThe block number to query. Defaults to "latest".

BalanceAtReply

FieldTypeDescription
balancebigintThe balance of the account in Wei.

estimateGas()

Estimates the gas required to execute a specific transaction. This method returns an object with a .result() method that blocks until the estimation completes.

Signature:

estimateGas(
  runtime: Runtime<unknown>,
  input: EstimateGasRequest | EstimateGasRequestJson
): { result: () => EstimateGasReply }

EstimateGasRequest / EstimateGasRequestJson

FieldTypeRequiredDescription
msgCallMsgJsonYesThe transaction message to simulate for gas estimation.

EstimateGasReply

FieldTypeDescription
gasbigintThe estimated amount of gas in gas units.

getTransactionByHash()

Retrieves a transaction by its hash. This method returns an object with a .result() method that blocks until the transaction is retrieved.

Signature:

getTransactionByHash(
  runtime: Runtime<unknown>,
  input: GetTransactionByHashRequest | GetTransactionByHashRequestJson
): { result: () => GetTransactionByHashReply }

GetTransactionByHashRequest / GetTransactionByHashRequestJson

FieldTypeRequiredDescription
hashstringYesThe 32-byte hash of the transaction to look up (hex string).

GetTransactionByHashReply

FieldTypeDescription
transactionTransactionThe transaction object, if found.

Transaction type

FieldTypeDescription
noncebigintThe nonce of the transaction.
gasbigintThe gas limit.
toUint8ArrayThe 20-byte address of the recipient.
dataUint8ArrayThe transaction data payload.
hashUint8ArrayThe 32-byte transaction hash.
valuebigintThe value transferred in Wei.
gasPricebigintThe gas price in Wei.

getTransactionReceipt()

Fetches the receipt for a transaction given its hash. This method returns an object with a .result() method that blocks until the receipt is retrieved.

Signature:

getTransactionReceipt(
  runtime: Runtime<unknown>,
  input: GetTransactionReceiptRequest | GetTransactionReceiptRequestJson
): { result: () => GetTransactionReceiptReply }

GetTransactionReceiptRequest / GetTransactionReceiptRequestJson

FieldTypeRequiredDescription
hashstringYesThe 32-byte hash of the transaction (hex string).

GetTransactionReceiptReply

FieldTypeDescription
receiptReceiptThe transaction receipt object, if found.

Receipt type

FieldTypeDescription
statusbigintTransaction status: 1 for success, 0 for failure.
gasUsedbigintThe amount of gas used by the transaction.
txIndexbigintThe index of the transaction within the block.
blockHashUint8ArrayThe 32-byte block hash.
logsLog[]An array of log objects emitted by the transaction.
txHashUint8ArrayThe 32-byte transaction hash.
effectiveGasPricebigintThe actual gas price paid per gas unit (optional).
blockNumberbigintThe block number where the transaction was included (optional).
contractAddressUint8ArrayThe address of the deployed contract (if applicable).

headerByNumber()

Retrieves a block header by its number. This method returns an object with a .result() method that blocks until the header is retrieved.

Signature:

headerByNumber(
  runtime: Runtime<unknown>,
  input: HeaderByNumberRequest | HeaderByNumberRequestJson
): { result: () => HeaderByNumberReply }

HeaderByNumberRequest / HeaderByNumberRequestJson

Field
Type
RequiredDescription
blockNumberstringNoThe number of the block to retrieve. If undefined, retrieves the latest block.

HeaderByNumberReply

FieldTypeDescription
headerHeaderThe block header object, if found.

Header type

FieldTypeDescription
timestampbigintThe Unix timestamp of the block.
blockNumberbigintThe block number (optional).
hashUint8ArrayThe 32-byte block hash.
parentHashUint8ArrayThe 32-byte hash of the parent block.

Write methods

writeReport()

Executes a state-changing transaction by submitting a cryptographically signed report to a designated receiver contract. This is the primary method for writing data onchain in CRE workflows.

Signature:

writeReport(
  runtime: Runtime<unknown>,
  input: WriteCreReportRequest | WriteCreReportRequestJson
): { result: () => WriteReportReply }

WriteCreReportRequest / WriteCreReportRequestJson

FieldTypeRequiredDescription
receiverstringYesThe 20-byte address of the receiver contract to call (hex string).
reportReportYesThe report object generated by runtime.report().
gasConfigGasConfigJsonNoGas limit configuration for the transaction.

GasConfig / GasConfigJson

FieldTypeRequiredDescription
gasLimitstringYesThe gas limit for the transaction.

WriteReportReply

FieldTypeDescription
txStatusTxStatusThe final status of the transaction: TX_STATUS_SUCCESS, TX_STATUS_REVERTED, or TX_STATUS_FATAL.
receiverContractExecutionStatusReceiverContractExecutionStatusThe status of the receiver contract's execution: RECEIVER_CONTRACT_EXECUTION_STATUS_SUCCESS or RECEIVER_CONTRACT_EXECUTION_STATUS_REVERTED (optional).
txHashUint8ArrayThe 32-byte transaction hash of the onchain submission (optional).
transactionFeebigintThe total fee paid for the transaction in Wei (optional).
errorMessagestringAn error message if the transaction failed (optional).

TxStatus enum

  • TX_STATUS_SUCCESS: The transaction was successful.
  • TX_STATUS_REVERTED: The transaction reverted.
  • TX_STATUS_FATAL: A fatal error occurred.

Usage example

import { cre, getNetwork, hexToBase64, bytesToHex } from "@chainlink/cre-sdk"
import { encodeFunctionData } from "viem"
import { ReserveManager } from "../contracts/abi"

// Encode the contract call data
const callData = encodeFunctionData({
  abi: ReserveManager,
  functionName: "updateReserves",
  args: [
    {
      totalMinted: 100n,
      totalReserve: 50n,
    },
  ],
})

// Generate a signed report
const reportResponse = runtime
  .report({
    encodedPayload: hexToBase64(callData),
    encoderName: "evm",
    signingAlgo: "ecdsa",
    hashingAlgo: "keccak256",
  })
  .result()

// Submit the report onchain
const writeResult = evmClient
  .writeReport(runtime, {
    receiver: "0x1234567890123456789012345678901234567890",
    report: reportResponse,
    gasConfig: {
      gasLimit: "1000000",
    },
  })
  .result()

runtime.log(`Transaction hash: ${bytesToHex(writeResult.txHash || new Uint8Array(32))}`)

Log tracking methods

These methods manage stateful log tracking subscriptions.

registerLogTracking()

Creates a persistent filter to track specific logs over time. This is a "fire-and-forget" operation that returns an empty result.

Signature:

registerLogTracking(
  runtime: Runtime<unknown>,
  input: RegisterLogTrackingRequest | RegisterLogTrackingRequestJson
): { result: () => Empty }

RegisterLogTrackingRequest / RegisterLogTrackingRequestJson

Field
Type
RequiredDescription
filterLPFilterJsonYesA struct defining the persistent log filter, including rate limits and retention policies.

unregisterLogTracking()

Removes a previously registered log tracking filter. This is a "fire-and-forget" operation that returns an empty result.

Signature:

unregisterLogTracking(
  runtime: Runtime<unknown>,
  input: UnregisterLogTrackingRequest | UnregisterLogTrackingRequestJson
): { result: () => Empty }

UnregisterLogTrackingRequest / UnregisterLogTrackingRequestJson

FieldTypeDescription
filterNamestringThe unique name of the filter to remove.

Helper functions

The TypeScript SDK provides several helper functions for working with the EVM Client.

encodeCallMsg()

Encodes a call message payload into a CallMsgJson, expected by the EVM capability.

Signature:

function encodeCallMsg(payload: EncodeCallMsgPayload): CallMsgJson

Parameters:

interface EncodeCallMsgPayload {
  from: Address // viem Address type (0x-prefixed hex string)
  to: Address
  data: Hex // viem Hex type (0x-prefixed hex string)
}

Usage:

import { encodeCallMsg } from "@chainlink/cre-sdk"
import { zeroAddress } from "viem"

const callMsg = encodeCallMsg({
  from: zeroAddress,
  to: "0x1234567890123456789012345678901234567890",
  data: "0xabcdef",
})

bytesToHex()

Converts a Uint8Array to a 0x-prefixed hex string.

Signature:

function bytesToHex(bytes: Uint8Array): Hex

hexToBase64()

Converts a 0x-prefixed hex string to a base64-encoded string. This is useful for preparing data for protobuf structures.

Signature:

function hexToBase64(hex: Hex): string

prepareReportRequest()

Prepares a report request with default EVM encoding parameters for use with runtime.report(). This helper simplifies report generation by automatically setting the standard encoding configuration (evm, ecdsa, keccak256) required for EVM-based workflows.

Signature:

function prepareReportRequest(
  hexEncodedPayload: Hex,
  reportEncoder?: Exclude<ReportRequestJson, "encodedPayload">
): ReportRequestJson

Parameters:

  • hexEncodedPayload: The hex-encoded payload (typically from encodeFunctionData()) to be signed by the DON
  • reportEncoder: Optional. Custom report encoder configuration. Defaults to EVM_DEFAULT_REPORT_ENCODER ({ encoderName: 'evm', signingAlgo: 'ecdsa', hashingAlgo: 'keccak256' })

Returns:

A ReportRequestJson object ready to pass to runtime.report().

Usage:

import { prepareReportRequest, type Runtime } from "@chainlink/cre-sdk"
import { encodeFunctionData } from "viem"
import { MyContractABI } from "./abi"

// Encode the function call data
const callData = encodeFunctionData({
  abi: MyContractABI,
  functionName: "updateValue",
  args: [42n],
})

// Generate a signed report using the helper (simplest approach)
const report = runtime.report(prepareReportRequest(callData)).result()

// The helper automatically sets:
// - encodedPayload: hexToBase64(callData)
// - encoderName: "evm"
// - signingAlgo: "ecdsa"
// - hashingAlgo: "keccak256"

Equivalent manual approach:

import { hexToBase64, type Runtime } from "@chainlink/cre-sdk"

// Without the helper, you must specify all parameters manually
const report = runtime
  .report({
    encodedPayload: hexToBase64(callData),
    encoderName: "evm",
    signingAlgo: "ecdsa",
    hashingAlgo: "keccak256",
  })
  .result()

LAST_FINALIZED_BLOCK_NUMBER

A constant representing the last finalized block number for use in callContract() and similar methods.

const LAST_FINALIZED_BLOCK_NUMBER = {
  absVal: Buffer.from([3]).toString("base64"), // 3 for finalized block
  sign: "-1",
}

Usage:

import { LAST_FINALIZED_BLOCK_NUMBER } from "@chainlink/cre-sdk"

const contractCall = evmClient
  .callContract(runtime, {
    call: encodeCallMsg({ from: zeroAddress, to: contractAddress, data: callData }),
    blockNumber: LAST_FINALIZED_BLOCK_NUMBER,
  })
  .result()

LATEST_BLOCK_NUMBER

A constant representing the latest mined block number.

const LATEST_BLOCK_NUMBER = {
  absVal: Buffer.from([2]).toString("base64"), // 2 for the latest block
  sign: "-1",
}

Chain Selectors

A chain selector is a unique identifier for a blockchain network used throughout the CRE platform. In TypeScript, you work with chain selectors primarily through the getNetwork() helper function.

Using getNetwork()

The recommended way to work with chain selectors in TypeScript:

import { getNetwork } from "@chainlink/cre-sdk"

const network = getNetwork({
  chainFamily: "evm",
  chainSelectorName: "ethereum-testnet-sepolia",
  isTestnet: true,
})

if (!network) {
  throw new Error("Network not found")
}

// Access the numeric chain selector (bigint)
const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector)
// network.chainSelector.selector is 16015286601757825753n (bigint)

Supported networks

The EVMClient class includes a static SUPPORTED_CHAINS constant with all available chain selectors:

cre.capabilities.EVMClient.SUPPORTED_CHAINS
// Returns:
// {
//   'avalanche-mainnet': 6433500567565415381n,
//   'avalanche-testnet-fuji': 14767482510784806043n,
//   'ethereum-testnet-sepolia': 16015286601757825753n,
//   // ... and more
// }

Chain selector reference

This table shows the chain selector names and their numeric IDs. In your configuration files (project.yaml, config.staging.json, config.production.json, etc.), you always use the String Name. The numeric ID is used internally by the SDK and is returned by the getNetwork() helper function.

Chain
String Name
Numeric ID
Arbitrum Mainnetethereum-mainnet-arbitrum-14949039107694359620
Arbitrum Sepoliaethereum-testnet-sepolia-arbitrum-13478487238524512106
Avalanche Mainnetavalanche-mainnet6433500567565415381
Avalanche Fuji Testnetavalanche-testnet-fuji14767482510784806043
BNB Smart Chain opBNB Mainnetbinance_smart_chain-mainnet-opbnb-1465944652040885897
BNB Smart Chain opBNB Testnetbinance_smart_chain-testnet-opbnb-113274425992935471758
Ethereum Mainnetethereum-mainnet5009297550715157269
Ethereum Sepolia Testnetethereum-testnet-sepolia16015286601757825753
Ethereum Sepolia (Base)ethereum-testnet-sepolia-base-110344971235874465080
Optimism Mainnetethereum-mainnet-optimism-13734403246176062136
Optimism Sepoliaethereum-testnet-sepolia-optimism-15224473277236331295
Polygon Mainnetpolygon-mainnet4051577828743386545
Polygon Amoy Testnetpolygon-testnet-amoy16281711391670634445

Usage in configuration files

In your project.yaml file (RPC configuration):

local-simulation:
  rpcs:
    - chain-name: ethereum-testnet-sepolia # String name for RPC endpoint
      url: https://your-rpc-url.com

In your workflow's config.json file (workflow-specific settings):

Your workflow configuration can include chain selector names as part of your custom config structure. For example:

{
  "schedule": "*/30 * * * * *",
  "evms": [
    {
      "storageAddress": "0x1234...",
      "chainName": "ethereum-testnet-sepolia" // Use string name in your config
    }
  ]
}

In your workflow TypeScript code:

// Recommended: Use getNetwork() with the string name from your config
const network = getNetwork({
  chainFamily: "evm",
  chainSelectorName: config.evms[0].chainName, // Read from your config
  isTestnet: true,
})

if (!network) {
  throw new Error(`Network not found: ${config.evms[0].chainName}`)
}

const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector)

Get the latest Chainlink content straight to your inbox.