@spectratools/aborean-cli 0.3.0 → 0.4.0

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 (2) hide show
  1. package/dist/cli.js +884 -154
  2. package/package.json +2 -2
package/dist/cli.js CHANGED
@@ -4,10 +4,12 @@
4
4
  import { readFileSync } from "fs";
5
5
  import { dirname, resolve } from "path";
6
6
  import { fileURLToPath } from "url";
7
- import { Cli as Cli4, z as z4 } from "incur";
7
+ import { Cli as Cli5, z as z5 } from "incur";
8
8
 
9
- // src/commands/gauges.ts
9
+ // src/commands/cl.ts
10
+ import { checksumAddress, isAddress } from "@spectratools/cli-shared";
10
11
  import { Cli, z } from "incur";
12
+ import { formatUnits, parseUnits } from "viem";
11
13
 
12
14
  // src/contracts/abis/CLFactory.abi.json
13
15
  var CLFactory_abi_default = [
@@ -122,6 +124,73 @@ var CLFactory_abi_default = [
122
124
  }
123
125
  ];
124
126
 
127
+ // src/contracts/abis/CLPool.abi.json
128
+ var CLPool_abi_default = [
129
+ {
130
+ type: "function",
131
+ name: "slot0",
132
+ inputs: [],
133
+ outputs: [
134
+ { name: "sqrtPriceX96", type: "uint160", internalType: "uint160" },
135
+ { name: "tick", type: "int24", internalType: "int24" },
136
+ { name: "observationIndex", type: "uint16", internalType: "uint16" },
137
+ { name: "observationCardinality", type: "uint16", internalType: "uint16" },
138
+ { name: "observationCardinalityNext", type: "uint16", internalType: "uint16" },
139
+ { name: "unlocked", type: "bool", internalType: "bool" }
140
+ ],
141
+ stateMutability: "view"
142
+ },
143
+ {
144
+ type: "function",
145
+ name: "liquidity",
146
+ inputs: [],
147
+ outputs: [{ name: "", type: "uint128", internalType: "uint128" }],
148
+ stateMutability: "view"
149
+ },
150
+ {
151
+ type: "function",
152
+ name: "token0",
153
+ inputs: [],
154
+ outputs: [{ name: "", type: "address", internalType: "address" }],
155
+ stateMutability: "view"
156
+ },
157
+ {
158
+ type: "function",
159
+ name: "token1",
160
+ inputs: [],
161
+ outputs: [{ name: "", type: "address", internalType: "address" }],
162
+ stateMutability: "view"
163
+ },
164
+ {
165
+ type: "function",
166
+ name: "tickSpacing",
167
+ inputs: [],
168
+ outputs: [{ name: "", type: "int24", internalType: "int24" }],
169
+ stateMutability: "view"
170
+ },
171
+ {
172
+ type: "function",
173
+ name: "factory",
174
+ inputs: [],
175
+ outputs: [{ name: "", type: "address", internalType: "address" }],
176
+ stateMutability: "view"
177
+ },
178
+ {
179
+ type: "function",
180
+ name: "gauge",
181
+ inputs: [],
182
+ outputs: [{ name: "", type: "address", internalType: "address" }],
183
+ stateMutability: "view"
184
+ },
185
+ {
186
+ type: "function",
187
+ name: "fee",
188
+ inputs: [],
189
+ outputs: [{ name: "", type: "uint24", internalType: "uint24" }],
190
+ stateMutability: "view"
191
+ }
192
+ ];
193
+
125
194
  // src/contracts/abis/Gauge.abi.json
