@gearbox-protocol/sdk 14.9.0 → 14.10.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/dist/cjs/{plugins/apy/apy-cache.js → common-utils/axios-cache/AxiosCache.js} +31 -20
- package/dist/cjs/common-utils/axios-cache/index.js +22 -0
- package/dist/cjs/common-utils/index.js +2 -0
- package/dist/cjs/plugins/apy/ApyPlugin.js +4 -4
- package/dist/cjs/plugins/apy/index.js +0 -2
- package/dist/cjs/plugins/remote-configs/CustomConfigSource.js +41 -0
- package/dist/cjs/plugins/remote-configs/RemoteConfigSource.js +56 -0
- package/dist/cjs/plugins/remote-configs/RemoteConfigsPlugin.js +186 -0
- package/dist/cjs/plugins/remote-configs/index.js +28 -0
- package/dist/cjs/plugins/remote-configs/package.json +1 -0
- package/dist/cjs/plugins/remote-configs/types.js +16 -0
- package/dist/esm/{plugins/apy/apy-cache.js → common-utils/axios-cache/AxiosCache.js} +27 -16
- package/dist/esm/common-utils/axios-cache/index.js +1 -0
- package/dist/esm/common-utils/index.js +1 -0
- package/dist/esm/plugins/apy/ApyPlugin.js +4 -4
- package/dist/esm/plugins/apy/index.js +0 -1
- package/dist/esm/plugins/remote-configs/CustomConfigSource.js +17 -0
- package/dist/esm/plugins/remote-configs/RemoteConfigSource.js +32 -0
- package/dist/esm/plugins/remote-configs/RemoteConfigsPlugin.js +165 -0
- package/dist/esm/plugins/remote-configs/index.js +4 -0
- package/dist/esm/plugins/remote-configs/package.json +1 -0
- package/dist/esm/plugins/remote-configs/types.js +0 -0
- package/dist/types/{plugins/apy/apy-cache.d.ts → common-utils/axios-cache/AxiosCache.d.ts} +6 -7
- package/dist/types/common-utils/axios-cache/index.d.ts +1 -0
- package/dist/types/common-utils/index.d.ts +1 -0
- package/dist/types/plugins/apy/index.d.ts +0 -1
- package/dist/types/plugins/remote-configs/CustomConfigSource.d.ts +13 -0
- package/dist/types/plugins/remote-configs/RemoteConfigSource.d.ts +31 -0
- package/dist/types/plugins/remote-configs/RemoteConfigsPlugin.d.ts +24 -0
- package/dist/types/plugins/remote-configs/index.d.ts +4 -0
- package/dist/types/plugins/remote-configs/types.d.ts +24 -0
- package/package.json +1 -1
|
@@ -26,50 +26,57 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
mod
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var
|
|
30
|
-
__export(
|
|
31
|
-
|
|
29
|
+
var AxiosCache_exports = {};
|
|
30
|
+
__export(AxiosCache_exports, {
|
|
31
|
+
AxiosCache: () => AxiosCache
|
|
32
32
|
});
|
|
33
|
-
module.exports = __toCommonJS(
|
|
33
|
+
module.exports = __toCommonJS(AxiosCache_exports);
|
|
34
34
|
var import_axios = __toESM(require("axios"));
|
|
35
|
-
class
|
|
35
|
+
class AxiosCache {
|
|
36
36
|
static #instances = /* @__PURE__ */ new Map();
|
|
37
37
|
#url;
|
|
38
38
|
#ttlMs;
|
|
39
39
|
#cache;
|
|
40
40
|
#pending;
|
|
41
41
|
#logger;
|
|
42
|
-
|
|
42
|
+
#getLogMeta;
|
|
43
|
+
constructor(url, ttlMs, logger, getLogMeta) {
|
|
43
44
|
this.#url = url;
|
|
44
45
|
this.#ttlMs = ttlMs;
|
|
45
46
|
this.#logger = logger;
|
|
47
|
+
this.#getLogMeta = getLogMeta;
|
|
46
48
|
}
|
|
47
49
|
/**
|
|
48
50
|
* Returns a shared cache instance for the given URL.
|
|
49
51
|
* The same instance is reused across all callers with identical URL.
|
|
50
52
|
*/
|
|
51
|
-
static get(url, ttlMs, logger) {
|
|
52
|
-
let instance =
|
|
53
|
+
static get(url, ttlMs, logger, getLogMeta) {
|
|
54
|
+
let instance = AxiosCache.#instances.get(url);
|
|
53
55
|
if (!instance) {
|
|
54
|
-
instance = new
|
|
55
|
-
|
|
56
|
+
instance = new AxiosCache(url, ttlMs, logger, getLogMeta);
|
|
57
|
+
AxiosCache.#instances.set(url, instance);
|
|
56
58
|
}
|
|
57
59
|
if (logger) {
|
|
58
60
|
instance.#logger = logger;
|
|
59
61
|
}
|
|
62
|
+
if (getLogMeta) {
|
|
63
|
+
instance.#getLogMeta = getLogMeta;
|
|
64
|
+
}
|
|
60
65
|
return instance;
|
|
61
66
|
}
|
|
62
67
|
/**
|
|
63
|
-
* Returns cached
|
|
68
|
+
* Returns cached data if fresh, otherwise fetches from the network.
|
|
64
69
|
* Concurrent calls are de-duplicated.
|
|
65
70
|
*/
|
|
66
71
|
async fetch() {
|
|
67
72
|
if (this.#cache && Date.now() - this.#cache.fetchedAt < this.#ttlMs) {
|
|
68
|
-
this.#logger?.debug(
|
|
73
|
+
this.#logger?.debug(
|
|
74
|
+
"axios cache: TTL still valid, returning cached data"
|
|
75
|
+
);
|
|
69
76
|
return this.#cache.data;
|
|
70
77
|
}
|
|
71
78
|
if (this.#pending) {
|
|
72
|
-
this.#logger?.debug("
|
|
79
|
+
this.#logger?.debug("axios cache: request in flight, waiting");
|
|
73
80
|
return this.#pending;
|
|
74
81
|
}
|
|
75
82
|
this.#pending = this.#doFetch();
|
|
@@ -91,30 +98,34 @@ class ApyOutputCache {
|
|
|
91
98
|
});
|
|
92
99
|
if (response.status === 304 && this.#cache) {
|
|
93
100
|
this.#cache.fetchedAt = Date.now();
|
|
94
|
-
this.#logger?.debug("
|
|
101
|
+
this.#logger?.debug("axios cache: 304 Not Modified, extended TTL");
|
|
95
102
|
return this.#cache.data;
|
|
96
103
|
}
|
|
97
|
-
const etag = response.headers
|
|
104
|
+
const etag = response.headers.etag;
|
|
98
105
|
this.#cache = {
|
|
99
106
|
data: response.data,
|
|
100
107
|
etag,
|
|
101
108
|
fetchedAt: Date.now()
|
|
102
109
|
};
|
|
110
|
+
const meta = this.#getLogMeta?.(response.data);
|
|
103
111
|
this.#logger?.debug(
|
|
104
|
-
`
|
|
112
|
+
`axios cache: fetched fresh data${meta ? ` (${meta})` : ""}`
|
|
105
113
|
);
|
|
106
114
|
return response.data;
|
|
107
115
|
} catch (e) {
|
|
108
|
-
this.#logger?.error(e, "
|
|
109
|
-
|
|
116
|
+
this.#logger?.error(e, "axios cache: fetch failed");
|
|
117
|
+
if (this.#cache) {
|
|
118
|
+
return this.#cache.data;
|
|
119
|
+
}
|
|
120
|
+
throw e;
|
|
110
121
|
}
|
|
111
122
|
}
|
|
112
123
|
/** Evicts all cached entries. Mainly useful for tests. */
|
|
113
124
|
static clearAll() {
|
|
114
|
-
|
|
125
|
+
AxiosCache.#instances.clear();
|
|
115
126
|
}
|
|
116
127
|
}
|
|
117
128
|
// Annotate the CommonJS export names for ESM import in node:
|
|
118
129
|
0 && (module.exports = {
|
|
119
|
-
|
|
130
|
+
AxiosCache
|
|
120
131
|
});
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
15
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
|
+
var axios_cache_exports = {};
|
|
17
|
+
module.exports = __toCommonJS(axios_cache_exports);
|
|
18
|
+
__reExport(axios_cache_exports, require("./AxiosCache.js"), module.exports);
|
|
19
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
20
|
+
0 && (module.exports = {
|
|
21
|
+
...require("./AxiosCache.js")
|
|
22
|
+
});
|
|
@@ -15,11 +15,13 @@ var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "defau
|
|
|
15
15
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
16
|
var common_utils_exports = {};
|
|
17
17
|
module.exports = __toCommonJS(common_utils_exports);
|
|
18
|
+
__reExport(common_utils_exports, require("./axios-cache/index.js"), module.exports);
|
|
18
19
|
__reExport(common_utils_exports, require("./charts/index.js"), module.exports);
|
|
19
20
|
__reExport(common_utils_exports, require("./static/index.js"), module.exports);
|
|
20
21
|
__reExport(common_utils_exports, require("./utils/index.js"), module.exports);
|
|
21
22
|
// Annotate the CommonJS export names for ESM import in node:
|
|
22
23
|
0 && (module.exports = {
|
|
24
|
+
...require("./axios-cache/index.js"),
|
|
23
25
|
...require("./charts/index.js"),
|
|
24
26
|
...require("./static/index.js"),
|
|
25
27
|
...require("./utils/index.js")
|
|
@@ -22,12 +22,12 @@ __export(ApyPlugin_exports, {
|
|
|
22
22
|
});
|
|
23
23
|
module.exports = __toCommonJS(ApyPlugin_exports);
|
|
24
24
|
var import_marketCompressor = require("../../abi/compressors/marketCompressor.js");
|
|
25
|
+
var import_axios_cache = require("../../common-utils/axios-cache/index.js");
|
|
25
26
|
var import_strategies = require("../../common-utils/utils/strategies/index.js");
|
|
26
27
|
var import_extra_apy = require("../../rewards/rewards/extra-apy.js");
|
|
27
28
|
var import_sdk = require("../../sdk/index.js");
|
|
28
29
|
var import_formatter = require("../../sdk/utils/formatter.js");
|
|
29
30
|
var import_hex = require("../../sdk/utils/hex.js");
|
|
30
|
-
var import_apy_cache = require("./apy-cache.js");
|
|
31
31
|
var import_apy_parser = require("./apy-parser.js");
|
|
32
32
|
var import_constants = require("./constants.js");
|
|
33
33
|
var import_pool_apy_utils = require("./pool-apy-utils.js");
|
|
@@ -277,13 +277,13 @@ class ApyPlugin extends import_sdk.BasePlugin {
|
|
|
277
277
|
// ---------------------------------------------------------------------------
|
|
278
278
|
async #fetchApy() {
|
|
279
279
|
try {
|
|
280
|
-
const cache =
|
|
280
|
+
const cache = import_axios_cache.AxiosCache.get(
|
|
281
281
|
this.#apyUrl,
|
|
282
282
|
this.#cacheTtlMs,
|
|
283
|
-
this.#logger
|
|
283
|
+
this.#logger,
|
|
284
|
+
(data) => `timestamp: ${data.timestamp}`
|
|
284
285
|
);
|
|
285
286
|
const output = await cache.fetch();
|
|
286
|
-
if (!output) return void 0;
|
|
287
287
|
const chainData = output.chains[this.sdk.chainId];
|
|
288
288
|
if (!chainData) {
|
|
289
289
|
this.#logger?.debug(
|
|
@@ -16,7 +16,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
16
16
|
var apy_exports = {};
|
|
17
17
|
module.exports = __toCommonJS(apy_exports);
|
|
18
18
|
__reExport(apy_exports, require("./ApyPlugin.js"), module.exports);
|
|
19
|
-
__reExport(apy_exports, require("./apy-cache.js"), module.exports);
|
|
20
19
|
__reExport(apy_exports, require("./apy-parser.js"), module.exports);
|
|
21
20
|
__reExport(apy_exports, require("./constants.js"), module.exports);
|
|
22
21
|
__reExport(apy_exports, require("./pool-apy-types.js"), module.exports);
|
|
@@ -25,7 +24,6 @@ __reExport(apy_exports, require("./types.js"), module.exports);
|
|
|
25
24
|
// Annotate the CommonJS export names for ESM import in node:
|
|
26
25
|
0 && (module.exports = {
|
|
27
26
|
...require("./ApyPlugin.js"),
|
|
28
|
-
...require("./apy-cache.js"),
|
|
29
27
|
...require("./apy-parser.js"),
|
|
30
28
|
...require("./constants.js"),
|
|
31
29
|
...require("./pool-apy-types.js"),
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var CustomConfigSource_exports = {};
|
|
20
|
+
__export(CustomConfigSource_exports, {
|
|
21
|
+
CustomConfigSource: () => CustomConfigSource
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(CustomConfigSource_exports);
|
|
24
|
+
class CustomConfigSource {
|
|
25
|
+
#getPools;
|
|
26
|
+
#getStrategies;
|
|
27
|
+
constructor(options) {
|
|
28
|
+
this.#getPools = options.getPools;
|
|
29
|
+
this.#getStrategies = options.getStrategies;
|
|
30
|
+
}
|
|
31
|
+
async getPools() {
|
|
32
|
+
return this.#getPools();
|
|
33
|
+
}
|
|
34
|
+
async getStrategies() {
|
|
35
|
+
return this.#getStrategies();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
39
|
+
0 && (module.exports = {
|
|
40
|
+
CustomConfigSource
|
|
41
|
+
});
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var RemoteConfigSource_exports = {};
|
|
20
|
+
__export(RemoteConfigSource_exports, {
|
|
21
|
+
RemoteConfigSource: () => RemoteConfigSource
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(RemoteConfigSource_exports);
|
|
24
|
+
var import_axios_cache = require("../../common-utils/axios-cache/index.js");
|
|
25
|
+
const DEFAULT_POOLS_URL = "https://static.gearbox.finance/client-v3/configs/pools/pools.json";
|
|
26
|
+
const DEFAULT_STRATEGIES_URL = "https://static.gearbox.finance/client-v3/configs/strategies/strategies.json";
|
|
27
|
+
const DEFAULT_CACHE_TTL_MS = 30 * 60 * 1e3;
|
|
28
|
+
class RemoteConfigSource {
|
|
29
|
+
#poolsCache;
|
|
30
|
+
#strategiesCache;
|
|
31
|
+
constructor(options) {
|
|
32
|
+
const poolsUrl = options?.poolsUrl ?? DEFAULT_POOLS_URL;
|
|
33
|
+
const strategiesUrl = options?.strategiesUrl ?? DEFAULT_STRATEGIES_URL;
|
|
34
|
+
const ttlMs = options?.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
35
|
+
this.#poolsCache = import_axios_cache.AxiosCache.get(
|
|
36
|
+
poolsUrl,
|
|
37
|
+
ttlMs,
|
|
38
|
+
options?.logger
|
|
39
|
+
);
|
|
40
|
+
this.#strategiesCache = import_axios_cache.AxiosCache.get(
|
|
41
|
+
strategiesUrl,
|
|
42
|
+
ttlMs,
|
|
43
|
+
options?.logger
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
async getPools() {
|
|
47
|
+
return this.#poolsCache.fetch();
|
|
48
|
+
}
|
|
49
|
+
async getStrategies() {
|
|
50
|
+
return this.#strategiesCache.fetch();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
54
|
+
0 && (module.exports = {
|
|
55
|
+
RemoteConfigSource
|
|
56
|
+
});
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var RemoteConfigsPlugin_exports = {};
|
|
20
|
+
__export(RemoteConfigsPlugin_exports, {
|
|
21
|
+
RemoteConfigsPlugin: () => RemoteConfigsPlugin
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(RemoteConfigsPlugin_exports);
|
|
24
|
+
var import_viem = require("viem");
|
|
25
|
+
var import_sdk = require("../../sdk/index.js");
|
|
26
|
+
var import_RemoteConfigSource = require("./RemoteConfigSource.js");
|
|
27
|
+
class RemoteConfigsPlugin extends import_sdk.BasePlugin {
|
|
28
|
+
#sources;
|
|
29
|
+
#pools;
|
|
30
|
+
#strategies;
|
|
31
|
+
constructor(loadOnAttach = false, options) {
|
|
32
|
+
super(loadOnAttach);
|
|
33
|
+
this.#sources = options?.sources ?? [new import_RemoteConfigSource.RemoteConfigSource()];
|
|
34
|
+
}
|
|
35
|
+
get loaded() {
|
|
36
|
+
return !!this.#pools && !!this.#strategies;
|
|
37
|
+
}
|
|
38
|
+
async load(force) {
|
|
39
|
+
if (!force && this.loaded) {
|
|
40
|
+
return this.state;
|
|
41
|
+
}
|
|
42
|
+
const [pools, strategies] = await Promise.all([
|
|
43
|
+
this.#loadPools(),
|
|
44
|
+
this.#loadStrategies()
|
|
45
|
+
]);
|
|
46
|
+
this.#pools = pools;
|
|
47
|
+
this.#strategies = strategies;
|
|
48
|
+
return this.state;
|
|
49
|
+
}
|
|
50
|
+
async syncState() {
|
|
51
|
+
await this.load(false);
|
|
52
|
+
}
|
|
53
|
+
get state() {
|
|
54
|
+
return {
|
|
55
|
+
pools: this.pools,
|
|
56
|
+
strategies: this.strategies
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
hydrate(state) {
|
|
60
|
+
this.#pools = state.pools;
|
|
61
|
+
this.#strategies = state.strategies;
|
|
62
|
+
}
|
|
63
|
+
stateHuman(_) {
|
|
64
|
+
return this.state;
|
|
65
|
+
}
|
|
66
|
+
// ---------------------------------------------------------------------------
|
|
67
|
+
// Accessors
|
|
68
|
+
// ---------------------------------------------------------------------------
|
|
69
|
+
/**
|
|
70
|
+
* Pool configs for the current SDK network.
|
|
71
|
+
* @throws if plugin is not loaded
|
|
72
|
+
*/
|
|
73
|
+
get pools() {
|
|
74
|
+
if (!this.#pools) {
|
|
75
|
+
throw new Error("remote-configs plugin not loaded");
|
|
76
|
+
}
|
|
77
|
+
return this.#pools;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Strategy configs for the current SDK network.
|
|
81
|
+
* @throws if plugin is not loaded
|
|
82
|
+
*/
|
|
83
|
+
get strategies() {
|
|
84
|
+
if (!this.#strategies) {
|
|
85
|
+
throw new Error("remote-configs plugin not loaded");
|
|
86
|
+
}
|
|
87
|
+
return this.#strategies;
|
|
88
|
+
}
|
|
89
|
+
// ---------------------------------------------------------------------------
|
|
90
|
+
// Internal
|
|
91
|
+
// ---------------------------------------------------------------------------
|
|
92
|
+
async #loadPools() {
|
|
93
|
+
for (const source of this.#sources) {
|
|
94
|
+
try {
|
|
95
|
+
const data = await source.getPools();
|
|
96
|
+
const mapped = this.#mapPoolPayload(
|
|
97
|
+
data.filter(
|
|
98
|
+
(p) => p.chainId === this.sdk.chainId && p.network.toLowerCase() === this.sdk.networkType.toLowerCase()
|
|
99
|
+
)
|
|
100
|
+
);
|
|
101
|
+
return mapped;
|
|
102
|
+
} catch (e) {
|
|
103
|
+
this.logger?.warn(e, `${source.constructor.name} failed to load pools`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
throw new Error("all config sources failed to load pools");
|
|
107
|
+
}
|
|
108
|
+
async #loadStrategies() {
|
|
109
|
+
for (const source of this.#sources) {
|
|
110
|
+
try {
|
|
111
|
+
const data = await source.getStrategies();
|
|
112
|
+
const mapped = this.#mapStrategyPayload(
|
|
113
|
+
data.filter(
|
|
114
|
+
(s) => s.chainId === this.sdk.chainId && s.network.toLowerCase() === this.sdk.networkType.toLowerCase()
|
|
115
|
+
)
|
|
116
|
+
);
|
|
117
|
+
return mapped;
|
|
118
|
+
} catch (e) {
|
|
119
|
+
this.logger?.warn(
|
|
120
|
+
e,
|
|
121
|
+
`${source.constructor.name} failed to load strategies`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
throw new Error("all config sources failed to load strategies");
|
|
126
|
+
}
|
|
127
|
+
#mapPoolPayload(payload) {
|
|
128
|
+
return payload.reduce((acc, p) => {
|
|
129
|
+
const addressLc = p.address.toLowerCase();
|
|
130
|
+
if ((0, import_viem.isAddress)(addressLc)) {
|
|
131
|
+
acc.push({
|
|
132
|
+
...p,
|
|
133
|
+
address: addressLc
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
return acc;
|
|
137
|
+
}, []);
|
|
138
|
+
}
|
|
139
|
+
#mapStrategyPayload(payload) {
|
|
140
|
+
return payload.reduce((acc, p) => {
|
|
141
|
+
const tokenOutAddressLc = p.tokenOutAddress.toLowerCase();
|
|
142
|
+
const creditManagers = p.creditManagers.filter((cm) => (0, import_viem.isAddress)(cm)).map((cm) => cm.toLowerCase());
|
|
143
|
+
const zeroSlippage = p.zeroSlippage ? import_sdk.TypedObjectUtils.entries(p.zeroSlippage).reduce((zsAcc, [address, value]) => {
|
|
144
|
+
const addressLc = address.toLowerCase();
|
|
145
|
+
if ((0, import_viem.isAddress)(addressLc)) zsAcc[addressLc] = value;
|
|
146
|
+
return zsAcc;
|
|
147
|
+
}, {}) : void 0;
|
|
148
|
+
const additionalRewardQuotas = p.additionalRewardQuotas ? import_sdk.TypedObjectUtils.entries(p.additionalRewardQuotas).reduce((rqAcc, [address, value]) => {
|
|
149
|
+
const addressLc = address.toLowerCase();
|
|
150
|
+
if ((0, import_viem.isAddress)(addressLc)) {
|
|
151
|
+
const rewards = value?.filter((r) => (0, import_viem.isAddress)(r)).map((r) => r.toLowerCase());
|
|
152
|
+
rqAcc[addressLc] = rewards;
|
|
153
|
+
}
|
|
154
|
+
return rqAcc;
|
|
155
|
+
}, {}) : void 0;
|
|
156
|
+
const additionalCollaterals = p.additionalCollaterals?.reduce((colAcc, cfg) => {
|
|
157
|
+
const token = typeof cfg === "string" ? cfg : cfg.token;
|
|
158
|
+
const tokenLc = token.toLowerCase();
|
|
159
|
+
const valid = (0, import_viem.isAddress)(tokenLc);
|
|
160
|
+
if (valid && !colAcc[tokenLc]) colAcc[tokenLc] = [];
|
|
161
|
+
const nextCfg = typeof cfg === "string" ? tokenLc : {
|
|
162
|
+
token: tokenLc,
|
|
163
|
+
cm: cfg.cm.toLowerCase()
|
|
164
|
+
};
|
|
165
|
+
if (valid) colAcc[tokenLc].push(nextCfg);
|
|
166
|
+
return colAcc;
|
|
167
|
+
}, {});
|
|
168
|
+
if ((0, import_viem.isAddress)(tokenOutAddressLc)) {
|
|
169
|
+
const { additionalCollaterals: _, ...rest } = p;
|
|
170
|
+
acc.push({
|
|
171
|
+
...rest,
|
|
172
|
+
tokenOutAddress: tokenOutAddressLc,
|
|
173
|
+
creditManagers,
|
|
174
|
+
...zeroSlippage ? { zeroSlippage } : {},
|
|
175
|
+
...additionalRewardQuotas ? { additionalRewardQuotas } : {},
|
|
176
|
+
...additionalCollaterals ? { additionalCollaterals } : {}
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
return acc;
|
|
180
|
+
}, []);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
184
|
+
0 && (module.exports = {
|
|
185
|
+
RemoteConfigsPlugin
|
|
186
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __reExport = (target, mod, secondTarget) => (__copyProps(target, mod, "default"), secondTarget && __copyProps(secondTarget, mod, "default"));
|
|
15
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
16
|
+
var remote_configs_exports = {};
|
|
17
|
+
module.exports = __toCommonJS(remote_configs_exports);
|
|
18
|
+
__reExport(remote_configs_exports, require("./CustomConfigSource.js"), module.exports);
|
|
19
|
+
__reExport(remote_configs_exports, require("./RemoteConfigSource.js"), module.exports);
|
|
20
|
+
__reExport(remote_configs_exports, require("./RemoteConfigsPlugin.js"), module.exports);
|
|
21
|
+
__reExport(remote_configs_exports, require("./types.js"), module.exports);
|
|
22
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
23
|
+
0 && (module.exports = {
|
|
24
|
+
...require("./CustomConfigSource.js"),
|
|
25
|
+
...require("./RemoteConfigSource.js"),
|
|
26
|
+
...require("./RemoteConfigsPlugin.js"),
|
|
27
|
+
...require("./types.js")
|
|
28
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "commonjs"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __copyProps = (to, from, except, desc) => {
|
|
7
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
8
|
+
for (let key of __getOwnPropNames(from))
|
|
9
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
10
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
11
|
+
}
|
|
12
|
+
return to;
|
|
13
|
+
};
|
|
14
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
15
|
+
var types_exports = {};
|
|
16
|
+
module.exports = __toCommonJS(types_exports);
|
|
@@ -1,42 +1,49 @@
|
|
|
1
1
|
import axios from "axios";
|
|
2
|
-
class
|
|
2
|
+
class AxiosCache {
|
|
3
3
|
static #instances = /* @__PURE__ */ new Map();
|
|
4
4
|
#url;
|
|
5
5
|
#ttlMs;
|
|
6
6
|
#cache;
|
|
7
7
|
#pending;
|
|
8
8
|
#logger;
|
|
9
|
-
|
|
9
|
+
#getLogMeta;
|
|
10
|
+
constructor(url, ttlMs, logger, getLogMeta) {
|
|
10
11
|
this.#url = url;
|
|
11
12
|
this.#ttlMs = ttlMs;
|
|
12
13
|
this.#logger = logger;
|
|
14
|
+
this.#getLogMeta = getLogMeta;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Returns a shared cache instance for the given URL.
|
|
16
18
|
* The same instance is reused across all callers with identical URL.
|
|
17
19
|
*/
|
|
18
|
-
static get(url, ttlMs, logger) {
|
|
19
|
-
let instance =
|
|
20
|
+
static get(url, ttlMs, logger, getLogMeta) {
|
|
21
|
+
let instance = AxiosCache.#instances.get(url);
|
|
20
22
|
if (!instance) {
|
|
21
|
-
instance = new
|
|
22
|
-
|
|
23
|
+
instance = new AxiosCache(url, ttlMs, logger, getLogMeta);
|
|
24
|
+
AxiosCache.#instances.set(url, instance);
|
|
23
25
|
}
|
|
24
26
|
if (logger) {
|
|
25
27
|
instance.#logger = logger;
|
|
26
28
|
}
|
|
29
|
+
if (getLogMeta) {
|
|
30
|
+
instance.#getLogMeta = getLogMeta;
|
|
31
|
+
}
|
|
27
32
|
return instance;
|
|
28
33
|
}
|
|
29
34
|
/**
|
|
30
|
-
* Returns cached
|
|
35
|
+
* Returns cached data if fresh, otherwise fetches from the network.
|
|
31
36
|
* Concurrent calls are de-duplicated.
|
|
32
37
|
*/
|
|
33
38
|
async fetch() {
|
|
34
39
|
if (this.#cache && Date.now() - this.#cache.fetchedAt < this.#ttlMs) {
|
|
35
|
-
this.#logger?.debug(
|
|
40
|
+
this.#logger?.debug(
|
|
41
|
+
"axios cache: TTL still valid, returning cached data"
|
|
42
|
+
);
|
|
36
43
|
return this.#cache.data;
|
|
37
44
|
}
|
|
38
45
|
if (this.#pending) {
|
|
39
|
-
this.#logger?.debug("
|
|
46
|
+
this.#logger?.debug("axios cache: request in flight, waiting");
|
|
40
47
|
return this.#pending;
|
|
41
48
|
}
|
|
42
49
|
this.#pending = this.#doFetch();
|
|
@@ -58,29 +65,33 @@ class ApyOutputCache {
|
|
|
58
65
|
});
|
|
59
66
|
if (response.status === 304 && this.#cache) {
|
|
60
67
|
this.#cache.fetchedAt = Date.now();
|
|
61
|
-
this.#logger?.debug("
|
|
68
|
+
this.#logger?.debug("axios cache: 304 Not Modified, extended TTL");
|
|
62
69
|
return this.#cache.data;
|
|
63
70
|
}
|
|
64
|
-
const etag = response.headers
|
|
71
|
+
const etag = response.headers.etag;
|
|
65
72
|
this.#cache = {
|
|
66
73
|
data: response.data,
|
|
67
74
|
etag,
|
|
68
75
|
fetchedAt: Date.now()
|
|
69
76
|
};
|
|
77
|
+
const meta = this.#getLogMeta?.(response.data);
|
|
70
78
|
this.#logger?.debug(
|
|
71
|
-
`
|
|
79
|
+
`axios cache: fetched fresh data${meta ? ` (${meta})` : ""}`
|
|
72
80
|
);
|
|
73
81
|
return response.data;
|
|
74
82
|
} catch (e) {
|
|
75
|
-
this.#logger?.error(e, "
|
|
76
|
-
|
|
83
|
+
this.#logger?.error(e, "axios cache: fetch failed");
|
|
84
|
+
if (this.#cache) {
|
|
85
|
+
return this.#cache.data;
|
|
86
|
+
}
|
|
87
|
+
throw e;
|
|
77
88
|
}
|
|
78
89
|
}
|
|
79
90
|
/** Evicts all cached entries. Mainly useful for tests. */
|
|
80
91
|
static clearAll() {
|
|
81
|
-
|
|
92
|
+
AxiosCache.#instances.clear();
|
|
82
93
|
}
|
|
83
94
|
}
|
|
84
95
|
export {
|
|
85
|
-
|
|
96
|
+
AxiosCache
|
|
86
97
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./AxiosCache.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { marketCompressorAbi } from "../../abi/compressors/marketCompressor.js";
|
|
2
|
+
import { AxiosCache } from "../../common-utils/axios-cache/index.js";
|
|
2
3
|
import {
|
|
3
4
|
getAvailableAndDisabledStrategies,
|
|
4
5
|
getReleasedStrategiesListCore,
|
|
@@ -16,7 +17,6 @@ import {
|
|
|
16
17
|
} from "../../sdk/index.js";
|
|
17
18
|
import { rayToNumber } from "../../sdk/utils/formatter.js";
|
|
18
19
|
import { hexEq } from "../../sdk/utils/hex.js";
|
|
19
|
-
import { ApyOutputCache } from "./apy-cache.js";
|
|
20
20
|
import { parseGearStats, parseNetworkApy } from "./apy-parser.js";
|
|
21
21
|
import { APY_STATE_CACHE_URL, DEFAULT_APY_INTERVAL_MS } from "./constants.js";
|
|
22
22
|
import {
|
|
@@ -272,13 +272,13 @@ class ApyPlugin extends BasePlugin {
|
|
|
272
272
|
// ---------------------------------------------------------------------------
|
|
273
273
|
async #fetchApy() {
|
|
274
274
|
try {
|
|
275
|
-
const cache =
|
|
275
|
+
const cache = AxiosCache.get(
|
|
276
276
|
this.#apyUrl,
|
|
277
277
|
this.#cacheTtlMs,
|
|
278
|
-
this.#logger
|
|
278
|
+
this.#logger,
|
|
279
|
+
(data) => `timestamp: ${data.timestamp}`
|
|
279
280
|
);
|
|
280
281
|
const output = await cache.fetch();
|
|
281
|
-
if (!output) return void 0;
|
|
282
282
|
const chainData = output.chains[this.sdk.chainId];
|
|
283
283
|
if (!chainData) {
|
|
284
284
|
this.#logger?.debug(
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
class CustomConfigSource {
|
|
2
|
+
#getPools;
|
|
3
|
+
#getStrategies;
|
|
4
|
+
constructor(options) {
|
|
5
|
+
this.#getPools = options.getPools;
|
|
6
|
+
this.#getStrategies = options.getStrategies;
|
|
7
|
+
}
|
|
8
|
+
async getPools() {
|
|
9
|
+
return this.#getPools();
|
|
10
|
+
}
|
|
11
|
+
async getStrategies() {
|
|
12
|
+
return this.#getStrategies();
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
export {
|
|
16
|
+
CustomConfigSource
|
|
17
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { AxiosCache } from "../../common-utils/axios-cache/index.js";
|
|
2
|
+
const DEFAULT_POOLS_URL = "https://static.gearbox.finance/client-v3/configs/pools/pools.json";
|
|
3
|
+
const DEFAULT_STRATEGIES_URL = "https://static.gearbox.finance/client-v3/configs/strategies/strategies.json";
|
|
4
|
+
const DEFAULT_CACHE_TTL_MS = 30 * 60 * 1e3;
|
|
5
|
+
class RemoteConfigSource {
|
|
6
|
+
#poolsCache;
|
|
7
|
+
#strategiesCache;
|
|
8
|
+
constructor(options) {
|
|
9
|
+
const poolsUrl = options?.poolsUrl ?? DEFAULT_POOLS_URL;
|
|
10
|
+
const strategiesUrl = options?.strategiesUrl ?? DEFAULT_STRATEGIES_URL;
|
|
11
|
+
const ttlMs = options?.cacheTtlMs ?? DEFAULT_CACHE_TTL_MS;
|
|
12
|
+
this.#poolsCache = AxiosCache.get(
|
|
13
|
+
poolsUrl,
|
|
14
|
+
ttlMs,
|
|
15
|
+
options?.logger
|
|
16
|
+
);
|
|
17
|
+
this.#strategiesCache = AxiosCache.get(
|
|
18
|
+
strategiesUrl,
|
|
19
|
+
ttlMs,
|
|
20
|
+
options?.logger
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
async getPools() {
|
|
24
|
+
return this.#poolsCache.fetch();
|
|
25
|
+
}
|
|
26
|
+
async getStrategies() {
|
|
27
|
+
return this.#strategiesCache.fetch();
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
RemoteConfigSource
|
|
32
|
+
};
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { isAddress } from "viem";
|
|
2
|
+
import {
|
|
3
|
+
BasePlugin,
|
|
4
|
+
TypedObjectUtils
|
|
5
|
+
} from "../../sdk/index.js";
|
|
6
|
+
import { RemoteConfigSource } from "./RemoteConfigSource.js";
|
|
7
|
+
class RemoteConfigsPlugin extends BasePlugin {
|
|
8
|
+
#sources;
|
|
9
|
+
#pools;
|
|
10
|
+
#strategies;
|
|
11
|
+
constructor(loadOnAttach = false, options) {
|
|
12
|
+
super(loadOnAttach);
|
|
13
|
+
this.#sources = options?.sources ?? [new RemoteConfigSource()];
|
|
14
|
+
}
|
|
15
|
+
get loaded() {
|
|
16
|
+
return !!this.#pools && !!this.#strategies;
|
|
17
|
+
}
|
|
18
|
+
async load(force) {
|
|
19
|
+
if (!force && this.loaded) {
|
|
20
|
+
return this.state;
|
|
21
|
+
}
|
|
22
|
+
const [pools, strategies] = await Promise.all([
|
|
23
|
+
this.#loadPools(),
|
|
24
|
+
this.#loadStrategies()
|
|
25
|
+
]);
|
|
26
|
+
this.#pools = pools;
|
|
27
|
+
this.#strategies = strategies;
|
|
28
|
+
return this.state;
|
|
29
|
+
}
|
|
30
|
+
async syncState() {
|
|
31
|
+
await this.load(false);
|
|
32
|
+
}
|
|
33
|
+
get state() {
|
|
34
|
+
return {
|
|
35
|
+
pools: this.pools,
|
|
36
|
+
strategies: this.strategies
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
hydrate(state) {
|
|
40
|
+
this.#pools = state.pools;
|
|
41
|
+
this.#strategies = state.strategies;
|
|
42
|
+
}
|
|
43
|
+
stateHuman(_) {
|
|
44
|
+
return this.state;
|
|
45
|
+
}
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Accessors
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
/**
|
|
50
|
+
* Pool configs for the current SDK network.
|
|
51
|
+
* @throws if plugin is not loaded
|
|
52
|
+
*/
|
|
53
|
+
get pools() {
|
|
54
|
+
if (!this.#pools) {
|
|
55
|
+
throw new Error("remote-configs plugin not loaded");
|
|
56
|
+
}
|
|
57
|
+
return this.#pools;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Strategy configs for the current SDK network.
|
|
61
|
+
* @throws if plugin is not loaded
|
|
62
|
+
*/
|
|
63
|
+
get strategies() {
|
|
64
|
+
if (!this.#strategies) {
|
|
65
|
+
throw new Error("remote-configs plugin not loaded");
|
|
66
|
+
}
|
|
67
|
+
return this.#strategies;
|
|
68
|
+
}
|
|
69
|
+
// ---------------------------------------------------------------------------
|
|
70
|
+
// Internal
|
|
71
|
+
// ---------------------------------------------------------------------------
|
|
72
|
+
async #loadPools() {
|
|
73
|
+
for (const source of this.#sources) {
|
|
74
|
+
try {
|
|
75
|
+
const data = await source.getPools();
|
|
76
|
+
const mapped = this.#mapPoolPayload(
|
|
77
|
+
data.filter(
|
|
78
|
+
(p) => p.chainId === this.sdk.chainId && p.network.toLowerCase() === this.sdk.networkType.toLowerCase()
|
|
79
|
+
)
|
|
80
|
+
);
|
|
81
|
+
return mapped;
|
|
82
|
+
} catch (e) {
|
|
83
|
+
this.logger?.warn(e, `${source.constructor.name} failed to load pools`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
throw new Error("all config sources failed to load pools");
|
|
87
|
+
}
|
|
88
|
+
async #loadStrategies() {
|
|
89
|
+
for (const source of this.#sources) {
|
|
90
|
+
try {
|
|
91
|
+
const data = await source.getStrategies();
|
|
92
|
+
const mapped = this.#mapStrategyPayload(
|
|
93
|
+
data.filter(
|
|
94
|
+
(s) => s.chainId === this.sdk.chainId && s.network.toLowerCase() === this.sdk.networkType.toLowerCase()
|
|
95
|
+
)
|
|
96
|
+
);
|
|
97
|
+
return mapped;
|
|
98
|
+
} catch (e) {
|
|
99
|
+
this.logger?.warn(
|
|
100
|
+
e,
|
|
101
|
+
`${source.constructor.name} failed to load strategies`
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
throw new Error("all config sources failed to load strategies");
|
|
106
|
+
}
|
|
107
|
+
#mapPoolPayload(payload) {
|
|
108
|
+
return payload.reduce((acc, p) => {
|
|
109
|
+
const addressLc = p.address.toLowerCase();
|
|
110
|
+
if (isAddress(addressLc)) {
|
|
111
|
+
acc.push({
|
|
112
|
+
...p,
|
|
113
|
+
address: addressLc
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
return acc;
|
|
117
|
+
}, []);
|
|
118
|
+
}
|
|
119
|
+
#mapStrategyPayload(payload) {
|
|
120
|
+
return payload.reduce((acc, p) => {
|
|
121
|
+
const tokenOutAddressLc = p.tokenOutAddress.toLowerCase();
|
|
122
|
+
const creditManagers = p.creditManagers.filter((cm) => isAddress(cm)).map((cm) => cm.toLowerCase());
|
|
123
|
+
const zeroSlippage = p.zeroSlippage ? TypedObjectUtils.entries(p.zeroSlippage).reduce((zsAcc, [address, value]) => {
|
|
124
|
+
const addressLc = address.toLowerCase();
|
|
125
|
+
if (isAddress(addressLc)) zsAcc[addressLc] = value;
|
|
126
|
+
return zsAcc;
|
|
127
|
+
}, {}) : void 0;
|
|
128
|
+
const additionalRewardQuotas = p.additionalRewardQuotas ? TypedObjectUtils.entries(p.additionalRewardQuotas).reduce((rqAcc, [address, value]) => {
|
|
129
|
+
const addressLc = address.toLowerCase();
|
|
130
|
+
if (isAddress(addressLc)) {
|
|
131
|
+
const rewards = value?.filter((r) => isAddress(r)).map((r) => r.toLowerCase());
|
|
132
|
+
rqAcc[addressLc] = rewards;
|
|
133
|
+
}
|
|
134
|
+
return rqAcc;
|
|
135
|
+
}, {}) : void 0;
|
|
136
|
+
const additionalCollaterals = p.additionalCollaterals?.reduce((colAcc, cfg) => {
|
|
137
|
+
const token = typeof cfg === "string" ? cfg : cfg.token;
|
|
138
|
+
const tokenLc = token.toLowerCase();
|
|
139
|
+
const valid = isAddress(tokenLc);
|
|
140
|
+
if (valid && !colAcc[tokenLc]) colAcc[tokenLc] = [];
|
|
141
|
+
const nextCfg = typeof cfg === "string" ? tokenLc : {
|
|
142
|
+
token: tokenLc,
|
|
143
|
+
cm: cfg.cm.toLowerCase()
|
|
144
|
+
};
|
|
145
|
+
if (valid) colAcc[tokenLc].push(nextCfg);
|
|
146
|
+
return colAcc;
|
|
147
|
+
}, {});
|
|
148
|
+
if (isAddress(tokenOutAddressLc)) {
|
|
149
|
+
const { additionalCollaterals: _, ...rest } = p;
|
|
150
|
+
acc.push({
|
|
151
|
+
...rest,
|
|
152
|
+
tokenOutAddress: tokenOutAddressLc,
|
|
153
|
+
creditManagers,
|
|
154
|
+
...zeroSlippage ? { zeroSlippage } : {},
|
|
155
|
+
...additionalRewardQuotas ? { additionalRewardQuotas } : {},
|
|
156
|
+
...additionalCollaterals ? { additionalCollaterals } : {}
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
return acc;
|
|
160
|
+
}, []);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
export {
|
|
164
|
+
RemoteConfigsPlugin
|
|
165
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type": "module","sideEffects":false}
|
|
File without changes
|
|
@@ -1,28 +1,27 @@
|
|
|
1
|
-
import type { Output } from "../../rewards/apy/index.js";
|
|
2
1
|
import type { ILogger } from "../../sdk/index.js";
|
|
3
2
|
/**
|
|
4
|
-
* Process-wide cache for
|
|
3
|
+
* Process-wide cache for axios JSON responses.
|
|
5
4
|
*
|
|
6
|
-
* Multiple
|
|
5
|
+
* Multiple plugin instances (one per SDK / network) share the same
|
|
7
6
|
* cached HTTP response so that only **one** request is made per TTL window
|
|
8
7
|
* regardless of how many SDK instances exist.
|
|
9
8
|
*
|
|
10
9
|
* Concurrent callers that arrive while a fetch is already in flight
|
|
11
10
|
* are de-duplicated — they all await the same promise.
|
|
12
11
|
*/
|
|
13
|
-
export declare class
|
|
12
|
+
export declare class AxiosCache<T> {
|
|
14
13
|
#private;
|
|
15
14
|
private constructor();
|
|
16
15
|
/**
|
|
17
16
|
* Returns a shared cache instance for the given URL.
|
|
18
17
|
* The same instance is reused across all callers with identical URL.
|
|
19
18
|
*/
|
|
20
|
-
static get(url: string, ttlMs: number, logger?: ILogger):
|
|
19
|
+
static get<T>(url: string, ttlMs: number, logger?: ILogger, getLogMeta?: (data: T) => string): AxiosCache<T>;
|
|
21
20
|
/**
|
|
22
|
-
* Returns cached
|
|
21
|
+
* Returns cached data if fresh, otherwise fetches from the network.
|
|
23
22
|
* Concurrent calls are de-duplicated.
|
|
24
23
|
*/
|
|
25
|
-
fetch(): Promise<
|
|
24
|
+
fetch(): Promise<T>;
|
|
26
25
|
/** Evicts all cached entries. Mainly useful for tests. */
|
|
27
26
|
static clearAll(): void;
|
|
28
27
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./AxiosCache.js";
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PoolConfigPayload } from "../../common-utils/static/pool-config.js";
|
|
2
|
+
import type { StrategyConfigPayload } from "../../common-utils/static/strategy.js";
|
|
3
|
+
import type { ConfigSource } from "./types.js";
|
|
4
|
+
export interface CustomConfigSourceOptions {
|
|
5
|
+
getPools: () => Promise<PoolConfigPayload[]>;
|
|
6
|
+
getStrategies: () => Promise<StrategyConfigPayload[]>;
|
|
7
|
+
}
|
|
8
|
+
export declare class CustomConfigSource implements ConfigSource {
|
|
9
|
+
#private;
|
|
10
|
+
constructor(options: CustomConfigSourceOptions);
|
|
11
|
+
getPools(): Promise<PoolConfigPayload[]>;
|
|
12
|
+
getStrategies(): Promise<StrategyConfigPayload[]>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { PoolConfigPayload } from "../../common-utils/static/pool-config.js";
|
|
2
|
+
import type { StrategyConfigPayload } from "../../common-utils/static/strategy.js";
|
|
3
|
+
import type { ILogger } from "../../sdk/index.js";
|
|
4
|
+
import type { ConfigSource } from "./types.js";
|
|
5
|
+
export interface RemoteConfigSourceOptions {
|
|
6
|
+
/**
|
|
7
|
+
* URL for pools config JSON.
|
|
8
|
+
* @default "https://static.gearbox.finance/client-v3/configs/pools/pools.json"
|
|
9
|
+
*/
|
|
10
|
+
poolsUrl?: string;
|
|
11
|
+
/**
|
|
12
|
+
* URL for strategies config JSON.
|
|
13
|
+
* @default "https://static.gearbox.finance/client-v3/configs/strategies/strategies.json"
|
|
14
|
+
*/
|
|
15
|
+
strategiesUrl?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Cache TTL in milliseconds.
|
|
18
|
+
* @default 60_000
|
|
19
|
+
*/
|
|
20
|
+
cacheTtlMs?: number;
|
|
21
|
+
/**
|
|
22
|
+
* Optional logger for cache diagnostics.
|
|
23
|
+
*/
|
|
24
|
+
logger?: ILogger;
|
|
25
|
+
}
|
|
26
|
+
export declare class RemoteConfigSource implements ConfigSource {
|
|
27
|
+
#private;
|
|
28
|
+
constructor(options?: RemoteConfigSourceOptions);
|
|
29
|
+
getPools(): Promise<Array<PoolConfigPayload>>;
|
|
30
|
+
getStrategies(): Promise<Array<StrategyConfigPayload>>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PoolConfigPayload } from "../../common-utils/static/pool-config.js";
|
|
2
|
+
import type { NotValidatedStrategy } from "../../common-utils/utils/strategies/types/strategy.js";
|
|
3
|
+
import { BasePlugin, type IOnchainSDKPlugin } from "../../sdk/index.js";
|
|
4
|
+
import type { RemoteConfigsPluginOptions, RemoteConfigsPluginState } from "./types.js";
|
|
5
|
+
export declare class RemoteConfigsPlugin extends BasePlugin<RemoteConfigsPluginState> implements IOnchainSDKPlugin<RemoteConfigsPluginState> {
|
|
6
|
+
#private;
|
|
7
|
+
constructor(loadOnAttach?: boolean, options?: RemoteConfigsPluginOptions);
|
|
8
|
+
get loaded(): boolean;
|
|
9
|
+
load(force?: boolean): Promise<RemoteConfigsPluginState>;
|
|
10
|
+
syncState(): Promise<void>;
|
|
11
|
+
get state(): RemoteConfigsPluginState;
|
|
12
|
+
hydrate(state: RemoteConfigsPluginState): void;
|
|
13
|
+
stateHuman(_?: boolean): RemoteConfigsPluginState;
|
|
14
|
+
/**
|
|
15
|
+
* Pool configs for the current SDK network.
|
|
16
|
+
* @throws if plugin is not loaded
|
|
17
|
+
*/
|
|
18
|
+
get pools(): PoolConfigPayload[];
|
|
19
|
+
/**
|
|
20
|
+
* Strategy configs for the current SDK network.
|
|
21
|
+
* @throws if plugin is not loaded
|
|
22
|
+
*/
|
|
23
|
+
get strategies(): NotValidatedStrategy[];
|
|
24
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { PoolConfigPayload } from "../../common-utils/static/pool-config.js";
|
|
2
|
+
import type { StrategyConfigPayload } from "../../common-utils/static/strategy.js";
|
|
3
|
+
import type { NotValidatedStrategy } from "../../common-utils/utils/strategies/types/strategy.js";
|
|
4
|
+
export interface RemoteConfigsPluginState {
|
|
5
|
+
pools: PoolConfigPayload[];
|
|
6
|
+
strategies: NotValidatedStrategy[];
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Abstraction for a config provider.
|
|
10
|
+
* Multiple sources can be composed; the plugin tries them in order
|
|
11
|
+
* until one succeeds.
|
|
12
|
+
*/
|
|
13
|
+
export interface ConfigSource {
|
|
14
|
+
getPools(): Promise<PoolConfigPayload[]>;
|
|
15
|
+
getStrategies(): Promise<StrategyConfigPayload[]>;
|
|
16
|
+
}
|
|
17
|
+
export interface RemoteConfigsPluginOptions {
|
|
18
|
+
/**
|
|
19
|
+
* Ordered list of config sources.
|
|
20
|
+
* Defaults to `[new RemoteConfigSource()]` if omitted.
|
|
21
|
+
*/
|
|
22
|
+
sources?: ConfigSource[];
|
|
23
|
+
}
|
|
24
|
+
export type { NotValidatedStrategy, PoolConfigPayload, StrategyConfigPayload };
|