From 0702dad19d3e9f9f8056d814167f56db8efd9ea9 Mon Sep 17 00:00:00 2001 From: Karim <98668332+khadni@users.noreply.github.com> Date: Tue, 20 Jan 2026 14:54:39 -0500 Subject: [PATCH 1/2] update TS examples to direct imports, clarify logging and error handling --- reports/llms-report.json | 127 ---- src/content/chainlink-local/llms-full.txt | 9 +- .../index-trigger-callback-example.ts | 2 +- .../cre/concepts/non-determinism-ts.mdx | 16 +- .../part-1-project-setup-ts.mdx | 8 +- .../getting-started/snippets/part-1-main.ts | 6 +- .../getting-started/snippets/part-2-main.ts | 16 +- .../getting-started/snippets/part-3-main.ts | 13 +- .../getting-started/snippets/part-4-main.ts | 15 +- .../secrets/using-secrets-deployed.mdx | 4 +- .../snippets/using-secrets-multiple-ts.ts | 8 +- .../snippets/using-secrets-single-ts.ts | 8 +- .../using-evm-client/onchain-read-ts.mdx | 22 +- .../onchain-write/writing-data-onchain.mdx | 26 +- .../using-http-client/get-request-ts.mdx | 60 +- .../using-http-client/post-request-ts.mdx | 41 +- .../submitting-reports-http-ts.mdx | 26 +- .../using-triggers/cron-trigger-ts.mdx | 10 +- .../using-triggers/evm-log-trigger-ts.mdx | 60 +- .../code-snippets/simulation-example.ts | 8 +- .../http-trigger/configuration-ts.mdx | 8 +- src/content/cre/index.mdx | 6 +- src/content/cre/llms-full-go.txt | 30 +- src/content/cre/llms-full-ts.txt | 621 +++++++++++------- .../cre/reference/sdk/consensus-ts.mdx | 17 +- src/content/cre/reference/sdk/core-ts.mdx | 142 +++- .../cre/reference/sdk/evm-client-ts.mdx | 28 +- .../cre/reference/sdk/http-client-ts.mdx | 22 +- src/content/cre/reference/sdk/overview-ts.mdx | 31 +- .../sdk/triggers/cron-trigger-ts.mdx | 12 +- .../sdk/triggers/evm-log-trigger-ts.mdx | 12 +- .../sdk/triggers/http-trigger-ts.mdx | 12 +- src/content/cre/release-notes.mdx | 10 +- .../templates/running-demo-workflow-ts.mdx | 6 +- 34 files changed, 846 insertions(+), 596 deletions(-) delete mode 100644 reports/llms-report.json diff --git a/reports/llms-report.json b/reports/llms-report.json deleted file mode 100644 index 35fdfc368f8..00000000000 --- a/reports/llms-report.json +++ /dev/null @@ -1,127 +0,0 @@ -{ - "startedAt": "2026-01-20T11:44:07.555Z", - "siteBase": "https://docs.chain.link", - "sections": [ - { - "section": "cre-go", - "pagesProcessed": 84, - "outputPath": "src/content/cre/llms-full-go.txt", - "bytes": 692263, - "prevBytes": 692263, - "deltaBytes": 0 - }, - { - "section": "cre-ts", - "pagesProcessed": 79, - "outputPath": "src/content/cre/llms-full-ts.txt", - "bytes": 654477, - "prevBytes": 654477, - "deltaBytes": 0 - }, - { - "section": "vrf", - "pagesProcessed": 35, - "outputPath": "src/content/vrf/llms-full.txt", - "bytes": 396719, - "prevBytes": 396719, - "deltaBytes": 0 - }, - { - "section": "ccip", - "pagesProcessed": 260, - "outputPath": "src/content/ccip/llms-full.txt", - "bytes": 3017262, - "prevBytes": 3017262, - "deltaBytes": 0 - }, - { - "section": "data-feeds", - "pagesProcessed": 37, - "outputPath": "src/content/data-feeds/llms-full.txt", - "bytes": 329359, - "prevBytes": 329359, - "deltaBytes": 0 - }, - { - "section": "data-streams", - "pagesProcessed": 60, - "outputPath": "src/content/data-streams/llms-full.txt", - "bytes": 555812, - "prevBytes": 555595, - "deltaBytes": 217 - }, - { - "section": "dta-technical-standard", - "pagesProcessed": 7, - "outputPath": "src/content/dta-technical-standard/llms-full.txt", - "bytes": 32397, - "prevBytes": 32397, - "deltaBytes": 0 - }, - { - "section": "datalink", - "pagesProcessed": 20, - "outputPath": "src/content/datalink/llms-full.txt", - "bytes": 152656, - "prevBytes": 152656, - "deltaBytes": 0 - }, - { - "section": "chainlink-functions", - "pagesProcessed": 27, - "outputPath": "src/content/chainlink-functions/llms-full.txt", - "bytes": 328258, - "prevBytes": 328258, - "deltaBytes": 0 - }, - { - "section": "chainlink-automation", - "pagesProcessed": 25, - "outputPath": "src/content/chainlink-automation/llms-full.txt", - "bytes": 214589, - "prevBytes": 214589, - "deltaBytes": 0 - }, - { - "section": "resources", - "pagesProcessed": 12, - "outputPath": "src/content/resources/llms-full.txt", - "bytes": 342270, - "prevBytes": 342270, - "deltaBytes": 0 - }, - { - "section": "architecture-overview", - "pagesProcessed": 4, - "outputPath": "src/content/architecture-overview/llms-full.txt", - "bytes": 13086, - "prevBytes": 13086, - "deltaBytes": 0 - }, - { - "section": "getting-started", - "pagesProcessed": 1, - "outputPath": "src/content/getting-started/llms-full.txt", - "bytes": 11261, - "prevBytes": 11261, - "deltaBytes": 0 - }, - { - "section": "chainlink-nodes", - "pagesProcessed": 37, - "outputPath": "src/content/chainlink-nodes/llms-full.txt", - "bytes": 673481, - "prevBytes": 673481, - "deltaBytes": 0 - }, - { - "section": "chainlink-local", - "pagesProcessed": 55, - "outputPath": "src/content/chainlink-local/llms-full.txt", - "bytes": 304657, - "prevBytes": 304657, - "deltaBytes": 0 - } - ], - "finishedAt": "2026-01-20T11:44:11.430Z" -} \ No newline at end of file diff --git a/src/content/chainlink-local/llms-full.txt b/src/content/chainlink-local/llms-full.txt index 5d96887c7d9..2a3a13dbf28 100644 --- a/src/content/chainlink-local/llms-full.txt +++ b/src/content/chainlink-local/llms-full.txt @@ -8573,7 +8573,10 @@ does not persist the files that you open from an external source. To save files, /// @notice Constructor initializes the contract with the router address. /// @param _router The address of the router contract. /// @param _link The address of the link contract. - constructor(address _router, address _link) { + constructor( + address _router, + address _link + ) { s_router = IRouterClient(_router); s_linkToken = LinkTokenInterface(_link); } @@ -8603,8 +8606,8 @@ does not persist the files that you open from an external source. To save files, Client.GenericExtraArgsV2({ gasLimit: 200_000, // Gas limit for the callback on the destination chain allowOutOfOrderExecution: true // Allows the message to be executed out of order relative to other messages - // from - // the same sender + // from + // the same sender }) ), // Set the feeToken address, indicating LINK will be used for fees diff --git a/src/content/cre/code-snippets/index-trigger-callback-example.ts b/src/content/cre/code-snippets/index-trigger-callback-example.ts index 2b87bd4d0d6..4d69dd7f999 100644 --- a/src/content/cre/code-snippets/index-trigger-callback-example.ts +++ b/src/content/cre/code-snippets/index-trigger-callback-example.ts @@ -1,4 +1,4 @@ -cre.handler( +handler( cronTrigger.trigger({ schedule: "0 */10 * * * *" }), // trigger fires every 10 minutes onCronTrigger // your callback function ) diff --git a/src/content/cre/concepts/non-determinism-ts.mdx b/src/content/cre/concepts/non-determinism-ts.mdx index f07046e911a..770025aa6fa 100644 --- a/src/content/cre/concepts/non-determinism-ts.mdx +++ b/src/content/cre/concepts/non-determinism-ts.mdx @@ -7,7 +7,7 @@ date: Last Modified metadata: description: "Learn how to avoid non-deterministic behaviors in CRE TypeScript workflows that prevent nodes from reaching consensus." datePublished: "2025-11-04" - lastModified: "2025-11-04" + lastModified: "2026-01-20" --- import { Aside } from "@components" @@ -45,7 +45,7 @@ const obj = { b: 2, a: 1 } // Order may vary across runtimes or serialization for (const key in obj) { - console.log(key) // Could be "b", "a" or "a", "b" + // key could be "b", "a" or "a", "b" — non-deterministic! } ``` @@ -56,7 +56,7 @@ const obj = { b: 2, a: 1 } // Preserves insertion order for (const key of Object.keys(obj)) { - console.log(key, obj[key]) // "b", "a" (insertion order) + // key order: "b", "a" (insertion order) } ``` @@ -67,7 +67,7 @@ const obj = { b: 2, a: 1 } // Guaranteed alphabetical order for (const key of Object.keys(obj).sort()) { - console.log(key, obj[key]) // "a", "b" (alphabetically sorted) + // key order: "a", "b" (alphabetically sorted) } ``` @@ -83,7 +83,7 @@ map.set("b", 2) map.set("a", 1) for (const [key, value] of map) { - console.log(key, value) // Always "b", then "a" + // Order: ["b", 2], then ["a", 1] — guaranteed } ``` @@ -93,7 +93,7 @@ for (const [key, value] of map) { const set = new Set(["b", "a"]) for (const value of set) { - console.log(value) // Always "b", then "a" + // Order: "b", then "a" — guaranteed } ``` @@ -125,11 +125,11 @@ const firstSuccess = await Promise.any([fetchFromAPI1(), fetchFromAPI2()]) **Good: Deterministic order with `.result()`** ```typescript -import { cre, type Runtime, type NodeRuntime, consensusMedianAggregation } from "@chainlink/cre-sdk" +import { HTTPClient, type Runtime, type NodeRuntime, consensusMedianAggregation } from "@chainlink/cre-sdk" // Fetch from API 1, then API 2, in a fixed order const fetchPrice = (nodeRuntime: NodeRuntime): bigint => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() // Try first API const response1 = httpClient diff --git a/src/content/cre/getting-started/part-1-project-setup-ts.mdx b/src/content/cre/getting-started/part-1-project-setup-ts.mdx index f86233e35a4..7c96dc090d4 100644 --- a/src/content/cre/getting-started/part-1-project-setup-ts.mdx +++ b/src/content/cre/getting-started/part-1-project-setup-ts.mdx @@ -7,7 +7,7 @@ pageId: "getting-started-part-1" metadata: description: "Getting started Part 1 (TypeScript): set up your first CRE project, explore the structure, and run a successful workflow simulation." datePublished: "2025-11-04" - lastModified: "2026-01-14" + lastModified: "2026-01-20" --- import { Aside, CopyText, CodeHighlightBlock } from "@components" @@ -160,6 +160,12 @@ Open `onchain-calculator/my-calculator-workflow/main.ts` to see its contents: - **`initWorkflow`**: Creates the workflow by registering handlers (trigger-callback pairs). This is where you define what events your workflow responds to. - **`main`**: The entry point that creates a `Runner`, passes your config type, and runs the workflow. + + ## Step 4: Configure your workflow Now that you've explored the generated files, let's configure your workflow for simulation. You'll need to adjust a few configuration files. diff --git a/src/content/cre/getting-started/snippets/part-1-main.ts b/src/content/cre/getting-started/snippets/part-1-main.ts index 5dfbe491fdc..b8eab23b5f8 100644 --- a/src/content/cre/getting-started/snippets/part-1-main.ts +++ b/src/content/cre/getting-started/snippets/part-1-main.ts @@ -1,4 +1,4 @@ -import { cre, Runner, type Runtime } from "@chainlink/cre-sdk" +import { CronCapability, handler, Runner, type Runtime } from "@chainlink/cre-sdk" type Config = { schedule: string @@ -10,9 +10,9 @@ const onCronTrigger = (runtime: Runtime): string => { } const initWorkflow = (config: Config) => { - const cron = new cre.capabilities.CronCapability() + const cron = new CronCapability() - return [cre.handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] + return [handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] } export async function main() { diff --git a/src/content/cre/getting-started/snippets/part-2-main.ts b/src/content/cre/getting-started/snippets/part-2-main.ts index 308ac63fa0b..b0e68ab7f79 100644 --- a/src/content/cre/getting-started/snippets/part-2-main.ts +++ b/src/content/cre/getting-started/snippets/part-2-main.ts @@ -1,4 +1,12 @@ -import { cre, consensusMedianAggregation, Runner, type NodeRuntime, type Runtime } from "@chainlink/cre-sdk" +import { + CronCapability, + HTTPClient, + handler, + consensusMedianAggregation, + Runner, + type NodeRuntime, + type Runtime, +} from "@chainlink/cre-sdk" type Config = { schedule: string @@ -10,15 +18,15 @@ type MyResult = { } const initWorkflow = (config: Config) => { - const cron = new cre.capabilities.CronCapability() + const cron = new CronCapability() - return [cre.handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] + return [handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] } // fetchMathResult is the function passed to the runInNodeMode helper. // It contains the logic for making the request and parsing the response. const fetchMathResult = (nodeRuntime: NodeRuntime): bigint => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const req = { url: nodeRuntime.config.apiUrl, diff --git a/src/content/cre/getting-started/snippets/part-3-main.ts b/src/content/cre/getting-started/snippets/part-3-main.ts index 97c9631ee97..593db2241ba 100644 --- a/src/content/cre/getting-started/snippets/part-3-main.ts +++ b/src/content/cre/getting-started/snippets/part-3-main.ts @@ -1,5 +1,8 @@ import { - cre, + CronCapability, + HTTPClient, + EVMClient, + handler, consensusMedianAggregation, Runner, type NodeRuntime, @@ -31,14 +34,14 @@ type MyResult = { } const initWorkflow = (config: Config) => { - const cron = new cre.capabilities.CronCapability() + const cron = new CronCapability() - return [cre.handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] + return [handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] } // fetchMathResult is the function passed to the runInNodeMode helper. const fetchMathResult = (nodeRuntime: NodeRuntime): bigint => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const req = { url: nodeRuntime.config.apiUrl, @@ -73,7 +76,7 @@ const onCronTrigger = (runtime: Runtime): MyResult => { throw new Error(`Unknown chain name: ${evmConfig.chainName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) // Encode the function call using the Storage ABI const callData = encodeFunctionData({ diff --git a/src/content/cre/getting-started/snippets/part-4-main.ts b/src/content/cre/getting-started/snippets/part-4-main.ts index 01b93fc59d9..b16f70ff4ec 100644 --- a/src/content/cre/getting-started/snippets/part-4-main.ts +++ b/src/content/cre/getting-started/snippets/part-4-main.ts @@ -1,5 +1,8 @@ import { - cre, + CronCapability, + HTTPClient, + EVMClient, + handler, consensusMedianAggregation, Runner, type NodeRuntime, @@ -37,9 +40,9 @@ type MyResult = { // highlight-end const initWorkflow = (config: Config) => { - const cron = new cre.capabilities.CronCapability() + const cron = new CronCapability() - return [cre.handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] + return [handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] } const onCronTrigger = (runtime: Runtime): MyResult => { @@ -61,7 +64,7 @@ const onCronTrigger = (runtime: Runtime): MyResult => { runtime.log(`Successfully fetched offchain value: ${offchainValue}`) // Step 2: Read onchain data using the EVM client - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) const callData = encodeFunctionData({ abi: Storage, @@ -120,7 +123,7 @@ const onCronTrigger = (runtime: Runtime): MyResult => { // highlight-end const fetchMathResult = (nodeRuntime: NodeRuntime): bigint => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const req = { url: nodeRuntime.config.apiUrl, @@ -146,7 +149,7 @@ function updateCalculatorResult( ): string { runtime.log(`Updating calculator result for consumer: ${evmConfig.calculatorConsumerAddress}`) - const evmClient = new cre.capabilities.EVMClient(chainSelector) + const evmClient = new EVMClient(chainSelector) // Encode the CalculatorResult struct according to the contract's ABI const reportData = encodeAbiParameters( diff --git a/src/content/cre/guides/workflow/secrets/using-secrets-deployed.mdx b/src/content/cre/guides/workflow/secrets/using-secrets-deployed.mdx index d64d82d93c7..7aba4836364 100644 --- a/src/content/cre/guides/workflow/secrets/using-secrets-deployed.mdx +++ b/src/content/cre/guides/workflow/secrets/using-secrets-deployed.mdx @@ -5,7 +5,7 @@ date: Last Modified metadata: description: "Secure your deployed workflows: learn to store and manage secrets in the Vault DON for deployed workflows running on DONs." datePublished: "2025-11-04" - lastModified: "2025-11-04" + lastModified: "2026-01-20" --- import { Aside, CodeHighlightBlockMulti } from "@components" @@ -139,7 +139,7 @@ Your workflow code uses the same API to access secrets, whether running in local ): string => { // Fetch the secret from the Vault DON (uses default "main" namespace) diff --git a/src/content/cre/guides/workflow/snippets/using-secrets-multiple-ts.ts b/src/content/cre/guides/workflow/snippets/using-secrets-multiple-ts.ts index 212560e14d8..62d46195a8f 100644 --- a/src/content/cre/guides/workflow/snippets/using-secrets-multiple-ts.ts +++ b/src/content/cre/guides/workflow/snippets/using-secrets-multiple-ts.ts @@ -1,4 +1,4 @@ -import { cre, Runner, type Runtime } from "@chainlink/cre-sdk" +import { CronCapability, handler, Runner, type Runtime } from "@chainlink/cre-sdk" // Config can be an empty object if you don't need any parameters from config.json type Config = Record @@ -21,9 +21,9 @@ const onCronTrigger = (runtime: Runtime): string => { // initWorkflow is the entry point for the workflow const initWorkflow = () => { - const cron = new cre.capabilities.CronCapability() + const cron = new CronCapability() - return [cre.handler(cron.trigger({ schedule: "0 */10 * * * *" }), onCronTrigger)] + return [handler(cron.trigger({ schedule: "0 */10 * * * *" }), onCronTrigger)] } // main is the entry point for the WASM binary @@ -31,5 +31,3 @@ export async function main() { const runner = await Runner.newRunner() await runner.run(initWorkflow) } - -main() diff --git a/src/content/cre/guides/workflow/snippets/using-secrets-single-ts.ts b/src/content/cre/guides/workflow/snippets/using-secrets-single-ts.ts index b7c81913051..8f32e23c02f 100644 --- a/src/content/cre/guides/workflow/snippets/using-secrets-single-ts.ts +++ b/src/content/cre/guides/workflow/snippets/using-secrets-single-ts.ts @@ -1,4 +1,4 @@ -import { cre, Runner, type Runtime } from "@chainlink/cre-sdk" +import { CronCapability, handler, Runner, type Runtime } from "@chainlink/cre-sdk" // Config can be an empty object if you don't need any parameters from config.json type Config = Record @@ -22,9 +22,9 @@ const onCronTrigger = (runtime: Runtime): string => { // initWorkflow is the entry point for the workflow const initWorkflow = () => { - const cron = new cre.capabilities.CronCapability() + const cron = new CronCapability() - return [cre.handler(cron.trigger({ schedule: "0 */10 * * * *" }), onCronTrigger)] + return [handler(cron.trigger({ schedule: "0 */10 * * * *" }), onCronTrigger)] } // main is the entry point for the WASM binary @@ -32,5 +32,3 @@ export async function main() { const runner = await Runner.newRunner() await runner.run(initWorkflow) } - -main() diff --git a/src/content/cre/guides/workflow/using-evm-client/onchain-read-ts.mdx b/src/content/cre/guides/workflow/using-evm-client/onchain-read-ts.mdx index b9877034b44..a18e0698f64 100644 --- a/src/content/cre/guides/workflow/using-evm-client/onchain-read-ts.mdx +++ b/src/content/cre/guides/workflow/using-evm-client/onchain-read-ts.mdx @@ -7,7 +7,7 @@ date: Last Modified metadata: description: "Read data from smart contracts in TypeScript: learn to call view functions and fetch verified blockchain state in your workflows." datePublished: "2025-11-04" - lastModified: "2025-12-10" + lastModified: "2026-01-20" --- import { Aside } from "@components" @@ -49,7 +49,8 @@ Here's a complete example of reading from a Storage contract: ```typescript import { - cre, + CronCapability, + EVMClient, getNetwork, encodeCallMsg, bytesToHex, @@ -84,7 +85,7 @@ const onCronTrigger = (runtime: Runtime): string => { } // Create EVM client with chain selector - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) // Encode the function call const callData = encodeFunctionData({ @@ -117,9 +118,10 @@ const onCronTrigger = (runtime: Runtime): string => { } const initWorkflow = (config: Config) => { + const cron = new CronCapability() return [ - cre.handler( - new cre.capabilities.CronCapability().trigger({ + cron.handler( + cron.trigger({ schedule: "*/10 * * * * *", // Every 10 seconds }), onCronTrigger @@ -295,7 +297,8 @@ Here's a full runnable workflow with external configuration: ```typescript import { - cre, + CronCapability, + EVMClient, getNetwork, encodeCallMsg, bytesToHex, @@ -326,7 +329,7 @@ const onCronTrigger = (runtime: Runtime): string => { throw new Error(`Network not found: ${runtime.config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) const callData = encodeFunctionData({ abi: storageAbi, @@ -356,9 +359,10 @@ const onCronTrigger = (runtime: Runtime): string => { } const initWorkflow = (config: Config) => { + const cron = new CronCapability() return [ - cre.handler( - new cre.capabilities.CronCapability().trigger({ + cron.handler( + cron.trigger({ schedule: "*/10 * * * * *", }), onCronTrigger diff --git a/src/content/cre/guides/workflow/using-evm-client/onchain-write/writing-data-onchain.mdx b/src/content/cre/guides/workflow/using-evm-client/onchain-write/writing-data-onchain.mdx index e375a796fe3..ee480ef131e 100644 --- a/src/content/cre/guides/workflow/using-evm-client/onchain-write/writing-data-onchain.mdx +++ b/src/content/cre/guides/workflow/using-evm-client/onchain-write/writing-data-onchain.mdx @@ -6,7 +6,7 @@ date: Last Modified metadata: description: "Write workflow results to the blockchain in TypeScript: complete guide to generating and submitting verified data to smart contracts." datePublished: "2025-11-04" - lastModified: "2025-11-04" + lastModified: "2026-01-20" --- import { Aside } from "@components" @@ -69,7 +69,7 @@ This example shows how to write a single `uint256` value to your consumer contra ### Step 1: Set up your imports ```typescript -import { cre, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime } from "@chainlink/cre-sdk" +import { EVMClient, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime } from "@chainlink/cre-sdk" import { encodeAbiParameters, parseAbiParameters } from "viem" ``` @@ -270,7 +270,7 @@ export { CalculatorResultParams, type CalculatorResult } from "./ConsumerContrac Now you can import and use these definitions in your workflow: ```typescript -import { cre, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime } from "@chainlink/cre-sdk" +import { EVMClient, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime } from "@chainlink/cre-sdk" import { encodeAbiParameters } from "viem" import { CalculatorResultParams, type CalculatorResult } from "../contracts/abi" @@ -285,7 +285,7 @@ const writeDataOnchain = (runtime: Runtime): string => { throw new Error(`Network not found`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) // Create type-safe data object const data: CalculatorResult = { @@ -357,7 +357,16 @@ Here's a full workflow that writes a struct to a consumer contract: ### Workflow code (`main.ts`) ```typescript -import { cre, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime, Runner } from "@chainlink/cre-sdk" +import { + CronCapability, + EVMClient, + getNetwork, + hexToBase64, + bytesToHex, + TxStatus, + type Runtime, + Runner, +} from "@chainlink/cre-sdk" import { encodeAbiParameters, parseAbiParameters } from "viem" import { z } from "zod" @@ -384,7 +393,7 @@ const writeDataOnchain = (runtime: Runtime): string => { } // Create EVM client - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) // 1. Encode your data (struct with 3 fields) const reportData = encodeAbiParameters( @@ -428,9 +437,10 @@ const writeDataOnchain = (runtime: Runtime): string => { } const initWorkflow = (config: Config) => { + const cron = new CronCapability() return [ - cre.handler( - new cre.capabilities.CronCapability().trigger({ + cron.handler( + cron.trigger({ schedule: config.schedule, }), writeDataOnchain diff --git a/src/content/cre/guides/workflow/using-http-client/get-request-ts.mdx b/src/content/cre/guides/workflow/using-http-client/get-request-ts.mdx index 48af5940349..84b21457667 100644 --- a/src/content/cre/guides/workflow/using-http-client/get-request-ts.mdx +++ b/src/content/cre/guides/workflow/using-http-client/get-request-ts.mdx @@ -7,7 +7,7 @@ pageId: "guides-workflow-http-get-request" metadata: description: "Fetch data from APIs in TypeScript: learn to make GET requests with consensus validation to bring offchain data into your workflow." datePublished: "2025-11-04" - lastModified: "2025-12-16" + lastModified: "2026-01-20" --- import { Aside } from "@components" @@ -80,7 +80,7 @@ Add the API URL to your `config.json` file. Define TypeScript types for the API response and your internal data model. ```typescript -import { cre, type Runtime, type HTTPSendRequester, Runner } from "@chainlink/cre-sdk" +import { HTTPClient, type Runtime, type HTTPSendRequester, Runner } from "@chainlink/cre-sdk" import { z } from "zod" // Config schema @@ -142,17 +142,19 @@ const fetchAndParse = (sendRequester: HTTPSendRequester, config: Config): PriceD In your `onCronTrigger` handler, call `httpClient.sendRequest()`. This returns a function that you call with `runtime.config`. ```typescript +import { HTTPClient, ConsensusAggregationByFields, median, type Runtime } from "@chainlink/cre-sdk" + const onCronTrigger = (runtime: Runtime): string => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() // sendRequest returns a function that we call with runtime.config const result = httpClient .sendRequest( runtime, fetchAndParse, - new cre.consensus.ConsensusAggregationByFields({ - price: cre.consensus.median(), - lastUpdated: cre.consensus.median(), + ConsensusAggregationByFields({ + price: median(), + lastUpdated: median(), }) )(runtime.config) // Call the returned function with config .result() @@ -168,7 +170,16 @@ const onCronTrigger = (runtime: Runtime): string => { Here's the full workflow code: ```typescript -import { cre, type Runtime, type HTTPSendRequester, Runner } from "@chainlink/cre-sdk" +import { + CronCapability, + HTTPClient, + handler, + ConsensusAggregationByFields, + median, + type Runtime, + type HTTPSendRequester, + Runner, +} from "@chainlink/cre-sdk" import { z } from "zod" // Config schema @@ -216,15 +227,15 @@ const fetchAndParse = (sendRequester: HTTPSendRequester, config: Config): PriceD // Main workflow handler const onCronTrigger = (runtime: Runtime): string => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const result = httpClient .sendRequest( runtime, fetchAndParse, - new cre.consensus.ConsensusAggregationByFields({ - price: cre.consensus.median(), - lastUpdated: cre.consensus.median(), + ConsensusAggregationByFields({ + price: median(), + lastUpdated: median(), }) )(runtime.config) // Call with config .result() @@ -237,8 +248,8 @@ const onCronTrigger = (runtime: Runtime): string => { // Initialize workflow const initWorkflow = (config: Config) => { return [ - cre.handler( - new cre.capabilities.CronCapability().trigger({ + handler( + new CronCapability().trigger({ schedule: config.schedule, }), onCronTrigger @@ -264,7 +275,16 @@ The pattern works like a "map-reduce" for the DON: The example below is functionally identical to the `sendRequest` example above, but implemented using the low-level pattern. ```typescript -import { cre, type Runtime, type NodeRuntime, Runner } from "@chainlink/cre-sdk" +import { + CronCapability, + HTTPClient, + handler, + ConsensusAggregationByFields, + median, + type Runtime, + type NodeRuntime, + Runner, +} from "@chainlink/cre-sdk" import { z } from "zod" // Config and types (same as before) @@ -290,7 +310,7 @@ type ExternalApiResponse = { // fetchPriceData is a function that runs on each individual node const fetchPriceData = (nodeRuntime: NodeRuntime): PriceData => { // 1. Create HTTP client and fetch raw data - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const req = { url: nodeRuntime.config.apiUrl, @@ -318,9 +338,9 @@ const onCronTrigger = (runtime: Runtime): string => { const result = runtime .runInNodeMode( fetchPriceData, - new cre.consensus.ConsensusAggregationByFields({ - price: cre.consensus.median(), - lastUpdated: cre.consensus.median(), + ConsensusAggregationByFields({ + price: median(), + lastUpdated: median(), }) )() .result() @@ -333,8 +353,8 @@ const onCronTrigger = (runtime: Runtime): string => { // Initialize workflow (same as before) const initWorkflow = (config: Config) => { return [ - cre.handler( - new cre.capabilities.CronCapability().trigger({ + handler( + new CronCapability().trigger({ schedule: config.schedule, }), onCronTrigger diff --git a/src/content/cre/guides/workflow/using-http-client/post-request-ts.mdx b/src/content/cre/guides/workflow/using-http-client/post-request-ts.mdx index 04363780b76..82f40a59550 100644 --- a/src/content/cre/guides/workflow/using-http-client/post-request-ts.mdx +++ b/src/content/cre/guides/workflow/using-http-client/post-request-ts.mdx @@ -7,7 +7,7 @@ pageId: "guides-workflow-http-post-request" metadata: description: "Send data to external APIs in TypeScript: learn to make POST requests from your workflow with authentication and custom headers." datePublished: "2025-11-04" - lastModified: "2025-12-16" + lastModified: "2026-01-20" --- import { Aside } from "@components" @@ -107,7 +107,7 @@ In your `main.ts`, define the TypeScript types for your configuration and the da ```typescript import { - cre, + HTTPClient, ok, consensusIdenticalAggregation, type Runtime, @@ -184,8 +184,10 @@ const postData = (sendRequester: HTTPSendRequester, config: Config): PostRespons In your main `onCronTrigger` handler, call `httpClient.sendRequest()`, which returns a function that you call with `runtime.config`. ```typescript +import { HTTPClient, consensusIdenticalAggregation, type Runtime } from "@chainlink/cre-sdk" + const onCronTrigger = (runtime: Runtime): string => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const result = httpClient .sendRequest( @@ -205,10 +207,12 @@ const onCronTrigger = (runtime: Runtime): string => { Finally, add the `initWorkflow` and `main` functions. ```typescript +import { CronCapability, handler, Runner } from "@chainlink/cre-sdk" + const initWorkflow = (config: Config) => { return [ - cre.handler( - new cre.capabilities.CronCapability().trigger({ + handler( + new CronCapability().trigger({ schedule: config.schedule, }), onCronTrigger @@ -228,7 +232,9 @@ export async function main() { ```typescript import { - cre, + CronCapability, + HTTPClient, + handler, ok, consensusIdenticalAggregation, type Runtime, @@ -294,7 +300,7 @@ const postData = (sendRequester: HTTPSendRequester, config: Config): PostRespons } const onCronTrigger = (runtime: Runtime): string => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const result = httpClient .sendRequest( @@ -310,8 +316,8 @@ const onCronTrigger = (runtime: Runtime): string => { const initWorkflow = (config: Config) => { return [ - cre.handler( - new cre.capabilities.CronCapability().trigger({ + handler( + new CronCapability().trigger({ schedule: config.schedule, }), onCronTrigger @@ -365,7 +371,16 @@ For more complex scenarios, you can use the lower-level `runtime.runInNodeMode() Here's how to make a POST request with an API key from secrets: ```typescript -import { cre, ok, consensusIdenticalAggregation, type Runtime, type NodeRuntime, Runner } from "@chainlink/cre-sdk" +import { + CronCapability, + HTTPClient, + handler, + ok, + consensusIdenticalAggregation, + type Runtime, + type NodeRuntime, + Runner, +} from "@chainlink/cre-sdk" import { z } from "zod" // Config and types @@ -393,7 +408,7 @@ const postData = (nodeRuntime: NodeRuntime): PostResponse => { // Use the secret value const apiKey = secret.value - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() // 2. Prepare the data const dataToSend: MyData = { @@ -441,8 +456,8 @@ const onCronTrigger = (runtime: Runtime): string => { const initWorkflow = (config: Config) => { return [ - cre.handler( - new cre.capabilities.CronCapability().trigger({ + handler( + new CronCapability().trigger({ schedule: config.schedule, }), onCronTrigger diff --git a/src/content/cre/guides/workflow/using-http-client/submitting-reports-http-ts.mdx b/src/content/cre/guides/workflow/using-http-client/submitting-reports-http-ts.mdx index 15a944fa962..eeb286668c6 100644 --- a/src/content/cre/guides/workflow/using-http-client/submitting-reports-http-ts.mdx +++ b/src/content/cre/guides/workflow/using-http-client/submitting-reports-http-ts.mdx @@ -7,7 +7,7 @@ pageId: "guides-workflow-http-submit-reports" metadata: description: "Send verified reports to external systems in TypeScript: learn to submit cryptographically signed workflow results via HTTP APIs." datePublished: "2025-11-04" - lastModified: "2025-11-04" + lastModified: "2026-01-20" --- import { Aside } from "@components" @@ -344,7 +344,7 @@ Use the high-level `httpClient.sendRequest()` pattern with `sendRequester.sendRe ```typescript import { - cre, + HTTPClient, consensusIdenticalAggregation, ok, type Runtime, @@ -369,7 +369,7 @@ const submitReportViaHTTP = (sendRequester: HTTPSendRequester, report: Report): // In your trigger callback const onCronTrigger = (runtime: Runtime): MyResult => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() // Assume 'report' was generated earlier in your workflow @@ -396,7 +396,8 @@ This example shows a workflow that: ```typescript import { - cre, + CronCapability, + HTTPClient, Runner, consensusIdenticalAggregation, hexToBase64, @@ -422,9 +423,9 @@ interface SubmitResponse { type MyResult = Record const initWorkflow = (config: Config) => { - const cron = new cre.capabilities.CronCapability() + const cron = new CronCapability() - return [cre.handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] + return [cron.handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] } // Transformation function: defines how the API expects the report @@ -481,7 +482,7 @@ const onCronTrigger = (runtime: Runtime, payload: CronPayload): MyResult runtime.log("Report generated successfully") // Step 2: Submit the report via HTTP - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const submitResult = httpClient .sendRequest( @@ -525,14 +526,21 @@ export async function main() { For complex scenarios where you need more control, use `clientCapability.sendReport()` with `runtime.runInNodeMode()`: ```typescript -import { cre, consensusIdenticalAggregation, ok, type Runtime, type NodeRuntime, type Report } from "@chainlink/cre-sdk" +import { + HTTPClient, + consensusIdenticalAggregation, + ok, + type Runtime, + type NodeRuntime, + type Report, +} from "@chainlink/cre-sdk" const onCronTrigger = (runtime: Runtime): MyResult => { // Assume 'report' was generated earlier const result = runtime .runInNodeMode((nodeRuntime: NodeRuntime) => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const response = httpClient.sendReport(nodeRuntime, report, formatReportSimple).result() diff --git a/src/content/cre/guides/workflow/using-triggers/cron-trigger-ts.mdx b/src/content/cre/guides/workflow/using-triggers/cron-trigger-ts.mdx index d84ba2539ee..64442c3e33b 100644 --- a/src/content/cre/guides/workflow/using-triggers/cron-trigger-ts.mdx +++ b/src/content/cre/guides/workflow/using-triggers/cron-trigger-ts.mdx @@ -7,7 +7,7 @@ date: Last Modified metadata: description: "Schedule workflows with Cron in TypeScript: learn to run your workflow at specific times or intervals using cron expressions." datePublished: "2025-11-04" - lastModified: "2025-11-04" + lastModified: "2026-01-20" --- import { Aside } from "@components" @@ -52,7 +52,7 @@ The timezone-aware scheduler automatically handles daylight saving time transiti ```typescript -import { cre, type Runtime, type CronPayload, Runner } from "@chainlink/cre-sdk" +import { CronCapability, handler, type Runtime, type CronPayload, Runner } from "@chainlink/cre-sdk" type Config = {} @@ -68,17 +68,17 @@ const onCronTrigger = (runtime: Runtime, payload: CronPayload): string = const initWorkflow = (config: Config) => { // Create the trigger - fires every 30 seconds in UTC - const cronTrigger = new cre.capabilities.CronCapability().trigger({ + const cronTrigger = new CronCapability().trigger({ schedule: "*/30 * * * * *", }) // Or use a timezone-aware schedule - fires daily at 9 AM Eastern Time - // const cronTrigger = new cre.capabilities.CronCapability().trigger({ + // const cronTrigger = new CronCapability().trigger({ // schedule: "TZ=America/New_York 0 9 * * *", // }) // Register a handler with the trigger and a callback function - return [cre.handler(cronTrigger, onCronTrigger)] + return [handler(cronTrigger, onCronTrigger)] } export async function main() { diff --git a/src/content/cre/guides/workflow/using-triggers/evm-log-trigger-ts.mdx b/src/content/cre/guides/workflow/using-triggers/evm-log-trigger-ts.mdx index deac6b2e277..3b42720ac48 100644 --- a/src/content/cre/guides/workflow/using-triggers/evm-log-trigger-ts.mdx +++ b/src/content/cre/guides/workflow/using-triggers/evm-log-trigger-ts.mdx @@ -7,7 +7,7 @@ date: Last Modified metadata: description: "React to blockchain events in TypeScript: learn to trigger your workflow when smart contracts emit specific events on EVM chain." datePublished: "2025-11-04" - lastModified: "2025-11-04" + lastModified: "2026-01-20" --- import { Aside } from "@components" @@ -35,7 +35,16 @@ You create an EVM Log trigger by calling the `EVMClient.logTrigger()` method wit The simplest configuration listens for **all events** from specific contract addresses: ```typescript -import { cre, getNetwork, type Runtime, type EVMLog, Runner, bytesToHex, hexToBase64 } from "@chainlink/cre-sdk" +import { + EVMClient, + handler, + getNetwork, + type Runtime, + type EVMLog, + Runner, + bytesToHex, + hexToBase64, +} from "@chainlink/cre-sdk" type Config = { chainSelectorName: string @@ -60,10 +69,10 @@ const initWorkflow = (config: Config) => { throw new Error(`Network not found: ${config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) return [ - cre.handler( + handler( evmClient.logTrigger({ addresses: [hexToBase64(config.contractAddress)], }), @@ -97,13 +106,13 @@ const initWorkflow = (config: Config) => { throw new Error(`Network not found: ${config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) // Compute the event signature hash for Transfer(address,address,uint256) const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) return [ - cre.handler( + handler( evmClient.logTrigger({ addresses: [hexToBase64(config.contractAddress)], topics: [ @@ -157,13 +166,13 @@ const initWorkflow = (config: Config) => { throw new Error(`Network not found: ${config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) const aliceAddress = "0xAlice..." as `0x${string}` return [ - cre.handler( + handler( evmClient.logTrigger({ addresses: [hexToBase64(config.contractAddress)], topics: [ @@ -204,14 +213,14 @@ const initWorkflow = (config: Config) => { throw new Error(`Network not found: ${config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) const aliceAddress = "0xAlice..." as `0x${string}` const bobAddress = "0xBob..." as `0x${string}` return [ - cre.handler( + handler( evmClient.logTrigger({ addresses: [hexToBase64(config.contractAddress)], topics: [ @@ -245,14 +254,14 @@ const initWorkflow = (config: Config) => { throw new Error(`Network not found: ${config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) const aliceAddress = "0xAlice..." as `0x${string}` const charlieAddress = "0xCharlie..." as `0x${string}` return [ - cre.handler( + handler( evmClient.logTrigger({ addresses: [hexToBase64(config.contractAddress)], topics: [ @@ -290,13 +299,13 @@ const initWorkflow = (config: Config) => { throw new Error(`Network not found: ${config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) const approvalEventHash = keccak256(toBytes("Approval(address,address,uint256)")) return [ - cre.handler( + handler( evmClient.logTrigger({ addresses: [hexToBase64(config.contractAddress)], topics: [ @@ -328,12 +337,12 @@ const initWorkflow = (config: Config) => { throw new Error(`Network not found: ${config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) return [ - cre.handler( + handler( evmClient.logTrigger({ addresses: [hexToBase64("0xTokenA..."), hexToBase64("0xTokenB..."), hexToBase64("0xTokenC...")], topics: [ @@ -365,7 +374,7 @@ const initWorkflow = (config: Config) => { throw new Error(`Network not found: ${config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) // Example: event ValueChanged(address indexed user, uint256 indexed newValue) const eventHash = keccak256(toBytes("ValueChanged(address,uint256)")) @@ -373,7 +382,7 @@ const initWorkflow = (config: Config) => { const targetValue = padHex(numberToHex(12345), { size: 32 }) return [ - cre.handler( + handler( evmClient.logTrigger({ addresses: [hexToBase64(config.contractAddress)], topics: [ @@ -553,7 +562,16 @@ const onLogTrigger = (runtime: Runtime, log: EVMLog): string => { Here's a complete example that listens for ERC20 `Transfer` events and decodes them: ```typescript -import { cre, getNetwork, type Runtime, type EVMLog, Runner, bytesToHex, hexToBase64 } from "@chainlink/cre-sdk" +import { + EVMClient, + handler, + getNetwork, + type Runtime, + type EVMLog, + Runner, + bytesToHex, + hexToBase64, +} from "@chainlink/cre-sdk" import { keccak256, toBytes, decodeEventLog, parseAbi } from "viem" type Config = { @@ -590,11 +608,11 @@ const initWorkflow = (config: Config) => { throw new Error(`Network not found: ${config.chainSelectorName}`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) const transferEventHash = keccak256(toBytes("Transfer(address,address,uint256)")) return [ - cre.handler( + handler( evmClient.logTrigger({ addresses: [hexToBase64(config.tokenAddress)], topics: [{ values: [hexToBase64(transferEventHash)] }], diff --git a/src/content/cre/guides/workflow/using-triggers/http-trigger/code-snippets/simulation-example.ts b/src/content/cre/guides/workflow/using-triggers/http-trigger/code-snippets/simulation-example.ts index a84b971f1d6..8e670de963e 100644 --- a/src/content/cre/guides/workflow/using-triggers/http-trigger/code-snippets/simulation-example.ts +++ b/src/content/cre/guides/workflow/using-triggers/http-trigger/code-snippets/simulation-example.ts @@ -1,4 +1,4 @@ -import { cre, type Runtime, type HTTPPayload, Runner, decodeJson } from "@chainlink/cre-sdk" +import { HTTPCapability, handler, type Runtime, type HTTPPayload, Runner, decodeJson } from "@chainlink/cre-sdk" type Config = { minimumAmount: number @@ -31,10 +31,10 @@ const onHttpTrigger = (runtime: Runtime, payload: HTTPPayload): string = } const initWorkflow = (config: Config) => { - const http = new cre.capabilities.HTTPCapability() + const http = new HTTPCapability() return [ - cre.handler(http.trigger({}), onHttpTrigger), // Empty config OK for simulation + handler(http.trigger({}), onHttpTrigger), // Empty config OK for simulation ] } @@ -42,5 +42,3 @@ export async function main() { const runner = await Runner.newRunner() await runner.run(initWorkflow) } - -main() diff --git a/src/content/cre/guides/workflow/using-triggers/http-trigger/configuration-ts.mdx b/src/content/cre/guides/workflow/using-triggers/http-trigger/configuration-ts.mdx index a48b3d43ad0..2fcec552bb7 100644 --- a/src/content/cre/guides/workflow/using-triggers/http-trigger/configuration-ts.mdx +++ b/src/content/cre/guides/workflow/using-triggers/http-trigger/configuration-ts.mdx @@ -7,7 +7,7 @@ date: Last Modified metadata: description: "Configure HTTP triggers in TypeScript: learn to set up authorization, write handler functions, and process HTTP request payloads." datePublished: "2025-11-04" - lastModified: "2025-11-10" + lastModified: "2026-01-20" --- import { Aside } from "@components" @@ -30,7 +30,7 @@ You create an HTTP trigger by calling the `HTTPCapability.trigger()` method. Its ```typescript -import { cre, type Runtime, type HTTPPayload, Runner } from "@chainlink/cre-sdk" +import { HTTPCapability, handler, type Runtime, type HTTPPayload, Runner } from "@chainlink/cre-sdk" type Config = { authorizedEVMAddress: string @@ -44,10 +44,10 @@ const onHttpTrigger = (runtime: Runtime, payload: HTTPPayload): string = } const initWorkflow = (config: Config) => { - const httpTrigger = new cre.capabilities.HTTPCapability() + const httpTrigger = new HTTPCapability() return [ - cre.handler( + handler( httpTrigger.trigger({ authorizedKeys: [ { diff --git a/src/content/cre/index.mdx b/src/content/cre/index.mdx index 0dd323aa09b..69165c62c54 100644 --- a/src/content/cre/index.mdx +++ b/src/content/cre/index.mdx @@ -5,7 +5,7 @@ isIndex: true metadata: description: "Discover Chainlink Runtime Environment (CRE): the all-in-one orchestration layer that provides a secure, verifiable environment for your institutional-grade smart contracts." datePublished: "2025-11-04" - lastModified: "2025-11-04" + lastModified: "2026-01-20" --- import { Aside, CodeHighlightBlockMulti } from "@components" @@ -61,7 +61,7 @@ Workflows use a **trigger-and-callback model** to provide a code-first developer 1. **A Trigger**: An event source that starts a workflow execution (e.g., `cron.Trigger`). This is the "when" of your workflow. 1. **A Callback**: A function that contains your business logic. It is inside this function that you will use the SDK's clients to invoke capabilities. This is the "what" of your workflow. -1. **The `cre.handler()`**: The glue that connects a single trigger to a single callback. +1. **The `handler()`**: The glue that connects a single trigger to a single callback. You can define multiple trigger and callback combinations in your workflow. You can also attach the same callback to multiple triggers for reusability. @@ -113,7 +113,7 @@ Learn more about [Consensus Computing in CRE](/cre/concepts/consensus-computing) | Concept | One-liner | | ------------------ | ----------------------------------------------------------------- | | **Workflow** | Compiled WebAssembly (WASM) binary. | -| **Handler** | `cre.handler(trigger, callback)` pair; the atom of execution. | +| **Handler** | `handler(trigger, callback)` pair; the atom of execution. | | **Trigger** | Event that starts an execution (cron, HTTP, EVM log, …). | | **Callback** | Function that runs when its trigger fires; contains your logic. | | **Runtime** | Object passed to a callback; used to invoke capabilities. | diff --git a/src/content/cre/llms-full-go.txt b/src/content/cre/llms-full-go.txt index 3b8ed1b34bb..ad881fc28f0 100644 --- a/src/content/cre/llms-full-go.txt +++ b/src/content/cre/llms-full-go.txt @@ -1,6 +1,6 @@ # Chainlink Runtime Environment (CRE) Source: https://docs.chain.link/cre -Last Updated: 2025-11-04 +Last Updated: 2026-01-20 ## What is CRE? @@ -51,7 +51,7 @@ Workflows use a **trigger-and-callback model** to provide a code-first developer 1. **A Trigger**: An event source that starts a workflow execution (e.g., `cron.Trigger`). This is the "when" of your workflow. 2. **A Callback**: A function that contains your business logic. It is inside this function that you will use the SDK's clients to invoke capabilities. This is the "what" of your workflow. -3. **The `cre.handler()`**: The glue that connects a single trigger to a single callback. +3. **The `handler()`**: The glue that connects a single trigger to a single callback. You can define multiple trigger and callback combinations in your workflow. You can also attach the same callback to multiple triggers for reusability. @@ -102,7 +102,7 @@ Learn more about [Consensus Computing in CRE](/cre/concepts/consensus-computing) | Concept | One-liner | | ------------------ | ----------------------------------------------------------------- | | **Workflow** | Compiled WebAssembly (WASM) binary. | -| **Handler** | `cre.handler(trigger, callback)` pair; the atom of execution. | +| **Handler** | `handler(trigger, callback)` pair; the atom of execution. | | **Trigger** | Event that starts an execution (cron, HTTP, EVM log, …). | | **Callback** | Function that runs when its trigger fires; contains your logic. | | **Runtime** | Object passed to a callback; used to invoke capabilities. | @@ -442,7 +442,7 @@ To help us assist you faster, please include: # Release Notes Source: https://docs.chain.link/cre/release-notes -Last Updated: 2026-01-16 +Last Updated: 2026-01-20 This page provides detailed release notes for CRE. It includes information on new features, significant changes, and known limitations. @@ -450,7 +450,7 @@ This page provides detailed release notes for CRE. It includes information on ne - **Bug Fixes**: Fixed issue where workflows could execute twice during simulation -- **Examples Updated**: All workflow examples in the SDK repository now use **direct imports** (e.g., `import { HTTPClient } from "@chainlink/cre-sdk"`) instead of the namespace pattern (e.g., `cre.capabilities.HTTPClient`). Both patterns remain fully supported—choose whichever fits your coding style. +- **Examples Updated**: All workflow examples in the SDK repository now use **direct imports** (e.g., `import { HTTPClient } from "@chainlink/cre-sdk"`) instead of the namespace pattern (e.g., `cre.capabilities.HTTPClient`). Both patterns remain fully supported—choose whichever fits your coding style. See [Import styles](/cre/reference/sdk/core-ts#import-styles) for details. [See all changes on GitHub](https://github.com/smartcontractkit/cre-sdk-typescript/compare/v1.0.2...v1.0.3) @@ -460,13 +460,13 @@ This page provides detailed release notes for CRE. It includes information on ne **New features:** -- **Optional `main()` call**: You no longer need to call `main()` at the end of your workflow files. The SDK now automatically executes the `main()` function during compilation. +- **Optional `main()` call**: You no longer need to call `main()` at the end of your workflow files. The SDK now automatically executes the `main()` function during compilation. See [`main()` reference](/cre/reference/sdk/core-ts#main) for details. - **Automatic error handling**: If you don't provide custom error handling, the SDK automatically adds `.catch(sendErrorResponse)` to your workflow's `main()` function. This ensures errors are properly reported instead of silently failing. -- **Direct imports**: You can now import SDK components directly (e.g., `import { HTTPClient } from "@chainlink/cre-sdk"`) instead of accessing them through the `cre` namespace (e.g., `cre.capabilities.HTTPClient`). Both import styles remain supported for backward compatibility. +- **Direct imports**: You can now import SDK components directly (e.g., `import { HTTPClient } from "@chainlink/cre-sdk"`) instead of accessing them through the `cre` namespace (e.g., `cre.capabilities.HTTPClient`). Both import styles remain supported for backward compatibility. See [Import styles](/cre/reference/sdk/core-ts#import-styles) for details and guidance on when to use each pattern. **Migration notes:** -- **Custom error handling**: If you need custom error handling, you can still add your own `.catch()` handler: `main().catch(myCustomHandler)`. The SDK will respect your custom handler and not override it. +- **Custom error handling**: If you need custom error handling, you can still add your own `.catch()` handler: `main().catch(myCustomHandler)`. The SDK will respect your custom handler and not override it. See [`main()` reference](/cre/reference/sdk/core-ts#main) for examples. [See all changes on GitHub](https://github.com/smartcontractkit/cre-sdk-typescript/compare/v1.0.1...v1.0.2) @@ -2451,7 +2451,10 @@ interface IReceiver is IERC165 { /// limit. The receiver is responsible for discarding stale reports. /// @param metadata Report's metadata. /// @param report Workflow report. - function onReport(bytes calldata metadata, bytes calldata report) external; + function onReport( + bytes calldata metadata, + bytes calldata report + ) external; } ``` @@ -2560,7 +2563,10 @@ abstract contract ReceiverTemplate is IReceiver, Ownable { /// @inheritdoc IReceiver /// @dev Performs optional validation checks based on which permission fields are set - function onReport(bytes calldata metadata, bytes calldata report) external override { + function onReport( + bytes calldata metadata, + bytes calldata report + ) external override { // Security Check 1: Verify caller is the trusted Chainlink Forwarder (if configured) if (s_forwarderAddress != address(0) && msg.sender != s_forwarderAddress) { revert InvalidSender(msg.sender, s_forwarderAddress); @@ -2731,12 +2737,10 @@ The simplest way to use `ReceiverTemplate` is to inherit from it and implement t ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.26; - import {ReceiverTemplate} from "./ReceiverTemplate.sol"; contract MyConsumer is ReceiverTemplate { uint256 public s_storedValue; - event ValueUpdated(uint256 newValue); // Constructor requires forwarder address @@ -4558,7 +4562,7 @@ For detailed CLI command documentation, see: # Using Secrets with Deployed Workflows Source: https://docs.chain.link/cre/guides/workflow/secrets/using-secrets-deployed -Last Updated: 2025-11-04 +Last Updated: 2026-01-20 When your workflow is deployed, it cannot access your local `.env` file or environment variables. Instead, secrets must be stored in the **Vault DON**—a decentralized, secure secret storage system that your deployed workflows can access at runtime. diff --git a/src/content/cre/llms-full-ts.txt b/src/content/cre/llms-full-ts.txt index cb9124312f9..36ea67bdec0 100644 --- a/src/content/cre/llms-full-ts.txt +++ b/src/content/cre/llms-full-ts.txt @@ -1,6 +1,6 @@ # Chainlink Runtime Environment (CRE) Source: https://docs.chain.link/cre -Last Updated: 2025-11-04 +Last Updated: 2026-01-20 ## What is CRE? @@ -51,14 +51,14 @@ Workflows use a **trigger-and-callback model** to provide a code-first developer 1. **A Trigger**: An event source that starts a workflow execution (e.g., `cron.Trigger`). This is the "when" of your workflow. 2. **A Callback**: A function that contains your business logic. It is inside this function that you will use the SDK's clients to invoke capabilities. This is the "what" of your workflow. -3. **The `cre.handler()`**: The glue that connects a single trigger to a single callback. +3. **The `handler()`**: The glue that connects a single trigger to a single callback. You can define multiple trigger and callback combinations in your workflow. You can also attach the same callback to multiple triggers for reusability. Here's what the trigger-and-callback pattern looks like: ```ts -cre.handler( +handler( cronTrigger.trigger({ schedule: "0 */10 * * * *" }), // trigger fires every 10 minutes onCronTrigger // your callback function ) @@ -102,7 +102,7 @@ Learn more about [Consensus Computing in CRE](/cre/concepts/consensus-computing) | Concept | One-liner | | ------------------ | ----------------------------------------------------------------- | | **Workflow** | Compiled WebAssembly (WASM) binary. | -| **Handler** | `cre.handler(trigger, callback)` pair; the atom of execution. | +| **Handler** | `handler(trigger, callback)` pair; the atom of execution. | | **Trigger** | Event that starts an execution (cron, HTTP, EVM log, …). | | **Callback** | Function that runs when its trigger fires; contains your logic. | | **Runtime** | Object passed to a callback; used to invoke capabilities. | @@ -442,7 +442,7 @@ To help us assist you faster, please include: # Release Notes Source: https://docs.chain.link/cre/release-notes -Last Updated: 2026-01-16 +Last Updated: 2026-01-20 This page provides detailed release notes for CRE. It includes information on new features, significant changes, and known limitations. @@ -450,7 +450,7 @@ This page provides detailed release notes for CRE. It includes information on ne - **Bug Fixes**: Fixed issue where workflows could execute twice during simulation -- **Examples Updated**: All workflow examples in the SDK repository now use **direct imports** (e.g., `import { HTTPClient } from "@chainlink/cre-sdk"`) instead of the namespace pattern (e.g., `cre.capabilities.HTTPClient`). Both patterns remain fully supported—choose whichever fits your coding style. +- **Examples Updated**: All workflow examples in the SDK repository now use **direct imports** (e.g., `import { HTTPClient } from "@chainlink/cre-sdk"`) instead of the namespace pattern (e.g., `cre.capabilities.HTTPClient`). Both patterns remain fully supported—choose whichever fits your coding style. See [Import styles](/cre/reference/sdk/core-ts#import-styles) for details. [See all changes on GitHub](https://github.com/smartcontractkit/cre-sdk-typescript/compare/v1.0.2...v1.0.3) @@ -460,13 +460,13 @@ This page provides detailed release notes for CRE. It includes information on ne **New features:** -- **Optional `main()` call**: You no longer need to call `main()` at the end of your workflow files. The SDK now automatically executes the `main()` function during compilation. +- **Optional `main()` call**: You no longer need to call `main()` at the end of your workflow files. The SDK now automatically executes the `main()` function during compilation. See [`main()` reference](/cre/reference/sdk/core-ts#main) for details. - **Automatic error handling**: If you don't provide custom error handling, the SDK automatically adds `.catch(sendErrorResponse)` to your workflow's `main()` function. This ensures errors are properly reported instead of silently failing. -- **Direct imports**: You can now import SDK components directly (e.g., `import { HTTPClient } from "@chainlink/cre-sdk"`) instead of accessing them through the `cre` namespace (e.g., `cre.capabilities.HTTPClient`). Both import styles remain supported for backward compatibility. +- **Direct imports**: You can now import SDK components directly (e.g., `import { HTTPClient } from "@chainlink/cre-sdk"`) instead of accessing them through the `cre` namespace (e.g., `cre.capabilities.HTTPClient`). Both import styles remain supported for backward compatibility. See [Import styles](/cre/reference/sdk/core-ts#import-styles) for details and guidance on when to use each pattern. **Migration notes:** -- **Custom error handling**: If you need custom error handling, you can still add your own `.catch()` handler: `main().catch(myCustomHandler)`. The SDK will respect your custom handler and not override it. +- **Custom error handling**: If you need custom error handling, you can still add your own `.catch()` handler: `main().catch(myCustomHandler)`. The SDK will respect your custom handler and not override it. See [`main()` reference](/cre/reference/sdk/core-ts#main) for examples. [See all changes on GitHub](https://github.com/smartcontractkit/cre-sdk-typescript/compare/v1.0.1...v1.0.2) @@ -1186,7 +1186,7 @@ This configuration sets the minimum purchase amount to 10, which we'll test with **Workflow code:** ```ts -import { cre, type Runtime, type HTTPPayload, Runner, decodeJson } from "@chainlink/cre-sdk" +import { HTTPCapability, handler, type Runtime, type HTTPPayload, Runner, decodeJson } from "@chainlink/cre-sdk" type Config = { minimumAmount: number @@ -1219,10 +1219,10 @@ const onHttpTrigger = (runtime: Runtime, payload: HTTPPayload): string = } const initWorkflow = (config: Config) => { - const http = new cre.capabilities.HTTPCapability() + const http = new HTTPCapability() return [ - cre.handler(http.trigger({}), onHttpTrigger), // Empty config OK for simulation + handler(http.trigger({}), onHttpTrigger), // Empty config OK for simulation ] } @@ -1230,8 +1230,6 @@ export async function main() { const runner = await Runner.newRunner() await runner.run(initWorkflow) } - -main() ``` **Run the simulation:** @@ -2040,7 +2038,10 @@ interface IReceiver is IERC165 { /// limit. The receiver is responsible for discarding stale reports. /// @param metadata Report's metadata. /// @param report Workflow report. - function onReport(bytes calldata metadata, bytes calldata report) external; + function onReport( + bytes calldata metadata, + bytes calldata report + ) external; } ``` @@ -2149,7 +2150,10 @@ abstract contract ReceiverTemplate is IReceiver, Ownable { /// @inheritdoc IReceiver /// @dev Performs optional validation checks based on which permission fields are set - function onReport(bytes calldata metadata, bytes calldata report) external override { + function onReport( + bytes calldata metadata, + bytes calldata report + ) external override { // Security Check 1: Verify caller is the trusted Chainlink Forwarder (if configured) if (s_forwarderAddress != address(0) && msg.sender != s_forwarderAddress) { revert InvalidSender(msg.sender, s_forwarderAddress); @@ -2320,12 +2324,10 @@ The simplest way to use `ReceiverTemplate` is to inherit from it and implement t ```sol // SPDX-License-Identifier: MIT pragma solidity ^0.8.26; - import {ReceiverTemplate} from "./ReceiverTemplate.sol"; contract MyConsumer is ReceiverTemplate { uint256 public s_storedValue; - event ValueUpdated(uint256 newValue); // Constructor requires forwarder address @@ -2837,7 +2839,7 @@ The forwarder address provides baseline security, but you can add additional val # Writing Data Onchain Source: https://docs.chain.link/cre/guides/workflow/using-evm-client/onchain-write/writing-data-onchain -Last Updated: 2025-11-04 +Last Updated: 2026-01-20 This guide shows you how to write data from your CRE workflow to a smart contract on the blockchain using the TypeScript SDK. You'll learn the complete two-step process with examples for both single values and structs. @@ -2897,7 +2899,7 @@ This example shows how to write a single `uint256` value to your consumer contra ### Step 1: Set up your imports ```typescript -import { cre, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime } from "@chainlink/cre-sdk" +import { EVMClient, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime } from "@chainlink/cre-sdk" import { encodeAbiParameters, parseAbiParameters } from "viem" ``` @@ -3098,7 +3100,7 @@ export { CalculatorResultParams, type CalculatorResult } from "./ConsumerContrac Now you can import and use these definitions in your workflow: ```typescript -import { cre, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime } from "@chainlink/cre-sdk" +import { EVMClient, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime } from "@chainlink/cre-sdk" import { encodeAbiParameters } from "viem" import { CalculatorResultParams, type CalculatorResult } from "../contracts/abi" @@ -3113,7 +3115,7 @@ const writeDataOnchain = (runtime: Runtime): string => { throw new Error(`Network not found`) } - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) // Create type-safe data object const data: CalculatorResult = { @@ -3185,7 +3187,7 @@ Here's a full workflow that writes a struct to a consumer contract: ### Workflow code (`main.ts`) ```typescript -import { cre, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime, Runner } from "@chainlink/cre-sdk" +import { CronCapability, EVMClient, getNetwork, hexToBase64, bytesToHex, TxStatus, type Runtime, Runner } from "@chainlink/cre-sdk" import { encodeAbiParameters, parseAbiParameters } from "viem" import { z } from "zod" @@ -3212,7 +3214,7 @@ const writeDataOnchain = (runtime: Runtime): string => { } // Create EVM client - const evmClient = new cre.capabilities.EVMClient(network.chainSelector.selector) + const evmClient = new EVMClient(network.chainSelector.selector) // 1. Encode your data (struct with 3 fields) const reportData = encodeAbiParameters( @@ -3256,9 +3258,10 @@ const writeDataOnchain = (runtime: Runtime): string => { } const initWorkflow = (config: Config) => { + const cron = new CronCapability() return [ - cre.handler( - new cre.capabilities.CronCapability().trigger({ + cron.handler( + cron.trigger({ schedule: config.schedule, }), writeDataOnchain @@ -3473,7 +3476,7 @@ For detailed CLI command documentation, see: # Using Secrets with Deployed Workflows Source: https://docs.chain.link/cre/guides/workflow/secrets/using-secrets-deployed -Last Updated: 2025-11-04 +Last Updated: 2026-01-20 When your workflow is deployed, it cannot access your local `.env` file or environment variables. Instead, secrets must be stored in the **Vault DON**—a decentralized, secure secret storage system that your deployed workflows can access at runtime. @@ -7351,7 +7354,7 @@ By default, triggers use `SAFE` if no confidence level is specified. For details # Avoiding Non-Determinism in Workflows Source: https://docs.chain.link/cre/concepts/non-determinism-ts -Last Updated: 2025-11-04 +Last Updated: 2026-01-20 ```typescript -import { cre, type Runtime, type HTTPPayload, Runner } from "@chainlink/cre-sdk" +import { HTTPCapability, handler, type Runtime, type HTTPPayload, Runner } from "@chainlink/cre-sdk" type Config = { authorizedEVMAddress: string @@ -11924,10 +11981,10 @@ const onHttpTrigger = (runtime: Runtime, payload: HTTPPayload): string = } const initWorkflow = (config: Config) => { - const httpTrigger = new cre.capabilities.HTTPCapability() + const httpTrigger = new HTTPCapability() return [ - cre.handler( + handler( httpTrigger.trigger({ authorizedKeys: [ { @@ -12398,7 +12455,7 @@ When you run a CLI command with a target, e.g., `--target staging-settings`: # SDK Reference: Consensus & Aggregation Source: https://docs.chain.link/cre/reference/sdk/consensus-ts -Last Updated: 2025-11-04 +Last Updated: 2026-01-20 Aggregation is the process of taking many results from individual nodes and reducing them to a single, reliable value. This aggregated value is what the DON reaches consensus on. When you run code on individual nodes using [`runtime.runInNodeMode()`](/cre/reference/sdk/core-ts/#runtimeruninnodemode), you must provide an aggregation strategy to tell the DON how to produce this single, trustworthy outcome. This is achieved using a `ConsensusAggregation`. @@ -12543,6 +12600,7 @@ Creates a consensus aggregation strategy by specifying how to aggregate each fie ```typescript import { + HTTPClient, ConsensusAggregationByFields, median, identical, @@ -12568,7 +12626,7 @@ const fetchReserveData = (sendRequester: HTTPSendRequester, config: Config): Res } const onTrigger = (runtime: Runtime): string => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const reserveInfo = httpClient .sendRequest( @@ -12599,7 +12657,9 @@ Here's a complete example demonstrating both simple and field-based aggregation: ```typescript import { - cre, + CronCapability, + HTTPClient, + handler, Runner, consensusMedianAggregation, ConsensusAggregationByFields, @@ -12623,7 +12683,7 @@ type PriceData = { // Simple aggregation example const fetchSimplePrice = (nodeRuntime: NodeRuntime): bigint => { - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const response = httpClient.sendRequest(nodeRuntime, { url: nodeRuntime.config.apiUrl }).result() const data = JSON.parse(response.body.toString()) return BigInt(data.price) @@ -12648,7 +12708,7 @@ const onCronTrigger = (runtime: Runtime, payload: CronPayload): string = runtime.log(`Simple median price: ${simplePrice}`) // Example 2: Field-based aggregation - const httpClient = new cre.capabilities.HTTPClient() + const httpClient = new HTTPClient() const priceData = httpClient .sendRequest( runtime, @@ -12667,9 +12727,9 @@ const onCronTrigger = (runtime: Runtime, payload: CronPayload): string = } const initWorkflow = (config: Config) => { - const cron = new cre.capabilities.CronCapability() + const cron = new CronCapability() - return [cre.handler(cron.trigger({ schedule: "0 */5 * * * *" }), onCronTrigger)] + return [handler(cron.trigger({ schedule: "0 */5 * * * *" }), onCronTrigger)] } export async function main() { @@ -12692,18 +12752,22 @@ If all nodes fail or consensus cannot be reached, the default value (`0n` in thi # SDK Reference: Core Source: https://docs.chain.link/cre/reference/sdk/core-ts -Last Updated: 2025-11-04 +Last Updated: 2026-01-20 This page provides a reference for the core data structures and functions of the CRE TypeScript SDK. These are the fundamental building blocks that every workflow uses, regardless of trigger types or capabilities. ## Import styles -The CRE TypeScript SDK supports two import styles. Both are fully supported and can be used interchangeably: +The CRE TypeScript SDK supports two equivalent import styles. **Both are fully supported**, produce identical behavior, and can be used interchangeably in your workflows. -**Direct imports (recommended for SDK v1.0.2+):** + + +**Direct imports (recommended for new projects):** ```typescript -import { Runner, HTTPClient, EVMClient, CronCapability } from "@chainlink/cre-sdk" +import { Runner, HTTPClient, EVMClient, CronCapability, handler } from "@chainlink/cre-sdk" // Use directly const httpClient = new HTTPClient() @@ -12720,22 +12784,27 @@ const httpClient = new cre.capabilities.HTTPClient() const evmClient = new cre.capabilities.EVMClient(chainSelector) ``` -Both styles are supported for backward compatibility. Choose the style that works best for your codebase. +**When to use each style:** + +| Style | Best for | +| --------------------- | ---------------------------------------------------------------------------- | +| **Direct imports** | New projects, cleaner import statements, better tree-shaking | +| **Namespace imports** | Existing codebases already using this pattern, preference for grouped access | ## Key concepts and components -### `cre.handler()` +### `handler()` -The `cre.handler()` function is the cornerstone of every workflow. It registers a handler that links a specific trigger to a callback function containing your workflow logic. It is typically called within your [`initWorkflow`](#initworkflow) function. +The `handler()` function is the cornerstone of every workflow. It registers a handler that links a specific trigger to a callback function containing your workflow logic. It is typically called within your [`initWorkflow`](#initworkflow) function. **Usage:** ```typescript -import { cre, type Runtime } from "@chainlink/cre-sdk" +import { handler, type Runtime } from "@chainlink/cre-sdk" const initWorkflow = (config: Config) => { return [ - cre.handler( + handler( // 1. A configured trigger, e.g., cron.trigger(...) // This determines WHEN the workflow runs triggerInstance, @@ -12772,7 +12841,7 @@ Both `Runtime` and `NodeRuntime` provide: - **`config`**: Access to your workflow's configuration - **`now()`**: Returns the current `Date` object -- **`log(message: string)`**: Logs a message (accepts a single string argument) +- **`log(message: string)`**: Logs a message (see [Logging](#logging) below) - **`callCapability(...)`**: Internal method for calling capabilities (used by generated code) `Runtime` additionally provides: @@ -12781,6 +12850,35 @@ Both `Runtime` and `NodeRuntime` provide: - **`getSecret(...)`**: Access to workflow secrets - **`report(...)`**: Generate cryptographically signed reports +### Logging + +Use `runtime.log()` to output messages from your workflow. This is the **only way** to produce visible logs—`console.log` does not work in the WASM environment. + +```typescript +const onCronTrigger = (runtime: Runtime): string => { + runtime.log("Workflow started") + + const result = someOperation() + runtime.log(`Operation result: ${result}`) + + return "done" +} +``` + +**Where logs appear:** + +| Environment | Location | +| --------------------- | ------------------------------------------------------------------------------------ | +| **Simulation** | Terminal output with `[USER LOG]` prefix | +| **Deployed workflow** | CRE UI → Workflows → select workflow → Execution tab → click an execution → Logs tab | + +See [Monitoring & Debugging Workflows](/cre/guides/operations/monitoring-workflows#logs-tab) for details on viewing logs for deployed workflows. + +**Important notes:** + +- `runtime.log()` accepts a **single string argument**—use template literals to include variables +- Logs are only available inside callback functions where you have access to the `runtime` object + ### Understanding the `.result()` Pattern All SDK capabilities in the TypeScript SDK use a two-step pattern for asynchronous operations: @@ -12800,11 +12898,11 @@ const response = request.result() **Common usage:** These steps are often chained together for simplicity: ```typescript -import { cre, encodeCallMsg, LAST_FINALIZED_BLOCK_NUMBER, type Runtime } from "@chainlink/cre-sdk" +import { EVMClient, encodeCallMsg, LAST_FINALIZED_BLOCK_NUMBER, type Runtime } from "@chainlink/cre-sdk" import { zeroAddress } from "viem" const onCronTrigger = (runtime: Runtime): string => { - const evmClient = new cre.capabilities.EVMClient(chainSelector) + const evmClient = new EVMClient(chainSelector) // Inline pattern: initiate and get result in one expression const contractCall = evmClient @@ -12898,13 +12996,67 @@ export async function main() { ``` + +**All of these patterns are valid:** + +- **Pattern 1: Let the SDK handle everything (recommended)** + + ```typescript + export async function main() { + const runner = await Runner.newRunner() + await runner.run(initWorkflow) + } + // No need to call main() - the SDK automatically appends: + // main().catch(sendErrorResponse) + ``` + +- **Pattern 2: Explicit call without `.catch()` - SDK adds error handling** + + ```typescript + export async function main() { + const runner = await Runner.newRunner() + await runner.run(initWorkflow) + } + + main() // SDK transforms this to: main().catch(sendErrorResponse) + ``` + +- **Pattern 3: Custom error handling - SDK respects your handler** + + ```typescript + import { sendErrorResponse } from "@chainlink/cre-sdk" + + export async function main() { + const runner = await Runner.newRunner() + await runner.run(initWorkflow) + } + + // If you provide .catch(), the SDK leaves it untouched + main().catch((error) => { + // Your custom error handling logic + // You should call sendErrorResponse to report the error + sendErrorResponse(error) + }) + ``` + + + + +`sendErrorResponse` reports the error to CRE and marks the execution as failed. + +- In **simulation**, the error appears in your terminal output. +- For **deployed workflows**, you'll see it in the [Execution tab](/cre/guides/operations/monitoring-workflows#execution-history) with a `Failure` status and the error message in the Logs tab. + **Key points:** - Must be an `async` function @@ -12918,7 +13070,7 @@ This is the second required entry point. The CRE runner calls this function to i **Required Signature:** ```typescript -import { cre, type Runtime } from "@chainlink/cre-sdk" +import { handler, type Runtime } from "@chainlink/cre-sdk" function initWorkflow(config: Config): Array> ``` @@ -12929,7 +13081,7 @@ function initWorkflow(config: Config): Array **Returns:** -- An array of handlers created with `cre.handler()` +- An array of handlers created with `handler()`