@sherwoodagent/cli 0.47.1 → 0.51.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/index.js CHANGED
@@ -1,8 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  HyperliquidProvider,
4
- getLatestSignals
5
- } from "./chunk-R2P4C2I7.js";
4
+ getLatestSignals,
5
+ hlCancelAllOrders,
6
+ hlGetMeta,
7
+ hlPlaceLimitOrder,
8
+ resolveHLCoin
9
+ } from "./chunk-OMW47WOO.js";
6
10
  import {
7
11
  UniswapProvider,
8
12
  applySlippage,
@@ -164,8 +168,8 @@ import {
164
168
  import { config as loadDotenv } from "dotenv";
165
169
  import { createRequire } from "module";
166
170
  import { Command, Option } from "commander";
167
- import { parseUnits as parseUnits6, formatUnits as formatUnits5, isAddress as isAddress6 } from "viem";
168
- import chalk13 from "chalk";
171
+ import { parseUnits as parseUnits7, formatUnits as formatUnits5, isAddress as isAddress6 } from "viem";
172
+ import chalk15 from "chalk";
169
173
  import ora8 from "ora";
170
174
  import { input, confirm, select } from "@inquirer/prompts";
171
175
 
@@ -2350,11 +2354,11 @@ ${opts.prompt}`;
2350
2354
  }
2351
2355
  try {
2352
2356
  const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-PEEWGSAO.js");
2353
- const { keccak256, toHex, isAddress: isAddr } = await import("viem");
2357
+ const { keccak256: keccak2562, toHex, isAddress: isAddr } = await import("viem");
2354
2358
  const { getChainContracts: getChainContracts2 } = await import("./config-REASKDIK.js");
2355
2359
  const { getChain: getActiveChain } = await import("./network-3ZU7UBDU.js");
2356
2360
  const vaultRecipient = opts.vault && isAddr(opts.vault) ? opts.vault : getChainContracts2(getActiveChain().id).vault;
2357
- const promptHash = keccak256(toHex(userContent)).slice(0, 18);
2361
+ const promptHash = keccak2562(toHex(userContent)).slice(0, 18);
2358
2362
  const { uid } = await createVeniceInferenceAttestation(
2359
2363
  result.model,
2360
2364
  result.usage.promptTokens,
@@ -4618,13 +4622,13 @@ function registerGuardianCommands(program2) {
4618
4622
  }
4619
4623
 
4620
4624
  // src/commands/grid.ts
4621
- import chalk12 from "chalk";
4625
+ import chalk14 from "chalk";
4622
4626
 
4623
4627
  // src/grid/loop.ts
4624
- import chalk11 from "chalk";
4625
- import { appendFile, mkdir as mkdir3 } from "fs/promises";
4626
- import { join as join3 } from "path";
4627
- import { homedir as homedir3 } from "os";
4628
+ import chalk13 from "chalk";
4629
+ import { appendFile, mkdir as mkdir4 } from "fs/promises";
4630
+ import { join as join4 } from "path";
4631
+ import { homedir as homedir4 } from "os";
4628
4632
 
4629
4633
  // src/grid/manager.ts
4630
4634
  import chalk9 from "chalk";
@@ -4964,6 +4968,45 @@ var GridManager = class {
4964
4968
  };
4965
4969
  }).filter((e) => e.fillCount > 0);
4966
4970
  }
4971
+ /**
4972
+ * Compute the orders that should be placed for the current grid state,
4973
+ * without simulating fills. Used by the live executor.
4974
+ *
4975
+ * Returns:
4976
+ * - ordersToPlace: all current grid levels that haven't been filled
4977
+ * - assetsToCancel: tokens whose grid was rebalanced (need cancel-and-place)
4978
+ * - needsRebalance: whether any grid was rebuilt this tick
4979
+ */
4980
+ computeOrders(prices) {
4981
+ const state = this.portfolio.getState();
4982
+ if (!state || state.paused || !this.config.enabled) {
4983
+ return { ordersToPlace: [], assetsToCancel: [], needsRebalance: false };
4984
+ }
4985
+ const ordersToPlace = [];
4986
+ const assetsToCancel = [];
4987
+ let needsRebalance = false;
4988
+ for (const grid of state.grids) {
4989
+ const price = prices[grid.token];
4990
+ if (!price || price <= 0) continue;
4991
+ const wasEmpty = grid.levels.length === 0;
4992
+ const fullRebuild = wasEmpty || this.needsFullRebuild(grid);
4993
+ const shift = !fullRebuild && grid.centerPrice > 0 && this.needsShift(grid, price);
4994
+ if (fullRebuild || shift) {
4995
+ needsRebalance = true;
4996
+ if (!wasEmpty) assetsToCancel.push(grid.token);
4997
+ }
4998
+ for (const level of grid.levels) {
4999
+ if (level.filled) continue;
5000
+ ordersToPlace.push({
5001
+ token: grid.token,
5002
+ isBuy: level.side === "buy",
5003
+ price: level.price,
5004
+ quantity: level.quantity
5005
+ });
5006
+ }
5007
+ }
5008
+ return { ordersToPlace, assetsToCancel, needsRebalance };
5009
+ }
4967
5010
  /** Get aggregate stats for display. */
4968
5011
  getStats() {
4969
5012
  const state = this.portfolio.getState();
@@ -5033,8 +5076,8 @@ var GridHedgeManager = class {
5033
5076
  await mkdir2(dirname2(HEDGE_STATE_PATH), { recursive: true });
5034
5077
  const tmp = `${HEDGE_STATE_PATH}.tmp.${process.pid}`;
5035
5078
  await writeFile2(tmp, JSON.stringify(this.state, null, 2), "utf-8");
5036
- const { rename: rename2 } = await import("fs/promises");
5037
- await rename2(tmp, HEDGE_STATE_PATH);
5079
+ const { rename: rename3 } = await import("fs/promises");
5080
+ await rename3(tmp, HEDGE_STATE_PATH);
5038
5081
  }
5039
5082
  /**
5040
5083
  * Run one hedge tick. Call after grid tick with current prices and open fill data.
@@ -5152,14 +5195,330 @@ var GridHedgeManager = class {
5152
5195
  }
5153
5196
  };
5154
5197
 
5198
+ // src/grid/executor.ts
5199
+ import chalk11 from "chalk";
5200
+ var GridExecutor = class {
5201
+ cfg;
5202
+ constructor(cfg) {
5203
+ this.cfg = cfg;
5204
+ }
5205
+ /**
5206
+ * Execute the order plan against Hyperliquid.
5207
+ * Cancels stale orders for rebalanced tokens, then places new orders.
5208
+ */
5209
+ async execute(plan) {
5210
+ const errors = [];
5211
+ let cancelled = 0;
5212
+ let placed = 0;
5213
+ for (const token of plan.assetsToCancel) {
5214
+ const coin = resolveHLCoin(token);
5215
+ if (!coin) {
5216
+ errors.push(`No HL ticker for ${token}`);
5217
+ continue;
5218
+ }
5219
+ try {
5220
+ await hlCancelAllOrders(coin);
5221
+ cancelled++;
5222
+ console.error(chalk11.dim(` [grid-exec] Cancelled all orders for ${coin}`));
5223
+ } catch (e) {
5224
+ errors.push(`Cancel ${coin} failed: ${e.message}`);
5225
+ }
5226
+ }
5227
+ for (const order of plan.ordersToPlace) {
5228
+ const coin = resolveHLCoin(order.token);
5229
+ if (!coin) {
5230
+ errors.push(`No HL ticker for ${order.token}`);
5231
+ continue;
5232
+ }
5233
+ try {
5234
+ const res = await hlPlaceLimitOrder(coin, order.isBuy, order.quantity, order.price);
5235
+ if (res.success) {
5236
+ placed++;
5237
+ } else {
5238
+ errors.push(`Place ${coin} ${order.isBuy ? "buy" : "sell"} @${order.price}: ${res.error}`);
5239
+ }
5240
+ } catch (e) {
5241
+ errors.push(`Place ${coin} threw: ${e.message}`);
5242
+ }
5243
+ }
5244
+ return { placed, cancelled, errors };
5245
+ }
5246
+ };
5247
+
5248
+ // src/grid/onchain-executor.ts
5249
+ import chalk12 from "chalk";
5250
+ import { mkdir as mkdir3, readFile as readFile3, rename as rename2, writeFile as writeFile3 } from "fs/promises";
5251
+ import { dirname as dirname3, join as join3 } from "path";
5252
+ import { homedir as homedir3 } from "os";
5253
+ import { encodeAbiParameters as encodeAbiParameters10, parseUnits as parseUnits6 } from "viem";
5254
+
5255
+ // src/grid/cloid.ts
5256
+ import { keccak256, encodeAbiParameters as encodeAbiParameters9 } from "viem";
5257
+ function gridCloid(strategy2, assetIndex, isBuy, levelIndex, nonce) {
5258
+ const hash = keccak256(
5259
+ encodeAbiParameters9(
5260
+ [
5261
+ { type: "address" },
5262
+ { type: "uint32" },
5263
+ { type: "bool" },
5264
+ { type: "uint32" },
5265
+ { type: "uint32" }
5266
+ ],
5267
+ [strategy2, assetIndex, isBuy, levelIndex, nonce]
5268
+ )
5269
+ );
5270
+ const top16 = hash.slice(0, 2 + 32);
5271
+ return BigInt(top16);
5272
+ }
5273
+
5274
+ // src/grid/strategy-abi.ts
5275
+ var HYPERLIQUID_GRID_STRATEGY_ABI = [
5276
+ {
5277
+ type: "function",
5278
+ name: "updateParams",
5279
+ inputs: [{ name: "data", type: "bytes" }],
5280
+ outputs: [],
5281
+ stateMutability: "nonpayable"
5282
+ }
5283
+ ];
5284
+
5285
+ // src/grid/onchain-executor.ts
5286
+ var ONCHAIN_STATE_PATH = join3(homedir3(), ".sherwood", "grid", "onchain-state.json");
5287
+ var UINT64_MAX = 18446744073709551615n;
5288
+ var ACTION_PLACE_GRID = 1;
5289
+ var ACTION_CANCEL_ALL = 2;
5290
+ var ACTION_CANCEL_AND_PLACE = 3;
5291
+ var GRID_ORDER_COMPONENTS = [
5292
+ { name: "assetIndex", type: "uint32" },
5293
+ { name: "isBuy", type: "bool" },
5294
+ { name: "limitPx", type: "uint64" },
5295
+ { name: "sz", type: "uint64" },
5296
+ { name: "cloid", type: "uint128" }
5297
+ ];
5298
+ var OnchainGridExecutor = class {
5299
+ cfg;
5300
+ nonces = /* @__PURE__ */ new Map();
5301
+ placedCloids = /* @__PURE__ */ new Map();
5302
+ meta = null;
5303
+ busy = false;
5304
+ constructor(cfg) {
5305
+ this.cfg = cfg;
5306
+ }
5307
+ /** Load persisted state. Call once before the first execute(). */
5308
+ async load() {
5309
+ try {
5310
+ const raw = await readFile3(ONCHAIN_STATE_PATH, "utf-8");
5311
+ const state = JSON.parse(raw);
5312
+ for (const [tok, n] of Object.entries(state.nonces)) this.nonces.set(tok, n);
5313
+ for (const [tok, cloids] of Object.entries(state.placedCloids)) {
5314
+ this.placedCloids.set(tok, cloids.map((s) => BigInt(s)));
5315
+ }
5316
+ console.error(chalk12.dim(` [grid-onchain] Loaded state: ${this.nonces.size} tokens`));
5317
+ } catch (e) {
5318
+ const code = e.code;
5319
+ if (code === "ENOENT") {
5320
+ } else {
5321
+ console.error(
5322
+ chalk12.yellow(
5323
+ ` [grid-onchain] Failed to load state (${e.message}) \u2014 starting fresh. Existing on-chain orders may be orphaned.`
5324
+ )
5325
+ );
5326
+ }
5327
+ }
5328
+ if (!this.meta) this.meta = await hlGetMeta();
5329
+ }
5330
+ /**
5331
+ * Atomic save: write to .tmp, then POSIX-rename. A crash mid-write leaves
5332
+ * either the old file intact or the new file fully written — never a
5333
+ * partial JSON that would crash load() on restart.
5334
+ */
5335
+ async save() {
5336
+ const state = {
5337
+ nonces: Object.fromEntries(this.nonces),
5338
+ placedCloids: Object.fromEntries(
5339
+ [...this.placedCloids].map(([tok, cloids]) => [tok, cloids.map((c) => c.toString())])
5340
+ )
5341
+ };
5342
+ await mkdir3(dirname3(ONCHAIN_STATE_PATH), { recursive: true });
5343
+ const tmp = ONCHAIN_STATE_PATH + ".tmp";
5344
+ await writeFile3(tmp, JSON.stringify(state, null, 2));
5345
+ await rename2(tmp, ONCHAIN_STATE_PATH);
5346
+ }
5347
+ /**
5348
+ * Execute the order plan: cancel stale orders for rebalanced tokens, then
5349
+ * place new orders. Each (token) is one tx. Persists state after each tx
5350
+ * so a crash mid-execution still leaves a recoverable on-disk record.
5351
+ *
5352
+ * Concurrency-guarded: a second concurrent call returns immediately rather
5353
+ * than racing tx submission against another in-flight execute().
5354
+ */
5355
+ async execute(plan) {
5356
+ if (this.busy) {
5357
+ return { placed: 0, cancelled: 0, txs: [], errors: ["execute() already in flight \u2014 skipping"] };
5358
+ }
5359
+ this.busy = true;
5360
+ try {
5361
+ if (!this.meta) await this.load();
5362
+ const errors = [];
5363
+ const txs = [];
5364
+ let placed = 0;
5365
+ let cancelled = 0;
5366
+ const ordersByToken = /* @__PURE__ */ new Map();
5367
+ for (const o of plan.ordersToPlace) {
5368
+ if (!ordersByToken.has(o.token)) ordersByToken.set(o.token, []);
5369
+ ordersByToken.get(o.token).push(o);
5370
+ }
5371
+ const cancelSet = new Set(plan.assetsToCancel);
5372
+ const allTokens = /* @__PURE__ */ new Set([...ordersByToken.keys(), ...cancelSet]);
5373
+ for (const token of allTokens) {
5374
+ const assetIndex = this.cfg.assetIndices[token];
5375
+ if (assetIndex === void 0) {
5376
+ errors.push(`No asset index for ${token}`);
5377
+ continue;
5378
+ }
5379
+ const coin = resolveHLCoin(token);
5380
+ if (!coin) {
5381
+ errors.push(`No HL ticker for ${token}`);
5382
+ continue;
5383
+ }
5384
+ const meta = this.meta.get(coin);
5385
+ if (!meta) {
5386
+ errors.push(`No HL meta for ${coin} (run \`sherwood grid status\` to refresh)`);
5387
+ continue;
5388
+ }
5389
+ const wantCancel = cancelSet.has(token);
5390
+ const orders = ordersByToken.get(token) ?? [];
5391
+ const wantPlace = orders.length > 0;
5392
+ try {
5393
+ if (wantCancel && wantPlace) {
5394
+ const tx = await this.cancelAndPlace(token, assetIndex, orders, meta);
5395
+ txs.push(tx);
5396
+ cancelled += 1;
5397
+ placed += orders.length;
5398
+ } else if (wantCancel) {
5399
+ const tx = await this.cancelAll(token, assetIndex);
5400
+ txs.push(tx);
5401
+ cancelled += 1;
5402
+ } else if (wantPlace) {
5403
+ const tx = await this.placeGrid(token, assetIndex, orders, meta);
5404
+ txs.push(tx);
5405
+ placed += orders.length;
5406
+ }
5407
+ await this.save();
5408
+ } catch (e) {
5409
+ errors.push(`${token}: ${e.message}`);
5410
+ }
5411
+ }
5412
+ return { placed, cancelled, txs, errors };
5413
+ } finally {
5414
+ this.busy = false;
5415
+ }
5416
+ }
5417
+ currentNonce(token) {
5418
+ return this.nonces.get(token) ?? 0;
5419
+ }
5420
+ bumpNonce(token) {
5421
+ const next = this.currentNonce(token) + 1;
5422
+ this.nonces.set(token, next);
5423
+ return next;
5424
+ }
5425
+ /**
5426
+ * Pure encoding — does NOT mutate placedCloids. Caller commits CLOIDs
5427
+ * only after the on-chain tx confirms successfully.
5428
+ *
5429
+ * Uses viem's `parseUnits` for decimal scaling instead of float math so
5430
+ * high-szDecimals tokens (BTC=5, ETH=4) keep full precision on small sizes.
5431
+ */
5432
+ encodeOrders(assetIndex, orders, meta, nonce) {
5433
+ const cloids = [];
5434
+ const encoded = orders.map((o, i) => {
5435
+ const cloid = gridCloid(this.cfg.strategyAddress, assetIndex, o.isBuy, i, nonce);
5436
+ cloids.push(cloid);
5437
+ const limitPx = parseUnits6(o.price.toFixed(meta.pxDecimals), meta.pxDecimals);
5438
+ const sz = parseUnits6(o.quantity.toFixed(meta.szDecimals), meta.szDecimals);
5439
+ if (limitPx > UINT64_MAX || sz > UINT64_MAX) {
5440
+ throw new Error(
5441
+ `Order exceeds uint64: token=${o.token} px=${limitPx} sz=${sz}`
5442
+ );
5443
+ }
5444
+ return { assetIndex, isBuy: o.isBuy, limitPx, sz, cloid };
5445
+ });
5446
+ return { encoded, cloids };
5447
+ }
5448
+ async placeGrid(token, assetIndex, orders, meta) {
5449
+ const nonce = this.bumpNonce(token);
5450
+ const { encoded, cloids } = this.encodeOrders(assetIndex, orders, meta, nonce);
5451
+ const data = encodeAbiParameters10(
5452
+ [{ type: "uint8" }, { type: "tuple[]", components: [...GRID_ORDER_COMPONENTS] }],
5453
+ [ACTION_PLACE_GRID, encoded]
5454
+ );
5455
+ const tx = await this.send(data);
5456
+ this.placedCloids.set(token, cloids);
5457
+ return tx;
5458
+ }
5459
+ async cancelAll(token, assetIndex) {
5460
+ const cloids = this.placedCloids.get(token) ?? [];
5461
+ if (cloids.length === 0) {
5462
+ this.bumpNonce(token);
5463
+ return "0x";
5464
+ }
5465
+ const data = encodeAbiParameters10(
5466
+ [{ type: "uint8" }, { type: "uint32" }, { type: "uint128[]" }],
5467
+ [ACTION_CANCEL_ALL, assetIndex, cloids]
5468
+ );
5469
+ const tx = await this.send(data);
5470
+ this.placedCloids.set(token, []);
5471
+ this.bumpNonce(token);
5472
+ return tx;
5473
+ }
5474
+ async cancelAndPlace(token, assetIndex, orders, meta) {
5475
+ const oldCloids = this.placedCloids.get(token) ?? [];
5476
+ const newNonce = this.bumpNonce(token);
5477
+ const { encoded, cloids: newCloids } = this.encodeOrders(assetIndex, orders, meta, newNonce);
5478
+ const data = encodeAbiParameters10(
5479
+ [
5480
+ { type: "uint8" },
5481
+ { type: "uint32" },
5482
+ { type: "uint128[]" },
5483
+ { type: "tuple[]", components: [...GRID_ORDER_COMPONENTS] }
5484
+ ],
5485
+ [ACTION_CANCEL_AND_PLACE, assetIndex, oldCloids, encoded]
5486
+ );
5487
+ const tx = await this.send(data);
5488
+ this.placedCloids.set(token, newCloids);
5489
+ return tx;
5490
+ }
5491
+ /**
5492
+ * Submit and wait for receipt. Throwing here surfaces to the per-token
5493
+ * try/catch in execute(), recording the error and skipping the save() so
5494
+ * placedCloids never reflects orders that didn't land.
5495
+ */
5496
+ async send(data) {
5497
+ const tx = await writeContractWithRetry({
5498
+ address: this.cfg.strategyAddress,
5499
+ abi: HYPERLIQUID_GRID_STRATEGY_ABI,
5500
+ functionName: "updateParams",
5501
+ args: [data]
5502
+ });
5503
+ const pub = getPublicClient();
5504
+ const receipt = await pub.waitForTransactionReceipt({ hash: tx, timeout: 3e4 });
5505
+ if (receipt.status !== "success") {
5506
+ throw new Error(`Tx ${tx} reverted on-chain`);
5507
+ }
5508
+ console.error(chalk12.dim(` [grid-onchain] tx ${tx.slice(0, 10)}... confirmed`));
5509
+ return tx;
5510
+ }
5511
+ };
5512
+
5155
5513
  // src/grid/loop.ts
