@steerprotocol/data-connector-loader 3.2.1 → 3.2.2

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
@@ -1,6 +1,7 @@
1
1
  # Steer Protocol App Loader
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
6
  - `ExecutionApp`: High-level execution entrypoint for running bundles with a config-based constructor.
6
7
  - `DataConnectorExecution`: Executes data connector bundles and handles request/response flow.
@@ -8,23 +9,13 @@
8
9
  ## Installation
9
10
 
10
11
  ```bash
11
- npm install test-data-connector-loader
12
+ npm install @steerprotocol/data-connector-loader
12
13
  # or
13
- yarn add test-data-connector-loader
14
+ yarn add @steerprotocol/data-connector-loader
14
15
  # or
15
- pnpm add test-data-connector-loader
16
+ pnpm add @steerprotocol/data-connector-loader
16
17
  ```
17
18
 
18
- The package includes an automatic postinstall script that fixes ESM/CJS interoperability issues with dependencies. No additional configuration is needed.
19
-
20
19
  ## ESM Support
21
20
 
22
- This package is an ESM module (`"type": "module"`). It automatically fixes ESM compatibility issues in its dependencies during installation.
23
-
24
- If you encounter import errors after installation, you can manually run the fix script:
25
-
26
- ```bash
27
- npm run postinstall
28
- ```
29
-
30
- For more details about the ESM fixes, see [docs/esm-fixes.md](docs/esm-fixes.md).
21
+ This package publishes both CommonJS and ESM entrypoints via `exports`.
@@ -11,7 +11,32 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.BundleBase = void 0;
13
13
  const app_loader_1 = require("@steerprotocol/app-loader");
14
- const providerUtils_js_1 = require("../utils/providerUtils.js");
14
+ const ethers_1 = require("ethers");
15
+ const UNSTABLE_RPC_PATTERNS = [/drpc\.org/i];
16
+ function createFallbackRpcProvider(urls) {
17
+ const seen = new Set();
18
+ const preferred = [];
19
+ const deprioritized = [];
20
+ for (const url of urls) {
21
+ const trimmed = url.trim();
22
+ if (trimmed.length === 0 || seen.has(trimmed)) {
23
+ continue;
24
+ }
25
+ seen.add(trimmed);
26
+ if (UNSTABLE_RPC_PATTERNS.some((pattern) => pattern.test(trimmed))) {
27
+ deprioritized.push(trimmed);
28
+ }
29
+ else {
30
+ preferred.push(trimmed);
31
+ }
32
+ }
33
+ const prioritized = preferred.length > 0 ? [...preferred, ...deprioritized] : [...preferred, ...deprioritized];
34
+ if (prioritized.length === 0) {
35
+ throw new Error('No RPC URLs configured');
36
+ }
37
+ const providers = prioritized.map((url) => new ethers_1.ethers.JsonRpcProvider(url));
38
+ return providers.length === 1 ? providers[0] : new ethers_1.ethers.FallbackProvider(providers);
39
+ }
15
40
  function bigIntReplacer(_key, value) {
16
41
  return typeof value === 'bigint' ? value.toString() : value;
17
42
  }
@@ -179,7 +204,7 @@ class BundleBase {
179
204
  }
180
205
  if (chainId && this.etherRpcConfig && this.etherRpcConfig[chainId]) {
181
206
  const rpcConfig = this.etherRpcConfig[chainId];
182
- return (0, providerUtils_js_1.createFallbackRpcProvider)((_a = rpcConfig.urls) !== null && _a !== void 0 ? _a : [rpcConfig.url]);
207
+ return createFallbackRpcProvider((_a = rpcConfig.urls) !== null && _a !== void 0 ? _a : [rpcConfig.url]);
183
208
  }
