@curvefi/api 2.72.2 → 2.72.4

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
@@ -1986,6 +1986,28 @@ import curve from "@curvefi/api";
1986
1986
  })()
1987
1987
  ```
1988
1988
 
1989
+ ### Fetch a single pool by address from blockchain
1990
+
1991
+ `curve.fetchPoolByAddress` fetches one factory pool by its swap address using only RPC (no API).
1992
+ It auto-detects which factory the pool belongs to, so you don't need to know the pool type in
1993
+ advance, and merges the pool into the corresponding pool data. It returns the pool id (which can
1994
+ be passed to `curve.getPool`). If the pool is already loaded it returns its id without any RPC call,
1995
+ and it throws if the address doesn't belong to any known factory.
1996
+
1997
+ ```ts
1998
+ import curve from "@curvefi/api";
1999
+
2000
+ (async () => {
2001
+ await curve.init('JsonRpc', {}, { gasPrice: 0 });
2002
+
2003
+ const poolId = await curve.fetchPoolByAddress("0xffb7f90354c496210c471459133da2e452d8138a");
2004
+ // 0xffb7f90354c496210c471459133da2e452d8138a
2005
+
2006
+ const pool = curve.getPool(poolId);
2007
+ // pool.name === "SWAN/WETH"
2008
+ })()
2009
+ ```
2010
+
1989
2011
  ### Deploy stable plain pool
1990
2012
 
1991
2013
  ```ts
package/lib/curve.d.ts CHANGED
@@ -78,6 +78,10 @@ export declare class Curve implements ICurve {
78
78
  fetchRecentlyDeployedStableNgFactoryPool: (poolAddress: string) => Promise<string>;
79
79
  fetchRecentlyDeployedTwocryptoFactoryPool: (poolAddress: string) => Promise<string>;
80
80
  fetchRecentlyDeployedTricryptoFactoryPool: (poolAddress: string) => Promise<string>;
81
+ private _getRpcFactoryDescriptors;
82
+ private _detectPoolFactory;
83
+ private _findLoadedFactoryPoolId;
84
+ fetchPoolByAddress: (poolAddress: string) => Promise<string>;
81
85
  getMainPoolList: () => string[];
82
86
  getFactoryPoolList: () => string[];
83
87
  getCrvusdFactoryPoolList: () => string[];
package/lib/curve.js CHANGED
@@ -281,6 +281,54 @@ export class Curve {
281
281
  this._updateDecimalsAndGauges(this.constants.TRICRYPTO_FACTORY_POOLS_DATA);
282
282
  return Object.keys(poolData)[0]; // id
283
283
  });
