@strkfarm/sdk 2.0.0-staging.69 → 2.0.0-staging.70

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/index.js CHANGED
@@ -65,6 +65,7 @@ __export(index_exports, {
65
65
  PasswordJsonCryptoUtil: () => PasswordJsonCryptoUtil,
66
66
  Pragma: () => Pragma,
67
67
  Pricer: () => Pricer,
68
+ PricerAvnuApi: () => PricerAvnuApi,
68
69
  PricerFromApi: () => PricerFromApi,
69
70
  PricerLST: () => PricerLST2,
70
71
  PricerRedis: () => PricerRedis,
@@ -139,7 +140,7 @@ __export(index_exports, {
139
140
  module.exports = __toCommonJS(index_exports);
140
141
 
141
142
  // src/modules/pricer.ts
142
- var import_axios2 = __toESM(require("axios"));
143
+ var import_axios3 = __toESM(require("axios"));
143
144
 
144
145
  // src/global.ts
145
146
  var import_axios = __toESM(require("axios"));
@@ -606,8 +607,9 @@ var defaultTokens = [{
606
607
  decimals: 18,
607
608
  coingeckId: void 0,
608
609
  displayDecimals: 6,
609
- priceCheckAmount: 1e-4
610
+ priceCheckAmount: 1e-4,
610
611
  // 112000 * 0.0001 = $11.2
612
+ dontPrice: true
611
613
  }, {
612
614
  name: "mRe7YIELD",
613
615
  symbol: "mRe7YIELD",
@@ -616,7 +618,8 @@ var defaultTokens = [{
616
618
  decimals: 18,
617
619
  coingeckId: void 0,
618
620
  displayDecimals: 2,
619
- priceCheckAmount: 100
621
+ priceCheckAmount: 100,
622
+ dontPrice: true
620
623
  }, {
621
624
  name: "fyeWBTC",
622
625
  symbol: "fyeWBTC",
@@ -625,8 +628,9 @@ var defaultTokens = [{
625
628
  decimals: 8,
626
629
  coingeckId: void 0,
627
630
  displayDecimals: 6,
628
- priceCheckAmount: 1e-3
631
+ priceCheckAmount: 1e-3,
629
632
  // 112000 * 0.0001 = $110.2
633
+ dontPrice: true
630
634
  }, {
631
635
  name: "fyETH",
632
636
  symbol: "fyETH",
@@ -635,7 +639,8 @@ var defaultTokens = [{
635
639
  decimals: 18,
636
640
  coingeckId: void 0,
637
641
  displayDecimals: 4,
638
- priceCheckAmount: 0.1
642
+ priceCheckAmount: 0.1,
643
+ dontPrice: true
639
644
  }, {
640
645
  name: "fyeUSDC",
641
646
  symbol: "fyeUSDC",
@@ -644,7 +649,8 @@ var defaultTokens = [{
644
649
  decimals: 6,
645
650
  coingeckId: void 0,
646
651
  displayDecimals: 2,
647
- priceCheckAmount: 100
652
+ priceCheckAmount: 100,
653
+ dontPrice: true
648
654
  }, {
649
655
  name: "strkBTC",
650
656
  symbol: "strkBTC",
@@ -935,7 +941,96 @@ var AvnuWrapper = class _AvnuWrapper {
935
941
  }
936
942
  };
937
943
 
944
+ // src/modules/pricer-avnu-api.ts
945
+ var import_axios2 = __toESM(require("axios"));
946
+ var AVNU_TOKENS_API = "https://starknet.impulse.avnu.fi/v3/tokens";
947
+ var PricerAvnuApi = class extends PricerBase {
948
+ constructor(config, tokens2) {
949
+ super(config, tokens2);
950
+ this.prices = {};
951
+ this.refreshInterval = 15e3;
952
+ this.staleTime = 5 * 60 * 1e3;
953
+ this.pollTimer = null;
954
+ this.loading = false;
955
+ }
956
+ start() {
957
+ this._loadPrices();
958
+ this.pollTimer = setInterval(() => {
959
+ this._loadPrices();
960
+ }, this.refreshInterval);
961
+ }
962
+ stop() {
963
+ if (this.pollTimer) {
964
+ clearInterval(this.pollTimer);
965
+ this.pollTimer = null;
966
+ }
967
+ }
968
+ isStale(timestamp) {
969
+ return Date.now() - timestamp.getTime() > this.staleTime;
970
+ }
971
+ hasPrice(tokenSymbol) {
972
+ const info = this.prices[tokenSymbol];
973
+ return !!info && !this.isStale(info.timestamp);
974
+ }
975
+ async getPrice(tokenSymbol) {
976
+ const info = this.prices[tokenSymbol];
977
+ if (!info) {
978
+ throw new Error(`AvnuApi: price of ${tokenSymbol} not found`);
979
+ }
980
+ if (this.isStale(info.timestamp)) {
981
+ throw new Error(`AvnuApi: price of ${tokenSymbol} is stale`);
982
+ }
983
+ return info;
984
+ }
985
+ async _loadPrices() {
986
+ if (this.loading) {
987
+ return;
988
+ }
989
+ this.loading = true;
990
+ const timestamp = /* @__PURE__ */ new Date();
991
+ try {
992
+ const result = await import_axios2.default.get(AVNU_TOKENS_API);
993
+ const priceByAddress = /* @__PURE__ */ new Map();
994
+ for (const entry of result.data) {
995
+ const usd = entry.starknet?.usd;
996
+ if (usd != null && usd > 0) {
997
+ priceByAddress.set(ContractAddr.standardise(entry.address), usd);
998
+ }
999
+ }
1000
+ for (const token of this.tokens) {
1001
+ if (token.symbol === "USDT" || token.symbol === "USDC") {
1002
+ this.prices[token.symbol] = { price: 1, timestamp };
1003
+ continue;
1004
+ }
1005
+ const targetToken = token.priceProxySymbol ? this.tokens.find((t) => t.symbol === token.priceProxySymbol) : token;
1006
+ if (!targetToken) {
1007
+ continue;
1008
+ }
1009
+ const addr = targetToken.address.address;
1010
+ const price = priceByAddress.get(addr);
1011
+ if (price != null) {
1012
+ this.prices[token.symbol] = { price, timestamp };
1013
+ logger.verbose(
1014
+ `AvnuApi: ${token.symbol} -> $${price}`
1015
+ );
1016
+ }
1017
+ }
1018
+ } catch (error) {
1019
+ logger.warn(`AvnuApi: failed to fetch tokens: ${error?.message ?? error}`);
1020
+ } finally {
1021
+ this.loading = false;
1022
+ }
1023
+ }
1024
+ };
1025
+
938
1026
  // src/modules/pricer.ts
1027
+ var PRICE_METHOD_PRIORITY = [
1028
+ "AvnuApi",
1029
+ "Coinbase",
1030
+ "Coinmarketcap",
1031
+ "Ekubo",
1032
+ "Avnu"
1033
+ ];
939
1034
  var Pricer = class extends PricerBase {
940
1035
  // e.g. ETH/USDC
941
1036
  constructor(config, tokens2, refreshInterval = 3e4, staleTime = 6e4) {
@@ -954,6 +1049,7 @@ var Pricer = class extends PricerBase {
954
1049
  this.EKUBO_API = "https://prod-api-quoter.ekubo.org/23448594291968334/{{AMOUNT}}/{{TOKEN_ADDRESS}}/0x033068F6539f8e6e6b131e6B2B814e6c34A5224bC66947c47DaB9dFeE93b35fb";
955
1050
  this.refreshInterval = refreshInterval;
956
1051
  this.staleTime = staleTime;
1052
+ this.avnuApiPricer = new PricerAvnuApi(config, tokens2);
957
1053
  }
958
1054
  isReady() {
959
1055
  const allPricesExist = Object.keys(this.prices).length === this.tokens.length;
@@ -983,6 +1079,7 @@ var Pricer = class extends PricerBase {
983
1079
  });
984
1080
  }
985
1081
  start() {
1082
+ this.avnuApiPricer.start();
986
1083
  this._loadPrices();
987
1084
  setInterval(() => {
988
1085
  this._loadPrices();
@@ -1007,6 +1104,9 @@ var Pricer = class extends PricerBase {
1007
1104
  let retry = 0;
1008
1105
  while (retry < MAX_RETRIES) {
1009
1106
  try {
1107
+ if (token.dontPrice) {
1108
+ return;
1109
+ }
1010
1110
  if (token.symbol === "USDT" || token.symbol === "USDC") {
1011
1111
  this.prices[token.symbol] = {
1012
1112
  price: 1,
@@ -1049,60 +1149,61 @@ var Pricer = class extends PricerBase {
1049
1149
  });
1050
1150
  if (this.isReady() && this.config.heartbeatUrl) {
1051
1151
  console.log(`sending beat`);
1052
- import_axios2.default.get(this.config.heartbeatUrl).catch((err) => {
1152
+ import_axios3.default.get(this.config.heartbeatUrl).catch((err) => {
1053
1153
  console.error("Pricer: Heartbeat err", err);
1054
1154
  });
1055
1155
  }
1056
1156
  }
1057
- async _getPrice(token, defaultMethod = "all") {
1058
- const methodToUse = this.methodToUse[token.symbol] || defaultMethod;
1059
- logger.verbose(`Fetching price of ${token.symbol} using ${methodToUse}`);
1060
- switch (methodToUse) {
1157
+ async _getPrice(token) {
1158
+ const pinned = this.methodToUse[token.symbol];
1159
+ if (pinned) {
1160
+ logger.verbose(`Fetching price of ${token.symbol} using pinned ${pinned}`);
1161
+ try {
1162
+ return await this._tryPriceMethod(token, pinned);
1163
+ } catch (error) {
1164
+ console.warn(`${pinned}: pinned price failed [${token.symbol}]: `, error.message);
1165
+ delete this.methodToUse[token.symbol];
1166
+ }
1167
+ }
1168
+ for (const method of PRICE_METHOD_PRIORITY) {
1169
+ logger.verbose(`Fetching price of ${token.symbol} using ${method}`);
1170
+ try {
1171
+ const result = await this._tryPriceMethod(token, method);
1172
+ this.methodToUse[token.symbol] = method;
1173
+ return result;
1174
+ } catch (error) {
1175
+ console.warn(`${method}: price err [${token.symbol}]: `, error.message);
1176
+ }
1177
+ }
1178
+ throw new FatalError(`Price not found for ${token.symbol}`);
1179
+ }
1180
+ async _tryPriceMethod(token, method) {
1181
+ switch (method) {
1182
+ case "AvnuApi":
1183
+ return await this._getPriceAvnuApi(token);
1061
1184
  case "Coinbase":
1062
- // try {
1063
- // const result = await this._getPriceCoinbase(token);
1064
- // this.methodToUse[token.symbol] = 'Coinbase';
1065
- // return result;
1066
- // } catch (error: any) {
1067
- // console.warn(`Coinbase: price err: message [${token.symbol}]: `, error.message);
1068
- // // do nothing, try next
1069
- // }
1185
+ return await this._getPriceCoinbase(token);
1070
1186
  case "Coinmarketcap":
1071
- try {
1072
- const result = await this._getPriceCoinMarketCap(token);
1073
- this.methodToUse[token.symbol] = "Coinmarketcap";
1074
- return result;
1075
- } catch (error) {
1076
- console.warn(`CoinMarketCap: price err [${token.symbol}]: `, Object.keys(error));
1077
- console.warn(`CoinMarketCap: price err [${token.symbol}]: `, error.message);
1078
- }
1187
+ return await this._getPriceCoinMarketCap(token);
1079
1188
  case "Ekubo":
1080
- try {
1081
- const result = await this._getPriceEkubo(token, new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals));
1082
- this.methodToUse[token.symbol] = "Ekubo";
1083
- return result;
1084
- } catch (error) {
1085
- console.warn(`Ekubo: price err [${token.symbol}]: `, error.message);
1086
- console.warn(`Ekubo: price err [${token.symbol}]: `, Object.keys(error));
1087
- }
1189
+ return await this._getPriceEkubo(
1190
+ token,
1191
+ new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals)
1192
+ );
1088
1193
  case "Avnu":
1089
- try {
1090
- const result = await this._getAvnuPrice(token, new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals));
1091
- this.methodToUse[token.symbol] = "Avnu";
1092
- return result;
1093
- } catch (error) {
1094
- console.warn(`Avnu: price err [${token.symbol}]: `, error.message);
1095
- console.warn(`Avnu: price err [${token.symbol}]: `, Object.keys(error));
1096
- }
1097
- }
1098
- if (defaultMethod == "all") {
1099
- return await this._getPrice(token, "Coinbase");
1194
+ return await this._getAvnuPrice(
1195
+ token,
1196
+ new Web3Number(token.priceCheckAmount ? token.priceCheckAmount : 1, token.decimals)
1197
+ );
1100
1198
  }
1101
- throw new FatalError(`Price not found for ${token.symbol}`);
1199
+ }
1200
+ async _getPriceAvnuApi(token) {
1201
+ const priceInfo = await this.avnuApiPricer.getPrice(token.symbol);
1202
+ return priceInfo.price;
1102
1203
  }
1103
1204
  async _getPriceCoinbase(token) {
1104
1205
  const url = this.PRICE_API.replace("{{PRICER_KEY}}", `${token.symbol}-USD`);
1105
- const result = await import_axios2.default.get(url);
1206
+ const result = await import_axios3.default.get(url);
1106
1207
  const data = result.data;
1107
1208
  return Number(data.data.amount);
1108
1209
  }
@@ -1128,7 +1229,7 @@ var Pricer = class extends PricerBase {
1128
1229
  async _getPriceEkubo(token, amountIn = new Web3Number(1, token.decimals), retry = 0) {
1129
1230
  logger.verbose(`Getting price of ${token.symbol} using Ekubo, amountIn: ${amountIn.toWei()}`);
1130
1231
  const url = this.EKUBO_API.replace("{{TOKEN_ADDRESS}}", token.address.toString()).replace("{{AMOUNT}}", amountIn.toWei());
1131
- const result = await import_axios2.default.get(url);
1232
+ const result = await import_axios3.default.get(url);
1132
1233
  const data = result.data;
1133
1234
  const multiplier = 1 / amountIn.toNumber();
1134
1235
  const outputUSDC = Number(Web3Number.fromWei(data.total_calculated, 6).toFixed(6)) * multiplier;
@@ -1274,7 +1375,7 @@ var Pragma = class extends PricerBase {
1274
1375
  };
1275
1376
 
1276
1377
  // src/modules/zkLend.ts
1277
- var import_axios3 = __toESM(require("axios"));
1378
+ var import_axios4 = __toESM(require("axios"));
1278
1379
 
1279
1380
  // src/dataTypes/bignumber.browser.ts
1280
1381
  var import_starknet8 = require("starknet");
@@ -1330,7 +1431,7 @@ var _ZkLend = class _ZkLend extends ILending {
1330
1431
  async init() {
1331
1432
  try {
1332
1433
  logger.verbose(`Initialising ${this.metadata.name}`);
1333
- const result = await import_axios3.default.get(_ZkLend.POOLS_URL);
1434
+ const result = await import_axios4.default.get(_ZkLend.POOLS_URL);
1334
1435
  const data = result.data;
1335
1436
  const savedTokens = await Global.getTokens();
1336
1437
  data.forEach((pool) => {
@@ -1422,7 +1523,7 @@ var _ZkLend = class _ZkLend extends ILending {
1422
1523
  */
1423
1524
  async getPositions(user) {
1424
1525
  const url = this.POSITION_URL.replace("{{USER_ADDR}}", user.address);
1425
- const result = await import_axios3.default.get(url);
1526
+ const result = await import_axios4.default.get(url);
1426
1527
  const data = result.data;
1427
1528
  const lendingPosition = [];
1428
1529
  logger.verbose(`${this.metadata.name}:: Positions: ${JSON.stringify(data)}`);
@@ -1455,7 +1556,7 @@ _ZkLend.POOLS_URL = "https://app.zklend.com/api/pools";
1455
1556
  var ZkLend = _ZkLend;
1456
1557
 
1457
1558
  // src/modules/pricer-from-api.ts
1458
- var import_axios4 = __toESM(require("axios"));
1559
+ var import_axios5 = __toESM(require("axios"));
1459
1560
 
1460
1561
  // src/modules/apollo-client-config.ts
1461
1562
  var import_client = require("@apollo/client");
@@ -1837,7 +1938,7 @@ var PricerFromApi = class extends PricerBase {
1837
1938
  const MAX_RETRIES = 5;
1838
1939
  for (retry = 1; retry < MAX_RETRIES + 1; retry++) {
1839
1940
  try {
1840
- const priceInfo = await import_axios4.default.get(
1941
+ const priceInfo = await import_axios5.default.get(
1841
1942
  `https://api.coinbase.com/v2/prices/${tokenSymbol}-USDT/spot`
1842
1943
  );
1843
1944
  if (!priceInfo) {
@@ -3121,7 +3222,7 @@ var ERC20 = class {
3121
3222
  };
3122
3223
 
3123
3224
  // src/modules/ekubo-quoter.ts
3124
- var import_axios5 = __toESM(require("axios"));
3225
+ var import_axios6 = __toESM(require("axios"));
3125
3226
  var EkuboQuoter = class {
3126
3227
  // e.g. ETH/USDC'
3127
3228
  constructor(config) {
@@ -3139,7 +3240,7 @@ var EkuboQuoter = class {
3139
3240
  let _fromToken = amount.gt(0) ? fromToken : toToken;
3140
3241
  let _toToken = amount.gt(0) ? toToken : fromToken;
3141
3242
  try {
3142
- const quote = await import_axios5.default.get(this.ENDPOINT.replace("{{AMOUNT}}", amount.toWei()).replace("{{TOKEN_FROM_ADDRESS}}", _fromToken).replace("{{TOKEN_TO_ADDRESS}}", _toToken));
3243
+ const quote = await import_axios6.default.get(this.ENDPOINT.replace("{{AMOUNT}}", amount.toWei()).replace("{{TOKEN_FROM_ADDRESS}}", _fromToken).replace("{{TOKEN_TO_ADDRESS}}", _toToken));
3143
3244
  console.log(`Ekubo quote from ${_fromToken} to ${_toToken} for ${amount.toString()}: ${JSON.stringify(quote.data)}`);
3144
3245
  return quote.data;
3145
3246
  } catch (error) {
@@ -5041,9 +5142,9 @@ var BaseStrategy = class extends CacheClass {
5041
5142
  };
5042
5143
 
5043
5144
  // src/node/headless.browser.ts
5044
- var import_axios6 = __toESM(require("axios"));
5145
+ var import_axios7 = __toESM(require("axios"));
5045
5146
  async function getAPIUsingHeadlessBrowser(url) {
5046
- const res = await import_axios6.default.get(url);
5147
+ const res = await import_axios7.default.get(url);
5047
5148
  return res.data;
5048
5149
  }
5049
5150
 
@@ -16968,7 +17069,7 @@ var EkuboCLVault = class _EkuboCLVault extends BaseStrategy {
16968
17069
  const token0Usd = Number(amount0.toFixed(13)) * P0.price;
16969
17070
  const token1Usd = Number(amount1.toFixed(13)) * P1.price;
16970
17071
  const totalUsdValue = token0Usd + token1Usd;
16971
- if (totalUsdValue === 0 || token0Usd === 0 || token1Usd === 0 || amount0.eq(0) || amount1.eq(0)) {
17072
+ if ((totalUsdValue === 0 || token0Usd === 0 || token1Usd === 0 || amount0.eq(0) || amount1.eq(0)) && this.metadata.settings?.liveStatus === "Active" /* ACTIVE */) {
16972
17073
  logger.warn(
16973
17074
  `${this.metadata.name}:getTVL - Zero value detected: usdValue=${totalUsdValue}, amount0=${amount0.toString()}, amount1=${amount1.toString()}, token0Price=${P0.price}, token1Price=${P1.price}, token0Usd=${token0Usd}, token1Usd=${token1Usd}`
16974
17075
  );
@@ -29193,7 +29294,7 @@ var YoLoVault = class extends BaseStrategy {
29193
29294
  sDec
29194
29295
  ).multipliedBy(secondaryTokenPrice.price);
29195
29296
  const totalUsdValue = primaryTokenUsd.plus(secondaryTokenUsd).toNumber();
29196
- if (totalUsdValue === 0 || primaryTokenAmount.eq(0) || secondaryTokenAmount.eq(0)) {
29297
+ if ((totalUsdValue === 0 || primaryTokenAmount.eq(0) || secondaryTokenAmount.eq(0)) && this.metadata.settings?.liveStatus === "Active" /* ACTIVE */) {
29197
29298
  logger.warn(
29198
29299
  `${this.metadata.name}:getTVL - Zero value detected: usdValue=${totalUsdValue}, primaryTokenAmount=${primaryTokenAmount.toString()}, secondaryTokenAmount=${secondaryTokenAmount.toString()}, primaryTokenPrice=${primaryTokenPrice.price}, secondaryTokenPrice=${secondaryTokenPrice.price}, primaryTokenUsd=${primaryTokenUsd.toNumber()}, secondaryTokenUsd=${secondaryTokenUsd.toNumber()}`
29199
29300
  );
@@ -32552,7 +32653,7 @@ var UniversalStrategy = class _UniversalStrategy extends BaseStrategy {
32552
32653
  this.metadata.depositTokens[0].symbol
32553
32654
  );
32554
32655
  const usdValue = Number(amount.toFixed(6)) * price.price;
32555
- if (usdValue === 0 || amount.eq(0)) {
32656
+ if ((usdValue === 0 || amount.eq(0)) && this.metadata.settings?.liveStatus === "Active" /* ACTIVE */) {
32556
32657
  logger.warn(
32557
32658
  `${this.metadata.name}:getTVL - Zero value detected: usdValue=${usdValue}, amount=${amount.toString()}, price=${price.price}`
32558
32659
  );
@@ -35291,7 +35392,7 @@ function createStrategy(type, config, pricer, metadata) {
35291
35392
  }
35292
35393
 
35293
35394
  // src/modules/pricer-lst.ts
35294
- var import_axios7 = __toESM(require("axios"));
35395
+ var import_axios8 = __toESM(require("axios"));
35295
35396
  var PricerLST2 = class extends Pricer {
35296
35397
  // e.g. xSTRK/STRK
35297
35398
  constructor(config, tokenMaps) {
@@ -35327,7 +35428,7 @@ var PricerLST2 = class extends Pricer {
35327
35428
  async _getPriceEkubo(token, amountIn = new Web3Number(1, token.decimals), retry = 0) {
35328
35429
  const underlying = this.getUnderlying(token);
35329
35430
  const url = this.EKUBO_API.replace("{{TOKEN_ADDRESS}}", token.address.toString()).replace("{{AMOUNT}}", amountIn.toWei()).replace("{{UNDERLYING_ADDRESS}}", underlying.address.toString());
35330
- const result = await import_axios7.default.get(url);
35431
+ const result = await import_axios8.default.get(url);
35331
35432
  const data = result.data;
35332
35433
  const multiplier = 1 / amountIn.toNumber();
35333
35434
  const outputUnderlying = Number(Web3Number.fromWei(data.total_calculated, underlying.decimals).toFixed(6)) * multiplier;
@@ -35479,6 +35580,7 @@ var PricerRedis = class extends Pricer {
35479
35580
  async startWithRedis(redisUrl) {
35480
35581
  await this.initRedis(redisUrl);
35481
35582
  logger.info(`Starting Pricer with Redis`);
35583
+ this.avnuApiPricer.start();
35482
35584
  this._loadPrices(this._setRedisPrices.bind(this));
35483
35585
  setInterval(() => {
35484
35586
  this._loadPrices(this._setRedisPrices.bind(this));
@@ -35913,6 +36015,7 @@ var deployer_default = Deployer;
35913
36015
  PasswordJsonCryptoUtil,
35914
36016
  Pragma,
35915
36017
  Pricer,
36018
+ PricerAvnuApi,
35916
36019
  PricerFromApi,
35917
36020
  PricerLST,
35918
36021
  PricerRedis,