@steerprotocol/data-connector-loader 5.0.0-next.1 → 5.0.0-next.10

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.
Files changed (50) hide show
  1. package/README.md +102 -0
  2. package/lib/bundle/bundleBase.d.ts +11 -14
  3. package/lib/bundle/bundleBase.js +56 -88
  4. package/lib/bundle/bundleDataConnector.d.ts +2 -6
  5. package/lib/bundle/bundleDataConnector.js +22 -47
  6. package/lib/esm/bundle/bundleBase.d.ts +11 -14
  7. package/lib/esm/bundle/bundleBase.js +77 -91
  8. package/lib/esm/bundle/bundleDataConnector.d.ts +2 -6
  9. package/lib/esm/bundle/bundleDataConnector.js +26 -49
  10. package/lib/esm/execution/executionApp.d.ts +16 -15
  11. package/lib/esm/execution/executionApp.js +364 -321
  12. package/lib/esm/execution/executionBase.d.ts +7 -7
  13. package/lib/esm/execution/executionBase.js +27 -13
  14. package/lib/esm/execution/executionDataConnector.d.ts +6 -3
  15. package/lib/esm/execution/executionDataConnector.js +128 -69
  16. package/lib/esm/index.d.ts +7 -7
  17. package/lib/esm/index.js +4 -4
  18. package/lib/esm/types.d.ts +20 -24
  19. package/lib/esm/types.js +5 -5
  20. package/lib/esm/utils/blockFinder.d.ts +2 -2
  21. package/lib/esm/utils/blockFinder.js +3 -3
  22. package/lib/esm/utils/consts.js +39 -39
  23. package/lib/esm/utils/pluginManager.d.ts +1 -1
  24. package/lib/esm/utils/pluginManager.js +6 -5
  25. package/lib/esm/utils/replace-old-subgraphs.js +79 -61
  26. package/lib/esm/utils/rpc.d.ts +4 -0
  27. package/lib/esm/utils/rpc.js +32 -0
  28. package/lib/esm/utils/utils.d.ts +8 -11
  29. package/lib/esm/utils/utils.js +61 -55
  30. package/lib/execution/executionApp.d.ts +16 -15
  31. package/lib/execution/executionApp.js +353 -315
  32. package/lib/execution/executionBase.d.ts +7 -7
  33. package/lib/execution/executionBase.js +27 -13
  34. package/lib/execution/executionDataConnector.d.ts +6 -3
  35. package/lib/execution/executionDataConnector.js +130 -64
  36. package/lib/index.d.ts +7 -7
  37. package/lib/index.js +1 -1
  38. package/lib/types.d.ts +20 -24
  39. package/lib/types.js +5 -5
  40. package/lib/utils/blockFinder.d.ts +2 -2
  41. package/lib/utils/blockFinder.js +3 -3
  42. package/lib/utils/consts.js +39 -39
  43. package/lib/utils/pluginManager.d.ts +1 -1
  44. package/lib/utils/pluginManager.js +5 -4
  45. package/lib/utils/replace-old-subgraphs.js +79 -61
  46. package/lib/utils/rpc.d.ts +4 -0
  47. package/lib/utils/rpc.js +47 -0
  48. package/lib/utils/utils.d.ts +8 -11
  49. package/lib/utils/utils.js +55 -60
  50. package/package.json +15 -15
@@ -1,14 +1,14 @@
1
- import type { ethers } from 'ethers';
2
- import type { DataConnector } from '../bundle/bundleDataConnector.js';
3
- import type { EtherRpcConfig, LegacyExecutionContext, VaultConfigPayload } from '../types.js';
1
+ import type { PublicClient } from "viem";
2
+ import type { DataConnector } from "../bundle/bundleDataConnector.js";
3
+ import type { ExecutionContext, RpcAccess, VaultConfigPayload } from "../types.js";
4
4
  export declare class ExecutionBase {
5
5
  maxRetries: number;
6
6
  constructor(maxRetries?: number);
7
7
  protected delay(ms: number): Promise<void>;
8
8
  protected log(...args: Array<any>): void;
9
- protected getExecutionContext(dataConnector: DataConnector, vaultConfig: VaultConfigPayload): Promise<LegacyExecutionContext>;
10
- execute<T>(_wasmFile: string | ArrayBuffer, _vaultConfig: string, _data: Array<any>, _identity?: ethers.Provider, _etherRpcConfig?: EtherRpcConfig): Promise<Array<T>>;
9
+ protected getExecutionContext(dataConnector: DataConnector, vaultConfig: VaultConfigPayload): Promise<ExecutionContext>;
10
+ execute<T>(_wasmFile: string | ArrayBuffer, _vaultConfig: string, _data: Array<any>, rpc?: RpcAccess): Promise<T | Array<T> | "continue">;
11
11
  protected getDataConnectorVersion(dataConnector: DataConnector): Promise<number>;
12
- getAverageBlockTime(provider: ethers.Provider, blockCount?: number): Promise<number>;
13
- getBlockNumberFromAvgBlockTime(provider: ethers.Provider, targetTimestamp: number, avgBlockTime: number): Promise<number>;
12
+ getAverageBlockTime(provider: PublicClient, blockCount?: number): Promise<number>;
13
+ getBlockNumberFromAvgBlockTime(provider: PublicClient, targetTimestamp: number, avgBlockTime: number): Promise<number>;
14
14
  }
