Skip to content

Commit da93546

Browse files
Add NoExcessive type and confidential http helper (#251)
* Add NoExcessive type and confidential http helper * Drop temp file * Strenghten the typings * Address CR feedback
1 parent 841191c commit da93546

26 files changed

Lines changed: 628 additions & 37 deletions

File tree

packages/cre-sdk-examples/.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@ node_modules
22
dist
33
.turbo
44
tmp.js
5-
tmp.wasm
5+
tmp.wasm
6+
.cre_build_tmp.js
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
{
2+
"schedule": "0 */1 * * * *",
3+
"url": "https://api.mathjs.org/v4?expr=randomInt(1,101)"
4+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import {
2+
ConfidentialHTTPClient,
3+
CronCapability,
4+
handler,
5+
httpRequest,
6+
json,
7+
ok,
8+
Runner,
9+
type Runtime,
10+
text,
11+
} from '@chainlink/cre-sdk'
12+
import { z } from 'zod'
13+
14+
const configSchema = z.object({
15+
schedule: z.string(),
16+
url: z.string(),
17+
})
18+
type Config = z.infer<typeof configSchema>
19+
20+
// Workflow demonstrate a usage of `httpRequest` helper
21+
// to build type-safe payloads for `ConfidentialHTTPClient`.
22+
const onCronTrigger = (runtime: Runtime<Config>) => {
23+
const client = new ConfidentialHTTPClient()
24+
25+
// Example 1: request config as separate variable
26+
const separateRequestConfig = {
27+
request: httpRequest({
28+
url: runtime.config.url,
29+
method: 'POST',
30+
bodyString: '{ hello: "world" }',
31+
multiHeaders: {
32+
'content-type': { values: ['application/json'] },
33+
},
34+
}),
35+
}
36+
37+
client.sendRequest(runtime, separateRequestConfig).result()
38+
39+
// Example 2: using helper inline
40+
client
41+
.sendRequest(runtime, {
42+
request: httpRequest({
43+
url: runtime.config.url,
44+
method: 'POST',
45+
body: { hello: 'world' },
46+
multiHeaders: {
47+
'content-type': { values: ['application/json'] },
48+
},
49+
}),
50+
})
51+
.result()
52+
53+
// Example 3: not using helper at all
54+
client
55+
.sendRequest(runtime, {
56+
request: {
57+
url: runtime.config.url,
58+
method: 'POST',
59+
// no helper -> must use bodyString/bodyBytes (proto oneof keys)
60+
bodyString: JSON.stringify({ hello: 'world' }),
61+
multiHeaders: {
62+
'content-type': { values: ['application/json'] },
63+
},
64+
},
65+
})
66+
.result()
67+
68+
return { success: true }
69+
}
70+
71+
const initWorkflow = (config: Config) => {
72+
const cron = new CronCapability()
73+
return [handler(cron.trigger({ schedule: config.schedule }), onCronTrigger)]
74+
}
75+
76+
export async function main() {
77+
const runner = await Runner.newRunner<Config>({ configSchema })
78+
await runner.run(initWorkflow)
79+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# ==========================================================================
2+
# CRE WORKFLOW SETTINGS FILE
3+
# ==========================================================================
4+
# This file defines environment-specific workflow settings used by the CRE CLI.
5+
#
6+
# Each top-level key is a target (e.g., `production`, `production-testnet`, etc.).
7+
# You can also define your own custom targets, such as `my-target`, and
8+
# point the CLI to it via an environment variable.
9+
#
10+
# Note: If any setting in this file conflicts with a setting in the CRE Project Settings File,
11+
# the value defined here in the workflow settings file will take precedence.
12+
#
13+
# Below is an example `my-target`:
14+
#
15+
# my-target:
16+
# user-workflow:
17+
# # Optional: The address of the workflow owner (wallet or MSIG contract).
18+
# # Used to establish ownership for encrypting the workflow's secrets.
19+
# # If omitted, defaults to an empty string.
20+
# workflow-owner-address: "0x1234567890abcdef1234567890abcdef12345678"
21+
#
22+
# # Required: The name of the workflow to register with the Workflow Registry contract.
23+
# workflow-name: "MyExampleWorkflow"
24+
25+
# ==========================================================================
26+
local-simulation:
27+
user-workflow:
28+
workflow-owner-address: "(optional) Multi-signature contract address"
29+
workflow-name: "confidential-http-with-body"
30+
workflow-artifacts:
31+
workflow-path: "./index.ts"
32+
config-path: "./config.json"
33+
34+
# ==========================================================================
35+
production-testnet:
36+
user-workflow:
37+
workflow-owner-address: "(optional) Multi-signature contract address"
38+
workflow-name: "confidential-http-with-body"

packages/cre-sdk/src/generated-sdk/capabilities/blockchain/evm/v1alpha/client_sdk_gen.ts

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import type { Runtime } from '@cre/sdk'
5959
import { Report } from '@cre/sdk/report'
6060
import { hexToBytes } from '@cre/sdk/utils/hex-utils'
6161
import type { Trigger } from '@cre/sdk/utils/triggers/trigger-interface'
62+
import type { CapabilityInput, NoExcess } from '@cre/sdk/utils/types/no-excess'
6263

6364
export type WriteCreReportRequest = {
6465
receiver: Uint8Array
@@ -176,6 +177,10 @@ export class ClientCapability {
176177

177178
constructor(private readonly ChainSelector: bigint) {}
178179

180+
callContract<TInput>(
181+
runtime: Runtime<unknown>,
182+
input: CapabilityInput<TInput, CallContractRequest, CallContractRequestJson>,
183+
): { result: () => CallContractReply }
179184
callContract(
180185
runtime: Runtime<unknown>,
181186
input: CallContractRequest | CallContractRequestJson,
@@ -211,6 +216,10 @@ export class ClientCapability {
211216
}
212217
}
213218

219+
filterLogs<TInput>(
220+
runtime: Runtime<unknown>,
221+
input: CapabilityInput<TInput, FilterLogsRequest, FilterLogsRequestJson>,
222+
): { result: () => FilterLogsReply }
214223
filterLogs(
215224
runtime: Runtime<unknown>,
216225
input: FilterLogsRequest | FilterLogsRequestJson,
@@ -246,6 +255,10 @@ export class ClientCapability {
246255
}
247256
}
248257

258+
balanceAt<TInput>(
259+
runtime: Runtime<unknown>,
260+
input: CapabilityInput<TInput, BalanceAtRequest, BalanceAtRequestJson>,
261+
): { result: () => BalanceAtReply }
249262
balanceAt(
250263
runtime: Runtime<unknown>,
251264
input: BalanceAtRequest | BalanceAtRequestJson,
@@ -281,6 +294,10 @@ export class ClientCapability {
281294
}
282295
}
283296

297+
estimateGas<TInput>(
298+
runtime: Runtime<unknown>,
299+
input: CapabilityInput<TInput, EstimateGasRequest, EstimateGasRequestJson>,
300+
): { result: () => EstimateGasReply }
284301
estimateGas(
285302
runtime: Runtime<unknown>,
286303
input: EstimateGasRequest | EstimateGasRequestJson,
@@ -316,6 +333,10 @@ export class ClientCapability {
316333
}
317334
}
318335

336+
getTransactionByHash<TInput>(
337+
runtime: Runtime<unknown>,
338+
input: CapabilityInput<TInput, GetTransactionByHashRequest, GetTransactionByHashRequestJson>,
339+
): { result: () => GetTransactionByHashReply }
319340
getTransactionByHash(
320341
runtime: Runtime<unknown>,
321342
input: GetTransactionByHashRequest | GetTransactionByHashRequestJson,
@@ -357,6 +378,10 @@ export class ClientCapability {
357378
}
358379
}
359380

381+
getTransactionReceipt<TInput>(
382+
runtime: Runtime<unknown>,
383+
input: CapabilityInput<TInput, GetTransactionReceiptRequest, GetTransactionReceiptRequestJson>,
384+
): { result: () => GetTransactionReceiptReply }
360385
getTransactionReceipt(
361386
runtime: Runtime<unknown>,
362387
input: GetTransactionReceiptRequest | GetTransactionReceiptRequestJson,
@@ -398,6 +423,10 @@ export class ClientCapability {
398423
}
399424
}
400425

426+
headerByNumber<TInput>(
427+
runtime: Runtime<unknown>,
428+
input: CapabilityInput<TInput, HeaderByNumberRequest, HeaderByNumberRequestJson>,
429+
): { result: () => HeaderByNumberReply }
401430
headerByNumber(
402431
runtime: Runtime<unknown>,
403432
input: HeaderByNumberRequest | HeaderByNumberRequestJson,
@@ -433,12 +462,23 @@ export class ClientCapability {
433462
}
434463
}
435464

436-
logTrigger(config: FilterLogTriggerRequestJson): ClientLogTrigger {
465+
logTrigger<TConfig extends FilterLogTriggerRequestJson>(
466+
config: NoExcess<TConfig, FilterLogTriggerRequestJson>,
467+
): ClientLogTrigger {
437468
// Include all labels in capability ID for routing when specified
438469
const capabilityId = `${ClientCapability.CAPABILITY_NAME}:ChainSelector:${this.ChainSelector}@${ClientCapability.CAPABILITY_VERSION}`
439-
return new ClientLogTrigger(config, capabilityId, 'LogTrigger', this.ChainSelector)
470+
return new ClientLogTrigger(
471+
config as FilterLogTriggerRequestJson,
472+
capabilityId,
473+
'LogTrigger',
474+
this.ChainSelector,
475+
)
440476
}
441477

478+
writeReport<TInput>(
479+
runtime: Runtime<unknown>,
480+
input: CapabilityInput<TInput, WriteCreReportRequest, WriteCreReportRequestJson>,
481+
): { result: () => WriteReportReply }
442482
writeReport(
443483
runtime: Runtime<unknown>,
444484
input: WriteCreReportRequest | WriteCreReportRequestJson,

packages/cre-sdk/src/generated-sdk/capabilities/internal/actionandtrigger/v1/basic_sdk_gen.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import type { Runtime } from '@cre/sdk'
1616
import { Report } from '@cre/sdk/report'
1717
import { hexToBytes } from '@cre/sdk/utils/hex-utils'
1818
import type { Trigger } from '@cre/sdk/utils/triggers/trigger-interface'
19+
import type { CapabilityInput, NoExcess } from '@cre/sdk/utils/types/no-excess'
1920

2021
/**
2122
* Basic Capability
@@ -31,6 +32,10 @@ export class BasicCapability {
3132
static readonly CAPABILITY_NAME = 'basic-test-action-trigger'
3233
static readonly CAPABILITY_VERSION = '1.0.0'
3334

35+
action<TInput>(
36+
runtime: Runtime<unknown>,
37+
input: CapabilityInput<TInput, Input, InputJson>,
38+
): { result: () => Output }
3439
action(runtime: Runtime<unknown>, input: Input | InputJson): { result: () => Output } {
3540
// Handle input conversion - unwrap if it's a wrapped type, convert from JSON if needed
3641
let payload: Input
@@ -62,9 +67,9 @@ export class BasicCapability {
6267
}
6368
}
6469

65-
trigger(config: ConfigJson): BasicTrigger {
70+
trigger<TConfig extends ConfigJson>(config: NoExcess<TConfig, ConfigJson>): BasicTrigger {
6671
const capabilityId = BasicCapability.CAPABILITY_ID
67-
return new BasicTrigger(config, capabilityId, 'Trigger')
72+
return new BasicTrigger(config as ConfigJson, capabilityId, 'Trigger')
6873
}
6974
}
7075

packages/cre-sdk/src/generated-sdk/capabilities/internal/basicaction/v1/basicaction_sdk_gen.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
import type { Runtime } from '@cre/sdk'
1010
import { Report } from '@cre/sdk/report'
1111
import { hexToBytes } from '@cre/sdk/utils/hex-utils'
12+
import type { CapabilityInput } from '@cre/sdk/utils/types/no-excess'
1213

1314
/**
1415
* BasicAction Capability
@@ -24,6 +25,10 @@ export class BasicActionCapability {
2425
static readonly CAPABILITY_NAME = 'basic-test-action'
2526
static readonly CAPABILITY_VERSION = '1.0.0'
2627

28+
performAction<TInput>(
29+
runtime: Runtime<unknown>,
30+
input: CapabilityInput<TInput, Inputs, InputsJson>,
31+
): { result: () => Outputs }
2732
performAction(runtime: Runtime<unknown>, input: Inputs | InputsJson): { result: () => Outputs } {
2833
// Handle input conversion - unwrap if it's a wrapped type, convert from JSON if needed
2934
let payload: Inputs

packages/cre-sdk/src/generated-sdk/capabilities/internal/basictrigger/v1/basic_sdk_gen.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
OutputsSchema,
99
} from '@cre/generated/capabilities/internal/basictrigger/v1/basic_trigger_pb'
1010
import type { Trigger } from '@cre/sdk/utils/triggers/trigger-interface'
11+
import type { NoExcess } from '@cre/sdk/utils/types/no-excess'
1112

1213
/**
1314
* Basic Capability
@@ -23,9 +24,9 @@ export class BasicCapability {
2324
static readonly CAPABILITY_NAME = 'basic-test-trigger'
2425
static readonly CAPABILITY_VERSION = '1.0.0'
2526

26-
trigger(config: ConfigJson): BasicTrigger {
27+
trigger<TConfig extends ConfigJson>(config: NoExcess<TConfig, ConfigJson>): BasicTrigger {
2728
const capabilityId = BasicCapability.CAPABILITY_ID
28-
return new BasicTrigger(config, capabilityId, 'Trigger')
29+
return new BasicTrigger(config as ConfigJson, capabilityId, 'Trigger')
2930
}
3031
}
3132

packages/cre-sdk/src/generated-sdk/capabilities/internal/consensus/v1alpha/consensus_sdk_gen.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { type Value, ValueSchema } from '@cre/generated/values/v1/values_pb'
1313
import type { Runtime } from '@cre/sdk'
1414
import { Report } from '@cre/sdk/report'
1515
import { hexToBytes } from '@cre/sdk/utils/hex-utils'
16+
import type { CapabilityInput } from '@cre/sdk/utils/types/no-excess'
1617

1718
/**
1819
* Consensus Capability
@@ -28,6 +29,10 @@ export class ConsensusCapability {
2829
static readonly CAPABILITY_NAME = 'consensus'
2930
static readonly CAPABILITY_VERSION = '1.0.0-alpha'
3031

32+
simple<TInput>(
33+
runtime: Runtime<unknown>,
34+
input: CapabilityInput<TInput, SimpleConsensusInputs, SimpleConsensusInputsJson>,
35+
): { result: () => Value }
3136
simple(
3237
runtime: Runtime<unknown>,
3338
input: SimpleConsensusInputs | SimpleConsensusInputsJson,
@@ -62,6 +67,10 @@ export class ConsensusCapability {
6267
}
6368
}
6469

70+
report<TInput>(
71+
runtime: Runtime<unknown>,
72+
input: CapabilityInput<TInput, ReportRequest, ReportRequestJson>,
73+
): { result: () => Report }
6574
report(
6675
runtime: Runtime<unknown>,
6776
input: ReportRequest | ReportRequestJson,

packages/cre-sdk/src/generated-sdk/capabilities/internal/nodeaction/v1/basicaction_sdk_gen.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,17 @@ import {
99
import type { NodeRuntime, Runtime } from '@cre/sdk'
1010
import { Report } from '@cre/sdk/report'
1111
import type { ConsensusAggregation, PrimitiveTypes, UnwrapOptions } from '@cre/sdk/utils'
12+
import type { CapabilityInput } from '@cre/sdk/utils/types/no-excess'
1213

1314
export class PerformActioner {
1415
constructor(
1516
private readonly runtime: NodeRuntime<unknown>,
1617
private readonly client: BasicActionCapability,
1718
) {}
18-
performAction(input: NodeInputs | NodeInputsJson): { result: () => NodeOutputs } {
19-
return this.client.performAction(this.runtime, input)
19+
performAction<TInput>(input: CapabilityInput<TInput, NodeInputs, NodeInputsJson>): {
20+
result: () => NodeOutputs
21+
} {
22+
return this.client.performAction<TInput>(this.runtime, input)
2023
}
2124
}
2225

@@ -34,9 +37,9 @@ export class BasicActionCapability {
3437
static readonly CAPABILITY_NAME = 'basic-test-node-action'
3538
static readonly CAPABILITY_VERSION = '1.0.0'
3639

37-
performAction(
40+
performAction<TInput>(
3841
runtime: NodeRuntime<unknown>,
39-
input: NodeInputs | NodeInputsJson,
42+
input: CapabilityInput<TInput, NodeInputs, NodeInputsJson>,
4043
): { result: () => NodeOutputs }
4144
performAction<TArgs extends unknown[], TOutput>(
4245
runtime: Runtime<unknown>,

0 commit comments

Comments
 (0)