@logswap/sdk 0.5.36 → 0.5.38

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/fpool.js CHANGED
@@ -22,8 +22,16 @@
22
22
  * twice, forever. One router is one spender — see `fPoolZapIn`/`fPoolZapOut` below, which target
23
23
  * `addresses.router`.
24
24
  */
25
- import { toFunctionSelector } from "viem";
26
- import { fPoolManagerAbi, logswapRouterAbi } from "./generated.js";
25
+ import { encodeFunctionData, toFunctionSelector } from "viem";
26
+ import { fPoolManagerAbi as fPoolPrimitiveAbi, fPoolSponsorAbi, logswapRouterAbi } from "./generated.js";
27
+ /**
28
+ * The F manager's ABI is the UNION of its two compiled halves (decisions 031): `FPoolManager`
29
+ * holds the primitive and forwards every other selector from its fallback to `FPoolSponsor` —
30
+ * the lever, `claim`, `dissolve`, the handover, the gates, the desk, the names — by delegatecall.
31
+ * One address from outside, so one ABI here; both halves carry the base's events and errors,
32
+ * and viem tolerates the duplicates.
33
+ */
34
+ export const fPoolManagerAbi = [...fPoolPrimitiveAbi, ...fPoolSponsorAbi];
27
35
  const WAD = 10n ** 18n;
28
36
  const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
29
37
  /** Read a basket pool whole. Batched — viem multicalls these when the transport allows. */
@@ -57,11 +65,9 @@ export async function getFPool(c, poolId) {
57
65
  ]);
58
66
  const bases = legs.map((l) => l[0]);
59
67
  const weights = legs.map((l) => l[1]);
60
- const x = legs.map((l) => l[2]);
61
- // the ISOLATION SHADOW, not the derived reserve: what this pool actually holds of the token.
62
- // In a singleton the contract's balance backs many pools, so this is the only per-pool figure.
63
- const reserves = legs.map((l) => l[3]);
64
- const { quote, Q, L, phi, theta0, bigSigma, authority, pendingAuthority, operator, minBuffer, gateMint, gateSwap, restructureBlock, feesOnly, seeded, dissolved } = p;
68
+ const x = legs.map((l) => l[2]); // derived by the manager: x_j = ln(w_j·L / R_j) (decisions 026)
69
+ const reserves = legs.map((l) => l[3]); // the state
70
+ const { quote, Q, L, phi, theta0, bigSigma, authority, pendingAuthority, operator, minBuffer, gateMint, gateSwap, restructureBlock, lockStrike, seeded, gen } = p;
65
71
  const totalSupply = p.shares;
