@strkfarm/sdk 1.0.8 → 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,83 +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
- ];
56
+ var import_axios2 = __toESM(require("axios"));
131
57
 
132
58
  // src/global.ts
59
+ var import_axios = __toESM(require("axios"));
133
60
  var logger = {
134
61
  ...console,
135
62
  verbose(message) {
@@ -145,6 +72,7 @@ var FatalError = class extends Error {
145
72
  this.name = "FatalError";
146
73
  }
147
74
  };
75
+ var tokens = [];
148
76
  var Global = class {
149
77
  static fatalError(message, err) {
150
78
  logger.error(message);
@@ -158,7 +86,23 @@ var Global = class {
158
86
  console.error(err);
159
87
  }
160
88
  static async getTokens() {
161
- 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;
162
106
  }
163
107
  static assert(condition, message) {
164
108
  if (!condition) {
@@ -167,20 +111,86 @@ var Global = class {
167
111
  }
168
112
  };
169
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
+
170
178
  // src/modules/pricer.ts
171
179
  var CoinMarketCap = require("coinmarketcap-api");
172
180
  var Pricer = class {
173
- constructor(config, tokens) {
181
+ constructor(config, tokens2) {
174
182
  this.tokens = [];
175
183
  this.prices = {};
176
184
  /**
177
185
  * TOKENA and TOKENB are the two token names to get price of TokenA in terms of TokenB
178
186
  */
179
187
  this.PRICE_API = `https://api.coinbase.com/v2/prices/{{PRICER_KEY}}/buy`;
180
- // backup oracle
188
+ this.EKUBO_API = "https://mainnet-api.ekubo.org/quote/{{AMOUNT}}/{{TOKEN_SYMBOL}}/USDC";
189
+ // e.g. ETH/USDC
190
+ // backup oracle001
181
191
  this.client = new CoinMarketCap(process.env.COINMARKETCAP_KEY);
182
192
  this.config = config;
183
- this.tokens = tokens;
193
+ this.tokens = tokens2;
184
194
  }
185
195
  isReady() {
186
196
  const allPricesExist = Object.keys(this.prices).length === this.tokens.length;
@@ -264,7 +274,7 @@ var Pricer = class {
264
274
  });
265
275
  if (this.isReady() && this.config.heartbeatUrl) {
266
276
  console.log(`sending beat`);
267
- import_axios.default.get(this.config.heartbeatUrl).catch((err) => {
277
+ import_axios2.default.get(this.config.heartbeatUrl).catch((err) => {
268
278
  console.error("Pricer: Heartbeat err", err);
269
279
  });
270
280
  }
@@ -278,14 +288,15 @@ var Pricer = class {
278
288
  return await this._getPriceCoinMarketCap(token);
279
289
  } catch (error) {
280
290
  }
291
+ try {
292
+ return await this._getPriceEkubo(token);
293
+ } catch (error) {
294
+ }
281
295
  throw new FatalError(`Price not found for ${token.name}`);
282
296
  }
283
297
  async _getPriceCoinbase(token) {
284
- if (!token.pricerKey) {
285
- throw new FatalError(`Pricer key not found for ${token.name}`);
286
- }
287
- const url = this.PRICE_API.replace("{{PRICER_KEY}}", token.pricerKey);
288
- 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);
289
300
  const data = result.data;
290
301
  return Number(data.data.amount);
291
302
  }
@@ -293,10 +304,24 @@ var Pricer = class {
293
304
  const result = await this.client.getQuotes({ symbol: token.symbol });
294
305
  return result.data[token.symbol].quote.USD.price;
295
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
+ }
296
321
  };
297
322
 
298
323
  // src/modules/pragma.ts
299
- var import_starknet = require("starknet");
324
+ var import_starknet2 = require("starknet");
300
325
 
301
326
  // src/data/pragma.abi.json
302
327
  var pragma_abi_default = [
@@ -400,7 +425,7 @@ var pragma_abi_default = [
400
425
  var Pragma = class {
401
426
  constructor(provider) {
402
427
  this.contractAddr = "0x023fb3afbff2c0e3399f896dcf7400acf1a161941cfb386e34a123f228c62832";
403
- 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);
404
429
  }
405
430
  async getPrice(tokenAddr) {
406
431
  if (!tokenAddr) {
@@ -414,43 +439,7 @@ var Pragma = class {
414
439
  };
415
440
 
416
441
  // src/modules/zkLend.ts
417
- var import_axios2 = __toESM(require("axios"));
418
-
419
- // src/dataTypes/bignumber.ts
420
- var import_bignumber = __toESM(require("bignumber.js"));
421
- var Web3Number = class _Web3Number extends import_bignumber.default {
422
- constructor(value, decimals) {
423
- super(value);
424
- this.decimals = decimals;
425
- }
426
- static fromWei(weiNumber, decimals) {
427
- const bn = new _Web3Number(weiNumber, decimals).dividedBy(10 ** decimals);
428
- return new _Web3Number(bn.toString(), decimals);
429
- }
430
- toWei() {
431
- return this.mul(10 ** this.decimals).toFixed(0);
432
- }
433
- multipliedBy(value) {
434
- return new _Web3Number(this.mul(value).toString(), this.decimals);
435
- }
436
- dividedBy(value) {
437
- return new _Web3Number(this.div(value).toString(), this.decimals);
438
- }
439
- plus(value) {
440
- return new _Web3Number(this.add(value).toString(), this.decimals);
441
- }
442
- minus(n, base) {
443
- return new _Web3Number(super.minus(n, base).toString(), this.decimals);
444
- }
445
- toString(base) {
446
- return super.toString(base);
447
- }
448
- // [customInspectSymbol](depth: any, inspectOptions: any, inspect: any) {
449
- // return this.toString();
450
- // }
451
- };
452
- import_bignumber.default.config({ DECIMAL_PLACES: 18 });
453
- Web3Number.config({ DECIMAL_PLACES: 18 });
442
+ var import_axios3 = __toESM(require("axios"));
454
443
 
455
444
  // src/interfaces/lending.ts
456
445
  var MarginType = /* @__PURE__ */ ((MarginType2) => {
@@ -494,7 +483,7 @@ var _ZkLend = class _ZkLend extends ILending {
494
483
  async init() {
495
484
  try {
496
485
  logger.verbose(`Initialising ${this.metadata.name}`);
497
- const result = await import_axios2.default.get(_ZkLend.POOLS_URL);
486
+ const result = await import_axios3.default.get(_ZkLend.POOLS_URL);
498
487
  const data = result.data;
499
488
  const savedTokens = await Global.getTokens();
500
489
  data.forEach((pool) => {
@@ -584,7 +573,7 @@ var _ZkLend = class _ZkLend extends ILending {
584
573
  */
585
574
  async getPositions(user) {
586
575
  const url = this.POSITION_URL.replace("{{USER_ADDR}}", user.address);
587
- const result = await import_axios2.default.get(url);
576
+ const result = await import_axios3.default.get(url);
588
577
  const data = result.data;
589
578
  const lendingPosition = [];
590
579
  logger.verbose(`${this.metadata.name}:: Positions: ${JSON.stringify(data)}`);
@@ -617,7 +606,7 @@ _ZkLend.POOLS_URL = "https://app.zklend.com/api/pools";
617
606
  var ZkLend = _ZkLend;
618
607
 
619
608
  // src/interfaces/common.ts
620
- var import_starknet2 = require("starknet");
609
+ var import_starknet3 = require("starknet");
621
610
  var Network = /* @__PURE__ */ ((Network2) => {
622
611
  Network2["mainnet"] = "mainnet";
623
612
  Network2["sepolia"] = "sepolia";
@@ -626,7 +615,7 @@ var Network = /* @__PURE__ */ ((Network2) => {
626
615
  })(Network || {});
627
616
  function getMainnetConfig(rpcUrl = "https://starknet-mainnet.public.blastapi.io", blockIdentifier = "pending") {
628
617
  return {
629
- provider: new import_starknet2.RpcProvider({
618
+ provider: new import_starknet3.RpcProvider({
630
619
  nodeUrl: rpcUrl,
631
620
  blockIdentifier
632
621
  }),
@@ -653,34 +642,6 @@ var Initializable = class {
653
642
  }
654
643
  };
655
644
 
656
- // src/dataTypes/address.ts
657
- var import_starknet3 = require("starknet");
658
- var ContractAddr = class _ContractAddr {
659
- constructor(address) {
660
- this.address = _ContractAddr.standardise(address);
661
- }
662
- static from(address) {
663
- return new _ContractAddr(address);
664
- }
665
- eq(other) {
666
- return this.address === other.address;
667
- }
668
- eqString(other) {
669
- return this.address === _ContractAddr.standardise(other);
670
- }
671
- static standardise(address) {
672
- let _a = address;
673
- if (!address) {
674
- _a = "0";
675
- }
676
- const a = import_starknet3.num.getHexString(import_starknet3.num.getDecimalString(_a.toString()));
677
- return a;
678
- }
679
- static eqString(a, b) {
680
- return _ContractAddr.standardise(a) === _ContractAddr.standardise(b);
681
- }
682
- };
683
-
684
645
  // src/strategies/autoCompounderStrk.ts
685
646
  var import_starknet4 = require("starknet");
686
647
  var AutoCompounderSTRK = class {
@@ -703,8 +664,9 @@ var AutoCompounderSTRK = class {
703
664
  this.init();
704
665
  }
705
666
  async init() {
706
- const cls = await this.config.provider.getClassAt(this.addr.address);
707
- this.contract = new import_starknet4.Contract(cls.abi, this.addr.address, this.config.provider);
667
+ const provider = this.config.provider;
668
+ const cls = await provider.getClassAt(this.addr.address);
669
+ this.contract = new import_starknet4.Contract(cls.abi, this.addr.address, provider);
708
670
  this.initialized = true;
709
671
  }
710
672
  async waitForInitilisation() {
@@ -947,8 +909,8 @@ var Store = class _Store {
947
909
  // src/node/pricer-redis.ts
948
910
  var import_redis = require("redis");
949
911
  var PricerRedis = class extends Pricer {
950
- constructor(config, tokens) {
951
- super(config, tokens);
912
+ constructor(config, tokens2) {
913
+ super(config, tokens2);
952
914
  this.redisClient = null;
953
915
  }
954
916
  /** Reads prices from Pricer._loadPrices and uses a callback to set prices in redis */