@nradko/metric-omm-sdk-v1 0.0.16

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.
Files changed (137) hide show
  1. package/README.md +111 -0
  2. package/dist/abis/MetricOmmPool.d.ts +784 -0
  3. package/dist/abis/MetricOmmPool.d.ts.map +1 -0
  4. package/dist/abis/MetricOmmPool.js +1008 -0
  5. package/dist/abis/MetricOmmPool.js.map +1 -0
  6. package/dist/abis/MetricOmmPoolFactory.d.ts +1365 -0
  7. package/dist/abis/MetricOmmPoolFactory.d.ts.map +1 -0
  8. package/dist/abis/MetricOmmPoolFactory.js +1754 -0
  9. package/dist/abis/MetricOmmPoolFactory.js.map +1 -0
  10. package/dist/abis/MetricOmmPoolLiquidityAdder.d.ts +308 -0
  11. package/dist/abis/MetricOmmPoolLiquidityAdder.d.ts.map +1 -0
  12. package/dist/abis/MetricOmmPoolLiquidityAdder.js +401 -0
  13. package/dist/abis/MetricOmmPoolLiquidityAdder.js.map +1 -0
  14. package/dist/abis/MetricOmmPoolStateView.d.ts +538 -0
  15. package/dist/abis/MetricOmmPoolStateView.d.ts.map +1 -0
  16. package/dist/abis/MetricOmmPoolStateView.js +717 -0
  17. package/dist/abis/MetricOmmPoolStateView.js.map +1 -0
  18. package/dist/abis/MetricOmmPoolSwapper.d.ts +557 -0
  19. package/dist/abis/MetricOmmPoolSwapper.d.ts.map +1 -0
  20. package/dist/abis/MetricOmmPoolSwapper.js +723 -0
  21. package/dist/abis/MetricOmmPoolSwapper.js.map +1 -0
  22. package/dist/abis/Multicall3.d.ts +333 -0
  23. package/dist/abis/Multicall3.d.ts.map +1 -0
  24. package/dist/abis/Multicall3.js +441 -0
  25. package/dist/abis/Multicall3.js.map +1 -0
  26. package/dist/abis/PriceProvider.d.ts +142 -0
  27. package/dist/abis/PriceProvider.d.ts.map +1 -0
  28. package/dist/abis/PriceProvider.js +184 -0
  29. package/dist/abis/PriceProvider.js.map +1 -0
  30. package/dist/abis/PriceProviderUi.d.ts +433 -0
  31. package/dist/abis/PriceProviderUi.d.ts.map +1 -0
  32. package/dist/abis/PriceProviderUi.js +318 -0
  33. package/dist/abis/PriceProviderUi.js.map +1 -0
  34. package/dist/abis/index.d.ts +11 -0
  35. package/dist/abis/index.d.ts.map +1 -0
  36. package/dist/abis/index.js +11 -0
  37. package/dist/abis/index.js.map +1 -0
  38. package/dist/addresses.d.ts +52 -0
  39. package/dist/addresses.d.ts.map +1 -0
  40. package/dist/addresses.js +58 -0
  41. package/dist/addresses.js.map +1 -0
  42. package/dist/constants.d.ts +20 -0
  43. package/dist/constants.d.ts.map +1 -0
  44. package/dist/constants.js +26 -0
  45. package/dist/constants.js.map +1 -0
  46. package/dist/factory/collectFees.d.ts +41 -0
  47. package/dist/factory/collectFees.d.ts.map +1 -0
  48. package/dist/factory/collectFees.js +120 -0
  49. package/dist/factory/collectFees.js.map +1 -0
  50. package/dist/factory/index.d.ts +5 -0
  51. package/dist/factory/index.d.ts.map +1 -0
  52. package/dist/factory/index.js +5 -0
  53. package/dist/factory/index.js.map +1 -0
  54. package/dist/index.d.ts +16 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +24 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/pool/create.d.ts +80 -0
  59. package/dist/pool/create.d.ts.map +1 -0
  60. package/dist/pool/create.js +80 -0
  61. package/dist/pool/create.js.map +1 -0
  62. package/dist/pool/index.d.ts +7 -0
  63. package/dist/pool/index.d.ts.map +1 -0
  64. package/dist/pool/index.js +10 -0
  65. package/dist/pool/index.js.map +1 -0
  66. package/dist/pool/liquidity.d.ts +165 -0
  67. package/dist/pool/liquidity.d.ts.map +1 -0
  68. package/dist/pool/liquidity.js +508 -0
  69. package/dist/pool/liquidity.js.map +1 -0
  70. package/dist/pool/read.d.ts +22 -0
  71. package/dist/pool/read.d.ts.map +1 -0
  72. package/dist/pool/read.js +88 -0
  73. package/dist/pool/read.js.map +1 -0
  74. package/dist/router/index.d.ts +5 -0
  75. package/dist/router/index.d.ts.map +1 -0
  76. package/dist/router/index.js +5 -0
  77. package/dist/router/index.js.map +1 -0
  78. package/dist/router/swap.d.ts +117 -0
  79. package/dist/router/swap.d.ts.map +1 -0
  80. package/dist/router/swap.js +298 -0
  81. package/dist/router/swap.js.map +1 -0
  82. package/dist/stateView/index.d.ts +5 -0
  83. package/dist/stateView/index.d.ts.map +1 -0
  84. package/dist/stateView/index.js +5 -0
  85. package/dist/stateView/index.js.map +1 -0
  86. package/dist/stateView/read.d.ts +80 -0
  87. package/dist/stateView/read.d.ts.map +1 -0
  88. package/dist/stateView/read.js +249 -0
  89. package/dist/stateView/read.js.map +1 -0
  90. package/dist/types.d.ts +134 -0
  91. package/dist/types.d.ts.map +1 -0
  92. package/dist/types.js +6 -0
  93. package/dist/types.js.map +1 -0
  94. package/dist/utils/binData.d.ts +65 -0
  95. package/dist/utils/binData.d.ts.map +1 -0
  96. package/dist/utils/binData.js +109 -0
  97. package/dist/utils/binData.js.map +1 -0
  98. package/dist/utils/index.d.ts +7 -0
  99. package/dist/utils/index.d.ts.map +1 -0
  100. package/dist/utils/index.js +10 -0
  101. package/dist/utils/index.js.map +1 -0
  102. package/dist/utils/liquidityMath.d.ts +10 -0
  103. package/dist/utils/liquidityMath.d.ts.map +1 -0
  104. package/dist/utils/liquidityMath.js +31 -0
  105. package/dist/utils/liquidityMath.js.map +1 -0
  106. package/dist/utils/price.d.ts +13 -0
  107. package/dist/utils/price.d.ts.map +1 -0
  108. package/dist/utils/price.js +21 -0
  109. package/dist/utils/price.js.map +1 -0
  110. package/package.json +74 -0
  111. package/src/abis/MetricOmmPool.ts +1007 -0
  112. package/src/abis/MetricOmmPoolFactory.ts +1753 -0
  113. package/src/abis/MetricOmmPoolLiquidityAdder.ts +400 -0
  114. package/src/abis/MetricOmmPoolStateView.ts +716 -0
  115. package/src/abis/MetricOmmPoolSwapper.ts +722 -0
  116. package/src/abis/Multicall3.ts +440 -0
  117. package/src/abis/PriceProvider.ts +183 -0
  118. package/src/abis/PriceProviderUi.ts +317 -0
  119. package/src/abis/index.ts +11 -0
  120. package/src/addresses.ts +100 -0
  121. package/src/constants.ts +35 -0
  122. package/src/factory/collectFees.ts +197 -0
  123. package/src/factory/index.ts +12 -0
  124. package/src/index.ts +157 -0
  125. package/src/pool/create.ts +158 -0
  126. package/src/pool/index.ts +47 -0
  127. package/src/pool/liquidity.ts +839 -0
  128. package/src/pool/read.ts +131 -0
  129. package/src/router/index.ts +27 -0
  130. package/src/router/swap.ts +507 -0
  131. package/src/stateView/index.ts +18 -0
  132. package/src/stateView/read.ts +355 -0
  133. package/src/types.ts +162 -0
  134. package/src/utils/binData.ts +127 -0
  135. package/src/utils/index.ts +26 -0
  136. package/src/utils/liquidityMath.ts +47 -0
  137. package/src/utils/price.ts +23 -0
