@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/admin.d.ts +72 -14
- package/dist/admin.js +116 -19
- package/dist/client.d.ts +7 -1
- package/dist/client.js +8 -2
- package/dist/fpool.d.ts +234 -46
- package/dist/fpool.js +122 -66
- package/dist/generated.d.ts +1328 -288
- package/dist/generated.js +866 -158
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/src/admin.ts +139 -19
- package/src/client.ts +14 -2
- package/src/fpool.ts +171 -105
- package/src/generated.ts +872 -160
- package/src/index.ts +1 -1
package/dist/fpool.js
CHANGED
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
* `addresses.router`.
|
|
31
31
|
*/
|
|
32
32
|
import { encodeFunctionData, toFunctionSelector } from "viem";
|
|
33
|
-
import { fPoolManagerAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, privatePolicyAbi, publicPolicyAbi } from "./generated.js";
|
|
33
|
+
import { fPoolManagerAbi, logswapRouterAbi, padPolicyAbi, polPolicyAbi, policyRegistryAbi, 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
|
|
@@ -61,7 +61,8 @@ 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
|
|
64
|
+
// to be a dozen getters a single read. No role in it since F version 15, no kind and no name
|
|
65
|
+
// since 18: those are the policy's.
|
|
65
66
|
const p = await rd("getPool", [poolId]);
|
|
66
67
|
// A pool that was never created reads as an all-zero struct rather than reverting, so the
|
|
67
68
|
// absence has to be named here or every caller mistakes "no such pool" for "a pool holding
|
|
@@ -72,12 +73,14 @@ export async function getFPool(c, poolId) {
|
|
|
72
73
|
throw new Error(`logswap: no F pool with id ${poolId}`);
|
|
73
74
|
const n = Number(p.n);
|
|
74
75
|
const idx = Array.from({ length: n }, (_, i) => BigInt(i));
|
|
75
|
-
const [theta, compositeX, legs] = await Promise.all([
|
|
76
|
+
const [theta, compositeX, legs, kind, name] = await Promise.all([
|
|
76
77
|
// before the seed there is no L and no floor: θ is X by convention (the manager says so since
|
|
77
78
|
// bd3dd87's successor; older deployments revert with DivWadFailed, so do not ask them)
|
|
78
79
|
p.L > 0n ? rd("theta", [poolId]) : rd("compositeX", [poolId]),
|
|
79
80
|
rd("compositeX", [poolId]),
|
|
80
81
|
Promise.all(idx.map((i) => rd("legOf", [poolId, i]))),
|
|
82
|
+
fPoolKindOfPolicy(c, p.policy),
|
|
83
|
+
fPoolNameOf(c, poolId, p.policy),
|
|
81
84
|
]);
|
|
82
85
|
const bases = legs.map((l) => l[0]);
|
|
83
86
|
const weights = legs.map((l) => l[1]);
|
|
@@ -100,25 +103,46 @@ export async function getFPool(c, poolId) {
|
|
|
100
103
|
bigSigma,
|
|
101
104
|
policy,
|
|
102
105
|
asks: Number(p.asks),
|
|
103
|
-
name
|
|
106
|
+
name,
|
|
104
107
|
restructureBlock: Number(restructureBlock),
|
|
105
|
-
kind
|
|
108
|
+
kind,
|
|
106
109
|
seeded,
|
|
107
110
|
gen: Number(gen),
|
|
108
111
|
totalSupply,
|
|
109
112
|
reserves,
|
|
110
113
|
};
|
|
111
114
|
}
|
|
112
|
-
/** The key's enum values. */
|
|
113
|
-
export const F_KIND = { public: 0, private: 1, pol: 2, pad: 3 };
|
|
114
115
|
const F_KIND_NAMES = ["public", "private", "pol", "pad"];
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
116
|
+
/** The policy's birth-time declaration that the seed's shares are the pool's (a pad's), in `asks`. */
|
|
117
|
+
export const SEED_TO_DEAD = 4;
|
|
118
|
+
const kindCache = new Map();
|
|
119
|
+
/**
|
|
120
|
+
* What a policy IS — its `kind()` tag, read once per policy address and cached for the client's
|
|
121
|
+
* chain: a pool's kind is its policy's word (decisions 049), never the manager's. An unknown tag
|
|
122
|
+
* (a policy that is not one of the protocol's four shapes) throws; the app has no screen for it.
|
|
123
|
+
*/
|
|
124
|
+
export function fPoolKindOfPolicy(c, policy) {
|
|
125
|
+
const key = `${c.public.chain?.id ?? 0}:${policy.toLowerCase()}`;
|
|
126
|
+
let hit = kindCache.get(key);
|
|
127
|
+
if (!hit) {
|
|
128
|
+
hit = c.public.readContract({ address: policy, abi: fPolicyBaseAbi, functionName: "kind" }).then((word) => {
|
|
129
|
+
const tag = bytes32ToText(word);
|
|
130
|
+
if (!F_KIND_NAMES.includes(tag))
|
|
131
|
+
throw new Error(`logswap: policy ${policy} says it is "${tag}", which is no kind this SDK knows`);
|
|
132
|
+
return tag;
|
|
133
|
+
});
|
|
134
|
+
kindCache.set(key, hit);
|
|
135
|
+
hit.catch(() => kindCache.delete(key)); // a failed read is not a fact
|
|
136
|
+
}
|
|
137
|
+
return hit;
|
|
120
138
|
}
|
|
121
|
-
/** The
|
|
139
|
+
/** The pool's label, as its policy holds it (decisions 049). "" when unnamed. */
|
|
140
|
+
export async function fPoolNameOf(c, poolId, policy) {
|
|
141
|
+
const p = policy ?? (await fPoolPolicyOf(c, poolId));
|
|
142
|
+
const word = (await c.public.readContract({ address: p, abi: fPolicyBaseAbi, functionName: "nameOf", args: [poolId] }));
|
|
143
|
+
return bytes32ToText(word);
|
|
144
|
+
}
|
|
145
|
+
/** The deployment's policy for a kind (decisions 044, 049): the protocol's policy that IS that kind. */
|
|
122
146
|
export function fPoolPolicyFor(c, kind) {
|
|
123
147
|
const a = c.addresses;
|
|
124
148
|
const policy = kind === "public" ? a.publicPolicy : kind === "private" ? a.privatePolicy : kind === "pol" ? a.polPolicy : a.padPolicy;
|
|
@@ -541,8 +565,8 @@ export var FPoolQuoteKind;
|
|
|
541
565
|
export async function fPoolQuoteSwap(c, a) {
|
|
542
566
|
try {
|
|
543
567
|
await c.public.simulateContract({
|
|
544
|
-
address: c.addresses.
|
|
545
|
-
abi:
|
|
568
|
+
address: c.addresses.router,
|
|
569
|
+
abi: logswapRouterAbi,
|
|
546
570
|
functionName: "quoteSwap",
|
|
547
571
|
// the taker matters only on a gated pool: the connected account, or the zero address
|
|
548
572
|
args: [a.poolId, a.kind, BigInt(a.j), BigInt(a.k ?? 0), a.amountIn, a.taker ?? c.wallet?.account?.address ?? ZERO_ADDRESS],
|
|
@@ -606,7 +630,7 @@ export function sortFPoolLegs(bases, ...companions) {
|
|
|
606
630
|
const idx = bases.map((_, i) => i).sort((a, b) => (bases[a].toLowerCase() < bases[b].toLowerCase() ? -1 : 1));
|
|
607
631
|
return { bases: idx.map((i) => bases[i]), companions: companions.map((arr) => idx.map((i) => arr[i])) };
|
|
608
632
|
}
|
|
609
|
-
/** The key as the manager hashes it: legs sorted, the kind's policy filled in when none is named. */
|
|
633
|
+
/** The key as the manager hashes it: legs sorted, the kind's policy filled in when none is named; no kind in it (049). */
|
|
610
634
|
export function fPoolKeyOf(c, a) {
|
|
611
635
|
const { bases, companions } = sortFPoolLegs(a.bases, a.weights);
|
|
612
636
|
return {
|
|
@@ -614,7 +638,6 @@ export function fPoolKeyOf(c, a) {
|
|
|
614
638
|
bases,
|
|
615
639
|
weights: companions[0],
|
|
616
640
|
phi: a.phi,
|
|
617
|
-
kind: F_KIND[a.kind],
|
|
618
641
|
policy: a.policy ?? fPoolPolicyFor(c, a.kind),
|
|
619
642
|
creator: a.creator,
|
|
620
643
|
salt: a.salt ?? ZERO_SALT,
|
|
@@ -769,7 +792,7 @@ export function fPoolLaunchCalls(poolId, a) {
|
|
|
769
792
|
const { bases, companions } = sortFPoolLegs(a.bases, a.weights, given);
|
|
770
793
|
if (!a.policy)
|
|
771
794
|
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,
|
|
795
|
+
const key = { quote: a.quote, bases, weights: companions[0], phi: a.phi, policy: a.policy, creator: a.creator, salt: a.salt ?? ZERO_SALT };
|
|
773
796
|
const enc = (functionName, args) => encodeFunctionData({ abi: fPoolManagerAbi, functionName, args });
|
|
774
797
|
const calls = [];
|
|
775
798
|
if (!a.initialized)
|
|
@@ -783,23 +806,22 @@ export function fPoolLaunchCalls(poolId, a) {
|
|
|
783
806
|
throw new Error(`logswap: openBuy.j = ${a.openBuy.j} is not a leg`);
|
|
784
807
|
calls.push(enc("swapQuoteIn", [poolId, BigInt(j), a.openBuy.amountIn, a.openBuy.minOut ?? 0n, a.account]));
|
|
785
808
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
//
|
|
789
|
-
// in this batch — `fPoolDeskOpening` sends them right after, as the same creator
|
|
809
|
+
// the name, the desk's gates and its list are the POLICY's (decisions 044, 049), not the
|
|
810
|
+
// manager's: they cannot ride in this batch — `fPoolLaunch` and `fPoolDeskOpening` send them
|
|
811
|
+
// right after, as the same creator
|
|
790
812
|
calls.push(...(a.extra ?? []));
|
|
791
813
|
return calls;
|
|
792
814
|
}
|
|
793
815
|
/**
|
|
794
|
-
* The desk's opening posture, on its policy (decisions 044): gated minting, the creator
|
|
795
|
-
* appointment: the authority is the operator until one is appointed (decisions 037).
|
|
796
|
-
* to `PrivatePolicy`; the launch batch cannot carry them (they are not manager calls).
|
|
816
|
+
* The desk's opening posture, on its policy (decisions 044, 048): gated minting, the creator a
|
|
817
|
+
* minter. No appointment: the authority is the operator until one is appointed (decisions 037).
|
|
818
|
+
* Two writes to `PrivatePolicy`; the launch batch cannot carry them (they are not manager calls).
|
|
797
819
|
*/
|
|
798
820
|
export async function fPoolDeskOpening(c, a) {
|
|
799
821
|
const policy = a.policy ?? fPoolPolicyFor(c, "private");
|
|
800
822
|
return [
|
|
801
823
|
await fPoolSetGates(c, { poolId: a.poolId, gateMint: true, gateSwap: false, account: a.account, policy }),
|
|
802
|
-
await
|
|
824
|
+
await fPoolSetMinters(c, { poolId: a.poolId, who: [a.account], allowed: true, account: a.account, policy }),
|
|
803
825
|
];
|
|
804
826
|
}
|
|
805
827
|
/**
|
|
@@ -821,8 +843,11 @@ export async function fPoolDeskOpening(c, a) {
|
|
|
821
843
|
*/
|
|
822
844
|
export async function fPoolLaunch(c, a) {
|
|
823
845
|
const poolId = await fPoolIdOf(c, a);
|
|
824
|
-
const
|
|
846
|
+
const policy = a.policy ?? fPoolPolicyFor(c, a.kind);
|
|
847
|
+
const calls = fPoolLaunchCalls(poolId, { ...a, policy });
|
|
825
848
|
const hash = await writeFPool0(c, "multicall", [calls], a.account);
|
|
849
|
+
if (a.name)
|
|
850
|
+
await fPoolSetName(c, { poolId, name: a.name, account: a.account, policy });
|
|
826
851
|
return { hash, poolId };
|
|
827
852
|
}
|
|
828
853
|
// ─── the roles, on the policy (decisions 044) ─────────────────────────────────────────────
|
|
@@ -864,51 +889,75 @@ export async function fPoolSetGates(c, a) {
|
|
|
864
889
|
return writePolicy(c, privatePolicyAbi, a, "setGates", [a.gateMint, a.gateSwap]);
|
|
865
890
|
}
|
|
866
891
|
/**
|
|
867
|
-
* Add to or remove from the pool's
|
|
868
|
-
*
|
|
892
|
+
* Add to or remove from the pool's MINTERS — who may mint, and swap (a zap in is both under one
|
|
893
|
+
* lock) — in one call (the authority, on the desk's policy; decisions 048). The list is keyed by
|
|
894
|
+
* the authority that granted it: a handover starts the buyer with an empty one. Stamps the
|
|
895
|
+
* block: no swap lands in it (047).
|
|
869
896
|
*/
|
|
870
|
-
export async function
|
|
871
|
-
return writePolicy(c, privatePolicyAbi, a, "
|
|
897
|
+
export async function fPoolSetMinters(c, a) {
|
|
898
|
+
return writePolicy(c, privatePolicyAbi, a, "setMinters", [a.who, a.allowed]);
|
|
872
899
|
}
|
|
873
|
-
/**
|
|
874
|
-
export async function
|
|
900
|
+
/** Add to or remove from the pool's TAKERS — who may swap only — in one call (the authority; decisions 048). Stamps the block. */
|
|
901
|
+
export async function fPoolSetTakers(c, a) {
|
|
902
|
+
return writePolicy(c, privatePolicyAbi, a, "setTakers", [a.who, a.allowed]);
|
|
903
|
+
}
|
|
904
|
+
async function readDesk(c, poolId, who, functionName, policy) {
|
|
875
905
|
const address = policy ?? (await fPoolPolicyOf(c, poolId));
|
|
876
|
-
return (await c.public.readContract({
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
906
|
+
return (await c.public.readContract({ address, abi: privatePolicyAbi, functionName, args: [poolId, who] }));
|
|
907
|
+
}
|
|
908
|
+
/** On the pool's minters under its current authority: may mint, and swap. */
|
|
909
|
+
export async function fPoolIsMinter(c, poolId, who, policy) {
|
|
910
|
+
return readDesk(c, poolId, who, "isMinter", policy);
|
|
911
|
+
}
|
|
912
|
+
/** On the pool's takers under its current authority: may swap only. */
|
|
913
|
+
export async function fPoolIsTaker(c, poolId, who, policy) {
|
|
914
|
+
return readDesk(c, poolId, who, "isTaker", policy);
|
|
882
915
|
}
|
|
883
|
-
/**
|
|
916
|
+
/** May swap: a minter or a taker (consulted only while the swap gate is on). */
|
|
917
|
+
export async function fPoolIsAllowed(c, poolId, who, policy) {
|
|
918
|
+
return readDesk(c, poolId, who, "isAllowed", policy);
|
|
919
|
+
}
|
|
920
|
+
/** Label the pool — the authority's own words on the pool's POLICY (decisions 049), mutable, never identity. At most 31 bytes of UTF-8. */
|
|
884
921
|
export async function fPoolSetName(c, a) {
|
|
885
|
-
return
|
|
922
|
+
return writePolicy(c, fPolicyBaseAbi, a, "setName", [textToBytes32(a.name)]);
|
|
886
923
|
}
|
|
887
924
|
/**
|
|
888
|
-
* What the PROTOCOL says an address is — "Keyrock"
|
|
889
|
-
* what makes it an attestation rather than a
|
|
925
|
+
* What the PROTOCOL says an address is — "Keyrock" — on the REGISTRY (decisions 049). Only its
|
|
926
|
+
* owner, the LOG authority, may write it, which is what makes it an attestation rather than a
|
|
927
|
+
* claim anyone could make about themselves.
|
|
890
928
|
*/
|
|
891
929
|
export async function fPoolSetSponsorName(c, a) {
|
|
892
930
|
const wallet = requireWallet(c);
|
|
931
|
+
const registry = await registryAddress(c);
|
|
893
932
|
const { request } = await c.public.simulateContract({
|
|
894
|
-
address:
|
|
895
|
-
abi:
|
|
933
|
+
address: registry,
|
|
934
|
+
abi: policyRegistryAbi,
|
|
896
935
|
functionName: "setSponsorName",
|
|
897
936
|
args: [a.who, textToBytes32(a.name)],
|
|
898
937
|
account: a.account,
|
|
899
938
|
});
|
|
900
939
|
return wallet.writeContract(request);
|
|
901
940
|
}
|
|
902
|
-
/** The protocol's attestation for an address, or "" when unattested — which most addresses are. */
|
|
941
|
+
/** The protocol's attestation for an address, or "" when unattested — which most addresses are, and every address on a deployment with no registry. */
|
|
903
942
|
export async function fPoolSponsorName(c, who) {
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
args: [who],
|
|
909
|
-
}));
|
|
943
|
+
const registry = c.addresses.policyRegistry ?? (await fPoolRegistryOf(c));
|
|
944
|
+
if (registry === ZERO_ADDRESS)
|
|
945
|
+
return "";
|
|
946
|
+
const word = (await c.public.readContract({ address: registry, abi: policyRegistryAbi, functionName: "sponsorName", args: [who] }));
|
|
910
947
|
return bytes32ToText(word);
|
|
911
948
|
}
|
|
949
|
+
/** The registry the manager asks at every birth — `addresses.policyRegistry`, else the manager's word; zero on a bare deployment. */
|
|
950
|
+
export async function fPoolRegistryOf(c) {
|
|
951
|
+
if (c.addresses.policyRegistry)
|
|
952
|
+
return c.addresses.policyRegistry;
|
|
953
|
+
return (await c.public.readContract({ address: c.addresses.fPoolManager, abi: fPoolManagerAbi, functionName: "registry" }));
|
|
954
|
+
}
|
|
955
|
+
async function registryAddress(c) {
|
|
956
|
+
const registry = await fPoolRegistryOf(c);
|
|
957
|
+
if (registry === ZERO_ADDRESS)
|
|
958
|
+
throw new Error("logswap: this deployment carries no policy registry");
|
|
959
|
+
return registry;
|
|
960
|
+
}
|
|
912
961
|
/** Who runs the pool (decisions 037): the appointed operator, or the authority until one is. */
|
|
913
962
|
export function fPoolOperatorOf(s) {
|
|
914
963
|
return s.operator === ZERO_ADDRESS ? s.authority : s.operator;
|
|
@@ -954,9 +1003,10 @@ export async function fPoolTransferShares(c, a) {
|
|
|
954
1003
|
return wallet.writeContract(request);
|
|
955
1004
|
}
|
|
956
1005
|
/**
|
|
957
|
-
* Every F pool ever created, from `Initialize` logs alone
|
|
958
|
-
* carries the full key preimage (bases,
|
|
959
|
-
* never be inverted; contracts PR #17
|
|
1006
|
+
* Every F pool ever created, from `Initialize` logs alone — plus one `kind()` read per distinct
|
|
1007
|
+
* policy, cached. Possible only because the event carries the full key preimage (bases,
|
|
1008
|
+
* weights, phi, policy) — the poolId is a hash and could never be inverted; contracts PR #17
|
|
1009
|
+
* exists for exactly this call.
|
|
960
1010
|
*/
|
|
961
1011
|
export async function discoverFPools(c, opts = {}) {
|
|
962
1012
|
const ev = fPoolManagerAbi.find((x) => x.type === "event" && x.name === "Initialize");
|
|
@@ -979,24 +1029,25 @@ export async function discoverFPools(c, opts = {}) {
|
|
|
979
1029
|
const a = l.args;
|
|
980
1030
|
q0Of.set(a.poolId.toLowerCase(), a.Q0);
|
|
981
1031
|
}
|
|
982
|
-
return logs.map((l) => {
|
|
1032
|
+
return Promise.all(logs.map(async (l) => {
|
|
983
1033
|
const a = l.args;
|
|
984
1034
|
const q0 = q0Of.get(a.poolId.toLowerCase());
|
|
1035
|
+
const kind = await fPoolKindOfPolicy(c, a.policy); // one read per distinct policy, cached
|
|
985
1036
|
return {
|
|
986
1037
|
poolId: a.poolId,
|
|
987
1038
|
quote: a.quote,
|
|
988
1039
|
bases: [...a.bases],
|
|
989
1040
|
weights: [...a.weights],
|
|
990
1041
|
phi: a.phi,
|
|
991
|
-
kind
|
|
1042
|
+
kind,
|
|
992
1043
|
policy: a.policy,
|
|
993
1044
|
creator: a.creator,
|
|
994
1045
|
block: l.blockNumber ?? 0n,
|
|
995
1046
|
seeded: q0 !== undefined,
|
|
996
1047
|
q0: q0 ?? 0n,
|
|
997
|
-
shape:
|
|
1048
|
+
shape: kind === "pad" ? "launch" : "basket", // the policy's word, not n = 1: a mono POL is a pool (decisions 036, 049)
|
|
998
1049
|
};
|
|
999
|
-
});
|
|
1050
|
+
}));
|
|
1000
1051
|
}
|
|
1001
1052
|
/** The policy's terms for one pool, by its kind. */
|
|
1002
1053
|
export async function getFPoolRules(c, s, roles) {
|
|
@@ -1035,14 +1086,19 @@ export async function getFPoolRules(c, s, roles) {
|
|
|
1035
1086
|
*/
|
|
1036
1087
|
export async function fPoolsControlledBy(c, who, opts = {}) {
|
|
1037
1088
|
const pools = opts.pools ?? (await discoverFPools(c, { fromBlock: opts.fromBlock }));
|
|
1038
|
-
|
|
1039
|
-
const
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1089
|
+
// the LIVE policy answers for the authority: a moved pool (046) is on another one than its birth's
|
|
1090
|
+
const states = await Promise.all(pools.map((p) => getFPool(c, p.poolId)));
|
|
1091
|
+
const authorities = await Promise.all(states.map((s) => c.public.readContract({ address: s.policy, abi: fPolicyBaseAbi, functionName: "authority", args: [s.poolId] })));
|
|
1092
|
+
const out = [];
|
|
1093
|
+
for (let i = 0; i < pools.length; ++i) {
|
|
1094
|
+
if (authorities[i].toLowerCase() !== who.toLowerCase())
|
|
1095
|
+
continue;
|
|
1096
|
+
const state = states[i];
|
|
1097
|
+
const roles = await getFPoolRoles(c, state.poolId, state);
|
|
1043
1098
|
const rules = await getFPoolRules(c, state, roles);
|
|
1044
|
-
|
|
1045
|
-
}
|
|
1099
|
+
out.push({ pool: pools[i], roles, state, rules });
|
|
1100
|
+
}
|
|
1101
|
+
return out;
|
|
1046
1102
|
}
|
|
1047
1103
|
/**
|
|
1048
1104
|
* Every holder of a pool's shares, from the ERC-6909 Transfer stream — the id is an indexed
|