@continuumdao/ctm-mpc-defi 0.2.2 → 0.2.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.
@@ -67,25 +67,25 @@ type CurveFullSession = {
67
67
  * same as the Curve dialog).
68
68
  */
69
69
  declare function fetchAllCurvePools(curve: {
70
- factory: {
70
+ factory?: {
71
71
  fetchPools: () => Promise<unknown>;
72
72
  };
73
- crvUSDFactory: {
73
+ crvUSDFactory?: {
74
74
  fetchPools: () => Promise<unknown>;
75
75
  };
76
- EYWAFactory: {
76
+ EYWAFactory?: {
77
77
  fetchPools: () => Promise<unknown>;
78
78
  };
79
- cryptoFactory: {
79
+ cryptoFactory?: {
80
80
  fetchPools: () => Promise<unknown>;
81
81
  };
82
- twocryptoFactory: {
82
+ twocryptoFactory?: {
83
83
  fetchPools: () => Promise<unknown>;
84
84
  };
85
- tricryptoFactory: {
85
+ tricryptoFactory?: {
86
86
  fetchPools: () => Promise<unknown>;
87
87
  };
88
- stableNgFactory: {
88
+ stableNgFactory?: {
89
89
  fetchPools: () => Promise<unknown>;
90
90
  };
91
91
  }): Promise<void>;
@@ -93,7 +93,7 @@ declare function fetchAllCurvePools(curve: {
93
93
  * One init + `fetchAllCurvePools` + graph build. Reuse this session for the asset list and the
94
94
  * Curve dialog to avoid duplicating the Curve API work.
95
95
  */
96
- declare function loadFullCurveSessionForRpc(rpcUrl: string): Promise<CurveFullSession | null>;
96
+ declare function loadFullCurveSessionForRpc(rpcUrl: string): Promise<CurveFullSession>;
97
97
  type CurveSessionSnapshot = {
98
98
  wrappedNative: string | undefined;
99
99
  swappableNodeKeys: string[];
@@ -101,7 +101,7 @@ type CurveSessionSnapshot = {
101
101
  adj: Record<string, string[]>;
102
102
  };
103
103
  /** JSON-safe Curve session for browser clients (via Next.js API route). */
104
- declare function loadCurveSessionSnapshotForRpc(rpcUrl: string): Promise<CurveSessionSnapshot | null>;
104
+ declare function loadCurveSessionSnapshotForRpc(rpcUrl: string): Promise<CurveSessionSnapshot>;
105
105
  type CurveCoinDataRow = {
106
106
  address: string;
107
107
  name?: string;
@@ -172,51 +172,77 @@ function bfsCurveSwapDestinations(adj, start) {
172
172
  }
173
173
 
174
174
  // src/protocols/evm/curve-dao/apiSession.ts
175
+ var CURVE_SESSION_CACHE_TTL_MS = 5 * 60 * 1e3;
176
+ var curveSessionCache = /* @__PURE__ */ new Map();
175
177
  async function fetchAllCurvePools(curve) {
176
178
  const run = (p) => p.catch(() => void 0);
177
- await Promise.all([
178
- run(curve.factory.fetchPools()),
179
- run(curve.crvUSDFactory.fetchPools()),
180
- run(curve.EYWAFactory.fetchPools()),
181
- run(curve.cryptoFactory.fetchPools()),
182
- run(curve.twocryptoFactory.fetchPools()),
183
- run(curve.tricryptoFactory.fetchPools()),
184
- run(curve.stableNgFactory.fetchPools())
185
- ]);
179
+ const tasks = [];
180
+ for (const key of [
181
+ "factory",
182
+ "crvUSDFactory",
183
+ "EYWAFactory",
184
+ "cryptoFactory",
185
+ "twocryptoFactory",
186
+ "tricryptoFactory",
187
+ "stableNgFactory"
188
+ ]) {
189
+ const f = curve[key];
190
+ if (f?.fetchPools) {
191
+ tasks.push(run(f.fetchPools()));
192
+ }
193
+ }
194
+ await Promise.all(tasks);
186
195
  }
187
196
  async function loadFullCurveSessionForRpc(rpcUrl) {
188
197
  const url = (rpcUrl ?? "").trim();
189
- if (!url) return null;
198
+ if (!url) {
199
+ throw new Error("rpcUrl is required.");
200
+ }
201
+ const cached = curveSessionCache.get(url);
202
+ if (cached && cached.expiresAt > Date.now()) {
203
+ return cached.session;
204
+ }
190
205
  try {
191
206
  const { default: curve } = await import('@curvefi/api');
192
207
  await curve.init("JsonRpc", { url }, {});
193
208
  const wrapped = curve.getNetworkConstants().NATIVE_COIN?.wrappedAddress;
194
209
  if (!curve.hasRouter || !curve.hasRouter()) {
195
- return {
210
+ const session2 = {
196
211
  curve,
197
212
  adj: /* @__PURE__ */ new Map(),
198
213
  swappableNodeKeys: /* @__PURE__ */ new Set(),
199
214
  wrappedNative: wrapped
200
215
  };
216
+ curveSessionCache.set(url, { session: session2, expiresAt: Date.now() + CURVE_SESSION_CACHE_TTL_MS });
217
+ return session2;
201
218
  }
202
219
  await fetchAllCurvePools(curve);
203
220
  const adj = buildCurveLiquidityGraphFromApi(curve);
204
221
  addNativeWethBridge(adj, wrapped);
205
- return {
222
+ const session = {
206
223
  curve,
207
224
  adj,
208
225
  swappableNodeKeys: swappableCurveGraphNodeKeys(adj),
209
226
  wrappedNative: wrapped
210
227
  };
211
- } catch {
212
- return null;
228
+ curveSessionCache.set(url, { session, expiresAt: Date.now() + CURVE_SESSION_CACHE_TTL_MS });
229
+ return session;
230
+ } catch (e) {
231
+ const msg = e instanceof Error ? e.message : String(e);
232
+ throw new Error(`Curve session init failed for RPC: ${msg}`);
213
233
  }
214
234
  }
215
235
  async function loadCurveSessionSnapshotForRpc(rpcUrl) {
216
236
  const session = await loadFullCurveSessionForRpc(rpcUrl);
217
- if (!session) return null;
237
+ if (!session) {
238
+ throw new Error("Failed to load Curve session for this RPC.");
239
+ }
240
+ const adjMap = session.adj;
241
+ if (!adjMap) {
242
+ throw new Error("Curve session has no pool graph for this RPC.");
243
+ }
218
244
  const adj = {};
219
- for (const [key, neighbors] of session.adj) {
245
+ for (const [key, neighbors] of adjMap) {
220
246
  adj[key] = [...neighbors];
221
247
  }
222
248
  return {
@@ -228,7 +254,9 @@ async function loadCurveSessionSnapshotForRpc(rpcUrl) {
228
254
  }
229
255
  async function fetchCurveCoinsDataForRpc(rpcUrl, addresses) {
230
256
  const session = await loadFullCurveSessionForRpc(rpcUrl);
231
- if (!session?.curve?.getCoinsData) return [];
257
+ if (!session.curve?.getCoinsData) {
258
+ throw new Error("Curve getCoinsData is not available for this RPC session.");
259
+ }
232
260
  const coins = await session.curve.getCoinsData(addresses);
233
261
  return addresses.map((addr, i) => {
234
262
  const c = coins[i];
@@ -799,8 +827,14 @@ async function curveDaoQuote(args) {
799
827
  throw new Error("amountHuman must be a positive decimal string.");
800
828
  }
801
829
  const session = await loadFullCurveSessionForRpc(rpcUrl);
802
- if (!session?.curve?.router?.getBestRouteAndOutput) {
803
- throw new Error("Curve router is not available (session load failed or chain has no router).");
830
+ const routerReady = Boolean(session.curve?.hasRouter?.() && session.curve.hasRouter());
831
+ if (!routerReady) {
832
+ throw new Error(
833
+ `Curve Router NG is not available on chain ${args.chainId}. Check that rpcGateway matches this chainId.`
834
+ );
835
+ }
836
+ if (!session.curve?.router?.getBestRouteAndOutput) {
837
+ throw new Error("Curve router API is unavailable after session load.");
804
838
  }
805
839
  const { curve, wrappedNative: wn } = session;
806
840
  const tokenInRouterId = toCurveRouterTokenId(normalizeNativeTokenIn(args.tokenIn), wn);