@steerprotocol/data-connector-loader 0.1.5 → 1.0.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.
Files changed (48) hide show
  1. package/lib/bundle/bundleBase.d.ts +29 -0
  2. package/lib/{dataConnector.js → bundle/bundleBase.js} +59 -42
  3. package/lib/bundle/bundleDataConnector.d.ts +8 -0
  4. package/lib/bundle/bundleDataConnector.js +73 -0
  5. package/lib/esm/bundle/bundleBase.d.ts +29 -0
  6. package/lib/esm/bundle/bundleBase.js +127 -0
  7. package/lib/esm/bundle/bundleDataConnector.d.ts +8 -0
  8. package/lib/esm/bundle/bundleDataConnector.js +57 -0
  9. package/lib/esm/execution/executionApp.d.ts +17 -0
  10. package/lib/esm/execution/executionApp.js +304 -0
  11. package/lib/esm/execution/executionBase.d.ts +14 -0
  12. package/lib/esm/execution/executionBase.js +95 -0
  13. package/lib/esm/execution/executionDataConnector.d.ts +9 -0
  14. package/lib/esm/execution/executionDataConnector.js +90 -0
  15. package/lib/esm/index.d.ts +5 -0
  16. package/lib/esm/index.js +5 -0
  17. package/lib/esm/package.json +1 -0
  18. package/lib/esm/types.d.ts +104 -0
  19. package/lib/esm/types.js +1 -0
  20. package/lib/esm/utils/blockFinder.js +20 -0
  21. package/lib/esm/utils/consts.d.ts +4 -0
  22. package/lib/esm/utils/consts.js +4 -0
  23. package/lib/esm/utils/pluginManager.js +67 -0
  24. package/lib/esm/utils/utils.d.ts +16 -0
  25. package/lib/esm/utils/utils.js +119 -0
  26. package/lib/execution/executionApp.d.ts +17 -0
  27. package/lib/execution/executionApp.js +323 -0
  28. package/lib/execution/executionBase.d.ts +14 -0
  29. package/lib/execution/executionBase.js +118 -0
  30. package/lib/execution/executionDataConnector.d.ts +9 -0
  31. package/lib/execution/executionDataConnector.js +110 -0
  32. package/lib/index.d.ts +5 -15
  33. package/lib/index.js +21 -197
  34. package/lib/types.d.ts +40 -0
  35. package/lib/utils/blockFinder.d.ts +8 -0
  36. package/lib/utils/consts.d.ts +4 -0
  37. package/lib/utils/consts.js +7 -0
  38. package/lib/utils/pluginManager.d.ts +11 -0
  39. package/lib/utils/utils.d.ts +16 -0
  40. package/lib/utils/utils.js +146 -0
  41. package/package.json +35 -5
  42. package/lib/dataConnector.d.ts +0 -27
  43. package/lib/utils.d.ts +0 -2
  44. package/lib/utils.js +0 -28
  45. /package/lib/{blockFinder.d.ts → esm/utils/blockFinder.d.ts} +0 -0
  46. /package/lib/{pluginManager.d.ts → esm/utils/pluginManager.d.ts} +0 -0
  47. /package/lib/{blockFinder.js → utils/blockFinder.js} +0 -0
  48. /package/lib/{pluginManager.js → utils/pluginManager.js} +0 -0
