@spectratools/aborean-cli 0.2.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.
- package/dist/cli.js +2132 -105
- package/package.json +2 -2
package/dist/cli.js
CHANGED
|
@@ -4,7 +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 Cli5, z as z5 } from "incur";
|
|
8
|
+
|
|
9
|
+
// src/commands/cl.ts
|
|
10
|
+
import { checksumAddress, isAddress } from "@spectratools/cli-shared";
|
|
7
11
|
import { Cli, z } from "incur";
|
|
12
|
+
import { formatUnits, parseUnits } from "viem";
|
|
8
13
|
|
|
9
14
|
// src/contracts/abis/CLFactory.abi.json
|
|
10
15
|
var CLFactory_abi_default = [
|
|
@@ -119,177 +124,246 @@ var CLFactory_abi_default = [
|
|
|
119
124
|
}
|
|
120
125
|
];
|
|
121
126
|
|
|
122
|
-
// src/contracts/abis/
|
|
123
|
-
var
|
|
127
|
+
// src/contracts/abis/CLPool.abi.json
|
|
128
|
+
var CLPool_abi_default = [
|
|
124
129
|
{
|
|
125
130
|
type: "function",
|
|
126
|
-
name: "
|
|
131
|
+
name: "slot0",
|
|
127
132
|
inputs: [],
|
|
128
|
-
outputs: [
|
|
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
|
+
],
|
|
129
141
|
stateMutability: "view"
|
|
130
142
|
},
|
|
131
143
|
{
|
|
132
144
|
type: "function",
|
|
133
|
-
name: "
|
|
134
|
-
inputs: [
|
|
135
|
-
outputs: [{ name: "", type: "
|
|
145
|
+
name: "liquidity",
|
|
146
|
+
inputs: [],
|
|
147
|
+
outputs: [{ name: "", type: "uint128", internalType: "uint128" }],
|
|
136
148
|
stateMutability: "view"
|
|
137
149
|
},
|
|
138
150
|
{
|
|
139
151
|
type: "function",
|
|
140
|
-
name: "
|
|
141
|
-
inputs: [
|
|
142
|
-
{ name: "tokenA", type: "address", internalType: "address" },
|
|
143
|
-
{ name: "tokenB", type: "address", internalType: "address" },
|
|
144
|
-
{ name: "stable", type: "bool", internalType: "bool" }
|
|
145
|
-
],
|
|
152
|
+
name: "token0",
|
|
153
|
+
inputs: [],
|
|
146
154
|
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
147
155
|
stateMutability: "view"
|
|
148
156
|
},
|
|
149
157
|
{
|
|
150
158
|
type: "function",
|
|
151
|
-
name: "
|
|
152
|
-
inputs: [
|
|
153
|
-
outputs: [{ name: "", type: "
|
|
159
|
+
name: "token1",
|
|
160
|
+
inputs: [],
|
|
161
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
154
162
|
stateMutability: "view"
|
|
155
163
|
},
|
|
156
164
|
{
|
|
157
165
|
type: "function",
|
|
158
|
-
name: "
|
|
159
|
-
inputs: [
|
|
160
|
-
|
|
161
|
-
{ name: "stable", type: "bool", internalType: "bool" }
|
|
162
|
-
],
|
|
163
|
-
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
166
|
+
name: "tickSpacing",
|
|
167
|
+
inputs: [],
|
|
168
|
+
outputs: [{ name: "", type: "int24", internalType: "int24" }],
|
|
164
169
|
stateMutability: "view"
|
|
165
170
|
},
|
|
166
171
|
{
|
|
167
172
|
type: "function",
|
|
168
|
-
name: "
|
|
173
|
+
name: "factory",
|
|
169
174
|
inputs: [],
|
|
170
175
|
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
171
176
|
stateMutability: "view"
|
|
172
177
|
},
|
|
173
178
|
{
|
|
174
179
|
type: "function",
|
|
175
|
-
name: "
|
|
180
|
+
name: "gauge",
|
|
176
181
|
inputs: [],
|
|
177
182
|
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
178
183
|
stateMutability: "view"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
type: "function",
|
|
187
|
+
name: "fee",
|
|
188
|
+
inputs: [],
|
|
189
|
+
outputs: [{ name: "", type: "uint24", internalType: "uint24" }],
|
|
190
|
+
stateMutability: "view"
|
|
179
191
|
}
|
|
180
192
|
];
|
|
181
193
|
|
|
182
|
-
// src/contracts/abis/
|
|
183
|
-
var
|
|
194
|
+
// src/contracts/abis/Gauge.abi.json
|
|
195
|
+
var Gauge_abi_default = [
|
|
184
196
|
{
|
|
185
197
|
type: "function",
|
|
186
|
-
name: "
|
|
198
|
+
name: "stakingToken",
|
|
199
|
+
inputs: [],
|
|
200
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
201
|
+
stateMutability: "view"
|
|
202
|
+
},
|
|
203
|
+
{
|
|
204
|
+
type: "function",
|
|
205
|
+
name: "rewardToken",
|
|
206
|
+
inputs: [],
|
|
207
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
208
|
+
stateMutability: "view"
|
|
209
|
+
},
|
|
210
|
+
{
|
|
211
|
+
type: "function",
|
|
212
|
+
name: "periodFinish",
|
|
187
213
|
inputs: [],
|
|
188
214
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
189
215
|
stateMutability: "view"
|
|
190
216
|
},
|
|
191
217
|
{
|
|
192
218
|
type: "function",
|
|
193
|
-
name: "
|
|
219
|
+
name: "rewardRate",
|
|
194
220
|
inputs: [],
|
|
195
221
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
196
222
|
stateMutability: "view"
|
|
197
223
|
},
|
|
198
224
|
{
|
|
199
225
|
type: "function",
|
|
200
|
-
name: "
|
|
201
|
-
inputs: [
|
|
202
|
-
outputs: [{ name: "", type: "
|
|
226
|
+
name: "lastUpdateTime",
|
|
227
|
+
inputs: [],
|
|
228
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
203
229
|
stateMutability: "view"
|
|
204
230
|
},
|
|
205
231
|
{
|
|
206
232
|
type: "function",
|
|
207
|
-
name: "
|
|
208
|
-
inputs: [
|
|
209
|
-
outputs: [{ name: "", type: "
|
|
233
|
+
name: "rewardPerTokenStored",
|
|
234
|
+
inputs: [],
|
|
235
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
210
236
|
stateMutability: "view"
|
|
211
237
|
},
|
|
212
238
|
{
|
|
213
239
|
type: "function",
|
|
214
|
-
name: "
|
|
215
|
-
inputs: [
|
|
240
|
+
name: "totalSupply",
|
|
241
|
+
inputs: [],
|
|
216
242
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
217
243
|
stateMutability: "view"
|
|
218
244
|
},
|
|
219
245
|
{
|
|
220
246
|
type: "function",
|
|
221
|
-
name: "
|
|
222
|
-
inputs: [{ name: "
|
|
223
|
-
outputs: [{ name: "", type: "
|
|
247
|
+
name: "balanceOf",
|
|
248
|
+
inputs: [{ name: "account", type: "address", internalType: "address" }],
|
|
249
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
224
250
|
stateMutability: "view"
|
|
225
251
|
},
|
|
226
252
|
{
|
|
227
253
|
type: "function",
|
|
228
|
-
name: "
|
|
229
|
-
inputs: [{ name: "", type: "address", internalType: "address" }],
|
|
230
|
-
outputs: [{ name: "", type: "
|
|
254
|
+
name: "earned",
|
|
255
|
+
inputs: [{ name: "account", type: "address", internalType: "address" }],
|
|
256
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
231
257
|
stateMutability: "view"
|
|
232
258
|
},
|
|
233
259
|
{
|
|
234
260
|
type: "function",
|
|
235
|
-
name: "
|
|
261
|
+
name: "fees0",
|
|
236
262
|
inputs: [],
|
|
237
|
-
outputs: [{ name: "", type: "
|
|
263
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
238
264
|
stateMutability: "view"
|
|
239
265
|
},
|
|
240
266
|
{
|
|
241
267
|
type: "function",
|
|
242
|
-
name: "
|
|
268
|
+
name: "fees1",
|
|
243
269
|
inputs: [],
|
|
244
|
-
outputs: [{ name: "", type: "
|
|
270
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
245
271
|
stateMutability: "view"
|
|
246
272
|
},
|
|
247
273
|
{
|
|
248
274
|
type: "function",
|
|
249
|
-
name: "
|
|
275
|
+
name: "left",
|
|
250
276
|
inputs: [],
|
|
251
|
-
outputs: [{ name: "", type: "
|
|
277
|
+
outputs: [{ name: "_left", type: "uint256", internalType: "uint256" }],
|
|
278
|
+
stateMutability: "view"
|
|
279
|
+
}
|
|
280
|
+
];
|
|
281
|
+
|
|
282
|
+
// src/contracts/abis/Minter.abi.json
|
|
283
|
+
var Minter_abi_default = [
|
|
284
|
+
{
|
|
285
|
+
type: "function",
|
|
286
|
+
name: "WEEK",
|
|
287
|
+
inputs: [],
|
|
288
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
252
289
|
stateMutability: "view"
|
|
253
290
|
},
|
|
254
291
|
{
|
|
255
292
|
type: "function",
|
|
256
|
-
name: "
|
|
293
|
+
name: "weekly",
|
|
257
294
|
inputs: [],
|
|
258
|
-
outputs: [{ name: "", type: "
|
|
295
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
259
296
|
stateMutability: "view"
|
|
260
297
|
},
|
|
261
298
|
{
|
|
262
299
|
type: "function",
|
|
263
|
-
name: "
|
|
300
|
+
name: "activePeriod",
|
|
264
301
|
inputs: [],
|
|
265
|
-
outputs: [{ name: "", type: "
|
|
302
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
266
303
|
stateMutability: "view"
|
|
267
304
|
},
|
|
268
305
|
{
|
|
269
306
|
type: "function",
|
|
270
|
-
name: "
|
|
307
|
+
name: "epochCount",
|
|
271
308
|
inputs: [],
|
|
272
|
-
outputs: [{ name: "", type: "
|
|
309
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
273
310
|
stateMutability: "view"
|
|
274
311
|
},
|
|
275
312
|
{
|
|
276
313
|
type: "function",
|
|
277
|
-
name: "
|
|
314
|
+
name: "teamRate",
|
|
278
315
|
inputs: [],
|
|
279
316
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
280
317
|
stateMutability: "view"
|
|
281
318
|
},
|
|
282
319
|
{
|
|
283
320
|
type: "function",
|
|
284
|
-
name: "
|
|
285
|
-
inputs: [
|
|
321
|
+
name: "tailEmissionRate",
|
|
322
|
+
inputs: [],
|
|
286
323
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
287
324
|
stateMutability: "view"
|
|
288
325
|
}
|
|
289
326
|
];
|
|
290
327
|
|
|
291
|
-
// src/contracts/abis/
|
|
292
|
-
var
|
|
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
|
+
},
|
|
293
367
|
{
|
|
294
368
|
type: "function",
|
|
295
369
|
name: "totalSupply",
|
|
@@ -299,46 +373,168 @@ var VotingEscrow_abi_default = [
|
|
|
299
373
|
},
|
|
300
374
|
{
|
|
301
375
|
type: "function",
|
|
302
|
-
name: "
|
|
303
|
-
inputs: [
|
|
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
|
+
|
|
390
|
+
// src/contracts/abis/PoolFactory.abi.json
|
|
391
|
+
var PoolFactory_abi_default = [
|
|
392
|
+
{
|
|
393
|
+
type: "function",
|
|
394
|
+
name: "allPoolsLength",
|
|
395
|
+
inputs: [],
|
|
304
396
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
305
397
|
stateMutability: "view"
|
|
306
398
|
},
|
|
307
399
|
{
|
|
308
400
|
type: "function",
|
|
309
|
-
name: "
|
|
310
|
-
inputs: [{ name: "
|
|
311
|
-
outputs: [
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
401
|
+
name: "allPools",
|
|
402
|
+
inputs: [{ name: "index", type: "uint256", internalType: "uint256" }],
|
|
403
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
404
|
+
stateMutability: "view"
|
|
405
|
+
},
|
|
406
|
+
{
|
|
407
|
+
type: "function",
|
|
408
|
+
name: "getPool",
|
|
409
|
+
inputs: [
|
|
410
|
+
{ name: "tokenA", type: "address", internalType: "address" },
|
|
411
|
+
{ name: "tokenB", type: "address", internalType: "address" },
|
|
412
|
+
{ name: "stable", type: "bool", internalType: "bool" }
|
|
315
413
|
],
|
|
414
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
316
415
|
stateMutability: "view"
|
|
317
416
|
},
|
|
318
417
|
{
|
|
319
418
|
type: "function",
|
|
320
|
-
name: "
|
|
321
|
-
inputs: [{ name: "
|
|
419
|
+
name: "isPair",
|
|
420
|
+
inputs: [{ name: "pool", type: "address", internalType: "address" }],
|
|
421
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
422
|
+
stateMutability: "view"
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
type: "function",
|
|
426
|
+
name: "getFee",
|
|
427
|
+
inputs: [
|
|
428
|
+
{ name: "pool", type: "address", internalType: "address" },
|
|
429
|
+
{ name: "stable", type: "bool", internalType: "bool" }
|
|
430
|
+
],
|
|
431
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
432
|
+
stateMutability: "view"
|
|
433
|
+
},
|
|
434
|
+
{
|
|
435
|
+
type: "function",
|
|
436
|
+
name: "implementation",
|
|
437
|
+
inputs: [],
|
|
322
438
|
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
323
439
|
stateMutability: "view"
|
|
324
440
|
},
|
|
325
441
|
{
|
|
326
442
|
type: "function",
|
|
327
|
-
name: "
|
|
443
|
+
name: "voter",
|
|
444
|
+
inputs: [],
|
|
445
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
446
|
+
stateMutability: "view"
|
|
447
|
+
}
|
|
448
|
+
];
|
|
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",
|
|
328
469
|
inputs: [
|
|
329
|
-
{
|
|
330
|
-
|
|
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" }
|
|
331
503
|
],
|
|
504
|
+
stateMutability: "nonpayable"
|
|
505
|
+
}
|
|
506
|
+
];
|
|
507
|
+
|
|
508
|
+
// src/contracts/abis/RewardsDistributor.abi.json
|
|
509
|
+
var RewardsDistributor_abi_default = [
|
|
510
|
+
{
|
|
511
|
+
type: "function",
|
|
512
|
+
name: "WEEK",
|
|
513
|
+
inputs: [],
|
|
332
514
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
333
515
|
stateMutability: "view"
|
|
334
516
|
},
|
|
335
517
|
{
|
|
336
518
|
type: "function",
|
|
337
|
-
name: "
|
|
519
|
+
name: "startTime",
|
|
520
|
+
inputs: [],
|
|
521
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
522
|
+
stateMutability: "view"
|
|
523
|
+
},
|
|
524
|
+
{
|
|
525
|
+
type: "function",
|
|
526
|
+
name: "timeCursorOf",
|
|
338
527
|
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
339
528
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
340
529
|
stateMutability: "view"
|
|
341
530
|
},
|
|
531
|
+
{
|
|
532
|
+
type: "function",
|
|
533
|
+
name: "lastTokenTime",
|
|
534
|
+
inputs: [],
|
|
535
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
536
|
+
stateMutability: "view"
|
|
537
|
+
},
|
|
342
538
|
{
|
|
343
539
|
type: "function",
|
|
344
540
|
name: "token",
|
|
@@ -348,18 +544,329 @@ var VotingEscrow_abi_default = [
|
|
|
348
544
|
},
|
|
349
545
|
{
|
|
350
546
|
type: "function",
|
|
351
|
-
name: "
|
|
547
|
+
name: "minter",
|
|
352
548
|
inputs: [],
|
|
549
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
550
|
+
stateMutability: "view"
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
type: "function",
|
|
554
|
+
name: "claimable",
|
|
555
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
353
556
|
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
354
557
|
stateMutability: "view"
|
|
355
558
|
}
|
|
356
559
|
];
|
|
357
560
|
|
|
358
|
-
// src/contracts/abis.
|
|
359
|
-
var
|
|
360
|
-
|
|
561
|
+
// src/contracts/abis/Voter.abi.json
|
|
562
|
+
var Voter_abi_default = [
|
|
563
|
+
{
|
|
564
|
+
type: "function",
|
|
565
|
+
name: "length",
|
|
566
|
+
inputs: [],
|
|
567
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
568
|
+
stateMutability: "view"
|
|
569
|
+
},
|
|
570
|
+
{
|
|
571
|
+
type: "function",
|
|
572
|
+
name: "totalWeight",
|
|
573
|
+
inputs: [],
|
|
574
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
575
|
+
stateMutability: "view"
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
type: "function",
|
|
579
|
+
name: "gauges",
|
|
580
|
+
inputs: [{ name: "pool", type: "address", internalType: "address" }],
|
|
581
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
582
|
+
stateMutability: "view"
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
type: "function",
|
|
586
|
+
name: "poolForGauge",
|
|
587
|
+
inputs: [{ name: "gauge", type: "address", internalType: "address" }],
|
|
588
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
589
|
+
stateMutability: "view"
|
|
590
|
+
},
|
|
591
|
+
{
|
|
592
|
+
type: "function",
|
|
593
|
+
name: "gaugeToFees",
|
|
594
|
+
inputs: [{ name: "gauge", type: "address", internalType: "address" }],
|
|
595
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
596
|
+
stateMutability: "view"
|
|
597
|
+
},
|
|
598
|
+
{
|
|
599
|
+
type: "function",
|
|
600
|
+
name: "gaugeToBribe",
|
|
601
|
+
inputs: [{ name: "gauge", type: "address", internalType: "address" }],
|
|
602
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
603
|
+
stateMutability: "view"
|
|
604
|
+
},
|
|
605
|
+
{
|
|
606
|
+
type: "function",
|
|
607
|
+
name: "weights",
|
|
608
|
+
inputs: [{ name: "pool", type: "address", internalType: "address" }],
|
|
609
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
610
|
+
stateMutability: "view"
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
type: "function",
|
|
614
|
+
name: "votes",
|
|
615
|
+
inputs: [
|
|
616
|
+
{ name: "tokenId", type: "uint256", internalType: "uint256" },
|
|
617
|
+
{ name: "pool", type: "address", internalType: "address" }
|
|
618
|
+
],
|
|
619
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
620
|
+
stateMutability: "view"
|
|
621
|
+
},
|
|
622
|
+
{
|
|
623
|
+
type: "function",
|
|
624
|
+
name: "usedWeights",
|
|
625
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
626
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
627
|
+
stateMutability: "view"
|
|
628
|
+
},
|
|
629
|
+
{
|
|
630
|
+
type: "function",
|
|
631
|
+
name: "lastVoted",
|
|
632
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
633
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
634
|
+
stateMutability: "view"
|
|
635
|
+
},
|
|
636
|
+
{
|
|
637
|
+
type: "function",
|
|
638
|
+
name: "isAlive",
|
|
639
|
+
inputs: [{ name: "gauge", type: "address", internalType: "address" }],
|
|
640
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
641
|
+
stateMutability: "view"
|
|
642
|
+
},
|
|
643
|
+
{
|
|
644
|
+
type: "function",
|
|
645
|
+
name: "isGauge",
|
|
646
|
+
inputs: [{ name: "", type: "address", internalType: "address" }],
|
|
647
|
+
outputs: [{ name: "", type: "bool", internalType: "bool" }],
|
|
648
|
+
stateMutability: "view"
|
|
649
|
+
},
|
|
650
|
+
{
|
|
651
|
+
type: "function",
|
|
652
|
+
name: "ve",
|
|
653
|
+
inputs: [],
|
|
654
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
655
|
+
stateMutability: "view"
|
|
656
|
+
},
|
|
657
|
+
{
|
|
658
|
+
type: "function",
|
|
659
|
+
name: "minter",
|
|
660
|
+
inputs: [],
|
|
661
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
662
|
+
stateMutability: "view"
|
|
663
|
+
},
|
|
664
|
+
{
|
|
665
|
+
type: "function",
|
|
666
|
+
name: "factoryRegistry",
|
|
667
|
+
inputs: [],
|
|
668
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
669
|
+
stateMutability: "view"
|
|
670
|
+
},
|
|
671
|
+
{
|
|
672
|
+
type: "function",
|
|
673
|
+
name: "forwarder",
|
|
674
|
+
inputs: [],
|
|
675
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
676
|
+
stateMutability: "view"
|
|
677
|
+
},
|
|
678
|
+
{
|
|
679
|
+
type: "function",
|
|
680
|
+
name: "governor",
|
|
681
|
+
inputs: [],
|
|
682
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
683
|
+
stateMutability: "view"
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
type: "function",
|
|
687
|
+
name: "epochGovernor",
|
|
688
|
+
inputs: [],
|
|
689
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
690
|
+
stateMutability: "view"
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
type: "function",
|
|
694
|
+
name: "emergencyCouncil",
|
|
695
|
+
inputs: [],
|
|
696
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
697
|
+
stateMutability: "view"
|
|
698
|
+
},
|
|
699
|
+
{
|
|
700
|
+
type: "function",
|
|
701
|
+
name: "maxVotingNum",
|
|
702
|
+
inputs: [],
|
|
703
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
704
|
+
stateMutability: "view"
|
|
705
|
+
},
|
|
706
|
+
{
|
|
707
|
+
type: "function",
|
|
708
|
+
name: "claimable",
|
|
709
|
+
inputs: [{ name: "gauge", type: "address", internalType: "address" }],
|
|
710
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
711
|
+
stateMutability: "view"
|
|
712
|
+
}
|
|
713
|
+
];
|
|
714
|
+
|
|
715
|
+
// src/contracts/abis/VotingEscrow.abi.json
|
|
716
|
+
var VotingEscrow_abi_default = [
|
|
717
|
+
{
|
|
718
|
+
type: "function",
|
|
719
|
+
name: "totalSupply",
|
|
720
|
+
inputs: [],
|
|
721
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
722
|
+
stateMutability: "view"
|
|
723
|
+
},
|
|
724
|
+
{
|
|
725
|
+
type: "function",
|
|
726
|
+
name: "supply",
|
|
727
|
+
inputs: [],
|
|
728
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
729
|
+
stateMutability: "view"
|
|
730
|
+
},
|
|
731
|
+
{
|
|
732
|
+
type: "function",
|
|
733
|
+
name: "permanentLockBalance",
|
|
734
|
+
inputs: [],
|
|
735
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
736
|
+
stateMutability: "view"
|
|
737
|
+
},
|
|
738
|
+
{
|
|
739
|
+
type: "function",
|
|
740
|
+
name: "epoch",
|
|
741
|
+
inputs: [],
|
|
742
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
743
|
+
stateMutability: "view"
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
type: "function",
|
|
747
|
+
name: "pointHistory",
|
|
748
|
+
inputs: [{ name: "_loc", type: "uint256", internalType: "uint256" }],
|
|
749
|
+
outputs: [
|
|
750
|
+
{
|
|
751
|
+
name: "",
|
|
752
|
+
type: "tuple",
|
|
753
|
+
internalType: "struct IVotingEscrow.GlobalPoint",
|
|
754
|
+
components: [
|
|
755
|
+
{ name: "bias", type: "int128", internalType: "int128" },
|
|
756
|
+
{ name: "slope", type: "int128", internalType: "int128" },
|
|
757
|
+
{ name: "ts", type: "uint256", internalType: "uint256" },
|
|
758
|
+
{ name: "blk", type: "uint256", internalType: "uint256" },
|
|
759
|
+
{
|
|
760
|
+
name: "permanentLockBalance",
|
|
761
|
+
type: "uint256",
|
|
762
|
+
internalType: "uint256"
|
|
763
|
+
}
|
|
764
|
+
]
|
|
765
|
+
}
|
|
766
|
+
],
|
|
767
|
+
stateMutability: "view"
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
type: "function",
|
|
771
|
+
name: "balanceOf",
|
|
772
|
+
inputs: [{ name: "owner", type: "address", internalType: "address" }],
|
|
773
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
774
|
+
stateMutability: "view"
|
|
775
|
+
},
|
|
776
|
+
{
|
|
777
|
+
type: "function",
|
|
778
|
+
name: "locked",
|
|
779
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
780
|
+
outputs: [
|
|
781
|
+
{ name: "amount", type: "int128", internalType: "int128" },
|
|
782
|
+
{ name: "end", type: "uint256", internalType: "uint256" },
|
|
783
|
+
{ name: "isPermanent", type: "bool", internalType: "bool" }
|
|
784
|
+
],
|
|
785
|
+
stateMutability: "view"
|
|
786
|
+
},
|
|
787
|
+
{
|
|
788
|
+
type: "function",
|
|
789
|
+
name: "ownerOf",
|
|
790
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
791
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
792
|
+
stateMutability: "view"
|
|
793
|
+
},
|
|
794
|
+
{
|
|
795
|
+
type: "function",
|
|
796
|
+
name: "tokenOfOwnerByIndex",
|
|
797
|
+
inputs: [
|
|
798
|
+
{ name: "owner", type: "address", internalType: "address" },
|
|
799
|
+
{ name: "index", type: "uint256", internalType: "uint256" }
|
|
800
|
+
],
|
|
801
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
802
|
+
stateMutability: "view"
|
|
803
|
+
},
|
|
804
|
+
{
|
|
805
|
+
type: "function",
|
|
806
|
+
name: "balanceOfNFT",
|
|
807
|
+
inputs: [{ name: "tokenId", type: "uint256", internalType: "uint256" }],
|
|
808
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
809
|
+
stateMutability: "view"
|
|
810
|
+
},
|
|
811
|
+
{
|
|
812
|
+
type: "function",
|
|
813
|
+
name: "token",
|
|
814
|
+
inputs: [],
|
|
815
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
816
|
+
stateMutability: "view"
|
|
817
|
+
}
|
|
818
|
+
];
|
|
819
|
+
|
|
820
|
+
// src/contracts/abis/VotingReward.abi.json
|
|
821
|
+
var VotingReward_abi_default = [
|
|
822
|
+
{
|
|
823
|
+
type: "function",
|
|
824
|
+
name: "rewardsListLength",
|
|
825
|
+
inputs: [],
|
|
826
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
827
|
+
stateMutability: "view"
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
type: "function",
|
|
831
|
+
name: "rewards",
|
|
832
|
+
inputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
833
|
+
outputs: [{ name: "", type: "address", internalType: "address" }],
|
|
834
|
+
stateMutability: "view"
|
|
835
|
+
},
|
|
836
|
+
{
|
|
837
|
+
type: "function",
|
|
838
|
+
name: "tokenRewardsPerEpoch",
|
|
839
|
+
inputs: [
|
|
840
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
841
|
+
{ name: "epochStart", type: "uint256", internalType: "uint256" }
|
|
842
|
+
],
|
|
843
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
844
|
+
stateMutability: "view"
|
|
845
|
+
},
|
|
846
|
+
{
|
|
847
|
+
type: "function",
|
|
848
|
+
name: "earned",
|
|
849
|
+
inputs: [
|
|
850
|
+
{ name: "token", type: "address", internalType: "address" },
|
|
851
|
+
{ name: "tokenId", type: "uint256", internalType: "uint256" }
|
|
852
|
+
],
|
|
853
|
+
outputs: [{ name: "", type: "uint256", internalType: "uint256" }],
|
|
854
|
+
stateMutability: "view"
|
|
855
|
+
}
|
|
856
|
+
];
|
|
857
|
+
|
|
858
|
+
// src/contracts/abis.ts
|
|
859
|
+
var clFactoryAbi = CLFactory_abi_default;
|
|
860
|
+
var clPoolAbi = CLPool_abi_default;
|
|
861
|
+
var gaugeAbi = Gauge_abi_default;
|
|
862
|
+
var minterAbi = Minter_abi_default;
|
|
863
|
+
var nonfungiblePositionManagerAbi = NonfungiblePositionManager_abi_default;
|
|
864
|
+
var poolFactoryAbi = PoolFactory_abi_default;
|
|
865
|
+
var quoterV2Abi = QuoterV2_abi_default;
|
|
866
|
+
var rewardsDistributorAbi = RewardsDistributor_abi_default;
|
|
361
867
|
var voterAbi = Voter_abi_default;
|
|
362
868
|
var votingEscrowAbi = VotingEscrow_abi_default;
|
|
869
|
+
var votingRewardAbi = VotingReward_abi_default;
|
|
363
870
|
|
|
364
871
|
// src/contracts/addresses.ts
|
|
365
872
|
var ABOREAN_V2_ADDRESSES = {
|
|
@@ -423,28 +930,1544 @@ var ABOREAN_ADDRESSES = {
|
|
|
423
930
|
...ABOREAN_CL_ADDRESSES
|
|
424
931
|
};
|
|
425
932
|
|
|
426
|
-
// src/contracts/client.ts
|
|
427
|
-
import { http, createPublicClient, defineChain } from "viem";
|
|
428
|
-
var abstractMainnet = defineChain({
|
|
429
|
-
id: 2741,
|
|
430
|
-
name: "Abstract Mainnet",
|
|
431
|
-
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
432
|
-
rpcUrls: {
|
|
433
|
-
default: { http: ["https://api.mainnet.abs.xyz"] },
|
|
434
|
-
public: { http: ["https://api.mainnet.abs.xyz"] }
|
|
435
|
-
},
|
|
436
|
-
contracts: {
|
|
437
|
-
multicall3: {
|
|
438
|
-
address: "0xcA11bde05977b3631167028862bE2a173976CA11"
|
|
933
|
+
// src/contracts/client.ts
|
|
934
|
+
import { http, createPublicClient, defineChain } from "viem";
|
|
935
|
+
var abstractMainnet = defineChain({
|
|
936
|
+
id: 2741,
|
|
937
|
+
name: "Abstract Mainnet",
|
|
938
|
+
nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
|
|
939
|
+
rpcUrls: {
|
|
940
|
+
default: { http: ["https://api.mainnet.abs.xyz"] },
|
|
941
|
+
public: { http: ["https://api.mainnet.abs.xyz"] }
|
|
942
|
+
},
|
|
943
|
+
contracts: {
|
|
944
|
+
multicall3: {
|
|
945
|
+
address: "0xcA11bde05977b3631167028862bE2a173976CA11"
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
});
|
|
949
|
+
function createAboreanPublicClient(rpcUrl) {
|
|
950
|
+
return createPublicClient({
|
|
951
|
+
chain: abstractMainnet,
|
|
952
|
+
transport: http(rpcUrl ?? process.env.ABSTRACT_RPC_URL ?? "https://api.mainnet.abs.xyz")
|
|
953
|
+
});
|
|
954
|
+
}
|
|
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
|
+
|
|
1493
|
+
// src/commands/_common.ts
|
|
1494
|
+
import { checksumAddress as checksumAddress2, weiToEth } from "@spectratools/cli-shared";
|
|
1495
|
+
var ZERO_ADDRESS = "0x0000000000000000000000000000000000000000";
|
|
1496
|
+
function toChecksum(address) {
|
|
1497
|
+
try {
|
|
1498
|
+
return checksumAddress2(address);
|
|
1499
|
+
} catch {
|
|
1500
|
+
return address;
|
|
1501
|
+
}
|
|
1502
|
+
}
|
|
1503
|
+
function asNum(value) {
|
|
1504
|
+
return Number(value);
|
|
1505
|
+
}
|
|
1506
|
+
function relTime(unixSeconds) {
|
|
1507
|
+
const ts = typeof unixSeconds === "bigint" ? Number(unixSeconds) : unixSeconds;
|
|
1508
|
+
if (!Number.isFinite(ts) || ts <= 0) return "n/a";
|
|
1509
|
+
const delta = ts - Math.floor(Date.now() / 1e3);
|
|
1510
|
+
const abs = Math.abs(delta);
|
|
1511
|
+
const hours = Math.floor(abs / 3600);
|
|
1512
|
+
const minutes = Math.floor(abs % 3600 / 60);
|
|
1513
|
+
const label = hours > 0 ? `${hours}h ${minutes}m` : `${minutes}m`;
|
|
1514
|
+
return delta >= 0 ? `in ${label}` : `${label} ago`;
|
|
1515
|
+
}
|
|
1516
|
+
function clampPositive(seconds) {
|
|
1517
|
+
return seconds > 0 ? seconds : 0;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
// src/commands/gauges.ts
|
|
1521
|
+
var env2 = z2.object({
|
|
1522
|
+
ABSTRACT_RPC_URL: z2.string().optional().describe("Abstract RPC URL override")
|
|
1523
|
+
});
|
|
1524
|
+
async function discoverGaugePools(client) {
|
|
1525
|
+
const [v2PoolCount, clPoolCount] = await Promise.all([
|
|
1526
|
+
client.readContract({
|
|
1527
|
+
abi: poolFactoryAbi,
|
|
1528
|
+
address: ABOREAN_V2_ADDRESSES.poolFactory,
|
|
1529
|
+
functionName: "allPoolsLength"
|
|
1530
|
+
}),
|
|
1531
|
+
client.readContract({
|
|
1532
|
+
abi: clFactoryAbi,
|
|
1533
|
+
address: ABOREAN_CL_ADDRESSES.clFactory,
|
|
1534
|
+
functionName: "allPoolsLength"
|
|
1535
|
+
})
|
|
1536
|
+
]);
|
|
1537
|
+
const v2Indices = Array.from({ length: asNum(v2PoolCount) }, (_, i) => BigInt(i));
|
|
1538
|
+
const clIndices = Array.from({ length: asNum(clPoolCount) }, (_, i) => BigInt(i));
|
|
1539
|
+
const [v2Pools, clPools] = await Promise.all([
|
|
1540
|
+
v2Indices.length ? client.multicall({
|
|
1541
|
+
allowFailure: false,
|
|
1542
|
+
contracts: v2Indices.map((index) => ({
|
|
1543
|
+
abi: poolFactoryAbi,
|
|
1544
|
+
address: ABOREAN_V2_ADDRESSES.poolFactory,
|
|
1545
|
+
functionName: "allPools",
|
|
1546
|
+
args: [index]
|
|
1547
|
+
}))
|
|
1548
|
+
}) : Promise.resolve([]),
|
|
1549
|
+
clIndices.length ? client.multicall({
|
|
1550
|
+
allowFailure: false,
|
|
1551
|
+
contracts: clIndices.map((index) => ({
|
|
1552
|
+
abi: clFactoryAbi,
|
|
1553
|
+
address: ABOREAN_CL_ADDRESSES.clFactory,
|
|
1554
|
+
functionName: "allPools",
|
|
1555
|
+
args: [index]
|
|
1556
|
+
}))
|
|
1557
|
+
}) : Promise.resolve([])
|
|
1558
|
+
]);
|
|
1559
|
+
const pools = [...v2Pools, ...clPools];
|
|
1560
|
+
if (!pools.length) return [];
|
|
1561
|
+
const gauges2 = await client.multicall({
|
|
1562
|
+
allowFailure: false,
|
|
1563
|
+
contracts: pools.map((pool) => ({
|
|
1564
|
+
abi: voterAbi,
|
|
1565
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
1566
|
+
functionName: "gauges",
|
|
1567
|
+
args: [pool]
|
|
1568
|
+
}))
|
|
1569
|
+
});
|
|
1570
|
+
return pools.map((pool, index) => ({ pool, gauge: gauges2[index] })).filter(({ gauge }) => gauge.toLowerCase() !== ZERO_ADDRESS.toLowerCase());
|
|
1571
|
+
}
|
|
1572
|
+
var gauges = Cli2.create("gauges", {
|
|
1573
|
+
description: "Inspect Aborean gauge emissions, staking, and user positions."
|
|
1574
|
+
});
|
|
1575
|
+
gauges.command("list", {
|
|
1576
|
+
description: "List active gauges with pool, emissions, and staking stats.",
|
|
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()
|
|
1589
|
+
})
|
|
1590
|
+
),
|
|
1591
|
+
count: z2.number()
|
|
1592
|
+
}),
|
|
1593
|
+
examples: [{ description: "List all active gauges and current emissions state" }],
|
|
1594
|
+
async run(c) {
|
|
1595
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
1596
|
+
const gaugePools = await discoverGaugePools(client);
|
|
1597
|
+
if (!gaugePools.length) {
|
|
1598
|
+
return c.ok({ gauges: [], count: 0 });
|
|
1599
|
+
}
|
|
1600
|
+
const details = await client.multicall({
|
|
1601
|
+
allowFailure: false,
|
|
1602
|
+
contracts: gaugePools.flatMap(({ gauge }) => [
|
|
1603
|
+
{
|
|
1604
|
+
abi: gaugeAbi,
|
|
1605
|
+
address: gauge,
|
|
1606
|
+
functionName: "rewardToken"
|
|
1607
|
+
},
|
|
1608
|
+
{
|
|
1609
|
+
abi: gaugeAbi,
|
|
1610
|
+
address: gauge,
|
|
1611
|
+
functionName: "rewardRate"
|
|
1612
|
+
},
|
|
1613
|
+
{
|
|
1614
|
+
abi: gaugeAbi,
|
|
1615
|
+
address: gauge,
|
|
1616
|
+
functionName: "totalSupply"
|
|
1617
|
+
},
|
|
1618
|
+
{
|
|
1619
|
+
abi: gaugeAbi,
|
|
1620
|
+
address: gauge,
|
|
1621
|
+
functionName: "periodFinish"
|
|
1622
|
+
},
|
|
1623
|
+
{
|
|
1624
|
+
abi: voterAbi,
|
|
1625
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
1626
|
+
functionName: "claimable",
|
|
1627
|
+
args: [gauge]
|
|
1628
|
+
}
|
|
1629
|
+
])
|
|
1630
|
+
});
|
|
1631
|
+
const items = gaugePools.map(({ pool, gauge }, index) => {
|
|
1632
|
+
const offset = index * 5;
|
|
1633
|
+
const rewardToken = details[offset];
|
|
1634
|
+
const rewardRate = details[offset + 1];
|
|
1635
|
+
const totalStaked = details[offset + 2];
|
|
1636
|
+
const periodFinish = details[offset + 3];
|
|
1637
|
+
const claimableEmissions = details[offset + 4];
|
|
1638
|
+
return {
|
|
1639
|
+
pool: toChecksum(pool),
|
|
1640
|
+
gauge: toChecksum(gauge),
|
|
1641
|
+
rewardToken: toChecksum(rewardToken),
|
|
1642
|
+
rewardRate: rewardRate.toString(),
|
|
1643
|
+
totalStaked: totalStaked.toString(),
|
|
1644
|
+
claimableEmissions: claimableEmissions.toString(),
|
|
1645
|
+
periodFinish: asNum(periodFinish),
|
|
1646
|
+
periodFinishRelative: relTime(periodFinish)
|
|
1647
|
+
};
|
|
1648
|
+
});
|
|
1649
|
+
return c.ok({
|
|
1650
|
+
gauges: items,
|
|
1651
|
+
count: items.length
|
|
1652
|
+
});
|
|
1653
|
+
}
|
|
1654
|
+
});
|
|
1655
|
+
gauges.command("info", {
|
|
1656
|
+
description: "Get detailed state for one gauge address.",
|
|
1657
|
+
args: z2.object({
|
|
1658
|
+
gauge: z2.string().describe("Gauge contract address")
|
|
1659
|
+
}),
|
|
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()
|
|
1678
|
+
}),
|
|
1679
|
+
examples: [
|
|
1680
|
+
{
|
|
1681
|
+
args: { gauge: "0x0000000000000000000000000000000000000001" },
|
|
1682
|
+
description: "Inspect one gauge in detail"
|
|
1683
|
+
}
|
|
1684
|
+
],
|
|
1685
|
+
async run(c) {
|
|
1686
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
1687
|
+
const gauge = c.args.gauge;
|
|
1688
|
+
const [
|
|
1689
|
+
pool,
|
|
1690
|
+
isAlive,
|
|
1691
|
+
bribeContract,
|
|
1692
|
+
feeContract,
|
|
1693
|
+
stakingToken,
|
|
1694
|
+
rewardToken,
|
|
1695
|
+
totalStaked,
|
|
1696
|
+
rewardRate,
|
|
1697
|
+
periodFinish,
|
|
1698
|
+
lastUpdateTime,
|
|
1699
|
+
rewardPerTokenStored,
|
|
1700
|
+
fees0,
|
|
1701
|
+
fees1,
|
|
1702
|
+
left
|
|
1703
|
+
] = await Promise.all([
|
|
1704
|
+
client.readContract({
|
|
1705
|
+
abi: voterAbi,
|
|
1706
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
1707
|
+
functionName: "poolForGauge",
|
|
1708
|
+
args: [gauge]
|
|
1709
|
+
}),
|
|
1710
|
+
client.readContract({
|
|
1711
|
+
abi: voterAbi,
|
|
1712
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
1713
|
+
functionName: "isAlive",
|
|
1714
|
+
args: [gauge]
|
|
1715
|
+
}),
|
|
1716
|
+
client.readContract({
|
|
1717
|
+
abi: voterAbi,
|
|
1718
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
1719
|
+
functionName: "gaugeToBribe",
|
|
1720
|
+
args: [gauge]
|
|
1721
|
+
}),
|
|
1722
|
+
client.readContract({
|
|
1723
|
+
abi: voterAbi,
|
|
1724
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
1725
|
+
functionName: "gaugeToFees",
|
|
1726
|
+
args: [gauge]
|
|
1727
|
+
}),
|
|
1728
|
+
client.readContract({
|
|
1729
|
+
abi: gaugeAbi,
|
|
1730
|
+
address: gauge,
|
|
1731
|
+
functionName: "stakingToken"
|
|
1732
|
+
}),
|
|
1733
|
+
client.readContract({
|
|
1734
|
+
abi: gaugeAbi,
|
|
1735
|
+
address: gauge,
|
|
1736
|
+
functionName: "rewardToken"
|
|
1737
|
+
}),
|
|
1738
|
+
client.readContract({
|
|
1739
|
+
abi: gaugeAbi,
|
|
1740
|
+
address: gauge,
|
|
1741
|
+
functionName: "totalSupply"
|
|
1742
|
+
}),
|
|
1743
|
+
client.readContract({
|
|
1744
|
+
abi: gaugeAbi,
|
|
1745
|
+
address: gauge,
|
|
1746
|
+
functionName: "rewardRate"
|
|
1747
|
+
}),
|
|
1748
|
+
client.readContract({
|
|
1749
|
+
abi: gaugeAbi,
|
|
1750
|
+
address: gauge,
|
|
1751
|
+
functionName: "periodFinish"
|
|
1752
|
+
}),
|
|
1753
|
+
client.readContract({
|
|
1754
|
+
abi: gaugeAbi,
|
|
1755
|
+
address: gauge,
|
|
1756
|
+
functionName: "lastUpdateTime"
|
|
1757
|
+
}),
|
|
1758
|
+
client.readContract({
|
|
1759
|
+
abi: gaugeAbi,
|
|
1760
|
+
address: gauge,
|
|
1761
|
+
functionName: "rewardPerTokenStored"
|
|
1762
|
+
}),
|
|
1763
|
+
client.readContract({
|
|
1764
|
+
abi: gaugeAbi,
|
|
1765
|
+
address: gauge,
|
|
1766
|
+
functionName: "fees0"
|
|
1767
|
+
}),
|
|
1768
|
+
client.readContract({
|
|
1769
|
+
abi: gaugeAbi,
|
|
1770
|
+
address: gauge,
|
|
1771
|
+
functionName: "fees1"
|
|
1772
|
+
}),
|
|
1773
|
+
client.readContract({
|
|
1774
|
+
abi: gaugeAbi,
|
|
1775
|
+
address: gauge,
|
|
1776
|
+
functionName: "left"
|
|
1777
|
+
})
|
|
1778
|
+
]);
|
|
1779
|
+
return c.ok({
|
|
1780
|
+
gauge: toChecksum(gauge),
|
|
1781
|
+
pool: toChecksum(pool),
|
|
1782
|
+
isAlive,
|
|
1783
|
+
stakingToken: toChecksum(stakingToken),
|
|
1784
|
+
rewardToken: toChecksum(rewardToken),
|
|
1785
|
+
totalStaked: totalStaked.toString(),
|
|
1786
|
+
rewardRate: rewardRate.toString(),
|
|
1787
|
+
rewardPerTokenStored: rewardPerTokenStored.toString(),
|
|
1788
|
+
fees0: fees0.toString(),
|
|
1789
|
+
fees1: fees1.toString(),
|
|
1790
|
+
left: left.toString(),
|
|
1791
|
+
periodFinish: asNum(periodFinish),
|
|
1792
|
+
periodFinishRelative: relTime(periodFinish),
|
|
1793
|
+
lastUpdateTime: asNum(lastUpdateTime),
|
|
1794
|
+
bribeContract: toChecksum(bribeContract),
|
|
1795
|
+
feeContract: toChecksum(feeContract)
|
|
1796
|
+
});
|
|
1797
|
+
}
|
|
1798
|
+
});
|
|
1799
|
+
gauges.command("staked", {
|
|
1800
|
+
description: "Show one address staking positions across all gauges.",
|
|
1801
|
+
args: z2.object({
|
|
1802
|
+
address: z2.string().describe("Wallet address to inspect")
|
|
1803
|
+
}),
|
|
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()
|
|
1814
|
+
})
|
|
1815
|
+
),
|
|
1816
|
+
count: z2.number()
|
|
1817
|
+
}),
|
|
1818
|
+
examples: [
|
|
1819
|
+
{
|
|
1820
|
+
args: { address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" },
|
|
1821
|
+
description: "List gauge positions for a wallet"
|
|
1822
|
+
}
|
|
1823
|
+
],
|
|
1824
|
+
async run(c) {
|
|
1825
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
1826
|
+
const gaugePools = await discoverGaugePools(client);
|
|
1827
|
+
if (!gaugePools.length) {
|
|
1828
|
+
return c.ok({
|
|
1829
|
+
address: toChecksum(c.args.address),
|
|
1830
|
+
positions: [],
|
|
1831
|
+
count: 0
|
|
1832
|
+
});
|
|
1833
|
+
}
|
|
1834
|
+
const positionData = await client.multicall({
|
|
1835
|
+
allowFailure: false,
|
|
1836
|
+
contracts: gaugePools.flatMap(({ gauge }) => [
|
|
1837
|
+
{
|
|
1838
|
+
abi: gaugeAbi,
|
|
1839
|
+
address: gauge,
|
|
1840
|
+
functionName: "balanceOf",
|
|
1841
|
+
args: [c.args.address]
|
|
1842
|
+
},
|
|
1843
|
+
{
|
|
1844
|
+
abi: gaugeAbi,
|
|
1845
|
+
address: gauge,
|
|
1846
|
+
functionName: "earned",
|
|
1847
|
+
args: [c.args.address]
|
|
1848
|
+
},
|
|
1849
|
+
{
|
|
1850
|
+
abi: gaugeAbi,
|
|
1851
|
+
address: gauge,
|
|
1852
|
+
functionName: "rewardToken"
|
|
1853
|
+
}
|
|
1854
|
+
])
|
|
1855
|
+
});
|
|
1856
|
+
const positions = gaugePools.map(({ pool, gauge }, index) => {
|
|
1857
|
+
const offset = index * 3;
|
|
1858
|
+
const staked = positionData[offset];
|
|
1859
|
+
const earned = positionData[offset + 1];
|
|
1860
|
+
const rewardToken = positionData[offset + 2];
|
|
1861
|
+
return {
|
|
1862
|
+
pool: toChecksum(pool),
|
|
1863
|
+
gauge: toChecksum(gauge),
|
|
1864
|
+
rewardToken: toChecksum(rewardToken),
|
|
1865
|
+
staked,
|
|
1866
|
+
earned
|
|
1867
|
+
};
|
|
1868
|
+
}).filter((position) => position.staked > 0n || position.earned > 0n).map((position) => ({
|
|
1869
|
+
pool: position.pool,
|
|
1870
|
+
gauge: position.gauge,
|
|
1871
|
+
rewardToken: position.rewardToken,
|
|
1872
|
+
staked: position.staked.toString(),
|
|
1873
|
+
earned: position.earned.toString()
|
|
1874
|
+
}));
|
|
1875
|
+
return c.ok({
|
|
1876
|
+
address: toChecksum(c.args.address),
|
|
1877
|
+
positions,
|
|
1878
|
+
count: positions.length
|
|
1879
|
+
});
|
|
1880
|
+
}
|
|
1881
|
+
});
|
|
1882
|
+
|
|
1883
|
+
// src/commands/ve.ts
|
|
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")
|
|
1887
|
+
});
|
|
1888
|
+
var ve = Cli3.create("ve", {
|
|
1889
|
+
description: "Inspect Aborean VotingEscrow (veABX) global and per-NFT lock state."
|
|
1890
|
+
});
|
|
1891
|
+
ve.command("stats", {
|
|
1892
|
+
description: "Get global VotingEscrow supply, locks, and decay checkpoint data.",
|
|
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()
|
|
1904
|
+
}),
|
|
1905
|
+
examples: [{ description: "Show global veABX state and decay metrics" }],
|
|
1906
|
+
async run(c) {
|
|
1907
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
1908
|
+
const [token, totalVotingPower, totalLocked, permanentLocked, epoch] = await Promise.all([
|
|
1909
|
+
client.readContract({
|
|
1910
|
+
abi: votingEscrowAbi,
|
|
1911
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
1912
|
+
functionName: "token"
|
|
1913
|
+
}),
|
|
1914
|
+
client.readContract({
|
|
1915
|
+
abi: votingEscrowAbi,
|
|
1916
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
1917
|
+
functionName: "totalSupply"
|
|
1918
|
+
}),
|
|
1919
|
+
client.readContract({
|
|
1920
|
+
abi: votingEscrowAbi,
|
|
1921
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
1922
|
+
functionName: "supply"
|
|
1923
|
+
}),
|
|
1924
|
+
client.readContract({
|
|
1925
|
+
abi: votingEscrowAbi,
|
|
1926
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
1927
|
+
functionName: "permanentLockBalance"
|
|
1928
|
+
}),
|
|
1929
|
+
client.readContract({
|
|
1930
|
+
abi: votingEscrowAbi,
|
|
1931
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
1932
|
+
functionName: "epoch"
|
|
1933
|
+
})
|
|
1934
|
+
]);
|
|
1935
|
+
const point = await client.readContract({
|
|
1936
|
+
abi: votingEscrowAbi,
|
|
1937
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
1938
|
+
functionName: "pointHistory",
|
|
1939
|
+
args: [epoch]
|
|
1940
|
+
});
|
|
1941
|
+
return c.ok({
|
|
1942
|
+
token: toChecksum(token),
|
|
1943
|
+
totalVotingPower: totalVotingPower.toString(),
|
|
1944
|
+
totalLocked: totalLocked.toString(),
|
|
1945
|
+
permanentLocked: permanentLocked.toString(),
|
|
1946
|
+
epoch: asNum(epoch),
|
|
1947
|
+
decayBias: point.bias.toString(),
|
|
1948
|
+
decaySlope: point.slope.toString(),
|
|
1949
|
+
lastCheckpointTimestamp: asNum(point.ts),
|
|
1950
|
+
lastCheckpointBlock: asNum(point.blk)
|
|
1951
|
+
});
|
|
1952
|
+
}
|
|
1953
|
+
});
|
|
1954
|
+
ve.command("lock", {
|
|
1955
|
+
description: "Get lock details and voting power for one veNFT token id.",
|
|
1956
|
+
args: z3.object({
|
|
1957
|
+
tokenId: z3.coerce.number().int().nonnegative().describe("veNFT token id")
|
|
1958
|
+
}),
|
|
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()
|
|
1967
|
+
}),
|
|
1968
|
+
examples: [{ args: { tokenId: 1 }, description: "Inspect lock details for veNFT #1" }],
|
|
1969
|
+
async run(c) {
|
|
1970
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
1971
|
+
const tokenId = BigInt(c.args.tokenId);
|
|
1972
|
+
const [owner, locked, votingPower] = await Promise.all([
|
|
1973
|
+
client.readContract({
|
|
1974
|
+
abi: votingEscrowAbi,
|
|
1975
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
1976
|
+
functionName: "ownerOf",
|
|
1977
|
+
args: [tokenId]
|
|
1978
|
+
}),
|
|
1979
|
+
client.readContract({
|
|
1980
|
+
abi: votingEscrowAbi,
|
|
1981
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
1982
|
+
functionName: "locked",
|
|
1983
|
+
args: [tokenId]
|
|
1984
|
+
}),
|
|
1985
|
+
client.readContract({
|
|
1986
|
+
abi: votingEscrowAbi,
|
|
1987
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
1988
|
+
functionName: "balanceOfNFT",
|
|
1989
|
+
args: [tokenId]
|
|
1990
|
+
})
|
|
1991
|
+
]);
|
|
1992
|
+
return c.ok({
|
|
1993
|
+
tokenId: c.args.tokenId,
|
|
1994
|
+
owner: toChecksum(owner),
|
|
1995
|
+
amount: locked.amount.toString(),
|
|
1996
|
+
unlockTime: asNum(locked.end),
|
|
1997
|
+
isPermanent: locked.isPermanent,
|
|
1998
|
+
votingPower: votingPower.toString()
|
|
1999
|
+
});
|
|
2000
|
+
}
|
|
2001
|
+
});
|
|
2002
|
+
ve.command("locks", {
|
|
2003
|
+
description: "List all veNFT locks owned by an address.",
|
|
2004
|
+
args: z3.object({
|
|
2005
|
+
address: z3.string().describe("Owner address")
|
|
2006
|
+
}),
|
|
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()
|
|
2017
|
+
})
|
|
2018
|
+
),
|
|
2019
|
+
count: z3.number()
|
|
2020
|
+
}),
|
|
2021
|
+
examples: [
|
|
2022
|
+
{
|
|
2023
|
+
args: { address: "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045" },
|
|
2024
|
+
description: "List all veNFT locks for an address"
|
|
2025
|
+
}
|
|
2026
|
+
],
|
|
2027
|
+
async run(c) {
|
|
2028
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
2029
|
+
const balance = await client.readContract({
|
|
2030
|
+
abi: votingEscrowAbi,
|
|
2031
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
2032
|
+
functionName: "balanceOf",
|
|
2033
|
+
args: [c.args.address]
|
|
2034
|
+
});
|
|
2035
|
+
const count = asNum(balance);
|
|
2036
|
+
if (!count) {
|
|
2037
|
+
return c.ok({
|
|
2038
|
+
address: toChecksum(c.args.address),
|
|
2039
|
+
locks: [],
|
|
2040
|
+
count: 0
|
|
2041
|
+
});
|
|
439
2042
|
}
|
|
2043
|
+
const indices = Array.from({ length: count }, (_, i) => BigInt(i));
|
|
2044
|
+
const tokenIds = await client.multicall({
|
|
2045
|
+
allowFailure: false,
|
|
2046
|
+
contracts: indices.map((index) => ({
|
|
2047
|
+
abi: votingEscrowAbi,
|
|
2048
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
2049
|
+
functionName: "tokenOfOwnerByIndex",
|
|
2050
|
+
args: [c.args.address, index]
|
|
2051
|
+
}))
|
|
2052
|
+
});
|
|
2053
|
+
const lockData = await client.multicall({
|
|
2054
|
+
allowFailure: false,
|
|
2055
|
+
contracts: tokenIds.flatMap((tokenId) => [
|
|
2056
|
+
{
|
|
2057
|
+
abi: votingEscrowAbi,
|
|
2058
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
2059
|
+
functionName: "locked",
|
|
2060
|
+
args: [tokenId]
|
|
2061
|
+
},
|
|
2062
|
+
{
|
|
2063
|
+
abi: votingEscrowAbi,
|
|
2064
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
2065
|
+
functionName: "balanceOfNFT",
|
|
2066
|
+
args: [tokenId]
|
|
2067
|
+
}
|
|
2068
|
+
])
|
|
2069
|
+
});
|
|
2070
|
+
const locks = tokenIds.map((tokenId, index) => {
|
|
2071
|
+
const offset = index * 2;
|
|
2072
|
+
const locked = lockData[offset];
|
|
2073
|
+
const votingPower = lockData[offset + 1];
|
|
2074
|
+
return {
|
|
2075
|
+
tokenId: tokenId.toString(),
|
|
2076
|
+
amount: locked.amount.toString(),
|
|
2077
|
+
unlockTime: asNum(locked.end),
|
|
2078
|
+
isPermanent: locked.isPermanent,
|
|
2079
|
+
votingPower: votingPower.toString()
|
|
2080
|
+
};
|
|
2081
|
+
});
|
|
2082
|
+
return c.ok({
|
|
2083
|
+
address: toChecksum(c.args.address),
|
|
2084
|
+
locks,
|
|
2085
|
+
count: locks.length
|
|
2086
|
+
});
|
|
440
2087
|
}
|
|
441
2088
|
});
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
})
|
|
2089
|
+
ve.command("voting-power", {
|
|
2090
|
+
description: "Get current voting power for one veNFT token id.",
|
|
2091
|
+
args: z3.object({
|
|
2092
|
+
tokenId: z3.coerce.number().int().nonnegative().describe("veNFT token id")
|
|
2093
|
+
}),
|
|
2094
|
+
env: env3,
|
|
2095
|
+
output: z3.object({
|
|
2096
|
+
tokenId: z3.number(),
|
|
2097
|
+
votingPower: z3.string()
|
|
2098
|
+
}),
|
|
2099
|
+
examples: [{ args: { tokenId: 1 }, description: "Get current voting power for veNFT #1" }],
|
|
2100
|
+
async run(c) {
|
|
2101
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
2102
|
+
const votingPower = await client.readContract({
|
|
2103
|
+
abi: votingEscrowAbi,
|
|
2104
|
+
address: ABOREAN_V2_ADDRESSES.votingEscrow,
|
|
2105
|
+
functionName: "balanceOfNFT",
|
|
2106
|
+
args: [BigInt(c.args.tokenId)]
|
|
2107
|
+
});
|
|
2108
|
+
return c.ok({
|
|
2109
|
+
tokenId: c.args.tokenId,
|
|
2110
|
+
votingPower: votingPower.toString()
|
|
2111
|
+
});
|
|
2112
|
+
}
|
|
2113
|
+
});
|
|
2114
|
+
|
|
2115
|
+
// src/commands/voter.ts
|
|
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")
|
|
2119
|
+
});
|
|
2120
|
+
async function discoverPools(client) {
|
|
2121
|
+
const [v2PoolCount, clPoolCount] = await Promise.all([
|
|
2122
|
+
client.readContract({
|
|
2123
|
+
abi: poolFactoryAbi,
|
|
2124
|
+
address: ABOREAN_V2_ADDRESSES.poolFactory,
|
|
2125
|
+
functionName: "allPoolsLength"
|
|
2126
|
+
}),
|
|
2127
|
+
client.readContract({
|
|
2128
|
+
abi: clFactoryAbi,
|
|
2129
|
+
address: ABOREAN_CL_ADDRESSES.clFactory,
|
|
2130
|
+
functionName: "allPoolsLength"
|
|
2131
|
+
})
|
|
2132
|
+
]);
|
|
2133
|
+
const v2Indices = Array.from({ length: asNum(v2PoolCount) }, (_, i) => BigInt(i));
|
|
2134
|
+
const clIndices = Array.from({ length: asNum(clPoolCount) }, (_, i) => BigInt(i));
|
|
2135
|
+
const [v2Pools, clPools] = await Promise.all([
|
|
2136
|
+
v2Indices.length ? client.multicall({
|
|
2137
|
+
allowFailure: false,
|
|
2138
|
+
contracts: v2Indices.map((index) => ({
|
|
2139
|
+
abi: poolFactoryAbi,
|
|
2140
|
+
address: ABOREAN_V2_ADDRESSES.poolFactory,
|
|
2141
|
+
functionName: "allPools",
|
|
2142
|
+
args: [index]
|
|
2143
|
+
}))
|
|
2144
|
+
}) : Promise.resolve([]),
|
|
2145
|
+
clIndices.length ? client.multicall({
|
|
2146
|
+
allowFailure: false,
|
|
2147
|
+
contracts: clIndices.map((index) => ({
|
|
2148
|
+
abi: clFactoryAbi,
|
|
2149
|
+
address: ABOREAN_CL_ADDRESSES.clFactory,
|
|
2150
|
+
functionName: "allPools",
|
|
2151
|
+
args: [index]
|
|
2152
|
+
}))
|
|
2153
|
+
}) : Promise.resolve([])
|
|
2154
|
+
]);
|
|
2155
|
+
return [...v2Pools, ...clPools];
|
|
447
2156
|
}
|
|
2157
|
+
var voter = Cli4.create("voter", {
|
|
2158
|
+
description: "Inspect Aborean voter epoch, pool weights, and claimable rewards context."
|
|
2159
|
+
});
|
|
2160
|
+
voter.command("epoch", {
|
|
2161
|
+
description: "Show current emissions epoch timing from Minter.",
|
|
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()
|
|
2171
|
+
}),
|
|
2172
|
+
examples: [{ description: "Inspect current voter epoch boundaries" }],
|
|
2173
|
+
async run(c) {
|
|
2174
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
2175
|
+
const [activePeriod, weekSeconds, epochCount, weeklyEmission] = await Promise.all([
|
|
2176
|
+
client.readContract({
|
|
2177
|
+
abi: minterAbi,
|
|
2178
|
+
address: ABOREAN_V2_ADDRESSES.minter,
|
|
2179
|
+
functionName: "activePeriod"
|
|
2180
|
+
}),
|
|
2181
|
+
client.readContract({
|
|
2182
|
+
abi: minterAbi,
|
|
2183
|
+
address: ABOREAN_V2_ADDRESSES.minter,
|
|
2184
|
+
functionName: "WEEK"
|
|
2185
|
+
}),
|
|
2186
|
+
client.readContract({
|
|
2187
|
+
abi: minterAbi,
|
|
2188
|
+
address: ABOREAN_V2_ADDRESSES.minter,
|
|
2189
|
+
functionName: "epochCount"
|
|
2190
|
+
}),
|
|
2191
|
+
client.readContract({
|
|
2192
|
+
abi: minterAbi,
|
|
2193
|
+
address: ABOREAN_V2_ADDRESSES.minter,
|
|
2194
|
+
functionName: "weekly"
|
|
2195
|
+
})
|
|
2196
|
+
]);
|
|
2197
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
2198
|
+
const epochEnd = asNum(activePeriod + weekSeconds);
|
|
2199
|
+
return c.ok({
|
|
2200
|
+
activePeriod: asNum(activePeriod),
|
|
2201
|
+
epochEnd,
|
|
2202
|
+
secondsRemaining: clampPositive(epochEnd - now),
|
|
2203
|
+
timeRemaining: relTime(activePeriod + weekSeconds),
|
|
2204
|
+
weekSeconds: asNum(weekSeconds),
|
|
2205
|
+
epochCount: asNum(epochCount),
|
|
2206
|
+
weeklyEmission: weeklyEmission.toString()
|
|
2207
|
+
});
|
|
2208
|
+
}
|
|
2209
|
+
});
|
|
2210
|
+
voter.command("weights", {
|
|
2211
|
+
description: "Show current pool voting weight distribution.",
|
|
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()
|
|
2220
|
+
})
|
|
2221
|
+
),
|
|
2222
|
+
count: z4.number()
|
|
2223
|
+
}),
|
|
2224
|
+
examples: [{ description: "List all pools with non-zero voting weight" }],
|
|
2225
|
+
async run(c) {
|
|
2226
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
2227
|
+
const pools = await discoverPools(client);
|
|
2228
|
+
if (!pools.length) {
|
|
2229
|
+
return c.ok({ totalWeight: "0", pools: [], count: 0 });
|
|
2230
|
+
}
|
|
2231
|
+
const [totalWeight, poolData] = await Promise.all([
|
|
2232
|
+
client.readContract({
|
|
2233
|
+
abi: voterAbi,
|
|
2234
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
2235
|
+
functionName: "totalWeight"
|
|
2236
|
+
}),
|
|
2237
|
+
client.multicall({
|
|
2238
|
+
allowFailure: false,
|
|
2239
|
+
contracts: pools.flatMap((pool) => [
|
|
2240
|
+
{
|
|
2241
|
+
abi: voterAbi,
|
|
2242
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
2243
|
+
functionName: "gauges",
|
|
2244
|
+
args: [pool]
|
|
2245
|
+
},
|
|
2246
|
+
{
|
|
2247
|
+
abi: voterAbi,
|
|
2248
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
2249
|
+
functionName: "weights",
|
|
2250
|
+
args: [pool]
|
|
2251
|
+
}
|
|
2252
|
+
])
|
|
2253
|
+
})
|
|
2254
|
+
]);
|
|
2255
|
+
const entries = pools.map((pool, index) => {
|
|
2256
|
+
const offset = index * 2;
|
|
2257
|
+
const gauge = poolData[offset] ?? ZERO_ADDRESS;
|
|
2258
|
+
const weight = poolData[offset + 1] ?? 0n;
|
|
2259
|
+
return {
|
|
2260
|
+
pool,
|
|
2261
|
+
gauge,
|
|
2262
|
+
weight
|
|
2263
|
+
};
|
|
2264
|
+
}).filter(
|
|
2265
|
+
(entry) => entry.gauge.toLowerCase() !== ZERO_ADDRESS.toLowerCase() && entry.weight > 0n
|
|
2266
|
+
).sort((a, b) => a.weight > b.weight ? -1 : a.weight < b.weight ? 1 : 0).map((entry) => ({
|
|
2267
|
+
pool: toChecksum(entry.pool),
|
|
2268
|
+
gauge: toChecksum(entry.gauge),
|
|
2269
|
+
weight: entry.weight.toString()
|
|
2270
|
+
}));
|
|
2271
|
+
return c.ok({
|
|
2272
|
+
totalWeight: totalWeight.toString(),
|
|
2273
|
+
pools: entries,
|
|
2274
|
+
count: entries.length
|
|
2275
|
+
});
|
|
2276
|
+
}
|
|
2277
|
+
});
|
|
2278
|
+
voter.command("rewards", {
|
|
2279
|
+
description: "Show claimable rebase rewards and voting context for a veNFT.",
|
|
2280
|
+
args: z4.object({
|
|
2281
|
+
tokenId: z4.coerce.number().int().nonnegative().describe("veNFT token id")
|
|
2282
|
+
}),
|
|
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()
|
|
2293
|
+
}),
|
|
2294
|
+
examples: [{ args: { tokenId: 1 }, description: "Check claimable voter/distributor rewards" }],
|
|
2295
|
+
async run(c) {
|
|
2296
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
2297
|
+
const tokenId = BigInt(c.args.tokenId);
|
|
2298
|
+
const [
|
|
2299
|
+
rewardToken,
|
|
2300
|
+
claimableRebase,
|
|
2301
|
+
timeCursor,
|
|
2302
|
+
lastTokenTime,
|
|
2303
|
+
distributorStartTime,
|
|
2304
|
+
usedWeight,
|
|
2305
|
+
lastVoted
|
|
2306
|
+
] = await Promise.all([
|
|
2307
|
+
client.readContract({
|
|
2308
|
+
abi: rewardsDistributorAbi,
|
|
2309
|
+
address: ABOREAN_V2_ADDRESSES.rewardsDistributor,
|
|
2310
|
+
functionName: "token"
|
|
2311
|
+
}),
|
|
2312
|
+
client.readContract({
|
|
2313
|
+
abi: rewardsDistributorAbi,
|
|
2314
|
+
address: ABOREAN_V2_ADDRESSES.rewardsDistributor,
|
|
2315
|
+
functionName: "claimable",
|
|
2316
|
+
args: [tokenId]
|
|
2317
|
+
}),
|
|
2318
|
+
client.readContract({
|
|
2319
|
+
abi: rewardsDistributorAbi,
|
|
2320
|
+
address: ABOREAN_V2_ADDRESSES.rewardsDistributor,
|
|
2321
|
+
functionName: "timeCursorOf",
|
|
2322
|
+
args: [tokenId]
|
|
2323
|
+
}),
|
|
2324
|
+
client.readContract({
|
|
2325
|
+
abi: rewardsDistributorAbi,
|
|
2326
|
+
address: ABOREAN_V2_ADDRESSES.rewardsDistributor,
|
|
2327
|
+
functionName: "lastTokenTime"
|
|
2328
|
+
}),
|
|
2329
|
+
client.readContract({
|
|
2330
|
+
abi: rewardsDistributorAbi,
|
|
2331
|
+
address: ABOREAN_V2_ADDRESSES.rewardsDistributor,
|
|
2332
|
+
functionName: "startTime"
|
|
2333
|
+
}),
|
|
2334
|
+
client.readContract({
|
|
2335
|
+
abi: voterAbi,
|
|
2336
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
2337
|
+
functionName: "usedWeights",
|
|
2338
|
+
args: [tokenId]
|
|
2339
|
+
}),
|
|
2340
|
+
client.readContract({
|
|
2341
|
+
abi: voterAbi,
|
|
2342
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
2343
|
+
functionName: "lastVoted",
|
|
2344
|
+
args: [tokenId]
|
|
2345
|
+
})
|
|
2346
|
+
]);
|
|
2347
|
+
return c.ok({
|
|
2348
|
+
tokenId: c.args.tokenId,
|
|
2349
|
+
rewardToken: toChecksum(rewardToken),
|
|
2350
|
+
claimableRebase: claimableRebase.toString(),
|
|
2351
|
+
timeCursor: asNum(timeCursor),
|
|
2352
|
+
lastTokenTime: asNum(lastTokenTime),
|
|
2353
|
+
distributorStartTime: asNum(distributorStartTime),
|
|
2354
|
+
usedWeight: usedWeight.toString(),
|
|
2355
|
+
lastVoted: asNum(lastVoted)
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2358
|
+
});
|
|
2359
|
+
voter.command("bribes", {
|
|
2360
|
+
description: "Show active bribe reward tokens and current-epoch amounts for a pool.",
|
|
2361
|
+
args: z4.object({
|
|
2362
|
+
pool: z4.string().describe("Pool address")
|
|
2363
|
+
}),
|
|
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()
|
|
2374
|
+
})
|
|
2375
|
+
),
|
|
2376
|
+
count: z4.number()
|
|
2377
|
+
}),
|
|
2378
|
+
examples: [
|
|
2379
|
+
{
|
|
2380
|
+
args: { pool: "0x0000000000000000000000000000000000000001" },
|
|
2381
|
+
description: "Inspect bribe reward tokens for one pool"
|
|
2382
|
+
}
|
|
2383
|
+
],
|
|
2384
|
+
async run(c) {
|
|
2385
|
+
const client = createAboreanPublicClient(c.env.ABSTRACT_RPC_URL);
|
|
2386
|
+
const [gauge, epochStart] = await Promise.all([
|
|
2387
|
+
client.readContract({
|
|
2388
|
+
abi: voterAbi,
|
|
2389
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
2390
|
+
functionName: "gauges",
|
|
2391
|
+
args: [c.args.pool]
|
|
2392
|
+
}),
|
|
2393
|
+
client.readContract({
|
|
2394
|
+
abi: minterAbi,
|
|
2395
|
+
address: ABOREAN_V2_ADDRESSES.minter,
|
|
2396
|
+
functionName: "activePeriod"
|
|
2397
|
+
})
|
|
2398
|
+
]);
|
|
2399
|
+
if (gauge.toLowerCase() === ZERO_ADDRESS.toLowerCase()) {
|
|
2400
|
+
return c.error({
|
|
2401
|
+
code: "NOT_FOUND",
|
|
2402
|
+
message: `No gauge exists for pool ${c.args.pool}`,
|
|
2403
|
+
retryable: false
|
|
2404
|
+
});
|
|
2405
|
+
}
|
|
2406
|
+
const bribeContract = await client.readContract({
|
|
2407
|
+
abi: voterAbi,
|
|
2408
|
+
address: ABOREAN_V2_ADDRESSES.voter,
|
|
2409
|
+
functionName: "gaugeToBribe",
|
|
2410
|
+
args: [gauge]
|
|
2411
|
+
});
|
|
2412
|
+
if (bribeContract.toLowerCase() === ZERO_ADDRESS.toLowerCase()) {
|
|
2413
|
+
return c.ok({
|
|
2414
|
+
pool: toChecksum(c.args.pool),
|
|
2415
|
+
gauge: toChecksum(gauge),
|
|
2416
|
+
bribeContract: toChecksum(bribeContract),
|
|
2417
|
+
epochStart: asNum(epochStart),
|
|
2418
|
+
rewardTokens: [],
|
|
2419
|
+
count: 0
|
|
2420
|
+
});
|
|
2421
|
+
}
|
|
2422
|
+
const rewardsLength = await client.readContract({
|
|
2423
|
+
abi: votingRewardAbi,
|
|
2424
|
+
address: bribeContract,
|
|
2425
|
+
functionName: "rewardsListLength"
|
|
2426
|
+
});
|
|
2427
|
+
const tokenCount = asNum(rewardsLength);
|
|
2428
|
+
if (!tokenCount) {
|
|
2429
|
+
return c.ok({
|
|
2430
|
+
pool: toChecksum(c.args.pool),
|
|
2431
|
+
gauge: toChecksum(gauge),
|
|
2432
|
+
bribeContract: toChecksum(bribeContract),
|
|
2433
|
+
epochStart: asNum(epochStart),
|
|
2434
|
+
rewardTokens: [],
|
|
2435
|
+
count: 0
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2438
|
+
const tokenIndices = Array.from({ length: tokenCount }, (_, i) => BigInt(i));
|
|
2439
|
+
const rewardTokens = await client.multicall({
|
|
2440
|
+
allowFailure: false,
|
|
2441
|
+
contracts: tokenIndices.map((index) => ({
|
|
2442
|
+
abi: votingRewardAbi,
|
|
2443
|
+
address: bribeContract,
|
|
2444
|
+
functionName: "rewards",
|
|
2445
|
+
args: [index]
|
|
2446
|
+
}))
|
|
2447
|
+
});
|
|
2448
|
+
const epochAmounts = await client.multicall({
|
|
2449
|
+
allowFailure: false,
|
|
2450
|
+
contracts: rewardTokens.map((token) => ({
|
|
2451
|
+
abi: votingRewardAbi,
|
|
2452
|
+
address: bribeContract,
|
|
2453
|
+
functionName: "tokenRewardsPerEpoch",
|
|
2454
|
+
args: [token, epochStart]
|
|
2455
|
+
}))
|
|
2456
|
+
});
|
|
2457
|
+
const items = rewardTokens.map((token, index) => ({
|
|
2458
|
+
token: toChecksum(token),
|
|
2459
|
+
epochAmount: epochAmounts[index].toString()
|
|
2460
|
+
}));
|
|
2461
|
+
return c.ok({
|
|
2462
|
+
pool: toChecksum(c.args.pool),
|
|
2463
|
+
gauge: toChecksum(gauge),
|
|
2464
|
+
bribeContract: toChecksum(bribeContract),
|
|
2465
|
+
epochStart: asNum(epochStart),
|
|
2466
|
+
rewardTokens: items,
|
|
2467
|
+
count: items.length
|
|
2468
|
+
});
|
|
2469
|
+
}
|
|
2470
|
+
});
|
|
448
2471
|
|
|
449
2472
|
// src/error-handling.ts
|
|
450
2473
|
import { AsyncLocalStorage } from "async_hooks";
|
|
@@ -576,23 +2599,27 @@ function applyFriendlyErrorHandling(cli2) {
|
|
|
576
2599
|
// src/cli.ts
|
|
577
2600
|
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
578
2601
|
var pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf8"));
|
|
579
|
-
var cli =
|
|
2602
|
+
var cli = Cli5.create("aborean", {
|
|
580
2603
|
version: pkg.version,
|
|
581
2604
|
description: "Aborean Finance DEX CLI for Abstract chain."
|
|
582
2605
|
});
|
|
583
|
-
|
|
584
|
-
|
|
2606
|
+
cli.command(gauges);
|
|
2607
|
+
cli.command(ve);
|
|
2608
|
+
cli.command(voter);
|
|
2609
|
+
var rootEnv = z5.object({
|
|
2610
|
+
ABSTRACT_RPC_URL: z5.string().optional().describe("Abstract RPC URL override")
|
|
585
2611
|
});
|
|
2612
|
+
cli.command(cl);
|
|
586
2613
|
cli.command("status", {
|
|
587
2614
|
description: "Get a cross-contract Aborean protocol snapshot (pool counts, gauge count, veABX supply).",
|
|
588
2615
|
env: rootEnv,
|
|
589
|
-
output:
|
|
590
|
-
v2PoolCount:
|
|
591
|
-
clPoolCount:
|
|
592
|
-
gaugeCount:
|
|
593
|
-
totalVotingWeight:
|
|
594
|
-
veABXTotalSupply:
|
|
595
|
-
veABXLockedSupply:
|
|
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)")
|
|
596
2623
|
}),
|
|
597
2624
|
examples: [{ description: "Fetch the current Aborean protocol status" }],
|
|
598
2625
|
async run(c) {
|