@chainlink/cre-sdk 1.6.0 → 1.7.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -10,6 +10,11 @@ export declare class SecretsError extends Error {
10
10
  error: string;
11
11
  constructor(secretRequest: SecretRequest, error: string);
12
12
  }
13
+ export declare class SecretsBatchError extends Error {
14
+ readonly secretRequests: SecretRequest[];
15
+ readonly error: string;
16
+ constructor(secretRequests: SecretRequest[], error: string);
17
+ }
13
18
  export declare class NullReportError extends Error {
14
19
  constructor();
15
20
  }
@@ -20,6 +20,16 @@ export class SecretsError extends Error {
20
20
  this.name = 'SecretsError';
21
21
  }
22
22
  }
23
+ export class SecretsBatchError extends Error {
24
+ secretRequests;
25
+ error;
26
+ constructor(secretRequests, error) {
27
+ super(`batch secret retrieval failed for ${secretRequests.length} request(s): ${error}. Verify the host response is complete and that the workflow has access to the requested secrets`);
28
+ this.secretRequests = secretRequests;
29
+ this.error = error;
30
+ this.name = 'SecretsBatchError';
31
+ }
32
+ }
23
33
  export class NullReportError extends Error {
24
34
  constructor() {
25
35
  super('null report');
@@ -1,5 +1,5 @@
1
1
  import { type Message } from '@bufbuild/protobuf';
2
- import { type AwaitCapabilitiesRequest, type AwaitCapabilitiesResponse, type AwaitSecretsRequest, type AwaitSecretsResponse, type CapabilityRequest, type GetSecretsRequest, Mode, type Secret, type SecretRequest, type SecretRequestJson } from '../../generated/sdk/v1alpha/sdk_pb';
2
+ import { type AwaitCapabilitiesRequest, type AwaitCapabilitiesResponse, type AwaitSecretsRequest, type AwaitSecretsResponse, type CapabilityRequest, type GetSecretsRequest, Mode, type Secret, type SecretRequest, type SecretRequestJson, type SecretResponse } from '../../generated/sdk/v1alpha/sdk_pb';
3
3
  import type { BaseRuntime, CallCapabilityParams, NodeRuntime, ReportRequest, ReportRequestJson, Runtime } from '..';
4
4
  import type { Report } from '../report';
5
5
  import { type ConsensusAggregation, type PrimitiveTypes, type UnwrapOptions } from '../utils';
@@ -82,10 +82,14 @@ export declare class RuntimeImpl<C> extends BaseRuntimeImpl<C> implements Runtim
82
82
  private captureError;
83
83
  private restoreDonMode;
84
84
  private runConsensusAndWrap;
85
+ getSecrets(requests: Array<SecretRequest | SecretRequestJson>): {
86
+ result: () => SecretResponse[];
87
+ };
85
88
  getSecret(request: SecretRequest | SecretRequestJson): {
86
89
  result: () => Secret;
87
90
  };
88
- private awaitAndUnwrapSecret;
91
+ private awaitAndUnwrapSecrets;
92
+ private unwrapSingleSecretResult;
89
93
  /**
90
94
  * Generates a report via consensus mechanism.
91
95
  */
@@ -102,8 +106,8 @@ export interface RuntimeHelpers {
102
106
  call(request: CapabilityRequest): boolean;
103
107
  /** Awaits capability responses. Blocks until responses are ready. */
104
108
  await(request: AwaitCapabilitiesRequest, maxResponseSize: bigint): AwaitCapabilitiesResponse;
105
- /** Requests secrets from host. Returns false if host rejects request. */
106
- getSecrets(request: GetSecretsRequest, maxResponseSize: bigint): boolean;
109
+ /** Requests secrets from host. Throws if host rejects the request. */
110
+ getSecrets(request: GetSecretsRequest, maxResponseSize: bigint): void;
107
111
  /** Awaits secret responses. Blocks until secrets are ready. */
108
112
  awaitSecrets(request: AwaitSecretsRequest, maxResponseSize: bigint): AwaitSecretsResponse;
109
113
  /** Switches execution mode (DON vs Node). Affects available operations. */
@@ -4,7 +4,7 @@ import { AwaitCapabilitiesRequestSchema, AwaitSecretsRequestSchema, CapabilityRe
4
4
  import { ConsensusCapability } from '../../generated-sdk/capabilities/internal/consensus/v1alpha/consensus_sdk_gen';
5
5
  import { Value, } from '../utils';
6
6
  import { CapabilityError } from '../utils/capabilities/capability-error';
7
- import { DonModeError, NodeModeError, SecretsError } from '../errors';
7
+ import { DonModeError, NodeModeError, SecretsBatchError, SecretsError } from '../errors';
8
8
  /**
9
9
  * Base implementation shared by DON and Node runtimes.
10
10
  *
@@ -245,7 +245,7 @@ export class RuntimeImpl extends BaseRuntimeImpl {
245
245
  },
246
246
  };
247
247
  }
248
- getSecret(request) {
248
+ getSecrets(requests) {
249
249
  // Enforce mode restrictions
250
250
  if (this.modeError) {
251
251
  return {
@@ -254,48 +254,90 @@ export class RuntimeImpl extends BaseRuntimeImpl {
254
254
  },
255
255
  };
256
256
  }
257
- // Normalize request (accept both protobuf and JSON formats)
258
- const secretRequest = request.$typeName
257
+ // Normalize requests (accept both protobuf and JSON formats)
258
+ const normalizedRequests = requests.map((request) => request.$typeName
259
259
  ? request
260
- : create(SecretRequestSchema, request);
260
+ : create(SecretRequestSchema, request));
261
+ if (normalizedRequests.length === 0) {
262
+ return {
263
+ result: () => [],
264
+ };
265
+ }
261
266
  // Allocate callback ID and send request
262
267
  const id = this.nextCallId;
263
268
  this.nextCallId++;
264
269
  const secretsReq = create(GetSecretsRequestSchema, {
265
270
  callbackId: id,
266
- requests: [secretRequest],
271
+ requests: normalizedRequests,
267
272
  });
268
- if (!this.helpers.getSecrets(secretsReq, this.maxResponseSize)) {
273
+ try {
274
+ this.helpers.getSecrets(secretsReq, this.maxResponseSize);
275
+ }
276
+ catch (err) {
277
+ const message = err instanceof Error ? err.message : String(err);
269
278
  return {
270
279
  result: () => {
271
- throw new SecretsError(secretRequest, 'host is not making the secrets request');
280
+ throw new SecretsBatchError(normalizedRequests, message);
272
281
  },
273
282
  };
274
283
  }
275
284
  // Return lazy result
276
285
  return {
277
- result: () => this.awaitAndUnwrapSecret(id, secretRequest),
286
+ result: () => this.awaitAndUnwrapSecrets(id, normalizedRequests),
278
287
  };
279
288
  }
280
- awaitAndUnwrapSecret(id, secretRequest) {
289
+ getSecret(request) {
290
+ const secretRequest = request.$typeName
291
+ ? request
292
+ : create(SecretRequestSchema, request);
293
+ const getSecretsCall = this.getSecrets([secretRequest]);
294
+ return {
295
+ result: () => {
296
+ let responseList;
297
+ try {
298
+ responseList = getSecretsCall.result();
299
+ }
300
+ catch (err) {
301
+ if (err instanceof SecretsBatchError) {
302
+ throw new SecretsError(secretRequest, err.error);
303
+ }
304
+ throw err;
305
+ }
306
+ return this.unwrapSingleSecretResult(responseList, secretRequest);
307
+ },
308
+ };
309
+ }
310
+ awaitAndUnwrapSecrets(id, requests) {
281
311
  const awaitRequest = create(AwaitSecretsRequestSchema, { ids: [id] });
282
- const awaitResponse = this.helpers.awaitSecrets(awaitRequest, this.maxResponseSize);
312
+ let awaitResponse;
313
+ try {
314
+ awaitResponse = this.helpers.awaitSecrets(awaitRequest, this.maxResponseSize);
315
+ }
316
+ catch (err) {
317
+ const message = err instanceof Error ? err.message : String(err);
318
+ throw new SecretsBatchError(requests, message);
319
+ }
283
320
  const secretsResponse = awaitResponse.responses[id];
284
321
  if (!secretsResponse) {
285
- throw new SecretsError(secretRequest, 'no response');
322
+ throw new SecretsBatchError(requests, 'no response');
286
323
  }
287
- const responses = secretsResponse.responses;
288
- if (responses.length !== 1) {
289
- throw new SecretsError(secretRequest, 'invalid value returned from host');
324
+ if (secretsResponse.responses.length !== requests.length) {
325
+ throw new SecretsBatchError(requests, 'invalid value returned from host');
326
+ }
327
+ return secretsResponse.responses;
328
+ }
329
+ unwrapSingleSecretResult(responseList, request) {
330
+ if (responseList.length !== 1) {
331
+ throw new SecretsError(request, 'invalid value returned from host');
290
332
  }
291
- const response = responses[0].response;
333
+ const response = responseList[0].response;
292
334
  switch (response.case) {
293
335
  case 'secret':
294
336
  return response.value;
295
337
  case 'error':
296
- throw new SecretsError(secretRequest, response.value.error);
338
+ throw new SecretsError(request, response.value.error);
297
339
  default:
298
- throw new SecretsError(secretRequest, 'cannot unmarshal returned value from host');
340
+ throw new SecretsError(request, 'cannot unmarshal returned value from host');
299
341
  }
300
342
  }
301
343
  /**
@@ -217,7 +217,6 @@ function createTestRuntimeHelpers(registry, secrets, testWriter, state, _maxResp
217
217
  }
218
218
  }
219
219
  pendingSecrets.set(req.callbackId, resp);
220
- return true;
221
220
  },
222
221
  awaitSecrets(request, _maxResponseSize) {
223
222
  const responses = {};
@@ -41,6 +41,7 @@ export class Runner {
41
41
  let result;
42
42
  try {
43
43
  const workflow = await initFn(this.config, {
44
+ getSecrets: runtime.getSecrets.bind(runtime),
44
45
  getSecret: runtime.getSecret.bind(runtime),
45
46
  });
46
47
  switch (this.request.request.case) {
@@ -42,7 +42,7 @@ class WasmRuntimeHelpers {
42
42
  }
43
43
  getSecrets(request, maxResponseSize) {
44
44
  const responseSize = toI32ResponseSize(maxResponseSize);
45
- return hostBindings.getSecrets(toBinary(GetSecretsRequestSchema, request), responseSize) >= 0;
45
+ hostBindings.getSecrets(toBinary(GetSecretsRequestSchema, request), responseSize);
46
46
  }
47
47
  awaitSecrets(request, maxResponseSize) {
48
48
  const responseSize = toI32ResponseSize(maxResponseSize);
@@ -1,6 +1,6 @@
1
1
  import type { Message } from '@bufbuild/protobuf';
2
- import type { Secret, SecretRequest, SecretRequestJson } from '../generated/sdk/v1alpha/sdk_pb';
3
- import { type Runtime } from './runtime';
2
+ import type { Secret, SecretRequest, SecretRequestJson, SecretResponse } from '../generated/sdk/v1alpha/sdk_pb';
3
+ import type { Runtime } from './runtime';
4
4
  import type { Trigger } from './utils/triggers/trigger-interface';
5
5
  import type { CreSerializable } from './utils';
6
6
  export type HandlerFn<TConfig, TTriggerOutput, TResult> = (runtime: Runtime<TConfig>, triggerOutput: TTriggerOutput) => Promise<CreSerializable<TResult>> | CreSerializable<TResult>;
@@ -11,6 +11,9 @@ export interface HandlerEntry<TConfig, TRawTriggerOutput extends Message<string>
11
11
  export type Workflow<TConfig> = ReadonlyArray<HandlerEntry<TConfig, any, any, any>>;
12
12
  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>;
13
13
  export type SecretsProvider = {
14
+ getSecrets(requests: Array<SecretRequest | SecretRequestJson>): {
15
+ result: () => SecretResponse[];
16
+ };
14
17
  getSecret(request: SecretRequest | SecretRequestJson): {
15
18
  result: () => Secret;
16
19
  };
@@ -1,4 +1,3 @@
1
- import {} from './runtime';
2
1
  export const handler = (trigger, fn) => ({
3
2
  trigger,
4
3
  fn,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chainlink/cre-sdk",
3
- "version": "1.6.0",
3
+ "version": "1.7.0-alpha.1",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,3 +0,0 @@
1
- export declare class SecretsError extends Error {
2
- constructor(message: string);
3
- }
@@ -1,6 +0,0 @@
1
- export class SecretsError extends Error {
2
- constructor(message) {
3
- super(message);
4
- this.name = 'SecretsError';
5
- }
6
- }