@@ -0,0 +1,9 @@
1
+ import { ExecutionBase } from './executionBase';
2
+ import { DataConnector } from '../bundle/bundleDataConnector';
3
+ export declare class DataConnectorExecution extends ExecutionBase {
4
+ private dataConnectors;
5
+ constructor(dataConnectors: Array<DataConnector>, maxRetries?: number);
6
+ execute<T>(_vaultConfig: string): Promise<Array<T>>;
7
+ private handleRequestResponse;
8
+ private transformData;
9
+ }
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.DataConnectorExecution = void 0;
13
+ const executionBase_1 = require("./executionBase");
14
+ const pluginManager_1 = require("../utils/pluginManager");
15
+ const utils_1 = require("../utils/utils");
16
+ class DataConnectorExecution extends executionBase_1.ExecutionBase {
17
+ constructor(dataConnectors, maxRetries = 3) {
18
+ super(maxRetries);
19
+ this.dataConnectors = dataConnectors;
20
+ }
21
+ execute(_vaultConfig) {
22
+ return __awaiter(this, void 0, void 0, function* () {
23
+ const vaultConfig = JSON.parse(_vaultConfig);
24
+ const transformationData = [];
25
+ const pluginManager = new pluginManager_1.PluginManager();
26
+ yield pluginManager.registerFromPublicConfig();
27
+ for (const dataConnector of this.dataConnectors) {
28
+ if (!dataConnector.module) {
29
+ yield dataConnector.load();
30
+ }
31
+ const executionContext = yield this.getExecutionContext(dataConnector, vaultConfig);
32
+ dataConnector.setExecutionContextDataConnector(executionContext);
33
+ const version = yield this.getDataConnectorVersion(dataConnector);
34
+ if (version === 1) {
35
+ const initialRequest = yield dataConnector.execute('');
36
+ const finalResponse = yield this.handleRequestResponse(dataConnector, pluginManager, initialRequest);
37
+ const transformedData = yield this.transformData(dataConnector, finalResponse);
38
+ transformationData.push(transformedData);
39
+ }
40
+ else {
41
+ const finalResponse = yield dataConnector.execute('');
42
+ const transformedData = yield this.transformData(dataConnector, finalResponse);
43
+ transformationData.push(transformedData);
44
+ }
45
+ }
46
+ return transformationData;
47
+ });
48
+ }
49
+ handleRequestResponse(dataConnector, pluginManager, initialRequest) {
50
+ return __awaiter(this, void 0, void 0, function* () {
51
+ let request = initialRequest;
52
+ let response;
53
+ try {
54
+ while (request !== 'true') {
55
+ if (dataConnector.configObj.isChainRead == true) {
56
+ response = yield dataConnector.view(JSON.parse(request));
57
+ }
58
+ else {
59
+ const parsedRequest = yield pluginManager.process(typeof request == 'string' ? JSON.parse(request) : request);
60
+ yield this.delay(1000);
61
+ response = yield (0, utils_1.fetchData)(parsedRequest, 0);
62
+ }
63
+ request = yield dataConnector.execute(JSON.stringify(response));
64
+ }
65
+ }
66
+ catch (e) {
67
+ // process.env.SILENT_ERRORS
68
+ if (process.env.DATA_LOADER_SILENT_ERRORS !== 'true') {
69
+ console.error('Data connector failed to process.', e);
70
+ }
71
+ throw e;
72
+ }
73
+ return dataConnector.getResults();
74
+ });
75
+ }
76
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
77
+ transformData(dataConnector, rawData) {
78
+ var _a, _b, _c;
79
+ return __awaiter(this, void 0, void 0, function* () {
80
+ let transformedData = typeof rawData === 'string' ? JSON.parse(rawData) : rawData;
81
+ if (transformedData == null || transformedData.length == 0) {
82
+ const results = dataConnector.getResults();
83
+ const parsedResults = JSON.parse(results);
84
+ if (parsedResults.length == null) {
85
+ transformedData = results;
86
+ }
87
+ else {
88
+ transformedData = parsedResults;
89
+ }
90
+ }
91
+ const version = yield this.getDataConnectorVersion(dataConnector);
92
+ if (version == 1 && transformedData.length > 0) {
93
+ const keys = Object.keys(transformedData[0]);
94
+ const requiredKeys = ['timestamp', 'open', 'high', 'low', 'close'];
95
+ const hasAllKeys = requiredKeys.every((key) => keys.includes(key));
96
+ // has the 'lookback' key
97
+ const lookback = (_a = dataConnector === null || dataConnector === void 0 ? void 0 : dataConnector.configObj) === null || _a === void 0 ? void 0 : _a.lookback;
98
+ if (hasAllKeys && !!lookback) {
99
+ // 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
100
+ if ((_b = dataConnector === null || dataConnector === void 0 ? void 0 : dataConnector.executionContext) === null || _b === void 0 ? void 0 : _b.epochTimestamp) {
101
+ const extended = (0, utils_1.extendOHLCV)(transformedData, lookback, ((_c = dataConnector === null || dataConnector === void 0 ? void 0 : dataConnector.executionContext) === null || _c === void 0 ? void 0 : _c.epochTimestamp) * 1000);
102
+ transformedData = extended;
103
+ }
104
+ }
105
+ }
106
+ return transformedData;
107
+ });
108
+ }
109
+ }
110
+ exports.DataConnectorExecution = DataConnectorExecution;
package/lib/index.d.ts CHANGED
@@ -1,15 +1,5 @@
1
- import { DataConnector } from './dataConnector';
2
- import { ethers } from 'ethers';
3
- export { DataConnector };
4
- export declare class DataConnectorExecution {
5
- private dataConnectors;
6
- constructor(dataConnectors: Array<DataConnector>);
7
- private delay;
8
- private log;
9
- private fetchData;
10
- private exponentialBackoffDelay;
11
- execute<T>(_vaultConfig: string): Promise<Array<T>>;
12
- getAverageBlockTime(provider: ethers.providers.Provider, blockCount?: number): Promise<number>;
13
- getBlockNumberFromAvgBlockTime(provider: ethers.providers.Provider, targetTimestamp: number, avgBlockTime: number): Promise<number>;
14
- private downloadWasmBundle;
15
- }
1
+ import { DataConnector } from './bundle/bundleDataConnector';
2
+ import { DataConnectorExecution } from './execution/executionDataConnector';
3
+ import { ExecutionApp } from './execution/executionApp';
4
+ export * from './types';
5
+ export { DataConnector, DataConnectorExecution, ExecutionApp };
package/lib/index.js CHANGED
@@ -1,200 +1,24 @@
1
1
  "use strict";