184
209
  else {
185
210
  return this.providerIdentity;
@@ -6,10 +6,4 @@ export declare class DataConnector extends BundleBase {
6
6
  constructor(wasmFile: string | ArrayBuffer, _config: string, executionAppConfig: ExecutionAppConfig, identity?: ethers.Provider, etherRpcConfig?: EtherRpcConfig);
7
7
  getRpcUrl(config: any): string | undefined;
8
8
  view(config: ViewConfig): Promise<string>;
9
- /**
10
- * Attempts to decode raw return data when the declared ABI doesn't match the actual
11
- * contract output. Tries removing trailing outputs one-by-one until decoding succeeds.
12
- * This handles pool variants that omit optional fields (e.g. feeProtocol in slot0).
13
- */
14
- private decodeFallback;
15
9
  }
@@ -48,22 +48,9 @@ class DataConnector extends bundleBase_js_1.BundleBase {
48
48
  const paramsArray = config.arguments;
49
49
  let result;
50
50
  if (consts_js_1.CENTRALIZE_CONTRACT_INTERACTION_CHAINS.indexOf(this.configObj.chainId.toString()) === -1) {
51
- try {
52
- result = yield contract[config.method](...paramsArray, {
53
- blockTag: (_a = this.executionContext) === null || _a === void 0 ? void 0 : _a.blockNumber,
54
- });
55
- }
56
- catch (err) {
57
- // Some pool variants return fewer ABI outputs than the standard spec (e.g. Aerodrome/
58
- // Velodrome slot0 has 6 fields instead of 7 — no feeProtocol). When ethers fails to
59
- // decode the raw return data, fall back to decoding with progressively fewer outputs.
60
- if ((err === null || err === void 0 ? void 0 : err.code) === 'BAD_DATA' && (err === null || err === void 0 ? void 0 : err.value)) {
61
- result = this.decodeFallback(err.value, config);
62
- }
63
- else {
64
- throw err;
65
- }
66
- }
51
+ result = yield contract[config.method](...paramsArray, {
52
+ blockTag: (_a = this.executionContext) === null || _a === void 0 ? void 0 : _a.blockNumber,
53
+ });
67
54
  }
68
55
  else {
69
56
  const viewContractConfig = {
@@ -80,30 +67,5 @@ class DataConnector extends bundleBase_js_1.BundleBase {
80
67
  return result;
81
68
  });
82
69
  }
83
- /**
84
- * Attempts to decode raw return data when the declared ABI doesn't match the actual
85
- * contract output. Tries removing trailing outputs one-by-one until decoding succeeds.
86
- * This handles pool variants that omit optional fields (e.g. feeProtocol in slot0).
87
- */
88
- decodeFallback(rawData, config) {
89
- var _a;
90
- const iface = new ethers_1.Interface(config.abi);
91
- const fragment = iface.getFunction(config.method);
92
- if (!((_a = fragment === null || fragment === void 0 ? void 0 : fragment.outputs) === null || _a === void 0 ? void 0 : _a.length)) {
93
- throw new Error(`Cannot find outputs for method "${config.method}" in ABI`);
94
- }
95
- const coder = ethers_1.AbiCoder.defaultAbiCoder();
96
- for (let numOutputs = fragment.outputs.length - 1; numOutputs >= 1; numOutputs--) {
97
- try {
98
- const types = fragment.outputs.slice(0, numOutputs).map((o) => o.format());
99
- const decoded = coder.decode(types, rawData);
100
- return decoded;
101
- }
102
- catch (_b) {
103
- // try with one fewer output
104
- }
105
- }
106
- throw new Error(`Could not decode result data for method "${config.method}" — no matching ABI shape found`);
107
- }
108
70
  }
109
71
  exports.DataConnector = DataConnector;
@@ -1,5 +1,30 @@
1
1
  import { loadWasm, loadWasmSync } from '@steerprotocol/app-loader';
2
- import { createFallbackRpcProvider } from '../utils/providerUtils.js';
2
+ import { ethers } from 'ethers';
3
+ const UNSTABLE_RPC_PATTERNS = [/drpc\.org/i];
4
+ function createFallbackRpcProvider(urls) {
5
+ const seen = new Set();
6
+ const preferred = [];
7
+ const deprioritized = [];
8
+ for (const url of urls) {
9
+ const trimmed = url.trim();
10
+ if (trimmed.length === 0 || seen.has(trimmed)) {
11
+ continue;
12
+ }
13
+ seen.add(trimmed);
14
+ if (UNSTABLE_RPC_PATTERNS.some((pattern) => pattern.test(trimmed))) {
15
+ deprioritized.push(trimmed);
16
+ }
17
+ else {
18
+ preferred.push(trimmed);
19
+ }
20
+ }
21
+ const prioritized = preferred.length > 0 ? [...preferred, ...deprioritized] : [...preferred, ...deprioritized];
22
+ if (prioritized.length === 0) {
23
+ throw new Error('No RPC URLs configured');
24
+ }
25
+ const providers = prioritized.map((url) => new ethers.JsonRpcProvider(url));
26
+ return providers.length === 1 ? providers[0] : new ethers.FallbackProvider(providers);
27
+ }
3
28
  function bigIntReplacer(_key, value) {
4
29
  return typeof value === 'bigint' ? value.toString() : value;
5
30
  }
@@ -6,10 +6,4 @@ export declare class DataConnector extends BundleBase {
6
6
  constructor(wasmFile: string | ArrayBuffer, _config: string, executionAppConfig: ExecutionAppConfig, identity?: ethers.Provider, etherRpcConfig?: EtherRpcConfig);
7
7
  getRpcUrl(config: any): string | undefined;
8
8
  view(config: ViewConfig): Promise<string>;
9
- /**
10
- * Attempts to decode raw return data when the declared ABI doesn't match the actual
11
- * contract output. Tries removing trailing outputs one-by-one until decoding succeeds.
12
- * This handles pool variants that omit optional fields (e.g. feeProtocol in slot0).
13
- */
14
- private decodeFallback;
15
9
  }
@@ -1,4 +1,4 @@
1
- import { AbiCoder, Contract, Interface } from 'ethers';
1
+ import { Contract } from 'ethers';
2
2
  import { CENTRALIZE_CONTRACT_INTERACTION_CHAINS } from '../utils/consts.js';
3
3
  import { callWithRetry } from '../utils/utils.js';
4
4
  import { BundleBase } from './bundleBase.js';
@@ -34,22 +34,9 @@ export class DataConnector extends BundleBase {
34
34
  const paramsArray = config.arguments;
35
35
  let result;
36
36
  if (CENTRALIZE_CONTRACT_INTERACTION_CHAINS.indexOf(this.configObj.chainId.toString()) === -1) {
37
- try {
38
- result = await contract[config.method](...paramsArray, {
39
- blockTag: this.executionContext?.blockNumber,
40
- });
41
- }
42
- catch (err) {
43
- // Some pool variants return fewer ABI outputs than the standard spec (e.g. Aerodrome/
44
- // Velodrome slot0 has 6 fields instead of 7 — no feeProtocol). When ethers fails to
45
- // decode the raw return data, fall back to decoding with progressively fewer outputs.
46
- if (err?.code === 'BAD_DATA' && err?.value) {
47
- result = this.decodeFallback(err.value, config);
48
- }
49
- else {
50
- throw err;
51
- }
52
- }
37
+ result = await contract[config.method](...paramsArray, {
38
+ blockTag: this.executionContext?.blockNumber,
39
+ });
53
40
  }
54
41
  else {
55
42
  const viewContractConfig = {
@@ -65,28 +52,4 @@ export class DataConnector extends BundleBase {
65
52
  // This gets stringified before calling main
66
53
  return result;
67
54
  }
68
- /**
69
- * Attempts to decode raw return data when the declared ABI doesn't match the actual
70
- * contract output. Tries removing trailing outputs one-by-one until decoding succeeds.
71
- * This handles pool variants that omit optional fields (e.g. feeProtocol in slot0).
72
- */
73
- decodeFallback(rawData, config) {
74
- const iface = new Interface(config.abi);
75
- const fragment = iface.getFunction(config.method);
76
- if (!fragment?.outputs?.length) {
77
- throw new Error(`Cannot find outputs for method "${config.method}" in ABI`);
78
- }
79
- const coder = AbiCoder.defaultAbiCoder();
80
- for (let numOutputs = fragment.outputs.length - 1; numOutputs >= 1; numOutputs--) {
81
- try {
82
- const types = fragment.outputs.slice(0, numOutputs).map((o) => o.format());
83
- const decoded = coder.decode(types, rawData);
84
- return decoded;
85
- }
86
- catch {
87
- // try with one fewer output
88
- }
89
- }
90
- throw new Error(`Could not decode result data for method "${config.method}" — no matching ABI shape found`);
91
- }
92
55
  }
@@ -501,8 +501,12 @@ export class ExecutionApp extends ExecutionBase {
501
501
  const dataConnector = new DataConnector(_wasmFile, _vaultConfig, this.config, _identity, _etherRpcConfig);
502
502
  await dataConnector.loadSync();
503
503
  const executionContext = await this.getExecutionContext(dataConnector, JSON.parse(_vaultConfig));
504
+ const smartRewardsContractAddress = _job.targetAddresses[0];
505
+ if (!smartRewardsContractAddress) {
506
+ throw new Error('Dynamic job must include at least one target address');
507
+ }
504
508
  const dynamicJobExecutionContext = {
505
- smartRewardsContractAddress: _job.targetAddresses?.[0],
509
+ smartRewardsContractAddress,
506
510
  };
507
511
  dataConnector.setExecutionContextStrategyExecution({
508
512
  ...executionContext,
@@ -108,10 +108,10 @@ export type ViewContractConfig = {
108
108
  };
109
109
  export type JobDetails = {
110
110
  id: string;
111
- name?: string;
112
- timestamp?: string;
113
- jobInfo?: ReadonlyArray<unknown>;
114
- targetAddresses?: ReadonlyArray<string>;
115
- ipfsHash?: string;
116
- status?: string;
111
+ name: string;
112
+ timestamp: string;
113
+ jobInfo: ReadonlyArray<unknown>;
114
+ targetAddresses: ReadonlyArray<string>;
115
+ ipfsHash: string;
116
+ status: string;
117
117
  };
@@ -509,13 +509,16 @@ class ExecutionApp extends executionBase_js_1.ExecutionBase {
509
509
  });
510
510
  }
511
511
  executeDynamicJobs(_wasmFile, _vaultConfig, _data, _job, _identity, _etherRpcConfig, forceDeposit) {
512
- var _a;
513
512
  return __awaiter(this, void 0, void 0, function* () {
514
513
  const dataConnector = new bundleDataConnector_js_1.DataConnector(_wasmFile, _vaultConfig, this.config, _identity, _etherRpcConfig);
515
514
  yield dataConnector.loadSync();
516
515
  const executionContext = yield this.getExecutionContext(dataConnector, JSON.parse(_vaultConfig));
516
+ const smartRewardsContractAddress = _job.targetAddresses[0];
517
+ if (!smartRewardsContractAddress) {
518
+ throw new Error('Dynamic job must include at least one target address');
519
+ }
517
520
  const dynamicJobExecutionContext = {
518
- smartRewardsContractAddress: (_a = _job.targetAddresses) === null || _a === void 0 ? void 0 : _a[0],
521
+ smartRewardsContractAddress,
519
522
  };
520
523
  dataConnector.setExecutionContextStrategyExecution(Object.assign(Object.assign({}, executionContext), dynamicJobExecutionContext), forceDeposit);
521
524
  _data = _data.map((element) => JSON.stringify(element));
package/lib/types.d.ts CHANGED
@@ -108,10 +108,10 @@ export type ViewContractConfig = {
108
108
  };
109
109
  export type JobDetails = {
110
110
  id: string;
111
- name?: string;
112
- timestamp?: string;
113
- jobInfo?: ReadonlyArray<unknown>;
114
- targetAddresses?: ReadonlyArray<string>;
115
- ipfsHash?: string;
116
- status?: string;
111
+ name: string;
112
+ timestamp: string;
113
+ jobInfo: ReadonlyArray<unknown>;
114
+ targetAddresses: ReadonlyArray<string>;
115
+ ipfsHash: string;
116
+ status: string;
117
117
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steerprotocol/data-connector-loader",
3
- "version": "3.2.1",
3
+ "version": "3.2.2",
4
4
  "description": "App Loader for Steer Protocol",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -24,7 +24,6 @@
24
24
  "test": "jest --config jest.config.cjs",
25
25
  "pack:local": "npm pack",
26
26
  "publish:test": "node scripts/publish-test.cjs",
27
- "postinstall": "node scripts/fix-node-modules.js",
28
27
  "prepare": "npm run build",
29
28
  "prepublishOnly": "npm test && npm run lint",
30
29
  "preversion": "npm run lint",
@@ -84,8 +83,8 @@
84
83
  "lib/**/*"
85
84
  ],
86
85
  "dependencies": {
87
- "@steerprotocol/sdk": "^1.28.0",
88
86
  "@steerprotocol/app-loader": "^2.1.1",
87
+ "@steerprotocol/sdk": "^2.0.0",
89
88
  "@steerprotocol/strategy-utils": "^3.1.2",
90
89
  "axios": "^1.3.4",
91
90
  "ethers": "^6.16.0",
@@ -1,4 +0,0 @@
1
- import { ethers } from 'ethers';
2
- export declare const prioritizeRpcUrls: (urls: ReadonlyArray<string>) => Array<string>;
3
- export declare const getPrimaryRpcUrl: (urls: ReadonlyArray<string>) => string;
4
- export declare const createFallbackRpcProvider: (urls: ReadonlyArray<string>) => ethers.Provider;
@@ -1,37 +0,0 @@
1
- import { ethers } from 'ethers';
2
- const UNSTABLE_RPC_PATTERNS = [/drpc\.org/i];
3
- const uniqueUrls = (urls) => {
4
- const seen = new Set();
5
- const normalized = [];
6
- for (const url of urls) {
7
- const trimmed = url.trim();
8
- if (trimmed.length === 0 || seen.has(trimmed)) {
9
- continue;
10
- }
11
- seen.add(trimmed);
12
- normalized.push(trimmed);
13
- }
14
- return normalized;
15
- };
16
- const isDeprioritizedRpcUrl = (url) => UNSTABLE_RPC_PATTERNS.some((pattern) => pattern.test(url));
17
- export const prioritizeRpcUrls = (urls) => {
18
- const normalized = uniqueUrls(urls);
19
- const preferred = normalized.filter((url) => !isDeprioritizedRpcUrl(url));
20
- const deprioritized = normalized.filter((url) => isDeprioritizedRpcUrl(url));
21
- return preferred.length > 0 ? [...preferred, ...deprioritized] : normalized;
22
- };
23
- export const getPrimaryRpcUrl = (urls) => {
24
- const prioritized = prioritizeRpcUrls(urls);
25
- if (prioritized.length === 0) {
26
- throw new Error('No RPC URLs configured');
27
- }
28
- return prioritized[0];
29
- };
30
- export const createFallbackRpcProvider = (urls) => {
31
- const prioritized = prioritizeRpcUrls(urls);
32
- if (prioritized.length === 0) {
33
- throw new Error('No RPC URLs configured');
34
- }
35
- const providers = prioritized.map((url) => new ethers.JsonRpcProvider(url));
36
- return providers.length === 1 ? providers[0] : new ethers.FallbackProvider(providers);
37
- };
@@ -1,4 +0,0 @@
1
- import { ethers } from 'ethers';
2
- export declare const prioritizeRpcUrls: (urls: ReadonlyArray<string>) => Array<string>;
3
- export declare const getPrimaryRpcUrl: (urls: ReadonlyArray<string>) => string;
4
- export declare const createFallbackRpcProvider: (urls: ReadonlyArray<string>) => ethers.Provider;
@@ -1,43 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createFallbackRpcProvider = exports.getPrimaryRpcUrl = exports.prioritizeRpcUrls = void 0;
4
- const ethers_1 = require("ethers");
5
- const UNSTABLE_RPC_PATTERNS = [/drpc\.org/i];
6
- const uniqueUrls = (urls) => {
7
- const seen = new Set();
8
- const normalized = [];
9
- for (const url of urls) {
10
- const trimmed = url.trim();
11
- if (trimmed.length === 0 || seen.has(trimmed)) {
12
- continue;
13
- }
14
- seen.add(trimmed);
15
- normalized.push(trimmed);
16
- }
17
- return normalized;
18
- };
19
- const isDeprioritizedRpcUrl = (url) => UNSTABLE_RPC_PATTERNS.some((pattern) => pattern.test(url));
20
- const prioritizeRpcUrls = (urls) => {
21
- const normalized = uniqueUrls(urls);
22
- const preferred = normalized.filter((url) => !isDeprioritizedRpcUrl(url));
23
- const deprioritized = normalized.filter((url) => isDeprioritizedRpcUrl(url));
24
- return preferred.length > 0 ? [...preferred, ...deprioritized] : normalized;
25
- };
26
- exports.prioritizeRpcUrls = prioritizeRpcUrls;
27
- const getPrimaryRpcUrl = (urls) => {
28
- const prioritized = (0, exports.prioritizeRpcUrls)(urls);
29
- if (prioritized.length === 0) {
30
- throw new Error('No RPC URLs configured');
31
- }
32
- return prioritized[0];
33
- };
34
- exports.getPrimaryRpcUrl = getPrimaryRpcUrl;
35
- const createFallbackRpcProvider = (urls) => {
36
- const prioritized = (0, exports.prioritizeRpcUrls)(urls);
37
- if (prioritized.length === 0) {
38
- throw new Error('No RPC URLs configured');
39
- }
40
- const providers = prioritized.map((url) => new ethers_1.ethers.JsonRpcProvider(url));
41
- return providers.length === 1 ? providers[0] : new ethers_1.ethers.FallbackProvider(providers);
42
- };
43
- exports.createFallbackRpcProvider = createFallbackRpcProvider;