@curvefi/api 2.72.4 → 2.72.6

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
@@ -24,7 +24,10 @@ import curve from "@curvefi/api";
24
24
 
25
25
  // 4. Without RPC
26
26
  await curve.init('NoRPC', {chainId: 1, networkName: 'ETHEREUM'});
27
-
27
+
28
+ // 5. API-only metadata (RPC stays live for quotes/routing)
29
+ await curve.init('JsonRpc', { url: <RPC_URL> }, { chainId: 1, apiOnlyMetadata: true });
30
+
28
31
  // Fetch factory pools
29
32
  await curve.factory.fetchPools();
30
33
  await curve.crvUSDFactory.fetchPools();
@@ -38,6 +41,10 @@ import curve from "@curvefi/api";
38
41
 
39
42
  **Note 2.** Web3 init requires the address. Therefore, it can be initialized only after receiving the address.
40
43
 
44
+ **Note 3.** ```apiOnlyMetadata``` (default ```false```) makes the library source pool metadata and TVL **exclusively from the HTTP APIs**, with no on-chain reads during `fetchPools` or route-graph building. Unlike `NoRPC`, the RPC provider stays live and is still used for user-facing quotes/routing — this is intended for backends that want to avoid hammering RPC nodes (e.g. rate-limited public endpoints) while initializing and listing pools. Two effects to be aware of:
45
+ - Factory gauge implementations are not read on-chain (`gaugeImplementation()` returns the zero address).
46
+ - Pools with no TVL in the API — including LLAMMAs, whose TVL is on-chain-only — are treated as 0 liquidity and therefore **excluded from the route graph**, instead of falling back to on-chain liquidity reads.
47
+
41
48
  **Wrong ❌️**