@@ -7,12 +7,18 @@ export class ExecutionBase {
7
7
  return new Promise((resolve) => setTimeout(resolve, ms));
8
8
  }
9
9
  log(...args) {
10
- if (process.env.DEBUG === 'true') {
10
+ if (process.env.DEBUG === "true") {
11
11
  console.log(...args);
12
12
  }
13
13
  }
14
14
  async getExecutionContext(dataConnector, vaultConfig) {
15
- const provider = dataConnector.getProvider({});
15
+ const chainId = dataConnector.executionAppConfig.chainId;
16
+ if (!Number.isSafeInteger(chainId))
17
+ throw new Error("Invalid execution chain ID");
18
+ const provider = dataConnector.getClient();
19
+ if (provider && (await provider.getChainId()) !== chainId) {
20
+ throw new Error("EXECUTION_CONTEXT_MISMATCH: provider chain does not match supplied context.");
21
+ }
16
22
  let blockTime = 0;
17
23
  let blockNumber = 9;
18
24
  // Use anchorBlockNumber if provided, otherwise calculate from average block time
@@ -28,6 +34,7 @@ export class ExecutionBase {
28
34
  blockNumber);
29
35
  }
30
36
  const context = {
37
+ chainId,
31
38
  executionTimestamp: new Date().getTime(),
32
39
  epochTimestamp: vaultConfig.epochTimestamp,
33
40
  epochLength: Number(vaultConfig.strategyConfigData.epochLength),
@@ -37,8 +44,8 @@ export class ExecutionBase {
37
44
  };
38
45
  return context;
39
46
  }
40
- async execute(_wasmFile, _vaultConfig, _data, _identity, _etherRpcConfig) {
41
- throw new Error('Not implemented');
47
+ async execute(_wasmFile, _vaultConfig, _data, rpc) {
48
+ throw new Error("Not implemented");
42
49
  }
43
50
  async getDataConnectorVersion(dataConnector) {
44
51
  let version = 1;
@@ -51,20 +58,27 @@ export class ExecutionBase {
51
58
  return version;
52
59
  }
53
60
  async getAverageBlockTime(provider, blockCount = 5) {
54
- const latestBlock = await provider.getBlock('latest');
61
+ const latestBlock = await provider.getBlock({ blockTag: "latest" });
55
62
  if (latestBlock) {
56
- const startBlockNumber = Math.max(0, latestBlock.number - blockCount + 1);
63
+ const startBlockNumber = Math.max(0, Number(latestBlock.number) - blockCount + 1);
57
64
  let totalTimeDiff = 0;
58
- let previousBlock = await provider.getBlock(startBlockNumber);
65
+ let previousBlock = await provider.getBlock({
66
+ blockNumber: BigInt(startBlockNumber),
67
+ });
59
68
  if (!previousBlock) {
60
69
  return 0;
61
70
  }
62
71
  for (let i = startBlockNumber + 1; i <= latestBlock.number; i++) {
63
- const currentBlock = await provider.getBlock(i);
64
- if (!currentBlock || !previousBlock || !currentBlock.timestamp || !previousBlock.timestamp) {
72
+ const currentBlock = await provider.getBlock({
73
+ blockNumber: BigInt(i),
74
+ });
75
+ if (!currentBlock ||
76
+ !previousBlock ||
77
+ !currentBlock.timestamp ||
78
+ !previousBlock.timestamp) {
65
79
  continue;
66
80
  }
67
- const timeDiff = currentBlock.timestamp - previousBlock.timestamp;
81
+ const timeDiff = Number(currentBlock.timestamp - previousBlock.timestamp);
68
82
  totalTimeDiff += timeDiff;
69
83
  previousBlock = currentBlock;
70
84
  }
@@ -76,19 +90,19 @@ export class ExecutionBase {
76
90
  }
77
91
  }
78
92
  async getBlockNumberFromAvgBlockTime(provider, targetTimestamp, avgBlockTime) {
79
- const latestBlock = await provider.getBlock('latest');
93
+ const latestBlock = await provider.getBlock({ blockTag: "latest" });
80
94
  const currentTime = Math.floor(Date.now() / 1000);
81
95
  const timeDifference = currentTime - targetTimestamp;
82
96
  if (!latestBlock) {
83
97
  return 0;
84
98
  }
85
99
  if (avgBlockTime === 0) {
86
- return latestBlock.number;
100
+ return Number(latestBlock.number);
87
101
  }
88
102
  // Calculate the estimated number of blocks based on the average block time
89
103
  const estimatedBlockCount = Math.floor(timeDifference / avgBlockTime);
90
104
  // Calculate the estimated block number
91
- const estimatedBlockNumber = latestBlock.number - estimatedBlockCount;
105
+ const estimatedBlockNumber = Number(latestBlock.number) - estimatedBlockCount;
92
106
  return Math.max(0, estimatedBlockNumber);
93
107
  }
94
108
  }
@@ -1,6 +1,6 @@
1
- import type { DataConnector } from '../bundle/bundleDataConnector.js';
2
- import { type ExecutionContext } from '../types.js';
3
- import { ExecutionBase } from './executionBase.js';
1
+ import type { DataConnector } from "../bundle/bundleDataConnector.js";
2
+ import { type ExecutionContext } from "../types.js";
3
+ import { ExecutionBase } from "./executionBase.js";
4
4
  export declare class DataConnectorExecution extends ExecutionBase {
5
5
  private dataConnectors;
6
6
  constructor(dataConnectors: Array<DataConnector>, maxRetries?: number);
@@ -12,6 +12,9 @@ export declare class DataConnectorExecution extends ExecutionBase {
12
12
  */
13
13
  executeWithContext<T>(_vaultConfig: string, context: ExecutionContext): Promise<Array<T>>;
14
14
  private executeV2Bundle;
15
+ private getConnectorVersion;
16
+ private executeInitializedV2Bundle;
17
+ private executeV1Bundle;
15
18
  executeDynamicJob<T>(_vaultConfig: string): Promise<Array<T>>;
16
19
  private handleRequestResponse;
17
20
  private transformData;
@@ -1,8 +1,8 @@
1
- import { DataConnectorTransportError } from '../types.js';
2
- import { PluginManager } from '../utils/pluginManager.js';
3
- import { changeUrlIfOld } from '../utils/replace-old-subgraphs.js';
4
- import { extendOHLCV, fetchData } from '../utils/utils.js';
5
- import { ExecutionBase } from './executionBase.js';
1
+ import axios from "axios";
2
+ import { DataConnectorTransportError, } from "../types.js";
3
+ import { changeUrlIfOld } from "../utils/replace-old-subgraphs.js";
4
+ import { extendOHLCV, fetchData } from "../utils/utils.js";
5
+ import { ExecutionBase } from "./executionBase.js";
6
6
  export class DataConnectorExecution extends ExecutionBase {
7
7
  constructor(dataConnectors, maxRetries = 3) {
8
8
  super(maxRetries);
@@ -11,39 +11,16 @@ export class DataConnectorExecution extends ExecutionBase {
11
11
  async execute(_vaultConfig) {
12
12
  const vaultConfig = JSON.parse(_vaultConfig);
13
13
  const transformationData = [];
14
- const pluginManager = new PluginManager();
15
- await pluginManager.registerFromPublicConfig();
16
14
  for (const dataConnector of this.dataConnectors) {
17
- if (!dataConnector.module) {
15
+ if (!dataConnector.module)
18
16
  await dataConnector.load();
19
- }
20
- let version = 1;
21
- try {
22
- version = dataConnector.version();
23
- }
24
- catch (e) {
25
- version = 1;
26
- }
27
- if (version >= 2) {
28
- const transformData = await this.executeV2Bundle(dataConnector, vaultConfig);
29
- transformationData.push(transformData);
17
+ if (this.getConnectorVersion(dataConnector) >= 2) {
18
+ transformationData.push(await this.executeV2Bundle(dataConnector, vaultConfig));
30
19
  }
31
20
  else {
32
- try {
33
- const executionContext = await this.getExecutionContext(dataConnector, vaultConfig);
34
- dataConnector.setExecutionContextDataConnector(executionContext);
35
- const initialRequest = await dataConnector.execute();
36
- if (initialRequest === null) {
37
- throw new Error('Data connector returned null request');
38
- }
39
- const finalResponse = await this.handleRequestResponse(dataConnector, pluginManager, initialRequest);
40
- const transformedData = await this.transformData(dataConnector, finalResponse);
41
- transformationData.push(transformedData);
42
- }
43
- catch (e) {
44
- const transformData = await this.executeV2Bundle(dataConnector, vaultConfig);
45
- transformationData.push(transformData);
46
- }
21
+ const executionContext = await this.getExecutionContext(dataConnector, vaultConfig);
22
+ dataConnector.setExecutionContextDataConnector(executionContext);
23
+ transformationData.push(await this.executeV1Bundle(dataConnector));
47
24
  }
48
25
  }
49
26
  return transformationData;
@@ -66,49 +43,77 @@ export class DataConnectorExecution extends ExecutionBase {
66
43
  context.executionTimestamp !== context.epochTimestamp * 1000 ||
67
44
  !Number.isFinite(context.epochLength) ||
68
45
  !Number.isFinite(context.blockTime) ||
69
- typeof context.vaultAddress !== 'string' ||
46
+ typeof context.vaultAddress !== "string" ||
70
47
  context.vaultAddress.length === 0) {
71
- throw new Error('INVALID_EXECUTION_CONTEXT: supplied execution context is malformed.');
48
+ throw new Error("INVALID_EXECUTION_CONTEXT: supplied execution context is malformed.");
72
49
  }
73
- if (context.vaultAddress.toLowerCase() !== vaultConfig.vaultAddress.toLowerCase()) {
74
- throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context vault does not match vaultConfig.vaultAddress.');
50
+ if (context.vaultAddress.toLowerCase() !==
51
+ vaultConfig.vaultAddress.toLowerCase()) {
52
+ throw new Error("EXECUTION_CONTEXT_MISMATCH: supplied context vault does not match vaultConfig.vaultAddress.");
75
53
  }
76
54
  const requestChainId = vaultConfig.chainId;
77
55
  if (requestChainId !== undefined && requestChainId !== context.chainId) {
78
- throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context chain does not match vaultConfig.chainId.');
56
+ throw new Error("EXECUTION_CONTEXT_MISMATCH: supplied context chain does not match vaultConfig.chainId.");
79
57
  }
80
58
  if (vaultConfig.anchorBlockNumber !== undefined &&
81
59
  String(vaultConfig.anchorBlockNumber) !== String(context.blockNumber)) {
82
- throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context block does not match anchorBlockNumber.');
60
+ throw new Error("EXECUTION_CONTEXT_MISMATCH: supplied context block does not match anchorBlockNumber.");
83
61
  }
84
- if (Number(vaultConfig.strategyConfigData?.epochLength) !== context.epochLength) {
85
- throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context epoch length does not match vaultConfig.');
62
+ if (Number(vaultConfig.strategyConfigData?.epochLength) !==
63
+ context.epochLength) {
64
+ throw new Error("EXECUTION_CONTEXT_MISMATCH: supplied context epoch length does not match vaultConfig.");
86
65
  }
66
+ const pinnedContext = Object.freeze({ ...context });
87
67
  const transformationData = [];
88
68
  for (const dataConnector of this.dataConnectors) {
89
- if (dataConnector.executionAppConfig.chainId !== context.chainId) {
90
- throw new Error('EXECUTION_CONTEXT_MISMATCH: supplied context chain does not match connector configuration.');
69
+ if (dataConnector.executionAppConfig.chainId !== pinnedContext.chainId) {
70
+ throw new Error("EXECUTION_CONTEXT_MISMATCH: supplied context chain does not match connector configuration.");
71
+ }
72
+ if (dataConnector.configObj.chainId !== undefined &&
73
+ Number(dataConnector.configObj.chainId) !== pinnedContext.chainId) {
74
+ throw new Error("EXECUTION_CONTEXT_MISMATCH: supplied context chain does not match connector settings.");
91
75
  }
92
76
  if (!dataConnector.module)
93
77
  await dataConnector.load();
94
- dataConnector.initializeDataConnectorWithContext(context);
95
- await dataConnector.execute();
96
- transformationData.push(JSON.parse(await dataConnector.transform()));
78
+ dataConnector.initializeDataConnectorWithContext(pinnedContext);
79
+ if (this.getConnectorVersion(dataConnector) >= 2) {
80
+ transformationData.push(await this.executeInitializedV2Bundle(dataConnector));
81
+ }
82
+ else {
83
+ transformationData.push(await this.executeV1Bundle(dataConnector, pinnedContext));
84
+ }
97
85
  }
98
86
  return transformationData;
99
87
  }
100
88
  async executeV2Bundle(dataConnector, vaultConfig) {
101
89
  const executionContext = await this.getExecutionContext(dataConnector, vaultConfig);
102
90
  dataConnector.setExecutionContextDataConnector(executionContext);
91
+ return this.executeInitializedV2Bundle(dataConnector);
92
+ }
93
+ getConnectorVersion(dataConnector) {
94
+ if (typeof dataConnector.module?.version !== "function")
95
+ return 1;
96
+ const version = dataConnector.version();
97
+ if (!Number.isInteger(version) || version < 1)
98
+ throw new Error("Invalid data connector version");
99
+ return version;
100
+ }
101
+ async executeInitializedV2Bundle(dataConnector) {
103
102
  await dataConnector.execute();
104
- const result = await dataConnector.transform();
105
- return JSON.parse(result);
103
+ return JSON.parse(await dataConnector.transform());
104
+ }
105
+ async executeV1Bundle(dataConnector, context) {
106
+ const initialRequest = await dataConnector.execute("");
107
+ if (initialRequest === null)
108
+ throw new Error("Data connector returned null request");
109
+ const result = await this.handleRequestResponse(dataConnector, initialRequest, context);
110
+ if (context)
111
+ return typeof result === "string" ? JSON.parse(result) : result;
112
+ return this.transformData(dataConnector, result);
106
113
  }
107
114
  async executeDynamicJob(_vaultConfig) {
108
115
  const vaultConfig = JSON.parse(_vaultConfig);
109
116
  const transformationData = [];
110
- const pluginManager = new PluginManager();
111
- await pluginManager.registerFromPublicConfig();
112
117
  for (const dataConnector of this.dataConnectors) {
113
118
  if (!dataConnector.module) {
114
119
  await dataConnector.load();
@@ -121,57 +126,111 @@ export class DataConnectorExecution extends ExecutionBase {
121
126
  }
122
127
  return transformationData;
123
128
  }
124
- async handleRequestResponse(dataConnector, pluginManager, initialRequest) {
129
+ async handleRequestResponse(dataConnector, initialRequest, context) {
125
130
  let request = initialRequest;
126
131
  let response;
127
132
  try {
128
- while (request !== 'true') {
129
- if (dataConnector.configObj.isChainRead == true) {
130
- response = await dataConnector.view(JSON.parse(request));
133
+ while (request !== "true") {
134
+ if (dataConnector.configObj.isChainRead === true) {
135
+ const view = JSON.parse(request);
136
+ if (context &&
137
+ view.chainId !== undefined &&
138
+ Number(view.chainId) !== context.chainId) {
139
+ throw new Error("EXECUTION_CONTEXT_MISMATCH: contract request chain does not match supplied context.");
140
+ }
141
+ response = await dataConnector.view(view);
131
142
  }
132
143
  else {
133
- const parsedRequest = await pluginManager.process(typeof request == 'string' ? JSON.parse(request) : request);
134
- const url = changeUrlIfOld(parsedRequest.url, dataConnector.configObj.subgraphStudioKey);
144
+ let parsedRequest = typeof request === "string" ? JSON.parse(request) : request;
145
+ const graphApiKey = dataConnector.executionAppConfig.apiKeys?.subgraphStudioKey;
146
+ const url = changeUrlIfOld(parsedRequest.url, graphApiKey ? undefined : dataConnector.configObj.subgraphStudioKey);
135
147
  parsedRequest.url = url;
148
+ let sentio = false;
149
+ let graph = false;
150
+ try {
151
+ const destination = new URL(axios.getUri(parsedRequest));
152
+ const hostname = destination.hostname.toLowerCase();
153
+ graph =
154
+ (destination.origin === "https://gateway.thegraph.com" ||
155
+ destination.origin ===
156
+ "https://gateway-arbitrum.network.thegraph.com") &&
157
+ /^\/api\/(subgraphs|deployments)\/id\/[a-zA-Z0-9]+$/.test(destination.pathname) &&
158
+ !destination.username &&
159
+ !destination.password;
160
+ sentio =
161
+ destination.protocol === "https:" &&
162
+ (hostname === "sentio.xyz" || hostname.endsWith(".sentio.xyz"));
163
+ }
164
+ catch {
165
+ /* Axios will report an invalid URL when sending the request. */
166
+ }
167
+ const sentioApiKey = dataConnector.executionAppConfig.apiKeys?.sentioApiKey;
136
168
  parsedRequest.headers = {
137
- 'Content-Type': url && !url.includes('subgraph-proxy-server') ? 'application/json' : 'text/plain;charset=UTF-8',
138
- ...(url?.includes('sentio') ? { 'api-key': dataConnector.executionAppConfig.apiKeys.sentioApiKey } : {}),
169
+ "Content-Type": url && !url.includes("subgraph-proxy-server")
170
+ ? "application/json"
171
+ : "text/plain;charset=UTF-8",
172
+ ...(sentio && sentioApiKey
173
+ ? {
174
+ "api-key": sentioApiKey,
175
+ }
176
+ : {}),
177
+ ...(graph && graphApiKey
178
+ ? { Authorization: `Bearer ${graphApiKey}` }
179
+ : {}),
180
+ ...parsedRequest.headers,
139
181
  };
182
+ if (sentio || (graph && graphApiKey)) {
183
+ const { url, baseURL, method, params, data, headers, timeout, responseType, allowAbsoluteUrls, } = parsedRequest;
184
+ parsedRequest = {
185
+ url,
186
+ baseURL,
187
+ method,
188
+ params,
189
+ data,
190
+ headers,
191
+ timeout,
192
+ responseType,
193
+ allowAbsoluteUrls,
194
+ proxy: false,
195
+ maxRedirects: 0,
196
+ };
197
+ }
140
198
  await this.delay(1000);
141
199
  try {
142
200
  response = await fetchData(parsedRequest, 0);
143
201
  }
144
202
  catch (error) {
145
203
  const message = error instanceof Error ? error.message : String(error);
146
- throw new DataConnectorTransportError(message.replace(/https?:\/\/[^\s@/]+(?::[^\s@/]+)?@/gi, 'https://[REDACTED]@'));
204
+ throw new DataConnectorTransportError(message.replace(/https?:\/\/[^\s@/]+(?::[^\s@/]+)?@/gi, "https://[REDACTED]@"));
147
205
  }
148
206
  }
149
- const nextRequest = await dataConnector.execute(JSON.stringify(response));
207
+ const nextRequest = await dataConnector.execute(JSON.stringify(response, (_key, value) => typeof value === "bigint" ? value.toString() : value));
150
208
  if (nextRequest === null) {
151
- throw new Error('Data connector returned null request');
209
+ throw new Error("Data connector returned null request");
152
210
  }
153
211
  request = nextRequest;
154
212
  }
155
213
  }
156
214
  catch (e) {
157
215
  // process.env.SILENT_ERRORS
158
- if (process.env.DATA_LOADER_SILENT_ERRORS !== 'true') {
159
- console.error('Data connector failed to process.', e);
216
+ if (process.env.DATA_LOADER_SILENT_ERRORS !== "true") {
217
+ console.error("Data connector failed to process.", e);
160
218
  }
161
219
  throw e;
162
220
  }
163
221
  return dataConnector.getResults();
164
222
  }
165
223
  async transformData(dataConnector, rawData) {
166
- let transformedData = typeof rawData === 'string' ? JSON.parse(rawData) : rawData;
167
- const version = await this.getDataConnectorVersion(dataConnector);
168
- if (version == 1 && transformedData.length > 0) {
224
+ let transformedData = typeof rawData === "string" ? JSON.parse(rawData) : rawData;
225
+ if (Array.isArray(transformedData) &&
226
+ transformedData.length > 0 &&
227
+ transformedData[0] != null) {
169
228
  const keys = Object.keys(transformedData[0]);
170
- const requiredKeys = ['timestamp', 'open', 'high', 'low', 'close'];
229
+ const requiredKeys = ["timestamp", "open", "high", "low", "close"];
171
230
  const hasAllKeys = requiredKeys.every((key) => keys.includes(key));
172
231
  // has the 'lookback' key
173
232
  const lookback = dataConnector?.configObj?.lookback;
174
- if (hasAllKeys && !!lookback) {
233
+ if (hasAllKeys && lookback) {
175
234
  // Now that we have identified a v1 data connector, we need to transform the data so that the data is up to the current execution epoch timestamp
176
235
  if (dataConnector?.executionContext?.epochTimestamp) {
177
236
  const extended = extendOHLCV(transformedData, lookback, dataConnector?.executionContext?.epochTimestamp * 1000);
@@ -1,8 +1,8 @@
1
- import { DataConnector } from './bundle/bundleDataConnector.js';
2
- import { ExecutionApp, type ExecutionAppConfig } from './execution/executionApp.js';
3
- import { DataConnectorExecution } from './execution/executionDataConnector.js';
4
- import type { ExecuteWithContextOptions, VaultConfigPayload } from './types.js';
5
- export type * from './types.js';
1
+ import { DataConnector } from "./bundle/bundleDataConnector.js";
2
+ import { ExecutionApp, type ExecutionAppConfig } from "./execution/executionApp.js";
3
+ import { DataConnectorExecution } from "./execution/executionDataConnector.js";
4
+ import type { ExecuteWithContextOptions, VaultConfigPayload } from "./types.js";
5
+ export type * from "./types.js";
6
+ export { DataConnectorTransportError, ExecutionContextError, StrategyExecutionError, } from "./types.js";
7
+ export type { ExecuteWithContextOptions, ExecutionAppConfig, VaultConfigPayload, };
6
8
  export { DataConnector, DataConnectorExecution, ExecutionApp };
7
- export { DataConnectorTransportError, ExecutionContextError, StrategyExecutionError } from './types.js';
8
- export type { ExecuteWithContextOptions, ExecutionAppConfig, VaultConfigPayload };
package/lib/esm/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { DataConnector } from './bundle/bundleDataConnector.js';
2
- import { ExecutionApp } from './execution/executionApp.js';
3
- import { DataConnectorExecution } from './execution/executionDataConnector.js';
1
+ import { DataConnector } from "./bundle/bundleDataConnector.js";
2
+ import { ExecutionApp, } from "./execution/executionApp.js";
3
+ import { DataConnectorExecution } from "./execution/executionDataConnector.js";
4
+ export { DataConnectorTransportError, ExecutionContextError, StrategyExecutionError, } from "./types.js";
4
5
  export { DataConnector, DataConnectorExecution, ExecutionApp };
5
- export { DataConnectorTransportError, ExecutionContextError, StrategyExecutionError } from './types.js';
@@ -1,8 +1,9 @@
1
- import type { ethers, InterfaceAbi } from 'ethers';
1
+ import type { Abi, PublicClient } from "viem";
2
+ import type { ExecutionAppConfig } from "./execution/executionApp.js";
2
3
  /** Error raised before a strategy is invoked when its supplied SDK anchor is unusable. */
3
4
  export declare class ExecutionContextError extends Error {
4
- readonly code: 'INVALID_EXECUTION_CONTEXT' | 'EXECUTION_CONTEXT_MISMATCH';
5
- constructor(code: ExecutionContextError['code'], message: string);
5
+ readonly code: "INVALID_EXECUTION_CONTEXT" | "EXECUTION_CONTEXT_MISMATCH";
6
+ constructor(code: ExecutionContextError["code"], message: string);
6
7
  }
7
8
  /** Error classification for failures in a connector transport request. */
8
9
  export declare class DataConnectorTransportError extends Error {
@@ -21,8 +22,6 @@ export interface ExecuteWithContextOptions {
21
22
  data: Array<unknown>;
22
23
  /** Resolved strategy execution context. */
23
24
  executionContext: SmartPoolExecutionContext;
24
- identity?: ethers.Provider;
25
- etherRpcConfig?: EtherRpcConfig;
26
25
  forceDeposit?: boolean;
27
26
  }
28
27
  export type VaultInput = {
@@ -84,8 +83,6 @@ export interface ExecutionContext {
84
83
  blockNumber: number;
85
84
  epochTimestamp: number;
86
85
  }
87
- /** Context produced by legacy execution paths, which may not have a chain binding. */
88
- export type LegacyExecutionContext = Omit<ExecutionContext, 'chainId'> & Partial<Pick<ExecutionContext, 'chainId'>>;
89
86
  export interface Position {
90
87
  startTick: number;
91
88
  endTick: number;
@@ -99,17 +96,25 @@ export interface SmartPoolExecutionContext extends ExecutionContext {
99
96
  totalAmount1: string;
100
97
  tickSpacing: number;
101
98
  }
102
- export type RpcConfig = {
103
- url: string;
104
- urls?: ReadonlyArray<string>;
105
- network?: string;
106
- };
107
- export type EtherRpcConfig = {
108
- [key: string]: RpcConfig;
99
+ /** RPC access for one execution chain. URL endpoints are validated individually. */
100
+ export type RpcAccess = {
101
+ client: PublicClient;
102
+ urls?: never;
103
+ } | {
104
+ urls: readonly string[];
105
+ client?: never;
109
106
  };
107
+ export interface DataConnectorOptions {
108
+ wasmFile: string | ArrayBuffer;
109
+ config: string;
110
+ executionConfig: ExecutionAppConfig;
111
+ rpc?: RpcAccess;
112
+ }
113
+ export type ContractAbi = Abi | readonly string[] | string;
110
114
  export interface ViewConfig {
115
+ chainId?: number;
111
116
  address: string;
112
- abi: InterfaceAbi;
117
+ abi: ContractAbi;
113
118
  method: string;
114
119
  arguments: Array<unknown>;
115
120
  }
@@ -127,15 +132,6 @@ export interface Slot0 {
127
132
  timepointIndex?: number;
128
133
  communityFee?: number;
129
134
  }
130
- export type ViewContractConfig = {
131
- epochTimestamp?: number;
132
- blockNumber?: number;
133
- address: string;
134
- abi: any;
135
- arguments: Array<any>;
136
- method: string;
137
- rpcUrl?: string;
138
- };
139
135
  export type JobDetails = {
140
136
  id: string;
141
137
  name: string;
package/lib/esm/types.js CHANGED
@@ -2,7 +2,7 @@
2
2
  export class ExecutionContextError extends Error {
3
3
  constructor(code, message) {
4
4
  super(message);
5
- this.name = 'ExecutionContextError';
5
+ this.name = "ExecutionContextError";
6
6
  this.code = code;
7
7
  }
8
8
  }
@@ -10,15 +10,15 @@ export class ExecutionContextError extends Error {
10
10
  export class DataConnectorTransportError extends Error {
11
11
  constructor(message) {
12
12
  super(message);
13
- this.code = 'DATA_CONNECTOR_TRANSPORT_ERROR';
14
- this.name = 'DataConnectorTransportError';
13
+ this.code = "DATA_CONNECTOR_TRANSPORT_ERROR";
14
+ this.name = "DataConnectorTransportError";
15
15
  }
16
16
  }
17
17
  /** Error classification for a WASM strategy failure. */
18
18
  export class StrategyExecutionError extends Error {
19
19
  constructor(message) {
20
20
  super(message);
21
- this.code = 'STRATEGY_EXECUTION_ERROR';
22
- this.name = 'StrategyExecutionError';
21
+ this.code = "STRATEGY_EXECUTION_ERROR";
22
+ this.name = "StrategyExecutionError";
23
23
  }
24
24
  }
@@ -1,8 +1,8 @@
1
- import type { ethers } from 'ethers';
1
+ import type { PublicClient } from "viem";
2
2
  /**
3
3
  * Iterates down from current block to find the block previous or equal to the given timestamp
4
4
  * Not the most efficient for far past timestamps, a binary search could be used for better performance
5
5
  * @param timestamp
6
6
  * @param Idenity
7
7
  */
8
- export declare function getBlockFromTimestamp(timestamp: number, provider: ethers.Provider): Promise<number>;
8
+ export declare function getBlockFromTimestamp(timestamp: number, provider: PublicClient): Promise<number>;
@@ -5,13 +5,13 @@
5
5
  * @param Idenity
6
6
  */
7
7
  export async function getBlockFromTimestamp(timestamp, provider) {
8
- let currentBlock = (await provider.getBlockNumber()) - 1;
9
- let runningTimestamp = (await provider.getBlock(currentBlock))?.timestamp;
8
+ let currentBlock = Number(await provider.getBlockNumber()) - 1;
9
+ let runningTimestamp = (await provider.getBlock({ blockNumber: BigInt(currentBlock) }))?.timestamp;
10
10
  if (!runningTimestamp)
11
11
  return currentBlock;
12
12
  while (runningTimestamp > timestamp) {
13
13
  currentBlock -= 1;
14
- runningTimestamp = (await provider.getBlock(currentBlock))?.timestamp;
14
+ runningTimestamp = (await provider.getBlock({ blockNumber: BigInt(currentBlock) }))?.timestamp;
15
15
  if (!runningTimestamp)
16
16
  return currentBlock;
17
17
  }