@steerprotocol/data-connector-loader 4.0.2 → 4.1.0

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.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## Public API
4
4
 
5
- - `ExecutionAppConfig`: Configuration object for `ExecutionApp` (vault, chainId, subgraph URL, pool type flags, API keys, retries).
5
+ - `ExecutionAppConfig`: Configuration object for `ExecutionApp`. The legacy `poolType` flags are retained for compatibility only.
6
6
  - `ExecutionApp`: High-level execution entrypoint for running bundles with a config-based constructor.
7
7
  - `DataConnectorExecution`: Executes data connector bundles and handles request/response flow.
8
8
 
@@ -21,3 +21,38 @@ pnpm add @steerprotocol/data-connector-loader
21
21
  ## ESM Support
22
22
 
23
23
  This package publishes both CommonJS and ESM entrypoints via `exports`.
24
+
25
+ ## Block-pinned strategy execution (recommended)
26
+
27
+ Resolve the vault context with `@steerprotocol/sdk` 3.3+ and pass its successful
28
+ `VaultExecutionContext` straight to `executeWithContext`. This path makes no
29
+ pool, vault, subgraph, latest-block, average-block-time, or wall-clock reads.
30
+ Uniswap v3-compatible, Algebra Integral, Aerodrome CL, and normalized Uniswap
31
+ v4 contexts are supported. PoolShark remains unsupported by the SDK context API.
32
+
33
+ ```ts
34
+ import { ExecutionApp } from '@steerprotocol/data-connector-loader';
35
+ import { getVaultExecutionContext } from '@steerprotocol/sdk';
36
+
37
+ const response = await getVaultExecutionContext({ publicClient, vaultAddress, blockNumber, epochTimestamp });
38
+ if (!response.success || !response.data) throw new Error(response.error ?? 'Context resolution failed');
39
+
40
+ const app = new ExecutionApp(legacyCompatibleConfig);
41
+ const actions = await app.executeWithContext({
42
+ wasmFile: strategyWasmBytes,
43
+ vaultConfig: JSON.stringify({ vaultAddress, anchorBlockNumber: Number(blockNumber), strategyConfigData: { epochLength: '3600' } }),
44
+ data: connectorOutputs,
45
+ executionContext: response.data,
46
+ });
47
+ ```
48
+
49
+ `vaultConfig` must include `vaultAddress`, `anchorBlockNumber`, and
50
+ `strategyConfigData.epochLength`. Positions are translated at the WASM boundary
51
+ from SDK `lowerTick`/`upperTick`/`relativeWeight` to
52
+ `startTick`/`endTick`/`weight`; totals remain decimal strings. If SDK reports no
53
+ last execution, WASM receives `lastExecutionTime: 0` (deterministic, no
54
+ wall-clock fallback). Errors are `ExecutionContextError`
55
+ (`INVALID_EXECUTION_CONTEXT` or `EXECUTION_CONTEXT_MISMATCH`) and
56
+ `StrategyExecutionError` (`STRATEGY_EXECUTION_ERROR`); neither is retryable
57
+ until its input or strategy failure is corrected. External connector HTTP data
58
+ remains external and unpinned.
@@ -25,7 +25,14 @@ export declare class BundleBase {
25
25
  executeDynamicJobBundle(data: Array<any>): Promise<string>;
26
26
  reset(): void;
27
27
  setExecutionContextStrategyExecution(executionContext: ExecutionContext, forceDeposit?: boolean): void;
28
+ /**
29
+ * Initializes a strategy from an already resolved SDK context. Unlike the
30
+ * legacy setter this deliberately does not derive a timestamp or block.
31
+ */
32
+ setExecutionContextStrategyExecutionPinned(executionContext: ExecutionContext, forceDeposit?: boolean): void;
28
33
  setExecutionContextDataConnector(executionContext: ExecutionContext): void;
34
+ /** Initializes a data connector with an immutable SDK anchor. */
35
+ setExecutionContextDataConnectorPinned(executionContext: ExecutionContext): void;
29
36
  protected executeModule(response: string): Promise<string | null>;
30
37
  protected executeModuleWithResult(...params: Array<number | string | ArrayBuffer | null>): Promise<string | null>;
31
38
  getProvider(config: any): ethers.Provider | undefined;
@@ -173,6 +173,20 @@ class BundleBase {
173
173
  }
174
174
  (_a = this.module) === null || _a === void 0 ? void 0 : _a.initialize(JSON.stringify(completeConfig, bigIntReplacer));
175
175
  }
