@logswap/sdk 0.5.47 → 0.5.49
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/admin.d.ts +19 -19
- package/dist/admin.js +29 -29
- package/dist/client.d.ts +6 -6
- package/dist/client.js +11 -8
- package/dist/fpool.d.ts +82 -82
- package/dist/fpool.js +99 -99
- package/dist/generated.d.ts +103 -103
- package/dist/generated.js +132 -79
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/admin.ts +29 -29
- package/src/client.ts +16 -13
- package/src/fpool.ts +133 -133
- package/src/generated.ts +132 -79
- package/src/index.ts +1 -1
package/dist/fpool.js
CHANGED
|
@@ -14,15 +14,15 @@
|
|
|
14
14
|
*
|
|
15
15
|
* **Two products, one contract.** The basket (n > 1) and the launch (n = 1, the creator alone on
|
|
16
16
|
* the lever) are the same bytecode under two key fields — the KIND (what the manager promises
|
|
17
|
-
* structurally) and the
|
|
17
|
+
* structurally) and the POLICY (the pool's policy: its roles, its gates, the terms of every harvest
|
|
18
18
|
* and release; decisions 041, 044) — and nothing in the maths. `describeFPool` below reports
|
|
19
19
|
* which shape a given pool is, because a UI has to decide what to render.
|
|
20
20
|
*
|
|
21
|
-
* **The roles are the
|
|
22
|
-
* authority, operator, gate or list: it asks the pool's
|
|
23
|
-
* answer. So `getFPool` carries the
|
|
24
|
-
* roles FROM the
|
|
25
|
-
* is a write to the
|
|
21
|
+
* **The roles are the policy's, not the manager's** (F version 15). The manager holds no
|
|
22
|
+
* authority, operator, gate or list: it asks the pool's policy `may(who, action)` and acts on the
|
|
23
|
+
* answer. So `getFPool` carries the policy and what it declared, {@link getFPoolRoles} reads the
|
|
24
|
+
* roles FROM the policy, and every role write — the handover, the operator, the gates, the list —
|
|
25
|
+
* is a write to the policy ({@link fPoolProposeAuthority}, {@link fPoolSetGates}, …).
|
|
26
26
|
*
|
|
27
27
|
* **Zaps live on the ROUTER, not here.** Permit2 is AllowanceTransfer mode, whose standing
|
|
28
28
|
* allowance is keyed by spender, so a second router would cost the user an allowance per token
|
|
@@ -30,24 +30,24 @@
|
|
|
30
30
|
* `addresses.router`.
|
|
31
31
|
*/
|
|
32
32
|
import { encodeFunctionData, toFunctionSelector } from "viem";
|
|
33
|
-
import { fPoolManagerAbi, logswapRouterAbi,
|
|
33
|
+
import { fPoolManagerAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
|
|
34
34
|
/**
|
|
35
35
|
* One contract, one ABI (decisions 039, F version 12): `harvest`, `claim`, `retire`, `regenerate`,
|
|
36
36
|
* `setLegs`, the names, the fee parameters are `FPoolManager`'s own code. The roles left it for
|
|
37
|
-
* the
|
|
38
|
-
* {@link
|
|
37
|
+
* the policies in F version 15 (decisions 044): {@link fPolicyBaseAbi} is what every policy shares,
|
|
38
|
+
* {@link privatePolicyAbi} the desk's, {@link padPolicyAbi} / {@link polPolicyAbi} / {@link publicPolicyAbi}
|
|
39
39
|
* the kinds'.
|
|
40
40
|
*/
|
|
41
|
-
export { fPoolManagerAbi,
|
|
41
|
+
export { fPoolManagerAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi };
|
|
42
42
|
/**
|
|
43
|
-
* What every protocol
|
|
44
|
-
* `maxHarvest`. `
|
|
45
|
-
* in for the base — a call through it to any of the four
|
|
43
|
+
* What every protocol policy shares (`FPolicyBase`): the roles and their handover, `harvestCut`,
|
|
44
|
+
* `maxHarvest`. `polPolicyAbi` is a superset of it and carries nothing that collides, so it stands
|
|
45
|
+
* in for the base — a call through it to any of the four policies decodes the base's functions.
|
|
46
46
|
*/
|
|
47
|
-
export const
|
|
47
|
+
export const fPolicyBaseAbi = polPolicyAbi;
|
|
48
48
|
const WAD = 10n ** 18n;
|
|
49
49
|
const ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
50
|
-
/** The optional questions a
|
|
50
|
+
/** The optional questions a policy declared at birth (decisions 044), as bits of `Pool.asks`. */
|
|
51
51
|
export const ASK_SWAP = 1;
|
|
52
52
|
export const ASK_MINT = 2;
|
|
53
53
|
/** Read a basket pool whole. Batched — viem multicalls these when the transport allows. */
|
|
@@ -61,7 +61,7 @@ export async function getFPool(c, poolId) {
|
|
|
61
61
|
args,
|
|
62
62
|
});
|
|
63
63
|
// `getPool` returns the whole scalar struct in one call — the singleton's shape makes what used
|
|
64
|
-
// to be a dozen getters a single read. No role in it since F version 15: those are the
|
|
64
|
+
// to be a dozen getters a single read. No role in it since F version 15: those are the policy's.
|
|
65
65
|
const p = await rd("getPool", [poolId]);
|
|
66
66
|
// A pool that was never created reads as an all-zero struct rather than reverting, so the
|
|
67
67
|
// absence has to be named here or every caller mistakes "no such pool" for "a pool holding
|
|
@@ -83,7 +83,7 @@ export async function getFPool(c, poolId) {
|
|
|
83
83
|
const weights = legs.map((l) => l[1]);
|
|
84
84
|
const x = legs.map((l) => l[2]); // derived by the manager: x_j = ln(w_j·L / R_j) (decisions 026)
|
|
85
85
|
const reserves = legs.map((l) => l[3]); // the state
|
|
86
|
-
const { quote, Q, L, phi, theta0, bigSigma,
|
|
86
|
+
const { quote, Q, L, phi, theta0, bigSigma, policy, restructureBlock, seeded, gen } = p;
|
|
87
87
|
const totalSupply = p.shares;
|
|
88
88
|
return {
|
|
89
89
|
poolId,
|
|
@@ -98,7 +98,7 @@ export async function getFPool(c, poolId) {
|
|
|
98
98
|
theta,
|
|
99
99
|
compositeX,
|
|
100
100
|
bigSigma,
|
|
101
|
-
|
|
101
|
+
policy,
|
|
102
102
|
asks: Number(p.asks),
|
|
103
103
|
name: bytes32ToText(p.name),
|
|
104
104
|
restructureBlock: Number(restructureBlock),
|
|
@@ -118,16 +118,16 @@ export function fPoolKindOf(n) {
|
|
|
118
118
|
throw new Error(`logswap: unknown pool kind ${n}`);
|
|
119
119
|
return k;
|
|
120
120
|
}
|
|
121
|
-
/** The deployment's
|
|
122
|
-
export function
|
|
121
|
+
/** The deployment's policy for a kind (decisions 044): what a key of that kind names. */
|
|
122
|
+
export function fPoolPolicyFor(c, kind) {
|
|
123
123
|
const a = c.addresses;
|
|
124
|
-
const
|
|
125
|
-
if (!
|
|
126
|
-
throw new Error(`logswap: this deployment carries no ${kind}
|
|
127
|
-
return
|
|
124
|
+
const policy = kind === "public" ? a.publicPolicy : kind === "private" ? a.privatePolicy : kind === "pol" ? a.polPolicy : a.padPolicy;
|
|
125
|
+
if (!policy)
|
|
126
|
+
throw new Error(`logswap: this deployment carries no ${kind} policy`);
|
|
127
|
+
return policy;
|
|
128
128
|
}
|
|
129
|
-
/** The
|
|
130
|
-
export async function
|
|
129
|
+
/** The policy a pool named in its key — one read; {@link getFPool} carries it too. */
|
|
130
|
+
export async function fPoolPolicyOf(c, poolId) {
|
|
131
131
|
const p = (await c.public.readContract({
|
|
132
132
|
address: c.addresses.fPoolManager,
|
|
133
133
|
abi: fPoolManagerAbi,
|
|
@@ -136,28 +136,28 @@ export async function fPoolHookOf(c, poolId) {
|
|
|
136
136
|
}));
|
|
137
137
|
if (/^0x0{40}$/i.test(p.quote))
|
|
138
138
|
throw new Error(`logswap: no F pool with id ${poolId}`);
|
|
139
|
-
return p.
|
|
139
|
+
return p.policy;
|
|
140
140
|
}
|
|
141
|
-
/** Read a pool's roles from its
|
|
141
|
+
/** Read a pool's roles from its policy. `state` saves the `getPool` round trip when already in hand. */
|
|
142
142
|
export async function getFPoolRoles(c, poolId, state) {
|
|
143
143
|
const s = state ?? (await getFPool(c, poolId));
|
|
144
|
-
const
|
|
144
|
+
const rdPolicy = (abi, functionName) => c.public.readContract({ address: s.policy, abi, functionName, args: [poolId] });
|
|
145
145
|
const [creator, authority, pendingAuthority, maxHarvest] = await Promise.all([
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
146
|
+
rdPolicy(fPolicyBaseAbi, "creator"),
|
|
147
|
+
rdPolicy(fPolicyBaseAbi, "authority"),
|
|
148
|
+
rdPolicy(fPolicyBaseAbi, "pendingAuthority"),
|
|
149
|
+
rdPolicy(fPolicyBaseAbi, "maxHarvest"),
|
|
150
150
|
]);
|
|
151
151
|
const desk = s.kind === "private";
|
|
152
152
|
const [operator, pendingOperator, gateMint, gateSwap] = desk
|
|
153
153
|
? await Promise.all([
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
154
|
+
rdPolicy(privatePolicyAbi, "operator"),
|
|
155
|
+
rdPolicy(privatePolicyAbi, "pendingOperator"),
|
|
156
|
+
rdPolicy(privatePolicyAbi, "gateMint"),
|
|
157
|
+
rdPolicy(privatePolicyAbi, "gateSwap"),
|
|
158
158
|
])
|
|
159
159
|
: [ZERO_ADDRESS, ZERO_ADDRESS, false, false];
|
|
160
|
-
return {
|
|
160
|
+
return { policy: s.policy, creator, authority, pendingAuthority, operator, pendingOperator, gateMint, gateSwap, maxHarvest };
|
|
161
161
|
}
|
|
162
162
|
export async function describeFPool(c, s) {
|
|
163
163
|
const rd = (functionName, args = [s.poolId]) => c.public.readContract({
|
|
@@ -606,7 +606,7 @@ export function sortFPoolLegs(bases, ...companions) {
|
|
|
606
606
|
const idx = bases.map((_, i) => i).sort((a, b) => (bases[a].toLowerCase() < bases[b].toLowerCase() ? -1 : 1));
|
|
607
607
|
return { bases: idx.map((i) => bases[i]), companions: companions.map((arr) => idx.map((i) => arr[i])) };
|
|
608
608
|
}
|
|
609
|
-
/** The key as the manager hashes it: legs sorted, the kind's
|
|
609
|
+
/** The key as the manager hashes it: legs sorted, the kind's policy filled in when none is named. */
|
|
610
610
|
export function fPoolKeyOf(c, a) {
|
|
611
611
|
const { bases, companions } = sortFPoolLegs(a.bases, a.weights);
|
|
612
612
|
return {
|
|
@@ -615,7 +615,7 @@ export function fPoolKeyOf(c, a) {
|
|
|
615
615
|
weights: companions[0],
|
|
616
616
|
phi: a.phi,
|
|
617
617
|
kind: F_KIND[a.kind],
|
|
618
|
-
|
|
618
|
+
policy: a.policy ?? fPoolPolicyFor(c, a.kind),
|
|
619
619
|
creator: a.creator,
|
|
620
620
|
salt: a.salt ?? ZERO_SALT,
|
|
621
621
|
};
|
|
@@ -674,7 +674,7 @@ export async function fPoolSeed(c, a) {
|
|
|
674
674
|
* operator harvested it out first ({@link fPoolRetire} does both in one transaction). The live
|
|
675
675
|
* (S, Q, R_j) become a frozen bundle every share of this generation redeems ({@link fPoolRedeem})
|
|
676
676
|
* or rolls ({@link fPoolRollIn}), forever; the pool is unseeded until the next {@link fPoolSeed},
|
|
677
|
-
* which opens generation `gen + 1` under the same id,
|
|
677
|
+
* which opens generation `gen + 1` under the same id, policy, roles, gates and lists.
|
|
678
678
|
*/
|
|
679
679
|
export async function fPoolRetireRaw(c, a) {
|
|
680
680
|
return writeFPool(c, a.poolId, "retire", [], a.account);
|
|
@@ -698,8 +698,8 @@ export async function fPoolRetire(c, a) {
|
|
|
698
698
|
* `retire` (decisions 035: a retire needs an empty bid on every pool). Since F version 14 one
|
|
699
699
|
* `harvest(Q)` does it: the protocol's cut leaves the pool with the amount (with no collector
|
|
700
700
|
* there is no cut). `[]` when the bid is already empty. Throws on a pad that still bids (its bid
|
|
701
|
-
* empties only as the market sells it down), and when the pool's
|
|
702
|
-
* (`
|
|
701
|
+
* empties only as the market sells it down), and when the pool's policy keeps a floor on the bid
|
|
702
|
+
* (`PolPolicy.keepQuote`, decisions 044): a `retire` under that policy waits for the market.
|
|
703
703
|
*/
|
|
704
704
|
export async function fPoolEmptyingHarvests(c, poolId) {
|
|
705
705
|
const s = await getFPool(c, poolId);
|
|
@@ -709,16 +709,16 @@ export async function fPoolEmptyingHarvests(c, poolId) {
|
|
|
709
709
|
throw new Error("logswap: a pad is retired only once its bid is empty (decisions 035)");
|
|
710
710
|
const { maxHarvest } = await getFPoolRoles(c, poolId, s);
|
|
711
711
|
if (maxHarvest < s.Q)
|
|
712
|
-
throw new Error("logswap: the pool's
|
|
712
|
+
throw new Error("logswap: the pool's policy keeps a floor on the bid — it cannot be harvested empty (decisions 044)");
|
|
713
713
|
return [s.Q];
|
|
714
714
|
}
|
|
715
715
|
/**
|
|
716
|
-
* Release the dead shares' pot under the
|
|
716
|
+
* Release the dead shares' pot under the policy's terms (decisions 041, 044) — a pad's graduation.
|
|
717
717
|
* The manager harvests the generation's income first (the pot then holds everything the dead
|
|
718
|
-
* shares earned), asks the
|
|
718
|
+
* shares earned), asks the policy, and applies its answer: a share to the payee it names (the pad's
|
|
719
719
|
* creator — the pool's authority), a cut to the collector, the rest bought in as more of the
|
|
720
|
-
* float the pool owns, a slice of every reserve burned. The
|
|
721
|
-
* threshold (`
|
|
720
|
+
* float the pool owns, a slice of every reserve burned. The policy refuses under its rung's
|
|
721
|
+
* threshold (`PadPolicy.NotGraduated`). Whoever runs the pool.
|
|
722
722
|
*/
|
|
723
723
|
export async function fPoolRegenerate(c, a) {
|
|
724
724
|
return writeFPool(c, a.poolId, "regenerate", [a.to ?? a.account], a.account);
|
|
@@ -730,7 +730,7 @@ export async function fPoolRegenerate(c, a) {
|
|
|
730
730
|
* next generation's composition (`legs`: a private pool's reshape — retire, admit, reweight), and
|
|
731
731
|
* `seed` it with what came back — the manager's `multicall`, one sender throughout, the same
|
|
732
732
|
* pool. The operator's when one is appointed and the seed's inventory is its own; by default the
|
|
733
|
-
* authority's. The
|
|
733
|
+
* authority's. The policy, its roles, gates, allowlist and the name carry over; anything else goes
|
|
734
734
|
* in `extra`, pre-encoded against {@link fPoolManagerAbi}. The seed names reserves (decisions
|
|
735
735
|
* 029): `r0` outright — one per leg of the NEXT table, 0 for a retired leg — or `x0` marks
|
|
736
736
|
* against the next table's `weights`.
|
|
@@ -767,9 +767,9 @@ export function fPoolLaunchCalls(poolId, a) {
|
|
|
767
767
|
if (given.length !== a.bases.length)
|
|
768
768
|
throw new Error(`logswap: ${given.length} reserves for ${a.bases.length} legs`);
|
|
769
769
|
const { bases, companions } = sortFPoolLegs(a.bases, a.weights, given);
|
|
770
|
-
if (!a.
|
|
771
|
-
throw new Error("logswap: fPoolLaunchCalls needs the key's
|
|
772
|
-
const key = { quote: a.quote, bases, weights: companions[0], phi: a.phi, kind: F_KIND[a.kind],
|
|
770
|
+
if (!a.policy)
|
|
771
|
+
throw new Error("logswap: fPoolLaunchCalls needs the key's policy — fPoolLaunch fills it from the deployment");
|
|
772
|
+
const key = { quote: a.quote, bases, weights: companions[0], phi: a.phi, kind: F_KIND[a.kind], policy: a.policy, creator: a.creator, salt: a.salt ?? ZERO_SALT };
|
|
773
773
|
const enc = (functionName, args) => encodeFunctionData({ abi: fPoolManagerAbi, functionName, args });
|
|
774
774
|
const calls = [];
|
|
775
775
|
if (!a.initialized)
|
|
@@ -785,21 +785,21 @@ export function fPoolLaunchCalls(poolId, a) {
|
|
|
785
785
|
}
|
|
786
786
|
if (a.name)
|
|
787
787
|
calls.push(enc("setName", [poolId, textToBytes32(a.name)]));
|
|
788
|
-
// the desk's gates and list are the
|
|
788
|
+
// the desk's gates and list are the POLICY's (decisions 044), not the manager's: they cannot ride
|
|
789
789
|
// in this batch — `fPoolDeskOpening` sends them right after, as the same creator
|
|
790
790
|
calls.push(...(a.extra ?? []));
|
|
791
791
|
return calls;
|
|
792
792
|
}
|
|
793
793
|
/**
|
|
794
|
-
* The desk's opening posture, on its
|
|
794
|
+
* The desk's opening posture, on its policy (decisions 044): gated minting, the creator listed. No
|
|
795
795
|
* appointment: the authority is the operator until one is appointed (decisions 037). Two writes
|
|
796
|
-
* to `
|
|
796
|
+
* to `PrivatePolicy`; the launch batch cannot carry them (they are not manager calls).
|
|
797
797
|
*/
|
|
798
798
|
export async function fPoolDeskOpening(c, a) {
|
|
799
|
-
const
|
|
799
|
+
const policy = a.policy ?? fPoolPolicyFor(c, "private");
|
|
800
800
|
return [
|
|
801
|
-
await fPoolSetGates(c, { poolId: a.poolId, gateMint: true, gateSwap: false, account: a.account,
|
|
802
|
-
await fPoolSetAllowed(c, { poolId: a.poolId, who: [a.account], allowed: true, account: a.account,
|
|
801
|
+
await fPoolSetGates(c, { poolId: a.poolId, gateMint: true, gateSwap: false, account: a.account, policy }),
|
|
802
|
+
await fPoolSetAllowed(c, { poolId: a.poolId, who: [a.account], allowed: true, account: a.account, policy }),
|
|
803
803
|
];
|
|
804
804
|
}
|
|
805
805
|
/**
|
|
@@ -821,20 +821,20 @@ export async function fPoolDeskOpening(c, a) {
|
|
|
821
821
|
*/
|
|
822
822
|
export async function fPoolLaunch(c, a) {
|
|
823
823
|
const poolId = await fPoolIdOf(c, a);
|
|
824
|
-
const calls = fPoolLaunchCalls(poolId, { ...a,
|
|
824
|
+
const calls = fPoolLaunchCalls(poolId, { ...a, policy: a.policy ?? fPoolPolicyFor(c, a.kind) });
|
|
825
825
|
const hash = await writeFPool0(c, "multicall", [calls], a.account);
|
|
826
826
|
return { hash, poolId };
|
|
827
827
|
}
|
|
828
|
-
// ─── the roles, on the
|
|
828
|
+
// ─── the roles, on the policy (decisions 044) ─────────────────────────────────────────────
|
|
829
829
|
//
|
|
830
|
-
// Every write here goes to the pool's
|
|
831
|
-
// may be passed when in hand (`FPoolState.
|
|
832
|
-
/** A write keyed by poolId, on the pool's
|
|
833
|
-
async function
|
|
830
|
+
// Every write here goes to the pool's POLICY, not the manager: the manager holds no role. `policy`
|
|
831
|
+
// may be passed when in hand (`FPoolState.policy`, `FPoolRoles.policy`); otherwise it is read once.
|
|
832
|
+
/** A write keyed by poolId, on the pool's policy. */
|
|
833
|
+
async function writePolicy(c, abi, a, functionName, args) {
|
|
834
834
|
const wallet = requireWallet(c);
|
|
835
|
-
const
|
|
835
|
+
const policy = a.policy ?? (await fPoolPolicyOf(c, a.poolId));
|
|
836
836
|
const { request } = await c.public.simulateContract({
|
|
837
|
-
address:
|
|
837
|
+
address: policy,
|
|
838
838
|
abi,
|
|
839
839
|
functionName,
|
|
840
840
|
args: [a.poolId, ...args],
|
|
@@ -843,39 +843,39 @@ async function writeHook(c, abi, a, functionName, args) {
|
|
|
843
843
|
return wallet.writeContract(request);
|
|
844
844
|
}
|
|
845
845
|
/**
|
|
846
|
-
* Propose the next authority — step one of two (decisions 020), on the pool's
|
|
846
|
+
* Propose the next authority — step one of two (decisions 020), on the pool's policy. Nothing moves
|
|
847
847
|
* until `next` accepts; proposing again (the zero address included) cancels a pending proposal.
|
|
848
|
-
* Indexed on-chain via the
|
|
848
|
+
* Indexed on-chain via the policy's AuthorityProposed.
|
|
849
849
|
*/
|
|
850
850
|
export async function fPoolProposeAuthority(c, a) {
|
|
851
|
-
return
|
|
851
|
+
return writePolicy(c, fPolicyBaseAbi, a, "proposeAuthority", [a.next]);
|
|
852
852
|
}
|
|
853
853
|
/**
|
|
854
|
-
* Accept a pending proposal — step two; only the proposed address can. Indexed via the
|
|
855
|
-
* AuthoritySet. On the desk's
|
|
854
|
+
* Accept a pending proposal — step two; only the proposed address can. Indexed via the policy's
|
|
855
|
+
* AuthoritySet. On the desk's policy this clears the operator (pending and accepted) and voids the
|
|
856
856
|
* seller's list (decisions 040, 044).
|
|
857
857
|
*/
|
|
858
858
|
export async function fPoolAcceptAuthority(c, a) {
|
|
859
|
-
return
|
|
859
|
+
return writePolicy(c, fPolicyBaseAbi, a, "acceptAuthority", []);
|
|
860
860
|
}
|
|
861
|
-
// ─── the desk's controls (
|
|
862
|
-
/** Turn the mint / swap gates on or off (the authority, on the desk's
|
|
861
|
+
// ─── the desk's controls (PrivatePolicy; decisions 021, 044) ───────────────────────────────
|
|
862
|
+
/** Turn the mint / swap gates on or off (the authority, on the desk's policy). `burn` is never gated. */
|
|
863
863
|
export async function fPoolSetGates(c, a) {
|
|
864
|
-
return
|
|
864
|
+
return writePolicy(c, privatePolicyAbi, a, "setGates", [a.gateMint, a.gateSwap]);
|
|
865
865
|
}
|
|
866
866
|
/**
|
|
867
|
-
* Add to or remove from the pool's list, in one call (the authority, on the desk's
|
|
867
|
+
* Add to or remove from the pool's list, in one call (the authority, on the desk's policy). The list
|
|
868
868
|
* is keyed by the authority that granted it: a handover starts the buyer with an empty one.
|
|
869
869
|
*/
|
|
870
870
|
export async function fPoolSetAllowed(c, a) {
|
|
871
|
-
return
|
|
871
|
+
return writePolicy(c, privatePolicyAbi, a, "setAllowed", [a.who, a.allowed]);
|
|
872
872
|
}
|
|
873
873
|
/** Whether `who` is on the pool's list under its current authority (consulted only while a gate is on). */
|
|
874
|
-
export async function fPoolIsAllowed(c, poolId, who,
|
|
875
|
-
const address =
|
|
874
|
+
export async function fPoolIsAllowed(c, poolId, who, policy) {
|
|
875
|
+
const address = policy ?? (await fPoolPolicyOf(c, poolId));
|
|
876
876
|
return (await c.public.readContract({
|
|
877
877
|
address,
|
|
878
|
-
abi:
|
|
878
|
+
abi: privatePolicyAbi,
|
|
879
879
|
functionName: "isAllowed",
|
|
880
880
|
args: [poolId, who],
|
|
881
881
|
}));
|
|
@@ -914,16 +914,16 @@ export function fPoolOperatorOf(s) {
|
|
|
914
914
|
return s.operator === ZERO_ADDRESS ? s.authority : s.operator;
|
|
915
915
|
}
|
|
916
916
|
/**
|
|
917
|
-
* Propose the operator (the authority, on the desk's
|
|
917
|
+
* Propose the operator (the authority, on the desk's policy) — the hot key that runs the pool:
|
|
918
918
|
* `harvest`, `retire`, `regenerate`, `setLegs`. Two-step: the proposed address takes the role with
|
|
919
919
|
* {@link fPoolAcceptOperator}. The zero address clears at once — the role returns to the authority.
|
|
920
920
|
*/
|
|
921
921
|
export async function fPoolAppointOperator(c, a) {
|
|
922
|
-
return
|
|
922
|
+
return writePolicy(c, privatePolicyAbi, a, "appointOperator", [a.operator]);
|
|
923
923
|
}
|
|
924
924
|
/** The proposed operator takes the role. */
|
|
925
925
|
export async function fPoolAcceptOperator(c, a) {
|
|
926
|
-
return
|
|
926
|
+
return writePolicy(c, privatePolicyAbi, a, "acceptOperator", []);
|
|
927
927
|
}
|
|
928
928
|
/**
|
|
929
929
|
* The next generation's composition (operator; private pools only; ONLY while the pool is
|
|
@@ -989,7 +989,7 @@ export async function discoverFPools(c, opts = {}) {
|
|
|
989
989
|
weights: [...a.weights],
|
|
990
990
|
phi: a.phi,
|
|
991
991
|
kind: fPoolKindOf(a.kind),
|
|
992
|
-
|
|
992
|
+
policy: a.policy,
|
|
993
993
|
creator: a.creator,
|
|
994
994
|
block: l.blockNumber ?? 0n,
|
|
995
995
|
seeded: q0 !== undefined,
|
|
@@ -998,28 +998,28 @@ export async function discoverFPools(c, opts = {}) {
|
|
|
998
998
|
};
|
|
999
999
|
});
|
|
1000
1000
|
}
|
|
1001
|
-
/** The
|
|
1002
|
-
export async function
|
|
1003
|
-
const rd = (abi, functionName, args = []) => c.public.readContract({ address: s.
|
|
1004
|
-
const harvestCut = await rd(
|
|
1001
|
+
/** The policy's terms for one pool, by its kind. */
|
|
1002
|
+
export async function getFPoolRules(c, s, roles) {
|
|
1003
|
+
const rd = (abi, functionName, args = []) => c.public.readContract({ address: s.policy, abi, functionName, args });
|
|
1004
|
+
const harvestCut = await rd(fPolicyBaseAbi, "harvestCut");
|
|
1005
1005
|
switch (s.kind) {
|
|
1006
1006
|
case "pad": {
|
|
1007
1007
|
const [rung, creatorShare, protocolShare, burnPerRung, pot] = await Promise.all([
|
|
1008
|
-
rd(
|
|
1009
|
-
rd(
|
|
1010
|
-
rd(
|
|
1011
|
-
rd(
|
|
1008
|
+
rd(padPolicyAbi, "rung", [s.poolId]),
|
|
1009
|
+
rd(padPolicyAbi, "creatorShare"),
|
|
1010
|
+
rd(padPolicyAbi, "protocolShare"),
|
|
1011
|
+
rd(padPolicyAbi, "burnPerRung"),
|
|
1012
1012
|
fPoolDividendOf(c, s.poolId, DEAD_ADDRESS, s.gen),
|
|
1013
1013
|
]);
|
|
1014
|
-
const threshold = await rd(
|
|
1014
|
+
const threshold = await rd(padPolicyAbi, "threshold", [rung]);
|
|
1015
1015
|
return { kind: "pad", harvestCut, rung: Number(rung), threshold, pot, creatorShare, protocolShare, burnPerRung };
|
|
1016
1016
|
}
|
|
1017
1017
|
case "pol": {
|
|
1018
|
-
const [keepQuote, minQuoteAtSeed] = await Promise.all([rd(
|
|
1018
|
+
const [keepQuote, minQuoteAtSeed] = await Promise.all([rd(polPolicyAbi, "keepQuote"), rd(polPolicyAbi, "minQuoteAtSeed")]);
|
|
1019
1019
|
return { kind: "pol", harvestCut, keepQuote, minQuoteAtSeed };
|
|
1020
1020
|
}
|
|
1021
1021
|
case "public": {
|
|
1022
|
-
const curated = await rd(
|
|
1022
|
+
const curated = await rd(publicPolicyAbi, "curated");
|
|
1023
1023
|
return { kind: "public", harvestCut, curated };
|
|
1024
1024
|
}
|
|
1025
1025
|
case "private": {
|
|
@@ -1029,19 +1029,19 @@ export async function getFPoolPolicy(c, s, roles) {
|
|
|
1029
1029
|
}
|
|
1030
1030
|
}
|
|
1031
1031
|
/**
|
|
1032
|
-
* Every F pool `who` is the AUTHORITY of, across the four
|
|
1032
|
+
* Every F pool `who` is the AUTHORITY of, across the four policies — the policy page's list. Pools
|
|
1033
1033
|
* `who` created and handed over are not here (the buyer's page shows them); pools handed TO
|
|
1034
1034
|
* `who` are. `pools` may be passed (from the indexer, say) to skip the log scan.
|
|
1035
1035
|
*/
|
|
1036
1036
|
export async function fPoolsControlledBy(c, who, opts = {}) {
|
|
1037
1037
|
const pools = opts.pools ?? (await discoverFPools(c, { fromBlock: opts.fromBlock }));
|
|
1038
|
-
const authorities = await Promise.all(pools.map((p) => c.public.readContract({ address: p.
|
|
1038
|
+
const authorities = await Promise.all(pools.map((p) => c.public.readContract({ address: p.policy, abi: fPolicyBaseAbi, functionName: "authority", args: [p.poolId] })));
|
|
1039
1039
|
const mine = pools.filter((_, i) => authorities[i].toLowerCase() === who.toLowerCase());
|
|
1040
1040
|
return Promise.all(mine.map(async (pool) => {
|
|
1041
1041
|
const state = await getFPool(c, pool.poolId);
|
|
1042
1042
|
const roles = await getFPoolRoles(c, pool.poolId, state);
|
|
1043
|
-
const
|
|
1044
|
-
return { pool, roles, state,
|
|
1043
|
+
const rules = await getFPoolRules(c, state, roles);
|
|
1044
|
+
return { pool, roles, state, rules };
|
|
1045
1045
|
}));
|
|
1046
1046
|
}
|
|
1047
1047
|
/**
|