42
49
  ```tsx
43
50
  import type { FunctionComponent } from 'react'
package/lib/curve.d.ts CHANGED
@@ -12,6 +12,7 @@ export type ContractItem = {
12
12
  export declare class Curve implements ICurve {
13
13
  provider: ethers.BrowserProvider | ethers.JsonRpcProvider;
14
14
  isNoRPC: boolean;
15
+ apiOnlyMetadata: boolean;
15
16
  multicallProvider: MulticallProvider;
16
17
  signer: ethers.Signer | null;
17
18
  signerAddress: string;
@@ -56,6 +57,7 @@ export declare class Curve implements ICurve {
56
57
  gasStrategy?: IGasStrategy;
57
58
  chainId?: number;
58
59
  poolsData?: Record<IPoolType, IExtendedPoolDataFromApi>;
60
+ apiOnlyMetadata?: boolean;
59
61
  }): Promise<void>;
60
62
  initContract: (address: string, abi: any, provider: BrowserProvider | JsonRpcProvider | Signer) => Contract;
61
63
  initMulticallContract: (address: string, abi: any) => MulticallContract;
package/lib/curve.js CHANGED
@@ -97,7 +97,7 @@ export class Curve {
97
97
  }
98
98
  this.constants.FACTORY_POOLS_DATA = yield this._filterHiddenPools(this.constants.FACTORY_POOLS_DATA, isFiltered);
99
99
  this._updateDecimalsAndGauges(this.constants.FACTORY_POOLS_DATA);
100
- this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory"] = this.isNoRPC ? null : yield this.contracts[this.constants.ALIASES.factory].contract.gauge_implementation(this.constantOptions);
100
+ this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory"] = (this.isNoRPC || this.apiOnlyMetadata) ? null : yield this.contracts[this.constants.ALIASES.factory].contract.gauge_implementation(this.constantOptions);
101
101
  });
102
102
  this.fetchCrvusdFactoryPools = (...args_1) => __awaiter(this, [...args_1], void 0, function* (useApi = true, isFiltered = false) {
103
103
  if (!("crvusd_factory" in this.constants.ALIASES))
@@ -128,7 +128,7 @@ export class Curve {
128
128
  }
129
129
  this.constants.CRYPTO_FACTORY_POOLS_DATA = yield this._filterHiddenPools(this.constants.CRYPTO_FACTORY_POOLS_DATA, isFiltered);
130
130
  this._updateDecimalsAndGauges(this.constants.CRYPTO_FACTORY_POOLS_DATA);
131
- this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-crypto"] = this.isNoRPC ? null : yield this.contracts[this.constants.ALIASES.crypto_factory].contract.gauge_implementation(this.constantOptions);
131
+ this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-crypto"] = (this.isNoRPC || this.apiOnlyMetadata) ? null : yield this.contracts[this.constants.ALIASES.crypto_factory].contract.gauge_implementation(this.constantOptions);
132
132
  });
133
133
  this.fetchStableNgFactoryPools = (...args_1) => __awaiter(this, [...args_1], void 0, function* (useApi = true, isFiltered = false) {
134
134
  if (!("stable_ng_factory" in this.constants.ALIASES))
@@ -160,11 +160,11 @@ export class Curve {
160
160
  this.constants.TWOCRYPTO_FACTORY_POOLS_DATA = yield this._filterHiddenPools(this.constants.TWOCRYPTO_FACTORY_POOLS_DATA, isFiltered);
161
161
  this._updateDecimalsAndGauges(this.constants.TWOCRYPTO_FACTORY_POOLS_DATA);
162
162
  if (this.chainId === 1) {
163
- this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-twocrypto"] = this.isNoRPC ? null :
163
+ this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-twocrypto"] = (this.isNoRPC || this.apiOnlyMetadata) ? null :
164
164
  yield this.contracts[this.constants.ALIASES.twocrypto_factory].contract.gauge_implementation(this.constantOptions);
165
165
  }
166
166
  else {
167
- this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-twocrypto"] = this.isNoRPC ? null :
167
+ this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-twocrypto"] = (this.isNoRPC || this.apiOnlyMetadata) ? null :
168
168
  yield this.contracts[this.constants.ALIASES.child_gauge_factory].contract.get_implementation(this.constantOptions);
169
169
  }
170
170
  });
@@ -183,11 +183,11 @@ export class Curve {
183
183
  this.constants.TRICRYPTO_FACTORY_POOLS_DATA = yield this._filterHiddenPools(this.constants.TRICRYPTO_FACTORY_POOLS_DATA, isFiltered);
184
184
  this._updateDecimalsAndGauges(this.constants.TRICRYPTO_FACTORY_POOLS_DATA);
185
185
  if (this.chainId === 1) {
186
- this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-tricrypto"] = this.isNoRPC ? null :
186
+ this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-tricrypto"] = (this.isNoRPC || this.apiOnlyMetadata) ? null :
187
187
  yield this.contracts[this.constants.ALIASES.tricrypto_factory].contract.gauge_implementation(this.constantOptions);
188
188
  }
189
189
  else {
190
- this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-tricrypto"] = this.isNoRPC ? null :
190
+ this.constants.FACTORY_GAUGE_IMPLEMENTATIONS["factory-tricrypto"] = (this.isNoRPC || this.apiOnlyMetadata) ? null :
191
191
  yield this.contracts[this.constants.ALIASES.child_gauge_factory].contract.get_implementation(this.constantOptions);
192
192
  }
193
193
  });
@@ -364,6 +364,7 @@ export class Curve {
364
364
  this.provider = null;
365
365
  this.signer = null;
366
366
  this.isNoRPC = false;
367
+ this.apiOnlyMetadata = false;
367
368
  this.signerAddress = '';
368
369
  this.chainId = 1;
369
370
  this.isLiteChain = false;
@@ -402,16 +403,17 @@ export class Curve {
402
403
  init(providerType_1, providerSettings_1) {
403
404
  return __awaiter(this, arguments, void 0, function* (providerType, providerSettings, options = {} // gasPrice in Gwei
404
405
  ) {
405
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
406
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
406
407
  this.provider = null;
407
408
  this.signer = null;
408
409
  this.isNoRPC = false;
410
+ this.apiOnlyMetadata = (_a = options.apiOnlyMetadata) !== null && _a !== void 0 ? _a : false;
409
411
  this.signerAddress = '';
410
412
  this.chainId = 1;
411
413
  this.multicallProvider = null;
412
414
  this.contracts = {};
413
415
  this.feeData = {};
414
- this.gasStrategy = (_a = options.gasStrategy) !== null && _a !== void 0 ? _a : 'standard';
416
+ this.gasStrategy = (_b = options.gasStrategy) !== null && _b !== void 0 ? _b : 'standard';
415
417
  this.constantOptions = { gasLimit: 12000000 };
416
418
  this.options = {};
417
419
  this.nativeTokenAddress = NETWORK_CONSTANTS[1].NATIVE_COIN.address;
@@ -459,7 +461,7 @@ export class Curve {
459
461
  if (providerSettings.privateKey) {
460
462
  signerPromise = Promise.resolve(new ethers.Wallet(providerSettings.privateKey, this.provider));
461
463
  }
462
- else if (!((_b = providerSettings.url) === null || _b === void 0 ? void 0 : _b.startsWith("https://rpc.gnosischain.com"))) {
464
+ else if (!((_c = providerSettings.url) === null || _c === void 0 ? void 0 : _c.startsWith("https://rpc.gnosischain.com"))) {
463
465
  signerPromise = this.provider.getSigner().catch(() => null);
464
466
  }
465
467
  // Web3 provider
@@ -506,11 +508,11 @@ export class Curve {
506
508
  this.constants.ALIASES = network_constants.ALIASES;
507
509
  this.constants.ALIASES.anycall = "0x37414a8662bc1d25be3ee51fb27c2686e2490a89";
508
510
  this.constants.ALIASES.voting_escrow_oracle = "0x12F407340697Ae0b177546E535b91A5be021fBF9";
509
- this.constants.POOLS_DATA = (_c = network_constants.POOLS_DATA) !== null && _c !== void 0 ? _c : {};
510
- this.constants.LLAMMAS_DATA = (_d = network_constants.LLAMMAS_DATA) !== null && _d !== void 0 ? _d : {};
511
+ this.constants.POOLS_DATA = (_d = network_constants.POOLS_DATA) !== null && _d !== void 0 ? _d : {};
512
+ this.constants.LLAMMAS_DATA = (_e = network_constants.LLAMMAS_DATA) !== null && _e !== void 0 ? _e : {};
511
513
  for (const poolId in this.constants.POOLS_DATA)
512
514
  this.constants.POOLS_DATA[poolId].in_api = true;
513
- this.constants.COINS = (_e = network_constants.COINS) !== null && _e !== void 0 ? _e : {};
515
+ this.constants.COINS = (_f = network_constants.COINS) !== null && _f !== void 0 ? _f : {};
514
516
  this.constants.DECIMALS = extractDecimals(Object.assign(Object.assign({}, this.constants.POOLS_DATA), this.constants.LLAMMAS_DATA));
515
517
  this.constants.DECIMALS[this.constants.NATIVE_TOKEN.address] = 18;
516
518
  this.constants.DECIMALS[this.constants.NATIVE_TOKEN.wrappedAddress] = 18;
@@ -519,18 +521,18 @@ export class Curve {
519
521
  this.constants.API_CONSTANTS = network_constants.API_CONSTANTS;
520
522
  }
521
523
  const [cTokens, yTokens, ycTokens, aTokens] = [
522
- (_f = network_constants.cTokens) !== null && _f !== void 0 ? _f : [],
523
- (_g = network_constants.yTokens) !== null && _g !== void 0 ? _g : [],
524
- (_h = network_constants.ycTokens) !== null && _h !== void 0 ? _h : [],
525
- (_j = network_constants.aTokens) !== null && _j !== void 0 ? _j : [],
524
+ (_g = network_constants.cTokens) !== null && _g !== void 0 ? _g : [],
525
+ (_h = network_constants.yTokens) !== null && _h !== void 0 ? _h : [],
526
+ (_j = network_constants.ycTokens) !== null && _j !== void 0 ? _j : [],
527
+ (_k = network_constants.aTokens) !== null && _k !== void 0 ? _k : [],
526
528
  ];
527
529
  const customAbiTokens = [...cTokens, ...yTokens, ...ycTokens, ...aTokens];
528
530
  if (this.isLiteChain) {
529
531
  this.constants.STABLE_FACTORY_CONSTANTS.stableNgBasePoolZap = network_constants.stableNgBasePoolZap;
530
532
  }
531
533
  else {
532
- this.constants.STABLE_FACTORY_CONSTANTS = (_k = STABLE_FACTORY_CONSTANTS[this.chainId]) !== null && _k !== void 0 ? _k : {};
533
- this.constants.CRYPTO_FACTORY_CONSTANTS = (_l = CRYPTO_FACTORY_CONSTANTS[this.chainId]) !== null && _l !== void 0 ? _l : {};
534
+ this.constants.STABLE_FACTORY_CONSTANTS = (_l = STABLE_FACTORY_CONSTANTS[this.chainId]) !== null && _l !== void 0 ? _l : {};
535
+ this.constants.CRYPTO_FACTORY_CONSTANTS = (_m = CRYPTO_FACTORY_CONSTANTS[this.chainId]) !== null && _m !== void 0 ? _m : {};
534
536
  }
535
537
  if (this.chainId === 5000) {
536
538
  this.constantOptions = {};
@@ -228,9 +228,15 @@ export function buildFactoryPoolsData(factoryType, rawPoolListInput) {
228
228
  }
229
229
  else if (pool.isMetaPool) {
230
230
  const allPoolsData = Object.assign(Object.assign({}, this.getPoolsData()), FACTORY_POOLS_DATA);
231
+ if (!pool.basePoolAddress) {
232
+ console.warn(`Skipping meta pool ${pool.id} (${pool.address}): base pool address is missing in API data.`);
233
+ return;
234
+ }
231
235
  const basePoolId = getPoolIdByAddress.call(this, rawPoolList, pool.basePoolAddress);
232
- if (!allPoolsData[basePoolId])
233
- throw new Error(`Base pool "${pool.basePoolAddress}" of meta pool ${pool.id} (${pool.address}) is not loaded. Build or fetch the base pool before this one.`);
236
+ if (!allPoolsData[basePoolId]) {
237
+ console.warn(`Skipping meta pool ${pool.id} (${pool.address}): base pool "${pool.basePoolAddress}" is not loaded.`);
238
+ return;
239
+ }
234
240
  this.constants.BASE_POOLS[basePoolId] = this.constants.BASE_POOLS[basePoolId] ? this.constants.BASE_POOLS[basePoolId] + 1 : 1;
235
241
  const basePoolCoinNames = (_d = allPoolsData[basePoolId]) === null || _d === void 0 ? void 0 : _d.underlying_coins;
236
242
  const basePoolCoinAddresses = (_e = allPoolsData[basePoolId]) === null || _e === void 0 ? void 0 : _e.underlying_coin_addresses;
package/lib/index.d.ts CHANGED
@@ -19,6 +19,7 @@ export declare const createCurve: () => {
19
19
  gasStrategy?: import("./interfaces.js").IGasStrategy;
20
20
  chainId?: number;
21
21
  poolsData?: Record<import("./interfaces.js").IPoolType, import("./interfaces.js").IExtendedPoolDataFromApi>;
22
+ apiOnlyMetadata?: boolean;
22
23
  } | undefined) => Promise<void>;
23
24
  chainId: number;
24
25
  signerAddress: string;
@@ -76,6 +77,7 @@ export declare const createCurve: () => {
76
77
  getIsLiteChain: () => boolean;
77
78
  isNoRPC: boolean;
78
79
  fetchPoolByAddress: (poolAddress: string) => Promise<string>;
80
+ apiOnlyMetadata: boolean;
79
81
  factory: {
80
82
  fetchPools: (useApi?: boolean, isFiltered?: boolean) => Promise<void>;
81
83
  fetchNewPools: () => Promise<string[]>;
@@ -359,6 +361,7 @@ declare const _default: {
359
361
  gasStrategy?: import("./interfaces.js").IGasStrategy;
360
362
  chainId?: number;
361
363
  poolsData?: Record<import("./interfaces.js").IPoolType, import("./interfaces.js").IExtendedPoolDataFromApi>;
364
+ apiOnlyMetadata?: boolean;
362
365
  } | undefined) => Promise<void>;
363
366
  chainId: number;
364
367
  signerAddress: string;
@@ -416,6 +419,7 @@ declare const _default: {
416
419
  getIsLiteChain: () => boolean;
417
420
  isNoRPC: boolean;
418
421
  fetchPoolByAddress: (poolAddress: string) => Promise<string>;
422
+ apiOnlyMetadata: boolean;
419
423
  factory: {
420
424
  fetchPools: (useApi?: boolean, isFiltered?: boolean) => Promise<void>;
421
425
  fetchNewPools: () => Promise<string[]>;
package/lib/index.js CHANGED
@@ -25,6 +25,7 @@ export const createCurve = () => {
25
25
  this.signerAddress = _curve.signerAddress;
26
26
  this.chainId = _curve.chainId;
27
27
  this.isNoRPC = _curve.isNoRPC;
28
+ this.apiOnlyMetadata = _curve.apiOnlyMetadata;
28
29
  });
29
30
  }
30
31
  return {
@@ -68,6 +69,7 @@ export const createCurve = () => {
68
69
  getIsLiteChain: _curve.getIsLiteChain.bind(_curve),
69
70
  isNoRPC: _curve.isNoRPC,
70
71
  fetchPoolByAddress: _curve.fetchPoolByAddress.bind(_curve),
72
+ apiOnlyMetadata: _curve.apiOnlyMetadata,
71
73
  factory: {
72
74
  fetchPools: _curve.fetchFactoryPools.bind(_curve),
73
75
  fetchNewPools: _curve.fetchNewFactoryPools.bind(_curve),
package/lib/router.js CHANGED
@@ -34,6 +34,8 @@ function _getTVL(poolId_1, _a) {
34
34
  if (totalLiquidity !== undefined)
35
35
  return Number(totalLiquidity);
36
36
  }
37
+ if (this.apiOnlyMetadata)
38
+ return 0;
37
39
  return Number(yield getPool.call(this, poolId).stats.totalLiquidityMemoized());
38
40
  });
39
41
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@curvefi/api",
3
- "version": "2.72.4",
3
+ "version": "2.72.6",
4
4
  "description": "JavaScript library for curve.finance",
5
5
  "main": "lib/index.js",
6
6
  "author": "Macket",