176
+ /**
177
+ * Initializes a strategy from an already resolved SDK context. Unlike the
178
+ * legacy setter this deliberately does not derive a timestamp or block.
179
+ */
180
+ setExecutionContextStrategyExecutionPinned(executionContext, forceDeposit) {
181
+ var _a;
182
+ this.executionContext = executionContext;
183
+ this.scheduleEpochTimestamp = executionContext.epochTimestamp;
184
+ const completeConfig = Object.assign(Object.assign({}, JSON.parse(this.config)), executionContext);
185
+ if (completeConfig.triggerStyle && forceDeposit === true) {
186
+ completeConfig.triggerStyle = 'None';
187
+ }
188
+ (_a = this.module) === null || _a === void 0 ? void 0 : _a.initialize(JSON.stringify(completeConfig, bigIntReplacer));
189
+ }
176
190
  setExecutionContextDataConnector(executionContext) {
177
191
  var _a;
178
192
  // Determine the timestamp for epoch
@@ -184,6 +198,14 @@ class BundleBase {
184
198
  this.scheduleEpochTimestamp = executionContext.epochTimestamp;
185
199
  (_a = this.module) === null || _a === void 0 ? void 0 : _a.initialize(JSON.stringify(completeConfig, bigIntReplacer));
186
200
  }
201
+ /** Initializes a data connector with an immutable SDK anchor. */
202
+ setExecutionContextDataConnectorPinned(executionContext) {
203
+ var _a;
204
+ this.executionContext = executionContext;
205
+ this.scheduleEpochTimestamp = executionContext.epochTimestamp;
206
+ const completeConfig = Object.assign(Object.assign({}, JSON.parse(this.config)), { executionContext });
207
+ (_a = this.module) === null || _a === void 0 ? void 0 : _a.initialize(JSON.stringify(completeConfig, bigIntReplacer));
208
+ }
187
209
  executeModule(response) {
188
210
  return __awaiter(this, void 0, void 0, function* () {
189
211
  if (!this.module) {
@@ -39,7 +39,7 @@ class DataConnector extends bundleBase_js_1.BundleBase {
39
39
  }
40
40
  // Makes contract instance and calls, returns stringified result
41
41
  view(config) {
42
- var _a;
42
+ var _a, _b;
43
43
  return __awaiter(this, void 0, void 0, function* () {
44
44
  const provider = this.getProvider(config);
45
45
  if (!provider)
@@ -55,6 +55,7 @@ class DataConnector extends bundleBase_js_1.BundleBase {
55
55
  else {
56
56
  const viewContractConfig = {
57
57
  epochTimestamp: this.scheduleEpochTimestamp,
58
+ blockNumber: (_b = this.executionContext) === null || _b === void 0 ? void 0 : _b.blockNumber,
58
59
  address: this.configObj.address || config.address,
59
60
  abi: config.abi,
60
61
  arguments: paramsArray,
@@ -25,7 +25,14 @@ export declare class BundleBase {
25
25
  executeDynamicJobBundle(data: Array<any>): Promise<string>;
26
26
  reset(): void;
27
27
  setExecutionContextStrategyExecution(executionContext: ExecutionContext, forceDeposit?: boolean): void;
28
+ /**
29
+ * Initializes a strategy from an already resolved SDK context. Unlike the
30
+ * legacy setter this deliberately does not derive a timestamp or block.
31
+ */
32
+ setExecutionContextStrategyExecutionPinned(executionContext: ExecutionContext, forceDeposit?: boolean): void;
28
33
  setExecutionContextDataConnector(executionContext: ExecutionContext): void;
34
+ /** Initializes a data connector with an immutable SDK anchor. */
35
+ setExecutionContextDataConnectorPinned(executionContext: ExecutionContext): void;
29
36
  protected executeModule(response: string): Promise<string | null>;
30
37
  protected executeModuleWithResult(...params: Array<number | string | ArrayBuffer | null>): Promise<string | null>;
31
38
  getProvider(config: any): ethers.Provider | undefined;
@@ -150,6 +150,19 @@ export class BundleBase {
150
150
  }
151
151
  this.module?.initialize(JSON.stringify(completeConfig, bigIntReplacer));
152
152
  }
153
+ /**
154
+ * Initializes a strategy from an already resolved SDK context. Unlike the
155
+ * legacy setter this deliberately does not derive a timestamp or block.
156
+ */
157
+ setExecutionContextStrategyExecutionPinned(executionContext, forceDeposit) {
158
+ this.executionContext = executionContext;
159
+ this.scheduleEpochTimestamp = executionContext.epochTimestamp;
160
+ const completeConfig = { ...JSON.parse(this.config), ...executionContext };
161
+ if (completeConfig.triggerStyle && forceDeposit === true) {
162
+ completeConfig.triggerStyle = 'None';
163
+ }
164
+ this.module?.initialize(JSON.stringify(completeConfig, bigIntReplacer));
165
+ }
153
166
  setExecutionContextDataConnector(executionContext) {
154
167
  // Determine the timestamp for epoch
155
168
  const timestamp = this.subtractDate(executionContext.executionTimestamp, Number(executionContext.epochLength)).getTime();
@@ -160,6 +173,13 @@ export class BundleBase {
160
173
  this.scheduleEpochTimestamp = executionContext.epochTimestamp;
161
174
  this.module?.initialize(JSON.stringify(completeConfig, bigIntReplacer));
162
175
  }
176
+ /** Initializes a data connector with an immutable SDK anchor. */
177
+ setExecutionContextDataConnectorPinned(executionContext) {
178
+ this.executionContext = executionContext;
179
+ this.scheduleEpochTimestamp = executionContext.epochTimestamp;
180
+ const completeConfig = { ...JSON.parse(this.config), executionContext };
181
+ this.module?.initialize(JSON.stringify(completeConfig, bigIntReplacer));
182
+ }
163
183
  async executeModule(response) {
164
184
  if (!this.module) {
165
185
  throw new Error('Module not initialized');
@@ -41,6 +41,7 @@ export class DataConnector extends BundleBase {
41
41
  else {
42
42
  const viewContractConfig = {
43
43
  epochTimestamp: this.scheduleEpochTimestamp,
44
+ blockNumber: this.executionContext?.blockNumber,
44
45
  address: this.configObj.address || config.address,
45
46
  abi: config.abi,
46
47
  arguments: paramsArray,
@@ -1,5 +1,5 @@
1
1
  import type { ethers } from 'ethers';
2
- import type { EtherRpcConfig, JobDetails } from '../types.js';
2
+ import type { EtherRpcConfig, ExecuteWithContextOptions, JobDetails } from '../types.js';
3
3
  import { ExecutionBase } from './executionBase.js';
4
4
  export interface ExecutionAppConfig {
5
5
  /** Vault address used for execution context and subgraph queries. */
@@ -43,6 +43,15 @@ export declare class ExecutionApp extends ExecutionBase {
43
43
  config: ExecutionAppConfig;
44
44
  constructor(config: ExecutionAppConfig);
45
45
  execute<T>(_wasmFile: string | ArrayBuffer, _vaultConfig: string, _data: Array<any>, _identity?: ethers.Provider, _etherRpcConfig?: EtherRpcConfig, forceDeposit?: boolean): Promise<Array<T>>;
46
+ /**
47
+ * Executes a strategy against the immutable context resolved by SDK 3.3+.
48
+ * This is the recommended API for new consumers. It intentionally bypasses
49
+ * all legacy vault, pool, subgraph, clock, and block-estimation reads.
50
+ */
51
+ executeWithContext<T>(options: ExecuteWithContextOptions): Promise<Array<T>>;
52
+ private parseVaultConfig;
53
+ private mapSdkExecutionContext;
54
+ private redactError;
46
55
  executeStabilityVault<T>(_wasmFile: string | ArrayBuffer, _vaultConfig: string, _data: Array<any>, _identity?: ethers.Provider, _etherRpcConfig?: EtherRpcConfig, forceDeposit?: boolean): Promise<Array<T>>;
47
56
  executeDynamicJobs<T>(_wasmFile: string | ArrayBuffer, _vaultConfig: string, _data: Array<any>, _job: JobDetails, _identity?: ethers.Provider, _etherRpcConfig?: EtherRpcConfig, forceDeposit?: boolean): Promise<Array<T>>;
48
57
  private getSmartPoolExecutionContext;
@@ -1,4 +1,5 @@
1
1
  import { DataConnector } from '../bundle/bundleDataConnector.js';
2
+ import { ExecutionContextError, StrategyExecutionError } from '../types.js';
2
3
  import { fetchData, readContract } from '../utils/utils.js';
3
4
  import { ExecutionBase } from './executionBase.js';
4
5
  export class ExecutionApp extends ExecutionBase {
@@ -484,6 +485,117 @@ export class ExecutionApp extends ExecutionBase {
484
485
  const result = await dataConnector.executeBundle(_data);
485
486
  return JSON.parse(result);
486
487
  }
488
+ /**
489
+ * Executes a strategy against the immutable context resolved by SDK 3.3+.
490
+ * This is the recommended API for new consumers. It intentionally bypasses
491
+ * all legacy vault, pool, subgraph, clock, and block-estimation reads.
492
+ */
493
+ async executeWithContext(options) {
494
+ const vaultConfig = this.parseVaultConfig(options.vaultConfig);
495
+ const executionContext = this.mapSdkExecutionContext(options.executionContext, vaultConfig);
496
+ const dataConnector = new DataConnector(options.wasmFile, options.vaultConfig, this.config, options.identity, options.etherRpcConfig);
497
+ try {
498
+ await dataConnector.loadSync();
499
+ dataConnector.setExecutionContextStrategyExecutionPinned(executionContext, options.forceDeposit);
500
+ const result = await dataConnector.executeBundle(options.data.map((item) => JSON.stringify(item)));
501
+ return JSON.parse(result);
502
+ }
503
+ catch (error) {
504
+ if (error instanceof ExecutionContextError)
505
+ throw error;
506
+ throw new StrategyExecutionError(this.redactError(error));
507
+ }
508
+ }
509
+ parseVaultConfig(vaultConfig) {
510
+ try {
511
+ return JSON.parse(vaultConfig);
512
+ }
513
+ catch {
514
+ throw new ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'vaultConfig must be valid JSON.');
515
+ }
516
+ }
517
+ mapSdkExecutionContext(context, vaultConfig) {
518
+ if (!context || typeof context !== 'object') {
519
+ throw new ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'A successful SDK VaultExecutionContext is required.');
520
+ }
521
+ const requiredStringFields = [
522
+ 'blockNumber',
523
+ 'epochTimestamp',
524
+ 'vaultAddress',
525
+ 'totalAmount0',
526
+ 'totalAmount1',
527
+ ];
528
+ for (const field of requiredStringFields) {
529
+ if (typeof context[field] !== 'string' || context[field].length === 0) {
530
+ throw new ExecutionContextError('INVALID_EXECUTION_CONTEXT', `SDK execution context has invalid ${field}.`);
531
+ }
532
+ }
533
+ if (!Number.isInteger(context.chainId) ||
534
+ !Number.isInteger(context.currentTick) ||
535
+ !Number.isInteger(context.tickSpacing)) {
536
+ throw new ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context has invalid chain or pool state.');
537
+ }
538
+ if (!Array.isArray(context.positions) ||
539
+ !/^\d+$/.test(context.blockNumber) ||
540
+ !/^\d+$/.test(context.epochTimestamp)) {
541
+ throw new ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context has malformed anchor fields.');
542
+ }
543
+ if (!/^\d+$/.test(context.totalAmount0) || !/^\d+$/.test(context.totalAmount1)) {
544
+ throw new ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context totals must be decimal strings.');
545
+ }
546
+ const sameAddress = (left, right) => left?.toLowerCase() === right?.toLowerCase();
547
+ if (!sameAddress(this.vault, context.vaultAddress) ||
548
+ !sameAddress(vaultConfig.vaultAddress, context.vaultAddress)) {
549
+ throw new ExecutionContextError('EXECUTION_CONTEXT_MISMATCH', 'Supplied context vault does not match the execution request.');
550
+ }
551
+ if (this.chainId !== context.chainId ||
552
+ (vaultConfig.chainId !== undefined && Number(vaultConfig.chainId) !== context.chainId)) {
553
+ throw new ExecutionContextError('EXECUTION_CONTEXT_MISMATCH', 'Supplied context chain does not match the execution request.');
554
+ }
555
+ if (vaultConfig.anchorBlockNumber !== undefined && String(vaultConfig.anchorBlockNumber) !== context.blockNumber) {
556
+ throw new ExecutionContextError('EXECUTION_CONTEXT_MISMATCH', 'Supplied context block does not match anchorBlockNumber.');
557
+ }
558
+ const epochLength = Number(vaultConfig.strategyConfigData?.epochLength);
559
+ if (!Number.isFinite(epochLength)) {
560
+ throw new ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'vaultConfig.strategyConfigData.epochLength is required.');
561
+ }
562
+ for (const position of context.positions) {
563
+ if (!Number.isInteger(position.lowerTick) ||
564
+ !Number.isInteger(position.upperTick) ||
565
+ !Number.isFinite(position.relativeWeight)) {
566
+ throw new ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context contains an invalid position.');
567
+ }
568
+ }
569
+ // Null is deterministic: WASM receives zero elapsed seconds, never wall-clock time.
570
+ const lastExecutionTime = context.lastExecutionTimeSeconds === null ? 0 : Number(context.lastExecutionTimeSeconds);
571
+ if (!Number.isFinite(lastExecutionTime) || lastExecutionTime < 0) {
572
+ throw new ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context has invalid lastExecutionTimeSeconds.');
573
+ }
574
+ return {
575
+ executionTimestamp: Number(context.epochTimestamp) * 1000,
576
+ epochTimestamp: Number(context.epochTimestamp),
577
+ epochLength,
578
+ vaultAddress: context.vaultAddress,
579
+ blockTime: 0,
580
+ blockNumber: Number(context.blockNumber),
581
+ currentTick: context.currentTick,
582
+ tickSpacing: context.tickSpacing,
583
+ positions: context.positions.map(({ lowerTick, upperTick, relativeWeight }) => ({
584
+ startTick: lowerTick,
585
+ endTick: upperTick,
586
+ weight: relativeWeight,
587
+ })),
588
+ totalAmount0: context.totalAmount0,
589
+ totalAmount1: context.totalAmount1,
590
+ lastExecutionTime,
591
+ };
592
+ }
593
+ redactError(error) {
594
+ const message = error instanceof Error ? error.message : String(error);
595
+ return message
596
+ .replace(/https?:\/\/[^\s@/]+(?::[^\s@/]+)?@/gi, 'https://[REDACTED]@')
597
+ .replace(/([?&](?:key|token|api[_-]?key|password)=)[^&\s]+/gi, '$1[REDACTED]');
598
+ }
487
599
  async executeStabilityVault(_wasmFile, _vaultConfig, _data, _identity, _etherRpcConfig, forceDeposit) {
488
600
  const dataConnector = new DataConnector(_wasmFile, _vaultConfig, this.config, _identity, _etherRpcConfig);
489
601
  await dataConnector.loadSync();
@@ -1,9 +1,16 @@
1
1
  import type { DataConnector } from '../bundle/bundleDataConnector.js';
2
+ import type { VaultExecutionContext } from '@steerprotocol/sdk';
2
3
  import { ExecutionBase } from './executionBase.js';
3
4
  export declare class DataConnectorExecution extends ExecutionBase {
4
5
  private dataConnectors;
5
6
  constructor(dataConnectors: Array<DataConnector>, maxRetries?: number);
6
7
  execute<T>(_vaultConfig: string): Promise<Array<T>>;
8
+ /**
9
+ * Runs connectors using the same immutable SDK anchor as strategy execution.
10
+ * Chain reads receive its exact blockNumber; HTTP and subgraph responses are
11
+ * intentionally not represented as block-pinned data.
12
+ */
13
+ executeWithContext<T>(_vaultConfig: string, context: VaultExecutionContext): Promise<Array<T>>;
7
14
  private executeV2Bundle;
8
15
  executeDynamicJob<T>(_vaultConfig: string): Promise<Array<T>>;
9
16
  private handleRequestResponse;
@@ -1,3 +1,4 @@
1
+ import { DataConnectorTransportError } from '../types.js';
1
2
  import { PluginManager } from '../utils/pluginManager.js';
2
3
  import { changeUrlIfOld } from '../utils/replace-old-subgraphs.js';
3
4
  import { extendOHLCV, fetchData } from '../utils/utils.js';
@@ -47,6 +48,47 @@ export class DataConnectorExecution extends ExecutionBase {
47
48
  }
48
49
  return transformationData;
49
50
  }
51
+ /**
52
+ * Runs connectors using the same immutable SDK anchor as strategy execution.
53
+ * Chain reads receive its exact blockNumber; HTTP and subgraph responses are
54
+ * intentionally not represented as block-pinned data.
55
+ */
56
+ async executeWithContext(_vaultConfig, context) {
57
+ const vaultConfig = JSON.parse(_vaultConfig);
58
+ if (!context || !/^\d+$/.test(context.blockNumber) || !/^\d+$/.test(context.epochTimestamp)) {
59
+ throw new Error('INVALID_EXECUTION_CONTEXT: supplied SDK execution context is malformed.');
60
+ }
61
+ if (context.vaultAddress.toLowerCase() !== vaultConfig.vaultAddress.toLowerCase()) {
62
+ throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context vault does not match vaultConfig.vaultAddress.');
63
+ }
64
+ const requestChainId = vaultConfig.chainId;
65
+ if (requestChainId !== undefined && requestChainId !== context.chainId) {
66
+ throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context chain does not match vaultConfig.chainId.');
67
+ }
68
+ if (vaultConfig.anchorBlockNumber !== undefined && String(vaultConfig.anchorBlockNumber) !== context.blockNumber) {
69
+ throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context block does not match anchorBlockNumber.');
70
+ }
71
+ const executionContext = {
72
+ executionTimestamp: Number(context.epochTimestamp) * 1000,
73
+ epochTimestamp: Number(context.epochTimestamp),
74
+ epochLength: Number(vaultConfig.strategyConfigData.epochLength),
75
+ vaultAddress: context.vaultAddress,
76
+ blockTime: 0,
77
+ blockNumber: Number(context.blockNumber),
78
+ };
79
+ const transformationData = [];
80
+ for (const dataConnector of this.dataConnectors) {
81
+ if (dataConnector.executionAppConfig.chainId !== context.chainId) {
82
+ throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context chain does not match connector configuration.');
83
+ }
84
+ if (!dataConnector.module)
85
+ await dataConnector.load();
86
+ dataConnector.setExecutionContextDataConnectorPinned(executionContext);
87
+ await dataConnector.execute();
88
+ transformationData.push(JSON.parse(await dataConnector.transform()));
89
+ }
90
+ return transformationData;
91
+ }
50
92
  async executeV2Bundle(dataConnector, vaultConfig) {
51
93
  const executionContext = await this.getExecutionContext(dataConnector, vaultConfig);
52
94
  dataConnector.setExecutionContextDataConnector(executionContext);
@@ -88,7 +130,13 @@ export class DataConnectorExecution extends ExecutionBase {
88
130
  ...(url?.includes('sentio') ? { 'api-key': dataConnector.executionAppConfig.apiKeys.sentioApiKey } : {}),
89
131
  };
90
132
  await this.delay(1000);
91
- response = await fetchData(parsedRequest, 0);
133
+ try {
134
+ response = await fetchData(parsedRequest, 0);
135
+ }
136
+ catch (error) {
137
+ const message = error instanceof Error ? error.message : String(error);
138
+ throw new DataConnectorTransportError(message.replace(/https?:\/\/[^\s@/]+(?::[^\s@/]+)?@/gi, 'https://[REDACTED]@'));
139
+ }
92
140
  }
93
141
  const nextRequest = await dataConnector.execute(JSON.stringify(response));
94
142
  if (nextRequest === null) {
@@ -1,7 +1,8 @@
1
1
  import { DataConnector } from './bundle/bundleDataConnector.js';
2
2
  import { ExecutionApp, type ExecutionAppConfig } from './execution/executionApp.js';
3
3
  import { DataConnectorExecution } from './execution/executionDataConnector.js';
4
- import type { VaultConfigPayload } from './types.js';
4
+ import type { ExecuteWithContextOptions, VaultConfigPayload } from './types.js';
5
5
  export type * from './types.js';
6
6
  export { DataConnector, DataConnectorExecution, ExecutionApp };
7
- export type { ExecutionAppConfig, VaultConfigPayload };
7
+ export { DataConnectorTransportError, ExecutionContextError, StrategyExecutionError } from './types.js';
8
+ export type { ExecuteWithContextOptions, ExecutionAppConfig, VaultConfigPayload };
package/lib/esm/index.js CHANGED
@@ -2,3 +2,4 @@ import { DataConnector } from './bundle/bundleDataConnector.js';
2
2
  import { ExecutionApp } from './execution/executionApp.js';
3
3
  import { DataConnectorExecution } from './execution/executionDataConnector.js';
4
4
  export { DataConnector, DataConnectorExecution, ExecutionApp };
5
+ export { DataConnectorTransportError, ExecutionContextError, StrategyExecutionError } from './types.js';
@@ -1,4 +1,31 @@
1
- import type { InterfaceAbi } from 'ethers';
1
+ import type { ethers, InterfaceAbi } from 'ethers';
2
+ import type { VaultExecutionContext } from '@steerprotocol/sdk';
3
+ /** Error raised before a strategy is invoked when its supplied SDK anchor is unusable. */
4
+ export declare class ExecutionContextError extends Error {
5
+ readonly code: 'INVALID_EXECUTION_CONTEXT' | 'EXECUTION_CONTEXT_MISMATCH';
6
+ constructor(code: ExecutionContextError['code'], message: string);
7
+ }
8
+ /** Error classification for failures in a connector transport request. */
9
+ export declare class DataConnectorTransportError extends Error {
10
+ readonly code = "DATA_CONNECTOR_TRANSPORT_ERROR";
11
+ constructor(message: string);
12
+ }
13
+ /** Error classification for a WASM strategy failure. */
14
+ export declare class StrategyExecutionError extends Error {
15
+ readonly code = "STRATEGY_EXECUTION_ERROR";
16
+ constructor(message: string);
17
+ }
18
+ /** Options for the block-pinned SDK execution path. */
19
+ export interface ExecuteWithContextOptions {
20
+ wasmFile: string | ArrayBuffer;
21
+ vaultConfig: string;
22
+ data: Array<unknown>;
23
+ /** Successful, normalized context returned by @steerprotocol/sdk 3.3+. */
24
+ executionContext: VaultExecutionContext;
25
+ identity?: ethers.Provider;
26
+ etherRpcConfig?: EtherRpcConfig;
27
+ forceDeposit?: boolean;
28
+ }
2
29
  export type VaultInput = {
3
30
  _id?: string;
4
31
  tokenId: string;
@@ -100,6 +127,7 @@ export interface Slot0 {
100
127
  }
101
128
  export type ViewContractConfig = {
102
129
  epochTimestamp?: number;
130
+ blockNumber?: number;
103
131
  address: string;
104
132
  abi: any;
105
133
  arguments: Array<any>;
package/lib/esm/types.js CHANGED
@@ -1 +1,24 @@
1
- export {};
1
+ /** Error raised before a strategy is invoked when its supplied SDK anchor is unusable. */
2
+ export class ExecutionContextError extends Error {
3
+ constructor(code, message) {
4
+ super(message);
5
+ this.name = 'ExecutionContextError';
6
+ this.code = code;
7
+ }
8
+ }
9
+ /** Error classification for failures in a connector transport request. */
10
+ export class DataConnectorTransportError extends Error {
11
+ constructor(message) {
12
+ super(message);
13
+ this.code = 'DATA_CONNECTOR_TRANSPORT_ERROR';
14
+ this.name = 'DataConnectorTransportError';
15
+ }
16
+ }
17
+ /** Error classification for a WASM strategy failure. */
18
+ export class StrategyExecutionError extends Error {
19
+ constructor(message) {
20
+ super(message);
21
+ this.code = 'STRATEGY_EXECUTION_ERROR';
22
+ this.name = 'StrategyExecutionError';
23
+ }
24
+ }
@@ -83,6 +83,7 @@ export async function readContract({ abi, address, chainId, contractArguments =
83
83
  console.log('Calling the centralized view');
84
84
  const viewContractConfig = {
85
85
  epochTimestamp: currentExecutionContext.epochTimestamp,
86
+ blockNumber: currentExecutionContext.blockNumber,
86
87
  address,
87
88
  abi,
88
89
  arguments: paramsArray,
@@ -1,5 +1,5 @@
1
1
  import type { ethers } from 'ethers';
2
- import type { EtherRpcConfig, JobDetails } from '../types.js';
2
+ import type { EtherRpcConfig, ExecuteWithContextOptions, JobDetails } from '../types.js';
3
3
  import { ExecutionBase } from './executionBase.js';
4
4
  export interface ExecutionAppConfig {
5
5
  /** Vault address used for execution context and subgraph queries. */
@@ -43,6 +43,15 @@ export declare class ExecutionApp extends ExecutionBase {
43
43
  config: ExecutionAppConfig;
44
44
  constructor(config: ExecutionAppConfig);
45
45
  execute<T>(_wasmFile: string | ArrayBuffer, _vaultConfig: string, _data: Array<any>, _identity?: ethers.Provider, _etherRpcConfig?: EtherRpcConfig, forceDeposit?: boolean): Promise<Array<T>>;
46
+ /**
47
+ * Executes a strategy against the immutable context resolved by SDK 3.3+.
48
+ * This is the recommended API for new consumers. It intentionally bypasses
49
+ * all legacy vault, pool, subgraph, clock, and block-estimation reads.
50
+ */
51
+ executeWithContext<T>(options: ExecuteWithContextOptions): Promise<Array<T>>;
52
+ private parseVaultConfig;
53
+ private mapSdkExecutionContext;
54
+ private redactError;
46
55
  executeStabilityVault<T>(_wasmFile: string | ArrayBuffer, _vaultConfig: string, _data: Array<any>, _identity?: ethers.Provider, _etherRpcConfig?: EtherRpcConfig, forceDeposit?: boolean): Promise<Array<T>>;
47
56
  executeDynamicJobs<T>(_wasmFile: string | ArrayBuffer, _vaultConfig: string, _data: Array<any>, _job: JobDetails, _identity?: ethers.Provider, _etherRpcConfig?: EtherRpcConfig, forceDeposit?: boolean): Promise<Array<T>>;
48
57
  private getSmartPoolExecutionContext;
@@ -11,6 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.ExecutionApp = void 0;
13
13
  const bundleDataConnector_js_1 = require("../bundle/bundleDataConnector.js");
14
+ const types_js_1 = require("../types.js");
14
15
  const utils_js_1 = require("../utils/utils.js");
15
16
  const executionBase_js_1 = require("./executionBase.js");
16
17
  class ExecutionApp extends executionBase_js_1.ExecutionBase {
@@ -496,6 +497,120 @@ class ExecutionApp extends executionBase_js_1.ExecutionBase {
496
497
  return JSON.parse(result);
497
498
  });
498
499
  }
500
+ /**
501
+ * Executes a strategy against the immutable context resolved by SDK 3.3+.
502
+ * This is the recommended API for new consumers. It intentionally bypasses
503
+ * all legacy vault, pool, subgraph, clock, and block-estimation reads.
504
+ */
505
+ executeWithContext(options) {
506
+ return __awaiter(this, void 0, void 0, function* () {
507
+ const vaultConfig = this.parseVaultConfig(options.vaultConfig);
508
+ const executionContext = this.mapSdkExecutionContext(options.executionContext, vaultConfig);
509
+ const dataConnector = new bundleDataConnector_js_1.DataConnector(options.wasmFile, options.vaultConfig, this.config, options.identity, options.etherRpcConfig);
510
+ try {
511
+ yield dataConnector.loadSync();
512
+ dataConnector.setExecutionContextStrategyExecutionPinned(executionContext, options.forceDeposit);
513
+ const result = yield dataConnector.executeBundle(options.data.map((item) => JSON.stringify(item)));
514
+ return JSON.parse(result);
515
+ }
516
+ catch (error) {
517
+ if (error instanceof types_js_1.ExecutionContextError)
518
+ throw error;
519
+ throw new types_js_1.StrategyExecutionError(this.redactError(error));
520
+ }
521
+ });
522
+ }
523
+ parseVaultConfig(vaultConfig) {
524
+ try {
525
+ return JSON.parse(vaultConfig);
526
+ }
527
+ catch (_a) {
528
+ throw new types_js_1.ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'vaultConfig must be valid JSON.');
529
+ }
530
+ }
531
+ mapSdkExecutionContext(context, vaultConfig) {
532
+ var _a;
533
+ if (!context || typeof context !== 'object') {
534
+ throw new types_js_1.ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'A successful SDK VaultExecutionContext is required.');
535
+ }
536
+ const requiredStringFields = [
537
+ 'blockNumber',
538
+ 'epochTimestamp',
539
+ 'vaultAddress',
540
+ 'totalAmount0',
541
+ 'totalAmount1',
542
+ ];
543
+ for (const field of requiredStringFields) {
544
+ if (typeof context[field] !== 'string' || context[field].length === 0) {
545
+ throw new types_js_1.ExecutionContextError('INVALID_EXECUTION_CONTEXT', `SDK execution context has invalid ${field}.`);
546
+ }
547
+ }
548
+ if (!Number.isInteger(context.chainId) ||
549
+ !Number.isInteger(context.currentTick) ||
550
+ !Number.isInteger(context.tickSpacing)) {
551
+ throw new types_js_1.ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context has invalid chain or pool state.');
552
+ }
553
+ if (!Array.isArray(context.positions) ||
554
+ !/^\d+$/.test(context.blockNumber) ||
555
+ !/^\d+$/.test(context.epochTimestamp)) {
556
+ throw new types_js_1.ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context has malformed anchor fields.');
557
+ }
558
+ if (!/^\d+$/.test(context.totalAmount0) || !/^\d+$/.test(context.totalAmount1)) {
559
+ throw new types_js_1.ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context totals must be decimal strings.');
560
+ }
561
+ const sameAddress = (left, right) => (left === null || left === void 0 ? void 0 : left.toLowerCase()) === (right === null || right === void 0 ? void 0 : right.toLowerCase());
562
+ if (!sameAddress(this.vault, context.vaultAddress) ||
563
+ !sameAddress(vaultConfig.vaultAddress, context.vaultAddress)) {
564
+ throw new types_js_1.ExecutionContextError('EXECUTION_CONTEXT_MISMATCH', 'Supplied context vault does not match the execution request.');
565
+ }
566
+ if (this.chainId !== context.chainId ||
567
+ (vaultConfig.chainId !== undefined && Number(vaultConfig.chainId) !== context.chainId)) {
568
+ throw new types_js_1.ExecutionContextError('EXECUTION_CONTEXT_MISMATCH', 'Supplied context chain does not match the execution request.');
569
+ }
570
+ if (vaultConfig.anchorBlockNumber !== undefined && String(vaultConfig.anchorBlockNumber) !== context.blockNumber) {
571
+ throw new types_js_1.ExecutionContextError('EXECUTION_CONTEXT_MISMATCH', 'Supplied context block does not match anchorBlockNumber.');
572
+ }
573
+ const epochLength = Number((_a = vaultConfig.strategyConfigData) === null || _a === void 0 ? void 0 : _a.epochLength);
574
+ if (!Number.isFinite(epochLength)) {
575
+ throw new types_js_1.ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'vaultConfig.strategyConfigData.epochLength is required.');
576
+ }
577
+ for (const position of context.positions) {
578
+ if (!Number.isInteger(position.lowerTick) ||
579
+ !Number.isInteger(position.upperTick) ||
580
+ !Number.isFinite(position.relativeWeight)) {
581
+ throw new types_js_1.ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context contains an invalid position.');
582
+ }
583
+ }
584
+ // Null is deterministic: WASM receives zero elapsed seconds, never wall-clock time.
585
+ const lastExecutionTime = context.lastExecutionTimeSeconds === null ? 0 : Number(context.lastExecutionTimeSeconds);
586
+ if (!Number.isFinite(lastExecutionTime) || lastExecutionTime < 0) {
587
+ throw new types_js_1.ExecutionContextError('INVALID_EXECUTION_CONTEXT', 'SDK execution context has invalid lastExecutionTimeSeconds.');
588
+ }
589
+ return {
590
+ executionTimestamp: Number(context.epochTimestamp) * 1000,
591
+ epochTimestamp: Number(context.epochTimestamp),
592
+ epochLength,
593
+ vaultAddress: context.vaultAddress,
594
+ blockTime: 0,
595
+ blockNumber: Number(context.blockNumber),
596
+ currentTick: context.currentTick,
597
+ tickSpacing: context.tickSpacing,
598
+ positions: context.positions.map(({ lowerTick, upperTick, relativeWeight }) => ({
599
+ startTick: lowerTick,
600
+ endTick: upperTick,
601
+ weight: relativeWeight,
602
+ })),
603
+ totalAmount0: context.totalAmount0,
604
+ totalAmount1: context.totalAmount1,
605
+ lastExecutionTime,
606
+ };
607
+ }
608
+ redactError(error) {
609
+ const message = error instanceof Error ? error.message : String(error);
610
+ return message
611
+ .replace(/https?:\/\/[^\s@/]+(?::[^\s@/]+)?@/gi, 'https://[REDACTED]@')
612
+ .replace(/([?&](?:key|token|api[_-]?key|password)=)[^&\s]+/gi, '$1[REDACTED]');
613
+ }
499
614
  executeStabilityVault(_wasmFile, _vaultConfig, _data, _identity, _etherRpcConfig, forceDeposit) {
500
615
  return __awaiter(this, void 0, void 0, function* () {
501
616
  const dataConnector = new bundleDataConnector_js_1.DataConnector(_wasmFile, _vaultConfig, this.config, _identity, _etherRpcConfig);
@@ -1,9 +1,16 @@
1
1
  import type { DataConnector } from '../bundle/bundleDataConnector.js';
2
+ import type { VaultExecutionContext } from '@steerprotocol/sdk';
2
3
  import { ExecutionBase } from './executionBase.js';
3
4
  export declare class DataConnectorExecution extends ExecutionBase {
4
5
  private dataConnectors;
5
6
  constructor(dataConnectors: Array<DataConnector>, maxRetries?: number);
6
7
  execute<T>(_vaultConfig: string): Promise<Array<T>>;
8
+ /**
9
+ * Runs connectors using the same immutable SDK anchor as strategy execution.
10
+ * Chain reads receive its exact blockNumber; HTTP and subgraph responses are
11
+ * intentionally not represented as block-pinned data.
12
+ */
13
+ executeWithContext<T>(_vaultConfig: string, context: VaultExecutionContext): Promise<Array<T>>;
7
14
  private executeV2Bundle;
8
15
  executeDynamicJob<T>(_vaultConfig: string): Promise<Array<T>>;
9
16
  private handleRequestResponse;
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.DataConnectorExecution = void 0;
13
+ const types_js_1 = require("../types.js");
13
14
  const pluginManager_js_1 = require("../utils/pluginManager.js");
14
15
  const replace_old_subgraphs_js_1 = require("../utils/replace-old-subgraphs.js");
15
16
  const utils_js_1 = require("../utils/utils.js");
@@ -61,6 +62,49 @@ class DataConnectorExecution extends executionBase_js_1.ExecutionBase {
61
62
  return transformationData;
62
63
  });
63
64
  }
65
+ /**
66
+ * Runs connectors using the same immutable SDK anchor as strategy execution.
67
+ * Chain reads receive its exact blockNumber; HTTP and subgraph responses are
68
+ * intentionally not represented as block-pinned data.
69
+ */
70
+ executeWithContext(_vaultConfig, context) {
71
+ return __awaiter(this, void 0, void 0, function* () {
72
+ const vaultConfig = JSON.parse(_vaultConfig);
73
+ if (!context || !/^\d+$/.test(context.blockNumber) || !/^\d+$/.test(context.epochTimestamp)) {
74
+ throw new Error('INVALID_EXECUTION_CONTEXT: supplied SDK execution context is malformed.');
75
+ }
76
+ if (context.vaultAddress.toLowerCase() !== vaultConfig.vaultAddress.toLowerCase()) {
77
+ throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context vault does not match vaultConfig.vaultAddress.');
78
+ }
79
+ const requestChainId = vaultConfig.chainId;
80
+ if (requestChainId !== undefined && requestChainId !== context.chainId) {
81
+ throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context chain does not match vaultConfig.chainId.');
82
+ }
83
+ if (vaultConfig.anchorBlockNumber !== undefined && String(vaultConfig.anchorBlockNumber) !== context.blockNumber) {
84
+ throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context block does not match anchorBlockNumber.');
85
+ }
86
+ const executionContext = {
87
+ executionTimestamp: Number(context.epochTimestamp) * 1000,
88
+ epochTimestamp: Number(context.epochTimestamp),
89
+ epochLength: Number(vaultConfig.strategyConfigData.epochLength),
90
+ vaultAddress: context.vaultAddress,
91
+ blockTime: 0,
92
+ blockNumber: Number(context.blockNumber),
93
+ };
94
+ const transformationData = [];
95
+ for (const dataConnector of this.dataConnectors) {
96
+ if (dataConnector.executionAppConfig.chainId !== context.chainId) {
97
+ throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context chain does not match connector configuration.');
98
+ }
99
+ if (!dataConnector.module)
100
+ yield dataConnector.load();
101
+ dataConnector.setExecutionContextDataConnectorPinned(executionContext);
102
+ yield dataConnector.execute();
103
+ transformationData.push(JSON.parse(yield dataConnector.transform()));
104
+ }
105
+ return transformationData;
106
+ });
107
+ }
64
108
  executeV2Bundle(dataConnector, vaultConfig) {
65
109
  return __awaiter(this, void 0, void 0, function* () {
66
110
  const executionContext = yield this.getExecutionContext(dataConnector, vaultConfig);
@@ -104,7 +148,13 @@ class DataConnectorExecution extends executionBase_js_1.ExecutionBase {
104
148
  parsedRequest.url = url;
105
149
  parsedRequest.headers = Object.assign({ 'Content-Type': url && !url.includes('subgraph-proxy-server') ? 'application/json' : 'text/plain;charset=UTF-8' }, ((url === null || url === void 0 ? void 0 : url.includes('sentio')) ? { 'api-key': dataConnector.executionAppConfig.apiKeys.sentioApiKey } : {}));
106
150
  yield this.delay(1000);
107
- response = yield (0, utils_js_1.fetchData)(parsedRequest, 0);
151
+ try {
152
+ response = yield (0, utils_js_1.fetchData)(parsedRequest, 0);
153
+ }
154
+ catch (error) {
155
+ const message = error instanceof Error ? error.message : String(error);
156
+ throw new types_js_1.DataConnectorTransportError(message.replace(/https?:\/\/[^\s@/]+(?::[^\s@/]+)?@/gi, 'https://[REDACTED]@'));
157
+ }
108
158
  }
109
159
  const nextRequest = yield dataConnector.execute(JSON.stringify(response));
110
160
  if (nextRequest === null) {
package/lib/index.d.ts CHANGED
@@ -1,7 +1,8 @@
1
1
  import { DataConnector } from './bundle/bundleDataConnector.js';
2
2
  import { ExecutionApp, type ExecutionAppConfig } from './execution/executionApp.js';
3
3
  import { DataConnectorExecution } from './execution/executionDataConnector.js';
4
- import type { VaultConfigPayload } from './types.js';
4
+ import type { ExecuteWithContextOptions, VaultConfigPayload } from './types.js';
5
5
  export type * from './types.js';
6
6
  export { DataConnector, DataConnectorExecution, ExecutionApp };
7
- export type { ExecutionAppConfig, VaultConfigPayload };
7
+ export { DataConnectorTransportError, ExecutionContextError, StrategyExecutionError } from './types.js';
8
+ export type { ExecuteWithContextOptions, ExecutionAppConfig, VaultConfigPayload };
package/lib/index.js CHANGED
@@ -1,9 +1,13 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ExecutionApp = exports.DataConnectorExecution = exports.DataConnector = void 0;
3
+ exports.StrategyExecutionError = exports.ExecutionContextError = exports.DataConnectorTransportError = exports.ExecutionApp = exports.DataConnectorExecution = exports.DataConnector = void 0;
4
4
  const bundleDataConnector_js_1 = require("./bundle/bundleDataConnector.js");
5
5
  Object.defineProperty(exports, "DataConnector", { enumerable: true, get: function () { return bundleDataConnector_js_1.DataConnector; } });
6
6
  const executionApp_js_1 = require("./execution/executionApp.js");
7
7
  Object.defineProperty(exports, "ExecutionApp", { enumerable: true, get: function () { return executionApp_js_1.ExecutionApp; } });
8
8
  const executionDataConnector_js_1 = require("./execution/executionDataConnector.js");
9
9
  Object.defineProperty(exports, "DataConnectorExecution", { enumerable: true, get: function () { return executionDataConnector_js_1.DataConnectorExecution; } });
10
+ var types_js_1 = require("./types.js");
11
+ Object.defineProperty(exports, "DataConnectorTransportError", { enumerable: true, get: function () { return types_js_1.DataConnectorTransportError; } });
12
+ Object.defineProperty(exports, "ExecutionContextError", { enumerable: true, get: function () { return types_js_1.ExecutionContextError; } });
13
+ Object.defineProperty(exports, "StrategyExecutionError", { enumerable: true, get: function () { return types_js_1.StrategyExecutionError; } });
package/lib/types.d.ts CHANGED
@@ -1,4 +1,31 @@
1
- import type { InterfaceAbi } from 'ethers';
1
+ import type { ethers, InterfaceAbi } from 'ethers';
2
+ import type { VaultExecutionContext } from '@steerprotocol/sdk';
3
+ /** Error raised before a strategy is invoked when its supplied SDK anchor is unusable. */
4
+ export declare class ExecutionContextError extends Error {
5
+ readonly code: 'INVALID_EXECUTION_CONTEXT' | 'EXECUTION_CONTEXT_MISMATCH';
6
+ constructor(code: ExecutionContextError['code'], message: string);
7
+ }
8
+ /** Error classification for failures in a connector transport request. */
9
+ export declare class DataConnectorTransportError extends Error {
10
+ readonly code = "DATA_CONNECTOR_TRANSPORT_ERROR";
11
+ constructor(message: string);
12
+ }
13
+ /** Error classification for a WASM strategy failure. */
14
+ export declare class StrategyExecutionError extends Error {
15
+ readonly code = "STRATEGY_EXECUTION_ERROR";
16
+ constructor(message: string);
17
+ }
18
+ /** Options for the block-pinned SDK execution path. */
19
+ export interface ExecuteWithContextOptions {
20
+ wasmFile: string | ArrayBuffer;
21
+ vaultConfig: string;
22
+ data: Array<unknown>;
23
+ /** Successful, normalized context returned by @steerprotocol/sdk 3.3+. */
24
+ executionContext: VaultExecutionContext;
25
+ identity?: ethers.Provider;
26
+ etherRpcConfig?: EtherRpcConfig;
27
+ forceDeposit?: boolean;
28
+ }
2
29
  export type VaultInput = {
3
30
  _id?: string;
4
31
  tokenId: string;
@@ -100,6 +127,7 @@ export interface Slot0 {
100
127
  }
101
128
  export type ViewContractConfig = {
102
129
  epochTimestamp?: number;
130
+ blockNumber?: number;
103
131
  address: string;
104
132
  abi: any;
105
133
  arguments: Array<any>;
package/lib/types.js CHANGED
@@ -1,2 +1,30 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StrategyExecutionError = exports.DataConnectorTransportError = exports.ExecutionContextError = void 0;
4
+ /** Error raised before a strategy is invoked when its supplied SDK anchor is unusable. */
5
+ class ExecutionContextError extends Error {
6
+ constructor(code, message) {
7
+ super(message);
8
+ this.name = 'ExecutionContextError';
9
+ this.code = code;
10
+ }
11
+ }
12
+ exports.ExecutionContextError = ExecutionContextError;
13
+ /** Error classification for failures in a connector transport request. */
14
+ class DataConnectorTransportError extends Error {
15
+ constructor(message) {
16
+ super(message);
17
+ this.code = 'DATA_CONNECTOR_TRANSPORT_ERROR';
18
+ this.name = 'DataConnectorTransportError';
19
+ }
20
+ }
21
+ exports.DataConnectorTransportError = DataConnectorTransportError;
22
+ /** Error classification for a WASM strategy failure. */
23
+ class StrategyExecutionError extends Error {
24
+ constructor(message) {
25
+ super(message);
26
+ this.code = 'STRATEGY_EXECUTION_ERROR';
27
+ this.name = 'StrategyExecutionError';
28
+ }
29
+ }
30
+ exports.StrategyExecutionError = StrategyExecutionError;
@@ -105,6 +105,7 @@ function readContract({ abi, address, chainId, contractArguments = [], currentEx
105
105
  console.log('Calling the centralized view');
106
106
  const viewContractConfig = {
107
107
  epochTimestamp: currentExecutionContext.epochTimestamp,
108
+ blockNumber: currentExecutionContext.blockNumber,
108
109
  address,
109
110
  abi,
110
111
  arguments: paramsArray,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steerprotocol/data-connector-loader",
3
- "version": "4.0.2",
3
+ "version": "4.1.0",
4
4
  "description": "App Loader for Steer Protocol",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -24,6 +24,7 @@
24
24
  "lint:fix": "eslint src --fix --ext .js,.ts",
25
25
  "test": "jest --config jest.config.cjs",
26
26
  "pack:local": "npm pack",
27
+ "test:packed-consumer": "node scripts/packed-consumer-smoke.cjs",
27
28
  "publish:test": "node scripts/publish-test.cjs",
28
29
  "prepare": "husky && npm run build",
29
30
  "prepublishOnly": "npm test && npm run lint",
@@ -82,10 +83,6 @@
82
83
  "@types/jest": "29.2.4",
83
84
  "@typescript-eslint/eslint-plugin": "5.46.0",
84
85
  "@typescript-eslint/parser": "5.47.1",
85
- "@uniswap/sdk-core": "^7.10.0",
86
- "@uniswap/v2-sdk": "^4.16.0",
87
- "@uniswap/v3-sdk": "^3.26.0",
88
- "date-fns": "^2.29.3",
89
86
  "eslint": "8.30.0",
90
87
  "eslint-plugin-jest": "27.1.7",
91
88
  "husky": "^9.1.7",
@@ -93,15 +90,14 @@
93
90
  "prettier": "2.8.1",
94
91
  "semantic-release": "^25.0.3",
95
92
  "ts-jest": "29.0.3",
96
- "typescript": "5.0.4",
97
- "viem": "^2.42.1"
93
+ "typescript": "5.0.4"
98
94
  },
99
95
  "files": [
100
96
  "lib/**/*"
101
97
  ],
102
98
  "dependencies": {
103
- "@steerprotocol/app-loader": "^3.0.4",
104
- "@steerprotocol/sdk": "^2.0.0",
99
+ "@steerprotocol/app-loader": "^3.0.6",
100
+ "@steerprotocol/sdk": "^3.3.0",
105
101
  "@steerprotocol/strategy-utils": "^3.1.2",
106
102
  "axios": "^1.3.4",
107
103
  "ethers": "^6.16.0",