66
72
  return {
67
73
  poolId,
@@ -84,9 +90,9 @@ export async function getFPool(c, poolId) {
84
90
  gateMint,
85
91
  gateSwap,
86
92
  restructureBlock: Number(restructureBlock),
87
- feesOnly,
93
+ lockStrike,
88
94
  seeded,
89
- dissolved,
95
+ gen: Number(gen),
90
96
  totalSupply,
91
97
  reserves,
92
98
  };
@@ -200,14 +206,69 @@ export async function fPoolZapOut(c, a) {
200
206
  const to = a.to ?? a.account;
201
207
  return writeRouter(c, "zapOut", [a.poolId, a.shares, a.tokenOut, a.minOut ?? 0n, to, a.deadline ?? defaultDeadline()], a.account);
202
208
  }
209
+ /**
210
+ * Roll a retired generation's bundle into the pool's live one (decisions 025, 032), on the
211
+ * router under one lock: redeem `shares` of generation `gen` in place — the legs, the quote and
212
+ * any unpulled dividend come back — buy through the pool's own curve only what the live
213
+ * generation's ratio lacks, mint `dL` of it to `to`, and refund the rest in kind. Quote the
214
+ * bundle does not cover is pulled from the payer, at most `maxQuoteIn`; surplus base is
215
+ * refunded, never sold. Size `dL` with {@link fPoolPreviewRollIn}. The router must be the
216
+ * caller's ERC-6909 operator ({@link approveRouterForFPool}).
217
+ */
218
+ export async function fPoolRollIn(c, a) {
219
+ const to = a.to ?? a.account;
220
+ return writeRouter(c, "rollIn", [a.poolId, BigInt(a.gen), a.shares, a.dL, a.maxQuoteIn ?? 0n, a.minShares ?? 0n, to, a.deadline ?? defaultDeadline()], a.account);
221
+ }
222
+ /**
223
+ * The roll `holder`'s `shares` of retired generation `gen` fund into the live one WITHOUT a
224
+ * trade: the largest `dL` the bundle's base covers on every leg, and the quote the bundle is
225
+ * short of (pass it as `maxQuoteIn`) or over (refunded — the up direction's distribution) at
226
+ * that `dL`. A leg the live generation admitted since makes `dL` zero: such a roll must buy, so
227
+ * size it below with `previewZapIn` in mind. Zero for the live generation, or before the next
228
+ * seed.
229
+ */
230
+ export async function fPoolPreviewRollIn(c, poolId, gen, holder, shares) {
231
+ const { logswapLensAbi } = await import("./generated.js");
232
+ const [dL, quoteShort, quoteExcess] = (await c.public.readContract({
233
+ address: c.addresses.lens,
234
+ abi: logswapLensAbi,
235
+ functionName: "previewRollIn",
236
+ args: [poolId, BigInt(gen), holder, shares],
237
+ }));
238
+ return { dL, quoteShort, quoteExcess };
239
+ }
203
240
  // ─── the floor lever (authority only) ─────────────────────────────────────────
204
241
  /**
205
- * Remove quote, lifting θ — price-neutral, pro-rata, no base moves. Under `feesOnly` the lift
206
- * stops at θ₀, so the authority extracts income and never the proceeds backing the floor.
242
+ * Remove quote, lifting θ — price-neutral, no base moves, and since decisions 028 a DIVIDEND to
243
+ * every share: the amount goes into the pool's pot and each holder's slice is settled lazily on
244
+ * their next transfer, mint or burn, or pulled with {@link fPoolClaim}. The sponsor's own slice —
245
+ * its shares' and the locked seed's at 0xdead — is pushed to `to` at once. Under `lockStrike`
246
+ * the lift stops at θ₀ (income only); on every live pool it stops at `LEVER_FLOOR` (Q/L ≥ ln 1.25).
207
247
  */
208
248
  export async function fPoolHarvest(c, a) {
209
249
  return writeFPool(c, a.poolId, "harvest", [a.amount, a.to ?? a.account], a.account);
210
250
  }
251
+ /**
252
+ * Pull one's settled dividend (decisions 028) on a generation's shares without moving them;
253
+ * anyone with shares. `gen` defaults to the live generation; a retired generation's harvests
254
+ * stay claimable under its own id (decisions 032).
255
+ */
256
+ export async function fPoolClaim(c, a) {
257
+ const gen = a.gen ?? (await fPoolGen(c, a.poolId));
258
+ return writeFPool(c, a.poolId, "claim", [BigInt(gen), a.to ?? a.account], a.account);
259
+ }
260
+ /** A holder's dividend as of now on generation `gen` (the live one by default) — banked plus pending on the current balance (decisions 028). */
261
+ export async function fPoolDividendOf(c, poolId, holder, gen) {
262
+ const g = gen ?? (await fPoolGen(c, poolId));
263
+ return c.public.readContract({
264
+ address: c.addresses.fPoolManager,
265
+ abi: fPoolManagerAbi,
266
+ functionName: "dividendOf",
267
+ args: [poolId, BigInt(g), holder],
268
+ });
269
+ }
270
+ /** The lever's floor: `harvest` may not take Q/L under ln 1.25 — the floor stays ≥ 20% below the mark (decisions 025). */
271
+ export const LEVER_FLOOR = 223143551314209755n;
211
272
  /** Commit quote, deepening θ — the other sign of `harvest`, the same word as the C floor edit (decisions 011). The mark does not move: governance may write θ, never x. */
212
273
  export async function fPoolDeepen(c, a) {
213
274
  return writeFPool(c, a.poolId, "deepen", [a.amount], a.account);
@@ -235,6 +296,18 @@ async function writeFPool(c, poolId, functionName, args, account) {
235
296
  });
236
297
  return wallet.writeContract(request);
237
298
  }
