@curvefi/llamalend-api 1.0.32 → 1.0.34

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/README.md CHANGED
@@ -34,7 +34,7 @@ import { useState, useMemo } from 'react'
34
34
  import { providers } from 'ethers'
35
35
  import Onboard from 'bnc-onboard'
36
36
  import type { Wallet } from 'bnc-onboard/dist/src/interfaces'
37
- import llamalend from '@curvefi/lending-api'
37
+ import llamalend from '@curvefi/llamalend-api'
38
38
  ...
39
39
 
40
40
  const WalletProvider: FunctionComponent = ({ children }) => {
@@ -79,7 +79,7 @@ import { useState, useMemo, useEffect } from 'react'
79
79
  import { providers } from 'ethers'
80
80
  import Onboard from 'bnc-onboard'
81
81
  import type { Wallet } from 'bnc-onboard/dist/src/interfaces'
82
- import llamalend from '@curvefi/lending-api'
82
+ import llamalend from '@curvefi/llamalend-api'
83
83
 
84
84
  ...
85
85
 
@@ -0,0 +1,2 @@
1
+ import { IDict, INetworkName } from "./interfaces.js";
2
+ export declare const _getUsdPricesFromApi: (network: INetworkName) => Promise<IDict<number>>;
package/lib/cached.js ADDED
@@ -0,0 +1,75 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { createUsdPricesDict, uncached_getAllPoolsFromApi } from './external-api.js';
11
+ /**
12
+ * Memoizes a function that returns a promise.
13
+ * Custom function instead of `memoizee` because we want to be able to set the cache manually based on server data.
14
+ * @param fn The function that returns a promise and will be memoized
15
+ * @param maxAge The maximum age of the cache in milliseconds
16
+ * @param createKey A function that creates a key for the cache based on the arguments passed to the function
17
+ * @returns A memoized `fn` function that includes a `set` method to set the cache manually
18
+ */
19
+ const memoize = (fn, { maxAge, createKey = (list) => list.toString(), }) => {
20
+ const cache = {};
21
+ const timeouts = {};
22
+ const setCache = (key, promise) => {
23
+ if (promise) {
24
+ cache[key] = promise;
25
+ }
26
+ else if (key in cache) {
27
+ delete cache[key];
28
+ }
29
+ if (key in timeouts) {
30
+ clearTimeout(timeouts[key]);
31
+ delete timeouts[key];
32
+ }
33
+ };
34
+ const scheduleCleanup = (key) => timeouts[key] = setTimeout(() => {
35
+ delete timeouts[key];
36
+ delete cache[key];
37
+ }, maxAge);
38
+ const cachedFn = (...args) => __awaiter(void 0, void 0, void 0, function* () {
39
+ const key = createKey(args);
40
+ if (key in cache) {
41
+ return cache[key];
42
+ }
43
+ const promise = fn(...args);
44
+ setCache(key, promise);
45
+ try {
46
+ const result = yield promise;
47
+ scheduleCleanup(key);
48
+ return result;
49
+ }
50
+ catch (e) {
51
+ delete cache[key];
52
+ throw e;
53
+ }
54
+ });
55
+ cachedFn.set = (result, ...args) => {
56
+ const key = createKey(args);
57
+ setCache(key, Promise.resolve(result));
58
+ scheduleCleanup(key);
59
+ };
60
+ return cachedFn;
61
+ };
62
+ const createCache = (poolsDict) => {
63
+ const poolLists = Object.values(poolsDict);
64
+ const usdPrices = createUsdPricesDict(poolLists);
65
+ return { poolsDict, poolLists, usdPrices };
66
+ };
67
+ /**
68
+ * This function is used to cache the data fetched from the API and the data derived from it.
69
+ * Note: do not expose this function to the outside world, instead encapsulate it in a function that returns the data you need.
70
+ */
71
+ const _getCachedData = memoize((network) => __awaiter(void 0, void 0, void 0, function* () { return createCache(yield uncached_getAllPoolsFromApi(network)); }), { maxAge: 1000 * 60 * 5 /* 5 minutes */ });
72
+ export const _getUsdPricesFromApi = (network) => __awaiter(void 0, void 0, void 0, function* () {
73
+ const { usdPrices } = yield _getCachedData(network);
74
+ return usdPrices;
75
+ });
@@ -1,7 +1,8 @@
1
1
  import memoize from "memoizee";
2
2
  import type { Llamalend } from "./llamalend.js";
3
- import { IDict, IMarketData, INetworkName, IQuoteOdos } from "./interfaces";
4
- export declare function _getUsdPricesFromApi(this: Llamalend): Promise<IDict<number>>;
3
+ import { IDict, IExtendedPoolDataFromApi, IMarketData, INetworkName, IQuoteOdos, IPoolType } from "./interfaces";
4
+ export declare const uncached_getAllPoolsFromApi: (network: INetworkName) => Promise<Record<IPoolType, IExtendedPoolDataFromApi>>;
5
+ export declare const createUsdPricesDict: (allTypesExtendedPoolData: IExtendedPoolDataFromApi[]) => IDict<number>;
5
6
  type UserCollateral = {
6
7
  total_deposit_precise: string;
7
8
  total_deposit_from_user: number;
@@ -9,105 +9,87 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { ethers } from "ethers";
11
11
  import memoize from "memoizee";
12
- const _getPoolsFromApi = memoize((network, poolFactory) => __awaiter(void 0, void 0, void 0, function* () {
13
- const response = yield fetch(`https://api.curve.finance/api/getPools/${network}/${poolFactory}`);
14
- const { data } = yield response.json();
15
- return data !== null && data !== void 0 ? data : { poolData: [], tvl: 0, tvlAll: 0 };
16
- }), {
17
- promise: true,
18
- maxAge: 5 * 60 * 1000, // 5m
12
+ const uncached_getPoolsFromApi = (network, poolType) => __awaiter(void 0, void 0, void 0, function* () {
13
+ var _a;
14
+ const api = "https://api.curve.finance/api";
15
+ const url = `${api}/getPools/${network}/${poolType}`;
16
+ return (_a = yield fetchData(url)) !== null && _a !== void 0 ? _a : { poolData: [], tvl: 0, tvlAll: 0 };
19
17
  });
20
- const _getAllPoolsFromApi = (network) => __awaiter(void 0, void 0, void 0, function* () {
21
- return yield Promise.all([
22
- _getPoolsFromApi(network, "main"),
23
- _getPoolsFromApi(network, "crypto"),
24
- _getPoolsFromApi(network, "factory"),
25
- _getPoolsFromApi(network, "factory-crvusd"),
26
- _getPoolsFromApi(network, "factory-crypto"),
27
- _getPoolsFromApi(network, "factory-twocrypto"),
28
- _getPoolsFromApi(network, "factory-tricrypto"),
29
- _getPoolsFromApi(network, "factory-stable-ng"),
30
- ]);
18
+ const getPoolTypes = () => ["main", "crypto", "factory", "factory-crvusd", "factory-crypto", "factory-twocrypto", "factory-tricrypto", "factory-stable-ng"];
19
+ export const uncached_getAllPoolsFromApi = (network) => __awaiter(void 0, void 0, void 0, function* () {
20
+ return Object.fromEntries(yield Promise.all(getPoolTypes().map((poolType) => __awaiter(void 0, void 0, void 0, function* () {
21
+ const data = yield uncached_getPoolsFromApi(network, poolType);
22
+ return [poolType, data];
23
+ }))));
31
24
  });
32
- export function _getUsdPricesFromApi() {
33
- return __awaiter(this, void 0, void 0, function* () {
34
- var _a, _b;
35
- const network = this.constants.NETWORK_NAME;
36
- const allTypesExtendedPoolData = yield _getAllPoolsFromApi(network);
37
- const priceDict = {};
38
- const priceDictByMaxTvl = {};
39
- for (const extendedPoolData of allTypesExtendedPoolData) {
40
- for (const pool of extendedPoolData.poolData) {
41
- const lpTokenAddress = (_a = pool.lpTokenAddress) !== null && _a !== void 0 ? _a : pool.address;
42
- const totalSupply = pool.totalSupply / (Math.pow(10, 18));
43
- if (lpTokenAddress.toLowerCase() in priceDict) {
44
- priceDict[lpTokenAddress.toLowerCase()].push({
45
- price: pool.usdTotal && totalSupply ? pool.usdTotal / totalSupply : 0,
46
- tvl: pool.usdTotal,
47
- });
48
- }
49
- else {
50
- priceDict[lpTokenAddress.toLowerCase()] = [];
51
- priceDict[lpTokenAddress.toLowerCase()].push({
52
- price: pool.usdTotal && totalSupply ? pool.usdTotal / totalSupply : 0,
53
- tvl: pool.usdTotal,
54
- });
55
- }
56
- for (const coin of pool.coins) {
57
- if (typeof coin.usdPrice === "number") {
58
- if (coin.address.toLowerCase() in priceDict) {
59
- priceDict[coin.address.toLowerCase()].push({
60
- price: coin.usdPrice,
61
- tvl: pool.usdTotal,
62
- });
63
- }
64
- else {
65
- priceDict[coin.address.toLowerCase()] = [];
66
- priceDict[coin.address.toLowerCase()].push({
67
- price: coin.usdPrice,
68
- tvl: pool.usdTotal,
69
- });
70
- }
25
+ export const createUsdPricesDict = (allTypesExtendedPoolData) => {
26
+ var _a, _b;
27
+ const priceDict = {};
28
+ const priceDictByMaxTvl = {};
29
+ for (const extendedPoolData of allTypesExtendedPoolData) {
30
+ for (const pool of extendedPoolData.poolData) {
31
+ const lpTokenAddress = (_a = pool.lpTokenAddress) !== null && _a !== void 0 ? _a : pool.address;
32
+ const totalSupply = pool.totalSupply / (Math.pow(10, 18));
33
+ if (lpTokenAddress.toLowerCase() in priceDict) {
34
+ priceDict[lpTokenAddress.toLowerCase()].push({
35
+ price: pool.usdTotal && totalSupply ? pool.usdTotal / totalSupply : 0,
36
+ tvl: pool.usdTotal,
37
+ });
38
+ }
39
+ else {
40
+ priceDict[lpTokenAddress.toLowerCase()] = [];
41
+ priceDict[lpTokenAddress.toLowerCase()].push({
42
+ price: pool.usdTotal && totalSupply ? pool.usdTotal / totalSupply : 0,
43
+ tvl: pool.usdTotal,
44
+ });
45
+ }
46
+ for (const coin of pool.coins) {
47
+ if (typeof coin.usdPrice === "number") {
48
+ if (coin.address.toLowerCase() in priceDict) {
49
+ priceDict[coin.address.toLowerCase()].push({
50
+ price: coin.usdPrice,
51
+ tvl: pool.usdTotal,
52
+ });
71
53
  }
72
- }
73
- for (const coin of (_b = pool.gaugeRewards) !== null && _b !== void 0 ? _b : []) {
74
- if (typeof coin.tokenPrice === "number") {
75
- if (coin.tokenAddress.toLowerCase() in priceDict) {
76
- priceDict[coin.tokenAddress.toLowerCase()].push({
77
- price: coin.tokenPrice,
78
- tvl: pool.usdTotal,
79
- });
80
- }
81
- else {
82
- priceDict[coin.tokenAddress.toLowerCase()] = [];
83
- priceDict[coin.tokenAddress.toLowerCase()].push({
84
- price: coin.tokenPrice,
85
- tvl: pool.usdTotal,
86
- });
87
- }
54
+ else {
55
+ priceDict[coin.address.toLowerCase()] = [];
56
+ priceDict[coin.address.toLowerCase()].push({
57
+ price: coin.usdPrice,
58
+ tvl: pool.usdTotal,
59
+ });
88
60
  }
89
61
  }
90
62
  }
91
- }
92
- for (const address in priceDict) {
93
- if (priceDict[address].length > 0) {
94
- const maxTvlItem = priceDict[address].reduce((prev, current) => {
95
- if (+current.tvl > +prev.tvl) {
96
- return current;
63
+ for (const coin of (_b = pool.gaugeRewards) !== null && _b !== void 0 ? _b : []) {
64
+ if (typeof coin.tokenPrice === "number") {
65
+ if (coin.tokenAddress.toLowerCase() in priceDict) {
66
+ priceDict[coin.tokenAddress.toLowerCase()].push({
67
+ price: coin.tokenPrice,
68
+ tvl: pool.usdTotal,
69
+ });
97
70
  }
98
71
  else {
99
- return prev;
72
+ priceDict[coin.tokenAddress.toLowerCase()] = [];
73
+ priceDict[coin.tokenAddress.toLowerCase()].push({
74
+ price: coin.tokenPrice,
75
+ tvl: pool.usdTotal,
76
+ });
100
77
  }
101
- });
102
- priceDictByMaxTvl[address] = maxTvlItem.price;
103
- }
104
- else {
105
- priceDictByMaxTvl[address] = 0;
78
+ }
106
79
  }
107
80
  }
108
- return priceDictByMaxTvl;
109
- });
110
- }
81
+ }
82
+ for (const address in priceDict) {
83
+ if (priceDict[address].length) {
84
+ const maxTvlItem = priceDict[address].reduce((prev, current) => +current.tvl > +prev.tvl ? current : prev);
85
+ priceDictByMaxTvl[address] = maxTvlItem.price;
86
+ }
87
+ else {
88
+ priceDictByMaxTvl[address] = 0;
89
+ }
90
+ }
91
+ return priceDictByMaxTvl;
92
+ };
111
93
  export const _getUserCollateral = memoize((network, controller, user) => __awaiter(void 0, void 0, void 0, function* () {
112
94
  const url = `https://prices.curve.finance/v1/lending/collateral_events/${network}/${controller}/${user}`;
113
95
  const response = yield fetch(url);
@@ -199,3 +181,16 @@ export const _getHiddenPools = memoize(() => __awaiter(void 0, void 0, void 0, f
199
181
  promise: true,
200
182
  maxAge: 5 * 60 * 1000, // 5m
201
183
  });
184
+ function fetchJson(url) {
185
+ return __awaiter(this, void 0, void 0, function* () {
186
+ var _a;
187
+ const response = yield fetch(url);
188
+ return (_a = yield response.json()) !== null && _a !== void 0 ? _a : {};
189
+ });
190
+ }
191
+ function fetchData(url) {
192
+ return __awaiter(this, void 0, void 0, function* () {
193
+ const { data } = yield fetchJson(url);
194
+ return data;
195
+ });
196
+ }
@@ -6,6 +6,7 @@ export interface IDict<T> {
6
6
  export type INetworkName = "ethereum" | "optimism" | "bsc" | "xdai" | "polygon" | 'sonic' | "x-layer" | "fantom" | "fraxtal" | "zksync" | "moonbeam" | "kava" | "mantle" | "base" | "arbitrum" | "celo" | "avalanche" | "aurora";
7
7
  export type IChainId = 1 | 10 | 56 | 100 | 137 | 146 | 196 | 250 | 252 | 324 | 1284 | 2222 | 5000 | 8453 | 42161 | 42220 | 43114 | 1313161554;
8
8
  export type IPoolFactory = "main" | "crypto" | "factory" | "factory-crvusd" | "factory-crypto" | "factory-twocrypto" | "factory-tricrypto" | "factory-stable-ng";
9
+ export type IPoolType = "main" | "crypto" | IPoolFactory;
9
10
  export interface ICurveContract {
10
11
  contract: Contract;
11
12
  multicallContract: MulticallContract;
@@ -47,6 +47,7 @@ export declare class MintMarketTemplate {
47
47
  fee: string;
48
48
  admin_fee: string;
49
49
  rate: string;
50
+ future_rate: string;
50
51
  liquidation_discount: string;
51
52
  loan_discount: string;
52
53
  }>;
package/lib/utils.js CHANGED
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { ethers } from "ethers";
11
11
  import BigNumber from 'bignumber.js';
12
- import { _getUsdPricesFromApi } from "./external-api.js";
12
+ import { _getUsdPricesFromApi } from "./cached.js";
13
13
  import { L2Networks } from "./constants/L2Networks.js";
14
14
  import memoize from "memoizee";
15
15
  export const MAX_ALLOWANCE = BigInt("115792089237316195423570985008687907853269984665640564039457584007913129639935"); // 2**256 - 1
@@ -264,7 +264,7 @@ export const _getUsdRate = function (assetId) {
264
264
  var _a, _c;
265
265
  if (this.chainId === 1 && assetId.toLowerCase() === '0x8762db106b2c2a0bccb3a80d1ed41273552616e8')
266
266
  return 0; // RSR
267
- const pricesFromApi = yield _getUsdPricesFromApi.call(this);
267
+ const pricesFromApi = yield _getUsdPricesFromApi(this.constants.NETWORK_NAME);
268
268
  if (assetId.toLowerCase() in pricesFromApi)
269
269
  return pricesFromApi[assetId.toLowerCase()];
270
270
  if (assetId === 'USD' || (this.chainId === 137 && (assetId.toLowerCase() === this.constants.COINS.am3crv.toLowerCase())))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curvefi/llamalend-api",
3
- "version": "1.0.32",
3
+ "version": "1.0.34",
4
4
  "description": "JavaScript library for Curve Lending",
5
5
  "main": "lib/index.js",
6
6
  "author": "Macket",
@@ -8,10 +8,10 @@
8
8
  "private": false,
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "https://github.com/curvefi/curve-lending-js.git"
11
+ "url": "https://github.com/curvefi/curve-llamalend.js.git"
12
12
  },
13
13
  "bugs": {
14
- "url": "https://github.com/curvefi/curve-lending-js/issues"
14
+ "url": "https://github.com/curvefi/curve-llamalend.js/issues"
15
15
  },
16
16
  "scripts": {
17
17
  "build": "rm -rf lib && tsc --project tsconfig.build.json",
@@ -41,9 +41,9 @@
41
41
  "vue-eslint-parser": "^10.1.3"
42
42
  },
43
43
  "dependencies": {
44
- "@curvefi/ethcall": "6.0.15",
45
- "bignumber.js": "^9.3.0",
46
- "ethers": "^6.14.3",
47
- "memoizee": "^0.4.17"
44
+ "@curvefi/ethcall": "6.0.16",
45
+ "bignumber.js": "9.3.1",
46
+ "ethers": "6.15.0",
47
+ "memoizee": "0.4.17"
48
48
  }
49
49
  }
package/src/cached.ts ADDED
@@ -0,0 +1,82 @@
1
+ import {IDict, IExtendedPoolDataFromApi, INetworkName, IPoolType} from "./interfaces.js";
2
+ import {createUsdPricesDict, uncached_getAllPoolsFromApi} from './external-api.js'
3
+
4
+ /**
5
+ * Memoizes a function that returns a promise.
6
+ * Custom function instead of `memoizee` because we want to be able to set the cache manually based on server data.
7
+ * @param fn The function that returns a promise and will be memoized
8
+ * @param maxAge The maximum age of the cache in milliseconds
9
+ * @param createKey A function that creates a key for the cache based on the arguments passed to the function
10
+ * @returns A memoized `fn` function that includes a `set` method to set the cache manually
11
+ */
12
+ const memoize = <TResult, TParams extends any[], TFunc extends (...args: TParams) => Promise<TResult>>(fn: TFunc, {
13
+ maxAge,
14
+ createKey = (list) => list.toString(),
15
+ }: {
16
+ maxAge: number,
17
+ createKey?: (args: TParams) => string
18
+ }) => {
19
+ const cache: Record<string, Promise<TResult>> = {};
20
+ const timeouts: Record<string, ReturnType<typeof setTimeout>> = {};
21
+
22
+ const setCache = (key: string, promise?: Promise<TResult>) => {
23
+ if (promise) {
24
+ cache[key] = promise;
25
+ } else if (key in cache) {
26
+ delete cache[key];
27
+ }
28
+ if (key in timeouts) {
29
+ clearTimeout(timeouts[key]);
30
+ delete timeouts[key]
31
+ }
32
+ };
33
+
34
+ const scheduleCleanup = (key: string) => timeouts[key] = setTimeout(() => {
35
+ delete timeouts[key];
36
+ delete cache[key];
37
+ }, maxAge);
38
+
39
+ const cachedFn = async (...args: TParams): Promise<TResult> => {
40
+ const key = createKey(args);
41
+ if (key in cache) {
42
+ return cache[key];
43
+ }
44
+ const promise = fn(...args);
45
+ setCache(key, promise);
46
+ try {
47
+ const result = await promise;
48
+ scheduleCleanup(key)
49
+ return result;
50
+ } catch (e) {
51
+ delete cache[key];
52
+ throw e;
53
+ }
54
+ };
55
+
56
+ cachedFn.set = (result: TResult, ...args: TParams) => {
57
+ const key = createKey(args);
58
+ setCache(key, Promise.resolve(result));
59
+ scheduleCleanup(key);
60
+ }
61
+
62
+ return cachedFn as TFunc & { set: (result: TResult, ...args: TParams) => void };
63
+ }
64
+
65
+ const createCache = (poolsDict: Record<IPoolType, IExtendedPoolDataFromApi>) => {
66
+ const poolLists = Object.values(poolsDict)
67
+ const usdPrices = createUsdPricesDict(poolLists);
68
+ return {poolsDict, poolLists, usdPrices};
69
+ };
70
+
71
+ /**
72
+ * This function is used to cache the data fetched from the API and the data derived from it.
73
+ * Note: do not expose this function to the outside world, instead encapsulate it in a function that returns the data you need.
74
+ */
75
+ const _getCachedData = memoize(async (network: INetworkName) =>
76
+ createCache(await uncached_getAllPoolsFromApi(network)), {maxAge: 1000 * 60 * 5 /* 5 minutes */})
77
+
78
+ export const _getUsdPricesFromApi = async (network:INetworkName): Promise<IDict<number>> => {
79
+ const {usdPrices} = await _getCachedData(network);
80
+ return usdPrices
81
+ }
82
+
@@ -6,40 +6,27 @@ import {
6
6
  IExtendedPoolDataFromApi,
7
7
  IMarketData,
8
8
  INetworkName,
9
- IPoolFactory,
10
9
  IQuoteOdos,
11
10
  IResponseApi,
11
+ IPoolType,
12
12
  } from "./interfaces";
13
13
 
14
-
15
- const _getPoolsFromApi = memoize(
16
- async (network: INetworkName, poolFactory: IPoolFactory ): Promise<IExtendedPoolDataFromApi> => {
17
- const response = await fetch(`https://api.curve.finance/api/getPools/${network}/${poolFactory}`);
18
- const { data } = await response.json() as { data?: IExtendedPoolDataFromApi, success: boolean };
19
- return data ?? { poolData: [], tvl: 0, tvlAll: 0 };
20
- },
21
- {
22
- promise: true,
23
- maxAge: 5 * 60 * 1000, // 5m
24
- }
25
- )
26
-
27
- const _getAllPoolsFromApi = async (network: INetworkName): Promise<IExtendedPoolDataFromApi[]> => {
28
- return await Promise.all([
29
- _getPoolsFromApi(network, "main"),
30
- _getPoolsFromApi(network, "crypto"),
31
- _getPoolsFromApi(network, "factory"),
32
- _getPoolsFromApi(network, "factory-crvusd"),
33
- _getPoolsFromApi(network, "factory-crypto"),
34
- _getPoolsFromApi(network, "factory-twocrypto"),
35
- _getPoolsFromApi(network, "factory-tricrypto"),
36
- _getPoolsFromApi(network, "factory-stable-ng"),
37
- ]);
14
+ const uncached_getPoolsFromApi = async (network: INetworkName, poolType: IPoolType): Promise<IExtendedPoolDataFromApi> => {
15
+ const api = "https://api.curve.finance/api";
16
+ const url = `${api}/getPools/${network}/${poolType}`;
17
+ return await fetchData(url) ?? { poolData: [], tvl: 0, tvlAll: 0 };
38
18
  }
39
19
 
40
- export async function _getUsdPricesFromApi(this: Llamalend): Promise<IDict<number>> {
41
- const network = this.constants.NETWORK_NAME;
42
- const allTypesExtendedPoolData = await _getAllPoolsFromApi(network);
20
+ const getPoolTypes = () => ["main", "crypto", "factory", "factory-crvusd", "factory-crypto", "factory-twocrypto", "factory-tricrypto", "factory-stable-ng"] as const;
21
+ export const uncached_getAllPoolsFromApi = async (network: INetworkName): Promise<Record<IPoolType, IExtendedPoolDataFromApi>> =>
22
+ Object.fromEntries(
23
+ await Promise.all(getPoolTypes().map(async (poolType) => {
24
+ const data = await uncached_getPoolsFromApi(network, poolType);
25
+ return [poolType, data];
26
+ }))
27
+ )
28
+
29
+ export const createUsdPricesDict = (allTypesExtendedPoolData: IExtendedPoolDataFromApi[]): IDict<number> => {
43
30
  const priceDict: IDict<Record<string, number>[]> = {};
44
31
  const priceDictByMaxTvl: IDict<number> = {};
45
32
 
@@ -97,24 +84,18 @@ export async function _getUsdPricesFromApi(this: Llamalend): Promise<IDict<numbe
97
84
  }
98
85
 
99
86
  for(const address in priceDict) {
100
- if(priceDict[address].length > 0) {
101
- const maxTvlItem = priceDict[address].reduce((prev, current) => {
102
- if (+current.tvl > +prev.tvl) {
103
- return current;
104
- } else {
105
- return prev;
106
- }
107
- });
87
+ if (priceDict[address].length) {
88
+ const maxTvlItem = priceDict[address].reduce((prev, current) => +current.tvl > +prev.tvl ? current : prev);
108
89
  priceDictByMaxTvl[address] = maxTvlItem.price
109
90
  } else {
110
91
  priceDictByMaxTvl[address] = 0
111
92
  }
112
-
113
93
  }
114
94
 
115
95
  return priceDictByMaxTvl
116
96
  }
117
97
 
98
+
118
99
  type UserCollateral = { total_deposit_precise: string, total_deposit_from_user: number, total_deposit_usd_value: number , total_borrowed: number, total_deposit_from_user_precise: number, total_deposit_from_user_usd_value: number}
119
100
  export const _getUserCollateral = memoize(
120
101
  async (network: INetworkName, controller: string, user: string): Promise<UserCollateral> => {
@@ -232,3 +213,13 @@ export const _getHiddenPools = memoize(
232
213
  maxAge: 5 * 60 * 1000, // 5m
233
214
  }
234
215
  )
216
+
217
+ async function fetchJson(url: string): Promise<any> {
218
+ const response = await fetch(url);
219
+ return await response.json() ?? {};
220
+ }
221
+
222
+ async function fetchData(url: string) {
223
+ const {data} = await fetchJson(url);
224
+ return data;
225
+ }
package/src/interfaces.ts CHANGED
@@ -8,6 +8,8 @@ export interface IDict<T> {
8
8
  export type INetworkName = "ethereum" | "optimism" | "bsc" | "xdai" | "polygon" | 'sonic' | "x-layer" | "fantom" | "fraxtal" | "zksync" | "moonbeam" | "kava" | "mantle" | "base" | "arbitrum" | "celo" | "avalanche" | "aurora";
9
9
  export type IChainId = 1 | 10 | 56 | 100 | 137 | 146 | 196 | 250 | 252 | 324 | 1284 | 2222 | 5000 | 8453 | 42161 | 42220 | 43114 | 1313161554;
10
10
  export type IPoolFactory = "main" | "crypto" | "factory" | "factory-crvusd" | "factory-crypto" | "factory-twocrypto" | "factory-tricrypto" | "factory-stable-ng";
11
+ export type IPoolType = "main" | "crypto" | IPoolFactory;
12
+
11
13
  export interface ICurveContract {
12
14
  contract: Contract,
13
15
  multicallContract: MulticallContract,
@@ -71,6 +71,7 @@ export class MintMarketTemplate {
71
71
  fee: string, // %
72
72
  admin_fee: string, // %
73
73
  rate: string, // %
74
+ future_rate: string, // %
74
75
  liquidation_discount: string, // %
75
76
  loan_discount: string, // %
76
77
  }>,
package/src/utils.ts CHANGED
@@ -2,7 +2,7 @@ import { ethers, BigNumberish, Numeric } from "ethers";
2
2
  import { Call } from "@curvefi/ethcall";
3
3
  import BigNumber from 'bignumber.js';
4
4
  import { ICurveContract, IDict, TGas } from "./interfaces.js";
5
- import { _getUsdPricesFromApi } from "./external-api.js";
5
+ import { _getUsdPricesFromApi } from "./cached.js";
6
6
  import type { Llamalend } from "./llamalend.js";
7
7
  import { JsonFragment } from "ethers/lib.esm";
8
8
  import { L2Networks } from "./constants/L2Networks.js";
@@ -286,7 +286,7 @@ export const ensureAllowance = async function (this: Llamalend, coins: string[],
286
286
  const _usdRatesCache: IDict<{ rate: number, time: number }> = {}
287
287
  export const _getUsdRate = async function (this: Llamalend, assetId: string): Promise<number> {
288
288
  if (this.chainId === 1 && assetId.toLowerCase() === '0x8762db106b2c2a0bccb3a80d1ed41273552616e8') return 0; // RSR
289
- const pricesFromApi = await _getUsdPricesFromApi.call(this);
289
+ const pricesFromApi = await _getUsdPricesFromApi(this.constants.NETWORK_NAME);
290
290
  if (assetId.toLowerCase() in pricesFromApi) return pricesFromApi[assetId.toLowerCase()];
291
291
 
292
292
  if (assetId === 'USD' || (this.chainId === 137 && (assetId.toLowerCase() === this.constants.COINS.am3crv.toLowerCase()))) return 1