diff --git a/cmd/creinit/creinit.go b/cmd/creinit/creinit.go index 50fc3548..3f599fb2 100644 --- a/cmd/creinit/creinit.go +++ b/cmd/creinit/creinit.go @@ -37,6 +37,7 @@ const ( const ( HelloWorldTemplate string = "HelloWorld" PoRTemplate string = "PoR" + ConfHTTPTemplate string = "ConfHTTP" ) type WorkflowTemplate struct { @@ -70,6 +71,7 @@ var languageTemplates = []LanguageTemplate{ Workflows: []WorkflowTemplate{ {Folder: "typescriptSimpleExample", Title: "Helloworld: Typescript Hello World example", ID: 3, Name: HelloWorldTemplate}, {Folder: "typescriptPorExampleDev", Title: "Custom data feed: Typescript updating on-chain data periodically using offchain API data", ID: 4, Name: PoRTemplate}, + {Folder: "typescriptConfHTTP", Title: "Confidential Http: Typescript example using the confidential http capability", ID: 5, Name: ConfHTTPTemplate}, }, }, } diff --git a/cmd/creinit/template/workflow/typescriptConfHTTP/README.md b/cmd/creinit/template/workflow/typescriptConfHTTP/README.md new file mode 100644 index 00000000..457e5ef0 --- /dev/null +++ b/cmd/creinit/template/workflow/typescriptConfHTTP/README.md @@ -0,0 +1,52 @@ +# Typescript Confidential HTTP Example + +This template provides a Typescript Confidential HTTP workflow example. It shows how to set a secret header and send it via the ConfidentialHTTP capability. + +Steps to run the example + +## 1. Update .env file + +You'll need to add a secret value to the .env file for requests to read. This is the value that will be set as a header when sending requests via the ConfidentialHTTP capability. + +``` +SECRET_HEADER_VALUE=abcd1234 +``` + +Note: Make sure your `workflow.yaml` file is pointing to the config.json, example: + +```yaml +staging-settings: + user-workflow: + workflow-name: "conf-http" + workflow-artifacts: + workflow-path: "./main.ts" + config-path: "./config.json" +``` + +## 2. Install dependencies + +If `bun` is not already installed, see https://bun.com/docs/installation for installing in your environment. + +```bash +cd && bun install +``` + +Example: For a workflow directory named `conf-http` the command would be: + +```bash +cd conf-http && bun install +``` + +## 3. Simulate the workflow + +Run the command from project root directory + +```bash +cre workflow simulate --target=staging-settings +``` + +Example: For workflow named `conf-http` the command would be: + +```bash +cre workflow simulate ./conf-http --target=staging-settings +``` diff --git a/cmd/creinit/template/workflow/typescriptConfHTTP/config.production.json b/cmd/creinit/template/workflow/typescriptConfHTTP/config.production.json new file mode 100644 index 00000000..4ffa68ef --- /dev/null +++ b/cmd/creinit/template/workflow/typescriptConfHTTP/config.production.json @@ -0,0 +1,4 @@ +{ + "schedule": "*/30 * * * * *", + "url": "https://postman-echo.com/headers" +} diff --git a/cmd/creinit/template/workflow/typescriptConfHTTP/config.staging.json b/cmd/creinit/template/workflow/typescriptConfHTTP/config.staging.json new file mode 100644 index 00000000..4ffa68ef --- /dev/null +++ b/cmd/creinit/template/workflow/typescriptConfHTTP/config.staging.json @@ -0,0 +1,4 @@ +{ + "schedule": "*/30 * * * * *", + "url": "https://postman-echo.com/headers" +} diff --git a/cmd/creinit/template/workflow/typescriptConfHTTP/main.ts.tpl b/cmd/creinit/template/workflow/typescriptConfHTTP/main.ts.tpl new file mode 100644 index 00000000..b7773eae --- /dev/null +++ b/cmd/creinit/template/workflow/typescriptConfHTTP/main.ts.tpl @@ -0,0 +1,86 @@ +import { + type ConfidentialHTTPSendRequester, + consensusIdenticalAggregation, + cre, + json, + ok, + Runner, + type Runtime, +} from '@chainlink/cre-sdk' +import { z } from 'zod' + +const configSchema = z.object({ + schedule: z.string(), + url: z.string(), +}) + +type Config = z.infer + +type ResponseValues = { + result: { + headers: { + 'secret-header': string + } + } +} + +const fetchResult = (sendRequester: ConfidentialHTTPSendRequester, config: Config) => { + const { responses } = sendRequester + .sendRequests({ + input: { + requests: [ + { + url: config.url, + method: 'GET', + headers: ['secret-header: {{.SECRET_HEADER}}'], + }, + ], + }, + vaultDonSecrets: [ + { + key: 'SECRET_HEADER', + }, + ], + }) + .result() + const response = responses[0] + + if (!ok(response)) { + throw new Error(`HTTP request failed with status: ${response.statusCode}`) + } + + return json(response) as ResponseValues +} + +const onCronTrigger = (runtime: Runtime) => { + runtime.log('Confidential HTTP workflow triggered.') + + const confHTTPClient = new cre.capabilities.ConfidentialHTTPClient() + const result = confHTTPClient + .sendRequests( + runtime, + fetchResult, + consensusIdenticalAggregation(), + )(runtime.config) + .result() + + runtime.log(`Successfully fetched result: ${result}`) + + return { + result, + } +} + +const initWorkflow = (config: Config) => { + const cron = new cre.capabilities.CronCapability() + + return [cre.handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)] +} + +export async function main() { + const runner = await Runner.newRunner({ configSchema }) + + await runner.run(initWorkflow) +} + +main() diff --git a/cmd/creinit/template/workflow/typescriptConfHTTP/package.json.tpl b/cmd/creinit/template/workflow/typescriptConfHTTP/package.json.tpl new file mode 100644 index 00000000..c39e19d2 --- /dev/null +++ b/cmd/creinit/template/workflow/typescriptConfHTTP/package.json.tpl @@ -0,0 +1,16 @@ +{ + "name": "typescript-simple-template", + "version": "1.0.0", + "main": "dist/main.js", + "private": true, + "scripts": { + "postinstall": "bunx cre-setup" + }, + "license": "UNLICENSED", + "dependencies": { + "@chainlink/cre-sdk": "^1.0.0" + }, + "devDependencies": { + "@types/bun": "1.2.21" + } +} diff --git a/cmd/creinit/template/workflow/typescriptConfHTTP/secrets.yaml b/cmd/creinit/template/workflow/typescriptConfHTTP/secrets.yaml new file mode 100644 index 00000000..8f567382 --- /dev/null +++ b/cmd/creinit/template/workflow/typescriptConfHTTP/secrets.yaml @@ -0,0 +1,3 @@ +secretsNames: + SECRET_HEADER: + - SECRET_HEADER_VALUE diff --git a/cmd/creinit/template/workflow/typescriptConfHTTP/tsconfig.json.tpl b/cmd/creinit/template/workflow/typescriptConfHTTP/tsconfig.json.tpl new file mode 100644 index 00000000..840fdc79 --- /dev/null +++ b/cmd/creinit/template/workflow/typescriptConfHTTP/tsconfig.json.tpl @@ -0,0 +1,16 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "ESNext", + "moduleResolution": "bundler", + "lib": ["ESNext"], + "outDir": "./dist", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true + }, + "include": [ + "main.ts" + ] +} diff --git a/cmd/creinit/template/workflow/typescriptPorExampleDev/package.json.tpl b/cmd/creinit/template/workflow/typescriptPorExampleDev/package.json.tpl index e183c457..55d5679b 100644 --- a/cmd/creinit/template/workflow/typescriptPorExampleDev/package.json.tpl +++ b/cmd/creinit/template/workflow/typescriptPorExampleDev/package.json.tpl @@ -8,7 +8,7 @@ }, "license": "UNLICENSED", "dependencies": { - "@chainlink/cre-sdk": "^1.0.0", + "@chainlink/cre-sdk": "^1.0.1", "viem": "2.34.0", "zod": "3.25.76" },