284
+ this.fetchPoolByAddress = (poolAddress) => __awaiter(this, void 0, void 0, function* () {
285
+ if (this.isNoRPC)
286
+ throw Error("curve.fetchPoolByAddress requires an RPC connection");
287
+ const swapAddress = poolAddress.toLowerCase();
288
+ const loaded = this._findLoadedFactoryPoolId(swapAddress);
289
+ if (loaded)
290
+ return loaded;
291
+ const descriptor = yield this._detectPoolFactory(swapAddress);
292
+ if (!descriptor)
293
+ throw Error(`Pool ${poolAddress} does not belong to any known factory`);
294
+ let poolData;
295
+ switch (descriptor.kind) {
296
+ case "factory":
297
+ poolData = lowerCasePoolDataAddresses(yield getFactoryPoolData.call(this, 0, swapAddress, descriptor.factoryAddress, true));
298
+ this.constants.FACTORY_POOLS_DATA = Object.assign(Object.assign({}, this.constants.FACTORY_POOLS_DATA), poolData);
299
+ this._updateDecimalsAndGauges(this.constants.FACTORY_POOLS_DATA);
300
+ break;
301
+ case "factory-crvusd":
302
+ poolData = lowerCasePoolDataAddresses(yield getFactoryPoolData.call(this, 0, swapAddress, descriptor.factoryAddress, true));
303
+ this.constants.CRVUSD_FACTORY_POOLS_DATA = Object.assign(Object.assign({}, this.constants.CRVUSD_FACTORY_POOLS_DATA), poolData);
304
+ this._updateDecimalsAndGauges(this.constants.CRVUSD_FACTORY_POOLS_DATA);
305
+ break;
306
+ case "factory-stable-ng":
307
+ poolData = lowerCasePoolDataAddresses(yield getFactoryPoolData.call(this, 0, swapAddress, descriptor.factoryAddress, true));
308
+ this.constants.STABLE_NG_FACTORY_POOLS_DATA = Object.assign(Object.assign({}, this.constants.STABLE_NG_FACTORY_POOLS_DATA), poolData);
309
+ this._updateDecimalsAndGauges(this.constants.STABLE_NG_FACTORY_POOLS_DATA);
310
+ break;
311
+ case "factory-crypto":
312
+ poolData = lowerCasePoolDataAddresses(yield getCryptoFactoryPoolData.call(this, 0, swapAddress, true));
313
+ this.constants.CRYPTO_FACTORY_POOLS_DATA = Object.assign(Object.assign({}, this.constants.CRYPTO_FACTORY_POOLS_DATA), poolData);
314
+ this._updateDecimalsAndGauges(this.constants.CRYPTO_FACTORY_POOLS_DATA);
315
+ break;
316
+ case "factory-twocrypto":
317
+ poolData = lowerCasePoolDataAddresses(yield getTwocryptoFactoryPoolData.call(this, 0, swapAddress, true));
318
+ this.constants.TWOCRYPTO_FACTORY_POOLS_DATA = Object.assign(Object.assign({}, this.constants.TWOCRYPTO_FACTORY_POOLS_DATA), poolData);
319
+ this._updateDecimalsAndGauges(this.constants.TWOCRYPTO_FACTORY_POOLS_DATA);
320
+ break;
321
+ case "factory-tricrypto":
322
+ poolData = lowerCasePoolDataAddresses(yield getTricryptoFactoryPoolData.call(this, 0, swapAddress, true));
323
+ this.constants.TRICRYPTO_FACTORY_POOLS_DATA = Object.assign(Object.assign({}, this.constants.TRICRYPTO_FACTORY_POOLS_DATA), poolData);
324
+ this._updateDecimalsAndGauges(this.constants.TRICRYPTO_FACTORY_POOLS_DATA);
325
+ break;
326
+ }
327
+ const id = Object.keys(poolData)[0];
328
+ if (!id)
329
+ throw Error(`Pool ${poolAddress} could not be loaded (unsupported implementation)`);
330
+ return id;
331
+ });
284
332
  this.getMainPoolList = () => Object.keys(this.constants.POOLS_DATA);
285
333
  this.getFactoryPoolList = () => Object.keys(this.constants.FACTORY_POOLS_DATA);
286
334
  this.getCrvusdFactoryPoolList = () => Object.keys(this.constants.CRVUSD_FACTORY_POOLS_DATA);
@@ -673,6 +721,54 @@ export class Curve {
673
721
  this.constants.DECIMALS = Object.assign(Object.assign({}, this.constants.DECIMALS), extractDecimals(pools));
674
722
  this.constants.GAUGES = [...this.constants.GAUGES, ...extractGauges.call(this, pools)];
675
723
  }