126
195
  var Gauge_abi_default = [
127
196
  {
@@ -256,6 +325,68 @@ var Minter_abi_default = [
256
325
  }
257
326
  ];
258
327
 
328
+ // src/contracts/abis/NonfungiblePositionManager.abi.json
329
+ var NonfungiblePositionManager_abi_default = [
330
+ {
331
+ type: "function",
332
+ name: "positions",
333
+ inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
334
+ outputs: [
335
+ { name: "nonce", type: "uint96", internalType: "uint96" },
336
+ { name: "operator", type: "address", internalType: "address" },
337
+ { name: "token0", type: "address", internalType: "address" },
338
+ { name: "token1", type: "address", internalType: "address" },
339
+ { name: "tickSpacing", type: "int24", internalType: "int24" },
340
+ { name: "tickLower", type: "int24", internalType: "int24" },
341
+ { name: "tickUpper", type: "int24", internalType: "int24" },
342
+ { name: "liquidity", type: "uint128", internalType: "uint128" },
343
+ { name: "feeGrowthInside0LastX128", type: "uint256", internalType: "uint256" },
344
+ { name: "feeGrowthInside1LastX128", type: "uint256", internalType: "uint256" },
345
+ { name: "tokensOwed0", type: "uint128", internalType: "uint128" },
346
+ { name: "tokensOwed1", type: "uint128", internalType: "uint128" }
347
+ ],
348
+ stateMutability: "view"
349
+ },
350
+ {
351
+ type: "function",
352
+ name: "balanceOf",
353
+ inputs: [{ name: "owner", type: "address", internalType: "address" }],
354
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
355
+ stateMutability: "view"
356
+ },
357
+ {
358
+ type: "function",
359
+ name: "tokenOfOwnerByIndex",
360
+ inputs: [
361
+ { name: "owner", type: "address", internalType: "address" },
362
+ { name: "index", type: "uint256", internalType: "uint256" }
363
+ ],
364
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
365
+ stateMutability: "view"
366
+ },
367
+ {
368
+ type: "function",
369
+ name: "totalSupply",
370
+ inputs: [],
371
+ outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
372
+ stateMutability: "view"
373
+ },
374
+ {
375
+ type: "function",
376
+ name: "factory",
377
+ inputs: [],
378
+ outputs: [{ name: "", type: "address", internalType: "address" }],
379
+ stateMutability: "view"
380
+ },
381
+ {
382
+ type: "function",
383
+ name: "WETH9",
384
+ inputs: [],
385
+ outputs: [{ name: "", type: "address", internalType: "address" }],
386
+ stateMutability: "view"
387
+ }
388
+ ];
389
+
259
390
  // src/contracts/abis/PoolFactory.abi.json
260
391
  var PoolFactory_abi_default = [
261
392
  {
@@ -316,6 +447,64 @@ var PoolFactory_abi_default = [
316
447
  }
317
448
  ];
318
449
 
450
+ // src/contracts/abis/QuoterV2.abi.json
451
+ var QuoterV2_abi_default = [
452
+ {
453
+ type: "function",
454
+ name: "factory",
455
+ inputs: [],
456
+ outputs: [{ name: "", type: "address", internalType: "address" }],
457
+ stateMutability: "view"
458
+ },
459
+ {
460
+ type: "function",
461
+ name: "WETH9",
462
+ inputs: [],
463
+ outputs: [{ name: "", type: "address", internalType: "address" }],
464
+ stateMutability: "view"
465
+ },
466
+ {
467
+ type: "function",
468
+ name: "quoteExactInputSingle",
469
+ inputs: [
470
+ {
471
+ name: "params",
472
+ type: "tuple",
473
+ internalType: "struct IQuoterV2.QuoteExactInputSingleParams",
474
+ components: [
475
+ { name: "tokenIn", type: "address", internalType: "address" },
476
+ { name: "tokenOut", type: "address", internalType: "address" },
477
+ { name: "amountIn", type: "uint256", internalType: "uint256" },
478
+ { name: "tickSpacing", type: "int24", internalType: "int24" },
479
+ { name: "sqrtPriceLimitX96", type: "uint160", internalType: "uint160" }
480
+ ]
481
+ }
482
+ ],
483
+ outputs: [
484
+ { name: "amountOut", type: "uint256", internalType: "uint256" },
485
+ { name: "sqrtPriceX96After", type: "uint160", internalType: "uint160" },
486
+ { name: "initializedTicksCrossed", type: "uint32", internalType: "uint32" },
487
+ { name: "gasEstimate", type: "uint256", internalType: "uint256" }
488
+ ],
489
+ stateMutability: "nonpayable"
490
+ },
491
+ {
492
+ type: "function",
493
+ name: "quoteExactInput",
494
+ inputs: [
495
+ { name: "path", type: "bytes", internalType: "bytes" },
496
+ { name: "amountIn", type: "uint256", internalType: "uint256" }
497
+ ],
498
+ outputs: [
499
+ { name: "amountOut", type: "uint256", internalType: "uint256" },
500
+ { name: "sqrtPriceX96AfterList", type: "uint160[]", internalType: "uint160[]" },
501
+ { name: "initializedTicksCrossedList", type: "uint32[]", internalType: "uint32[]" },
502
+ { name: "gasEstimate", type: "uint256", internalType: "uint256" }
503
+ ],
504
+ stateMutability: "nonpayable"
505
+ }
506
+ ];
507
+
319
508
  // src/contracts/abis/RewardsDistributor.abi.json
320
509
  var RewardsDistributor_abi_default = [
321
510
  {
@@ -668,9 +857,12 @@ var VotingReward_abi_default = [
668
857
 
669
858
  // src/contracts/abis.ts
670
859
  var clFactoryAbi = CLFactory_abi_default;
860
+ var clPoolAbi = CLPool_abi_default;
671
861
  var gaugeAbi = Gauge_abi_default;
672
862
  var minterAbi = Minter_abi_default;
863
+ var nonfungiblePositionManagerAbi = NonfungiblePositionManager_abi_default;
673
864
  var poolFactoryAbi = PoolFactory_abi_default;
865
+ var quoterV2Abi = QuoterV2_abi_default;
674
866
  var rewardsDistributorAbi = RewardsDistributor_abi_default;
675
867
  var voterAbi = Voter_abi_default;
676
868
  var votingEscrowAbi = VotingEscrow_abi_default;
@@ -761,12 +953,549 @@ function createAboreanPublicClient(rpcUrl) {
761
953
  });
762
954
  }
763
955
 
956
+ // src/commands/cl.ts
957
+ var Q96 = 2n ** 96n;
958
+ var MULTICALL_BATCH_SIZE = 100;
959
+ var env = z.object({
960
+ ABSTRACT_RPC_URL: z.string().optional().describe("Abstract RPC URL override")
961
+ });
962
+ var tokenSchema = z.object({
963
+ address: z.string(),
964
+ symbol: z.string(),
965
+ decimals: z.number()
966
+ });
967
+ var poolRowSchema = z.object({
968
+ pool: z.string(),
969
+ pair: z.string(),
970
+ token0: tokenSchema,
971
+ token1: tokenSchema,
972
+ fee: z.number(),
973
+ feePercent: z.number(),
974
+ tickSpacing: z.number(),
975
+ liquidity: z.string(),
976
+ currentTick: z.number(),
977
+ sqrtPriceX96: z.string(),
978
+ activeLiquidityEstimate: z.object({
979
+ token0: z.string(),
980
+ token1: z.string(),
981
+ totalInToken0: z.number().nullable(),
982
+ totalInToken1: z.number().nullable()
983
+ }),
984
+ price: z.object({
985
+ token1PerToken0: z.number().nullable(),
986
+ token0PerToken1: z.number().nullable()
987
+ })
988
+ });
989
+ var quoteOutputSchema = z.object({
990
+ pool: z.string(),
991
+ selectedFee: z.number(),
992
+ selectedTickSpacing: z.number(),
993
+ tokenIn: tokenSchema,
994
+ tokenOut: tokenSchema,
995
+ amountIn: z.object({
996
+ raw: z.string(),
997
+ decimal: z.string()
998
+ }),
999
+ amountOut: z.object({
1000
+ raw: z.string(),
1001
+ decimal: z.string()
1002
+ }),
1003
+ execution: z.object({
1004
+ sqrtPriceX96After: z.string(),
1005
+ initializedTicksCrossed: z.number(),
1006
+ gasEstimate: z.string()
1007
+ }),
1008
+ prices: z.object({
1009
+ poolMidPriceOutPerIn: z.number().nullable(),
1010
+ quotePriceOutPerIn: z.number().nullable(),
1011
+ priceImpactPct: z.number().nullable()
1012
+ })
1013
+ });
1014
+ var erc20MetadataAbi = [
1015
+ {
1016
+ type: "function",
1017
+ name: "symbol",
1018
+ stateMutability: "view",
1019
+ inputs: [],
1020
+ outputs: [{ type: "string" }]
1021
+ },
1022
+ {
1023
+ type: "function",
1024
+ name: "decimals",
1025
+ stateMutability: "view",
1026
+ inputs: [],
1027
+ outputs: [{ type: "uint8" }]
1028
+ }
1029
+ ];
1030
+ function shortAddress(address) {
1031
+ return `${address.slice(0, 6)}\u2026${address.slice(-4)}`;
1032
+ }
1033
+ function finiteOrNull(value) {
1034
+ return Number.isFinite(value) ? value : null;
1035
+ }
1036
+ function toTokenMetaFallback(address) {
1037
+ return {
1038
+ address,
1039
+ symbol: shortAddress(checksumAddress(address)),
1040
+ decimals: 18
1041
+ };
1042
+ }
1043
+ function chunk(items, size) {
1044
+ const out = [];
1045
+ for (let i = 0; i < items.length; i += size) {
1046
+ out.push(items.slice(i, i + size));
1047
+ }
1048
+ return out;
1049
+ }
1050
+ async function multicallAllowFailure(client, contracts) {
1051
+ const batches = chunk(contracts, MULTICALL_BATCH_SIZE);
1052
+ const out = [];
1053
+ for (const batch of batches) {
1054
+ const res = await client.multicall({
1055
+ allowFailure: true,
1056
+ contracts: batch
1057
+ });
1058
+ out.push(...res);
1059
+ }
1060
+ return out;
1061
+ }
1062
+ async function multicallStrict(client, contracts) {
1063
+ const batches = chunk(contracts, MULTICALL_BATCH_SIZE);
1064
+ const out = [];
1065
+ for (const batch of batches) {
1066
+ const res = await client.multicall({
1067
+ allowFailure: false,
1068
+ contracts: batch
1069
+ });
1070
+ out.push(...res);
1071
+ }
1072
+ return out;
1073
+ }
1074
+ function derivePrices(sqrtPriceX96, token0Decimals, token1Decimals) {
1075
+ const sqrtRatio = Number(sqrtPriceX96) / 2 ** 96;
1076
+ const rawPrice = sqrtRatio * sqrtRatio;
1077
+ const decimalScale = 10 ** (token0Decimals - token1Decimals);
1078
+ const token1PerToken0 = finiteOrNull(rawPrice * decimalScale);
1079
+ const token0PerToken1 = token1PerToken0 === null || token1PerToken0 === 0 ? null : finiteOrNull(1 / token1PerToken0);
1080
+ return {
1081
+ token1PerToken0,
1082
+ token0PerToken1
1083
+ };
1084
+ }
1085
+ function estimateActiveLiquidity(liquidity, sqrtPriceX96, token0Decimals, token1Decimals, prices) {
1086
+ if (sqrtPriceX96 === 0n) {
1087
+ return {
1088
+ token0: "0",
1089
+ token1: "0",
1090
+ totalInToken0: null,
1091
+ totalInToken1: null
1092
+ };
1093
+ }
1094
+ const reserve0Raw = liquidity * Q96 / sqrtPriceX96;
1095
+ const reserve1Raw = liquidity * sqrtPriceX96 / Q96;
1096
+ const reserve0 = Number(formatUnits(reserve0Raw, token0Decimals));
1097
+ const reserve1 = Number(formatUnits(reserve1Raw, token1Decimals));
1098
+ const totalInToken1 = prices.token1PerToken0 === null ? null : finiteOrNull(reserve1 + reserve0 * prices.token1PerToken0);
1099
+ const totalInToken0 = prices.token0PerToken1 === null ? null : finiteOrNull(reserve0 + reserve1 * prices.token0PerToken1);
1100
+ return {
1101
+ token0: formatUnits(reserve0Raw, token0Decimals),
1102
+ token1: formatUnits(reserve1Raw, token1Decimals),
1103
+ totalInToken0,
1104
+ totalInToken1
1105
+ };
1106
+ }
1107
+ async function readTokenMetadata(client, tokenAddresses) {
1108
+ const uniqueTokens = [...new Set(tokenAddresses.map((x) => x.toLowerCase()))];
1109
+ if (uniqueTokens.length === 0) {
1110
+ return /* @__PURE__ */ new Map();
1111
+ }
1112
+ const contracts = uniqueTokens.flatMap((address) => [
1113
+ {
1114
+ abi: erc20MetadataAbi,
1115
+ address,
1116
+ functionName: "symbol"
1117
+ },
1118
+ {
1119
+ abi: erc20MetadataAbi,
1120
+ address,
1121
+ functionName: "decimals"
1122
+ }
1123
+ ]);
1124
+ const results = await multicallAllowFailure(client, contracts);
1125
+ const out = /* @__PURE__ */ new Map();
1126
+ for (let i = 0; i < uniqueTokens.length; i += 1) {
1127
+ const address = uniqueTokens[i];
1128
+ const symbolResult = results[i * 2];
1129
+ const decimalsResult = results[i * 2 + 1];
1130
+ const fallback = toTokenMetaFallback(address);
1131
+ const symbol = symbolResult && symbolResult.status === "success" && typeof symbolResult.result === "string" ? symbolResult.result : fallback.symbol;
1132
+ const decimals = decimalsResult && decimalsResult.status === "success" && typeof decimalsResult.result === "number" ? decimalsResult.result : fallback.decimals;
1133
+ out.set(address, {
1134
+ address: checksumAddress(address),
1135
+ symbol,
1136
+ decimals
1137
+ });
1138
+ }
1139
+ return out;
1140
+ }
1141
+ async function listPoolAddresses(client) {
1142
+ const count = await client.readContract({
1143
+ abi: clFactoryAbi,
1144
+ address: ABOREAN_CL_ADDRESSES.clFactory,
1145
+ functionName: "allPoolsLength"
1146
+ });
1147
+ if (count === 0n) {
1148
+ return [];
1149
+ }
1150
+ const poolIndexContracts = Array.from({ length: Number(count) }, (_, i) => ({
1151
+ abi: clFactoryAbi,
1152
+ address: ABOREAN_CL_ADDRESSES.clFactory,
1153
+ functionName: "allPools",
1154
+ args: [BigInt(i)]
1155
+ }));
1156
+ const poolAddresses = await multicallStrict(client, poolIndexContracts);
1157
+ return poolAddresses;
1158
+ }
1159
+ async function readPoolStates(client, poolAddresses) {
1160
+ if (poolAddresses.length === 0) {
1161
+ return [];
1162
+ }
1163
+ const poolContracts = poolAddresses.flatMap((pool) => [
1164
+ {
1165
+ abi: clPoolAbi,
1166
+ address: pool,
1167
+ functionName: "token0"
1168
+ },
1169
+ {
1170
+ abi: clPoolAbi,
1171
+ address: pool,
1172
+ functionName: "token1"
1173
+ },
1174
+ {
1175
+ abi: clPoolAbi,
1176
+ address: pool,
1177
+ functionName: "tickSpacing"
1178
+ },
1179
+ {
1180
+ abi: clPoolAbi,
1181
+ address: pool,
1182
+ functionName: "fee"
1183
+ },
1184
+ {
1185
+ abi: clPoolAbi,
1186
+ address: pool,
1187
+ functionName: "liquidity"
1188
+ },
1189
+ {
1190
+ abi: clPoolAbi,
1191
+ address: pool,
1192
+ functionName: "slot0"
1193
+ }
1194
+ ]);
1195
+ const values = await multicallStrict(client, poolContracts);
1196
+ return poolAddresses.map((pool, i) => ({
1197
+ pool,
1198
+ token0: values[i * 6],
1199
+ token1: values[i * 6 + 1],
1200
+ tickSpacing: Number(values[i * 6 + 2]),
1201
+ fee: Number(values[i * 6 + 3]),
1202
+ liquidity: values[i * 6 + 4],
1203
+ slot0: values[i * 6 + 5]
1204
+ }));
1205
+ }
1206
+ function toPoolRow(pool, tokenMeta) {
1207
+ const token0 = tokenMeta.get(pool.token0) ?? toTokenMetaFallback(pool.token0);
1208
+ const token1 = tokenMeta.get(pool.token1) ?? toTokenMetaFallback(pool.token1);
1209
+ const prices = derivePrices(pool.slot0[0], token0.decimals, token1.decimals);
1210
+ const activeLiquidityEstimate = estimateActiveLiquidity(
1211
+ pool.liquidity,
1212
+ pool.slot0[0],
1213
+ token0.decimals,
1214
+ token1.decimals,
1215
+ prices
1216
+ );
1217
+ return {
1218
+ pool: checksumAddress(pool.pool),
1219
+ pair: `${token0.symbol}/${token1.symbol}`,
1220
+ token0,
1221
+ token1,
1222
+ fee: pool.fee,
1223
+ feePercent: pool.fee / 1e4,
1224
+ tickSpacing: pool.tickSpacing,
1225
+ liquidity: pool.liquidity.toString(),
1226
+ currentTick: pool.slot0[1],
1227
+ sqrtPriceX96: pool.slot0[0].toString(),
1228
+ activeLiquidityEstimate,
1229
+ price: prices
1230
+ };
1231
+ }
1232
+ function normalizeAddress(address) {
1233
+ return address.toLowerCase();
1234
+ }
1235
+ var cl = Cli.create("cl", {
1236
+ description: "Concentrated liquidity (Slipstream) pools, positions, and quotes."
1237
+ });
1238
+ cl.command("pools", {
1239
+ description: "List Slipstream pools with current state, prices, and active liquidity estimate.",
1240
+ env,
1241
+ output: z.object({
1242
+ count: z.number(),
1243
+ pools: z.array(poolRowSchema)
1244
+ }),
1245
+ async run(c) {
1246
+ const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
1247
+ const pools = await listPoolAddresses(client);
1248
+ const poolStates = await readPoolStates(client, pools);
1249
+ const tokenMeta = await readTokenMetadata(
1250
+ client,
1251
+ poolStates.flatMap((pool) => [pool.token0, pool.token1])
1252
+ );
1253
+ const rows = poolStates.map((pool) => toPoolRow(pool, tokenMeta));
1254
+ return c.ok({
1255
+ count: rows.length,
1256
+ pools: rows
1257
+ });
1258
+ }
1259
+ });
1260
+ cl.command("pool", {
1261
+ description: "Get detailed state for a Slipstream pool address.",
1262
+ args: z.object({
1263
+ pool: z.string().describe("Pool address")
1264
+ }),
1265
+ env,
1266
+ output: z.object({
1267
+ pool: poolRowSchema
1268
+ }),
1269
+ async run(c) {
1270
+ if (!isAddress(c.args.pool)) {
1271
+ return c.error({
1272
+ code: "INVALID_ADDRESS",
1273
+ message: `Invalid pool address: "${c.args.pool}". Use a valid 0x-prefixed 20-byte hex address.`
1274
+ });
1275
+ }
1276
+ const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
1277
+ const checksummedPool = checksumAddress(c.args.pool);
1278
+ const [poolState] = await readPoolStates(client, [checksummedPool]);
1279
+ const tokenMeta = await readTokenMetadata(client, [poolState.token0, poolState.token1]);
1280
+ return c.ok({
1281
+ pool: toPoolRow(poolState, tokenMeta)
1282
+ });
1283
+ }
1284
+ });
1285
+ cl.command("positions", {
1286
+ description: "List concentrated liquidity NFT positions for an owner.",
1287
+ args: z.object({
1288
+ owner: z.string().describe("Owner wallet address")
1289
+ }),
1290
+ env,
1291
+ output: z.object({
1292
+ owner: z.string(),
1293
+ count: z.number(),
1294
+ positions: z.array(
1295
+ z.object({
1296
+ tokenId: z.string(),
1297
+ pair: z.string(),
1298
+ token0: tokenSchema,
1299
+ token1: tokenSchema,
1300
+ tickSpacing: z.number(),
1301
+ tickLower: z.number(),
1302
+ tickUpper: z.number(),
1303
+ liquidity: z.string(),
1304
+ tokensOwed0: z.object({ raw: z.string(), decimal: z.string() }),
1305
+ tokensOwed1: z.object({ raw: z.string(), decimal: z.string() })
1306
+ })
1307
+ )
1308
+ }),
1309
+ async run(c) {
1310
+ if (!isAddress(c.args.owner)) {
1311
+ return c.error({
1312
+ code: "INVALID_ADDRESS",
1313
+ message: `Invalid owner address: "${c.args.owner}". Use a valid 0x-prefixed 20-byte hex address.`
1314
+ });
1315
+ }
1316
+ const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
1317
+ const owner = checksumAddress(c.args.owner);
1318
+ const balance = await client.readContract({
1319
+ abi: nonfungiblePositionManagerAbi,
1320
+ address: ABOREAN_CL_ADDRESSES.nonfungiblePositionManager,
1321
+ functionName: "balanceOf",
1322
+ args: [owner]
1323
+ });
1324
+ if (balance === 0n) {
1325
+ return c.ok({ owner, count: 0, positions: [] });
1326
+ }
1327
+ const tokenIdContracts = Array.from({ length: Number(balance) }, (_, i) => ({
1328
+ abi: nonfungiblePositionManagerAbi,
1329
+ address: ABOREAN_CL_ADDRESSES.nonfungiblePositionManager,
1330
+ functionName: "tokenOfOwnerByIndex",
1331
+ args: [owner, BigInt(i)]
1332
+ }));
1333
+ const tokenIds = await multicallStrict(client, tokenIdContracts);
1334
+ const positionContracts = tokenIds.map((tokenId) => ({
1335
+ abi: nonfungiblePositionManagerAbi,
1336
+ address: ABOREAN_CL_ADDRESSES.nonfungiblePositionManager,
1337
+ functionName: "positions",
1338
+ args: [tokenId]
1339
+ }));
1340
+ const positionsRaw = await multicallStrict(client, positionContracts);
1341
+ const tokenMeta = await readTokenMetadata(
1342
+ client,
1343
+ positionsRaw.flatMap((position) => [position[2], position[3]])
1344
+ );
1345
+ const positions = tokenIds.map((tokenId, i) => {
1346
+ const position = positionsRaw[i];
1347
+ const token0 = tokenMeta.get(position[2]) ?? toTokenMetaFallback(position[2]);
1348
+ const token1 = tokenMeta.get(position[3]) ?? toTokenMetaFallback(position[3]);
1349
+ return {
1350
+ tokenId: tokenId.toString(),
1351
+ pair: `${token0.symbol}/${token1.symbol}`,
1352
+ token0,
1353
+ token1,
1354
+ tickSpacing: position[4],
1355
+ tickLower: position[5],
1356
+ tickUpper: position[6],
1357
+ liquidity: position[7].toString(),
1358
+ tokensOwed0: {
1359
+ raw: position[10].toString(),
1360
+ decimal: formatUnits(position[10], token0.decimals)
1361
+ },
1362
+ tokensOwed1: {
1363
+ raw: position[11].toString(),
1364
+ decimal: formatUnits(position[11], token1.decimals)
1365
+ }
1366
+ };
1367
+ });
1368
+ return c.ok({
1369
+ owner,
1370
+ count: positions.length,
1371
+ positions
1372
+ });
1373
+ }
1374
+ });
1375
+ cl.command("quote", {
1376
+ description: "Quote a single-hop Slipstream swap via QuoterV2.",
1377
+ args: z.object({
1378
+ tokenIn: z.string().describe("Input token address"),
1379
+ tokenOut: z.string().describe("Output token address"),
1380
+ amountIn: z.string().describe("Input amount in human-readable decimal units")
1381
+ }),
1382
+ options: z.object({
1383
+ fee: z.coerce.number().int().positive().optional().describe("Optional fee tier filter")
1384
+ }),
1385
+ env,
1386
+ output: quoteOutputSchema,
1387
+ async run(c) {
1388
+ const { tokenIn, tokenOut, amountIn } = c.args;
1389
+ if (!isAddress(tokenIn) || !isAddress(tokenOut)) {
1390
+ return c.error({
1391
+ code: "INVALID_ADDRESS",
1392
+ message: "tokenIn and tokenOut must both be valid 0x-prefixed 20-byte addresses."
1393
+ });
1394
+ }
1395
+ const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
1396
+ const inAddress = checksumAddress(tokenIn);
1397
+ const outAddress = checksumAddress(tokenOut);
1398
+ const allPools = await listPoolAddresses(client);
1399
+ const poolStates = await readPoolStates(client, allPools);
1400
+ const pairPools = poolStates.filter((pool) => {
1401
+ const a = normalizeAddress(pool.token0);
1402
+ const b = normalizeAddress(pool.token1);
1403
+ const tokenInNorm = normalizeAddress(inAddress);
1404
+ const tokenOutNorm = normalizeAddress(outAddress);
1405
+ return a === tokenInNorm && b === tokenOutNorm || a === tokenOutNorm && b === tokenInNorm;
1406
+ });
1407
+ const filteredPools = typeof c.options.fee === "number" ? pairPools.filter((pool) => pool.fee === c.options.fee) : pairPools;
1408
+ if (filteredPools.length === 0) {
1409
+ return c.error({
1410
+ code: "POOL_NOT_FOUND",
1411
+ message: typeof c.options.fee === "number" ? `No Slipstream pool found for pair ${inAddress}/${outAddress} at fee tier ${c.options.fee}.` : `No Slipstream pool found for pair ${inAddress}/${outAddress}.`
1412
+ });
1413
+ }
1414
+ const selectedPool = [...filteredPools].sort((a, b) => {
1415
+ if (a.liquidity === b.liquidity) return 0;
1416
+ return a.liquidity > b.liquidity ? -1 : 1;
1417
+ })[0];
1418
+ const tokenMeta = await readTokenMetadata(client, [inAddress, outAddress]);
1419
+ const inMeta = tokenMeta.get(inAddress) ?? toTokenMetaFallback(inAddress);
1420
+ const outMeta = tokenMeta.get(outAddress) ?? toTokenMetaFallback(outAddress);
1421
+ let amountInRaw;
1422
+ try {
1423
+ amountInRaw = parseUnits(amountIn, inMeta.decimals);
1424
+ } catch {
1425
+ return c.error({
1426
+ code: "INVALID_AMOUNT",
1427
+ message: `Invalid amountIn: "${amountIn}" for token ${inMeta.symbol} (${inMeta.decimals} decimals).`
1428
+ });
1429
+ }
1430
+ const quote = await client.readContract({
1431
+ abi: quoterV2Abi,
1432
+ address: ABOREAN_CL_ADDRESSES.quoterV2,
1433
+ functionName: "quoteExactInputSingle",
1434
+ args: [
1435
+ {
1436
+ tokenIn: inAddress,
1437
+ tokenOut: outAddress,
1438
+ amountIn: amountInRaw,
1439
+ tickSpacing: selectedPool.tickSpacing,
1440
+ sqrtPriceLimitX96: 0n
1441
+ }
1442
+ ]
1443
+ });
1444
+ const amountOutRaw = quote[0];
1445
+ const amountOutDecimal = formatUnits(amountOutRaw, outMeta.decimals);
1446
+ const amountInDecimal = formatUnits(amountInRaw, inMeta.decimals);
1447
+ const quotePriceOutPerIn = Number(amountInDecimal) === 0 ? null : finiteOrNull(Number(amountOutDecimal) / Number(amountInDecimal));
1448
+ const poolTokenMeta = await readTokenMetadata(client, [
1449
+ selectedPool.token0,
1450
+ selectedPool.token1
1451
+ ]);
1452
+ const poolToken0Meta = poolTokenMeta.get(selectedPool.token0) ?? toTokenMetaFallback(selectedPool.token0);
1453
+ const poolToken1Meta = poolTokenMeta.get(selectedPool.token1) ?? toTokenMetaFallback(selectedPool.token1);
1454
+ const poolPrices = derivePrices(
1455
+ selectedPool.slot0[0],
1456
+ poolToken0Meta.decimals,
1457
+ poolToken1Meta.decimals
1458
+ );
1459
+ const inIsToken0 = normalizeAddress(inAddress) === normalizeAddress(selectedPool.token0);
1460
+ const poolMidPriceOutPerIn = inIsToken0 ? poolPrices.token1PerToken0 : poolPrices.token0PerToken1;
1461
+ const priceImpactPct = quotePriceOutPerIn === null || poolMidPriceOutPerIn === null || poolMidPriceOutPerIn === 0 ? null : finiteOrNull((poolMidPriceOutPerIn - quotePriceOutPerIn) / poolMidPriceOutPerIn * 100);
1462
+ return c.ok({
1463
+ pool: checksumAddress(selectedPool.pool),
1464
+ selectedFee: selectedPool.fee,
1465
+ selectedTickSpacing: selectedPool.tickSpacing,
1466
+ tokenIn: inMeta,
1467
+ tokenOut: outMeta,
1468
+ amountIn: {
1469
+ raw: amountInRaw.toString(),
1470
+ decimal: amountInDecimal
1471
+ },
1472
+ amountOut: {
1473
+ raw: amountOutRaw.toString(),
1474
+ decimal: amountOutDecimal
1475
+ },
1476
+ execution: {
1477
+ sqrtPriceX96After: quote[1].toString(),
1478
+ initializedTicksCrossed: quote[2],
1479
+ gasEstimate: quote[3].toString()
1480
+ },
1481
+ prices: {
1482
+ poolMidPriceOutPerIn,
1483
+ quotePriceOutPerIn,
1484
+ priceImpactPct
1485
+ }
1486
+ });
1487
+ }
1488
+ });
1489
+
1490
+ // src/commands/gauges.ts
1491
+ import { Cli as Cli2, z as z2 } from "incur";
1492
+
764
1493
  // src/commands/_common.ts
765
- import { checksumAddress, weiToEth } from "@spectratools/cli-shared";
1494
+ import { checksumAddress as checksumAddress2, weiToEth } from "@spectratools/cli-shared";
766
1495
  var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
767
1496
  function toChecksum(address) {
768
1497
  try {
769
- return checksumAddress(address);
1498
+ return checksumAddress2(address);
770
1499
  } catch {
771
1500
  return address;
772
1501
  }
@@ -789,8 +1518,8 @@ function clampPositive(seconds) {
789
1518
  }
790
1519
 
791
1520
  // src/commands/gauges.ts
792
- var env = z.object({
793
- ABSTRACT_RPC_URL: z.string().optional().describe("Abstract RPC URL override")
1521
+ var env2 = z2.object({
1522
+ ABSTRACT_RPC_URL: z2.string().optional().describe("Abstract RPC URL override")
794
1523
  });
795
1524
  async function discoverGaugePools(client) {
796
1525
  const [v2PoolCount, clPoolCount] = await Promise.all([
@@ -840,26 +1569,26 @@ async function discoverGaugePools(client) {
840
1569
  });
841
1570
  return pools.map((pool, index) => ({ pool, gauge: gauges2[index] })).filter(({ gauge }) => gauge.toLowerCase() !== ZERO_ADDRESS.toLowerCase());
842
1571
  }
843
- var gauges = Cli.create("gauges", {
1572
+ var gauges = Cli2.create("gauges", {
844
1573
  description: "Inspect Aborean gauge emissions, staking, and user positions."
845
1574
  });
846
1575
  gauges.command("list", {
847
1576
  description: "List active gauges with pool, emissions, and staking stats.",
848
- env,
849
- output: z.object({
850
- gauges: z.array(
851
- z.object({
852
- pool: z.string(),
853
- gauge: z.string(),
854
- rewardToken: z.string(),
855
- rewardRate: z.string(),
856
- totalStaked: z.string(),
857
- claimableEmissions: z.string(),
858
- periodFinish: z.number(),
859
- periodFinishRelative: z.string()
1577
+ env: env2,
1578
+ output: z2.object({
1579
+ gauges: z2.array(
1580
+ z2.object({
1581
+ pool: z2.string(),
1582
+ gauge: z2.string(),
1583
+ rewardToken: z2.string(),
1584
+ rewardRate: z2.string(),
1585
+ totalStaked: z2.string(),
1586
+ claimableEmissions: z2.string(),
1587
+ periodFinish: z2.number(),
1588
+ periodFinishRelative: z2.string()
860
1589
  })
861
1590
  ),
862
- count: z.number()
1591
+ count: z2.number()
863
1592
  }),
864
1593
  examples: [{ description: "List all active gauges and current emissions state" }],
865
1594
  async run(c) {
@@ -925,27 +1654,27 @@ gauges.command("list", {
925
1654
  });
926
1655
  gauges.command("info", {
927
1656
  description: "Get detailed state for one gauge address.",
928
- args: z.object({
929
- gauge: z.string().describe("Gauge contract address")
1657
+ args: z2.object({
1658
+ gauge: z2.string().describe("Gauge contract address")
930
1659
  }),
931
- env,
932
- output: z.object({
933
- gauge: z.string(),
934
- pool: z.string(),
935
- isAlive: z.boolean(),
936
- stakingToken: z.string(),
937
- rewardToken: z.string(),
938
- totalStaked: z.string(),
939
- rewardRate: z.string(),
940
- rewardPerTokenStored: z.string(),
941
- fees0: z.string(),
942
- fees1: z.string(),
943
- left: z.string(),
944
- periodFinish: z.number(),
945
- periodFinishRelative: z.string(),
946
- lastUpdateTime: z.number(),
947
- bribeContract: z.string(),
948
- feeContract: z.string()
1660
+ env: env2,
1661
+ output: z2.object({
1662
+ gauge: z2.string(),
1663
+ pool: z2.string(),
1664
+ isAlive: z2.boolean(),
1665
+ stakingToken: z2.string(),
1666
+ rewardToken: z2.string(),
1667
+ totalStaked: z2.string(),
1668
+ rewardRate: z2.string(),
1669
+ rewardPerTokenStored: z2.string(),
1670
+ fees0: z2.string(),
1671
+ fees1: z2.string(),
1672
+ left: z2.string(),
1673
+ periodFinish: z2.number(),
1674
+ periodFinishRelative: z2.string(),
1675
+ lastUpdateTime: z2.number(),
1676
+ bribeContract: z2.string(),
1677
+ feeContract: z2.string()
949
1678
  }),
950
1679
  examples: [
951
1680
  {
@@ -1069,22 +1798,22 @@ gauges.command("info", {
1069
1798
  });
1070
1799
  gauges.command("staked", {
1071
1800
  description: "Show one address staking positions across all gauges.",
1072
- args: z.object({
1073
- address: z.string().describe("Wallet address to inspect")
1801
+ args: z2.object({
1802
+ address: z2.string().describe("Wallet address to inspect")
1074
1803
  }),
1075
- env,
1076
- output: z.object({
1077
- address: z.string(),
1078
- positions: z.array(
1079
- z.object({
1080
- pool: z.string(),
1081
- gauge: z.string(),
1082
- rewardToken: z.string(),
1083
- staked: z.string(),
1084
- earned: z.string()
1804
+ env: env2,
1805
+ output: z2.object({
1806
+ address: z2.string(),
1807
+ positions: z2.array(
1808
+ z2.object({
1809
+ pool: z2.string(),
1810
+ gauge: z2.string(),
1811
+ rewardToken: z2.string(),
1812
+ staked: z2.string(),
1813
+ earned: z2.string()
1085
1814
  })
1086
1815
  ),
1087
- count: z.number()
1816
+ count: z2.number()
1088
1817
  }),
1089
1818
  examples: [
1090
1819
  {
@@ -1152,26 +1881,26 @@ gauges.command("staked", {
1152
1881
  });
1153
1882
 
1154
1883
  // src/commands/ve.ts
1155
- import { Cli as Cli2, z as z2 } from "incur";
1156
- var env2 = z2.object({
1157
- ABSTRACT_RPC_URL: z2.string().optional().describe("Abstract RPC URL override")
1884
+ import { Cli as Cli3, z as z3 } from "incur";
1885
+ var env3 = z3.object({
1886
+ ABSTRACT_RPC_URL: z3.string().optional().describe("Abstract RPC URL override")
1158
1887
  });
1159
- var ve = Cli2.create("ve", {
1888
+ var ve = Cli3.create("ve", {
1160
1889
  description: "Inspect Aborean VotingEscrow (veABX) global and per-NFT lock state."
1161
1890
  });
1162
1891
  ve.command("stats", {
1163
1892
  description: "Get global VotingEscrow supply, locks, and decay checkpoint data.",
1164
- env: env2,
1165
- output: z2.object({
1166
- token: z2.string(),
1167
- totalVotingPower: z2.string(),
1168
- totalLocked: z2.string(),
1169
- permanentLocked: z2.string(),
1170
- epoch: z2.number(),
1171
- decayBias: z2.string(),
1172
- decaySlope: z2.string(),
1173
- lastCheckpointTimestamp: z2.number(),
1174
- lastCheckpointBlock: z2.number()
1893
+ env: env3,
1894
+ output: z3.object({
1895
+ token: z3.string(),
1896
+ totalVotingPower: z3.string(),
1897
+ totalLocked: z3.string(),
1898
+ permanentLocked: z3.string(),
1899
+ epoch: z3.number(),
1900
+ decayBias: z3.string(),
1901
+ decaySlope: z3.string(),
1902
+ lastCheckpointTimestamp: z3.number(),
1903
+ lastCheckpointBlock: z3.number()
1175
1904
  }),
1176
1905
  examples: [{ description: "Show global veABX state and decay metrics" }],
1177
1906
  async run(c) {
@@ -1224,17 +1953,17 @@ ve.command("stats", {
1224
1953
  });
1225
1954
  ve.command("lock", {
1226
1955
  description: "Get lock details and voting power for one veNFT token id.",
1227
- args: z2.object({
1228
- tokenId: z2.coerce.number().int().nonnegative().describe("veNFT token id")
1956
+ args: z3.object({
1957
+ tokenId: z3.coerce.number().int().nonnegative().describe("veNFT token id")
1229
1958
  }),
1230
- env: env2,
1231
- output: z2.object({
1232
- tokenId: z2.number(),
1233
- owner: z2.string(),
1234
- amount: z2.string(),
1235
- unlockTime: z2.number(),
1236
- isPermanent: z2.boolean(),
1237
- votingPower: z2.string()
1959
+ env: env3,
1960
+ output: z3.object({
1961
+ tokenId: z3.number(),
1962
+ owner: z3.string(),
1963
+ amount: z3.string(),
1964
+ unlockTime: z3.number(),
1965
+ isPermanent: z3.boolean(),
1966
+ votingPower: z3.string()
1238
1967
  }),
1239
1968
  examples: [{ args: { tokenId: 1 }, description: "Inspect lock details for veNFT #1" }],
1240
1969
  async run(c) {
@@ -1272,22 +2001,22 @@ ve.command("lock", {
1272
2001
  });
1273
2002
  ve.command("locks", {
1274
2003
  description: "List all veNFT locks owned by an address.",
1275
- args: z2.object({
1276
- address: z2.string().describe("Owner address")
2004
+ args: z3.object({
2005
+ address: z3.string().describe("Owner address")
1277
2006
  }),
1278
- env: env2,
1279
- output: z2.object({
1280
- address: z2.string(),
1281
- locks: z2.array(
1282
- z2.object({
1283
- tokenId: z2.string(),
1284
- amount: z2.string(),
1285
- unlockTime: z2.number(),
1286
- isPermanent: z2.boolean(),
1287
- votingPower: z2.string()
2007
+ env: env3,
2008
+ output: z3.object({
2009
+ address: z3.string(),
2010
+ locks: z3.array(
2011
+ z3.object({
2012
+ tokenId: z3.string(),
2013
+ amount: z3.string(),
2014
+ unlockTime: z3.number(),
2015
+ isPermanent: z3.boolean(),
2016
+ votingPower: z3.string()
1288
2017
  })
1289
2018
  ),
1290
- count: z2.number()
2019
+ count: z3.number()
1291
2020
  }),
1292
2021
  examples: [
1293
2022
  {
@@ -1359,13 +2088,13 @@ ve.command("locks", {
1359
2088
  });
1360
2089
  ve.command("voting-power", {
1361
2090
  description: "Get current voting power for one veNFT token id.",
1362
- args: z2.object({
1363
- tokenId: z2.coerce.number().int().nonnegative().describe("veNFT token id")
2091
+ args: z3.object({
2092
+ tokenId: z3.coerce.number().int().nonnegative().describe("veNFT token id")
1364
2093
  }),
1365
- env: env2,
1366
- output: z2.object({
1367
- tokenId: z2.number(),
1368
- votingPower: z2.string()
2094
+ env: env3,
2095
+ output: z3.object({
2096
+ tokenId: z3.number(),
2097
+ votingPower: z3.string()
1369
2098
  }),
1370
2099
  examples: [{ args: { tokenId: 1 }, description: "Get current voting power for veNFT #1" }],
1371
2100
  async run(c) {
@@ -1384,9 +2113,9 @@ ve.command("voting-power", {
1384
2113
  });
1385
2114
 
1386
2115
  // src/commands/voter.ts
1387
- import { Cli as Cli3, z as z3 } from "incur";
1388
- var env3 = z3.object({
1389
- ABSTRACT_RPC_URL: z3.string().optional().describe("Abstract RPC URL override")
2116
+ import { Cli as Cli4, z as z4 } from "incur";
2117
+ var env4 = z4.object({
2118
+ ABSTRACT_RPC_URL: z4.string().optional().describe("Abstract RPC URL override")
1390
2119
  });
1391
2120
  async function discoverPools(client) {
1392
2121
  const [v2PoolCount, clPoolCount] = await Promise.all([
@@ -1425,20 +2154,20 @@ async function discoverPools(client) {
1425
2154
  ]);
1426
2155
  return [...v2Pools, ...clPools];
1427
2156
  }
1428
- var voter = Cli3.create("voter", {
2157
+ var voter = Cli4.create("voter", {
1429
2158
  description: "Inspect Aborean voter epoch, pool weights, and claimable rewards context."
1430
2159
  });
1431
2160
  voter.command("epoch", {
1432
2161
  description: "Show current emissions epoch timing from Minter.",
1433
- env: env3,
1434
- output: z3.object({
1435
- activePeriod: z3.number(),
1436
- epochEnd: z3.number(),
1437
- secondsRemaining: z3.number(),
1438
- timeRemaining: z3.string(),
1439
- weekSeconds: z3.number(),
1440
- epochCount: z3.number(),
1441
- weeklyEmission: z3.string()
2162
+ env: env4,
2163
+ output: z4.object({
2164
+ activePeriod: z4.number(),
2165
+ epochEnd: z4.number(),
2166
+ secondsRemaining: z4.number(),
2167
+ timeRemaining: z4.string(),
2168
+ weekSeconds: z4.number(),
2169
+ epochCount: z4.number(),
2170
+ weeklyEmission: z4.string()
1442
2171
  }),
1443
2172
  examples: [{ description: "Inspect current voter epoch boundaries" }],
1444
2173
  async run(c) {
@@ -1480,17 +2209,17 @@ voter.command("epoch", {
1480
2209
  });
1481
2210
  voter.command("weights", {
1482
2211
  description: "Show current pool voting weight distribution.",
1483
- env: env3,
1484
- output: z3.object({
1485
- totalWeight: z3.string(),
1486
- pools: z3.array(
1487
- z3.object({
1488
- pool: z3.string(),
1489
- gauge: z3.string(),
1490
- weight: z3.string()
2212
+ env: env4,
2213
+ output: z4.object({
2214
+ totalWeight: z4.string(),
2215
+ pools: z4.array(
2216
+ z4.object({
2217
+ pool: z4.string(),
2218
+ gauge: z4.string(),
2219
+ weight: z4.string()
1491
2220
  })
1492
2221
  ),
1493
- count: z3.number()
2222
+ count: z4.number()
1494
2223
  }),
1495
2224
  examples: [{ description: "List all pools with non-zero voting weight" }],
1496
2225
  async run(c) {
@@ -1548,19 +2277,19 @@ voter.command("weights", {
1548
2277
  });
1549
2278
  voter.command("rewards", {
1550
2279
  description: "Show claimable rebase rewards and voting context for a veNFT.",
1551
- args: z3.object({
1552
- tokenId: z3.coerce.number().int().nonnegative().describe("veNFT token id")
2280
+ args: z4.object({
2281
+ tokenId: z4.coerce.number().int().nonnegative().describe("veNFT token id")
1553
2282
  }),
1554
- env: env3,
1555
- output: z3.object({
1556
- tokenId: z3.number(),
1557
- rewardToken: z3.string(),
1558
- claimableRebase: z3.string(),
1559
- timeCursor: z3.number(),
1560
- lastTokenTime: z3.number(),
1561
- distributorStartTime: z3.number(),
1562
- usedWeight: z3.string(),
1563
- lastVoted: z3.number()
2283
+ env: env4,
2284
+ output: z4.object({
2285
+ tokenId: z4.number(),
2286
+ rewardToken: z4.string(),
2287
+ claimableRebase: z4.string(),
2288
+ timeCursor: z4.number(),
2289
+ lastTokenTime: z4.number(),
2290
+ distributorStartTime: z4.number(),
2291
+ usedWeight: z4.string(),
2292
+ lastVoted: z4.number()
1564
2293
  }),
1565
2294
  examples: [{ args: { tokenId: 1 }, description: "Check claimable voter/distributor rewards" }],
1566
2295
  async run(c) {
@@ -1629,22 +2358,22 @@ voter.command("rewards", {
1629
2358
  });
1630
2359
  voter.command("bribes", {
1631
2360
  description: "Show active bribe reward tokens and current-epoch amounts for a pool.",
1632
- args: z3.object({
1633
- pool: z3.string().describe("Pool address")
2361
+ args: z4.object({
2362
+ pool: z4.string().describe("Pool address")
1634
2363
  }),
1635
- env: env3,
1636
- output: z3.object({
1637
- pool: z3.string(),
1638
- gauge: z3.string(),
1639
- bribeContract: z3.string(),
1640
- epochStart: z3.number(),
1641
- rewardTokens: z3.array(
1642
- z3.object({
1643
- token: z3.string(),
1644
- epochAmount: z3.string()
2364
+ env: env4,
2365
+ output: z4.object({
2366
+ pool: z4.string(),
2367
+ gauge: z4.string(),
2368
+ bribeContract: z4.string(),
2369
+ epochStart: z4.number(),
2370
+ rewardTokens: z4.array(
2371
+ z4.object({
2372
+ token: z4.string(),
2373
+ epochAmount: z4.string()
1645
2374
  })
1646
2375
  ),
1647
- count: z3.number()
2376
+ count: z4.number()
1648
2377
  }),
1649
2378
  examples: [
1650
2379
  {
@@ -1870,26 +2599,27 @@ function applyFriendlyErrorHandling(cli2) {
1870
2599
  // src/cli.ts
1871
2600
  var __dirname = dirname(fileURLToPath(import.meta.url));
1872
2601
  var pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf8"));
1873
- var cli = Cli4.create("aborean", {
2602
+ var cli = Cli5.create("aborean", {
1874
2603
  version: pkg.version,
1875
2604
  description: "Aborean Finance DEX CLI for Abstract chain."
1876
2605
  });
1877
2606
  cli.command(gauges);
1878
2607
  cli.command(ve);
1879
2608
  cli.command(voter);
1880
- var rootEnv = z4.object({
1881
- ABSTRACT_RPC_URL: z4.string().optional().describe("Abstract RPC URL override")
2609
+ var rootEnv = z5.object({
2610
+ ABSTRACT_RPC_URL: z5.string().optional().describe("Abstract RPC URL override")
1882
2611
  });
2612
+ cli.command(cl);
1883
2613
  cli.command("status", {
1884
2614
  description: "Get a cross-contract Aborean protocol snapshot (pool counts, gauge count, veABX supply).",
1885
2615
  env: rootEnv,
1886
- output: z4.object({
1887
- v2PoolCount: z4.number().describe("Number of V2 AMM pools"),
1888
- clPoolCount: z4.number().describe("Number of Slipstream (CL) pools"),
1889
- gaugeCount: z4.number().describe("Number of pools with gauges"),
1890
- totalVotingWeight: z4.string().describe("Total voting weight (wei)"),
1891
- veABXTotalSupply: z4.string().describe("Total veABX supply (wei)"),
1892
- veABXLockedSupply: z4.string().describe("Total ABX locked in VotingEscrow (wei)")
2616
+ output: z5.object({
2617
+ v2PoolCount: z5.number().describe("Number of V2 AMM pools"),
2618
+ clPoolCount: z5.number().describe("Number of Slipstream (CL) pools"),
2619
+ gaugeCount: z5.number().describe("Number of pools with gauges"),
2620
+ totalVotingWeight: z5.string().describe("Total voting weight (wei)"),
2621
+ veABXTotalSupply: z5.string().describe("Total veABX supply (wei)"),
2622
+ veABXLockedSupply: z5.string().describe("Total ABX locked in VotingEscrow (wei)")
1893
2623
  }),
1894
2624
  examples: [{ description: "Fetch the current Aborean protocol status" }],
1895
2625
  async run(c) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spectratools/aborean-cli",
3
- "version": "0.3.0",
3
+ "version": "0.4.0",
4
4
  "description": "CLI for Aborean Finance DEX on Abstract (pools, swaps, gauges, voting escrow).",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,7 +30,7 @@
30
30
  "aborean-cli": "./dist/cli.js"
31
31
  },
32
32
  "dependencies": {
33
- "incur": "^0.2.2",
33
+ "incur": "^0.3.0",
34
34
  "ox": "^0.14.0",
35
35
  "viem": "^2.47.0",
36
36
  "@spectratools/cli-shared": "0.1.1"