From 01d4c658a8066ab4bffb922aa99531aca445c36e Mon Sep 17 00:00:00 2001 From: De Clercq Wentzel <10665586+wentzeld@users.noreply.github.com> Date: Fri, 27 Feb 2026 08:33:30 -0800 Subject: [PATCH 1/4] fix: correct confidentialHTTP SDK reference and guide docs - Move EncryptOutput/encryptOutput from ConfidentialHTTPRequest to HTTPRequest - Fix Client.SendRequest signature: cre.Runtime not cre.NodeRuntime - Remove nonexistent high-level SendRequest/ConfidentialHTTPSendRequester patterns - Remove incorrect RunInNodeMode wrapping (not needed for confidential HTTP) - Fix all code examples in both Go and TS guides --- .../making-requests-go.mdx | 52 ++++--- .../making-requests-ts.mdx | 94 +++++-------- .../sdk/confidential-http-client-go.mdx | 114 ++++------------ .../sdk/confidential-http-client-ts.mdx | 129 +++--------------- 4 files changed, 102 insertions(+), 287 deletions(-) diff --git a/src/content/cre/guides/workflow/using-confidential-http-client/making-requests-go.mdx b/src/content/cre/guides/workflow/using-confidential-http-client/making-requests-go.mdx index ab19387e39f..6aa8634bc0b 100644 --- a/src/content/cre/guides/workflow/using-confidential-http-client/making-requests-go.mdx +++ b/src/content/cre/guides/workflow/using-confidential-http-client/making-requests-go.mdx @@ -94,10 +94,10 @@ type Result struct { ### Step 4: Implement the request logic -Use `cre.RunInNodeMode` to make the confidential request. The `confidentialhttp.Client` requires a `NodeRuntime`: +Unlike the regular HTTP client, the Confidential HTTP client takes a `cre.Runtime` directly and does not require `cre.RunInNodeMode` wrapping: ```go -func makeConfidentialRequest(config Config, nodeRuntime cre.NodeRuntime) (Result, error) { +func makeConfidentialRequest(config Config, runtime cre.Runtime) (Result, error) { // 1. Define the request body with secret template placeholders payload := `{"auth": "{{.myApiKey}}", "action": "getTransaction", "id": "tx-123"}` @@ -113,17 +113,17 @@ func makeConfidentialRequest(config Config, nodeRuntime cre.NodeRuntime) (Result // 3. Create the client and send the request client := confidentialhttp.Client{} - resp, err := client.SendRequest(nodeRuntime, &confidentialhttp.ConfidentialHTTPRequest{ + resp, err := client.SendRequest(runtime, &confidentialhttp.ConfidentialHTTPRequest{ Request: &confidentialhttp.HTTPRequest{ - Url: config.URL, - Method: "POST", - Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: payload}, + Url: config.URL, + Method: "POST", + Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: payload}, MultiHeaders: headers, + EncryptOutput: false, }, VaultDonSecrets: []*confidentialhttp.SecretIdentifier{ {Key: "myApiKey"}, }, - EncryptOutput: false, }).Await() if err != nil { return Result{}, fmt.Errorf("confidential HTTP request failed: %w", err) @@ -141,14 +141,11 @@ func makeConfidentialRequest(config Config, nodeRuntime cre.NodeRuntime) (Result ### Step 5: Wire it into your workflow -Call the request function from your trigger handler using `cre.RunInNodeMode`: +Call the request function from your trigger handler: ```go func onCronTrigger(config *Config, runtime cre.Runtime, outputs *cron.Payload) (string, error) { - result, err := cre.RunInNodeMode(*config, runtime, - makeConfidentialRequest, - cre.ConsensusIdenticalAggregation[Result](), - ).Await() + result, err := makeConfidentialRequest(*config, runtime) if err != nil { return "", fmt.Errorf("failed to get result: %w", err) } @@ -212,18 +209,18 @@ By default, the API response is returned unencrypted (`EncryptOutput: false`). T 1. **Include the key in your `VaultDonSecrets`** and set `EncryptOutput: true`: ```go - resp, err := client.SendRequest(nodeRuntime, &confidentialhttp.ConfidentialHTTPRequest{ + resp, err := client.SendRequest(runtime, &confidentialhttp.ConfidentialHTTPRequest{ Request: &confidentialhttp.HTTPRequest{ - Url: config.URL, - Method: "POST", - Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: payload}, - MultiHeaders: headers, + Url: config.URL, + Method: "POST", + Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: payload}, + MultiHeaders: headers, + EncryptOutput: true, }, VaultDonSecrets: []*confidentialhttp.SecretIdentifier{ {Key: "myApiKey"}, {Key: "san_marino_aes_gcm_encryption_key"}, }, - EncryptOutput: true, }).Await() ``` @@ -309,10 +306,7 @@ func InitWorkflow(config *Config, logger *slog.Logger, secretsProvider cre.Secre } func onCronTrigger(config *Config, runtime cre.Runtime, outputs *cron.Payload) (string, error) { - result, err := cre.RunInNodeMode(*config, runtime, - makeConfidentialRequest, - cre.ConsensusIdenticalAggregation[Result](), - ).Await() + result, err := makeConfidentialRequest(*config, runtime) if err != nil { return "", fmt.Errorf("failed to get result: %w", err) } @@ -321,7 +315,7 @@ func onCronTrigger(config *Config, runtime cre.Runtime, outputs *cron.Payload) ( return result.TransactionID, nil } -func makeConfidentialRequest(config Config, nodeRuntime cre.NodeRuntime) (Result, error) { +func makeConfidentialRequest(config Config, runtime cre.Runtime) (Result, error) { payload := `{"auth": "{{.myApiKey}}", "action": "getTransaction", "id": "tx-123"}` headers := map[string]*confidentialhttp.HeaderValues{ @@ -334,18 +328,18 @@ func makeConfidentialRequest(config Config, nodeRuntime cre.NodeRuntime) (Result } client := confidentialhttp.Client{} - resp, err := client.SendRequest(nodeRuntime, &confidentialhttp.ConfidentialHTTPRequest{ + resp, err := client.SendRequest(runtime, &confidentialhttp.ConfidentialHTTPRequest{ Request: &confidentialhttp.HTTPRequest{ - Url: config.URL, - Method: "POST", - Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: payload}, - MultiHeaders: headers, + Url: config.URL, + Method: "POST", + Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: payload}, + MultiHeaders: headers, + EncryptOutput: true, }, VaultDonSecrets: []*confidentialhttp.SecretIdentifier{ {Key: "myApiKey"}, {Key: "san_marino_aes_gcm_encryption_key"}, }, - EncryptOutput: true, }).Await() if err != nil { return Result{}, fmt.Errorf("confidential HTTP request failed: %w", err) diff --git a/src/content/cre/guides/workflow/using-confidential-http-client/making-requests-ts.mdx b/src/content/cre/guides/workflow/using-confidential-http-client/making-requests-ts.mdx index 7f52d11df7d..12cea748269 100644 --- a/src/content/cre/guides/workflow/using-confidential-http-client/making-requests-ts.mdx +++ b/src/content/cre/guides/workflow/using-confidential-http-client/making-requests-ts.mdx @@ -87,25 +87,35 @@ type TransactionResult = { } ``` -### Step 4: Implement the fetch function +### Step 4: Implement the request and wire it into your workflow -Create the function that will be passed to `sendRequest()`. This function receives a `ConfidentialHTTPSendRequester` and your config as parameters: +Unlike the regular HTTP client, the Confidential HTTP client takes a `Runtime` directly and does not require `runInNodeMode` wrapping: ```typescript -import { type ConfidentialHTTPSendRequester, ok, json } from "@chainlink/cre-sdk" +import { + CronCapability, + ConfidentialHTTPClient, + handler, + ok, + json, + type Runtime, + Runner, +} from "@chainlink/cre-sdk" + +const onCronTrigger = (runtime: Runtime): TransactionResult => { + const confHTTPClient = new ConfidentialHTTPClient() -const fetchTransaction = (sendRequester: ConfidentialHTTPSendRequester, config: Config): TransactionResult => { // 1. Send the confidential request - const response = sendRequester - .sendRequest({ + const response = confHTTPClient + .sendRequest(runtime, { request: { - url: config.url, + url: runtime.config.url, method: "GET", multiHeaders: { Authorization: { values: ["Basic {{.myApiKey}}"] }, }, }, - vaultDonSecrets: [{ key: "myApiKey", owner: config.owner }], + vaultDonSecrets: [{ key: "myApiKey", owner: runtime.config.owner }], }) .result() @@ -115,33 +125,9 @@ const fetchTransaction = (sendRequester: ConfidentialHTTPSendRequester, config: } // 3. Parse and return the result - return json(response) as TransactionResult -} -``` - -### Step 5: Wire it into your workflow - -In your trigger handler, call `confHTTPClient.sendRequest()` with your fetch function and a consensus method: - -```typescript -import { - CronCapability, - ConfidentialHTTPClient, - handler, - consensusIdenticalAggregation, - type Runtime, - Runner, -} from "@chainlink/cre-sdk" - -const onCronTrigger = (runtime: Runtime): string => { - const confHTTPClient = new ConfidentialHTTPClient() - - const result = confHTTPClient - .sendRequest(runtime, fetchTransaction, consensusIdenticalAggregation())(runtime.config) - .result() - + const result = json(response) as TransactionResult runtime.log(`Transaction result: ${result.transactionId} — ${result.status}`) - return result.transactionId + return result } ``` @@ -197,17 +183,17 @@ export AES_KEY_ALL="your-256-bit-hex-encoded-key" 1. **Include the key in your `vaultDonSecrets`** and set `encryptOutput: true`: ```typescript - const response = sendRequester - .sendRequest({ + const response = confHTTPClient + .sendRequest(runtime, { request: { - url: config.url, + url: runtime.config.url, method: "GET", multiHeaders: { Authorization: { values: ["Basic {{.myApiKey}}"] }, }, + encryptOutput: true, }, - vaultDonSecrets: [{ key: "myApiKey", owner: config.owner }, { key: "san_marino_aes_gcm_encryption_key" }], - encryptOutput: true, + vaultDonSecrets: [{ key: "myApiKey", owner: runtime.config.owner }, { key: "san_marino_aes_gcm_encryption_key" }], }) .result() ``` @@ -233,10 +219,8 @@ import { CronCapability, ConfidentialHTTPClient, handler, - consensusIdenticalAggregation, ok, json, - type ConfidentialHTTPSendRequester, type Runtime, Runner, } from "@chainlink/cre-sdk" @@ -257,18 +241,20 @@ type TransactionResult = { status: string } -// Fetch function — receives a ConfidentialHTTPSendRequester and config -const fetchTransaction = (sendRequester: ConfidentialHTTPSendRequester, config: Config): TransactionResult => { - const response = sendRequester - .sendRequest({ +// Main workflow handler +const onCronTrigger = (runtime: Runtime): TransactionResult => { + const confHTTPClient = new ConfidentialHTTPClient() + + const response = confHTTPClient + .sendRequest(runtime, { request: { - url: config.url, + url: runtime.config.url, method: "GET", multiHeaders: { Authorization: { values: ["Basic {{.myApiKey}}"] }, }, }, - vaultDonSecrets: [{ key: "myApiKey", owner: config.owner }], + vaultDonSecrets: [{ key: "myApiKey", owner: runtime.config.owner }], }) .result() @@ -276,19 +262,9 @@ const fetchTransaction = (sendRequester: ConfidentialHTTPSendRequester, config: throw new Error(`HTTP request failed with status: ${response.statusCode}`) } - return json(response) as TransactionResult -} - -// Main workflow handler -const onCronTrigger = (runtime: Runtime): string => { - const confHTTPClient = new ConfidentialHTTPClient() - - const result = confHTTPClient - .sendRequest(runtime, fetchTransaction, consensusIdenticalAggregation())(runtime.config) - .result() - + const result = json(response) as TransactionResult runtime.log(`Transaction result: ${result.transactionId} — ${result.status}`) - return result.transactionId + return result } // Initialize workflow diff --git a/src/content/cre/reference/sdk/confidential-http-client-go.mdx b/src/content/cre/reference/sdk/confidential-http-client-go.mdx index 69ad6489a92..fcd696ae9e3 100644 --- a/src/content/cre/reference/sdk/confidential-http-client-go.mdx +++ b/src/content/cre/reference/sdk/confidential-http-client-go.mdx @@ -19,10 +19,9 @@ The [Confidential HTTP](/cre/capabilities/confidential-http-go) Client lets you ## Quick reference -| Method | Description | -| -------------------------------------------------------------- | ---------------------------------------------------------- | -| [`confidentialhttp.SendRequest`](#confidentialhttpsendrequest) | High-level helper with automatic `RunInNodeMode` wrapping | -| [`client.SendRequest`](#clientsendrequest) | Low-level method requiring manual `RunInNodeMode` wrapping | +| Method | Description | +| ------------------------------------------ | ----------------------------------------- | +| [`client.SendRequest`](#clientsendrequest) | Makes a confidential HTTP request. | ## Core types @@ -34,7 +33,6 @@ The top-level request type that combines an HTTP request with Vault DON secrets | -------------------------------------- | ------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | | `Request` | `*HTTPRequest` | The HTTP request to execute inside the enclave. See [`HTTPRequest`](#confidentialhttphttprequest). | | `VaultDonSecrets` | `[]*SecretIdentifier` | List of secrets to fetch from the Vault DON and make available in the enclave. See [`SecretIdentifier`](#confidentialhttpsecretidentifier). | -| `EncryptOutput` | `bool` | If `true`, encrypts the response body before it leaves the enclave. See [Response encryption](#response-encryption). Default: `false`. | ### `confidentialhttp.HTTPRequest` @@ -49,6 +47,7 @@ Defines the HTTP request that will be executed inside the enclave. | `TemplatePublicValues` | `map[string]string` | Public (non-secret) values used to fill template placeholders in the body and headers. | | `CustomRootCaCertPem` | `[]byte` | Optional custom root CA certificate (PEM format) for verifying the external server's TLS certificate. | | `Timeout` | `*durationpb.Duration` | Optional request timeout. | +| `EncryptOutput` | `bool` | If `true`, encrypts the response body before it leaves the enclave. See [Response encryption](#response-encryption). Default: `false`. | #### Setting the request body @@ -100,75 +99,20 @@ Represents multiple values for a single HTTP header key. ## Making requests -### `confidentialhttp.SendRequest` - -The high-level helper function for making confidential HTTP requests. Automatically handles the `cre.RunInNodeMode` pattern. - -**Signature:** - -```go -func SendRequest[C, T any]( - config C, - runtime cre.Runtime, - client *Client, - fn func(config C, logger *slog.Logger, sendRequester *SendRequester) (T, error), - ca cre.ConsensusAggregation[T], -) cre.Promise[T] -``` - -**Parameters:** - -- `config`: Your workflow's configuration struct, passed to `fn`. -- `runtime`: The top-level `cre.Runtime` from your trigger callback. -- `client`: An initialized `*confidentialhttp.Client`. -- `fn`: Your request logic function that receives `config`, `logger`, and `sendRequester`. -- `ca`: The [consensus aggregation method](/cre/reference/sdk/consensus). - -**Example:** - -```go -func fetchData(config *Config, logger *slog.Logger, sendRequester *confidentialhttp.SendRequester) (*Result, error) { - resp, err := sendRequester.SendRequest(&confidentialhttp.ConfidentialHTTPRequest{ - Request: &confidentialhttp.HTTPRequest{ - Url: config.URL, - Method: "GET", - MultiHeaders: map[string]*confidentialhttp.HeaderValues{ - "Authorization": {Values: []string{"Basic {{.apiKey}}"}}, - }, - }, - VaultDonSecrets: []*confidentialhttp.SecretIdentifier{ - {Key: "apiKey"}, - }, - }).Await() - if err != nil { - return nil, err - } - // Parse resp.Body... - return &Result{}, nil -} - -// In your trigger callback -client := &confidentialhttp.Client{} -result, err := confidentialhttp.SendRequest(config, runtime, client, - fetchData, - cre.ConsensusIdenticalAggregation[*Result](), -).Await() -``` - ### `client.SendRequest` -The lower-level method for making confidential HTTP requests. Must be manually wrapped in `cre.RunInNodeMode`. +Makes a confidential HTTP request. The request executes inside a secure enclave, so unlike the regular HTTP client, there is no need to wrap this call in `cre.RunInNodeMode`. **Signature:** ```go -func (c *Client) SendRequest(runtime cre.NodeRuntime, input *ConfidentialHTTPRequest) cre.Promise[*HTTPResponse] +func (c *Client) SendRequest(runtime cre.Runtime, input *ConfidentialHTTPRequest) cre.Promise[*HTTPResponse] ``` **Parameters:** -- `runtime`: A `cre.NodeRuntime` provided by `cre.RunInNodeMode`. -- `input`: A `*ConfidentialHTTPRequest` containing the request, secrets, and encryption settings. +- `runtime`: The `cre.Runtime` from your trigger callback. +- `input`: A `*ConfidentialHTTPRequest` containing the request and secrets. **Returns:** @@ -177,30 +121,26 @@ func (c *Client) SendRequest(runtime cre.NodeRuntime, input *ConfidentialHTTPReq **Example:** ```go -result, err := cre.RunInNodeMode(config, runtime, - func(config Config, nodeRuntime cre.NodeRuntime) (Result, error) { - client := confidentialhttp.Client{} - resp, err := client.SendRequest(nodeRuntime, &confidentialhttp.ConfidentialHTTPRequest{ - Request: &confidentialhttp.HTTPRequest{ - Url: config.URL, - Method: "POST", - Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: `{"auth": "{{.apiKey}}"}`}, - MultiHeaders: map[string]*confidentialhttp.HeaderValues{ - "Content-Type": {Values: []string{"application/json"}}, - }, - }, - VaultDonSecrets: []*confidentialhttp.SecretIdentifier{ - {Key: "apiKey"}, - }, - }).Await() - if err != nil { - return Result{}, err - } - // Parse and return... - return Result{}, nil +client := &confidentialhttp.Client{} +resp, err := client.SendRequest(runtime, &confidentialhttp.ConfidentialHTTPRequest{ + Request: &confidentialhttp.HTTPRequest{ + Url: config.URL, + Method: "POST", + Body: &confidentialhttp.HTTPRequest_BodyString{BodyString: `{"auth": "{{.apiKey}}"}`}, + MultiHeaders: map[string]*confidentialhttp.HeaderValues{ + "Content-Type": {Values: []string{"application/json"}}, + "Authorization": {Values: []string{"Basic {{.apiKey}}"}}, + }, + EncryptOutput: false, + }, + VaultDonSecrets: []*confidentialhttp.SecretIdentifier{ + {Key: "apiKey"}, }, - cre.ConsensusIdenticalAggregation[Result](), -).Await() +}).Await() +if err != nil { + return Result{}, err +} +// Parse resp.Body... ``` **Guide:** [Making Confidential Requests](/cre/guides/workflow/using-confidential-http-client/making-requests-go) diff --git a/src/content/cre/reference/sdk/confidential-http-client-ts.mdx b/src/content/cre/reference/sdk/confidential-http-client-ts.mdx index e541e200b6f..6187919bdad 100644 --- a/src/content/cre/reference/sdk/confidential-http-client-ts.mdx +++ b/src/content/cre/reference/sdk/confidential-http-client-ts.mdx @@ -19,10 +19,9 @@ The [Confidential HTTP](/cre/capabilities/confidential-http-ts) Client lets you ## Quick reference -| Method | Description | -| --------------------------------------------------- | -------------------------------------------------------------------------------------- | -| [`sendRequest` (high-level)](#sendrequest) | **Recommended.** Makes a confidential HTTP request with built-in consensus and typing. | -| [`sendRequest` (low-level)](#low-level-sendrequest) | Makes a confidential HTTP request manually inside a `runInNodeMode` block. | +| Method | Description | +| ------------------------------- | -------------------------------------- | +| [`sendRequest`](#sendrequest) | Makes a confidential HTTP request. | ## Core types @@ -39,7 +38,6 @@ The top-level request type that combines an HTTP request with Vault DON secrets | -------------------------------------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------- | | `request` | `HTTPRequest` \| `HTTPRequestJson` | The HTTP request to execute inside the enclave. See [`HTTPRequest`](#httprequest--httprequestjson). | | `vaultDonSecrets` | `SecretIdentifier[]` \| `SecretIdentifierJson[]` | List of secrets to fetch from the Vault DON and make available in the enclave. See [`SecretIdentifier`](#secretidentifier--secretidentifierjson). | -| `encryptOutput` | `boolean` | If `true`, encrypts the response body before it leaves the enclave. See [Response encryption](#response-encryption). Default: `false`. | ### `HTTPRequest` / `HTTPRequestJson` @@ -55,6 +53,7 @@ Defines the HTTP request that will be executed inside the enclave. | `templatePublicValues` | `{ [key: string]: string }` (optional) | Public (non-secret) values used to fill template placeholders in the body and headers. | | `customRootCaCertPem` | `Uint8Array` \| `string` (optional) | Optional custom root CA certificate (PEM format) for verifying the external server's TLS certificate. | | `timeout` | `Duration` \| `DurationJson` (optional) | Optional request timeout (e.g., `"5s"`). | +| `encryptOutput` | `boolean` (optional) | If `true`, encrypts the response body before it leaves the enclave. See [Response encryption](#response-encryption). Default: `false`. | {/* prettier-ignore */}