724
+ _getRpcFactoryDescriptors() {
725
+ const aliases = this.constants.ALIASES;
726
+ const descriptors = [
727
+ { kind: "factory-stable-ng", alias: "stable_ng_factory" },
728
+ { kind: "factory", alias: "factory" },
729
+ { kind: "factory-crvusd", alias: "crvusd_factory" },
730
+ { kind: "factory-crypto", alias: "crypto_factory" },
731
+ { kind: "factory-twocrypto", alias: "twocrypto_factory" },
732
+ { kind: "factory-tricrypto", alias: "tricrypto_factory" },
733
+ ];
734
+ return descriptors
735
+ .filter((d) => (d.alias in aliases) && aliases[d.alias] !== this.constants.ZERO_ADDRESS)
736
+ .map((d) => ({ kind: d.kind, factoryAddress: aliases[d.alias] }));
737
+ }
738
+ _detectPoolFactory(poolAddress) {
739
+ return __awaiter(this, void 0, void 0, function* () {
740
+ var _a;
741
+ const descriptors = this._getRpcFactoryDescriptors();
742
+ const matches = yield Promise.all(descriptors.map((d) => __awaiter(this, void 0, void 0, function* () {
743
+ var _a;
744
+ const contract = (_a = this.contracts[d.factoryAddress]) === null || _a === void 0 ? void 0 : _a.contract;
745
+ if (!contract)
746
+ return null;
747
+ try {
748
+ const coins = yield contract.get_coins(poolAddress, this.constantOptions);
749
+ return coins.some((c) => c !== this.constants.ZERO_ADDRESS) ? d : null;
750
+ }
751
+ catch (_b) {
752
+ return null;
753
+ }
754
+ })));
755
+ return (_a = matches.find(Boolean)) !== null && _a !== void 0 ? _a : null;
756
+ });
757
+ }
758
+ _findLoadedFactoryPoolId(swapAddress) {
759
+ const dicts = [
760
+ this.constants.FACTORY_POOLS_DATA,
761
+ this.constants.CRVUSD_FACTORY_POOLS_DATA,
762
+ this.constants.STABLE_NG_FACTORY_POOLS_DATA,
763
+ this.constants.CRYPTO_FACTORY_POOLS_DATA,
764
+ this.constants.TWOCRYPTO_FACTORY_POOLS_DATA,
765
+ this.constants.TRICRYPTO_FACTORY_POOLS_DATA,
766
+ ];
767
+ for (const dict of dicts)
768
+ if (swapAddress in dict)
769
+ return swapAddress;
770
+ return null;
771
+ }
676
772
  setCustomFeeData(customFeeData) {
677
773
  this.feeData = Object.assign(Object.assign({}, this.feeData), customFeeData);
678
774
  }
@@ -1,2 +1,2 @@
1
1
  import { ICurve, IDict, IPoolData } from "../interfaces";
2
- export declare function getCryptoFactoryPoolData(this: ICurve, fromIdx?: number, swapAddress?: string): Promise<IDict<IPoolData>>;
2
+ export declare function getCryptoFactoryPoolData(this: ICurve, fromIdx?: number, swapAddress?: string, skipRecentlyCreatedCheck?: boolean): Promise<IDict<IPoolData>>;
@@ -193,10 +193,10 @@ function getCoinsData(tokenAddresses, coinAddresses, existingCoinAddrNameDict, e
193
193
  });
194
194
  }
