Using Secrets in Simulation

This guide explains how to use secrets during local development and simulation. When you're simulating a workflow on your local machine with cre workflow simulate, secrets are provided via environment variables or a .env file.

At a high level, the process follows a simple, three-step pattern:

  1. Declare: You declare the logical names of your secrets in a secrets.yaml file.
  2. Provide: You provide the actual secret values in a .env file or as environment variables.
  3. Use: You access the secrets in your workflow code using the SDK's secret management API.

This separation of concerns ensures that your workflow code is portable and your secrets are never hard-coded.

Step-by-step guide

Step 1: Declare your secrets (secrets.yaml)

The first step is to create a secrets.yaml file in the root of your project. This file acts as a manifest, defining the "logical names" or "IDs" for the secrets your workflow will use.

In this file, you map a logical name (which you'll use in your workflow code) to one environment variable name that will hold the actual secret value.

Example secrets.yaml:

# in project-root/secrets.yaml
secretsNames:
  # This is the logical ID you will use in your workflow code
  SECRET_ADDRESS:
    # This is the environment variable the CLI will look for
    - SECRET_ADDRESS_ALL

Step 2: Provide the secret values

Next, you need to provide the actual values for the secrets. The cre CLI can read these values in two primary ways.

You can provide secrets as standard environment variables directly in your shell.

For example, in your terminal:

export SECRET_ADDRESS_ALL="0x1234567890abcdef1234567890abcdef12345678"

When you run the cre workflow simulate command in the same terminal session, the CLI will have access to this variable.

Method 2: Using a .env file

Create a .env file in your project's root directory. The cre CLI automatically finds this file and loads the variables defined within it into the environment for your simulation. The variable names here must match those you declared in secrets.yaml.

Example .env file:

# in project-root/.env

# The variable name matches the one in secrets.yaml
SECRET_ADDRESS_ALL="0x1234567890abcdef1234567890abcdef12345678"

Step 3: Use the secret in your workflow

Now you can access the secret in your workflow code. The SDK provides a method to retrieve secrets using the logical ID you defined in secrets.yaml.

The following code shows a complete, runnable workflow that triggers on a schedule, fetches a secret, and logs its value.

Example workflow:

Fetching Single Secret (TypeScript)
Typescript
1 import { cre, Runner, type Runtime } from "@chainlink/cre-sdk"
2 โ€‹
3 // Config can be an empty object if you don't need any parameters from config.json
4 type Config = Record<string, never>
5 โ€‹
6 // Define the logical name of the secret as a constant for clarity
7 const SECRET_NAME = "SECRET_ADDRESS"
8 โ€‹
9 // onCronTrigger is the callback function that gets executed when the cron trigger fires
10 // This is where you use the secret
11 const onCronTrigger = (runtime: Runtime<Config>): string => {
12 // Call runtime.getSecret with the secret's logical ID
13 const secret = runtime.getSecret({ id: SECRET_NAME }).result()
14 โ€‹
15 // Use the secret's value
16 const secretAddress = secret.value
17 runtime.log(`Successfully fetched a secret! Address: ${secretAddress}`)
18 โ€‹
19 // ... now you can use the secretAddress in your logic ...
20 return "Success"
21 }
22 โ€‹
23 // initWorkflow is the entry point for the workflow
24 const initWorkflow = () => {
25 const cron = new cre.capabilities.CronCapability()
26 โ€‹
27 return [cre.handler(cron.trigger({ schedule: "0 */10 * * * *" }), onCronTrigger)]
28 }
29 โ€‹
30 // main is the entry point for the WASM binary
31 export async function main() {
32 const runner = await Runner.newRunner<Config>()
33 await runner.run(initWorkflow)
34 }
35 โ€‹
36 main()
37 โ€‹

Step 4: Configure secrets path in workflow.yaml

Before simulating, you need to tell the CLI where to find your secrets file. This is configured in your workflow.yaml file under workflow-artifacts.secrets-path.

Open your workflow.yaml file and set the secrets-path:

local-simulation:
  user-workflow:
    workflow-name: "my-workflow"
    workflow-artifacts:
      workflow-path: "./main.ts"
      config-path: "./config.json"
      secrets-path: "../secrets.yaml" # Path to your secrets file

Notice the path ../secrets.yaml. Because the workflow artifacts are relative to the workflow directory, you need to point to the secrets.yaml file located one level up in the project root.

Step 5: Run the simulation

Now you can simulate your workflow:

cre workflow simulate my-workflow --target staging-settings

The CLI will automatically read the secrets-path from your workflow.yaml and load the secrets from your .env file or environment variables you provided in your terminal session.

Fetching multiple secrets

You can fetch multiple secrets by calling the secret retrieval method multiple times within your workflow.

The following example builds on the previous one. First, update your secrets.yaml to declare two secrets:

secretsNames:
  SECRET_ADDRESS:
    - SECRET_ADDRESS_ALL
  API_KEY:
    - API_KEY_ALL

Then provide the values in your .env file or export them as environment variables in your terminal session:

export SECRET_ADDRESS_ALL="0x1234567890abcdef1234567890abcdef12345678"
export API_KEY_ALL="your-api-key-here"

Now you can fetch both secrets in your workflow code:

Fetching Multiple Secrets (TypeScript)
Typescript
1 import { cre, Runner, type Runtime } from "@chainlink/cre-sdk"
2 โ€‹
3 // Config can be an empty object if you don't need any parameters from config.json
4 type Config = Record<string, never>
5 โ€‹
6 const SECRET_ADDRESS_NAME = "SECRET_ADDRESS"
7 const API_KEY_NAME = "API_KEY"
8 โ€‹
9 const onCronTrigger = (runtime: Runtime<Config>): string => {
10 // 1. Request the first secret
11 const secretAddress = runtime.getSecret({ id: SECRET_ADDRESS_NAME }).result()
12 โ€‹
13 // 2. Request the second secret
14 const apiKey = runtime.getSecret({ id: API_KEY_NAME }).result()
15 โ€‹
16 // 3. Use your secrets
17 runtime.log(`Successfully fetched secrets! Address: ${secretAddress.value}, API Key: ${apiKey.value}`)
18 โ€‹
19 return "Success"
20 }
21 โ€‹
22 // initWorkflow is the entry point for the workflow
23 const initWorkflow = () => {
24 const cron = new cre.capabilities.CronCapability()
25 โ€‹
26 return [cre.handler(cron.trigger({ schedule: "0 */10 * * * *" }), onCronTrigger)]
27 }
28 โ€‹
29 // main is the entry point for the WASM binary
30 export async function main() {
31 const runner = await Runner.newRunner<Config>()
32 await runner.run(initWorkflow)
33 }
34 โ€‹
35 main()
36 โ€‹

Get the latest Chainlink content straight to your inbox.