From d4d15b171edf2239ed5f5654e1001ffd7fcd5667 Mon Sep 17 00:00:00 2001 From: De Clercq Wentzel <10665586+wentzeld@users.noreply.github.com> Date: Mon, 2 Mar 2026 07:38:22 -0800 Subject: [PATCH] docs: document encodeCallMsg validation and logTriggerConfig helper - Add caution about silent data corruption when bypassing encodeCallMsg - Document field-context error messages in encodeCallMsg - Add logTriggerConfig() as recommended approach for log trigger setup - Restructure EVM log trigger docs to prioritize logTriggerConfig over manual hexToBase64 --- .../cre/reference/sdk/evm-client-ts.mdx | 53 ++++- .../sdk/triggers/evm-log-trigger-ts.mdx | 187 ++++++++++++------ 2 files changed, 176 insertions(+), 64 deletions(-) diff --git a/src/content/cre/reference/sdk/evm-client-ts.mdx b/src/content/cre/reference/sdk/evm-client-ts.mdx index d26104691e8..20fde4f3b32 100644 --- a/src/content/cre/reference/sdk/evm-client-ts.mdx +++ b/src/content/cre/reference/sdk/evm-client-ts.mdx @@ -502,7 +502,13 @@ The TypeScript SDK provides several helper functions for working with the EVM Cl ### `encodeCallMsg()` -Encodes a call message payload into a `CallMsgJson`, expected by the EVM capability. +Encodes a call message payload into a `CallMsgJson`, expected by the EVM capability. This helper converts `0x`-prefixed hex strings to the base64 format required by the protobuf `CallMsg` structure. + + **Signature:** @@ -520,6 +526,12 @@ interface EncodeCallMsgPayload { } ``` +All fields must be valid `0x`-prefixed hex strings. If any field contains invalid hex, the function throws an error identifying which field is invalid: + +``` +Invalid hex in 'to' field of CallMsg: Invalid hex string: missing '0x' prefix... +``` + **Usage:** ```typescript @@ -708,6 +720,45 @@ const report = runtime --- +### `logTriggerConfig()` + +Creates a validated log trigger configuration from hex-encoded addresses and topics. This helper converts hex values to the base64-encoded format expected by `evmClient.logTrigger()`, validates byte lengths (20 bytes for addresses, 32 bytes for topics), and formats the confidence level. + +**Signature:** + +```typescript +function logTriggerConfig(opts: LogTriggerConfigOptions): FilterLogTriggerRequestJson +``` + +**Parameters:** + +| Field | Type | Description | +| ------------ | --------------------------------------- | ---------------------------------------------------------------------------- | +| `addresses` | `Hex[]` | **Required.** EVM addresses to monitor (`0x`-prefixed hex, 20 bytes each). | +| `topics` | `Hex[][]` | Optional. Up to 4 arrays of topic values (`0x`-prefixed hex, 32 bytes each). | +| `confidence` | `'SAFE'` \| `'LATEST'` \| `'FINALIZED'` | Optional. Block confirmation level. Defaults to `SAFE`. | + +**Usage:** + +```typescript +import { logTriggerConfig } from "@chainlink/cre-sdk" +import { keccak256, toBytes } from "viem" + +const transferEvent = keccak256(toBytes("Transfer(address,address,uint256)")) + +const trigger = evmClient.logTrigger( + logTriggerConfig({ + addresses: ["0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9"], + topics: [[transferEvent]], + confidence: "LATEST", + }) +) +``` + +See [EVM Log Trigger](/cre/reference/sdk/triggers/evm-log-trigger-ts) for the full configuration reference. + +--- + ### `LAST_FINALIZED_BLOCK_NUMBER` A constant representing the last finalized block number for use in `callContract()` and similar methods. diff --git a/src/content/cre/reference/sdk/triggers/evm-log-trigger-ts.mdx b/src/content/cre/reference/sdk/triggers/evm-log-trigger-ts.mdx index 8caccb57096..6a586439c5e 100644 --- a/src/content/cre/reference/sdk/triggers/evm-log-trigger-ts.mdx +++ b/src/content/cre/reference/sdk/triggers/evm-log-trigger-ts.mdx @@ -16,15 +16,10 @@ The EVM Log Trigger fires when a specific log (event) is emitted by an onchain s ## Creating the trigger - +The recommended way to create a log trigger is with the `logTriggerConfig()` helper, which accepts hex-encoded addresses and topics and handles base64 conversion, byte-length validation, and confidence level formatting automatically: ```typescript -import { EVMClient, getNetwork, hexToBase64 } from "@chainlink/cre-sdk" +import { EVMClient, getNetwork, logTriggerConfig } from "@chainlink/cre-sdk" import { keccak256, toBytes } from "viem" // Create an EVMClient instance with a chain selector @@ -39,8 +34,35 @@ const evmClient = new EVMClient(network.chainSelector.selector) // Create a log trigger with address and event signature const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) +const trigger = evmClient.logTrigger( + logTriggerConfig({ + addresses: ["0x1234567890123456789012345678901234567890"], + topics: [[transferEventHash]], + }) +) +``` + + + +
+Manual configuration with hexToBase64() + +If you need more control, you can encode values manually using `hexToBase64()`: + +```typescript +import { EVMClient, getNetwork, hexToBase64 } from "@chainlink/cre-sdk" +import { keccak256, toBytes } from "viem" + +const evmClient = new EVMClient(network.chainSelector.selector) + +const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) + const trigger = evmClient.logTrigger({ - addresses: [hexToBase64("0x123...abc")], + addresses: [hexToBase64("0x1234567890123456789012345678901234567890")], topics: [ { values: [hexToBase64(transferEventHash)], @@ -49,14 +71,95 @@ const trigger = evmClient.logTrigger({ }) ``` -## Configuration +
-The `logTrigger()` method accepts a configuration object with the following fields: +## `logTriggerConfig()` helper + +The `logTriggerConfig()` helper is the recommended way to build the configuration object for `logTrigger()`. It accepts hex-encoded addresses and topics (the format you get from viem) and handles: + +- **Base64 conversion**: Converts `0x`-prefixed hex to the base64 encoding required by the proto +- **Byte-length validation**: Verifies addresses are 20 bytes and topics are 32 bytes +- **Confidence formatting**: Accepts short names (`'LATEST'`, `'SAFE'`, `'FINALIZED'`) instead of the full `CONFIDENCE_LEVEL_` prefix + +**Signature:** + +```typescript +function logTriggerConfig(opts: LogTriggerConfigOptions): FilterLogTriggerRequestJson +``` + +**Parameters:** + +```typescript +interface LogTriggerConfigOptions { + /** EVM addresses to monitor — hex strings with 0x prefix (20 bytes each) */ + addresses: Hex[] + /** Topic filters — array of up to 4 arrays of hex topic values (32 bytes each). + * - topics[0]: event signatures (keccak256 hashes), at least one required + * - topics[1]: possible values for first indexed arg (optional) + * - topics[2]: possible values for second indexed arg (optional) + * - topics[3]: possible values for third indexed arg (optional) + */ + topics?: Hex[][] + /** Confidence level for log finality. Defaults to SAFE. */ + confidence?: "SAFE" | "LATEST" | "FINALIZED" +} +``` + +**Validation errors:** + +The helper throws descriptive errors for common mistakes: + +- Missing `0x` prefix on addresses or topics +- Addresses that aren't exactly 20 bytes +- Topics that aren't exactly 32 bytes +- Error messages include the index of the invalid value (e.g., `"Invalid address at index 1: ..."`) + +**Example with topic filtering:** + +```typescript +import { logTriggerConfig } from "@chainlink/cre-sdk" +import { keccak256, toBytes, padHex } from "viem" + +const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) +const fromAddress = padHex("0xabcdef1234567890abcdef1234567890abcdef12", { size: 32 }) + +const trigger = evmClient.logTrigger( + logTriggerConfig({ + addresses: ["0x1234567890123456789012345678901234567890"], + topics: [ + // Topic 0: Event signature (Transfer event) - already 32 bytes + [transferEventHash], + // Topic 1: From address (indexed parameter 1) - must pad from 20 to 32 bytes + [fromAddress], + // Topic 2: Omit for wildcard (any "to" address) + ], + confidence: "FINALIZED", + }) +) +``` + + + + + +--- + +## Raw configuration reference + +The `logTrigger()` method accepts a `FilterLogTriggerRequestJson` object directly. When using `logTriggerConfig()`, the helper builds this object for you. If you need to construct it manually, the fields are: |
Field
|
Type
| Description | | -------------------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `addresses` | `string[]` | **Required.** A list of contract addresses to monitor. **Must be base64 encoded** using `hexToBase64()`. At least one address is required. | -| `topics` | `TopicValues[]` | **Required.** An array to filter event topics. The first element must contain at least one event signature. The next three elements can contain indexed argument values (optional). An empty array element acts as a wildcard for indexed arguments. **All topic values must be base64 encoded** using `hexToBase64()`. | +| `topics` | `TopicValues[]` | Optional. An array to filter event topics. The first element must contain at least one event signature. The next three elements can contain indexed argument values (optional). An empty array element acts as a wildcard for indexed arguments. **All topic values must be base64 encoded** using `hexToBase64()`. | | `confidence` | `string` | Optional. The block confirmation level to monitor. Can be: |