5156
- var GRID_CYCLES_PATH = join3(homedir3(), ".sherwood", "grid", "cycles.jsonl");
5514
+ var GRID_CYCLES_PATH = join4(homedir4(), ".sherwood", "grid", "cycles.jsonl");
5157
5515
  var GridLoop = class {
5158
5516
  cfg;
5159
5517
  gridConfig;
5160
5518
  manager;
5161
5519
  hedge;
5162
5520
  hl;
5521
+ executor = null;
5163
5522
  running = false;
5164
5523
  cycleCount = 0;
5165
5524
  timer = null;
@@ -5169,12 +5528,25 @@ var GridLoop = class {
5169
5528
  this.manager = new GridManager(this.gridConfig);
5170
5529
  this.hedge = new GridHedgeManager();
5171
5530
  this.hl = new HyperliquidProvider();
5531
+ if (cfg.live) {
5532
+ if (!cfg.assetIndices) {
5533
+ throw new Error("assetIndices required when live=true");
5534
+ }
5535
+ if (cfg.strategyAddress) {
5536
+ this.executor = new OnchainGridExecutor({
5537
+ strategyAddress: cfg.strategyAddress,
5538
+ assetIndices: cfg.assetIndices
5539
+ });
5540
+ } else {
5541
+ this.executor = new GridExecutor({ assetIndices: cfg.assetIndices });
5542
+ }
5543
+ }
5172
5544
  }
5173
5545
  /** Start the grid loop. Resolves when shut down via SIGINT/SIGTERM. */
5174
5546
  async start() {
5175
5547
  this.running = true;
5176
5548
  const shutdown = () => {
5177
- console.error(chalk11.yellow("\n [grid-loop] Shutting down\u2026"));
5549
+ console.error(chalk13.yellow("\n [grid-loop] Shutting down\u2026"));
5178
5550
  this.running = false;
5179
5551
  if (this.timer) {
5180
5552
  clearTimeout(this.timer);
@@ -5184,7 +5556,10 @@ var GridLoop = class {
5184
5556
  process.on("SIGINT", shutdown);
5185
5557
  process.on("SIGTERM", shutdown);
5186
5558
  await this.manager.init(this.cfg.capital);
5187
- console.error(chalk11.cyan(
5559
+ if (this.executor instanceof OnchainGridExecutor) {
5560
+ await this.executor.load();
5561
+ }
5562
+ console.error(chalk13.cyan(
5188
5563
  `
5189
5564
  [grid-loop] Started \u2014 capital=$${this.cfg.capital.toFixed(0)} cycle=${(this.cfg.cycle / 1e3).toFixed(0)}s tokens=[${this.gridConfig.tokens.join(", ")}] leverage=${this.gridConfig.leverage}x levels=${this.gridConfig.levelsPerSide}/side
5190
5565
  `
@@ -5193,7 +5568,7 @@ var GridLoop = class {
5193
5568
  try {
5194
5569
  await this.tick();
5195
5570
  } catch (err) {
5196
- console.error(chalk11.red(` [grid-loop] Tick error: ${err.message}`));
5571
+ console.error(chalk13.red(` [grid-loop] Tick error: ${err.message}`));
5197
5572
  }
5198
5573
  if (this.running) {
5199
5574
  await new Promise((resolve2) => {
@@ -5203,7 +5578,7 @@ var GridLoop = class {
5203
5578
  }
5204
5579
  process.off("SIGINT", shutdown);
5205
5580
  process.off("SIGTERM", shutdown);
5206
- console.error(chalk11.yellow(" [grid-loop] Stopped."));
5581
+ console.error(chalk13.yellow(" [grid-loop] Stopped."));
5207
5582
  }
5208
5583
  /** Execute one grid cycle. */
5209
5584
  async tick() {
@@ -5217,25 +5592,37 @@ var GridLoop = class {
5217
5592
  }
5218
5593
  }
5219
5594
  if (Object.keys(prices).length === 0) {
5220
- console.error(chalk11.dim(` [grid-loop] #${this.cycleCount} \u2014 no prices, skipping`));
5595
+ console.error(chalk13.dim(` [grid-loop] #${this.cycleCount} \u2014 no prices, skipping`));
5221
5596
  return;
5222
5597
  }
5223
5598
  const result = await this.manager.tick(prices);
5224
5599
  const elapsed = Date.now() - start;
5600
+ if (this.executor) {
5601
+ const plan = this.manager.computeOrders(prices);
5602
+ if (plan.ordersToPlace.length > 0 || plan.assetsToCancel.length > 0) {
5603
+ const res = await this.executor.execute(plan);
5604
+ if (res.errors.length > 0) {
5605
+ console.error(chalk13.yellow(` [grid-loop] Executor errors: ${res.errors.join("; ")}`));
5606
+ }
5607
+ if (res.placed > 0 || res.cancelled > 0) {
5608
+ console.error(chalk13.cyan(` [grid-loop] Live: placed=${res.placed} cancelled=${res.cancelled}`));
5609
+ }
5610
+ }
5611
+ }
5225
5612
  if (result.roundTrips > 0) {
5226
- console.error(chalk11.green(
5613
+ console.error(chalk13.green(
5227
5614
  ` [grid-loop] #${this.cycleCount} \u2014 ${result.roundTrips} RT(s), +$${result.pnlUsd.toFixed(2)} PnL, ${result.fills} fill(s) [${elapsed}ms]`
5228
5615
  ));
5229
5616
  }
5230
5617
  if (result.fills > 0 && result.roundTrips === 0) {
5231
- console.error(chalk11.dim(
5618
+ console.error(chalk13.dim(
5232
5619
  ` [grid-loop] #${this.cycleCount} \u2014 ${result.fills} fill(s), 0 RTs [${elapsed}ms]`
5233
5620
  ));
5234
5621
  }
5235
5622
  const openExposure = this.manager.getOpenFillExposure();
5236
5623
  const hedgeResult = await this.hedge.tick(openExposure, prices);
5237
5624
  if (hedgeResult.adjustments > 0) {
5238
- console.error(chalk11.magenta(
5625
+ console.error(chalk13.magenta(
5239
5626
  ` [hedge] ${hedgeResult.adjustments} adjustment(s), unrealized: $${hedgeResult.unrealizedPnl.toFixed(2)}, total realized: $${hedgeResult.totalRealizedPnl.toFixed(2)}`
5240
5627
  ));
5241
5628
  }
@@ -5255,7 +5642,7 @@ var GridLoop = class {
5255
5642
  hedgeTotalRealizedPnl: hedgeResult.totalRealizedPnl
5256
5643
  };
5257
5644
  try {
5258
- await mkdir3(join3(homedir3(), ".sherwood", "grid"), { recursive: true });
5645
+ await mkdir4(join4(homedir4(), ".sherwood", "grid"), { recursive: true });
5259
5646
  await appendFile(GRID_CYCLES_PATH, JSON.stringify(cycleEntry) + "\n");
5260
5647
  } catch {
5261
5648
  }
@@ -5264,7 +5651,7 @@ var GridLoop = class {
5264
5651
  if (stats2) {
5265
5652
  const hedgeStatus = this.hedge.getStatus();
5266
5653
  const hedgeInfo = hedgeStatus && hedgeStatus.positions.length > 0 ? ` hedge=$${hedgeResult.unrealizedPnl.toFixed(2)}unr/$${hedgeStatus.totalRealizedPnl.toFixed(2)}real` : "";
5267
- console.error(chalk11.cyan(
5654
+ console.error(chalk13.cyan(
5268
5655
  ` [grid-loop] Status #${this.cycleCount} \u2014 totalPnL=$${stats2.totalPnlUsd.toFixed(2)} todayPnL=$${stats2.todayPnlUsd.toFixed(2)} RTs=${stats2.totalRoundTrips} alloc=$${stats2.allocation.toFixed(0)}${hedgeInfo}${stats2.paused ? " (PAUSED)" : ""}`
5269
5656
  ));
5270
5657
  }
@@ -5273,19 +5660,36 @@ var GridLoop = class {
5273
5660
  };
5274
5661
 
5275
5662
  // src/commands/grid.ts
5276
- var DIM5 = chalk12.gray;
5277
- var G5 = chalk12.green;
5278
- var BOLD5 = chalk12.white.bold;
5279
- var W5 = chalk12.white;
5663
+ var DIM5 = chalk14.gray;
5664
+ var G5 = chalk14.green;
5665
+ var BOLD5 = chalk14.white.bold;
5666
+ var W5 = chalk14.white;
5280
5667
  var SEP5 = () => console.log(DIM5("\u2500".repeat(60)));
5281
5668
  function registerGridCommand(program2) {
5282
5669
  const grid = program2.command("grid").description("Grid trading strategy \u2014 ATR-based grid on BTC/ETH/SOL");
5283
- grid.command("start").description("Start the grid trading loop").option("--capital <usd>", "Starting capital in USD", "5000").option("--cycle <seconds>", "Cycle interval in seconds", "60").option("--tokens <list>", "Comma-separated token list", "bitcoin,ethereum,solana").option("--leverage <n>", "Leverage multiplier", "5").option("--levels <n>", "Grid levels per side", "15").action(async (opts) => {
5670
+ grid.command("start").description("Start the grid trading loop").option("--capital <usd>", "Starting capital in USD", "5000").option("--cycle <seconds>", "Cycle interval in seconds", "60").option("--tokens <list>", "Comma-separated token list", "bitcoin,ethereum,solana").option("--leverage <n>", "Leverage multiplier", "5").option("--levels <n>", "Grid levels per side", "15").option("--live", "enable live execution (places real orders on Hyperliquid)").option("--asset-indices <pairs>", "comma-separated token=index pairs (e.g. bitcoin=3,ethereum=4,solana=5)").option("--strategy <address>", "on-chain strategy contract address (enables on-chain executor)").action(async (opts) => {
5284
5671
  const capital = parseFloat(opts.capital);
5285
5672
  const cycleMs = parseInt(opts.cycle, 10) * 1e3;
5286
5673
  const tokens = opts.tokens.split(",").map((t) => t.trim());
5287
5674
  const leverage = parseFloat(opts.leverage);
5288
5675
  const levels = parseInt(opts.levels, 10);
5676
+ const live = !!opts.live;
5677
+ let assetIndices;
5678
+ if (live) {
5679
+ if (!opts.assetIndices) {
5680
+ throw new Error("--asset-indices required when --live (e.g. --asset-indices bitcoin=3,ethereum=4,solana=5)");
5681
+ }
5682
+ assetIndices = {};
5683
+ for (const pair of opts.assetIndices.split(",")) {
5684
+ const [tok, idx] = pair.split("=");
5685
+ if (!tok || !idx) throw new Error(`Bad asset-indices pair: ${pair}`);
5686
+ assetIndices[tok.trim()] = Number(idx);
5687
+ }
5688
+ }
5689
+ const strategyAddress = opts.strategy;
5690
+ if (strategyAddress && !live) {
5691
+ throw new Error("--strategy requires --live");
5692
+ }
5289
5693
  const weight = 1 / tokens.length;
5290
5694
  const tokenSplit = {};
5291
5695
  for (const t of tokens) {
@@ -5303,6 +5707,9 @@ function registerGridCommand(program2) {
5303
5707
  const loop = new GridLoop({
5304
5708
  capital,
5305
5709
  cycle: cycleMs,
5710
+ live,
5711
+ assetIndices,
5712
+ strategyAddress,
5306
5713
  config: {
5307
5714
  ...DEFAULT_GRID_CONFIG,
5308
5715
  tokens,
@@ -5326,7 +5733,7 @@ function registerGridCommand(program2) {
5326
5733
  console.log(G5.bold(" Grid Portfolio"));
5327
5734
  SEP5();
5328
5735
  console.log(W5(` Allocation: $${state.totalAllocation.toLocaleString()}`));
5329
- console.log(W5(` Status: ${state.paused ? chalk12.red("PAUSED \u2014 " + state.pauseReason) : G5("Active")}`));
5736
+ console.log(W5(` Status: ${state.paused ? chalk14.red("PAUSED \u2014 " + state.pauseReason) : G5("Active")}`));
5330
5737
  console.log(W5(` Initialized: ${new Date(state.initializedAt).toLocaleString()}`));
5331
5738
  SEP5();
5332
5739
  console.log();
@@ -5339,13 +5746,13 @@ function registerGridCommand(program2) {
5339
5746
  const pnl = `$${g.stats.totalPnlUsd.toFixed(2)}`.padStart(10);
5340
5747
  const todayPnl = `$${g.stats.todayPnlUsd.toFixed(2)}`.padStart(10);
5341
5748
  const fills = String(g.stats.totalFills).padStart(6);
5342
- const pnlColor = g.stats.totalPnlUsd >= 0 ? G5 : chalk12.red;
5343
- const todayColor = g.stats.todayPnlUsd >= 0 ? G5 : chalk12.red;
5749
+ const pnlColor = g.stats.totalPnlUsd >= 0 ? G5 : chalk14.red;
5750
+ const todayColor = g.stats.todayPnlUsd >= 0 ? G5 : chalk14.red;
5344
5751
  console.log(` ${W5(name)} ${alloc} ${rts} ${pnlColor(pnl)} ${todayColor(todayPnl)} ${fills}`);
5345
5752
  }
5346
5753
  console.log(DIM5(" " + "\u2500".repeat(72)));
5347
- const totalPnlColor = agg.totalPnlUsd >= 0 ? G5 : chalk12.red;
5348
- const todayTotalColor = agg.todayPnlUsd >= 0 ? G5 : chalk12.red;
5754
+ const totalPnlColor = agg.totalPnlUsd >= 0 ? G5 : chalk14.red;
5755
+ const todayTotalColor = agg.todayPnlUsd >= 0 ? G5 : chalk14.red;
5349
5756
  console.log(` ${BOLD5("TOTAL".padEnd(13))} ${`$${state.totalAllocation.toFixed(0)}`.padStart(8)} ${String(agg.totalRoundTrips).padStart(6)} ${totalPnlColor(`$${agg.totalPnlUsd.toFixed(2)}`.padStart(10))} ${todayTotalColor(`$${agg.todayPnlUsd.toFixed(2)}`.padStart(10))} ${String(agg.todayFills).padStart(6)}`);
5350
5757
  console.log();
5351
5758
  });
@@ -5364,15 +5771,15 @@ async function loadXmtp() {
5364
5771
  async function loadCron() {
5365
5772
  return import("./cron-EOULYO3R.js");
5366
5773
  }
5367
- var G6 = chalk13.green;
5368
- var W6 = chalk13.white;
5369
- var DIM6 = chalk13.gray;
5370
- var BOLD6 = chalk13.white.bold;
5371
- var LABEL5 = chalk13.green.bold;
5774
+ var G6 = chalk15.green;
5775
+ var W6 = chalk15.white;
5776
+ var DIM6 = chalk15.gray;
5777
+ var BOLD6 = chalk15.white.bold;
5778
+ var LABEL5 = chalk15.green.bold;
5372
5779
  var SEP6 = () => console.log(DIM6("\u2500".repeat(60)));
5373
5780
  function validateAddress(value, name) {
5374
5781
  if (!isAddress6(value)) {
5375
- console.error(chalk13.red(`Invalid ${name} address: ${value}`));
5782
+ console.error(chalk15.red(`Invalid ${name} address: ${value}`));
5376
5783
  process.exit(1);
5377
5784
  }
5378
5785
  return value;
@@ -5392,7 +5799,7 @@ program.name("sherwood").description("CLI for agent-managed investment syndicate
5392
5799
  process.env.ENABLE_TESTNET = "true";
5393
5800
  if (network !== "base") {
5394
5801
  console.warn(
5395
- chalk13.yellow("[warn] --testnet ignored, --chain takes precedence")
5802
+ chalk15.yellow("[warn] --testnet ignored, --chain takes precedence")
5396
5803
  );
5397
5804
  } else {
5398
5805
  network = "base-sepolia";
@@ -5400,7 +5807,7 @@ program.name("sherwood").description("CLI for agent-managed investment syndicate
5400
5807
  }
5401
5808
  setNetwork(network);
5402
5809
  if (getNetwork() !== "base") {
5403
- console.log(chalk13.yellow(`[${getNetwork()}]`));
5810
+ console.log(chalk15.yellow(`[${getNetwork()}]`));
5404
5811
  }
5405
5812
  });
5406
5813
  var syndicate = program.command("syndicate");
@@ -5448,7 +5855,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5448
5855
  asset = opts.asset;
5449
5856
  } else {
5450
5857
  const supported = Object.keys(ASSET_SYMBOLS).join(", ");
5451
- console.error(chalk13.red(` Unknown asset "${opts.asset}". Use a symbol (${supported}) or a 0x address.`));
5858
+ console.error(chalk15.red(` Unknown asset "${opts.asset}". Use a symbol (${supported}) or a 0x address.`));
5452
5859
  process.exit(1);
5453
5860
  }
5454
5861
  } else if (nonInteractive) {
@@ -5478,7 +5885,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5478
5885
  console.log(W6(` Agent ID: #${agentIdStr}`));
5479
5886
  console.log(W6(` Asset: ${assetSymbol} (${asset.slice(0, 10)}...)`));
5480
5887
  console.log(W6(` Share token: ${symbol}`));
5481
- console.log(W6(` Open deposits: ${openDeposits ? G6("yes") : chalk13.red("no (whitelist)")}`));
5888
+ console.log(W6(` Open deposits: ${openDeposits ? G6("yes") : chalk15.red("no (whitelist)")}`));
5482
5889
  SEP6();
5483
5890
  if (!nonInteractive) {
5484
5891
  const go = await confirm({ message: G6("Deploy syndicate?"), default: true });
@@ -5505,7 +5912,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5505
5912
  metadataURI = await uploadMetadata(metadata);
5506
5913
  spinner2.succeed(G6(`Metadata pinned: ${DIM6(metadataURI)}`));
5507
5914
  } catch (err) {
5508
- spinner2.warn(chalk13.yellow(`IPFS upload failed \u2014 using inline metadata`));
5915
+ spinner2.warn(chalk15.yellow(`IPFS upload failed \u2014 using inline metadata`));
5509
5916
  const json = JSON.stringify({ name, description, subdomain, asset: assetSymbol, openDeposits, createdBy: "@sherwoodagent/cli" });
5510
5917
  metadataURI = `data:application/json;base64,${Buffer.from(json).toString("base64")}`;
5511
5918
  }
@@ -5515,12 +5922,12 @@ syndicate.command("create").description("Create a new syndicate via the factory
5515
5922
  const existingInfo = await getSyndicate(existingId);
5516
5923
  const callerAddress = getAccount().address.toLowerCase();
5517
5924
  if (existingInfo.creator.toLowerCase() !== callerAddress) {
5518
- console.error(chalk13.red(`
5925
+ console.error(chalk15.red(`
5519
5926
  \u2716 Subdomain '${subdomain}' is already taken by another syndicate.
5520
5927
  `));
5521
5928
  process.exit(1);
5522
5929
  }
5523
- console.log(chalk13.yellow(`
5930
+ console.log(chalk15.yellow(`
5524
5931
  \u26A0 Syndicate '${subdomain}' already exists \u2014 resuming setup...
5525
5932
  `));
5526
5933
  const spinner2 = ora8({ text: W6("Resuming setup..."), color: "green" }).start();
@@ -5551,7 +5958,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5551
5958
  cacheGroupId(subdomain, groupId);
5552
5959
  }
5553
5960
  } catch {
5554
- console.warn(chalk13.yellow("\n \u26A0 Could not set up XMTP chat group"));
5961
+ console.warn(chalk15.yellow("\n \u26A0 Could not set up XMTP chat group"));
5555
5962
  }
5556
5963
  try {
5557
5964
  const cron = await loadCron();
@@ -5598,7 +6005,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5598
6005
  // agentAddress = creator EOA (direct execution)
5599
6006
  );
5600
6007
  } catch (regErr) {
5601
- console.warn(chalk13.yellow("\n \u26A0 Could not auto-register creator as agent \u2014 register manually with `syndicate add`"));
6008
+ console.warn(chalk15.yellow("\n \u26A0 Could not auto-register creator as agent \u2014 register manually with `syndicate add`"));
5602
6009
  }
5603
6010
  spinner.text = W6("Setting up chat...");
5604
6011
  try {
@@ -5611,8 +6018,8 @@ syndicate.command("create").description("Create a new syndicate via the factory
5611
6018
  } catch {
5612
6019
  }
5613
6020
  } catch {
5614
- console.warn(chalk13.yellow("\n \u26A0 Could not create XMTP chat group"));
5615
- console.warn(chalk13.dim(` Recover later with: sherwood chat ${subdomain} init`));
6021
+ console.warn(chalk15.yellow("\n \u26A0 Could not create XMTP chat group"));
6022
+ console.warn(chalk15.dim(` Recover later with: sherwood chat ${subdomain} init`));
5616
6023
  }
5617
6024
  try {
5618
6025
  const cron = await loadCron();
@@ -5640,7 +6047,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
5640
6047
  console.log(G6(" \u2713 Syndicate saved to ~/.sherwood/config.json (set as primary)"));
5641
6048
  console.log();
5642
6049
  } catch (err) {
5643
- console.error(chalk13.red(`
6050
+ console.error(chalk15.red(`
5644
6051
  \u2716 ${formatContractError(err)}`));
5645
6052
  process.exit(1);
5646
6053
  }
@@ -5690,38 +6097,38 @@ syndicate.command("list").description("List active syndicates (queries subgraph,
5690
6097
  }
5691
6098
  spinner.stop();
5692
6099
  if (syndicates.length === 0) {
5693
- console.log(chalk13.dim("No active syndicates found."));
6100
+ console.log(chalk15.dim("No active syndicates found."));
5694
6101
  return;
5695
6102
  }
5696
6103
  console.log();
5697
- console.log(chalk13.bold(`Active Syndicates (${syndicates.length})`));
6104
+ console.log(chalk15.bold(`Active Syndicates (${syndicates.length})`));
5698
6105
  if (!process.env.SUBGRAPH_URL && !opts.allChains) {
5699
- console.log(chalk13.dim(" (Set SUBGRAPH_URL for faster indexed queries)"));
6106
+ console.log(chalk15.dim(" (Set SUBGRAPH_URL for faster indexed queries)"));
5700
6107
  }
5701
6108
  if (opts.allChains) {
5702
- console.log(chalk13.dim(" (Aggregated across chains via on-chain factory calls; SUBGRAPH_URL is single-chain only)"));
6109
+ console.log(chalk15.dim(" (Aggregated across chains via on-chain factory calls; SUBGRAPH_URL is single-chain only)"));
5703
6110
  }
5704
- console.log(chalk13.dim("\u2500".repeat(70)));
6111
+ console.log(chalk15.dim("\u2500".repeat(70)));
5705
6112
  for (const s of syndicates) {
5706
6113
  const ts = typeof s.createdAt === "string" ? Number(s.createdAt) : Number(s.createdAt);
5707
6114
  const date = new Date(ts * 1e3).toLocaleDateString();
5708
6115
  const ensName = s.subdomain ? `${s.subdomain}.sherwoodagent.eth` : "";
5709
- const chainTag = s.chain ? chalk13.dim(`[${s.chain}] `) : "";
5710
- console.log(` ${chainTag}#${s.id} ${chalk13.bold(ensName || String(s.vault))}`);
5711
- if (ensName) console.log(` Vault: ${chalk13.cyan(String(s.vault))}`);
6116
+ const chainTag = s.chain ? chalk15.dim(`[${s.chain}] `) : "";
6117
+ console.log(` ${chainTag}#${s.id} ${chalk15.bold(ensName || String(s.vault))}`);
6118
+ if (ensName) console.log(` Vault: ${chalk15.cyan(String(s.vault))}`);
5712
6119
  console.log(` Creator: ${s.creator}`);
5713
6120
  console.log(` Created: ${date}`);
5714
6121
  if (s.totalDeposits) {
5715
6122
  console.log(` Deposits: ${s.totalDeposits} USDC`);
5716
6123
  }
5717
6124
  if (s.metadataURI) {
5718
- console.log(` Metadata: ${chalk13.dim(s.metadataURI)}`);
6125
+ console.log(` Metadata: ${chalk15.dim(s.metadataURI)}`);
5719
6126
  }
5720
6127
  console.log();
5721
6128
  }
5722
6129
  } catch (err) {
5723
6130
  spinner.fail("Failed to load syndicates");
5724
- console.error(chalk13.red(formatContractError(err)));
6131
+ console.error(chalk15.red(formatContractError(err)));
5725
6132
  process.exit(1);
5726
6133
  }
5727
6134
  });
@@ -5761,38 +6168,38 @@ syndicate.command("info").description("Display syndicate details by ID or subdom
5761
6168
  spinner.stop();
5762
6169
  if (crossChainHint) {
5763
6170
  const others = crossChainHint.others.length > 0 ? ` (also on: ${crossChainHint.others.join(", ")})` : "";
5764
- console.log(chalk13.yellow(` Found on chain: ${chalk13.bold(crossChainHint.network)}${others}`));
5765
- console.log(chalk13.dim(` Re-run with --chain ${crossChainHint.network} to interact with this syndicate.`));
6171
+ console.log(chalk15.yellow(` Found on chain: ${chalk15.bold(crossChainHint.network)}${others}`));
6172
+ console.log(chalk15.dim(` Re-run with --chain ${crossChainHint.network} to interact with this syndicate.`));
5766
6173
  console.log();
5767
6174
  }
5768
6175
  if (!info.vault || info.vault === "0x0000000000000000000000000000000000000000") {
5769
- console.log(chalk13.red(`Syndicate #${id} not found.`));
6176
+ console.log(chalk15.red(`Syndicate #${id} not found.`));
5770
6177
  process.exit(1);
5771
6178
  }
5772
6179
  const date = new Date(Number(info.createdAt) * 1e3).toLocaleDateString();
5773
6180
  console.log();
5774
- console.log(chalk13.bold(`Syndicate #${info.id}`));
5775
- console.log(chalk13.dim("\u2500".repeat(40)));
6181
+ console.log(chalk15.bold(`Syndicate #${info.id}`));
6182
+ console.log(chalk15.dim("\u2500".repeat(40)));
5776
6183
  if (info.subdomain) {
5777
- console.log(` ENS: ${chalk13.bold(`${info.subdomain}.sherwoodagent.eth`)}`);
6184
+ console.log(` ENS: ${chalk15.bold(`${info.subdomain}.sherwoodagent.eth`)}`);
5778
6185
  }
5779
- console.log(` Vault: ${chalk13.cyan(info.vault)}`);
6186
+ console.log(` Vault: ${chalk15.cyan(info.vault)}`);
5780
6187
  console.log(` Creator: ${info.creator}`);
5781
6188
  console.log(` Created: ${date}`);
5782
- console.log(` Active: ${info.active ? chalk13.green("yes") : chalk13.red("no")}`);
6189
+ console.log(` Active: ${info.active ? chalk15.green("yes") : chalk15.red("no")}`);
5783
6190
  if (info.metadataURI) {
5784
- console.log(` Metadata: ${chalk13.dim(info.metadataURI)}`);
6191
+ console.log(` Metadata: ${chalk15.dim(info.metadataURI)}`);
5785
6192
  }
5786
6193
  if (info.subdomain) {
5787
6194
  const xmtpGroupId = getCachedGroupId(info.subdomain);
5788
6195
  if (xmtpGroupId) {
5789
- console.log(` XMTP Group: ${chalk13.cyan(xmtpGroupId)}`);
6196
+ console.log(` XMTP Group: ${chalk15.cyan(xmtpGroupId)}`);
5790
6197
  }
5791
6198
  }
5792
6199
  setVaultAddress(info.vault);
5793
6200
  const vaultInfo = crossChainHint ? await withNetwork(crossChainHint.network, () => getVaultInfo()) : await getVaultInfo();
5794
6201
  console.log();
5795
- console.log(chalk13.bold(" Vault Stats"));
6202
+ console.log(chalk15.bold(" Vault Stats"));
5796
6203
  console.log(` Total Assets: ${vaultInfo.totalAssets}`);
5797
6204
  console.log(` Agent Count: ${vaultInfo.agentCount}`);
5798
6205
  console.log(` Redemptions Locked: ${vaultInfo.redemptionsLocked}`);
@@ -5800,7 +6207,7 @@ syndicate.command("info").description("Display syndicate details by ID or subdom
5800
6207
  console.log();
5801
6208
  } catch (err) {
5802
6209
  spinner.fail("Failed to load syndicate info");
5803
- console.error(chalk13.red(formatContractError(err)));
6210
+ console.error(chalk15.red(formatContractError(err)));
5804
6211
  process.exit(1);
5805
6212
  }
5806
6213
  });
@@ -5836,7 +6243,7 @@ syndicate.command("update-metadata").description("Update syndicate metadata (cre
5836
6243
  console.log(DIM6(` ${getExplorerUrl(hash)}`));
5837
6244
  } catch (err) {
5838
6245
  spinner.fail("Metadata update failed");
5839
- console.error(chalk13.red(formatContractError(err)));
6246
+ console.error(chalk15.red(formatContractError(err)));
5840
6247
  process.exit(1);
5841
6248
  }
5842
6249
  });
@@ -5847,10 +6254,10 @@ syndicate.command("approve-depositor").description("Approve an address to deposi
5847
6254
  const depositor = validateAddress(opts.depositor, "depositor");
5848
6255
  const hash = await approveDepositor(depositor);
5849
6256
  spinner.succeed(`Depositor approved: ${hash}`);
5850
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6257
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
5851
6258
  } catch (err) {
5852
6259
  spinner.fail("Approval failed");
5853
- console.error(chalk13.red(formatContractError(err)));
6260
+ console.error(chalk15.red(formatContractError(err)));
5854
6261
  process.exit(1);
5855
6262
  }
5856
6263
  });
@@ -5861,10 +6268,10 @@ syndicate.command("remove-depositor").description("Remove an address from the de
5861
6268
  const depositor = validateAddress(opts.depositor, "depositor");
5862
6269
  const hash = await removeDepositor(depositor);
5863
6270
  spinner.succeed(`Depositor removed: ${hash}`);
5864
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6271
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
5865
6272
  } catch (err) {
5866
6273
  spinner.fail("Removal failed");
5867
- console.error(chalk13.red(formatContractError(err)));
6274
+ console.error(chalk15.red(formatContractError(err)));
5868
6275
  process.exit(1);
5869
6276
  }
5870
6277
  });
@@ -5905,7 +6312,7 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
5905
6312
  });
5906
6313
  if (balance === 0n) {
5907
6314
  spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
5908
- console.error(chalk13.dim(" Mint one first: sherwood identity mint --name <name>"));
6315
+ console.error(chalk15.dim(" Mint one first: sherwood identity mint --name <name>"));
5909
6316
  process.exit(1);
5910
6317
  }
5911
6318
  const tokenId = await client.readContract({
@@ -5921,13 +6328,13 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
5921
6328
  args: [agentWallet, 0n]
5922
6329
  });
5923
6330
  agentId = tokenId;
5924
- console.log(chalk13.dim(` Resolved agent ID: #${agentId}`));
6331
+ console.log(chalk15.dim(` Resolved agent ID: #${agentId}`));
5925
6332
  }
5926
6333
  }
5927
6334
  spinner.text = "Registering agent...";
5928
6335
  const hash = await registerAgent(agentId, agentWallet);
5929
6336
  spinner.succeed(`Agent registered: ${hash}`);
5930
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6337
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
5931
6338
  try {
5932
6339
  const xmtp = await loadXmtp();
5933
6340
  const xmtpClient = await xmtp.getXmtpClient();
@@ -5939,14 +6346,14 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
5939
6346
  syndicate: subdomain,
5940
6347
  timestamp: Math.floor(Date.now() / 1e3)
5941
6348
  });
5942
- console.log(chalk13.dim(` Added to chat: ${subdomain}`));
6349
+ console.log(chalk15.dim(` Added to chat: ${subdomain}`));
5943
6350
  } catch {
5944
- console.warn(chalk13.yellow(" \u26A0 Could not add agent to chat group"));
5945
- console.warn(chalk13.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
6351
+ console.warn(chalk15.yellow(" \u26A0 Could not add agent to chat group"));
6352
+ console.warn(chalk15.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
5946
6353
  }
5947
6354
  } catch (err) {
5948
6355
  spinner.fail("Registration failed");
5949
- console.error(chalk13.red(formatContractError(err)));
6356
+ console.error(chalk15.red(formatContractError(err)));
5950
6357
  process.exit(1);
5951
6358
  }
5952
6359
  });
@@ -5954,7 +6361,7 @@ syndicate.command("share").description("Print the shareable dashboard URL for yo
5954
6361
  try {
5955
6362
  const subdomain = opts.subdomain || getPrimarySyndicate(getChain().id)?.subdomain;
5956
6363
  if (!subdomain) {
5957
- console.error(chalk13.red(" No syndicate configured. Pass --subdomain <name> or run 'syndicate create/join' first."));
6364
+ console.error(chalk15.red(" No syndicate configured. Pass --subdomain <name> or run 'syndicate create/join' first."));
5958
6365
  process.exit(1);
5959
6366
  }
5960
6367
  const syndicateInfo = await resolveSyndicate(subdomain);
@@ -5981,7 +6388,7 @@ syndicate.command("share").description("Print the shareable dashboard URL for yo
5981
6388
  }
5982
6389
  console.log();
5983
6390
  } catch (err) {
5984
- console.error(chalk13.red(` \u2716 ${formatContractError(err)}`));
6391
+ console.error(chalk15.red(` \u2716 ${formatContractError(err)}`));
5985
6392
  process.exit(1);
5986
6393
  }
5987
6394
  });
@@ -6006,14 +6413,14 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6006
6413
  const hits = await searchSyndicateAcrossChains(subdomain);
6007
6414
  spinner.fail(`Syndicate "${subdomain}" not found on ${getNetwork()}`);
6008
6415
  if (hits.length === 0) {
6009
- console.error(chalk13.red(` Not found on any supported chain.`));
6416
+ console.error(chalk15.red(` Not found on any supported chain.`));
6010
6417
  } else if (hits.length === 1) {
6011
- console.error(chalk13.yellow(` Found on chain: ${chalk13.bold(hits[0].network)}`));
6012
- console.error(chalk13.dim(` Re-run: sherwood --chain ${hits[0].network} syndicate join --subdomain ${subdomain}`));
6418
+ console.error(chalk15.yellow(` Found on chain: ${chalk15.bold(hits[0].network)}`));
6419
+ console.error(chalk15.dim(` Re-run: sherwood --chain ${hits[0].network} syndicate join --subdomain ${subdomain}`));
6013
6420
  } else {
6014
6421
  const chains = hits.map((h) => h.network).join(", ");
6015
- console.error(chalk13.yellow(` Found on chains: ${chalk13.bold(chains)}`));
6016
- console.error(chalk13.dim(` Specify which chain to join with --chain <network>.`));
6422
+ console.error(chalk15.yellow(` Found on chains: ${chalk15.bold(chains)}`));
6423
+ console.error(chalk15.dim(` Specify which chain to join with --chain <network>.`));
6017
6424
  }
6018
6425
  process.exit(1);
6019
6426
  }
@@ -6026,17 +6433,17 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6026
6433
  try {
6027
6434
  const xmtp = await loadXmtp();
6028
6435
  await xmtp.getXmtpClient();
6029
- console.log(chalk13.dim(" XMTP identity ready"));
6436
+ console.log(chalk15.dim(" XMTP identity ready"));
6030
6437
  } catch {
6031
- console.warn(chalk13.yellow(" \u26A0 Could not initialize XMTP identity"));
6438
+ console.warn(chalk15.yellow(" \u26A0 Could not initialize XMTP identity"));
6032
6439
  }
6033
6440
  try {
6034
6441
  const cron = await loadCron();
6035
6442
  const cronResult = cron.registerSyndicateCrons(subdomain, isTestnet(), getNotifyTo());
6036
6443
  if (cronResult.isOpenClaw && cronResult.registered) {
6037
- console.log(chalk13.green(" \u2713 Participation crons registered"));
6444
+ console.log(chalk15.green(" \u2713 Participation crons registered"));
6038
6445
  } else if (!cronResult.isOpenClaw) {
6039
- console.log(chalk13.dim(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
6446
+ console.log(chalk15.dim(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
6040
6447
  }
6041
6448
  } catch {
6042
6449
  }
@@ -6049,14 +6456,14 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6049
6456
  );
6050
6457
  if (existingRequest) {
6051
6458
  spinner.succeed("You already have a pending join request for this syndicate");
6052
- console.log(chalk13.dim(` Attestation: ${existingRequest.uid}`));
6053
- console.log(chalk13.dim(` Submitted: ${new Date(existingRequest.time * 1e3).toLocaleString()}`));
6459
+ console.log(chalk15.dim(` Attestation: ${existingRequest.uid}`));
6460
+ console.log(chalk15.dim(` Submitted: ${new Date(existingRequest.time * 1e3).toLocaleString()}`));
6054
6461
  try {
6055
6462
  const xmtp = await loadXmtp();
6056
6463
  await xmtp.getXmtpClient();
6057
- console.log(chalk13.dim(" XMTP identity ready"));
6464
+ console.log(chalk15.dim(" XMTP identity ready"));
6058
6465
  } catch {
6059
- console.warn(chalk13.yellow(" \u26A0 Could not initialize XMTP identity"));
6466
+ console.warn(chalk15.yellow(" \u26A0 Could not initialize XMTP identity"));
6060
6467
  }
6061
6468
  return;
6062
6469
  }
@@ -6077,7 +6484,7 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6077
6484
  spinner.succeed("Join request created (XMTP identity ready)");
6078
6485
  } catch {
6079
6486
  spinner.succeed("Join request created");
6080
- console.warn(chalk13.yellow(" \u26A0 Could not initialize XMTP identity \u2014 creator may not be able to auto-add you to chat"));
6487
+ console.warn(chalk15.yellow(" \u26A0 Could not initialize XMTP identity \u2014 creator may not be able to auto-add you to chat"));
6081
6488
  }
6082
6489
  addSyndicate(getChain().id, { subdomain, vault: syndicate2.vault, role: "agent" });
6083
6490
  setPrimarySyndicate(getChain().id, subdomain);
@@ -6107,7 +6514,7 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
6107
6514
  console.log();
6108
6515
  } catch (err) {
6109
6516
  spinner.fail("Join request failed");
6110
- console.error(chalk13.red(formatContractError(err)));
6517
+ console.error(chalk15.red(formatContractError(err)));
6111
6518
  process.exit(1);
6112
6519
  }
6113
6520
  });
@@ -6175,7 +6582,7 @@ syndicate.command("requests").description("View pending join requests for a synd
6175
6582
  console.log();
6176
6583
  } catch (err) {
6177
6584
  spinner.fail("Failed to load requests");
6178
- console.error(chalk13.red(formatContractError(err)));
6585
+ console.error(chalk15.red(formatContractError(err)));
6179
6586
  process.exit(1);
6180
6587
  }
6181
6588
  });
@@ -6250,8 +6657,8 @@ syndicate.command("approve").description("Approve an agent join request (registe
6250
6657
  });
6251
6658
  console.log(DIM6(` Added to chat: ${subdomain}`));
6252
6659
  } catch {
6253
- console.warn(chalk13.yellow(" \u26A0 Could not add agent to chat group"));
6254
- console.warn(chalk13.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
6660
+ console.warn(chalk15.yellow(" \u26A0 Could not add agent to chat group"));
6661
+ console.warn(chalk15.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
6255
6662
  }
6256
6663
  spinner.succeed("Agent approved and registered");
6257
6664
  console.log();
@@ -6264,7 +6671,7 @@ syndicate.command("approve").description("Approve an agent join request (registe
6264
6671
  SEP6();
6265
6672
  } catch (err) {
6266
6673
  spinner.fail("Approval failed");
6267
- console.error(chalk13.red(formatContractError(err)));
6674
+ console.error(chalk15.red(formatContractError(err)));
6268
6675
  process.exit(1);
6269
6676
  }
6270
6677
  });
@@ -6276,14 +6683,14 @@ syndicate.command("reject").description("Reject a join request by revoking its a
6276
6683
  console.log(DIM6(` ${getEasExplorerUrl(hash)}`));
6277
6684
  } catch (err) {
6278
6685
  spinner.fail("Rejection failed");
6279
- console.error(chalk13.red(formatContractError(err)));
6686
+ console.error(chalk15.red(formatContractError(err)));
6280
6687
  process.exit(1);
6281
6688
  }
6282
6689
  });
6283
6690
  syndicate.command("leave").description("Leave a syndicate \u2014 removes participation crons and session state").option("--subdomain <name>", "Syndicate subdomain to leave").action(async (opts) => {
6284
6691
  const subdomain = opts.subdomain || getPrimarySyndicate(getChain().id)?.subdomain;
6285
6692
  if (!subdomain) {
6286
- console.error(chalk13.red(" No syndicate configured. Pass --subdomain <name>."));
6693
+ console.error(chalk15.red(" No syndicate configured. Pass --subdomain <name>."));
6287
6694
  process.exit(1);
6288
6695
  }
6289
6696
  const spinner = ora8("Cleaning up...").start();
@@ -6303,13 +6710,13 @@ syndicate.command("leave").description("Leave a syndicate \u2014 removes partici
6303
6710
  }
6304
6711
  console.log(G6(" \u2713 Session state cleared"));
6305
6712
  console.log();
6306
- console.log(chalk13.dim(" Note: This does not remove you on-chain. To exit your position:"));
6307
- console.log(chalk13.dim(" sherwood vault balance \u2014 check your LP share balance"));
6308
- console.log(chalk13.dim(" Redeem shares via the vault contract or dashboard"));
6713
+ console.log(chalk15.dim(" Note: This does not remove you on-chain. To exit your position:"));
6714
+ console.log(chalk15.dim(" sherwood vault balance \u2014 check your LP share balance"));
6715
+ console.log(chalk15.dim(" Redeem shares via the vault contract or dashboard"));
6309
6716
  console.log();
6310
6717
  } catch (err) {
6311
6718
  spinner.fail("Leave failed");
6312
- console.error(chalk13.red(err instanceof Error ? err.message : String(err)));
6719
+ console.error(chalk15.red(err instanceof Error ? err.message : String(err)));
6313
6720
  process.exit(1);
6314
6721
  }
6315
6722
  });
@@ -6360,7 +6767,7 @@ syndicate.command("set-primary").description("Set the active syndicate for CLI c
6360
6767
  }
6361
6768
  }
6362
6769
  if (!target) {
6363
- console.error(chalk13.red(" Could not resolve syndicate. Pass --subdomain or --vault."));
6770
+ console.error(chalk15.red(" Could not resolve syndicate. Pass --subdomain or --vault."));
6364
6771
  process.exit(1);
6365
6772
  }
6366
6773
  setPrimarySyndicate(chainId, target);
@@ -6368,7 +6775,7 @@ syndicate.command("set-primary").description("Set the active syndicate for CLI c
6368
6775
  \u2713 Primary syndicate set to ${target}.sherwoodagent.eth
6369
6776
  `));
6370
6777
  } catch (err) {
6371
- console.error(chalk13.red(formatContractError(err)));
6778
+ console.error(chalk15.red(formatContractError(err)));
6372
6779
  process.exit(1);
6373
6780
  }
6374
6781
  });
@@ -6376,13 +6783,13 @@ var vaultCmd = program.command("vault");
6376
6783
  vaultCmd.command("deposit").description("Deposit into a vault").option("--vault <address>", "Vault address (default: from config)").requiredOption("--amount <amount>", "Amount to deposit (in asset units)").option("--use-eth", "Auto-wrap ETH \u2192 WETH before depositing (for WETH vaults)").action(async (opts) => {
6377
6784
  resolveVault(opts);
6378
6785
  const decimals = await getAssetDecimals();
6379
- const amount = parseUnits6(opts.amount, decimals);
6786
+ const amount = parseUnits7(opts.amount, decimals);
6380
6787
  try {
6381
6788
  if (!opts.useEth) {
6382
6789
  await preflightDeposit(amount);
6383
6790
  }
6384
6791
  } catch (err) {
6385
- console.error(chalk13.red(`
6792
+ console.error(chalk15.red(`
6386
6793
  \u2716 ${err instanceof Error ? err.message : String(err)}
6387
6794
  `));
6388
6795
  process.exit(1);
@@ -6397,10 +6804,10 @@ vaultCmd.command("deposit").description("Deposit into a vault").option("--vault
6397
6804
  hash = await deposit(amount);
6398
6805
  }
6399
6806
  spinner.succeed(`Deposited: ${hash}`);
6400
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6807
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
6401
6808
  } catch (err) {
6402
6809
  spinner.fail("Deposit failed");
6403
- console.error(chalk13.red(formatContractError(err)));
6810
+ console.error(chalk15.red(formatContractError(err)));
6404
6811
  process.exit(1);
6405
6812
  }
6406
6813
  });
@@ -6411,8 +6818,8 @@ vaultCmd.command("info").description("Display vault state").option("--vault <add
6411
6818
  const info = await getVaultInfo();
6412
6819
  spinner.stop();
6413
6820
  console.log();
6414
- console.log(chalk13.bold("Vault Info"));
6415
- console.log(chalk13.dim("\u2500".repeat(40)));
6821
+ console.log(chalk15.bold("Vault Info"));
6822
+ console.log(chalk15.dim("\u2500".repeat(40)));
6416
6823
  console.log(` Address: ${info.address}`);
6417
6824
  console.log(` Total Assets: ${info.totalAssets}`);
6418
6825
  console.log(` Agent Count: ${info.agentCount}`);
@@ -6421,7 +6828,7 @@ vaultCmd.command("info").description("Display vault state").option("--vault <add
6421
6828
  console.log();
6422
6829
  } catch (err) {
6423
6830
  spinner.fail("Failed to load vault info");
6424
- console.error(chalk13.red(formatContractError(err)));
6831
+ console.error(chalk15.red(formatContractError(err)));
6425
6832
  process.exit(1);
6426
6833
  }
6427
6834
  });
@@ -6432,15 +6839,15 @@ vaultCmd.command("balance").description("Show LP share balance and asset value")
6432
6839
  const balance = await getBalance(opts.address);
6433
6840
  spinner.stop();
6434
6841
  console.log();
6435
- console.log(chalk13.bold("LP Position"));
6436
- console.log(chalk13.dim("\u2500".repeat(40)));
6842
+ console.log(chalk15.bold("LP Position"));
6843
+ console.log(chalk15.dim("\u2500".repeat(40)));
6437
6844
  console.log(` Shares: ${balance.shares.toString()}`);
6438
6845
  console.log(` Asset Value: ${balance.assetsValue}`);
6439
6846
  console.log(` % of Vault: ${balance.percentOfVault}`);
6440
6847
  console.log();
6441
6848
  } catch (err) {
6442
6849
  spinner.fail("Failed to load balance");
6443
- console.error(chalk13.red(formatContractError(err)));
6850
+ console.error(chalk15.red(formatContractError(err)));
6444
6851
  process.exit(1);
6445
6852
  }
6446
6853
  });
