@strkfarm/sdk 1.0.9 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -8,7 +8,7 @@ interface TokenInfo {
8
8
  symbol: string;
9
9
  address: string;
10
10
  decimals: number;
11
- pricerKey?: string;
11
+ coingeckId?: string;
12
12
  }
13
13
  declare enum Network {
14
14
  mainnet = "mainnet",
@@ -23,6 +23,32 @@ interface IConfig {
23
23
  }
24
24
  declare function getMainnetConfig(rpcUrl?: string, blockIdentifier?: BlockIdentifier): IConfig;
25
25
 
26
+ declare class Web3Number extends BigNumber {
27
+ decimals: number;
28
+ constructor(value: string | number, decimals: number);
29
+ static fromWei(weiNumber: string | number, decimals: number): Web3Number;
30
+ toWei(): string;
31
+ multipliedBy(value: string | number): Web3Number;
32
+ dividedBy(value: string | number): Web3Number;
33
+ plus(value: string | number): Web3Number;
34
+ minus(n: number | string, base?: number): Web3Number;
35
+ toString(base?: number | undefined): string;
36
+ }
37
+
38
+ /**
39
+ * A simple wrapper around a contract address that is universally comparable
40
+ * - Helps avoid padding issues
41
+ */
42
+ declare class ContractAddr {
43
+ readonly address: string;
44
+ constructor(address: string);
45
+ static from(address: string): ContractAddr;
46
+ eq(other: ContractAddr): boolean;
47
+ eqString(other: string): boolean;
48
+ static standardise(address: string | bigint): string;
49
+ static eqString(a: string, b: string): boolean;
50
+ }
51
+
26
52
  interface PriceInfo {
27
53
  price: number;
28
54
  timestamp: Date;
@@ -37,6 +63,7 @@ declare class Pricer {
37
63
  * TOKENA and TOKENB are the two token names to get price of TokenA in terms of TokenB
38
64
  */
39
65
  protected PRICE_API: string;
66
+ protected EKUBO_API: string;
40
67
  protected client: any;
41
68
  constructor(config: IConfig, tokens: TokenInfo[]);
42
69
  isReady(): boolean;
@@ -49,6 +76,7 @@ declare class Pricer {
49
76
  _getPrice(token: TokenInfo): Promise<number>;
50
77
  _getPriceCoinbase(token: TokenInfo): Promise<number>;
51
78
  _getPriceCoinMarketCap(token: TokenInfo): Promise<number>;
79
+ _getPriceEkubo(token: TokenInfo, amountIn?: Web3Number, retry?: number): Promise<number>;
52
80
  }
53
81
 
54
82
  declare class Pragma {
@@ -58,32 +86,6 @@ declare class Pragma {
58
86
  getPrice(tokenAddr: string): Promise<number>;
59
87
  }
60
88
 
61
- /**
62
- * A simple wrapper around a contract address that is universally comparable
63
- * - Helps avoid padding issues
64
- */
65
- declare class ContractAddr {
66
- readonly address: string;
67
- constructor(address: string);
68
- static from(address: string): ContractAddr;
69
- eq(other: ContractAddr): boolean;
70
- eqString(other: string): boolean;
71
- static standardise(address: string | bigint): string;
72
- static eqString(a: string, b: string): boolean;
73
- }
74
-
75
- declare class Web3Number extends BigNumber {
76
- decimals: number;
77
- constructor(value: string | number, decimals: number);
78
- static fromWei(weiNumber: string | number, decimals: number): Web3Number;
79
- toWei(): string;
80
- multipliedBy(value: string | number): Web3Number;
81
- dividedBy(value: string | number): Web3Number;
82
- plus(value: string | number): Web3Number;
83
- minus(n: number | string, base?: number): Web3Number;
84
- toString(base?: number | undefined): string;
85
- }
86
-
87
89
  interface ILendingMetadata {
88
90
  name: string;
89
91
  logo: string;
package/dist/index.js CHANGED
@@ -53,90 +53,10 @@ __export(src_exports, {
53
53
  module.exports = __toCommonJS(src_exports);
54
54
 
55
55
  // src/modules/pricer.ts
56
- var import_axios = __toESM(require("axios"));
57
-
58
- // src/data/tokens.json
59
- var tokens_default = [
60
- {
61
- name: "Ether",
62
- symbol: "ETH",
63
- address: "0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7",
64
- decimals: 18,
65
- pricerKey: "ETH-USDT"
66
- },
67
- {
68
- name: "USD Coin",
69
- symbol: "USDC",
70
- address: "0x053c91253bc9682c04929ca02ed00b3e423f6710d2ee7e0d5ebb06f3ecf368a8",
71
- decimals: 6,
72
- pricerKey: "USDC-USDT"
73
- },
74
- {
75
- name: "Wrapped BTC",
76
- symbol: "WBTC",
77
- address: "0x03fe2b97c1fd336e750087d68b9b867997fd64a2661ff3ca5a7c771641e8e7ac",
78
- decimals: 8,
79
- pricerKey: "WBTC-USDT"
80
- },
81
- {
82
- name: "Tether USD",
83
- symbol: "USDT",
84
- address: "0x068f5c6a61780768455de69077e07e89787839bf8166decfbf92b645209c0fb8",
85
- decimals: 6,
86
- pricerKey: "USDT-USDT"
87
- },
88
- {
89
- name: "Dai Stablecoin",
90
- symbol: "DAIv0",
91
- address: "",
92
- decimals: 18,
93
- pricerKey: "DAI-USDT"
94
- },
95
- {
96
- name: "Starknet Wrapped Staked Ether",
97
- symbol: "wstETH",
98
- address: "0x042b8f0484674ca266ac5d08e4ac6a3fe65bd3129795def2dca5c34ecc5f96d2",
99
- decimals: 18,
100
- pricerKey: "wstETH-USDT"
101
- },
102
- {
103
- name: "Starknet Token",
104
- symbol: "STRK",
105
- address: "0x04718f5a0fc34cc1af16a1cdee98ffb20c31f5cd61d6ab07201858f4287c938d",
106
- decimals: 18,
107
- pricerKey: "STRK-USDT"
108
- },
109
- {
110
- name: "zkLend Token",
111
- symbol: "ZEND",
112
- address: "",
113
- decimals: 18,
114
- pricerKey: "ZEND-USDT"
115
- },
116
- {
117
- name: "Dai Stablecoin",
118
- symbol: "DAI",
119
- address: "",
120
- decimals: 18,
121
- pricerKey: "DAI-USDT"
122
- },
123
- {
124
- name: "Ekubo Protocol",
125
- symbol: "EKUBO",
126
- address: "",
127
- decimals: 18,
128
- pricerKey: "DAI-USDT"
129
- },
130
- {
131
- name: "kSTRK token",
132
- symbol: "kSTRK",
133
- address: "",
134
- decimals: 18,
135
- pricerKey: "DAI-USDT"
136
- }
137
- ];
56
+ var import_axios2 = __toESM(require("axios"));
138
57
 
139
58
  // src/global.ts
59
+ var import_axios = __toESM(require("axios"));
140
60
  var logger = {
141
61
  ...console,
142
62
  verbose(message) {
@@ -152,6 +72,7 @@ var FatalError = class extends Error {
152
72
  this.name = "FatalError";
153
73
  }
154
74
  };
75
+ var tokens = [];
155
76
  var Global = class {
156
77
  static fatalError(message, err) {
157
78
  logger.error(message);
@@ -165,7 +86,23 @@ var Global = class {
165
86
  console.error(err);
166
87
  }
167
88
  static async getTokens() {
168
- return tokens_default;
89
+ if (tokens.length) return tokens;
90
+ const data = await import_axios.default.get("https://starknet.api.avnu.fi/v1/starknet/tokens");
91
+ const tokensData = data.data.content;
92
+ tokensData.forEach((token) => {
93
+ if (!token.tags.includes("AVNU") || !token.tags.includes("Verified")) {
94
+ return;
95
+ }
96
+ tokens.push({
97
+ name: token.name,
98
+ symbol: token.symbol,
99
+ address: token.address,
100
+ decimals: token.decimals,
101
+ coingeckId: token.extensions.coingeckoId
102
+ });
103
+ });
104
+ console.log(tokens);
105
+ return tokens;
169
106
  }
170
107
  static assert(condition, message) {
171
108
  if (!condition) {
@@ -174,20 +111,86 @@ var Global = class {
174
111
  }
175
112
  };
176
113
 
114
+ // src/dataTypes/bignumber.ts
115
+ var import_bignumber = __toESM(require("bignumber.js"));
116
+ var Web3Number = class _Web3Number extends import_bignumber.default {
117
+ constructor(value, decimals) {
118
+ super(value);
119
+ this.decimals = decimals;
120
+ }
121
+ static fromWei(weiNumber, decimals) {
122
+ const bn = new _Web3Number(weiNumber, decimals).dividedBy(10 ** decimals);
123
+ return new _Web3Number(bn.toString(), decimals);
124
+ }
125
+ toWei() {
126
+ return this.mul(10 ** this.decimals).toFixed(0);
127
+ }
128
+ multipliedBy(value) {
129
+ return new _Web3Number(this.mul(value).toString(), this.decimals);
130
+ }
131
+ dividedBy(value) {
132
+ return new _Web3Number(this.div(value).toString(), this.decimals);
133
+ }
134
+ plus(value) {
135
+ return new _Web3Number(this.add(value).toString(), this.decimals);
136
+ }
137
+ minus(n, base) {
138
+ return new _Web3Number(super.minus(n, base).toString(), this.decimals);
139
+ }
140
+ toString(base) {
141
+ return super.toString(base);
142
+ }
143
+ // [customInspectSymbol](depth: any, inspectOptions: any, inspect: any) {
144
+ // return this.toString();
145
+ // }
146
+ };
147
+ import_bignumber.default.config({ DECIMAL_PLACES: 18 });
148
+ Web3Number.config({ DECIMAL_PLACES: 18 });
149
+
150
+ // src/dataTypes/address.ts
151
+ var import_starknet = require("starknet");
152
+ var ContractAddr = class _ContractAddr {
153
+ constructor(address) {
154
+ this.address = _ContractAddr.standardise(address);
155
+ }
156
+ static from(address) {
157
+ return new _ContractAddr(address);
158
+ }
159
+ eq(other) {
160
+ return this.address === other.address;
161
+ }
162
+ eqString(other) {
163
+ return this.address === _ContractAddr.standardise(other);
164
+ }
165
+ static standardise(address) {
166
+ let _a = address;
167
+ if (!address) {
168
+ _a = "0";
169
+ }
170
+ const a = import_starknet.num.getHexString(import_starknet.num.getDecimalString(_a.toString()));
171
+ return a;
172
+ }
173
+ static eqString(a, b) {
174
+ return _ContractAddr.standardise(a) === _ContractAddr.standardise(b);
175
+ }
176
+ };
177
+
177
178
  // src/modules/pricer.ts
178
179
  var CoinMarketCap = require("coinmarketcap-api");
179
180
  var Pricer = class {
180
- constructor(config, tokens) {
181
+ constructor(config, tokens2) {
181
182
  this.tokens = [];
182
183
  this.prices = {};
183
184
  /**
184
185
  * TOKENA and TOKENB are the two token names to get price of TokenA in terms of TokenB
185
186
  */
186
187
  this.PRICE_API = `https://api.coinbase.com/v2/prices/{{PRICER_KEY}}/buy`;
187
- // backup oracle
188
+ this.EKUBO_API = "https://mainnet-api.ekubo.org/quote/{{AMOUNT}}/{{TOKEN_SYMBOL}}/USDC";
189
+ // e.g. ETH/USDC
190
+ // backup oracle001
188
191
  this.client = new CoinMarketCap(process.env.COINMARKETCAP_KEY);
189
192
  this.config = config;
190
- this.tokens = tokens;
193
+ this.tokens = tokens2;
191
194
  }
192
195
  isReady() {
193
196
  const allPricesExist = Object.keys(this.prices).length === this.tokens.length;
@@ -271,7 +274,7 @@ var Pricer = class {
271
274
  });
272
275
  if (this.isReady() && this.config.heartbeatUrl) {
273
276
  console.log(`sending beat`);
274
- import_axios.default.get(this.config.heartbeatUrl).catch((err) => {
277
+ import_axios2.default.get(this.config.heartbeatUrl).catch((err) => {
275
278
  console.error("Pricer: Heartbeat err", err);
276
279
  });
277
280
  }
@@ -285,14 +288,15 @@ var Pricer = class {
285
288
  return await this._getPriceCoinMarketCap(token);
286
289
  } catch (error) {
287
290
  }
291
+ try {
292
+ return await this._getPriceEkubo(token);
293
+ } catch (error) {
294
+ }
288
295
  throw new FatalError(`Price not found for ${token.name}`);
289
296
  }
290
297
  async _getPriceCoinbase(token) {
291
- if (!token.pricerKey) {
292
- throw new FatalError(`Pricer key not found for ${token.name}`);
293
- }
294
- const url = this.PRICE_API.replace("{{PRICER_KEY}}", token.pricerKey);
295
- const result = await import_axios.default.get(url);
298
+ const url = this.PRICE_API.replace("{{PRICER_KEY}}", `${token.symbol}-USD`);
299
+ const result = await import_axios2.default.get(url);
296
300
  const data = result.data;
297
301
  return Number(data.data.amount);
298
302
  }
@@ -300,10 +304,24 @@ var Pricer = class {
300
304
  const result = await this.client.getQuotes({ symbol: token.symbol });
301
305
  return result.data[token.symbol].quote.USD.price;
302
306
  }
307
+ async _getPriceEkubo(token, amountIn = new Web3Number(1, token.decimals), retry = 0) {
308
+ const url = this.EKUBO_API.replace("{{TOKEN_SYMBOL}}", token.symbol).replace("{{AMOUNT}}", amountIn.toWei());
309
+ const result = await import_axios2.default.get(url);
310
+ const data = result.data;
311
+ const outputUSDC = Number(Web3Number.fromWei(data.total, 6).toFixed(6));
312
+ logger.verbose(`Ekubo: ${token.symbol} -> USDC: ${outputUSDC}, retry: ${retry}`);
313
+ if (outputUSDC === 0 && retry < 3) {
314
+ const amountIn2 = new Web3Number(100, token.decimals);
315
+ return await this._getPriceEkubo(token, amountIn2, retry + 1);
316
+ }
317
+ const usdcPrice = (await this.getPrice("USDC")).price;
318
+ logger.verbose(`USDC Price: ${usdcPrice}`);
319
+ return outputUSDC * usdcPrice;
320
+ }
303
321
  };
304
322
 
305
323
  // src/modules/pragma.ts
306
- var import_starknet = require("starknet");
324
+ var import_starknet2 = require("starknet");
307
325
 
308
326
  // src/data/pragma.abi.json
309
327
  var pragma_abi_default = [
@@ -407,7 +425,7 @@ var pragma_abi_default = [
407
425
  var Pragma = class {
408
426
  constructor(provider) {
409
427
  this.contractAddr = "0x023fb3afbff2c0e3399f896dcf7400acf1a161941cfb386e34a123f228c62832";
410
- this.contract = new import_starknet.Contract(pragma_abi_default, this.contractAddr, provider);
428
+ this.contract = new import_starknet2.Contract(pragma_abi_default, this.contractAddr, provider);
411
429
  }
412
430
  async getPrice(tokenAddr) {
413
431
  if (!tokenAddr) {
@@ -421,43 +439,7 @@ var Pragma = class {
421
439
  };
422
440
 
423
441
  // src/modules/zkLend.ts
424
- var import_axios2 = __toESM(require("axios"));
425
-
426
- // src/dataTypes/bignumber.ts
427
- var import_bignumber = __toESM(require("bignumber.js"));
428
- var Web3Number = class _Web3Number extends import_bignumber.default {
429
- constructor(value, decimals) {
430
- super(value);
431
- this.decimals = decimals;
432
- }
433
- static fromWei(weiNumber, decimals) {
434
- const bn = new _Web3Number(weiNumber, decimals).dividedBy(10 ** decimals);
435
- return new _Web3Number(bn.toString(), decimals);
436
- }
437
- toWei() {
438
- return this.mul(10 ** this.decimals).toFixed(0);
439
- }
440
- multipliedBy(value) {
441
- return new _Web3Number(this.mul(value).toString(), this.decimals);
442
- }
443
- dividedBy(value) {
444
- return new _Web3Number(this.div(value).toString(), this.decimals);
445
- }
446
- plus(value) {
447
- return new _Web3Number(this.add(value).toString(), this.decimals);
448
- }
449
- minus(n, base) {
450
- return new _Web3Number(super.minus(n, base).toString(), this.decimals);
451
- }
452
- toString(base) {
453
- return super.toString(base);
454
- }
455
- // [customInspectSymbol](depth: any, inspectOptions: any, inspect: any) {
456
- // return this.toString();
457
- // }
458
- };
459
- import_bignumber.default.config({ DECIMAL_PLACES: 18 });
460
- Web3Number.config({ DECIMAL_PLACES: 18 });
442
+ var import_axios3 = __toESM(require("axios"));
461
443
 
462
444
  // src/interfaces/lending.ts
463
445
  var MarginType = /* @__PURE__ */ ((MarginType2) => {
@@ -501,7 +483,7 @@ var _ZkLend = class _ZkLend extends ILending {
501
483
  async init() {
502
484
  try {
503
485
  logger.verbose(`Initialising ${this.metadata.name}`);
504
- const result = await import_axios2.default.get(_ZkLend.POOLS_URL);
486
+ const result = await import_axios3.default.get(_ZkLend.POOLS_URL);
505
487
  const data = result.data;
506
488
  const savedTokens = await Global.getTokens();
507
489
  data.forEach((pool) => {
@@ -591,7 +573,7 @@ var _ZkLend = class _ZkLend extends ILending {
591
573
  */
592
574
  async getPositions(user) {
593
575
  const url = this.POSITION_URL.replace("{{USER_ADDR}}", user.address);
594
- const result = await import_axios2.default.get(url);
576
+ const result = await import_axios3.default.get(url);
595
577
  const data = result.data;
596
578
  const lendingPosition = [];
597
579
  logger.verbose(`${this.metadata.name}:: Positions: ${JSON.stringify(data)}`);
@@ -624,7 +606,7 @@ _ZkLend.POOLS_URL = "https://app.zklend.com/api/pools";
624
606
  var ZkLend = _ZkLend;
625
607
 
626
608
  // src/interfaces/common.ts
627
- var import_starknet2 = require("starknet");
609
+ var import_starknet3 = require("starknet");
628
610
  var Network = /* @__PURE__ */ ((Network2) => {
629
611
  Network2["mainnet"] = "mainnet";
630
612
  Network2["sepolia"] = "sepolia";
@@ -633,7 +615,7 @@ var Network = /* @__PURE__ */ ((Network2) => {
633
615
  })(Network || {});
634
616
  function getMainnetConfig(rpcUrl = "https://starknet-mainnet.public.blastapi.io", blockIdentifier = "pending") {
635
617
  return {
636
- provider: new import_starknet2.RpcProvider({
618
+ provider: new import_starknet3.RpcProvider({
637
619
  nodeUrl: rpcUrl,
638
620
  blockIdentifier
639
621
  }),
@@ -660,34 +642,6 @@ var Initializable = class {
660
642
  }
661
643
  };
662
644
 
663
- // src/dataTypes/address.ts
664
- var import_starknet3 = require("starknet");
665
- var ContractAddr = class _ContractAddr {
666
- constructor(address) {
667
- this.address = _ContractAddr.standardise(address);
668
- }
669
- static from(address) {
670
- return new _ContractAddr(address);
671
- }
672
- eq(other) {
673
- return this.address === other.address;
674
- }
675
- eqString(other) {
676
- return this.address === _ContractAddr.standardise(other);
677
- }
678
- static standardise(address) {
679
- let _a = address;
680
- if (!address) {
681
- _a = "0";
682
- }
683
- const a = import_starknet3.num.getHexString(import_starknet3.num.getDecimalString(_a.toString()));
684
- return a;
685
- }
686
- static eqString(a, b) {
687
- return _ContractAddr.standardise(a) === _ContractAddr.standardise(b);
688
- }
689
- };
690
-
691
645
  // src/strategies/autoCompounderStrk.ts
692
646
  var import_starknet4 = require("starknet");
693
647
  var AutoCompounderSTRK = class {
@@ -955,8 +909,8 @@ var Store = class _Store {
955
909
  // src/node/pricer-redis.ts
956
910
  var import_redis = require("redis");
957
911
  var PricerRedis = class extends Pricer {
958
- constructor(config, tokens) {
959
- super(config, tokens);
912
+ constructor(config, tokens2) {
913
+ super(config, tokens2);
960
914
  this.redisClient = null;
961
915
  }
962
916
  /** Reads prices from Pricer._loadPrices and uses a callback to set prices in redis */