299
+ /** A manager write that is NOT keyed by a poolId — `multicall`. */
300
+ async function writeFPool0(c, functionName, args, account) {
301
+ const wallet = requireWallet(c);
302
+ const { request } = await c.public.simulateContract({
303
+ address: c.addresses.fPoolManager,
304
+ abi: fPoolManagerAbi,
305
+ functionName,
306
+ args,
307
+ account,
308
+ });
309
+ return wallet.writeContract(request);
310
+ }
238
311
  async function writeRouter(c, functionName, args, account,
239
312
  /** Tokens the call pulls: missing Permit2 allowances are SIGNED and ride in the same tx. */
240
313
  pullTokens = []) {
@@ -320,22 +393,71 @@ export async function approveRouterForFPool(c, account) {
320
393
  // One ERC-6909 space, split structurally on bit 255 — the C manager's scheme. Derived here rather
321
394
  // than read from the chain: it is pure, and a client that has to call to learn an id cannot build
322
395
  // a multicall that uses it.
323
- /** The ERC-6909 id carrying a pool's shares. Bit 255 set. */
324
- export function fPoolShareId(poolId) {
325
- return (1n << 255n) | (BigInt(poolId) >> 1n);
396
+ /**
397
+ * The ERC-6909 id carrying generation `gen` of a pool's shares (decisions 032): bit 255 set (the
398
+ * share flag), the pool id's top 239 bits, the generation in the low 16. Each generation's shares
399
+ * are their own asset — a retired one is a claim on its bundle, the live one on the pool.
400
+ */
401
+ export function fPoolShareId(poolId, gen = 0n) {
402
+ return (1n << 255n) | ((BigInt(poolId) >> 17n) << 16n) | BigInt(gen);
403
+ }
404
+ /** The generation a share id carries — its low 16 bits. */
405
+ export function fPoolGenOfShareId(id) {
406
+ return Number(id & 0xffffn);
407
+ }
408
+ /** The pool's live generation, one read. */
409
+ export async function fPoolGen(c, poolId) {
410
+ const p = (await c.public.readContract({
411
+ address: c.addresses.fPoolManager,
412
+ abi: fPoolManagerAbi,
413
+ functionName: "getPool",
414
+ args: [poolId],
415
+ }));
416
+ return Number(p.gen);
326
417
  }
327
418
  /** The ERC-6909 id carrying claims on a token. Bit 255 clear, so it can never meet a share id. */
328
419
  export function fPoolClaimId(token) {
329
420
  return BigInt(token);
330
421
  }
331
- export async function fPoolShareBalance(c, poolId, owner) {
422
+ /** A holder's shares of generation `gen` — the live one by default. */
423
+ export async function fPoolShareBalance(c, poolId, owner, gen) {
424
+ const g = gen ?? (await fPoolGen(c, poolId));
332
425
  return c.public.readContract({
333
426
  address: c.addresses.fPoolManager,
334
427
  abi: fPoolManagerAbi,
335
428
  functionName: "balanceOf",
336
- args: [owner, fPoolShareId(poolId)],
429
+ args: [owner, fPoolShareId(poolId, g)],
337
430
  });
338
431
  }
432
+ /** A retired generation's bundle (decisions 032): what is left to redeem — supply, quote, base per leg index. */
433
+ export async function fPoolBundleOf(c, poolId, gen) {
434
+ const [supply, quote, base] = (await c.public.readContract({
435
+ address: c.addresses.fPoolManager,
436
+ abi: fPoolManagerAbi,
437
+ functionName: "bundleOf",
438
+ args: [poolId, BigInt(gen)],
439
+ }));
440
+ return { supply, quote, base: [...base] };
441
+ }
442
+ /** A holder's claims on a pool's retired generations — one row per generation still held (decisions 032). */
443
+ export async function fPoolClaimsOf(c, poolId, owner) {
444
+ const { logswapLensAbi } = await import("./generated.js");
445
+ const rows = (await c.public.readContract({
446
+ address: c.addresses.lens,
447
+ abi: logswapLensAbi,
448
+ functionName: "fClaimsOf",
449
+ args: [poolId, owner],
450
+ }));
451
+ return rows.map((r) => ({ gen: Number(r.gen), shares: r.shares, base: [...r.base], quote: r.quote, dividend: r.dividend }));
452
+ }
453
+ /**
454
+ * Redeem `shares` of a RETIRED generation (decisions 032): its bundle, pro rata — the base per
455
+ * leg and the quote — plus the owner's settled dividend. Not `burn`: nothing can move a bundle's
456
+ * ratio, so there is no slippage to bound. The owner, or an operator of theirs.
457
+ */
458
+ export async function fPoolRedeem(c, a) {
459
+ return writeFPool(c, a.poolId, "redeem", [BigInt(a.gen), a.owner ?? a.account, a.shares], a.account);
460
+ }
339
461
  export async function fPoolClaimBalance(c, token, owner) {
340
462
  return c.public.readContract({
341
463
  address: c.addresses.fPoolManager,
@@ -433,7 +555,7 @@ export async function fPoolInitialize(c, a) {
433
555
  if (sum !== 10n ** 18n)
434
556
  throw new Error(`logswap: weights sum to ${sum}, expected 1e18`);
435
557
  const { bases, companions } = sortFPoolLegs(a.bases, a.weights);
436
- const key = { quote: a.quote, bases, weights: companions[0], phi: a.phi, feesOnly: a.feesOnly, authority: a.authority, salt: a.salt ?? ZERO_SALT };
558
+ const key = { quote: a.quote, bases, weights: companions[0], phi: a.phi, lockStrike: a.lockStrike, authority: a.authority, salt: a.salt ?? ZERO_SALT };
437
559
  const wallet = requireWallet(c);
438
560
  const { request } = await c.public.simulateContract({
439
561
  address: c.addresses.fPoolManager,
@@ -447,7 +569,7 @@ export async function fPoolInitialize(c, a) {
447
569
  /** The pool id is the key's hash — pure, so it can be read before or after creation. */
448
570
  export async function fPoolIdOf(c, a) {
449
571
  const { bases, companions } = sortFPoolLegs(a.bases, a.weights);
450
- const key = { quote: a.quote, bases, weights: companions[0], phi: a.phi, feesOnly: a.feesOnly, authority: a.authority, salt: a.salt ?? ZERO_SALT };
572
+ const key = { quote: a.quote, bases, weights: companions[0], phi: a.phi, lockStrike: a.lockStrike, authority: a.authority, salt: a.salt ?? ZERO_SALT };
451
573
  return c.public.readContract({
452
574
  address: c.addresses.fPoolManager,
453
575
  abi: fPoolManagerAbi,
@@ -456,17 +578,57 @@ export async function fPoolIdOf(c, a) {
456
578
  });
457
579
  }
458
580
  /**
459
- * Arm the pool: deposit the full basket at marks `x0` plus `Q0` of quote. Authority-only on-chain
460
- * (an open seed lets anyone front-run the creator for the strike). `x0` must align with the
461
- * SORTED bases — use {@link sortFPoolLegs} on (bases, weights, x0) together when building forms.
581
+ * The reserve a leg holds at a mark: `R = Lj·e^{−x}`, WAD math. The seed names RESERVES since
582
+ * decisions 029 — the sponsor states holdings and the price follows, `p = Lj / R` — so this is
583
+ * the one conversion from a price to what the pool will hold, done here, on the way in. Float
584
+ * precision (~1e-16 relative) is what a seed needs: any reserve is a legal seed, and the mark
585
+ * the pool derives from it is the one the sponsor meant to within that.
586
+ */
587
+ export function fPoolReserveAt(Lj, x) {
588
+ const e = Math.exp(-Number(x) / 1e18);
589
+ return (Lj * BigInt(Math.round(e * 1e18))) / 10n ** 18n;
590
+ }
591
+ /**
592
+ * Arm the pool: deposit `r0[j]` of each base plus `Q0` of quote against exposure `L0`. Pass either
593
+ * the reserves outright (`r0`) or the marks the pool should open at (`x0`, converted here with
594
+ * {@link fPoolReserveAt} against the key's weights). Authority-only on-chain (an open seed lets
595
+ * anyone front-run the creator for the strike). Arrays align with the SORTED bases — use
596
+ * {@link sortFPoolLegs} on (bases, weights, x0) together when building forms.
462
597
  */
463
598
  export async function fPoolSeed(c, a) {
464
- return writeFPool(c, a.poolId, "seed", [a.L0, a.x0, a.Q0], a.account);
599
+ const r0 = "r0" in a ? a.r0 : a.x0.map((x, j) => fPoolReserveAt((a.weights[j] * a.L0) / 10n ** 18n, x));
600
+ return writeFPool(c, a.poolId, "seed", [a.L0, r0, a.Q0], a.account);
465
601
  }
466
- /** End of life. Gated on-chain to the authority and to Q at dust (the raise is not abortable). */
602
+ /**
603
+ * Retire the live generation (decisions 025, 032). Allowed at Q ≤ L/1e9 on every pool — the
604
+ * market filled the ask — and on a pool that is not strike-locked at any Q. The live (S, Q, R_j)
605
+ * become a frozen bundle every share of this generation redeems ({@link fPoolRedeem}) or rolls
606
+ * ({@link fPoolRollIn}), forever; the pool is unseeded until the next {@link fPoolSeed}, which
607
+ * opens generation `gen + 1` under the same id, gates, lists and promises.
608
+ */
467
609
  export async function fPoolDissolve(c, a) {
468
610
  return writeFPool(c, a.poolId, "dissolve", [], a.account);
469
611
  }
612
+ /**
613
+ * The sponsor's relaunch as ONE transaction (decisions 025, 032): `dissolve` the live generation,
614
+ * `redeem` the sponsor's own shares of it (when `shares` > 0), `seed` the next generation with
615
+ * what came back — the manager's `multicall`, the sponsor as sender throughout, the same pool.
616
+ * Gates, allowlist, operator, `minBuffer` and names carry over; anything else goes in `extra`,
617
+ * pre-encoded against {@link fPoolManagerAbi}. The seed names reserves (decisions 029): `r0`
618
+ * outright, or `x0` marks against the key's `weights`.
619
+ */
620
+ export async function fPoolRelaunch(c, a) {
621
+ const gen = await fPoolGen(c, a.poolId);
622
+ const r0 = "r0" in a ? a.r0 : a.x0.map((x, j) => fPoolReserveAt((a.weights[j] * a.L0) / WAD, x));
623
+ const enc = (functionName, args) => encodeFunctionData({ abi: fPoolManagerAbi, functionName, args });
624
+ const calls = [
625
+ enc("dissolve", [a.poolId]),
626
+ ...(a.shares > 0n ? [enc("redeem", [a.poolId, BigInt(gen), a.account, a.shares])] : []),
627
+ enc("seed", [a.poolId, a.L0, r0, a.Q0]),
628
+ ...(a.extra ?? []),
629
+ ];
630
+ return writeFPool0(c, "multicall", [calls], a.account);
631
+ }
470
632
  /**
471
633
  * Propose the next authority — step one of two (contracts `2aa6b7b`, decisions 020). Nothing moves
472
634
  * until `next` accepts; proposing again (the zero address included) cancels a pending proposal.
@@ -480,8 +642,6 @@ export async function fPoolAcceptAuthority(c, a) {
480
642
  return writeFPool(c, a.poolId, "acceptAuthority", [], a.account);
481
643
  }
482
644
  // ─── the sponsor's controls and the desk (contracts bd3dd87, decisions 021) ───────────────
483
- /** `setLegL`'s "keep the stored mark" sentinel — the only legal `x` for a live leg. */
484
- export const NO_X = -(2n ** 255n);
485
645
  /** Turn the mint / swap gates on or off (authority). `burn` is never gated. */
486
646
  export async function fPoolSetGates(c, a) {
487
647
  return writeFPool(c, a.poolId, "setGates", [a.gateMint, a.gateSwap], a.account);
@@ -541,15 +701,17 @@ export async function fPoolRaiseMinBuffer(c, a) {
541
701
  }
542
702
  /**
543
703
  * Set leg `j`'s liquidity (operator, sole LP only): grow, shrink, retire (`newLj = 0`), or re-admit
544
- * a retired leg at a named mark `x`. For a live leg leave `x` undefined — its mark is the market's.
545
- * The base moves single-sidedly through the lock; shares adjust to hold the share value.
704
+ * a retired leg holding `r` of the base (decisions 029 — the price follows, `p = newLj / r`; use
705
+ * {@link fPoolReserveAt} from a mark). For a live leg leave `r` undefined — its price is the
706
+ * market's, the reserve scales with the liquidity. Base moves single-sidedly through the lock;
707
+ * shares adjust to hold the share value.
546
708
  */
547
709
  export async function fPoolSetLegL(c, a) {
548
- return writeFPool(c, a.poolId, "setLegL", [BigInt(a.j), a.newLj, a.x ?? NO_X], a.account);
710
+ return writeFPool(c, a.poolId, "setLegL", [BigInt(a.j), a.newLj, a.r ?? 0n], a.account);
549
711
  }
550
- /** Admit a base the pool has never held, at a named mark, with liquidity `Lj` (operator, sole LP only). */
712
+ /** Admit a base the pool has never held: `R` of it against liquidity `Lj`, so at `p = Lj / R` (operator, sole LP only). */
551
713
  export async function fPoolAdmitLeg(c, a) {
552
- return writeFPool(c, a.poolId, "admitLeg", [a.base, a.Lj, a.x], a.account);
714
+ return writeFPool(c, a.poolId, "admitLeg", [a.base, a.Lj, a.R], a.account);
553
715
  }
554
716
  /**
555
717
  * Move shares (ERC-6909 `transfer`) — to another holder, or to `0xdead` to lock them for good.
@@ -558,18 +720,19 @@ export async function fPoolAdmitLeg(c, a) {
558
720
  */
559
721
  export async function fPoolTransferShares(c, a) {
560
722
  const wallet = requireWallet(c);
723
+ const gen = a.gen ?? (await fPoolGen(c, a.poolId));
561
724
  const { request } = await c.public.simulateContract({
562
725
  address: c.addresses.fPoolManager,
563
726
  abi: fPoolManagerAbi,
564
727
  functionName: "transfer",
565
- args: [a.to, fPoolShareId(a.poolId), a.shares],
728
+ args: [a.to, fPoolShareId(a.poolId, gen), a.shares],
566
729
  account: a.account,
567
730
  });
568
731
  return wallet.writeContract(request);
569
732
  }
570
733
  /**
571
734
  * Every F pool ever created, from `Initialize` logs alone. Possible only because the event
572
- * carries the full key preimage (bases, weights, phi, feesOnly) — the poolId is a hash and could
735
+ * carries the full key preimage (bases, weights, phi, lockStrike) — the poolId is a hash and could
573
736
  * never be inverted; contracts PR #17 exists for exactly this call.
574
737
  */
575
738
  export async function discoverFPools(c, opts = {}) {
@@ -602,7 +765,7 @@ export async function discoverFPools(c, opts = {}) {
602
765
  bases: [...a.bases],
603
766
  weights: [...a.weights],
604
767
  phi: a.phi,
605
- feesOnly: a.feesOnly,
768
+ lockStrike: a.lockStrike,
606
769
  authority: a.authority,
607
770
  block: l.blockNumber ?? 0n,
608
771
  seeded: q0 !== undefined,
@@ -620,7 +783,7 @@ export async function fPoolShareHolders(c, poolIdHex, opts = {}) {
620
783
  const ev = fPoolManagerAbi.find((x) => x.type === "event" && x.name === "Transfer");
621
784
  if (!ev)
622
785
  throw new Error("logswap: 6909 Transfer event missing from the generated ABI");
623
- const id = fPoolShareId(poolIdHex);
786
+ const id = fPoolShareId(poolIdHex, opts.gen ?? (await fPoolGen(c, poolIdHex)));
624
787
  const logs = await c.public.getLogs({
625
788
  address: c.addresses.fPoolManager,
626
789
  event: ev,
@@ -641,7 +804,7 @@ export async function fPoolShareHolders(c, poolIdHex, opts = {}) {
641
804
  .map(([holder, shares]) => ({ holder: holder, shares }))
642
805
  .sort((a, b) => (b.shares > a.shares ? 1 : -1));
643
806
  }
644
- /** Every F pool's state in one lens call (the raw manager struct: quote, phi, authority, feesOnly, seeded, dissolved, n, Q, L, shares, theta0, bigSigma, leverTheta). */
807
+ /** Every F pool's state in one lens call (the raw manager struct: quote, phi, authority, lockStrike, seeded, gen, n, Q, L, shares, theta0, bigSigma, leverTheta). */
645
808
  export async function getFPoolsRaw(c, poolIds) {
646
809
  const { logswapLensAbi } = await import("./generated.js");
647
810
  return (await c.public.readContract({ address: c.addresses.lens, abi: logswapLensAbi, functionName: "getFPools", args: [poolIds] }));