@sherwoodagent/cli 0.73.4 → 0.74.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/{abis-KP7M4IPM.js → abis-OLIDCWDS.js} +2 -2
  2. package/dist/{addresses-DGB3D457.js → addresses-OFFTM6NG.js} +4 -4
  3. package/dist/{agent-UNSW5IPO.js → agent-B7V5L2ZL.js} +8 -8
  4. package/dist/{chat-KT2WVDT2.js → chat-CXUU4AXK.js} +9 -10
  5. package/dist/{chat-KT2WVDT2.js.map → chat-CXUU4AXK.js.map} +1 -1
  6. package/dist/{chunk-ROKE6ZAW.js → chunk-2OHX3O55.js} +6 -20
  7. package/dist/chunk-2OHX3O55.js.map +1 -0
  8. package/dist/chunk-3ZOWP3VO.js +173 -0
  9. package/dist/chunk-3ZOWP3VO.js.map +1 -0
  10. package/dist/chunk-4LKU7ASB.js +1253 -0
  11. package/dist/chunk-4LKU7ASB.js.map +1 -0
  12. package/dist/{chunk-GSC7PVEO.js → chunk-6MV4ESXM.js} +43 -7
  13. package/dist/chunk-6MV4ESXM.js.map +1 -0
  14. package/dist/{chunk-CHWBQJLT.js → chunk-6UEQUVTQ.js} +8 -21
  15. package/dist/chunk-6UEQUVTQ.js.map +1 -0
  16. package/dist/{chunk-NPWYX6NU.js → chunk-BD4ZV7FQ.js} +3 -3
  17. package/dist/{chunk-BKJ7HYX7.js → chunk-DGLLSZ2D.js} +10 -10
  18. package/dist/chunk-DGLLSZ2D.js.map +1 -0
  19. package/dist/chunk-EGJESQXZ.js +1 -0
  20. package/dist/{chunk-ZURDCYGU.js → chunk-EW6FTUOL.js} +9 -5
  21. package/dist/chunk-EW6FTUOL.js.map +1 -0
  22. package/dist/{chunk-2U4TWPWQ.js → chunk-K3EYEJMT.js} +5 -5
  23. package/dist/{chunk-DXJJMRBM.js → chunk-LHVSS27T.js} +2 -2
  24. package/dist/{chunk-GU5VZGXB.js → chunk-O65AC2YS.js} +5 -5
  25. package/dist/chunk-TU655ZTV.js +3866 -0
  26. package/dist/chunk-TU655ZTV.js.map +1 -0
  27. package/dist/{chunk-IFL5SREW.js → chunk-UINMHN6S.js} +2 -2
  28. package/dist/{chunk-CZRJ5GWE.js → chunk-YADJ5YWY.js} +54 -24
  29. package/dist/chunk-YADJ5YWY.js.map +1 -0
  30. package/dist/{client-NAL3HVLK.js → client-C3C6IXAH.js} +4 -4
  31. package/dist/{config-FAQO37S7.js → config-7HU4X7EK.js} +4 -4
  32. package/dist/{eas-QAH7XVLK.js → eas-XWQYAUEM.js} +7 -7
  33. package/dist/{governor-S56M6BV6.js → governor-NHXBIFFB.js} +7 -7
  34. package/dist/index.js +201 -1286
  35. package/dist/index.js.map +1 -1
  36. package/dist/{network-MKMX2NG6.js → network-WU2QC3L4.js} +3 -3
  37. package/dist/{price-HHDBMKIE.js → price-QSVIM6QY.js} +15 -37
  38. package/dist/price-QSVIM6QY.js.map +1 -0
  39. package/dist/providers-YOOQFBN2.js +31 -0
  40. package/dist/providers-YOOQFBN2.js.map +1 -0
  41. package/dist/{research-IJBOMYL3.js → research-NQKYGTLY.js} +9 -9
  42. package/dist/{session-L67AVWBY.js → session-NLI6UFKB.js} +19 -174
  43. package/dist/session-NLI6UFKB.js.map +1 -0
  44. package/dist/{trade-LGFQEK3I.js → trade-6VYB6YJZ.js} +277 -43
  45. package/dist/trade-6VYB6YJZ.js.map +1 -0
  46. package/dist/{vault-XWFPGHRA.js → vault-45POYGLN.js} +14 -9
  47. package/dist/{xmtp-6US7GH3Z.js → xmtp-KH5I6GOL.js} +11 -15
  48. package/dist/xmtp-KH5I6GOL.js.map +1 -0
  49. package/package.json +2 -1
  50. package/dist/chunk-BKJ7HYX7.js.map +0 -1
  51. package/dist/chunk-BQMOE4FJ.js +0 -1629
  52. package/dist/chunk-BQMOE4FJ.js.map +0 -1
  53. package/dist/chunk-CHWBQJLT.js.map +0 -1
  54. package/dist/chunk-CZRJ5GWE.js.map +0 -1
  55. package/dist/chunk-DIZEB2VV.js +0 -325
  56. package/dist/chunk-DIZEB2VV.js.map +0 -1
  57. package/dist/chunk-GSC7PVEO.js.map +0 -1
  58. package/dist/chunk-ROKE6ZAW.js.map +0 -1
  59. package/dist/chunk-ZURDCYGU.js.map +0 -1
  60. package/dist/price-HHDBMKIE.js.map +0 -1
  61. package/dist/research-4TBGYEVI.js +0 -14
  62. package/dist/session-L67AVWBY.js.map +0 -1
  63. package/dist/trade-LGFQEK3I.js.map +0 -1
  64. package/dist/xmtp-6US7GH3Z.js.map +0 -1
  65. /package/dist/{abis-KP7M4IPM.js.map → abis-OLIDCWDS.js.map} +0 -0
  66. /package/dist/{addresses-DGB3D457.js.map → addresses-OFFTM6NG.js.map} +0 -0
  67. /package/dist/{agent-UNSW5IPO.js.map → agent-B7V5L2ZL.js.map} +0 -0
  68. /package/dist/{chunk-NPWYX6NU.js.map → chunk-BD4ZV7FQ.js.map} +0 -0
  69. /package/dist/{client-NAL3HVLK.js.map → chunk-EGJESQXZ.js.map} +0 -0
  70. /package/dist/{chunk-2U4TWPWQ.js.map → chunk-K3EYEJMT.js.map} +0 -0
  71. /package/dist/{chunk-DXJJMRBM.js.map → chunk-LHVSS27T.js.map} +0 -0
  72. /package/dist/{chunk-GU5VZGXB.js.map → chunk-O65AC2YS.js.map} +0 -0
  73. /package/dist/{chunk-IFL5SREW.js.map → chunk-UINMHN6S.js.map} +0 -0
  74. /package/dist/{config-FAQO37S7.js.map → client-C3C6IXAH.js.map} +0 -0
  75. /package/dist/{eas-QAH7XVLK.js.map → config-7HU4X7EK.js.map} +0 -0
  76. /package/dist/{governor-S56M6BV6.js.map → eas-XWQYAUEM.js.map} +0 -0
  77. /package/dist/{network-MKMX2NG6.js.map → governor-NHXBIFFB.js.map} +0 -0
  78. /package/dist/{research-4TBGYEVI.js.map → network-WU2QC3L4.js.map} +0 -0
  79. /package/dist/{research-IJBOMYL3.js.map → research-NQKYGTLY.js.map} +0 -0
  80. /package/dist/{vault-XWFPGHRA.js.map → vault-45POYGLN.js.map} +0 -0