@@ -0,0 +1,355 @@
1
+ /**
2
+ * MetricAMM SDK - StateView Read Functions
3
+ * Efficient batch read functions using the StateView contract
4
+ */
5
+
6
+ import type { Address, PublicClient } from "viem";
7
+ import { STATE_VIEW_ABI } from "../constants.js";
8
+ import type {
9
+ Slot0,
10
+ Slot1,
11
+ BinStateExternal,
12
+ BinStatesExternal,
13
+ BinStatesScaled,
14
+ FeeConfig,
15
+ PositionBinSharesResult,
16
+ } from "../types.js";
17
+
18
+ /**
19
+ * Get slot0 data efficiently (all in one call)
20
+ */
21
+ export async function getSlot0(
22
+ publicClient: PublicClient,
23
+ stateViewAddress: Address,
24
+ poolAddress: Address,
25
+ ): Promise<Slot0> {
26
+ const result = (await publicClient.readContract({
27
+ address: stateViewAddress,
28
+ abi: STATE_VIEW_ABI,
29
+ functionName: "slot0",
30
+ args: [poolAddress],
31
+ })) as any[];
32
+
33
+ return {
34
+ pauseLevel: Number(result[0]),
35
+ curBinIdx: Number(result[1]),
36
+ curPosInBin: result[2],
37
+ curBinDistFromProvidedPrice: Number(result[3]),
38
+ spreadFeeE6: Number(result[4]),
39
+ notionalFeeE8: Number(result[5]),
40
+ };
41
+ }
42
+
43
+ /**
44
+ * Get slot1 data (total scaled token amounts in bins)
45
+ */
46
+ export async function getSlot1(
47
+ publicClient: PublicClient,
48
+ stateViewAddress: Address,
49
+ poolAddress: Address,
50
+ ): Promise<Slot1> {
51
+ const result = (await publicClient.readContract({
52
+ address: stateViewAddress,
53
+ abi: STATE_VIEW_ABI,
54
+ functionName: "slot1",
55
+ args: [poolAddress],
56
+ })) as any[];
57
+
58
+ return {
59
+ totalScaledToken0InBins: result[0],
60
+ totalScaledToken1InBins: result[1],
61
+ };
62
+ }
63
+
64
+ /**
65
+ * Get bin state with balances in external (native token decimal) units
66
+ */
67
+ export async function getBinStateExternal(
68
+ publicClient: PublicClient,
69
+ stateViewAddress: Address,
70
+ poolAddress: Address,
71
+ binIdx: number,
72
+ ): Promise<BinStateExternal> {
73
+ const result = (await publicClient.readContract({
74
+ address: stateViewAddress,
75
+ abi: STATE_VIEW_ABI,
76
+ functionName: "binState",
77
+ args: [poolAddress, binIdx],
78
+ })) as any[];
79
+
80
+ return {
81
+ token0Balance: result[0],
82
+ token1Balance: result[1],
83
+ lengthE6: result[2],
84
+ addFeeBuyE6: result[3],
85
+ addFeeSellE6: result[4],
86
+ };
87
+ }
88
+
89
+ /**
90
+ * Get multiple bin states efficiently (batch read)
91
+ */
92
+ export async function getBinStatesExternal(
93
+ publicClient: PublicClient,
94
+ stateViewAddress: Address,
95
+ poolAddress: Address,
96
+ binIndices: number[],
97
+ ): Promise<BinStatesExternal> {
98
+ const result = (await publicClient.readContract({
99
+ address: stateViewAddress,
100
+ abi: STATE_VIEW_ABI,
101
+ functionName: "binStates",
102
+ args: [poolAddress, binIndices],
103
+ })) as any[];
104
+
105
+ return {
106
+ token0Balances: result[0],
107
+ token1Balances: result[1],
108
+ lengthsInUnits: result[2],
109
+ addFeeBuysE6: result[3],
110
+ addFeeSellsE6: result[4],
111
+ totalShares: result[5],
112
+ };
113
+ }
114
+
115
+ /**
116
+ * Get multiple bin states in scaled (internal) units (parallel reads).
117
+ */
118
+ export async function getBinStatesScaled(
119
+ publicClient: PublicClient,
120
+ stateViewAddress: Address,
121
+ poolAddress: Address,
122
+ binIndices: number[],
123
+ ): Promise<BinStatesScaled> {
124
+ const scaledReads = binIndices.map(
125
+ (binIdx) =>
126
+ publicClient.readContract({
127
+ address: stateViewAddress,
128
+ abi: STATE_VIEW_ABI,
129
+ functionName: "binStateScaled",
130
+ args: [poolAddress, binIdx],
131
+ }) as Promise<readonly [bigint, bigint, number, number, number]>,
132
+ );
133
+ const shareReads = binIndices.map(
134
+ (binIdx) =>
135
+ publicClient.readContract({
136
+ address: stateViewAddress,
137
+ abi: STATE_VIEW_ABI,
138
+ functionName: "binTotalShares",
139
+ args: [poolAddress, binIdx],
140
+ }) as Promise<bigint>,
141
+ );
142
+
143
+ const [scaled, shares] = await Promise.all([Promise.all(scaledReads), Promise.all(shareReads)]);
144
+
145
+ return {
146
+ token0BalancesScaled: scaled.map((r) => r[0]),
147
+ token1BalancesScaled: scaled.map((r) => r[1]),
148
+ lengthsInUnits: scaled.map((r) => r[2]),
149
+ addFeeBuysE6: scaled.map((r) => r[3]),
150
+ addFeeSellsE6: scaled.map((r) => r[4]),
151
+ totalShares: shares,
152
+ };
153
+ }
154
+
155
+ /**
156
+ * Get bin total shares
157
+ */
158
+ export async function getBinTotalShares(
159
+ publicClient: PublicClient,
160
+ stateViewAddress: Address,
161
+ poolAddress: Address,
162
+ binIdx: number,
163
+ ): Promise<bigint> {
164
+ return (await publicClient.readContract({
165
+ address: stateViewAddress,
166
+ abi: STATE_VIEW_ABI,
167
+ functionName: "binTotalShares",
168
+ args: [poolAddress, binIdx],
169
+ })) as bigint;
170
+ }
171
+
172
+ /**
173
+ * Get user position shares via StateView
174
+ */
175
+ export async function getPositionBinSharesFromStateView(
176
+ publicClient: PublicClient,
177
+ stateViewAddress: Address,
178
+ poolAddress: Address,
179
+ owner: Address,
180
+ salt: bigint,
181
+ binIdx: number,
182
+ ): Promise<bigint> {
183
+ return (await publicClient.readContract({
184
+ address: stateViewAddress,
185
+ abi: STATE_VIEW_ABI,
186
+ functionName: "positionBinShares",
187
+ args: [poolAddress, owner, salt, binIdx],
188
+ })) as bigint;
189
+ }
190
+
191
+ /**
192
+ * Create a position bin key (matches Solidity's toPositionBinKey)
193
+ * Layout: [address(160)] | [salt(80)] | [bin(16)] = 256 bits
194
+ */
195
+ export function toPositionBinKey(owner: Address, salt: bigint, bin: number): `0x${string}` {
196
+ // Convert owner address to bigint (160 bits)
197
+ const ownerBigInt = BigInt(owner);
198
+ // Salt is 80 bits, bin is 16 bits (signed, convert to uint16)
199
+ const binUint16 = bin < 0 ? BigInt(bin + 0x10000) : BigInt(bin);
200
+ // Pack: owner << 96 | salt << 16 | bin
201
+ const packed =
202
+ (ownerBigInt << 96n) | ((salt & 0xffffffffffffffffffffn) << 16n) | (binUint16 & 0xffffn);
203
+ return `0x${packed.toString(16).padStart(64, "0")}` as `0x${string}`;
204
+ }
205
+
206
+ /**
207
+ * Get user position shares for a range of bins via StateView batch call
208
+ *
209
+ * @param publicClient - Viem public client
210
+ * @param stateViewAddress - StateView contract address
211
+ * @param poolAddress - Pool address
212
+ * @param owner - Position owner (e.g., NFTPositionManager address)
213
+ * @param salt - Position salt (e.g., NFT token ID)
214
+ * @param lowerBin - Lower bin index (inclusive)
215
+ * @param upperBin - Upper bin index (inclusive)
216
+ * @returns Array of { binIdx, shares } for bins with non-zero shares
217
+ */
218
+ export async function getPositionBinSharesRange(
219
+ publicClient: PublicClient,
220
+ stateViewAddress: Address,
221
+ poolAddress: Address,
222
+ owner: Address,
223
+ salt: bigint,
224
+ lowerBin: number,
225
+ upperBin: number,
226
+ ): Promise<PositionBinSharesResult[]> {
227
+ const binIndices: number[] = [];
228
+ const positionBinKeys: `0x${string}`[] = [];
229
+
230
+ for (let bin = lowerBin; bin <= upperBin; bin++) {
231
+ binIndices.push(bin);
232
+ positionBinKeys.push(toPositionBinKey(owner, salt, bin));
233
+ }
234
+
235
+ // Batch read all bin shares using the new positionBinSharesBatch function
236
+ const results = (await publicClient.readContract({
237
+ address: stateViewAddress,
238
+ abi: STATE_VIEW_ABI,
239
+ functionName: "positionBinSharesBatch",
240
+ args: [poolAddress, positionBinKeys],
241
+ })) as bigint[];
242
+
243
+ const positionShares: PositionBinSharesResult[] = [];
244
+ for (let i = 0; i < binIndices.length; i++) {
245
+ const shares = results[i];
246
+ if (shares > 0n) {
247
+ positionShares.push({
248
+ binIdx: binIndices[i],
249
+ shares,
250
+ });
251
+ }
252
+ }
253
+
254
+ return positionShares;
255
+ }
256
+
257
+ /**
258
+ * Get user position shares for specific (possibly non-contiguous) bins via StateView batch call.
259
+ *
260
+ * Unlike getPositionBinSharesRange which scans a contiguous range,
261
+ * this function queries exact bin indices you specify.
262
+ *
263
+ * @param publicClient - Viem public client
264
+ * @param stateViewAddress - StateView contract address
265
+ * @param poolAddress - Pool address
266
+ * @param owner - Position owner address
267
+ * @param salt - Position salt
268
+ * @param bins - Array of specific bin indices to query (e.g., [-3, 1, 2])
269
+ * @returns Array of { binIdx, shares } for bins with non-zero shares
270
+ */
271
+ export async function getPositionBinSharesForBins(
272
+ publicClient: PublicClient,
273
+ stateViewAddress: Address,
274
+ poolAddress: Address,
275
+ owner: Address,
276
+ salt: bigint,
277
+ bins: number[],
278
+ ): Promise<PositionBinSharesResult[]> {
279
+ const positionBinKeys = bins.map((bin) => toPositionBinKey(owner, salt, bin));
280
+
281
+ const results = (await publicClient.readContract({
282
+ address: stateViewAddress,
283
+ abi: STATE_VIEW_ABI,
284
+ functionName: "positionBinSharesBatch",
285
+ args: [poolAddress, positionBinKeys],
286
+ })) as bigint[];
287
+
288
+ const positionShares: PositionBinSharesResult[] = [];
289
+ for (let i = 0; i < bins.length; i++) {
290
+ const shares = results[i];
291
+ if (shares > 0n) {
292
+ positionShares.push({
293
+ binIdx: bins[i],
294
+ shares,
295
+ });
296
+ }
297
+ }
298
+
299
+ return positionShares;
300
+ }
301
+
302
+ /**
303
+ * Get fee configuration
304
+ */
305
+ export async function getFeeConfig(
306
+ publicClient: PublicClient,
307
+ stateViewAddress: Address,
308
+ poolAddress: Address,
309
+ ): Promise<FeeConfig> {
310
+ const result = (await publicClient.readContract({
311
+ address: stateViewAddress,
312
+ abi: STATE_VIEW_ABI,
313
+ functionName: "feeConfig",
314
+ args: [poolAddress],
315
+ })) as any[];
316
+
317
+ return {
318
+ adminAddr: result[0],
319
+ protocolFee: result[1],
320
+ adminFee: result[2],
321
+ adminFeeDest: result[3],
322
+ };
323
+ }
324
+
325
+ /**
326
+ * Get price provider address
327
+ */
328
+ export async function getPriceProvider(
329
+ publicClient: PublicClient,
330
+ stateViewAddress: Address,
331
+ poolAddress: Address,
332
+ ): Promise<Address> {
333
+ return (await publicClient.readContract({
334
+ address: stateViewAddress,
335
+ abi: STATE_VIEW_ABI,
336
+ functionName: "priceProvider",
337
+ args: [poolAddress],
338
+ })) as Address;
339
+ }
340
+
341
+ /**
342
+ * Get last trade timestamp
343
+ */
344
+ export async function getLastTradeTimestamp(
345
+ publicClient: PublicClient,
346
+ stateViewAddress: Address,
347
+ poolAddress: Address,
348
+ ): Promise<number> {
349
+ return (await publicClient.readContract({
350
+ address: stateViewAddress,
351
+ abi: STATE_VIEW_ABI,
352
+ functionName: "lastTradeTimestamp",
353
+ args: [poolAddress],
354
+ })) as number;
355
+ }
package/src/types.ts ADDED
@@ -0,0 +1,162 @@
1
+ /**
2
+ * MetricAMM SDK Types
3
+ * All interfaces and type definitions
4
+ */
5
+
6
+ import type { Address } from "viem";
7
+
8
+ // ============ Core Types ============
9
+
10
+ export interface LiquidityDelta {
11
+ bin: number; // int24
12
+ deltaShares: bigint; // int104
13
+ }
14
+
15
+ /**
16
+ * v1 pool and LiquidityAdder payload: parallel arrays of bin indices and share magnitudes (add or remove).
17
+ */
18
+ export interface PoolLiquidityDelta {
19
+ binIdxs: readonly bigint[];
20
+ shares: readonly bigint[];
21
+ }
22
+
23
+ /**
24
+ * Bin configuration for pool creation.
25
+ * All values are in E6 format (1e6 = 100%).
26
+ *
27
+ * @example
28
+ * // Bin with 1% length, 0.3% buy fee, 0.1% sell fee
29
+ * { lengthE6: 10000, addFeeBuyE6: 3000, addFeeSellE6: 1000 }
30
+ */
31
+ export interface BinData {
32
+ /** Bin length in E6 format (10000 = 1%, 1000000 = 100%) */
33
+ lengthE6: number;
34
+ /** Additional buy fee in E6 format */
35
+ addFeeBuyE6: number;
36
+ /** Additional sell fee in E6 format */
37
+ addFeeSellE6: number;
38
+ }
39
+
40
+ // ============ Pool Types ============
41
+
42
+ export interface PoolImmutables {
43
+ factory: Address;
44
+ token0: Address;
45
+ token1: Address;
46
+ token0ScaleMultiplier: bigint;
47
+ token1ScaleMultiplier: bigint;
48
+ initialScaledToken0PerShareE18: bigint;
49
+ initialScaledToken1PerShareE18: bigint;
50
+ minimalMintableLiquidity: bigint;
51
+ maxDriftE8: bigint;
52
+ maxDriftDecayPerSecondE8: bigint;
53
+ lowestBin: number;
54
+ highestBin: number;
55
+ }
56
+
57
+ export interface PoolState {
58
+ pauseLevel: number;
59
+ curBinIdx: number;
60
+ curPosInBin: bigint;
61
+ curBinDistFromProvidedPrice: number;
62
+ spreadFeeE6: number;
63
+ notionalFeeE8: number;
64
+ totalScaledToken0InBins: bigint;
65
+ totalScaledToken1InBins: bigint;
66
+ }
67
+
68
+ export interface BinState {
69
+ token0BalanceScaled: bigint;
70
+ token1BalanceScaled: bigint;
71
+ lengthE6: number;
72
+ addFeeBuyE6: number;
73
+ addFeeSellE6: number;
74
+ }
75
+
76
+ export interface BinStateExternal {
77
+ token0Balance: bigint; // Unscaled, in native token decimals
78
+ token1Balance: bigint; // Unscaled, in native token decimals
79
+ lengthE6: number;
80
+ addFeeBuyE6: number;
81
+ addFeeSellE6: number;
82
+ }
83
+
84
+ export interface BinStatesExternal {
85
+ token0Balances: bigint[];
86
+ token1Balances: bigint[];
87
+ lengthsInUnits: number[];
88
+ addFeeBuysE6: number[];
89
+ addFeeSellsE6: number[];
90
+ totalShares: bigint[];
91
+ }
92
+
93
+ export interface BinStatesScaled {
94
+ token0BalancesScaled: bigint[];
95
+ token1BalancesScaled: bigint[];
96
+ lengthsInUnits: number[];
97
+ addFeeBuysE6: number[];
98
+ addFeeSellsE6: number[];
99
+ totalShares: bigint[];
100
+ }
101
+
102
+ // ============ StateView Types ============
103
+
104
+ export interface Slot0 {
105
+ pauseLevel: number;
106
+ curBinIdx: number;
107
+ curPosInBin: bigint;
108
+ curBinDistFromProvidedPrice: number;
109
+ spreadFeeE6: number;
110
+ notionalFeeE8: number;
111
+ }
112
+
113
+ export interface Slot1 {
114
+ totalScaledToken0InBins: bigint;
115
+ totalScaledToken1InBins: bigint;
116
+ }
117
+
118
+ export interface FeeConfig {
119
+ adminAddr: Address;
120
+ protocolFee: number;
121
+ adminFee: number;
122
+ adminFeeDest: Address;
123
+ }
124
+
125
+ // ============ Position Types ============
126
+
127
+ /**
128
+ * Result type for getPositionBinSharesRange
129
+ */
130
+ export interface PositionBinSharesResult {
131
+ binIdx: number;
132
+ shares: bigint;
133
+ }
134
+
135
+ // ============ Liquidity Types ============
136
+
137
+ export interface CalculateUniformLiquidityParams {
138
+ valuePerBinInToken: bigint;
139
+ valueIsInToken0: boolean;
140
+ currentPrice: number;
141
+ lowerBin: number;
142
+ upperBin: number;
143
+ }
144
+
145
+ export interface LiquidityBinValueInput {
146
+ bin: number;
147
+ targetValueInToken: bigint;
148
+ targetValueInToken0: boolean;
149
+ }
150
+
151
+ export interface CalculateAnyLiquidityParams {
152
+ bins: LiquidityBinValueInput[];
153
+ currentPrice: number;
154
+ }
155
+
156
+ export interface PreparedLiquidityDistribution {
157
+ deltas: LiquidityDelta[];
158
+ specAmount0: bigint;
159
+ specAmount1: bigint;
160
+ }
161
+
162
+ export type CalculatedLiquidityDistribution = PreparedLiquidityDistribution;
@@ -0,0 +1,127 @@
1
+ /**
2
+ * MetricAMM SDK - Bin Data Utilities
3
+ * Functions for packing/unpacking bin data
4
+ */
5
+
6
+ import type { BinData } from "../types.js";
7
+
8
+ /**
9
+ * Pack bin data into 48-bit representation
10
+ * Layout: [lengthE6: 16 bits][addFeeBuyE6: 16 bits][addFeeSellE6: 16 bits]
11
+ */
12
+ export function packBinData(binData: BinData): bigint {
13
+ const length = BigInt(binData.lengthE6) & 0xffffn;
14
+ const buyFee = BigInt(binData.addFeeBuyE6) & 0xffffn;
15
+ const sellFee = BigInt(binData.addFeeSellE6) & 0xffffn;
16
+
17
+ return length | (buyFee << 16n) | (sellFee << 32n);
18
+ }
19
+
20
+ /**
21
+ * Pack 5 bins into a single uint256
22
+ * Each bin takes 48 bits, total 240 bits used, 16 bits unused
23
+ */
24
+ export function packBins5(bins: BinData[]): bigint {
25
+ if (bins.length !== 5) {
26
+ throw new Error("Must provide exactly 5 bins");
27
+ }
28
+
29
+ let packed = 0n;
30
+ for (let i = 0; i < 5; i++) {
31
+ const binPacked = packBinData(bins[i]);
32
+ packed |= binPacked << (BigInt(i) * 48n);
33
+ }
34
+
35
+ return packed;
36
+ }
37
+
38
+ /**
39
+ * Pack an array of bin data into uint256 array (5 bins per uint256)
40
+ * Pads with zero bins if length is not divisible by 5
41
+ */
42
+ export function packBinDataArray(bins: BinData[]): bigint[] {
43
+ const zeroBin: BinData = { lengthE6: 0, addFeeBuyE6: 0, addFeeSellE6: 0 };
44
+ const result: bigint[] = [];
45
+
46
+ // Process in chunks of 5
47
+ for (let i = 0; i < bins.length; i += 5) {
48
+ const chunk: BinData[] = [];
49
+ for (let j = 0; j < 5; j++) {
50
+ chunk.push(bins[i + j] || zeroBin);
51
+ }
52
+ result.push(packBins5(chunk));
53
+ }
54
+
55
+ return result;
56
+ }
57
+
58
+ /**
59
+ * Unpack 48-bit bin data
60
+ */
61
+ export function unpackBinData(packed: bigint): BinData {
62
+ const lengthE6 = Number(packed & 0xffffn);
63
+ const addFeeBuyE6 = Number((packed >> 16n) & 0xffffn);
64
+ const addFeeSellE6 = Number((packed >> 32n) & 0xffffn);
65
+
66
+ return {
67
+ lengthE6,
68
+ addFeeBuyE6,
69
+ addFeeSellE6,
70
+ };
71
+ }
72
+
73
+ /**
74
+ * Pack bin data array into uint256 array ready for contract calls.
75
+ *
76
+ * @param bins Array of bin configurations
77
+ * @returns Packed uint256 array ready for contract calls
78
+ *
79
+ * @example
80
+ * // Create 3 bins: 1% length with default fees
81
+ * const bins = createBins([
82
+ * { lengthE6: 10000, addFeeBuyE6: 0, addFeeSellE6: 0 },
83
+ * { lengthE6: 10000, addFeeBuyE6: 0, addFeeSellE6: 0 },
84
+ * { lengthE6: 10000, addFeeBuyE6: 0, addFeeSellE6: 0 },
85
+ * ]);
86
+ *
87
+ * @example
88
+ * // Create bins with custom fees
89
+ * const bins = createBins([
90
+ * { lengthE6: 10000, addFeeBuyE6: 500, addFeeSellE6: 200 }, // 1% length, +0.05% buy, +0.02% sell
91
+ * { lengthE6: 20000, addFeeBuyE6: 0, addFeeSellE6: 0 }, // 2% length, no extra fees
92
+ * ]);
93
+ */
94
+ export function createBins(bins: BinData[]): bigint[] {
95
+ return packBinDataArray(bins);
96
+ }
97
+
98
+ /**
99
+ * Create uniform bins with the same configuration.
100
+ *
101
+ * @param count Number of bins to create
102
+ * @param lengthE6 Bin length in E6 format (10000 = 1%)
103
+ * @param addFeeBuyE6 Additional buy fee in E6 format (default: 0)
104
+ * @param addFeeSellE6 Additional sell fee in E6 format (default: 0)
105
+ * @returns Packed uint256 array ready for contract calls
106
+ *
107
+ * @example
108
+ * // Create 20 uniform bins, each 1% length
109
+ * const bins = createUniformBins(20, 10000);
110
+ *
111
+ * @example
112
+ * // Create 10 bins with 0.5% length and +0.1% buy fee
113
+ * const bins = createUniformBins(10, 5000, 1000);
114
+ */
115
+ export function createUniformBins(
116
+ count: number,
117
+ lengthE6: number,
118
+ addFeeBuyE6: number = 0,
119
+ addFeeSellE6: number = 0,
120
+ ): bigint[] {
121
+ const bins: BinData[] = Array(count).fill({
122
+ lengthE6,
123
+ addFeeBuyE6,
124
+ addFeeSellE6,
125
+ });
126
+ return packBinDataArray(bins);
127
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * MetricAMM SDK - Utility Functions
3
+ */
4
+
5
+ // Bin data utilities
6
+ export {
7
+ packBinData,
8
+ packBins5,
9
+ packBinDataArray,
10
+ unpackBinData,
11
+ createBins,
12
+ createUniformBins,
13
+ } from "./binData.js";
14
+
15
+ // Price utilities
16
+ export { priceToQ64, q64ToPrice } from "./price.js";
17
+
18
+ // Liquidity math utilities
19
+ export {
20
+ ONE_E18,
21
+ ceilDiv,
22
+ toPriceE18 as toPriceX18,
23
+ convertToken0ToToken1,
24
+ convertToken1ToToken0,
25
+ scaledPositiveDeltaToExternal,
26
+ } from "./liquidityMath.js";
@@ -0,0 +1,47 @@
1
+ /**
2
+ * MetricAMM SDK - Liquidity Math Utilities
3
+ */
4
+
5
+ export const ONE_E18 = 1_000_000_000_000_000_000n;
6
+
7
+ export function ceilDiv(numerator: bigint, denominator: bigint): bigint {
8
+ if (denominator <= 0n) throw new Error("denominator must be > 0");
9
+ if (numerator < 0n) throw new Error("numerator must be >= 0");
10
+ return numerator === 0n ? 0n : (numerator + denominator - 1n) / denominator;
11
+ }
12
+
13
+ export function toPriceE18(currentPrice: number): bigint {
14
+ if (!Number.isFinite(currentPrice) || currentPrice <= 0) {
15
+ throw new Error("currentPrice must be a positive finite number");
16
+ }
17
+ const priceE18 = BigInt(Math.round(currentPrice * 1e18));
18
+ if (priceE18 <= 0n) {
19
+ throw new Error("currentPrice is too small");
20
+ }
21
+ return priceE18;
22
+ }
23
+
24
+ export function convertToken0ToToken1(
25
+ amount0: bigint,
26
+ token0ScaleMultiplier: bigint,
27
+ token1ScaleMultiplier: bigint,
28
+ priceE18: bigint,
29
+ ): bigint {
30
+ return (amount0 * token0ScaleMultiplier * priceE18) / (token1ScaleMultiplier * ONE_E18);
31
+ }
32
+
33
+ export function convertToken1ToToken0(
34
+ amount1: bigint,
35
+ token0ScaleMultiplier: bigint,
36
+ token1ScaleMultiplier: bigint,
37
+ priceX18: bigint,
38
+ ): bigint {
39
+ return (amount1 * token1ScaleMultiplier * ONE_E18) / (token0ScaleMultiplier * priceX18);
40
+ }
41
+
42
+ export function scaledPositiveDeltaToExternal(
43
+ scaledAmount: bigint,
44
+ scaleMultiplier: bigint,
45
+ ): bigint {
46
+ return ceilDiv(scaledAmount, scaleMultiplier);
47
+ }