Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 7 additions & 2 deletions packages/cre-sdk-examples/.env.example
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,16 @@
###############################################################################
# Ethereum private key or 1Password reference (e.g. op://vault/item/field)
CRE_ETH_PRIVATE_KEY=0000000000000000000000000000000000000000000000000000000000000001
# Solana 64-byte base58 keypair.
CRE_SOLANA_PRIVATE_KEY=1111111111111111111111111111111PPm2a2NNZH2EFJ5UkEjkH9Fcxn8cvjTmZDKQQisyLDmA
# Profile to use for this environment (e.g. staging-settins, production-settings)
CRE_TARGET=staging-settings
# This one will be used in PoR workflow
SECRET_ADDRESS_ALL=0x4700A50d858Cb281847ca4Ee0938F80DEfB3F1dd
# This one will be used in secrets workflow
SECRET_CHARACTER_ID=5
# These will be used in secrets workflow
SECRET_URL_VALUE="https://swapi.info/api/people/{characterId}"
SECRET_CHARACTER_ID1=5
SECRET_CHARACTER_ID2=6
SECRET_CHARACTER_ID3=7
# Secret header value for HTTP trigger
SECRET_HEADER_VALUE=abcd1234
10 changes: 8 additions & 2 deletions packages/cre-sdk-examples/secrets.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
secretsNames:
SECRET_ADDRESS:
- SECRET_ADDRESS_ALL
CHARACTER_ID:
- SECRET_CHARACTER_ID
SECRET_URL:
- SECRET_URL_VALUE
CHARACTER_ID1:
- SECRET_CHARACTER_ID1
CHARACTER_ID2:
- SECRET_CHARACTER_ID2
CHARACTER_ID3:
- SECRET_CHARACTER_ID3
SECRET_HEADER:
- SECRET_HEADER_VALUE
22 changes: 15 additions & 7 deletions packages/cre-sdk-examples/src/workflows/secrets/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import {
} from '@chainlink/cre-sdk'
import { z } from 'zod'

const configSchema = z.object({
url: z.string(),
})
const configSchema = z.object({})

type Config = z.infer<typeof configSchema>

Expand All @@ -40,10 +38,10 @@ type StarWarsCharacter = z.infer<typeof responseSchema>

const fetchStarWarsCharacter = (
sendRequester: HTTPSendRequester,
config: Config,
urlTemplate: string,
characterId: string,
): StarWarsCharacter => {
const url = config.url.replace('{characterId}', characterId)
const url = urlTemplate.replace('{characterId}', characterId)
const response = sendRequester.sendRequest({ url, method: 'GET' }).result()

// Check if the response is successful using the helper function
Expand All @@ -58,14 +56,24 @@ const fetchStarWarsCharacter = (

const onHTTPTrigger = async (runtime: Runtime<Config>) => {
const httpCapability = new HTTPClient()
const characterId = runtime.getSecret({ id: 'CHARACTER_ID' }).result().value
// Fetch a single secret
const secretUrlValue = runtime.getSecret({ id: 'SECRET_URL' }).result().value

// Fetch multiple secrets — throws if any secret fails
const secretsToFetch = [{ id: 'CHARACTER_ID1' }, { id: 'CHARACTER_ID2' }, { id: 'CHARACTER_ID3' }]
const secrets = runtime.getSecrets(secretsToFetch).result()
const characterIds = secretsToFetch.map((secretRequest) => secrets[secretRequest.id].value)

// choose a random character id
// Math.random() is safe to use in the workflow
const characterId = characterIds[Math.floor(Math.random() * characterIds.length)]

const result: StarWarsCharacter = httpCapability
.sendRequest(
runtime,
fetchStarWarsCharacter,
consensusIdenticalAggregation(),
)(runtime.config, characterId)
)(secretUrlValue, characterId)
.result()

return result
Expand Down
10 changes: 9 additions & 1 deletion packages/cre-sdk/api-baseline.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export interface Runtime<C> extends BaseRuntime<C>, SecretsProvider {
}
import type { Message } from '@bufbuild/protobuf';
import type { Secret, SecretRequest, SecretRequestJson } from '@cre/generated/sdk/v1alpha/sdk_pb';
import { type Runtime } from '@cre/sdk/runtime';
import type { Runtime } from '@cre/sdk/runtime';
import type { Trigger } from '@cre/sdk/utils/triggers/trigger-interface';
import type { CreSerializable } from './utils';
export type HandlerFn<TConfig, TTriggerOutput, TResult> = (runtime: Runtime<TConfig>, triggerOutput: TTriggerOutput) => Promise<CreSerializable<TResult>> | CreSerializable<TResult>;
Expand All @@ -85,6 +85,9 @@ export interface HandlerEntry<TConfig, TRawTriggerOutput extends Message<string>
export type Workflow<TConfig> = ReadonlyArray<HandlerEntry<TConfig, any, any, any>>;
export declare const handler: <TRawTriggerOutput extends Message<string>, TTriggerOutput, TConfig, TResult>(trigger: Trigger<TRawTriggerOutput, TTriggerOutput>, fn: HandlerFn<TConfig, TTriggerOutput, TResult>) => HandlerEntry<TConfig, TRawTriggerOutput, TTriggerOutput, TResult>;
export type SecretsProvider = {
getSecrets(requests: Array<SecretRequest | SecretRequestJson>): {
result: () => Record<string, Secret>;
};
getSecret(request: SecretRequest | SecretRequestJson): {
result: () => Secret;
};
Expand All @@ -102,6 +105,11 @@ export declare class SecretsError extends Error {
error: string;
constructor(secretRequest: SecretRequest, error: string);
}
export declare class SecretsBatchError extends Error {
readonly secretRequests: SecretRequest[];
readonly error: string;
constructor(secretRequests: SecretRequest[], error: string);
}
export declare class NullReportError extends Error {
constructor();
}
Expand Down
12 changes: 12 additions & 0 deletions packages/cre-sdk/src/sdk/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,18 @@ export class SecretsError extends Error {
}
}

export class SecretsBatchError extends Error {
constructor(
public readonly secretRequests: SecretRequest[],
public readonly error: string,
) {
super(
`batch secret retrieval failed for ${secretRequests.length} request(s):\n${error}\nVerify the host response is complete and that the workflow has access to the requested secrets`,
)
this.name = 'SecretsBatchError'
}
}

export class NullReportError extends Error {
constructor() {
super('null report')
Expand Down
Loading
Loading