@@ -0,0 +1,1253 @@
1
+ import {
2
+ AERODROME,
3
+ CHAINLINK,
4
+ MOONWELL,
5
+ ROBINHOOD_STOCK_ROUTES,
6
+ SYNTHRA,
7
+ TOKENS,
8
+ UNISWAP,
9
+ VENICE,
10
+ robinhoodEquityMaxAge
11
+ } from "./chunk-UINMHN6S.js";
12
+ import {
13
+ getPublicClient
14
+ } from "./chunk-2OHX3O55.js";
15
+ import {
16
+ getNetwork
17
+ } from "./chunk-LHVSS27T.js";
18
+ import {
19
+ BASE_STRATEGY_ABI,
20
+ ERC20_ABI,
21
+ UNISWAP_QUOTER_V2_ABI
22
+ } from "./chunk-TU655ZTV.js";
23
+
24
+ // src/lib/swap-router.ts
25
+ import { encodeFunctionData as encodeFunctionData9, decodeFunctionResult } from "viem";
26
+
27
+ // src/lib/template-encoder.ts
28
+ import {
29
+ parseUnits,
30
+ isAddress,
31
+ encodeAbiParameters as encodeAbiParameters9,
32
+ concat as concat2,
33
+ numberToHex as numberToHex2
34
+ } from "viem";
35
+ import chalk from "chalk";
36
+
37
+ // src/strategies/moonwell-supply-template.ts
38
+ import { encodeAbiParameters, encodeFunctionData } from "viem";
39
+ function buildInitData(underlying, mToken, supplyAmount, minRedeemAmount, isNativeEthMarket) {
40
+ return encodeAbiParameters(
41
+ [
42
+ { type: "address" },
43
+ { type: "address" },
44
+ { type: "uint256" },
45
+ { type: "uint256" },
46
+ { type: "bool" }
47
+ ],
48
+ [underlying, mToken, supplyAmount, minRedeemAmount, isNativeEthMarket]
49
+ );
50
+ }
51
+ function buildExecuteCalls(clone, underlying, supplyAmount) {
52
+ return [
53
+ {
54
+ target: underlying,
55
+ data: encodeFunctionData({
56
+ abi: ERC20_ABI,
57
+ functionName: "approve",
58
+ args: [clone, supplyAmount]
59
+ }),
60
+ value: 0n
61
+ },
62
+ {
63
+ target: clone,
64
+ data: encodeFunctionData({
65
+ abi: BASE_STRATEGY_ABI,
66
+ functionName: "execute"
67
+ }),
68
+ value: 0n
69
+ }
70
+ ];
71
+ }
72
+ function buildSettleCalls(clone) {
73
+ return [
74
+ {
75
+ target: clone,
76
+ data: encodeFunctionData({
77
+ abi: BASE_STRATEGY_ABI,
78
+ functionName: "settle"
79
+ }),
80
+ value: 0n
81
+ }
82
+ ];
83
+ }
84
+
85
+ // src/strategies/venice-inference-template.ts
86
+ import { encodeAbiParameters as encodeAbiParameters2, encodeFunctionData as encodeFunctionData2 } from "viem";
87
+ var INIT_PARAMS_TYPES = [
88
+ {
89
+ type: "tuple",
90
+ components: [
91
+ { name: "asset", type: "address" },
92
+ { name: "weth", type: "address" },
93
+ { name: "vvv", type: "address" },
94
+ { name: "sVVV", type: "address" },
95
+ { name: "aeroRouter", type: "address" },
96
+ { name: "aeroFactory", type: "address" },
97
+ { name: "agent", type: "address" },
98
+ { name: "assetAmount", type: "uint256" },
99
+ { name: "minVVV", type: "uint256" },
100
+ { name: "deadlineOffset", type: "uint256" },
101
+ { name: "singleHop", type: "bool" }
102
+ ]
103
+ }
104
+ ];
105
+ function buildInitData2(params) {
106
+ return encodeAbiParameters2(INIT_PARAMS_TYPES, [params]);
107
+ }
108
+ function buildExecuteCalls2(clone, asset, assetAmount) {
109
+ return [
110
+ {
111
+ target: asset,
112
+ data: encodeFunctionData2({
113
+ abi: ERC20_ABI,
114
+ functionName: "approve",
115
+ args: [clone, assetAmount]
116
+ }),
117
+ value: 0n
118
+ },
119
+ {
120
+ target: clone,
121
+ data: encodeFunctionData2({
122
+ abi: BASE_STRATEGY_ABI,
123
+ functionName: "execute"
124
+ }),
125
+ value: 0n
126
+ }
127
+ ];
128
+ }
129
+ function buildSettleCalls2(clone) {
130
+ return [
131
+ {
132
+ target: clone,
133
+ data: encodeFunctionData2({
134
+ abi: BASE_STRATEGY_ABI,
135
+ functionName: "settle"
136
+ }),
137
+ value: 0n
138
+ }
139
+ ];
140
+ }
141
+
142
+ // src/strategies/aerodrome-lp-template.ts
143
+ import { encodeAbiParameters as encodeAbiParameters3, encodeFunctionData as encodeFunctionData3 } from "viem";
144
+ var INIT_PARAMS_TYPES2 = [
145
+ {
146
+ type: "tuple",
147
+ components: [
148
+ { name: "tokenA", type: "address" },
149
+ { name: "tokenB", type: "address" },
150
+ { name: "stable", type: "bool" },
151
+ { name: "factory", type: "address" },
152
+ { name: "router", type: "address" },
153
+ { name: "gauge", type: "address" },
154
+ { name: "lpToken", type: "address" },
155
+ { name: "amountADesired", type: "uint256" },
156
+ { name: "amountBDesired", type: "uint256" },
157
+ { name: "amountAMin", type: "uint256" },
158
+ { name: "amountBMin", type: "uint256" },
159
+ { name: "minAmountAOut", type: "uint256" },
160
+ { name: "minAmountBOut", type: "uint256" }
161
+ ]
162
+ }
163
+ ];
164
+ function buildInitData3(params) {
165
+ return encodeAbiParameters3(INIT_PARAMS_TYPES2, [params]);
166
+ }
167
+ function buildExecuteCalls3(clone, tokenA, amountA, tokenB, amountB) {
168
+ return [
169
+ {
170
+ target: tokenA,
171
+ data: encodeFunctionData3({
172
+ abi: ERC20_ABI,
173
+ functionName: "approve",
174
+ args: [clone, amountA]
175
+ }),
176
+ value: 0n
177
+ },
178
+ {
179
+ target: tokenB,
180
+ data: encodeFunctionData3({
181
+ abi: ERC20_ABI,
182
+ functionName: "approve",
183
+ args: [clone, amountB]
184
+ }),
185
+ value: 0n
186
+ },
187
+ {
188
+ target: clone,
189
+ data: encodeFunctionData3({
190
+ abi: BASE_STRATEGY_ABI,
191
+ functionName: "execute"
192
+ }),
193
+ value: 0n
194
+ }
195
+ ];
196
+ }
197
+ function buildSettleCalls3(clone) {
198
+ return [
199
+ {
200
+ target: clone,
201
+ data: encodeFunctionData3({
202
+ abi: BASE_STRATEGY_ABI,
203
+ functionName: "settle"
204
+ }),
205
+ value: 0n
206
+ }
207
+ ];
208
+ }
209
+
210
+ // src/strategies/wsteth-moonwell-template.ts
211
+ import { encodeAbiParameters as encodeAbiParameters4, encodeFunctionData as encodeFunctionData4, maxUint256 } from "viem";
212
+ var INIT_PARAMS_TYPES3 = [
213
+ {
214
+ type: "tuple",
215
+ components: [
216
+ { name: "weth", type: "address" },
217
+ { name: "wsteth", type: "address" },
218
+ { name: "mwsteth", type: "address" },
219
+ { name: "aeroRouter", type: "address" },
220
+ { name: "aeroFactory", type: "address" },
221
+ { name: "chainlinkWstethEthFeed", type: "address" },
222
+ { name: "supplyAmount", type: "uint256" },
223
+ { name: "minWstethOutPerWeth", type: "uint256" },
224
+ { name: "minWethOutPerWsteth", type: "uint256" },
225
+ { name: "deadlineOffset", type: "uint256" }
226
+ ]
227
+ }
228
+ ];
229
+ function buildInitData4(params) {
230
+ return encodeAbiParameters4(INIT_PARAMS_TYPES3, [params]);
231
+ }
232
+ function buildExecuteCalls4(clone, weth, supplyAmount) {
233
+ const approveAmount = supplyAmount === 0n ? maxUint256 : supplyAmount;
234
+ return [
235
+ {
236
+ target: weth,
237
+ data: encodeFunctionData4({
238
+ abi: ERC20_ABI,
239
+ functionName: "approve",
240
+ args: [clone, approveAmount]
241
+ }),
242
+ value: 0n
243
+ },
244
+ {
245
+ target: clone,
246
+ data: encodeFunctionData4({
247
+ abi: BASE_STRATEGY_ABI,
248
+ functionName: "execute"
249
+ }),
250
+ value: 0n
251
+ },
252
+ {
253
+ target: weth,
254
+ data: encodeFunctionData4({
255
+ abi: ERC20_ABI,
256
+ functionName: "approve",
257
+ args: [clone, 0n]
258
+ }),
259
+ value: 0n
260
+ }
261
+ ];
262
+ }
263
+ function buildSettleCalls4(clone) {
264
+ return [
265
+ {
266
+ target: clone,
267
+ data: encodeFunctionData4({
268
+ abi: BASE_STRATEGY_ABI,
269
+ functionName: "settle"
270
+ }),
271
+ value: 0n
272
+ }
273
+ ];
274
+ }
275
+
276
+ // src/strategies/mamo-yield-template.ts
277
+ import { encodeAbiParameters as encodeAbiParameters5, encodeFunctionData as encodeFunctionData5 } from "viem";
278
+ function buildInitData5(underlying, mamoFactory, minRedeemAmount) {
279
+ return encodeAbiParameters5(
280
+ [
281
+ { type: "address" },
282
+ { type: "address" },
283
+ { type: "uint256" }
284
+ ],
285
+ [underlying, mamoFactory, minRedeemAmount]
286
+ );
287
+ }
288
+ function buildExecuteCalls5(clone, underlying, amount) {
289
+ return [
290
+ {
291
+ target: underlying,
292
+ data: encodeFunctionData5({
293
+ abi: ERC20_ABI,
294
+ functionName: "approve",
295
+ args: [clone, amount]
296
+ }),
297
+ value: 0n
298
+ },
299
+ {
300
+ target: clone,
301
+ data: encodeFunctionData5({
302
+ abi: BASE_STRATEGY_ABI,
303
+ functionName: "execute"
304
+ }),
305
+ value: 0n
306
+ }
307
+ ];
308
+ }
309
+ function buildSettleCalls5(clone) {
310
+ return [
311
+ {
312
+ target: clone,
313
+ data: encodeFunctionData5({
314
+ abi: BASE_STRATEGY_ABI,
315
+ functionName: "settle"
316
+ }),
317
+ value: 0n
318
+ }
319
+ ];
320
+ }
321
+
322
+ // src/strategies/portfolio-template.ts
323
+ import { concat, encodeAbiParameters as encodeAbiParameters6, encodeFunctionData as encodeFunctionData6, numberToHex, pad } from "viem";
324
+ function withMode(mode, routeData) {
325
+ const modeByte = `0x${mode.toString(16).padStart(2, "0")}`;
326
+ return concat([modeByte, routeData]);
327
+ }
328
+ function v3SingleHopExtraData(fee) {
329
+ return withMode(0, encodeAbiParameters6([{ type: "uint24" }], [fee]));
330
+ }
331
+ function v4SingleHopExtraData(fee, tickSpacing) {
332
+ return withMode(
333
+ 2,
334
+ encodeAbiParameters6(
335
+ [{ type: "uint24" }, { type: "int24" }],
336
+ [fee, tickSpacing]
337
+ )
338
+ );
339
+ }
340
+ function v4PathExtraData(hops) {
341
+ if (hops.length < 2) throw new Error("v4PathExtraData: mode 3 needs >= 2 hops (use v4SingleHopExtraData for one)");
342
+ return withMode(
343
+ 3,
344
+ encodeAbiParameters6(
345
+ [
346
+ {
347
+ type: "tuple[]",
348
+ components: [
349
+ { type: "address", name: "currency" },
350
+ { type: "uint24", name: "fee" },
351
+ { type: "int24", name: "tickSpacing" }
352
+ ]
353
+ }
354
+ ],
355
+ [hops.map((h) => ({ currency: h.currency, fee: h.fee, tickSpacing: h.tickSpacing }))]
356
+ )
357
+ );
358
+ }
359
+ var EQUITY_MAX_PRICE_AGE_SECONDS = 96 * 60 * 60;
360
+ var MIN_MAX_PRICE_AGE = 3600;
361
+ var MAX_MAX_PRICE_AGE = 2592e3;
362
+ function pushFeedId(feed, maxAgeSeconds) {
363
+ if (maxAgeSeconds === void 0 || maxAgeSeconds === 0) {
364
+ return pad(feed, { size: 32 });
365
+ }
366
+ if (!Number.isInteger(maxAgeSeconds) || maxAgeSeconds < MIN_MAX_PRICE_AGE || maxAgeSeconds > MAX_MAX_PRICE_AGE) {
367
+ throw new Error(
368
+ `pushFeedId: maxAgeSeconds must be an integer in [${MIN_MAX_PRICE_AGE}, ${MAX_MAX_PRICE_AGE}] (or 0 for the contract default), got ${maxAgeSeconds}`
369
+ );
370
+ }
371
+ const packed = BigInt(maxAgeSeconds) << 160n | BigInt(feed);
372
+ return numberToHex(packed, { size: 32 });
373
+ }
374
+ function buildInitData6(asset, swapAdapter, chainlinkVerifier, allocations, totalAmount, maxSlippageBps) {
375
+ const tokens = allocations.map((a) => a.token);
376
+ const weightsBps = allocations.map((a) => BigInt(a.weightBps));
377
+ const swapExtraData = allocations.map((a) => a.swapExtraData);
378
+ const priceDecimals = allocations.map((a) => a.priceDecimals);
379
+ const feedIds = allocations.map((a) => a.feedId);
380
+ return encodeAbiParameters6(
381
+ [
382
+ { type: "address" },
383
+ { type: "address" },
384
+ { type: "address" },
385
+ { type: "address[]" },
386
+ { type: "uint256[]" },
387
+ { type: "uint256" },
388
+ { type: "uint256" },
389
+ { type: "bytes[]" },
390
+ { type: "uint8[]" },
391
+ { type: "bytes32[]" }
392
+ ],
393
+ [
394
+ asset,
395
+ swapAdapter,
396
+ chainlinkVerifier,
397
+ tokens,
398
+ weightsBps,
399
+ totalAmount,
400
+ BigInt(maxSlippageBps),
401
+ swapExtraData,
402
+ priceDecimals,
403
+ feedIds
404
+ ]
405
+ );
406
+ }
407
+ function buildExecuteCalls6(clone, asset, totalAmount) {
408
+ return [
409
+ {
410
+ target: asset,
411
+ data: encodeFunctionData6({
412
+ abi: ERC20_ABI,
413
+ functionName: "approve",
414
+ args: [clone, totalAmount]
415
+ }),
416
+ value: 0n
417
+ },
418
+ {
419
+ target: clone,
420
+ data: encodeFunctionData6({
421
+ abi: BASE_STRATEGY_ABI,
422
+ functionName: "execute"
423
+ }),
424
+ value: 0n
425
+ }
426
+ ];
427
+ }
428
+ function buildSettleCalls6(clone) {
429
+ return [
430
+ {
431
+ target: clone,
432
+ data: encodeFunctionData6({
433
+ abi: BASE_STRATEGY_ABI,
434
+ functionName: "settle"
435
+ }),
436
+ value: 0n
437
+ }
438
+ ];
439
+ }
440
+
441
+ // src/strategies/hyperliquid-perp-template.ts
442
+ import { encodeAbiParameters as encodeAbiParameters7, encodeFunctionData as encodeFunctionData7, maxUint256 as maxUint2562 } from "viem";
443
+ function buildInitData7(asset, depositAmount, perpAssetIndex, leverage, maxPositionSize, maxTradesPerDay) {
444
+ return encodeAbiParameters7(
445
+ [
446
+ { type: "address" },
447
+ { type: "uint256" },
448
+ { type: "uint32" },
449
+ { type: "uint32" },
450
+ { type: "uint256" },
451
+ { type: "uint32" }
452
+ ],
453
+ [asset, depositAmount, perpAssetIndex, leverage, maxPositionSize, maxTradesPerDay]
454
+ );
455
+ }
456
+ function buildExecuteCalls7(clone, asset, amount) {
457
+ const approveAmount = amount === 0n ? maxUint2562 : amount;
458
+ return [
459
+ {
460
+ target: asset,
461
+ data: encodeFunctionData7({
462
+ abi: ERC20_ABI,
463
+ functionName: "approve",
464
+ args: [clone, approveAmount]
465
+ }),
466
+ value: 0n
467
+ },
468
+ {
469
+ target: clone,
470
+ data: encodeFunctionData7({
471
+ abi: BASE_STRATEGY_ABI,
472
+ functionName: "execute"
473
+ }),
474
+ value: 0n
475
+ },
476
+ {
477
+ target: asset,
478
+ data: encodeFunctionData7({
479
+ abi: ERC20_ABI,
480
+ functionName: "approve",
481
+ args: [clone, 0n]
482
+ }),
483
+ value: 0n
484
+ }
485
+ ];
486
+ }
487
+ function buildSettleCalls7(clone) {
488
+ return [
489
+ {
490
+ target: clone,
491
+ data: encodeFunctionData7({
492
+ abi: BASE_STRATEGY_ABI,
493
+ functionName: "settle"
494
+ }),
495
+ value: 0n
496
+ }
497
+ ];
498
+ }
499
+
500
+ // src/strategies/hyperliquid-grid-template.ts
501
+ import { encodeAbiParameters as encodeAbiParameters8, encodeFunctionData as encodeFunctionData8, maxUint256 as maxUint2563 } from "viem";
502
+ function buildInitData8(asset, depositAmount, leverage, maxOrderSize, maxOrdersPerTick, assetIndices) {
503
+ return encodeAbiParameters8(
504
+ [
505
+ { type: "address" },
506
+ { type: "uint256" },
507
+ { type: "uint32" },
508
+ { type: "uint256" },
509
+ { type: "uint32" },
510
+ { type: "uint32[]" }
511
+ ],
512
+ [asset, depositAmount, leverage, maxOrderSize, maxOrdersPerTick, assetIndices]
513
+ );
514
+ }
515
+ function buildExecuteCalls8(clone, asset, amount) {
516
+ const approveAmount = amount === 0n ? maxUint2563 : amount;
517
+ return [
518
+ {
519
+ target: asset,
520
+ data: encodeFunctionData8({
521
+ abi: ERC20_ABI,
522
+ functionName: "approve",
523
+ args: [clone, approveAmount]
524
+ }),
525
+ value: 0n
526
+ },
527
+ {
528
+ target: clone,
529
+ data: encodeFunctionData8({
530
+ abi: BASE_STRATEGY_ABI,
531
+ functionName: "execute"
532
+ }),
533
+ value: 0n
534
+ },
535
+ {
536
+ target: asset,
537
+ data: encodeFunctionData8({
538
+ abi: ERC20_ABI,
539
+ functionName: "approve",
540
+ args: [clone, 0n]
541
+ }),
542
+ value: 0n
543
+ }
544
+ ];
545
+ }
546
+ function buildSettleCalls8(clone) {
547
+ return [
548
+ {
549
+ target: clone,
550
+ data: encodeFunctionData8({
551
+ abi: BASE_STRATEGY_ABI,
552
+ functionName: "settle"
553
+ }),
554
+ value: 0n
555
+ }
556
+ ];
557
+ }
558
+
559
+ // src/lib/template-encoder.ts
560
+ var ZERO = "0x0000000000000000000000000000000000000000";
561
+ var ZERO_BYTES32 = "0x0000000000000000000000000000000000000000000000000000000000000000";
562
+ function encodeV3Path(tokens, fees) {
563
+ if (tokens.length !== fees.length + 1) throw new Error("tokens.length must be fees.length + 1");
564
+ const parts = [];
565
+ for (let i = 0; i < tokens.length; i++) {
566
+ parts.push(tokens[i].toLowerCase());
567
+ if (i < fees.length) {
568
+ parts.push(numberToHex2(fees[i], { size: 3 }));
569
+ }
570
+ }
571
+ return concat2(parts);
572
+ }
573
+ function buildSwapExtraData(network, tokenIn, tokenOut, feeTier, hop, perHopSlippageBps = 100) {
574
+ if (hop) {
575
+ const path = encodeV3Path([tokenIn, hop.via, tokenOut], [hop.feeIn, hop.feeOut]);
576
+ const encoded2 = encodeAbiParameters9(
577
+ [{ type: "bytes" }, { type: "uint16" }],
578
+ [path, perHopSlippageBps]
579
+ );
580
+ return `0x01${encoded2.slice(2)}`;
581
+ }
582
+ const encoded = encodeAbiParameters9([{ type: "uint24" }], [feeTier]);
583
+ return `0x00${encoded.slice(2)}`;
584
+ }
585
+ function parseSwapRouteSpec(spec, token) {
586
+ const s = spec.trim();
587
+ const [kind, ...restParts] = s.split(":");
588
+ const rest = restParts.join(":");
589
+ switch (kind) {
590
+ case "v3": {
591
+ const fee = Number(rest);
592
+ if (!Number.isInteger(fee) || fee <= 0) throw new Error(`bad v3 fee in '${spec}'`);
593
+ return v3SingleHopExtraData(fee);
594
+ }
595
+ case "v4": {
596
+ const [feeStr, tsStr] = rest.split(":");
597
+ const fee = Number(feeStr);
598
+ const tickSpacing = Number(tsStr);
599
+ if (!Number.isInteger(fee) || fee <= 0) throw new Error(`bad v4 fee in '${spec}'`);
600
+ if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) throw new Error(`bad v4 tickSpacing in '${spec}'`);
601
+ return v4SingleHopExtraData(fee, tickSpacing);
602
+ }
603
+ case "v4path": {
604
+ const hops = rest.split("+").map((hopStr) => {
605
+ const [currencyRaw, feeTs] = hopStr.split("@");
606
+ if (!feeTs) throw new Error(`bad v4path hop '${hopStr}' in '${spec}' (expected currency@fee:tickSpacing)`);
607
+ const [feeStr, tsStr] = feeTs.split(":");
608
+ const fee = Number(feeStr);
609
+ const tickSpacing = Number(tsStr);
610
+ if (!Number.isInteger(fee) || fee <= 0) throw new Error(`bad v4path fee in '${spec}'`);
611
+ if (!Number.isInteger(tickSpacing) || tickSpacing <= 0) throw new Error(`bad v4path tickSpacing in '${spec}'`);
612
+ const c = currencyRaw.trim().toLowerCase();
613
+ let currency;
614
+ if (c === "eth" || c === "native") currency = ZERO;
615
+ else if (c === "self") currency = token;
616
+ else if (isAddress(currencyRaw.trim())) currency = currencyRaw.trim();
617
+ else throw new Error(`bad v4path currency '${currencyRaw}' in '${spec}' (use eth/native/self/0x-address)`);
618
+ return { currency, fee, tickSpacing };
619
+ });
620
+ return v4PathExtraData(hops);
621
+ }
622
+ default:
623
+ throw new Error(`unknown swap-route kind '${kind}' in '${spec}' (use v3/v4/v4path)`);
624
+ }
625
+ }
626
+ async function detectSwapRoute(asset, token, preferredFeeTier) {
627
+ const network = getNetwork();
628
+ return {
629
+ extraData: buildSwapExtraData(network, asset, token, preferredFeeTier),
630
+ routeDesc: `direct (fee ${preferredFeeTier})`
631
+ };
632
+ }
633
+ function computeProposalAssetChecks(templateKey, opts) {
634
+ if (templateKey === "moonwell-supply" || templateKey === "mamo-yield") {
635
+ if (!opts.amount) return [];
636
+ const token = opts.token || "USDC";
637
+ const asset = resolveToken(token);
638
+ const decimals = assetDecimalsForSymbol(token);
639
+ return [{ asset, amount: parseUnits(opts.amount, decimals), label: token.toUpperCase() }];
640
+ }
641
+ if (templateKey === "venice-inference") {
642
+ if (!opts.amount) return [];
643
+ const assetSymbol = opts.asset || "USDC";
644
+ const asset = resolveToken(assetSymbol);
645
+ const decimals = assetDecimalsForSymbol(assetSymbol);
646
+ return [{ asset, amount: parseUnits(opts.amount, decimals), label: assetSymbol.toUpperCase() }];
647
+ }
648
+ if (templateKey === "aerodrome-lp") {
649
+ if (!opts.tokenA || !opts.tokenB || !opts.amountA || !opts.amountB) return [];
650
+ return [];
651
+ }
652
+ if (templateKey === "wsteth-moonwell") {
653
+ if (!opts.amount) return [];
654
+ return [{
655
+ asset: TOKENS().WETH,
656
+ amount: parseUnits(opts.amount, 18),
657
+ label: "WETH"
658
+ }];
659
+ }
660
+ if (templateKey === "portfolio") {
661
+ if (!opts.amount) return [];
662
+ const assetSymbol = opts.asset || defaultPortfolioAsset();
663
+ const asset = resolveToken(assetSymbol);
664
+ const decimals = assetDecimalsForSymbol(assetSymbol);
665
+ return [{ asset, amount: parseUnits(opts.amount, decimals), label: assetSymbol.toUpperCase() }];
666
+ }
667
+ if (templateKey === "hyperliquid-perp" || templateKey === "hyperliquid-grid") {
668
+ if (!opts.amount) return [];
669
+ const token = opts.token || "USDC";
670
+ const asset = resolveToken(token);
671
+ const decimals = assetDecimalsForSymbol(token);
672
+ return [{ asset, amount: parseUnits(opts.amount, decimals), label: token.toUpperCase() }];
673
+ }
674
+ return [];
675
+ }
676
+ function parseAlignedOverrides(raw, expectedLen) {
677
+ if (raw === void 0) return { values: [], mismatch: false };
678
+ const values = raw.split(",").map((s) => s.trim());
679
+ return { values, mismatch: values.length !== expectedLen };
680
+ }
681
+ async function buildInitDataForTemplate(templateKey, opts, vault, resolved) {
682
+ if (templateKey === "moonwell-supply") {
683
+ if (!opts.amount) {
684
+ console.error(chalk.red("--amount is required for moonwell-supply template"));
685
+ process.exit(1);
686
+ }
687
+ const token = opts.token || "USDC";
688
+ const underlying = resolveToken(token);
689
+ const mToken = resolveMToken(token);
690
+ const decimals = assetDecimalsForSymbol(token);
691
+ const supplyAmount = parseUnits(opts.amount, decimals);
692
+ const minRedeem = parseUnits(opts.minRedeem || opts.amount, decimals);
693
+ const isNativeEthMarket = token.toUpperCase() !== "USDC";
694
+ return {
695
+ initData: buildInitData(underlying, mToken, supplyAmount, minRedeem, isNativeEthMarket),
696
+ asset: underlying,
697
+ assetAmount: supplyAmount
698
+ };
699
+ }
700
+ if (templateKey === "venice-inference") {
701
+ if (!opts.amount) {
702
+ console.error(chalk.red("--amount is required for venice-inference template"));
703
+ process.exit(1);
704
+ }
705
+ const assetSymbol = opts.asset || "USDC";
706
+ const asset = resolveToken(assetSymbol);
707
+ const vvv = VENICE().VVV;
708
+ const isDirect = asset.toLowerCase() === vvv.toLowerCase();
709
+ const decimals = assetDecimalsForSymbol(assetSymbol);
710
+ const assetAmount = parseUnits(opts.amount, decimals);
711
+ const agent = opts.agent || resolved?.veniceAgent;
712
+ if (!agent) {
713
+ throw new Error(
714
+ "venice-inference: missing agent \u2014 pass --agent or resolve chain inputs (signer default) before encoding"
715
+ );
716
+ }
717
+ const isSingleHop = !!opts.singleHop;
718
+ let minVVV = 0n;
719
+ if (!isDirect) {
720
+ if (opts.minVvv) {
721
+ minVVV = parseUnits(opts.minVvv, 18);
722
+ } else if (resolved?.veniceMinVVV !== void 0) {
723
+ minVVV = resolved.veniceMinVVV;
724
+ } else {
725
+ throw new Error(
726
+ "venice-inference: missing resolved minVVV quote \u2014 pass --min-vvv or resolve chain inputs before encoding"
727
+ );
728
+ }
729
+ }
730
+ const params = {
731
+ asset,
732
+ weth: isDirect ? ZERO : TOKENS().WETH,
733
+ vvv,
734
+ sVVV: VENICE().STAKING,
735
+ aeroRouter: isDirect ? ZERO : AERODROME().ROUTER,
736
+ aeroFactory: isDirect ? ZERO : AERODROME().FACTORY,
737
+ agent,
738
+ assetAmount,
739
+ minVVV,
740
+ deadlineOffset: 300n,
741
+ singleHop: isSingleHop
742
+ };
743
+ return {
744
+ initData: buildInitData2(params),
745
+ asset,
746
+ assetAmount
747
+ };
748
+ }
749
+ if (templateKey === "aerodrome-lp") {
750
+ for (const flag of ["tokenA", "tokenB", "amountA", "amountB", "lpToken"]) {
751
+ if (!opts[flag]) {
752
+ console.error(chalk.red(`--${flag.replace(/([A-Z])/g, "-$1").toLowerCase()} is required for aerodrome-lp template`));
753
+ process.exit(1);
754
+ }
755
+ }
756
+ const tokenA = opts.tokenA;
757
+ const tokenB = opts.tokenB;
758
+ if (!resolved?.aerodromeDecimals) {
759
+ throw new Error(
760
+ "aerodrome-lp: missing resolved tokenA/tokenB decimals \u2014 resolve chain inputs before encoding"
761
+ );
762
+ }
763
+ const { decimalsA, decimalsB } = resolved.aerodromeDecimals;
764
+ const amountA = parseUnits(opts.amountA, decimalsA);
765
+ const amountB = parseUnits(opts.amountB, decimalsB);
766
+ const minAOut = parseUnits(opts.minAOut || "0", decimalsA);
767
+ const minBOut = parseUnits(opts.minBOut || "0", decimalsB);
768
+ const params = {
769
+ tokenA,
770
+ tokenB,
771
+ stable: !!opts.stable,
772
+ factory: AERODROME().FACTORY,
773
+ router: AERODROME().ROUTER,
774
+ gauge: opts.gauge || ZERO,
775
+ lpToken: opts.lpToken,
776
+ amountADesired: amountA,
777
+ amountBDesired: amountB,
778
+ amountAMin: amountA,
779
+ // use desired as min for now
780
+ amountBMin: amountB,
781
+ minAmountAOut: minAOut,
782
+ minAmountBOut: minBOut
783
+ };
784
+ return {
785
+ initData: buildInitData3(params),
786
+ asset: tokenA,
787
+ assetAmount: amountA,
788
+ extraApprovals: [{ token: tokenB, amount: amountB }]
789
+ };
790
+ }
791
+ if (templateKey === "wsteth-moonwell") {
792
+ const supplyAmount = opts.amount ? parseUnits(opts.amount, 18) : 0n;
793
+ const slippageBps = BigInt(opts.slippage || "500");
794
+ const ONE = 10n ** 18n;
795
+ const minWstethOutPerWeth = ONE * (10000n - slippageBps) / 10000n;
796
+ const minWethOutPerWsteth = ONE * (10000n - slippageBps) / 10000n;
797
+ const params = {
798
+ weth: TOKENS().WETH,
799
+ wsteth: TOKENS().wstETH,
800
+ mwsteth: MOONWELL().mWstETH,
801
+ aeroRouter: AERODROME().ROUTER,
802
+ aeroFactory: AERODROME().FACTORY,
803
+ chainlinkWstethEthFeed: CHAINLINK().WSTETH_ETH_FEED,
804
+ supplyAmount,
805
+ minWstethOutPerWeth,
806
+ minWethOutPerWsteth,
807
+ deadlineOffset: 300n
808
+ };
809
+ return {
810
+ initData: buildInitData4(params),
811
+ asset: TOKENS().WETH,
812
+ assetAmount: supplyAmount
813
+ };
814
+ }
815
+ if (templateKey === "mamo-yield") {
816
+ if (!opts.amount) {
817
+ console.error(chalk.red("--amount is required for mamo-yield template"));
818
+ process.exit(1);
819
+ }
820
+ if (!opts.mamoFactory) {
821
+ console.error(chalk.red("--mamo-factory is required for mamo-yield template"));
822
+ process.exit(1);
823
+ }
824
+ const token = opts.token || "USDC";
825
+ const underlying = resolveToken(token);
826
+ const decimals = assetDecimalsForSymbol(token);
827
+ const amount = parseUnits(opts.amount, decimals);
828
+ const minRedeemAmount = parseUnits(opts.minRedeem || opts.amount, decimals);
829
+ return {
830
+ initData: buildInitData5(underlying, opts.mamoFactory, minRedeemAmount),
831
+ asset: underlying,
832
+ assetAmount: amount
833
+ };
834
+ }
835
+ if (templateKey === "portfolio") {
836
+ let robinhoodDefaultRoute2 = function(token, symbol) {
837
+ if (network !== "robinhood") return null;
838
+ if (wethAddr !== ZERO && token.toLowerCase() === wethAddr.toLowerCase()) {
839
+ return { extraData: v3SingleHopExtraData(500), routeDesc: "v3 direct (fee 500)" };
840
+ }
841
+ const r = ROBINHOOD_STOCK_ROUTES[symbol.toUpperCase()];
842
+ if (r) {
843
+ return {
844
+ extraData: v4PathExtraData([
845
+ { currency: ZERO, fee: r.nativeFee, tickSpacing: r.nativeTickSpacing },
846
+ { currency: token, fee: r.stockFee, tickSpacing: r.stockTickSpacing }
847
+ ]),
848
+ routeDesc: `v4 multi-hop (USDG\u2192ETH fee ${r.nativeFee} / ts ${r.nativeTickSpacing} \u2192 ${symbol.toUpperCase()} fee ${r.stockFee} / ts ${r.stockTickSpacing})`
849
+ };
850
+ }
851
+ return null;
852
+ };
853
+ var robinhoodDefaultRoute = robinhoodDefaultRoute2;
854
+ if (!opts.amount) {
855
+ console.error(chalk.red("--amount is required for portfolio template"));
856
+ process.exit(1);
857
+ }
858
+ if (!opts.tokens || !opts.weights) {
859
+ console.error(chalk.red("--tokens and --weights are required for portfolio template"));
860
+ console.error(chalk.dim(" --tokens: comma-separated token addresses or symbols"));
861
+ console.error(chalk.dim(" --weights: comma-separated bps (must sum to 10000)"));
862
+ process.exit(1);
863
+ }
864
+ const network = getNetwork();
865
+ const tokens = TOKENS();
866
+ const assetSymbol = opts.asset || defaultPortfolioAsset();
867
+ const asset = resolveToken(assetSymbol);
868
+ const decimals = assetDecimalsForSymbol(assetSymbol);
869
+ const totalAmount = parseUnits(opts.amount, decimals);
870
+ const maxSlippageBps = Number(opts.maxSlippage || "500");
871
+ const feeTier = opts.feeTier || "3000";
872
+ const tokenSpecs = opts.tokens.split(",").map((t) => t.trim());
873
+ const tokenAddrs = tokenSpecs.map((trimmed) => {
874
+ if (isAddress(trimmed)) return trimmed;
875
+ const allTokens = tokens;
876
+ const resolvedAddr = allTokens[trimmed.toUpperCase()];
877
+ if (resolvedAddr && resolvedAddr !== ZERO) return resolvedAddr;
878
+ console.error(chalk.red(`Unknown token: ${trimmed}`));
879
+ process.exit(1);
880
+ });
881
+ const weightsBps = opts.weights.split(",").map((w) => Number(w.trim()));
882
+ if (tokenAddrs.length !== weightsBps.length) {
883
+ console.error(chalk.red("--tokens and --weights must have same length"));
884
+ process.exit(1);
885
+ }
886
+ if (weightsBps.reduce((a, b) => a + b, 0) !== 1e4) {
887
+ console.error(chalk.red(`Weights must sum to 10000`));
888
+ process.exit(1);
889
+ }
890
+ const swapAdapter = opts.swapAdapter || resolveSwapAdapter();
891
+ const chainlinkVerifier = CHAINLINK().VERIFIER_PROXY;
892
+ const pushMode = chainlinkVerifier === ZERO;
893
+ const chainlink = CHAINLINK();
894
+ const feedIds = parseAlignedOverrides(opts.feedIds, tokenAddrs.length);
895
+ const feedIdOverrides = feedIds.values;
896
+ if (feedIds.mismatch) {
897
+ console.error(chalk.red("--feed-ids must have the same length as --tokens"));
898
+ process.exit(1);
899
+ }
900
+ const priceDecimals = parseAlignedOverrides(opts.priceDecimals, tokenAddrs.length);
901
+ const priceDecimalOverrides = priceDecimals.values;
902
+ if (priceDecimals.mismatch) {
903
+ console.error(chalk.red("--price-decimals must have the same length as --tokens"));
904
+ process.exit(1);
905
+ }
906
+ const swapRoutes = parseAlignedOverrides(opts.swapRoutes, tokenAddrs.length);
907
+ const swapRouteOverrides = swapRoutes.values;
908
+ if (swapRoutes.mismatch) {
909
+ console.error(chalk.red("--swap-routes must have the same length as --tokens"));
910
+ process.exit(1);
911
+ }
912
+ const maxPriceAges = parseAlignedOverrides(opts.maxPriceAges, tokenAddrs.length);
913
+ const maxPriceAgeOverrides = maxPriceAges.values;
914
+ if (maxPriceAges.mismatch) {
915
+ console.error(chalk.red("--max-price-ages must have the same length as --tokens"));
916
+ process.exit(1);
917
+ }
918
+ const wethAddr = TOKENS().WETH;
919
+ console.log(chalk.dim(" Detecting swap routes..."));
920
+ const allocations = [];
921
+ for (let i = 0; i < tokenAddrs.length; i++) {
922
+ const token = tokenAddrs[i];
923
+ let route = null;
924
+ const override = swapRouteOverrides[i];
925
+ if (override) {
926
+ try {
927
+ route = { extraData: parseSwapRouteSpec(override, token), routeDesc: `explicit '${override}'` };
928
+ } catch (e) {
929
+ console.error(chalk.red(`Bad --swap-routes entry for ${tokenSpecs[i]}: ${e.message}`));
930
+ process.exit(1);
931
+ }
932
+ }
933
+ if (!route) route = robinhoodDefaultRoute2(token, tokenSpecs[i]);
934
+ if (!route && network === "robinhood") {
935
+ console.error(
936
+ chalk.red(
937
+ `No verified default swap route for ${tokenSpecs[i]} on robinhood mainnet.`
938
+ )
939
+ );
940
+ console.error(
941
+ chalk.yellow(
942
+ ` Pass --swap-routes to set it explicitly for this token, e.g.
943
+ --swap-routes 'v4path:eth@500:10+self@50000:1000' (USDG\u2192ETH\u2192${tokenSpecs[i].toUpperCase()})`
944
+ )
945
+ );
946
+ process.exit(1);
947
+ }
948
+ if (!route) route = await detectSwapRoute(asset, token, Number(feeTier));
949
+ if (!route) {
950
+ console.error(chalk.red(`No swap route found for ${token}. No Uniswap V3 pool (direct or via WETH). Pass --swap-routes to set it explicitly.`));
951
+ process.exit(1);
952
+ }
953
+ console.log(chalk.dim(` ${token.slice(0, 10)}... \u2192 ${route.routeDesc}`));
954
+ let feedId = feedIdOverrides[i];
955
+ let priceDecimals2 = priceDecimalOverrides[i] ? Number(priceDecimalOverrides[i]) : pushMode ? 8 : 18;
956
+ const sym = tokenSpecs[i].toUpperCase();
957
+ let maxPriceAge = 0;
958
+ if (maxPriceAgeOverrides[i]) {
959
+ maxPriceAge = Number(maxPriceAgeOverrides[i]);
960
+ if (!Number.isInteger(maxPriceAge) || maxPriceAge < 0) {
961
+ console.error(chalk.red(`Bad --max-price-ages entry for ${tokenSpecs[i]}: '${maxPriceAgeOverrides[i]}' (expected a non-negative integer count of seconds)`));
962
+ process.exit(1);
963
+ }
964
+ } else if (pushMode && network === "robinhood") {
965
+ const { maxPriceAge: age, unknownAddress } = robinhoodEquityMaxAge(
966
+ tokenSpecs[i],
967
+ tokens,
968
+ EQUITY_MAX_PRICE_AGE_SECONDS
969
+ );
970
+ maxPriceAge = age;
971
+ if (unknownAddress && feedIdOverrides[i]) {
972
+ console.warn(
973
+ chalk.yellow(
974
+ ` Warning: token ${tokenSpecs[i]} is not in the ${network} registry, so its push feed uses the contract's 26h default max-price-age.
975
+ If this is a tokenized-equity feed, pass --max-price-ages (e.g. ${EQUITY_MAX_PRICE_AGE_SECONDS}) for this slot or it will trip StalePrice over long weekends.`
976
+ )
977
+ );
978
+ }
979
+ }
980
+ if (pushMode && !feedId) {
981
+ const feedKey = sym === "WETH" || sym === "ETH" ? "ETH_USD_FEED" : `${sym}_USD_FEED`;
982
+ const feed = isAddress(tokenSpecs[i]) ? void 0 : chainlink[feedKey];
983
+ if (!feed || feed === ZERO) {
984
+ console.error(chalk.red(`No Chainlink push feed for ${tokenSpecs[i]} on ${network}. Pass --feed-ids <feedAddr,...> to supply AggregatorV3 addresses.`));
985
+ process.exit(1);
986
+ }
987
+ feedId = pushFeedId(feed, maxPriceAge);
988
+ } else if (pushMode && feedId && isAddress(feedId)) {
989
+ feedId = pushFeedId(feedId, maxPriceAge);
990
+ }
991
+ if (!feedId || feedId === ZERO_BYTES32) {
992
+ console.error(chalk.red(`Missing Chainlink feedId for allocation ${i} (${tokenSpecs[i]}). The strategy requires a non-zero feedId per token \u2014 pass --feed-ids as a comma-separated list.`));
993
+ process.exit(1);
994
+ }
995
+ allocations.push({
996
+ token,
997
+ weightBps: weightsBps[i],
998
+ swapExtraData: route.extraData,
999
+ priceDecimals: priceDecimals2,
1000
+ feedId
1001
+ });
1002
+ }
1003
+ return {
1004
+ initData: buildInitData6(asset, swapAdapter, chainlinkVerifier, allocations, totalAmount, maxSlippageBps),
1005
+ asset,
1006
+ assetAmount: totalAmount
1007
+ };
1008
+ }
1009
+ if (templateKey === "hyperliquid-perp") {
1010
+ const token = opts.token || "USDC";
1011
+ const asset = resolveToken(token);
1012
+ const decimals = assetDecimalsForSymbol(token);
1013
+ const depositAmount = opts.amount ? parseUnits(opts.amount, decimals) : 0n;
1014
+ const leverage = Number(opts.leverage || "10");
1015
+ const assetIndex = Number(opts.assetIndex || "0");
1016
+ const maxPosition = parseUnits(opts.maxPosition || "100000", decimals);
1017
+ const maxTradesDay = Number(opts.maxTradesPerDay || "50");
1018
+ return {
1019
+ initData: buildInitData7(asset, depositAmount, assetIndex, leverage, maxPosition, maxTradesDay),
1020
+ asset,
1021
+ assetAmount: depositAmount
1022
+ };
1023
+ }
1024
+ if (templateKey === "hyperliquid-grid") {
1025
+ const token = opts.token || "USDC";
1026
+ const asset = resolveToken(token);
1027
+ const decimals = assetDecimalsForSymbol(token);
1028
+ const depositAmount = opts.amount ? parseUnits(opts.amount, decimals) : 0n;
1029
+ const leverage = Number(opts.leverage || "5");
1030
+ const maxOrderSize = parseUnits(opts.maxOrderSize || "10000", decimals);
1031
+ const maxOrdersPerTick = Number(opts.maxOrdersPerTick || "20");
1032
+ const assetIndices = (opts.assetIndices || "0").split(",").map((s) => Number(s.trim())).filter((n) => !Number.isNaN(n));
1033
+ return {
1034
+ initData: buildInitData8(asset, depositAmount, leverage, maxOrderSize, maxOrdersPerTick, assetIndices),
1035
+ asset,
1036
+ assetAmount: depositAmount
1037
+ };
1038
+ }
1039
+ throw new Error(`No init builder for template: ${templateKey}`);
1040
+ }
1041
+ function buildCallsForTemplate(templateKey, clone, asset, assetAmount, extraApprovals) {
1042
+ if (templateKey === "moonwell-supply") {
1043
+ return {
1044
+ executeCalls: buildExecuteCalls(clone, asset, assetAmount),
1045
+ settleCalls: buildSettleCalls(clone)
1046
+ };
1047
+ }
1048
+ if (templateKey === "venice-inference") {
1049
+ return {
1050
+ executeCalls: buildExecuteCalls2(clone, asset, assetAmount),
1051
+ settleCalls: buildSettleCalls2(clone)
1052
+ };
1053
+ }
1054
+ if (templateKey === "aerodrome-lp") {
1055
+ const tokenB = extraApprovals?.[0]?.token ?? ZERO;
1056
+ const amountB = extraApprovals?.[0]?.amount ?? 0n;
1057
+ return {
1058
+ executeCalls: buildExecuteCalls3(clone, asset, assetAmount, tokenB, amountB),
1059
+ settleCalls: buildSettleCalls3(clone)
1060
+ };
1061
+ }
1062
+ if (templateKey === "wsteth-moonwell") {
1063
+ return {
1064
+ executeCalls: buildExecuteCalls4(clone, asset, assetAmount),
1065
+ settleCalls: buildSettleCalls4(clone)
1066
+ };
1067
+ }
1068
+ if (templateKey === "mamo-yield") {
1069
+ return {
1070
+ executeCalls: buildExecuteCalls5(clone, asset, assetAmount),
1071
+ settleCalls: buildSettleCalls5(clone)
1072
+ };
1073
+ }
1074
+ if (templateKey === "portfolio") {
1075
+ return {
1076
+ executeCalls: buildExecuteCalls6(clone, asset, assetAmount),
1077
+ settleCalls: buildSettleCalls6(clone)
1078
+ };
1079
+ }
1080
+ if (templateKey === "hyperliquid-perp") {
1081
+ return {
1082
+ executeCalls: buildExecuteCalls7(clone, asset, assetAmount),
1083
+ settleCalls: buildSettleCalls7(clone)
1084
+ };
1085
+ }
1086
+ if (templateKey === "hyperliquid-grid") {
1087
+ return {
1088
+ executeCalls: buildExecuteCalls8(clone, asset, assetAmount),
1089
+ settleCalls: buildSettleCalls8(clone)
1090
+ };
1091
+ }
1092
+ throw new Error(`No call builder for template: ${templateKey}`);
1093
+ }
1094
+ function resolveSwapAdapter() {
1095
+ const network = getNetwork();
1096
+ if (network === "robinhood-testnet" && SYNTHRA().ROUTER === ZERO) {
1097
+ console.error(chalk.red("Synthra DEX not available"));
1098
+ process.exit(1);
1099
+ }
1100
+ const adapterAddr = UNISWAP().SWAP_ADAPTER;
1101
+ if (adapterAddr !== ZERO) return adapterAddr;
1102
+ console.error(chalk.red("UniswapSwapAdapter not deployed yet. Use --swap-adapter to specify manually."));
1103
+ process.exit(1);
1104
+ }
1105
+ function resolveToken(symbolOrAddress) {
1106
+ if (isAddress(symbolOrAddress)) return symbolOrAddress;
1107
+ const upper = symbolOrAddress.toUpperCase();
1108
+ const tokenMap = {
1109
+ ...TOKENS(),
1110
+ VVV: VENICE().VVV
1111
+ };
1112
+ const addr = tokenMap[upper];
1113
+ if (!addr || addr === ZERO) {
1114
+ console.error(chalk.red(`Unknown token: ${symbolOrAddress}`));
1115
+ process.exit(1);
1116
+ }
1117
+ return addr;
1118
+ }
1119
+ function defaultPortfolioAsset() {
1120
+ const network = getNetwork();
1121
+ if (network === "robinhood-testnet") return "WETH";
1122
+ return "USDC";
1123
+ }
1124
+ function assetDecimalsForSymbol(symbol) {
1125
+ const upper = symbol.toUpperCase();
1126
+ return upper === "USDC" || upper === "USDG" ? 6 : 18;
1127
+ }
1128
+ function resolveMToken(tokenSymbol) {
1129
+ const upper = tokenSymbol.toUpperCase();
1130
+ const moonwell = MOONWELL();
1131
+ const mTokenMap = {
1132
+ USDC: moonwell.mUSDC,
1133
+ WETH: moonwell.mWETH
1134
+ };
1135
+ const addr = mTokenMap[upper];
1136
+ if (!addr || addr === ZERO) {
1137
+ console.error(chalk.red(`No Moonwell market for: ${tokenSymbol}`));
1138
+ process.exit(1);
1139
+ }
1140
+ return addr;
1141
+ }
1142
+
1143
+ // src/lib/swap-router.ts
1144
+ var DEFAULT_FEE_TIER = 3e3;
1145
+ var ZERO2 = "0x0000000000000000000000000000000000000000";
1146
+ async function detectRoute(tokenIn, tokenOut, preferredFeeTier = DEFAULT_FEE_TIER) {
1147
+ const detected = await detectSwapRoute(tokenIn, tokenOut, preferredFeeTier);
1148
+ if (!detected) {
1149
+ throw new Error(`No swap route found for ${tokenIn}\u2192${tokenOut} (fee ${preferredFeeTier})`);
1150
+ }
1151
+ return {
1152
+ kind: "v3-direct",
1153
+ tokenIn,
1154
+ tokenOut,
1155
+ feeTier: preferredFeeTier,
1156
+ routeDesc: detected.routeDesc
1157
+ };
1158
+ }
1159
+ function quoterAddress() {
1160
+ const quoter = UNISWAP().QUOTER_V2;
1161
+ if (quoter === ZERO2) {
1162
+ throw new Error("QuoterV2 not deployed on this network");
1163
+ }
1164
+ return quoter;
1165
+ }
1166
+ async function quote(params, deps = {}) {
1167
+ const route = await detectRoute(params.tokenIn, params.tokenOut, params.feeTier);
1168
+ if (route.kind === "v3-hop") {
1169
+ const path = encodeSwapPath(
1170
+ [route.tokenIn, route.via, route.tokenOut],
1171
+ [route.feeIn, route.feeOut]
1172
+ );
1173
+ const result2 = await getMultiHopQuote({ path, amountIn: params.amountIn }, deps);
1174
+ return { route, ...result2 };
1175
+ }
1176
+ const result = await getQuote(
1177
+ {
1178
+ tokenIn: route.tokenIn,
1179
+ tokenOut: route.tokenOut,
1180
+ amountIn: params.amountIn,
1181
+ fee: route.feeTier
1182
+ },
1183
+ deps
1184
+ );
1185
+ return { route, ...result };
1186
+ }
1187
+ async function getQuote(params, deps = {}) {
1188
+ const client = deps.client ?? getPublicClient();
1189
+ const calldata = encodeFunctionData9({
1190
+ abi: UNISWAP_QUOTER_V2_ABI,
1191
+ functionName: "quoteExactInputSingle",
1192
+ args: [
1193
+ {
1194
+ tokenIn: params.tokenIn,
1195
+ tokenOut: params.tokenOut,
1196
+ amountIn: params.amountIn,
1197
+ fee: params.fee,
1198
+ sqrtPriceLimitX96: 0n
1199
+ }
1200
+ ]
1201
+ });
1202
+ const { data } = await client.call({ to: quoterAddress(), data: calldata });
1203
+ if (!data) {
1204
+ throw new Error("Quoter returned no data \u2014 pool may not exist for this pair/fee");
1205
+ }
1206
+ const [amountOut, sqrtPriceX96After, , gasEstimate] = decodeFunctionResult({
1207
+ abi: UNISWAP_QUOTER_V2_ABI,
1208
+ functionName: "quoteExactInputSingle",
1209
+ data
1210
+ });
1211
+ return { amountOut, sqrtPriceX96After, gasEstimate };
1212
+ }
1213
+ async function getMultiHopQuote(params, deps = {}) {
1214
+ const client = deps.client ?? getPublicClient();
1215
+ const calldata = encodeFunctionData9({
1216
+ abi: UNISWAP_QUOTER_V2_ABI,
1217
+ functionName: "quoteExactInput",
1218
+ args: [params.path, params.amountIn]
1219
+ });
1220
+ const { data } = await client.call({ to: quoterAddress(), data: calldata });
1221
+ if (!data) {
1222
+ throw new Error("Quoter returned no data \u2014 pool may not exist for this path");
1223
+ }
1224
+ const [amountOut, , , gasEstimate] = decodeFunctionResult({
1225
+ abi: UNISWAP_QUOTER_V2_ABI,
1226
+ functionName: "quoteExactInput",
1227
+ data
1228
+ });
1229
+ return { amountOut, sqrtPriceX96After: 0n, gasEstimate };
1230
+ }
1231
+ function applySlippage(amountOut, slippageBps) {
1232
+ return amountOut * BigInt(1e4 - slippageBps) / 10000n;
1233
+ }
1234
+ function encodeSwapPath(tokens, fees) {
1235
+ if (tokens.length < 2 || fees.length !== tokens.length - 1) {
1236
+ throw new Error("Invalid path: need at least 2 tokens and (tokens-1) fees");
1237
+ }
1238
+ return encodeV3Path(tokens, fees);
1239
+ }
1240
+
1241
+ export {
1242
+ computeProposalAssetChecks,
1243
+ buildInitDataForTemplate,
1244
+ buildCallsForTemplate,
1245
+ resolveToken,
1246
+ assetDecimalsForSymbol,
1247
+ quote,
1248
+ getQuote,
1249
+ getMultiHopQuote,
1250
+ applySlippage,
1251
+ encodeSwapPath
1252
+ };
1253
+ //# sourceMappingURL=chunk-4LKU7ASB.js.map