@logswap/sdk 0.5.68 → 0.5.70
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 +11 -7
- package/dist/admin.js +16 -8
- package/dist/client.d.ts +1 -1
- package/dist/client.js +3 -1
- package/dist/fpool.d.ts +93 -94
- package/dist/fpool.js +161 -20
- package/dist/generated.d.ts +110 -349
- package/dist/generated.js +83 -240
- package/package.json +1 -1
- package/src/admin.ts +25 -10
- package/src/client.ts +3 -1
- package/src/fpool.ts +218 -27
- package/src/generated.ts +83 -240
package/src/fpool.ts
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* `addresses.router`.
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
|
-
import { encodeAbiParameters, encodeFunctionData, keccak256, toFunctionSelector, type Address, type Hash, type Hex } from "viem";
|
|
33
|
+
import { decodeAbiParameters, encodeAbiParameters, encodeFunctionData, erc20Abi, keccak256, toFunctionSelector, type Address, type Hash, type Hex } from "viem";
|
|
34
34
|
import { fPoolManagerAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, policyRegistryAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
|
|
35
35
|
|
|
36
36
|
/**
|
|
@@ -42,8 +42,8 @@ import { fPoolManagerAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, policyRe
|
|
|
42
42
|
*/
|
|
43
43
|
export { fPoolManagerAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi };
|
|
44
44
|
/**
|
|
45
|
-
* What every protocol policy shares (`FPolicyBase`): the roles and their handover
|
|
46
|
-
* `maxHarvest
|
|
45
|
+
* What every protocol policy shares (`FPolicyBase`): the roles and their handover and the
|
|
46
|
+
* `maxHarvest` readout (a harvest has no cut, decisions 056). `polPolicyAbi` is a superset of it and carries nothing that collides, so it stands
|
|
47
47
|
* in for the base — a call through it to any of the four policies decodes the base's functions.
|
|
48
48
|
*/
|
|
49
49
|
export const fPolicyBaseAbi = polPolicyAbi;
|
|
@@ -1079,7 +1079,7 @@ export async function fPoolIdOf(c: LogswapClient, a: Omit<FPoolCreateArgs, "acco
|
|
|
1079
1079
|
/**
|
|
1080
1080
|
* Rebuild a live pool's KEY from its id: the `FInitialize` log carries every field but the salt,
|
|
1081
1081
|
* which is taken from `opts.salt` (zero by default — every pool the SDK's create flow makes
|
|
1082
|
-
* without naming one). The result is checked against the id, so a wrong salt throws rather than
|
|
1082
|
+
* without naming one; a pad's carries its split, so it is rebuilt from the policy's record with nonce 0 — pass `opts.salt` for another nonce). The result is checked against the id, so a wrong salt throws rather than
|
|
1083
1083
|
* returning a key that names another pool. What {@link fPoolMigrate} needs when handed an id.
|
|
1084
1084
|
*/
|
|
1085
1085
|
export async function fPoolKeyOfPool(c: LogswapClient, poolId: Hex, opts: { salt?: Hex; fromBlock?: bigint } = {}): Promise<FPoolKey> {
|
|
@@ -1104,6 +1104,16 @@ export async function fPoolKeyOfPool(c: LogswapClient, poolId: Hex, opts: { salt
|
|
|
1104
1104
|
creator: a.creator,
|
|
1105
1105
|
salt: opts.salt ?? ZERO_SALT,
|
|
1106
1106
|
};
|
|
1107
|
+
if (fPoolIdOfKey(key).toLowerCase() !== poolId.toLowerCase() && opts.salt === undefined) {
|
|
1108
|
+
// a pad's salt carries its split (decisions 056): rebuild it from the policy's record with the default nonce
|
|
1109
|
+
try {
|
|
1110
|
+
const [creatorShare, burnPerRung] = (await c.public.readContract({ address: a.policy, abi: padPolicyAbi, functionName: "splitOf", args: [poolId] } as never)) as readonly [bigint, bigint, bigint];
|
|
1111
|
+
const padKey = { ...key, salt: padSalt({ creatorShare, burnPerRung }) };
|
|
1112
|
+
if (fPoolIdOfKey(padKey).toLowerCase() === poolId.toLowerCase()) return padKey;
|
|
1113
|
+
} catch {
|
|
1114
|
+
/* not a pad: fall through to the error */
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1107
1117
|
if (fPoolIdOfKey(key).toLowerCase() !== poolId.toLowerCase()) {
|
|
1108
1118
|
throw new Error(`logswap: F pool ${poolId} was not born with salt ${key.salt} — pass its salt, or its whole key`);
|
|
1109
1119
|
}
|
|
@@ -1252,6 +1262,29 @@ export const DEAD_ADDRESS: Address = "0x000000000000000000000000000000000000dEaD
|
|
|
1252
1262
|
/** The manager's `MIN_SHARES`: the seed mints this much to 0xdead on every pool, the rest to the seeder — or, on a pad, to 0xdead too. */
|
|
1253
1263
|
export const F_MIN_SHARES = 1000n;
|
|
1254
1264
|
|
|
1265
|
+
/**
|
|
1266
|
+
* One genesis transaction: a swap the creator sends right after the seed, inside the launch's
|
|
1267
|
+
* `multicall`. A `buy` spends `amountIn` of quote for leg `j` (an index into `bases` AS GIVEN); a
|
|
1268
|
+
* `sell` spends `amountIn` of that leg for quote. The creator pays and is paid — the manager settles
|
|
1269
|
+
* to its sender — so a `recipient` is paid by an ERC-20 transfer of the row's output
|
|
1270
|
+
* ({@link fPoolGenesisTransfers}); without one the output stays with the creator.
|
|
1271
|
+
*/
|
|
1272
|
+
export interface FPoolGenesisRow {
|
|
1273
|
+
side: "buy" | "sell";
|
|
1274
|
+
j: number;
|
|
1275
|
+
amountIn: bigint;
|
|
1276
|
+
/** Defaults to 0. With a `recipient`, {@link fPoolLaunch} pins it to the simulated output, which is what the transfer pays. */
|
|
1277
|
+
minOut?: bigint;
|
|
1278
|
+
recipient?: Address;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
/** An ERC-20 transfer owed to a genesis recipient: one per (token, recipient), rows summed. */
|
|
1282
|
+
export interface FPoolGenesisTransfer {
|
|
1283
|
+
token: Address;
|
|
1284
|
+
to: Address;
|
|
1285
|
+
amount: bigint;
|
|
1286
|
+
}
|
|
1287
|
+
|
|
1255
1288
|
export interface FPoolLaunchArgs extends Omit<FPoolCreateArgs, "account"> {
|
|
1256
1289
|
L0: bigint;
|
|
1257
1290
|
/** Quote the seed pulls. A pad seeds at 0 — pure float, a resting ask, nothing raised. */
|
|
@@ -1264,6 +1297,18 @@ export interface FPoolLaunchArgs extends Omit<FPoolCreateArgs, "account"> {
|
|
|
1264
1297
|
* this buy — they are one transaction — so `minOut` is safe at its default of 0.
|
|
1265
1298
|
*/
|
|
1266
1299
|
openBuy?: { j: number; amountIn: bigint; minOut?: bigint };
|
|
1300
|
+
/**
|
|
1301
|
+
* The genesis transactions: an ordered list of swaps right after the seed, each with an optional
|
|
1302
|
+
* recipient ({@link FPoolGenesisRow}). The same batch as `openBuy`, which stays as the one-buy
|
|
1303
|
+
* case and runs first when both are given. See `specs/f-pools/opening.md`.
|
|
1304
|
+
*/
|
|
1305
|
+
openBatch?: FPoolGenesisRow[];
|
|
1306
|
+
/**
|
|
1307
|
+
* How a row's recipient is paid. `auto` (default): in the launch's own transaction when the
|
|
1308
|
+
* wallet batches atomically (EIP-5792), else left to {@link fPoolSendGenesisTransfers};
|
|
1309
|
+
* `followup`: always left to it. Ignored when no row names a recipient.
|
|
1310
|
+
*/
|
|
1311
|
+
deliver?: "auto" | "followup";
|
|
1267
1312
|
/** The pool's label (≤ 31 bytes of UTF-8) — the policy's word (049), written right after the batch by {@link fPoolLaunch}; not in the batch. */
|
|
1268
1313
|
name?: string;
|
|
1269
1314
|
/**
|
|
@@ -1301,10 +1346,10 @@ export function fPoolLaunchCalls(
|
|
|
1301
1346
|
calls.push(enc("seed", [poolId, a.L0, companions[1]!, a.Q0]));
|
|
1302
1347
|
// gen 0 by construction: a launch is the pool's FIRST seed — a relaunch is `fPoolRelaunch`.
|
|
1303
1348
|
// No transfer to 0xdead: on a pad `seed` mints every share there itself.
|
|
1304
|
-
|
|
1305
|
-
const j = bases.indexOf(a.bases[
|
|
1306
|
-
if (j < 0) throw new Error(`logswap:
|
|
1307
|
-
calls.push(enc("swapQuoteIn", [poolId, BigInt(j),
|
|
1349
|
+
for (const row of fPoolGenesisRows(a)) {
|
|
1350
|
+
const j = bases.indexOf(a.bases[row.j]!);
|
|
1351
|
+
if (j < 0) throw new Error(`logswap: genesis row j = ${row.j} is not a leg`);
|
|
1352
|
+
calls.push(enc(row.side === "buy" ? "swapQuoteIn" : "swapBaseIn", [poolId, BigInt(j), row.amountIn, row.minOut ?? 0n, a.account]));
|
|
1308
1353
|
}
|
|
1309
1354
|
// the name, the desk's gates and its list are the POLICY's, not the
|
|
1310
1355
|
// manager's: they cannot ride in this batch — `fPoolLaunch` and `fPoolDeskOpening` send them
|
|
@@ -1313,6 +1358,87 @@ export function fPoolLaunchCalls(
|
|
|
1313
1358
|
return calls;
|
|
1314
1359
|
}
|
|
1315
1360
|
|
|
1361
|
+
/** The genesis rows in the order they run: `openBuy` first when given, then `openBatch`. Legs as given. */
|
|
1362
|
+
export function fPoolGenesisRows(a: Pick<FPoolLaunchArgs, "openBuy" | "openBatch">): FPoolGenesisRow[] {
|
|
1363
|
+
return [...(a.openBuy ? [{ side: "buy" as const, ...a.openBuy }] : []), ...(a.openBatch ?? [])];
|
|
1364
|
+
}
|
|
1365
|
+
|
|
1366
|
+
/**
|
|
1367
|
+
* What each genesis row returned, read by simulating the launch's `multicall` on the chain — the
|
|
1368
|
+
* contract's own rounding, no re-implementation. Exact at send time: the pool is new, and nothing
|
|
1369
|
+
* can trade between the seed and the rows. Needs the creator's funds and allowances, as the launch
|
|
1370
|
+
* does. One output per row, in {@link fPoolGenesisRows} order: base for a buy, quote for a sell.
|
|
1371
|
+
*/
|
|
1372
|
+
export async function fPoolGenesisOutputs(
|
|
1373
|
+
c: LogswapClient,
|
|
1374
|
+
poolId: Hex,
|
|
1375
|
+
a: FPoolLaunchArgs & ({ r0: bigint[] } | { x0: bigint[] }),
|
|
1376
|
+
): Promise<bigint[]> {
|
|
1377
|
+
const rows = fPoolGenesisRows(a);
|
|
1378
|
+
if (rows.length === 0) return [];
|
|
1379
|
+
const calls = fPoolLaunchCalls(poolId, a);
|
|
1380
|
+
const { result } = await c.public.simulateContract({
|
|
1381
|
+
address: c.addresses.fPoolManager!,
|
|
1382
|
+
abi: fPoolManagerAbi,
|
|
1383
|
+
functionName: "multicall",
|
|
1384
|
+
args: [calls],
|
|
1385
|
+
account: signerFor(c, a.account),
|
|
1386
|
+
} as never);
|
|
1387
|
+
const results = result as readonly Hex[];
|
|
1388
|
+
const first = (a.initialized ? 0 : 1) + 1; // [initialize] · seed · rows
|
|
1389
|
+
return rows.map((_, i) => decodeAbiParameters([{ type: "uint256" }], results[first + i]!)[0] as bigint);
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
/**
|
|
1393
|
+
* The transfers that pay the recipients: each row's output (`outs`, aligned with
|
|
1394
|
+
* {@link fPoolGenesisRows}) to its `recipient`, summed per (token, recipient), zero amounts dropped.
|
|
1395
|
+
* The token is the leg's base for a buy and the quote for a sell. Pure.
|
|
1396
|
+
*/
|
|
1397
|
+
export function fPoolGenesisTransfers(
|
|
1398
|
+
a: Pick<FPoolLaunchArgs, "quote" | "bases" | "openBuy" | "openBatch">,
|
|
1399
|
+
outs: bigint[],
|
|
1400
|
+
): FPoolGenesisTransfer[] {
|
|
1401
|
+
const out = new Map<string, FPoolGenesisTransfer>();
|
|
1402
|
+
fPoolGenesisRows(a).forEach((row, i) => {
|
|
1403
|
+
if (!row.recipient || !outs[i]) return;
|
|
1404
|
+
const token = row.side === "buy" ? a.bases[row.j]! : a.quote;
|
|
1405
|
+
const k = `${token.toLowerCase()}:${row.recipient.toLowerCase()}`;
|
|
1406
|
+
const t = out.get(k);
|
|
1407
|
+
if (t) t.amount += outs[i]!;
|
|
1408
|
+
else out.set(k, { token, to: row.recipient, amount: outs[i]! });
|
|
1409
|
+
});
|
|
1410
|
+
return [...out.values()];
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
/** Pay genesis recipients with plain ERC-20 transfers, one transaction each, in order. For a launch that did not deliver itself. */
|
|
1414
|
+
export async function fPoolSendGenesisTransfers(c: LogswapClient, a: { transfers: FPoolGenesisTransfer[]; account: Address }): Promise<Hash[]> {
|
|
1415
|
+
const wallet = requireWallet(c);
|
|
1416
|
+
const hashes: Hash[] = [];
|
|
1417
|
+
for (const t of a.transfers) {
|
|
1418
|
+
const { request } = await c.public.simulateContract({
|
|
1419
|
+
address: t.token,
|
|
1420
|
+
abi: erc20Abi,
|
|
1421
|
+
functionName: "transfer",
|
|
1422
|
+
args: [t.to, t.amount],
|
|
1423
|
+
account: signerFor(c, a.account),
|
|
1424
|
+
} as never);
|
|
1425
|
+
hashes.push(await wallet.writeContract(request as never));
|
|
1426
|
+
}
|
|
1427
|
+
return hashes;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
/** Whether the wallet runs a batch of calls atomically (EIP-5792 `atomic` capability), on the client's chain. A wallet without it, or one that errors, says no. */
|
|
1431
|
+
export async function fPoolWalletBatchesAtomically(c: LogswapClient, account: Address): Promise<boolean> {
|
|
1432
|
+
try {
|
|
1433
|
+
const wallet = requireWallet(c);
|
|
1434
|
+
const chainId = wallet.chain?.id;
|
|
1435
|
+
const caps = (await wallet.getCapabilities({ account, chainId })) as { atomic?: { status?: string } };
|
|
1436
|
+
return caps?.atomic?.status === "supported" || caps?.atomic?.status === "ready";
|
|
1437
|
+
} catch {
|
|
1438
|
+
return false;
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
|
|
1316
1442
|
/**
|
|
1317
1443
|
* The desk's opening posture, on its policy: gated minting, the creator a
|
|
1318
1444
|
* minter. No appointment: the authority is the operator until one is appointed.
|
|
@@ -1346,13 +1472,42 @@ export async function fPoolDeskOpening(c: LogswapClient, a: { poolId: Hex; accou
|
|
|
1346
1472
|
export async function fPoolLaunch(
|
|
1347
1473
|
c: LogswapClient,
|
|
1348
1474
|
a: FPoolLaunchArgs & ({ r0: bigint[] } | { x0: bigint[] }),
|
|
1349
|
-
): Promise<{ hash: Hash; poolId: Hex }> {
|
|
1475
|
+
): Promise<{ hash: Hash; poolId: Hex; transfers: FPoolGenesisTransfer[]; delivered: boolean }> {
|
|
1350
1476
|
const poolId = await fPoolIdOf(c, a);
|
|
1351
1477
|
const policy = a.policy ?? fPoolPolicyFor(c, a.kind);
|
|
1352
|
-
|
|
1353
|
-
|
|
1478
|
+
let args = { ...a, policy };
|
|
1479
|
+
// With recipients, each row's minOut is pinned to its simulated output and the transfers pay
|
|
1480
|
+
// exactly that: a row that returns less reverts the launch, a wei of surplus stays with the creator.
|
|
1481
|
+
let transfers: FPoolGenesisTransfer[] = [];
|
|
1482
|
+
const rows = fPoolGenesisRows(a);
|
|
1483
|
+
if (rows.some((r) => r.recipient)) {
|
|
1484
|
+
const outs = await fPoolGenesisOutputs(c, poolId, args);
|
|
1485
|
+
args = { ...args, openBuy: undefined, openBatch: rows.map((r, i) => ({ ...r, minOut: outs[i]! })) };
|
|
1486
|
+
transfers = fPoolGenesisTransfers(args, outs);
|
|
1487
|
+
}
|
|
1488
|
+
const calls = fPoolLaunchCalls(poolId, args);
|
|
1489
|
+
let hash: Hash;
|
|
1490
|
+
let delivered = transfers.length === 0;
|
|
1491
|
+
if (transfers.length > 0 && a.deliver !== "followup" && (await fPoolWalletBatchesAtomically(c, a.account))) {
|
|
1492
|
+
const wallet = requireWallet(c);
|
|
1493
|
+
const { id } = await wallet.sendCalls({
|
|
1494
|
+
account: signerFor(c, a.account),
|
|
1495
|
+
forceAtomic: true,
|
|
1496
|
+
calls: [
|
|
1497
|
+
{ to: c.addresses.fPoolManager!, data: encodeFunctionData({ abi: fPoolManagerAbi, functionName: "multicall", args: [calls] } as never) },
|
|
1498
|
+
...transfers.map((t) => ({ to: t.token, data: encodeFunctionData({ abi: erc20Abi, functionName: "transfer", args: [t.to, t.amount] }) })),
|
|
1499
|
+
],
|
|
1500
|
+
} as never);
|
|
1501
|
+
const status = await wallet.waitForCallsStatus({ id });
|
|
1502
|
+
const receipt = status.receipts?.[0];
|
|
1503
|
+
if (status.status !== "success" || !receipt) throw new Error("logswap: the launch batch did not succeed — nothing was created");
|
|
1504
|
+
hash = receipt.transactionHash;
|
|
1505
|
+
delivered = true;
|
|
1506
|
+
} else {
|
|
1507
|
+
hash = await writeFPool0(c, "multicall", [calls], a.account);
|
|
1508
|
+
}
|
|
1354
1509
|
if (a.name) await fPoolSetName(c, { poolId, name: a.name, account: a.account, policy });
|
|
1355
|
-
return { hash, poolId };
|
|
1510
|
+
return { hash, poolId, transfers, delivered };
|
|
1356
1511
|
}
|
|
1357
1512
|
|
|
1358
1513
|
// ─── the roles, on the policy ─────────────────────────────────────────────
|
|
@@ -1640,7 +1795,6 @@ export interface FPoolControlled {
|
|
|
1640
1795
|
export type FPoolRules =
|
|
1641
1796
|
| {
|
|
1642
1797
|
kind: "pad";
|
|
1643
|
-
harvestCut: bigint;
|
|
1644
1798
|
/** The pad's graduation count: the pool's generation (F version 21 — `PadPolicy.rung` is gone). */
|
|
1645
1799
|
gen: number;
|
|
1646
1800
|
/** @deprecated Equal to {@link gen} since F version 21, kept for callers; read `gen`. */
|
|
@@ -1648,43 +1802,81 @@ export type FPoolRules =
|
|
|
1648
1802
|
/** The pot the next graduation needs: `PadPolicy.threshold(gen)`. */
|
|
1649
1803
|
threshold: bigint;
|
|
1650
1804
|
pot: bigint;
|
|
1805
|
+
/** This pad's split, recorded at its birth from the key's salt and never changed (decisions 056): the creator's cut of the pot, the protocol's, and the burn per rung. The rest of the pot is bought in. */
|
|
1651
1806
|
creatorShare: bigint;
|
|
1652
1807
|
protocolShare: bigint;
|
|
1653
1808
|
burnPerRung: bigint;
|
|
1809
|
+
/** The ranges the collector's policy holds NOW for the pads born after this read: what a new creator may choose. */
|
|
1810
|
+
ranges: PadRanges;
|
|
1654
1811
|
}
|
|
1655
|
-
| { kind: "pol";
|
|
1656
|
-
| { kind: "public";
|
|
1657
|
-
| { kind: "private";
|
|
1812
|
+
| { kind: "pol"; keepQuote: bigint; minQuoteAtSeed: bigint }
|
|
1813
|
+
| { kind: "public"; curated: boolean }
|
|
1814
|
+
| { kind: "private"; gateMint: boolean; gateSwap: boolean; operator: Address };
|
|
1815
|
+
|
|
1816
|
+
/** The collector's ranges on a pad's creator choices (`PadPolicy`, decisions 056), WAD fractions: of the pot, and of every reserve per rung. */
|
|
1817
|
+
export interface PadRanges {
|
|
1818
|
+
/** The protocol's share of the pot, recorded into each pad at birth. */
|
|
1819
|
+
protocolShare: bigint;
|
|
1820
|
+
creatorShareMin: bigint;
|
|
1821
|
+
creatorShareMax: bigint;
|
|
1822
|
+
burnMin: bigint;
|
|
1823
|
+
burnMax: bigint;
|
|
1824
|
+
}
|
|
1825
|
+
|
|
1826
|
+
const MAX_U64 = (1n << 64n) - 1n;
|
|
1827
|
+
const MAX_U128 = (1n << 128n) - 1n;
|
|
1828
|
+
|
|
1829
|
+
/**
|
|
1830
|
+
* The salt that carries a pad's split (`PadPolicy.pack`, decisions 056): `creatorShare` in the top 64 bits, `burnPerRung` in
|
|
1831
|
+
* the next 64 (WAD fractions), a nonce in the low 128 that tells two otherwise identical pads apart. It is part of the pool's
|
|
1832
|
+
* identity, so it is chosen at launch (`FPoolLaunchArgs.salt`) and never changes; the policy refuses a split outside its ranges.
|
|
1833
|
+
*/
|
|
1834
|
+
export function padSalt(s: { creatorShare: bigint; burnPerRung: bigint; nonce?: bigint }): Hex {
|
|
1835
|
+
const nonce = s.nonce ?? 0n;
|
|
1836
|
+
if (s.creatorShare < 0n || s.creatorShare > MAX_U64 || s.burnPerRung < 0n || s.burnPerRung > MAX_U64) throw new Error("logswap: a pad's split is a WAD fraction that fits 64 bits");
|
|
1837
|
+
if (nonce < 0n || nonce > MAX_U128) throw new Error("logswap: a pad salt's nonce fits 128 bits");
|
|
1838
|
+
return `0x${((s.creatorShare << 192n) | (s.burnPerRung << 128n) | nonce).toString(16).padStart(64, "0")}` as Hex;
|
|
1839
|
+
}
|
|
1840
|
+
|
|
1841
|
+
/** The inverse of {@link padSalt}. */
|
|
1842
|
+
export function padSplitOfSalt(salt: Hex): { creatorShare: bigint; burnPerRung: bigint; nonce: bigint } {
|
|
1843
|
+
const v = BigInt(salt);
|
|
1844
|
+
return { creatorShare: v >> 192n, burnPerRung: (v >> 128n) & MAX_U64, nonce: v & MAX_U128 };
|
|
1845
|
+
}
|
|
1658
1846
|
|
|
1659
1847
|
/** The policy's terms for one pool, by its kind. */
|
|
1660
1848
|
export async function getFPoolRules(c: LogswapClient, s: Pick<FPoolState, "poolId" | "policy" | "kind" | "gen">, roles?: FPoolRoles): Promise<FPoolRules> {
|
|
1661
1849
|
const rd = <T>(abi: readonly unknown[], functionName: string, args: readonly unknown[] = []) =>
|
|
1662
1850
|
c.public.readContract({ address: s.policy, abi, functionName, args } as never) as Promise<T>;
|
|
1663
|
-
const harvestCut = await rd<bigint>(fPolicyBaseAbi, "harvestCut");
|
|
1664
1851
|
switch (s.kind) {
|
|
1665
1852
|
case "pad": {
|
|
1666
1853
|
// the rung is the manager's generation (F version 21): a move carries it, nothing to ask the policy
|
|
1667
1854
|
const gen = s.gen;
|
|
1668
|
-
const [
|
|
1669
|
-
rd<bigint>(padPolicyAbi, "
|
|
1670
|
-
rd<bigint>(padPolicyAbi, "protocolShare"),
|
|
1671
|
-
rd<bigint>(padPolicyAbi, "burnPerRung"),
|
|
1855
|
+
const [split, pot, threshold, protocolNow, creatorShareMin, creatorShareMax, burnMin, burnMax] = await Promise.all([
|
|
1856
|
+
rd<readonly [bigint, bigint, bigint]>(padPolicyAbi, "splitOf", [s.poolId]),
|
|
1672
1857
|
fPoolDividendOf(c, s.poolId, DEAD_ADDRESS, gen),
|
|
1673
1858
|
rd<bigint>(padPolicyAbi, "threshold", [BigInt(gen)]),
|
|
1859
|
+
rd<bigint>(padPolicyAbi, "protocolShare"),
|
|
1860
|
+
rd<bigint>(padPolicyAbi, "creatorShareMin"),
|
|
1861
|
+
rd<bigint>(padPolicyAbi, "creatorShareMax"),
|
|
1862
|
+
rd<bigint>(padPolicyAbi, "burnMin"),
|
|
1863
|
+
rd<bigint>(padPolicyAbi, "burnMax"),
|
|
1674
1864
|
]);
|
|
1675
|
-
|
|
1865
|
+
const [creatorShare, burnPerRung, protocolShare] = split;
|
|
1866
|
+
const ranges: PadRanges = { protocolShare: protocolNow, creatorShareMin, creatorShareMax, burnMin, burnMax };
|
|
1867
|
+
return { kind: "pad", gen, rung: gen, threshold, pot, creatorShare, protocolShare, burnPerRung, ranges };
|
|
1676
1868
|
}
|
|
1677
1869
|
case "pol": {
|
|
1678
1870
|
const [keepQuote, minQuoteAtSeed] = await Promise.all([rd<bigint>(polPolicyAbi, "keepQuote"), rd<bigint>(polPolicyAbi, "minQuoteAtSeed")]);
|
|
1679
|
-
return { kind: "pol",
|
|
1871
|
+
return { kind: "pol", keepQuote, minQuoteAtSeed };
|
|
1680
1872
|
}
|
|
1681
1873
|
case "public": {
|
|
1682
1874
|
const curated = await rd<boolean>(publicPolicyAbi, "curated");
|
|
1683
|
-
return { kind: "public",
|
|
1875
|
+
return { kind: "public", curated };
|
|
1684
1876
|
}
|
|
1685
1877
|
case "private": {
|
|
1686
1878
|
const r = roles ?? (await getFPoolRoles(c, s.poolId, s));
|
|
1687
|
-
return { kind: "private",
|
|
1879
|
+
return { kind: "private", gateMint: r.gateMint, gateSwap: r.gateSwap, operator: fPoolOperatorOf(r) };
|
|
1688
1880
|
}
|
|
1689
1881
|
}
|
|
1690
1882
|
}
|
|
@@ -1753,8 +1945,7 @@ export async function fPoolShareHolders(
|
|
|
1753
1945
|
}
|
|
1754
1946
|
|
|
1755
1947
|
/**
|
|
1756
|
-
* What a policy answers `onRegenerate` with
|
|
1757
|
-
* `IFPolicy.Terms`. `carried` is F version 21's fifth word — the holder the next generation
|
|
1948
|
+
* What a policy answers `onRegenerate` with: `IFPolicy.Terms`. `carried` is F version 21's fifth word — the holder the next generation
|
|
1758
1949
|
* carries beside the dead shares; the reply is exactly 160 bytes.
|
|
1759
1950
|
*/
|
|
1760
1951
|
export interface FPolicyTerms {
|