@logswap/sdk 0.5.49 → 0.5.51

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/index.d.ts CHANGED
@@ -19,5 +19,5 @@ export * from "./onboard.js";
19
19
  export * from "./indexer.js";
20
20
  export * from "./tokencache.js";
21
21
  export * from "./fpool.js";
22
- export { cPoolManagerAbi, fPoolManagerAbi, logswapLensAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
22
+ export { cPoolManagerAbi, fPoolManagerAbi, logswapLensAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, policyRegistryAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
23
23
  export * from "./admin.js";
package/dist/index.js CHANGED
@@ -19,5 +19,5 @@ export * from "./onboard.js";
19
19
  export * from "./indexer.js";
20
20
  export * from "./tokencache.js";
21
21
  export * from "./fpool.js";
22
- export { cPoolManagerAbi, fPoolManagerAbi, logswapLensAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
22
+ export { cPoolManagerAbi, fPoolManagerAbi, logswapLensAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, policyRegistryAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
23
23
  export * from "./admin.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@logswap/sdk",
3
- "version": "0.5.49",
3
+ "version": "0.5.51",
4
4
  "description": "TypeScript SDK for Logswap, the liquidity primitive introducing the logarithmic invariant — typed wrappers over the CPoolManager / FPoolManager / Router / Lens surface.",
5
5
  "license": "GPL-2.0-or-later",
6
6
  "type": "module",
package/src/admin.ts CHANGED
@@ -1,19 +1,20 @@
1
1
  /**
2
- * admin — the protocol's (feeCollector's) writes: the protocol's cut of the mint fee on both
3
- * managers, the policies a pool of each kind may be born with, the policies' own numbers, and the
4
- * two-step collector handover. Plain writes to the managers and the policies; no router.
2
+ * admin — the protocol's writes: the C manager's cut of the mint fee (the F manager's is a
3
+ * constant, decisions 049), the policies a pool may be born with (the registry's), the
4
+ * policies' own numbers, and the two-step collector handover. Plain writes to the managers,
5
+ * the registry and the policies; no router.
5
6
  *
6
7
  * One vocabulary (decisions 040): both managers call the protocol's cut of the mint fee
7
- * `MINT_FEE_PROTOCOL_CUT` and set it through `setFeeParams(uint256)` — one cut each since C
8
- * version 4 / F version 14. The harvest's cut is the policy's answer at every harvest (decisions
9
- * 044), set on the policy (`setHarvestCut`) and capped by the manager (`HARVEST_CUT_MAX`); the
10
- * release's protocol share likewise (`POT_CUT_MAX`).
8
+ * `MINT_FEE_PROTOCOL_CUT`; C sets it through `setFeeParams(uint256)`, F holds it as a constant
9
+ * (049). The harvest's cut is the policy's answer at every harvest (decisions 044), set on the
10
+ * policy (`setHarvestCut`) and capped by the manager (`HARVEST_CUT_MAX`); the release's
11
+ * protocol share likewise (`POT_CUT_MAX`).
11
12
  */
12
13
 
13
14
  import type { Address, Hash } from "viem";
14
15
  import type { LogswapClient } from "./client.js";
15
- import { cPoolManagerAbi, fPoolManagerAbi, padPolicyAbi, polPolicyAbi, publicPolicyAbi } from "./generated.js";
16
- import { F_KIND, fPolicyBaseAbi, type FPoolKind } from "./fpool.js";
16
+ import { cPoolManagerAbi, fPoolManagerAbi, padPolicyAbi, polPolicyAbi, policyRegistryAbi, publicPolicyAbi } from "./generated.js";
17
+ import { bytes32ToText, fPolicyBaseAbi, fPoolKindOfPolicy, textToBytes32, type FPoolKind } from "./fpool.js";
17
18
 
18
19
  function wallet(c: LogswapClient) {
19
20
  if (!c.wallet) throw new Error("a wallet client is required");
@@ -28,22 +29,122 @@ function write(c: LogswapClient, address: Address, abi: readonly unknown[], func
28
29
  export async function setFeeParamsC(c: LogswapClient, mintFeeProtocolCutWad: bigint): Promise<Hash> {
29
30
  return write(c, c.addresses.cPoolManager, cPoolManagerAbi, "setFeeParams", [mintFeeProtocolCutWad]);
30
31
  }
31
- /** The F manager's `setFeeParams(mintFeeProtocolCut)` — one cut, the C manager's shape (F version 14). */
32
- export async function setFeeParams(c: LogswapClient, mintFeeProtocolCutWad: bigint): Promise<Hash> {
33
- return write(c, c.addresses.fPoolManager as Address, fPoolManagerAbi, "setFeeParams", [mintFeeProtocolCutWad]);
32
+ /** The F manager's `MINT_FEE_PROTOCOL_CUT` — a constant since F version 18 (decisions 049); there is no setter. */
33
+ export async function fMintFeeProtocolCut(c: LogswapClient): Promise<bigint> {
34
+ return c.public.readContract({ address: c.addresses.fPoolManager as Address, abi: fPoolManagerAbi, functionName: "MINT_FEE_PROTOCOL_CUT" } as never) as Promise<bigint>;
35
+ }
36
+
37
+ // ─── the registry (decisions 046): the LOG authority's, not the collector's ─────────────────
38
+
39
+ const ZERO = "0x0000000000000000000000000000000000000000" as const;
40
+
41
+ /**
42
+ * The policy registry the F manager asks at every birth — `addresses.policyRegistry` when the
43
+ * deployment carries it, else read once from the manager. The zero address is a deployment with
44
+ * no registry: it asks nobody, and nothing here can be written.
45
+ */
46
+ export async function policyRegistryOf(c: LogswapClient): Promise<Address> {
47
+ if (c.addresses.policyRegistry) return c.addresses.policyRegistry;
48
+ return (await c.public.readContract({ address: c.addresses.fPoolManager as Address, abi: fPoolManagerAbi, functionName: "registry" } as never)) as Address;
49
+ }
50
+
51
+ /** Whether `policy` is approved now — listed and not yet sunset. True everywhere on a deployment with no registry. */
52
+ export async function policyApproved(c: LogswapClient, policy: Address): Promise<boolean> {
53
+ const registry = await policyRegistryOf(c);
54
+ if (registry === ZERO) return true;
55
+ return c.public.readContract({ address: registry, abi: policyRegistryAbi, functionName: "isApproved", args: [policy] } as never) as Promise<boolean>;
56
+ }
57
+
58
+ /** One policy on the registry's list, with what it says it is. */
59
+ export interface RegistryEntry {
60
+ policy: Address;
61
+ /** The policy's own `kind()` tag (decisions 049) — what a pool born under it is. */
62
+ kind: FPoolKind;
63
+ name: string;
64
+ /** The block it closes to new pools from; 0 = open. */
65
+ until: bigint;
66
+ /** Approved now: listed and not yet sunset. */
67
+ approved: boolean;
34
68
  }
35
69
 
36
70
  /**
37
- * Approve a policy for pools of `kind` to be born with, or withdraw the approval (decisions 041,
38
- * 044). Read at `initialize` and never again: a live pool keeps its policy.
71
+ * Every policy listed, sunset ones included — one flat list (decisions 049), each with the kind
72
+ * it says it is; `kind` narrows it to one, which is what a create form's dropdown reads. Empty
73
+ * with no registry.
39
74
  */
40
- export async function setPolicyApproved(c: LogswapClient, kind: FPoolKind, policy: Address, approved: boolean): Promise<Hash> {
41
- return write(c, c.addresses.fPoolManager as Address, fPoolManagerAbi, "setPolicyApproved", [F_KIND[kind], policy, approved]);
75
+ export async function registryPolicies(c: LogswapClient, kind?: FPoolKind): Promise<RegistryEntry[]> {
76
+ const registry = await policyRegistryOf(c);
77
+ if (registry === ZERO) return [];
78
+ const list = (await c.public.readContract({ address: registry, abi: policyRegistryAbi, functionName: "policies" } as never)) as readonly Address[];
79
+ const block = await c.public.getBlockNumber();
80
+ const all = await Promise.all(
81
+ list.map(async (policy) => {
82
+ const [[listed, until, , name], tag] = await Promise.all([
83
+ c.public.readContract({ address: registry, abi: policyRegistryAbi, functionName: "entries", args: [policy] } as never) as Promise<[boolean, bigint, number, `0x${string}`]>,
84
+ fPoolKindOfPolicy(c, policy),
85
+ ]);
86
+ return { policy, kind: tag, name: bytes32ToText(name), until, approved: listed && (until === 0n || block < until) };
87
+ }),
88
+ );
89
+ return kind ? all.filter((e) => e.kind === kind) : all;
90
+ }
91
+
92
+ /** The registry's owner — the LOG authority — and the proposed next one. */
93
+ export async function registryOwner(c: LogswapClient): Promise<{ owner: Address; pending: Address }> {
94
+ const registry = await policyRegistryOf(c);
95
+ if (registry === ZERO) return { owner: ZERO, pending: ZERO };
96
+ const [owner, pending] = await Promise.all([
97
+ c.public.readContract({ address: registry, abi: policyRegistryAbi, functionName: "owner" } as never) as Promise<Address>,
98
+ c.public.readContract({ address: registry, abi: policyRegistryAbi, functionName: "pendingOwner" } as never) as Promise<Address>,
99
+ ]);
100
+ return { owner, pending };
101
+ }
102
+
103
+ async function registryWrite(c: LogswapClient, functionName: string, args: readonly unknown[]): Promise<Hash> {
104
+ const registry = await policyRegistryOf(c);
105
+ if (registry === ZERO) throw new Error("logswap: this deployment carries no policy registry");
106
+ return write(c, registry, policyRegistryAbi, functionName, args);
107
+ }
108
+
109
+ /** `PolicyRegistry.approve`: list `policy` under `name` (at most 31 bytes). Again renames it and clears its sunset. The owner's. */
110
+ export async function registryApprove(c: LogswapClient, policy: Address, name: string): Promise<Hash> {
111
+ return registryWrite(c, "approve", [policy, textToBytes32(name)]);
112
+ }
113
+
114
+ /** `PolicyRegistry.sunset`: close `policy` to new pools from `untilBlock` on; 0 reopens. The owner's. */
115
+ export async function registrySunset(c: LogswapClient, policy: Address, untilBlock: bigint): Promise<Hash> {
116
+ return registryWrite(c, "sunset", [policy, untilBlock]);
42
117
  }
43
118
 
44
- /** Whether `policy` is approved for pools of `kind`. */
45
- export async function policyApproved(c: LogswapClient, kind: FPoolKind, policy: Address): Promise<boolean> {
46
- return c.public.readContract({ address: c.addresses.fPoolManager as Address, abi: fPoolManagerAbi, functionName: "policyApproved", args: [F_KIND[kind], policy] } as never) as Promise<boolean>;
119
+ /** `PolicyRegistry.revoke`: remove `policy` from the list at once. Live pools are untouched. The owner's. */
120
+ export async function registryRevoke(c: LogswapClient, policy: Address): Promise<Hash> {
121
+ return registryWrite(c, "revoke", [policy]);
122
+ }
123
+
124
+ /** The registry owner's two-step handover. */
125
+ export async function registryProposeOwner(c: LogswapClient, next: Address): Promise<Hash> {
126
+ return registryWrite(c, "proposeOwner", [next]);
127
+ }
128
+ export async function registryAcceptOwner(c: LogswapClient): Promise<Hash> {
129
+ return registryWrite(c, "acceptOwner", []);
130
+ }
131
+
132
+ /**
133
+ * Approve or revoke, the F version 15–16 shape kept for callers: `approved` true is
134
+ * {@link registryApprove} under the policy's own tag as its name, false is {@link registryRevoke}.
135
+ */
136
+ export async function setPolicyApproved(c: LogswapClient, policy: Address, approved: boolean): Promise<Hash> {
137
+ return approved ? registryApprove(c, policy, await fPoolKindOfPolicy(c, policy)) : registryRevoke(c, policy);
138
+ }
139
+
140
+ /**
141
+ * Move a pool to another approved policy of the same kind (decisions 046, 049): the registry
142
+ * owner's alone, orchestrated on the registry — `migrate(manager, poolId, to)`. The new policy
143
+ * takes the authority and the name from the old; the operator and the lists void; no swap lands
144
+ * in the block.
145
+ */
146
+ export async function fPoolMigrate(c: LogswapClient, a: { poolId: `0x${string}`; to: Address }): Promise<Hash> {
147
+ return registryWrite(c, "migrate", [c.addresses.fPoolManager as Address, a.poolId, a.to]);
47
148
  }
48
149
 
49
150
  // ─── the policies' numbers (the collector's; each bounded where it reaches the manager) ─────
@@ -67,6 +168,25 @@ export async function polSetRules(c: LogswapClient, policy: Address, s: { keepQu
67
168
  return write(c, policy, polPolicyAbi, "setRules", [s.keepQuote, s.minQuoteAtSeed]);
68
169
  }
69
170
 
171
+ /** `setQuoteListed` on any protocol policy: a quote a pool of that kind may be born against while it curates quotes. The collector's. */
172
+ export async function policySetQuoteListed(c: LogswapClient, policy: Address, quote: Address, listed: boolean): Promise<Hash> {
173
+ return write(c, policy, fPolicyBaseAbi, "setQuoteListed", [quote, listed]);
174
+ }
175
+
176
+ /** `setQuoteCurated` on any protocol policy: on, a birth against an unlisted quote is refused. The collector's. */
177
+ export async function policySetQuoteCurated(c: LogswapClient, policy: Address, curated: boolean): Promise<Hash> {
178
+ return write(c, policy, fPolicyBaseAbi, "setQuoteCurated", [curated]);
179
+ }
180
+
181
+ /** Whether `quote` passes `policy`'s birth check now: listed, or the policy does not curate quotes. */
182
+ export async function policyQuoteAllowed(c: LogswapClient, policy: Address, quote: Address): Promise<{ curated: boolean; listed: boolean; allowed: boolean }> {
183
+ const [curated, listed] = await Promise.all([
184
+ c.public.readContract({ address: policy, abi: fPolicyBaseAbi, functionName: "quoteCurated" } as never) as Promise<boolean>,
185
+ c.public.readContract({ address: policy, abi: fPolicyBaseAbi, functionName: "quoteListed", args: [quote] } as never) as Promise<boolean>,
186
+ ]);
187
+ return { curated, listed, allowed: !curated || listed };
188
+ }
189
+
70
190
  /** `PublicPolicy.setListed`: an asset a curated seed may hold. */
71
191
  export async function publicSetListed(c: LogswapClient, policy: Address, token: Address, listed: boolean): Promise<Hash> {
72
192
  return write(c, policy, publicPolicyAbi, "setListed", [token, listed]);
package/src/client.ts CHANGED
@@ -31,6 +31,12 @@ export interface LogswapAddresses {
31
31
  privatePolicy?: Address;
32
32
  polPolicy?: Address;
33
33
  padPolicy?: Address;
34
+ /**
35
+ * The policy registry (decisions 046): what a pool of each kind may be born under, and the
36
+ * owner that may move a pool between policies. Read from the F manager (`registry()`) when
37
+ * absent; a deployment with none asks nobody.
38
+ */
39
+ policyRegistry?: Address;
34
40
  /** Optional — the router falls back to plain approvals when absent. */
35
41
  permit2?: Address;
36
42
  }
@@ -116,13 +122,19 @@ export const EXPECTED_VERSION = 4n;
116
122
  // 15 (2026-09-20): the policy answers every question (decisions 044) — `FPoolKey.authority` is
117
123
  // `creator` (every pool id moves again); the roles, gates and list are the pool's POLICY's
118
124
  // (`FPolicyBase` / `PrivatePolicy`), not the manager's: `getPool` has `policy` and `asks` and no
119
- // role; `proposeAuthority`, `appointOperator`, `setGates`, `setAllowed` are policy writes;
125
+ // role; `proposeAuthority`, `appointOperator`, `setGates`, `setAllowed` (`setMinters` / `setTakers` since 17) are policy writes;
120
126
  // `policyApproved(kind, policy)` / `setPolicyApproved(kind, policy, ok)`; `Regenerated` names the payee;
121
127
  // `HARVEST_CUT_MAX` / `POT_CUT_MAX` cap what a policy may route to the protocol.
122
128
  // 16 (2026-09-21): the word is POLICY (decisions 045) — a rename, no pool id moves: `FPoolKey.policy`,
123
129
  // `IFPolicy`, `FPolicyBase`, `PublicPolicy` … `PadPolicy`, `policyApproved` / `setPolicyApproved`,
124
130
  // `PolicyApproved`; `PolPolicy.setPolicy` / `PolicySet` are `setRules` / `RulesSet`.
125
- export const EXPECTED_F_VERSION = 16n;
131
+ // 17 (2026-09-21): the registry, the move, the stamp, two lists, one base (decisions 046–048) — no
132
+ // pool id moves: the F manager takes a `PolicyRegistry` at construction and asks it at a birth
133
+ // (`policyApproved` / `setPolicyApproved` left the manager: `registryApprove` …); the key's policy
134
+ // is the policy at birth, `migrate` moves a pool for the registry's owner; `stamp` / `setAsks` are
135
+ // the policy's; the desk's `setAllowed` / `isAllowed` are `setMinters` / `setTakers` / `isMinter` /
136
+ // `isTaker`; a pad and a POL hold one base (`OneBase`).
137
+ export const EXPECTED_F_VERSION = 18n;
126
138
 
127
139
  export async function assertVersion(c: LogswapClient, expected = EXPECTED_VERSION): Promise<void> {
128
140
  const { cPoolManagerAbi } = await import("./generated.js");