195
195
  export function getCryptoFactoryPoolData() {
196
- return __awaiter(this, arguments, void 0, function* (fromIdx = 0, swapAddress) {
196
+ return __awaiter(this, arguments, void 0, function* (fromIdx = 0, swapAddress, skipRecentlyCreatedCheck = false) {
197
197
  var _a, _b;
198
198
  const [poolIds, swapAddresses] = swapAddress ?
199
- [[yield getRecentlyCreatedCryptoPoolId.call(this, swapAddress)], [swapAddress.toLowerCase()]]
199
+ [[skipRecentlyCreatedCheck ? swapAddress.toLowerCase() : yield getRecentlyCreatedCryptoPoolId.call(this, swapAddress)], [swapAddress.toLowerCase()]]
200
200
  : yield getCryptoFactoryIdsAndSwapAddresses.call(this, fromIdx);
201
201
  if (poolIds.length === 0)
202
202
  return {};
@@ -1,2 +1,2 @@
1
1
  import { ICurve, IDict, IPoolData } from "../interfaces";
2
- export declare function getTricryptoFactoryPoolData(this: ICurve, fromIdx?: number, swapAddress?: string): Promise<IDict<IPoolData>>;
2
+ export declare function getTricryptoFactoryPoolData(this: ICurve, fromIdx?: number, swapAddress?: string, skipRecentlyCreatedCheck?: boolean): Promise<IDict<IPoolData>>;
@@ -162,10 +162,10 @@ function getCoinsData(tokenAddresses, coinAddresses, existingCoinAddrNameDict, e
162
162
  });
163
163
  }
164
164
  export function getTricryptoFactoryPoolData() {
165
- return __awaiter(this, arguments, void 0, function* (fromIdx = 0, swapAddress) {
165
+ return __awaiter(this, arguments, void 0, function* (fromIdx = 0, swapAddress, skipRecentlyCreatedCheck = false) {
166
166
  var _a;
167
167
  const [poolIds, swapAddresses] = swapAddress ?
168
- [[yield getRecentlyCreatedCryptoPoolId.call(this, swapAddress)], [swapAddress.toLowerCase()]]
168
+ [[skipRecentlyCreatedCheck ? swapAddress.toLowerCase() : yield getRecentlyCreatedCryptoPoolId.call(this, swapAddress)], [swapAddress.toLowerCase()]]
169
169
  : yield getCryptoFactoryIdsAndSwapAddresses.call(this, fromIdx);
170
170
  if (poolIds.length === 0)
171
171
  return {};
@@ -1,2 +1,2 @@
1
1
  import { ICurve, IDict, IPoolData } from "../interfaces";
2
- export declare function getTwocryptoFactoryPoolData(this: ICurve, fromIdx?: number, swapAddress?: string): Promise<IDict<IPoolData>>;
2
+ export declare function getTwocryptoFactoryPoolData(this: ICurve, fromIdx?: number, swapAddress?: string, skipRecentlyCreatedCheck?: boolean): Promise<IDict<IPoolData>>;
@@ -168,9 +168,9 @@ function getCoinsData(tokenAddresses, coinAddresses, existingCoinAddrNameDict, e
168
168
  });
169
169
  }
170
170
  export function getTwocryptoFactoryPoolData() {
171
- return __awaiter(this, arguments, void 0, function* (fromIdx = 0, swapAddress) {
171
+ return __awaiter(this, arguments, void 0, function* (fromIdx = 0, swapAddress, skipRecentlyCreatedCheck = false) {
172
172
  const [poolIds, swapAddresses] = swapAddress ?
173
- [[yield getRecentlyCreatedCryptoPoolId.call(this, swapAddress)], [swapAddress.toLowerCase()]]
173
+ [[skipRecentlyCreatedCheck ? swapAddress.toLowerCase() : yield getRecentlyCreatedCryptoPoolId.call(this, swapAddress)], [swapAddress.toLowerCase()]]
174
174
  : yield getTwocryptoFactoryIdsAndSwapAddresses.call(this, fromIdx);
175
175
  if (poolIds.length === 0)
176
176
  return {};
@@ -7,4 +7,4 @@ export declare function getBasePools(this: Curve, factoryAddress: string, rawSwa
7
7
  ids: string[];
8
8
  addresses: string[];
9
9
  }>;
10
- export declare function getFactoryPoolData(this: Curve, fromIdx?: number, swapAddress?: string, factoryAddress?: string): Promise<IDict<IPoolData>>;
10
+ export declare function getFactoryPoolData(this: Curve, fromIdx?: number, swapAddress?: string, factoryAddress?: string, skipRecentlyCreatedCheck?: boolean): Promise<IDict<IPoolData>>;
@@ -224,10 +224,10 @@ function getCoinsData(coinAddresses, existingCoinAddrNameDict, existingCoinAddrD
224
224
  });
225
225
  }
226
226
  export function getFactoryPoolData() {
227
- return __awaiter(this, arguments, void 0, function* (fromIdx = 0, swapAddress, factoryAddress = this.constants.ALIASES.factory) {
227
+ return __awaiter(this, arguments, void 0, function* (fromIdx = 0, swapAddress, factoryAddress = this.constants.ALIASES.factory, skipRecentlyCreatedCheck = false) {
228
228
  var _a, _b, _c, _e;
229
229
  const [rawPoolIds, rawSwapAddresses] = swapAddress ?
230
- [[yield getRecentlyCreatedPoolId.call(this, swapAddress, factoryAddress)], [swapAddress.toLowerCase()]]
230
+ [[skipRecentlyCreatedCheck ? swapAddress.toLowerCase() : yield getRecentlyCreatedPoolId.call(this, swapAddress, factoryAddress)], [swapAddress.toLowerCase()]]
231
231
  : yield getFactoryIdsAndSwapAddresses.call(this, fromIdx, factoryAddress);
232
232
  if (rawPoolIds.length === 0)
233
233
  return {};
package/lib/index.d.ts CHANGED
@@ -75,6 +75,7 @@ export declare const createCurve: () => {
75
75
  getNetworkConstants: () => import("./interfaces.js").INetworkConstants;
76
76
  getIsLiteChain: () => boolean;
77
77
  isNoRPC: boolean;
78
+ fetchPoolByAddress: (poolAddress: string) => Promise<string>;
78
79
  factory: {
79
80
  fetchPools: (useApi?: boolean, isFiltered?: boolean) => Promise<void>;
80
81
  fetchNewPools: () => Promise<string[]>;
@@ -414,6 +415,7 @@ declare const _default: {
414
415
  getNetworkConstants: () => import("./interfaces.js").INetworkConstants;
415
416
  getIsLiteChain: () => boolean;
416
417
  isNoRPC: boolean;
418
+ fetchPoolByAddress: (poolAddress: string) => Promise<string>;
417
419
  factory: {
418
420
  fetchPools: (useApi?: boolean, isFiltered?: boolean) => Promise<void>;
419
421
  fetchNewPools: () => Promise<string[]>;
package/lib/index.js CHANGED
@@ -67,6 +67,7 @@ export const createCurve = () => {
67
67
  getNetworkConstants: _curve.getNetworkConstants.bind(_curve),
68
68
  getIsLiteChain: _curve.getIsLiteChain.bind(_curve),
69
69
  isNoRPC: _curve.isNoRPC,
70
+ fetchPoolByAddress: _curve.fetchPoolByAddress.bind(_curve),
70
71
  factory: {
71
72
  fetchPools: _curve.fetchFactoryPools.bind(_curve),
72
73
  fetchNewPools: _curve.fetchNewFactoryPools.bind(_curve),
@@ -16,6 +16,7 @@ export interface IPricesGauge {
16
16
  gauge_weight: string;
17
17
  gauge_relative_weight: number;
18
18
  gauge_type: string;
19
+ creation_date: string;
19
20
  }
20
21
  export declare const getGaugesOverview: () => Promise<IPricesGauge[]>;
21
22
  export declare const getPoolsFromPricesApi: (network: INetworkName, poolType: IPoolType) => Promise<IExtendedPoolDataFromApi>;
package/lib/prices-api.js CHANGED
@@ -45,15 +45,21 @@ const _getGaugesOverview = memoize(() => __awaiter(void 0, void 0, void 0, funct
45
45
  maxAge: 5 * 60 * 1000,
46
46
  });
47
47
  const getGaugeAddressByPoolAddress = (network) => __awaiter(void 0, void 0, void 0, function* () {
48
- var _a, _b;
48
+ var _a;
49
49
  const { gauges } = yield _getGaugesOverview();
50
- const map = new Map();
50
+ const newestGaugeByPoolAddress = new Map();
51
51
  for (const gauge of gauges !== null && gauges !== void 0 ? gauges : []) {
52
- if (((_a = gauge.pool) === null || _a === void 0 ? void 0 : _a.chain) !== network || gauge.gauge_type !== "Liquidity")
52
+ // LMCallback gauges reward LlamaLend borrowers who use this pool's LP token as collateral.
53
+ // LPs can't stake in them, so they must not replace the pool's real gauge.
54
+ if (((_a = gauge.pool) === null || _a === void 0 ? void 0 : _a.chain) !== network || gauge.gauge_type === "LMCallback")
53
55
  continue;
54
- map.set(gauge.pool.address.toLowerCase(), ((_b = gauge.effective_address) !== null && _b !== void 0 ? _b : gauge.address).toLowerCase());
56
+ const poolAddress = gauge.pool.address.toLowerCase();
57
+ const current = newestGaugeByPoolAddress.get(poolAddress);
58
+ // A pool can have several gauges when one was redeployed, keep the newest instead of relying on API order.
59
+ if (!current || gauge.creation_date > current.creation_date)
60
+ newestGaugeByPoolAddress.set(poolAddress, gauge);
55
61
  }
56
- return map;
62
+ return new Map(Array.from(newestGaugeByPoolAddress, ([poolAddress, gauge]) => { var _a; return [poolAddress, ((_a = gauge.effective_address) !== null && _a !== void 0 ? _a : gauge.address).toLowerCase()]; }));
57
63
  });
58
64
  export const getGaugesOverview = () => __awaiter(void 0, void 0, void 0, function* () {
59
65
  const { gauges } = yield _getGaugesOverview();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curvefi/api",
3
- "version": "2.72.2",
3
+ "version": "2.72.4",
4
4
  "description": "JavaScript library for curve.finance",
5
5
  "main": "lib/index.js",
6
6
  "author": "Macket",