2
- var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
- return new (P || (P = Promise))(function (resolve, reject) {
5
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
- step((generator = generator.apply(thisArg, _arguments || [])).next());
9
- });
10
- };
11
- var __importDefault = (this && this.__importDefault) || function (mod) {
12
- return (mod && mod.__esModule) ? mod : { "default": mod };
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
13
15
  };
14
16
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.DataConnectorExecution = exports.DataConnector = void 0;
16
- const dataConnector_1 = require("./dataConnector");
17
- Object.defineProperty(exports, "DataConnector", { enumerable: true, get: function () { return dataConnector_1.DataConnector; } });
18
- const axios_1 = __importDefault(require("axios"));
19
- const pluginManager_1 = require("./pluginManager");
20
- const utils_1 = require("./utils");
21
- class DataConnectorExecution {
22
- constructor(dataConnectors) {
23
- this.dataConnectors = dataConnectors;
24
- }
25
- delay(ms) {
26
- return new Promise((resolve) => setTimeout(resolve, ms));
27
- }
28
- log(...args) {
29
- if (process.env.DEBUG === 'true') {
30
- console.log(...args);
31
- }
32
- }
33
- fetchData(request, attempts) {
34
- return __awaiter(this, void 0, void 0, function* () {
35
- this.log('Request payload: =============', request);
36
- attempts = attempts + 1;
37
- try {
38
- const response = (yield (0, axios_1.default)(request)).data;
39
- this.log('API Response: =============', response);
40
- if ('errors' in response && response['errors'].length > 0) {
41
- if (attempts < 3) {
42
- yield this.delay(this.exponentialBackoffDelay(attempts));
43
- return yield this.fetchData(request, attempts);
44
- }
45
- else {
46
- throw new Error('Maximum retry attempts reached');
47
- }
48
- }
49
- return response;
50
- }
51
- catch (error) {
52
- if (attempts < 3) {
53
- yield this.delay(this.exponentialBackoffDelay(attempts));
54
- return yield this.fetchData(request, attempts);
55
- }
56
- else {
57
- throw error;
58
- }
59
- }
60
- });
61
- }
62
- exponentialBackoffDelay(attempts) {
63
- const baseDelay = 1000; // 1 second
64
- const maxDelay = 30000; // 30 seconds
65
- const delay = Math.min(baseDelay * Math.pow(2, attempts - 1), maxDelay);
66
- return delay;
67
- }
68
- execute(_vaultConfig) {
69
- var _a, _b, _c;
70
- return __awaiter(this, void 0, void 0, function* () {
71
- const executionTimestamp = new Date().getTime();
72
- const vaultConfig = JSON.parse(_vaultConfig);
73
- const transformationData = [];
74
- const pluginManager = new pluginManager_1.PluginManager();
75
- yield pluginManager.registerFromPublicConfig();
76
- for (const dataConnector of this.dataConnectors) {
77
- if (!dataConnector.module) {
78
- yield dataConnector.load();
79
- }
80
- const provider = dataConnector.getProvider({});
81
- let blockTime = 0;
82
- let blockNumber = 9;
83
- if (provider) {
84
- blockTime = yield this.getAverageBlockTime(provider);
85
- blockNumber = yield this.getBlockNumberFromAvgBlockTime(provider, vaultConfig.epochTimestamp / 1000, // convert to seconds
86
- blockTime);
87
- }
88
- dataConnector.setExecutionContext({
89
- executionTimestamp,
90
- epochTimestamp: vaultConfig.epochTimestamp,
91
- epochLength: Number(vaultConfig.strategyConfigData.epochLength),
92
- vaultAddress: vaultConfig.vaultAddress,
93
- blockTime,
94
- blockNumber,
95
- });
96
- let version = 1;
97
- try {
98
- version = yield dataConnector.version();
99
- }
100
- catch (e) {
101
- // Data connector is missing version function, fallback to v1 logic
102
- }
103
- let request = yield dataConnector.execute('');
104
- let response;
105
- try {
106
- while (request !== 'true') {
107
- if (dataConnector.configObj.isChainRead == true) {
108
- response = yield dataConnector.view(JSON.parse(request));
109
- }
110
- else {
111
- const parsedRequest = yield pluginManager.process(typeof request == 'string' ? JSON.parse(request) : request);
112
- yield this.delay(1000);
113
- response = yield this.fetchData(parsedRequest, 0);
114
- }
115
- request = yield dataConnector.execute(JSON.stringify(response));
116
- }
117
- }
118
- catch (e) {
119
- // process.env.SILENT_ERRORS
120
- if (process.env.DATA_LOADER_SILENT_ERRORS !== 'true') {
121
- console.error('Data connector failed to process.', e);
122
- }
123
- throw e;
124
- }
125
- let transformedData = JSON.parse(dataConnector.getResults());
126
- if (version == 1 && transformedData.length > 0) {
127
- const keys = Object.keys(transformedData[0]);
128
- const requiredKeys = ['timestamp', 'open', 'high', 'low', 'close'];
129
- const hasAllKeys = requiredKeys.every((key) => keys.includes(key));
130
- // has the 'lookback' key
131
- const lookback = (_a = dataConnector === null || dataConnector === void 0 ? void 0 : dataConnector.configObj) === null || _a === void 0 ? void 0 : _a.lookback;
132
- if (hasAllKeys && !!lookback) {
133
- // 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
134
- if ((_b = dataConnector === null || dataConnector === void 0 ? void 0 : dataConnector.executionContext) === null || _b === void 0 ? void 0 : _b.epochTimestamp) {
135
- const extended = (0, utils_1.extendOHLCV)(transformedData, lookback, ((_c = dataConnector === null || dataConnector === void 0 ? void 0 : dataConnector.executionContext) === null || _c === void 0 ? void 0 : _c.epochTimestamp) * 1000);
136
- transformedData = extended;
137
- }
138
- }
139
- }
140
- transformationData.push(transformedData);
141
- }
142
- return transformationData;
143
- });
144
- }
145
- getAverageBlockTime(provider, blockCount = 5) {
146
- return __awaiter(this, void 0, void 0, function* () {
147
- const latestBlock = yield provider.getBlock('latest');
148
- if (latestBlock) {
149
- const startBlockNumber = Math.max(0, latestBlock.number - blockCount + 1);
150
- let totalTimeDiff = 0;
151
- let previousBlock = yield provider.getBlock(startBlockNumber);
152
- if (!previousBlock) {
153
- return 0;
154
- }
155
- for (let i = startBlockNumber + 1; i <= latestBlock.number; i++) {
156
- const currentBlock = yield provider.getBlock(i);
157
- if (!currentBlock || !previousBlock || !currentBlock.timestamp || !previousBlock.timestamp) {
158
- continue;
159
- }
160
- const timeDiff = currentBlock.timestamp - previousBlock.timestamp;
161
- totalTimeDiff += timeDiff;
162
- previousBlock = currentBlock;
163
- }
164
- const averageBlockTime = totalTimeDiff / (blockCount - 1);
165
- return averageBlockTime;
166
- }
167
- else {
168
- return 0;
169
- }
170
- });
171
- }
172
- getBlockNumberFromAvgBlockTime(provider, targetTimestamp, avgBlockTime) {
173
- return __awaiter(this, void 0, void 0, function* () {
174
- const latestBlock = yield provider.getBlock('latest');
175
- const currentTime = Math.floor(Date.now() / 1000);
176
- const timeDifference = currentTime - targetTimestamp;
177
- if (!latestBlock) {
178
- return 0;
179
- }
180
- if (avgBlockTime === 0) {
181
- return latestBlock.number;
182
- }
183
- // Calculate the estimated number of blocks based on the average block time
184
- const estimatedBlockCount = Math.floor(timeDifference / avgBlockTime);
185
- // Calculate the estimated block number
186
- const estimatedBlockNumber = latestBlock.number - estimatedBlockCount;
187
- return Math.max(0, estimatedBlockNumber);
188
- });
189
- }
190
- downloadWasmBundle(ipfsHash) {
191
- return __awaiter(this, void 0, void 0, function* () {
192
- const response = yield axios_1.default.get(`https://steerprotocol.mypinata.cloud/ipfs/${ipfsHash}`, {
193
- responseType: 'arraybuffer',
194
- });
195
- const wasmFile = new Uint8Array(response.data);
196
- return wasmFile;
197
- });
198
- }
199
- }
200
- exports.DataConnectorExecution = DataConnectorExecution;
17
+ exports.ExecutionApp = exports.DataConnectorExecution = exports.DataConnector = void 0;
18
+ const bundleDataConnector_1 = require("./bundle/bundleDataConnector");
19
+ Object.defineProperty(exports, "DataConnector", { enumerable: true, get: function () { return bundleDataConnector_1.DataConnector; } });
20
+ const executionDataConnector_1 = require("./execution/executionDataConnector");
21
+ Object.defineProperty(exports, "DataConnectorExecution", { enumerable: true, get: function () { return executionDataConnector_1.DataConnectorExecution; } });
22
+ const executionApp_1 = require("./execution/executionApp");
23
+ Object.defineProperty(exports, "ExecutionApp", { enumerable: true, get: function () { return executionApp_1.ExecutionApp; } });
24
+ __exportStar(require("./types"), exports);
package/lib/types.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { ContractInterface } from 'ethers';
1
2
  export type VaultInput = {
2
3
  _id?: string;
3
4
  tokenId: string;
@@ -25,6 +26,7 @@ export interface VaultConfigPayload {
25
26
  dataConnectorsData: DataConnectorsDaum[];
26
27
  vaultAddress: string;
27
28
  epochTimestamp: number;
29
+ anchorBlockNumber?: number;
28
30
  }
29
31
  export interface StrategyConfigData {
30
32
  [key: string]: string | number;
@@ -55,6 +57,16 @@ export interface ExecutionContext {
55
57
  blockNumber: number;
56
58
  epochTimestamp: number;
57
59
  }
60
+ export interface Position {
61
+ startTick: number;
62
+ endTick: number;
63
+ weight: number;
64
+ }
65
+ export interface SmartPoolExecutionContext extends ExecutionContext {
66
+ positions: Position[];
67
+ currentTick: number;
68
+ lastExecutionTime: number;
69
+ }
58
70
  export type RpcConfig = {
59
71
  url: string;
60
72
  network?: string;
@@ -62,3 +74,31 @@ export type RpcConfig = {
62
74
  export type EtherRpcConfig = {
63
75
  [key: string]: RpcConfig;
64
76
  };
77
+ export interface ViewConfig {
78
+ address: string;
79
+ abi: ContractInterface;
80
+ method: string;
81
+ arguments: unknown[];
82
+ }
83
+ export interface Slot0 {
84
+ sqrtPriceX96?: bigint;
85
+ tick: number;
86
+ observationIndex?: number;
87
+ observationCardinality?: number;
88
+ observationCardinalityNext?: number;
89
+ feeProtocol?: number;
90
+ unlocked: boolean;
91
+ price?: bigint;
92
+ prevInitializedTick?: number;
93
+ fee?: number;
94
+ timepointIndex?: number;
95
+ communityFee?: number;
96
+ }
97
+ export type ViewContractConfig = {
98
+ epochTimestamp?: number;
99
+ address: string;
100
+ abi: any;
101
+ arguments: Array<any>;
102
+ method: string;
103
+ rpcUrl?: string;
104
+ };
@@ -0,0 +1,8 @@
1
+ import { ethers } from 'ethers';
2
+ /**
3
+ * Iterates down from current block to find the block previous or equal to the given timestamp
4
+ * Not the most efficient for far past timestamps, a binary search could be used for better performance
5
+ * @param timestamp
6
+ * @param Idenity
7
+ */
8
+ export declare function getBlockFromTimestamp(timestamp: number, provider: ethers.providers.Provider): Promise<number>;
@@ -0,0 +1,4 @@
1
+ export declare const API_BASE_URL = "https://cvrlulno2m.execute-api.ap-southeast-1.amazonaws.com/dev/contract-view-call";
2
+ export declare const API_MAX_RETRIES = 3;
3
+ export declare const API_INITIAL_DELAY = 1000;
4
+ export declare const CENTRALIZE_CONTRACT_INTERACTION_CHAINS: string[];
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.CENTRALIZE_CONTRACT_INTERACTION_CHAINS = exports.API_INITIAL_DELAY = exports.API_MAX_RETRIES = exports.API_BASE_URL = void 0;
4
+ exports.API_BASE_URL = 'https://cvrlulno2m.execute-api.ap-southeast-1.amazonaws.com/dev/contract-view-call';
5
+ exports.API_MAX_RETRIES = 3;
6
+ exports.API_INITIAL_DELAY = 1000;
7
+ exports.CENTRALIZE_CONTRACT_INTERACTION_CHAINS = ['2222', '42161', '9001', '137', '56'];
@@ -0,0 +1,11 @@
1
+ import { AxiosRequestConfig } from 'axios';
2
+ export declare class PluginManager {
3
+ private registeredPluginConfigs;
4
+ constructor();
5
+ registerFromPublicConfig(): Promise<void>;
6
+ registerPluginConfig(name: string, domain: string, headers: object): void;
7
+ private findMatchingPluginConfigs;
8
+ private interpolateEnvVars;
9
+ private interpolateHeaders;
10
+ process(config: AxiosRequestConfig): Promise<AxiosRequestConfig>;
11
+ }
@@ -0,0 +1,16 @@
1
+ import { Candle } from '@steerprotocol/app-loader';
2
+ import { AxiosRequestConfig } from 'axios';
3
+ import { ExecutionContext, ViewContractConfig } from '../types';
4
+ import { providers } from 'ethers';
5
+ export declare const extendOHLCV: (rawData: Candle[], period: number, endTimestamp: number) => Candle[];
6
+ export declare function fetchData(request: AxiosRequestConfig, attempts: number): Promise<any>;
7
+ export declare function readSlot0Contract({ address, abi, currentExecutionContext, functionName, provider, rpc, chainId, }: {
8
+ address: string;
9
+ abi: any;
10
+ currentExecutionContext: ExecutionContext;
11
+ functionName: string;
12
+ provider: providers.Provider;
13
+ rpc: string;
14
+ chainId: number;
15
+ }): Promise<any>;
16
+ export declare function callWithRetry(config: ViewContractConfig): Promise<any>;
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.callWithRetry = exports.readSlot0Contract = exports.fetchData = exports.extendOHLCV = void 0;
16
+ const axios_1 = __importDefault(require("axios"));
17
+ const ethers_1 = require("ethers");
18
+ const consts_1 = require("./consts");
19
+ // The purpose of this function is to look at the end timestamp and extend the current candle array so that it backfills any missing candles up to the end timestamp
20
+ const extendOHLCV = (rawData, period, endTimestamp) => {
21
+ // Sort rawData by timestamp
22
+ const sortedData = rawData.sort((a, b) => a.timestamp - b.timestamp);
23
+ const lastCandle = sortedData[sortedData.length - 1];
24
+ const startTimestamp = lastCandle ? lastCandle.timestamp : endTimestamp;
25
+ // Calculate the number of periods to backfill
26
+ const periodsToBackfill = Math.floor((endTimestamp - startTimestamp) / 1000 / period);
27
+ // Backfill the candles
28
+ for (let i = 0; i < periodsToBackfill; i++) {
29
+ const candleWidth = period * (i + 1);
30
+ const newCandle = {
31
+ timestamp: startTimestamp + candleWidth,
32
+ open: lastCandle.open,
33
+ high: lastCandle.open,
34
+ low: lastCandle.open,
35
+ close: lastCandle.open,
36
+ volume: 0, // You may need to replace these with appropriate logic
37
+ };
38
+ sortedData.push(newCandle);
39
+ }
40
+ // Return the converted data
41
+ return sortedData;
42
+ };
43
+ exports.extendOHLCV = extendOHLCV;
44
+ function delay(ms) {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ return new Promise((resolve) => setTimeout(resolve, ms));
47
+ });
48
+ }
49
+ function exponentialBackoffDelay(attempts) {
50
+ const baseDelay = 1000; // 1 second
51
+ const maxDelay = 30000; // 30 seconds
52
+ const delay = Math.min(baseDelay * Math.pow(2, attempts - 1), maxDelay);
53
+ return delay;
54
+ }
55
+ function fetchData(request, attempts) {
56
+ return __awaiter(this, void 0, void 0, function* () {
57
+ log('Request payload: =============', request);
58
+ attempts = attempts + 1;
59
+ try {
60
+ const response = (yield (0, axios_1.default)(request)).data;
61
+ // this.log('API Response: =============', response);
62
+ if ('errors' in response && response['errors'].length > 0) {
63
+ if (attempts < 3) {
64
+ yield delay(exponentialBackoffDelay(attempts));
65
+ return yield fetchData(request, attempts);
66
+ }
67
+ else {
68
+ throw new Error('Maximum retry attempts reached');
69
+ }
70
+ }
71
+ return response;
72
+ }
73
+ catch (error) {
74
+ if (attempts < 3) {
75
+ yield delay(exponentialBackoffDelay(attempts));
76
+ return yield fetchData(request, attempts);
77
+ }
78
+ else {
79
+ throw error;
80
+ }
81
+ }
82
+ });
83
+ }
84
+ exports.fetchData = fetchData;
85
+ function readSlot0Contract({ address, abi, currentExecutionContext, functionName, provider, rpc, chainId, }) {
86
+ return __awaiter(this, void 0, void 0, function* () {
87
+ // Create a new contract instance
88
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
+ if (!provider)
90
+ throw new Error('Provider not initialized');
91
+ const contract = new ethers_1.Contract(address, abi, provider);
92
+ // For formatting the parameters if needed
93
+ const paramsArray = [];
94
+ // Calculate block number for determinism
95
+ // Best way to handle contextually non-null values?
96
+ // const syncedBlock = await getBlockFromTimestamp(this.executionContext!.epochTimestamp, this.providerIdentity!) //@note uncomment for deterministic blocks
97
+ // Call the desired method with the specified arguments at synced block
98
+ // , {blockTag: syncedBlock}
99
+ let result;
100
+ if (consts_1.CENTRALIZE_CONTRACT_INTERACTION_CHAINS.indexOf(chainId.toString()) === -1) {
101
+ result = yield contract[functionName](...paramsArray, {
102
+ blockTag: currentExecutionContext === null || currentExecutionContext === void 0 ? void 0 : currentExecutionContext.blockNumber,
103
+ }); //@note uncomment for deterministic blocks
104
+ }
105
+ else {
106
+ const viewContractConfig = {
107
+ epochTimestamp: currentExecutionContext.epochTimestamp,
108
+ address: address,
109
+ abi: abi,
110
+ arguments: paramsArray,
111
+ method: functionName,
112
+ rpcUrl: rpc,
113
+ };
114
+ result = yield callWithRetry(viewContractConfig);
115
+ }
116
+ // This gets stringified before calling main
117
+ return result;
118
+ });
119
+ }
120
+ exports.readSlot0Contract = readSlot0Contract;
121
+ function callWithRetry(config) {
122
+ return __awaiter(this, void 0, void 0, function* () {
123
+ let retries = 0;
124
+ let delay = consts_1.API_INITIAL_DELAY;
125
+ while (retries < consts_1.API_MAX_RETRIES) {
126
+ try {
127
+ const response = yield axios_1.default.post(consts_1.API_BASE_URL, config);
128
+ return JSON.parse(response.data); // Return the data if the call was successful
129
+ }
130
+ catch (error) {
131
+ console.error(`Attempt ${retries + 1} failed. Retrying in to fetch the contract method ${config.method} ${delay / 1000} seconds...`);
132
+ yield new Promise((resolve) => setTimeout(resolve, delay));
133
+ delay *= 2; // Double the delay for the next retry
134
+ retries++;
135
+ }
136
+ }
137
+ throw new Error(`Failed after ${consts_1.API_MAX_RETRIES} attempts. to call method ${config.method}`);
138
+ });
139
+ }
140
+ exports.callWithRetry = callWithRetry;
141
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
142
+ function log(...args) {
143
+ if (process.env.DEBUG === 'true') {
144
+ console.log(...args);
145
+ }
146
+ }