@@ -6451,22 +6858,22 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
6451
6858
  let shares;
6452
6859
  try {
6453
6860
  if (opts.shares) {
6454
- shares = parseUnits6(opts.shares, shareDecimals);
6861
+ shares = parseUnits7(opts.shares, shareDecimals);
6455
6862
  } else {
6456
6863
  shares = await getShareBalance();
6457
6864
  if (shares === 0n) {
6458
- console.error(chalk13.red("\n \u2716 No shares to redeem.\n"));
6865
+ console.error(chalk15.red("\n \u2716 No shares to redeem.\n"));
6459
6866
  process.exit(1);
6460
6867
  }
6461
6868
  }
6462
6869
  } catch (err) {
6463
- console.error(chalk13.red(`
6870
+ console.error(chalk15.red(`
6464
6871
  \u2716 ${err instanceof Error ? err.message : String(err)}
6465
6872
  `));
6466
6873
  process.exit(1);
6467
6874
  }
6468
6875
  if (opts.receiver && !isAddress6(opts.receiver)) {
6469
- console.error(chalk13.red(`
6876
+ console.error(chalk15.red(`
6470
6877
  \u2716 Invalid receiver address: ${opts.receiver}
6471
6878
  `));
6472
6879
  process.exit(1);
@@ -6474,7 +6881,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
6474
6881
  try {
6475
6882
  await preflightRedeem(shares);
6476
6883
  } catch (err) {
6477
- console.error(chalk13.red(`
6884
+ console.error(chalk15.red(`
6478
6885
  \u2716 ${err instanceof Error ? err.message : String(err)}
6479
6886
  `));
6480
6887
  process.exit(1);
@@ -6487,11 +6894,11 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
6487
6894
  opts.receiver
6488
6895
  );
6489
6896
  spinner.succeed(`Redeemed: ${hash}`);
6490
- console.log(chalk13.dim(` ${getExplorerUrl(hash)}`));
6897
+ console.log(chalk15.dim(` ${getExplorerUrl(hash)}`));
6491
6898
  console.log(` Assets received: ${formatUnits5(assetsOut, assetDecimals)}`);
6492
6899
  } catch (err) {
6493
6900
  spinner.fail("Redeem failed");
6494
- console.error(chalk13.red(formatContractError(err)));
6901
+ console.error(chalk15.red(formatContractError(err)));
6495
6902
  process.exit(1);
6496
6903
  }
6497
6904
  });
@@ -6513,9 +6920,9 @@ try {
6513
6920
  registerChatCommands(program);
6514
6921
  } catch {
6515
6922
  program.command("chat <name> [action] [actionArgs...]").description("Syndicate chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
6516
- console.error(chalk13.red("XMTP CLI not available."));
6517
- console.error(chalk13.dim("Install with: npm install -g @xmtp/cli"));
6518
- console.error(chalk13.dim("Or reinstall: npm i -g @sherwoodagent/cli"));
6923
+ console.error(chalk15.red("XMTP CLI not available."));
6924
+ console.error(chalk15.dim("Install with: npm install -g @xmtp/cli"));
6925
+ console.error(chalk15.dim("Or reinstall: npm i -g @sherwoodagent/cli"));
6519
6926
  process.exit(1);
6520
6927
  });
6521
6928
  }
@@ -6529,7 +6936,7 @@ registerGovernorCommands(program);
6529
6936
  registerGuardianCommands(program);
6530
6937
  var { registerResearchCommands } = await import("./research-QBKISW2M.js");
6531
6938
  registerResearchCommands(program);
6532
- var { registerAgentCommands } = await import("./agent-4HKHLQEJ.js");
6939
+ var { registerAgentCommands } = await import("./agent-ZPAZTJG3.js");
6533
6940
  registerAgentCommands(program);
6534
6941
  var { registerTradeCommands } = await import("./trade-NO6CNWCA.js");
6535
6942
  registerTradeCommands(program);
@@ -6540,58 +6947,58 @@ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (
6540
6947
  if (opts.privateKey) {
6541
6948
  setPrivateKey(opts.privateKey);
6542
6949
  const account = getAccount();
6543
- console.log(chalk13.green("Private key saved to ~/.sherwood/config.json"));
6544
- console.log(chalk13.dim(` Wallet: ${account.address}`));
6950
+ console.log(chalk15.green("Private key saved to ~/.sherwood/config.json"));
6951
+ console.log(chalk15.dim(` Wallet: ${account.address}`));
6545
6952
  saved = true;
6546
6953
  }
6547
6954
  if (opts.vault) {
6548
6955
  const chainId = getChain().id;
6549
6956
  setChainContract(chainId, "vault", opts.vault);
6550
- console.log(chalk13.green(`Vault saved to ~/.sherwood/config.json (chain ${chainId})`));
6551
- console.log(chalk13.dim(` Vault: ${opts.vault}`));
6957
+ console.log(chalk15.green(`Vault saved to ~/.sherwood/config.json (chain ${chainId})`));
6958
+ console.log(chalk15.dim(` Vault: ${opts.vault}`));
6552
6959
  saved = true;
6553
6960
  }
6554
6961
  if (opts.rpc) {
6555
6962
  const network = getNetwork();
6556
6963
  setConfigRpcUrl(network, opts.rpc);
6557
- console.log(chalk13.green(`RPC URL saved for ${network}`));
6558
- console.log(chalk13.dim(` RPC: ${opts.rpc}`));
6964
+ console.log(chalk15.green(`RPC URL saved for ${network}`));
6965
+ console.log(chalk15.dim(` RPC: ${opts.rpc}`));
6559
6966
  saved = true;
6560
6967
  }
6561
6968
  if (opts.notifyTo) {
6562
6969
  setNotifyTo(opts.notifyTo);
6563
- console.log(chalk13.green("Notify destination saved to ~/.sherwood/config.json"));
6564
- console.log(chalk13.dim(` Notify to: ${opts.notifyTo}`));
6970
+ console.log(chalk15.green("Notify destination saved to ~/.sherwood/config.json"));
6971
+ console.log(chalk15.dim(` Notify to: ${opts.notifyTo}`));
6565
6972
  saved = true;
6566
6973
  }
6567
6974
  if (opts.uniswapApiKey) {
6568
6975
  setUniswapApiKey(opts.uniswapApiKey);
6569
- console.log(chalk13.green("Uniswap API key saved to ~/.sherwood/config.json"));
6976
+ console.log(chalk15.green("Uniswap API key saved to ~/.sherwood/config.json"));
6570
6977
  saved = true;
6571
6978
  }
6572
6979
  if (opts.veniceApiKey) {
6573
6980
  setVeniceApiKey(opts.veniceApiKey);
6574
- console.log(chalk13.green("Venice API key saved to ~/.sherwood/config.json"));
6981
+ console.log(chalk15.green("Venice API key saved to ~/.sherwood/config.json"));
6575
6982
  saved = true;
6576
6983
  }
6577
6984
  if (opts.anthropicApiKey) {
6578
6985
  setAnthropicApiKey(opts.anthropicApiKey);
6579
- console.log(chalk13.green("Anthropic API key saved to ~/.sherwood/config.json"));
6986
+ console.log(chalk15.green("Anthropic API key saved to ~/.sherwood/config.json"));
6580
6987
  saved = true;
6581
6988
  }
6582
6989
  if (opts.xmtpGroup) {
6583
6990
  const parts = opts.xmtpGroup.split(":");
6584
6991
  if (parts.length !== 2 || !parts[0] || !parts[1]) {
6585
- console.log(chalk13.red("Format: --xmtp-group <subdomain>:<groupId>"));
6992
+ console.log(chalk15.red("Format: --xmtp-group <subdomain>:<groupId>"));
6586
6993
  process.exit(1);
6587
6994
  }
6588
6995
  cacheGroupId(parts[0], parts[1]);
6589
- console.log(chalk13.green(`XMTP group ID cached for ${parts[0]}`));
6590
- console.log(chalk13.dim(` Group ID: ${parts[1]}`));
6996
+ console.log(chalk15.green(`XMTP group ID cached for ${parts[0]}`));
6997
+ console.log(chalk15.dim(` Group ID: ${parts[1]}`));
6591
6998
  saved = true;
6592
6999
  }
6593
7000
  if (!saved) {
6594
- console.log(chalk13.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --anthropic-api-key, --xmtp-group"));
7001
+ console.log(chalk15.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --anthropic-api-key, --xmtp-group"));
6595
7002
  process.exit(1);
6596
7003
  }
6597
7004
  });
@@ -6602,25 +7009,25 @@ configCmd.command("show").description("Display current config for the active net
6602
7009
  const config = loadConfig();
6603
7010
  const customRpc = config.rpc?.[network];
6604
7011
  console.log();
6605
- console.log(chalk13.bold(`Sherwood Config`));
6606
- console.log(chalk13.dim("\u2500".repeat(50)));
6607
- console.log(` Network: ${chalk13.cyan(network)} (chain ${chainId})`);
6608
- console.log(` RPC: ${customRpc ? chalk13.green(customRpc) : chalk13.dim("default")}`);
6609
- console.log(` Wallet: ${config.privateKey ? chalk13.green("configured") : chalk13.dim("not set")}`);
6610
- console.log(` Agent ID: ${config.agentId ?? chalk13.dim("not set")}`);
6611
- console.log(` Vault: ${contracts.vault ?? chalk13.dim("not set")}`);
6612
- console.log(` Uniswap: ${getUniswapApiKey() ? chalk13.green("API key configured") : chalk13.dim("not set")}`);
6613
- console.log(` Venice: ${getVeniceApiKey() ? chalk13.green("API key configured") : chalk13.dim("not set")}`);
7012
+ console.log(chalk15.bold(`Sherwood Config`));
7013
+ console.log(chalk15.dim("\u2500".repeat(50)));
7014
+ console.log(` Network: ${chalk15.cyan(network)} (chain ${chainId})`);
7015
+ console.log(` RPC: ${customRpc ? chalk15.green(customRpc) : chalk15.dim("default")}`);
7016
+ console.log(` Wallet: ${config.privateKey ? chalk15.green("configured") : chalk15.dim("not set")}`);
7017
+ console.log(` Agent ID: ${config.agentId ?? chalk15.dim("not set")}`);
7018
+ console.log(` Vault: ${contracts.vault ?? chalk15.dim("not set")}`);
7019
+ console.log(` Uniswap: ${getUniswapApiKey() ? chalk15.green("API key configured") : chalk15.dim("not set")}`);
7020
+ console.log(` Venice: ${getVeniceApiKey() ? chalk15.green("API key configured") : chalk15.dim("not set")}`);
6614
7021
  const groupEntries = Object.entries(config.groupCache || {}).filter(([, v]) => v);
6615
7022
  if (groupEntries.length > 0) {
6616
7023
  console.log();
6617
- console.log(chalk13.bold(" XMTP Groups"));
7024
+ console.log(chalk15.bold(" XMTP Groups"));
6618
7025
  for (const [sub, gid] of groupEntries) {
6619
- console.log(` ${sub}: ${chalk13.cyan(gid)}`);
7026
+ console.log(` ${sub}: ${chalk15.cyan(gid)}`);
6620
7027
  }
6621
7028
  }
6622
7029
  console.log();
6623
- console.log(chalk13.dim(" Config file: ~/.sherwood/config.json"));
7030
+ console.log(chalk15.dim(" Config file: ~/.sherwood/config.json"));
6624
7031
  console.log();
6625
7032
  });
6626
7033
  program.parse();