@sherwoodagent/cli 0.17.3 → 0.18.1

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 (29) hide show
  1. package/dist/{chat-MQPTP4QO.js → chat-7CB4YGGP.js} +4 -4
  2. package/dist/{chunk-EMDEQLUU.js → chunk-5ZC2A7UP.js} +2 -2
  3. package/dist/{chunk-PRX5GLSN.js → chunk-ARD44YTT.js} +2 -2
  4. package/dist/{chunk-KYABEFLH.js → chunk-FR4LYDPJ.js} +2 -2
  5. package/dist/chunk-L24NGLKY.js +124 -0
  6. package/dist/chunk-L24NGLKY.js.map +1 -0
  7. package/dist/{chunk-EDH6ICCT.js → chunk-Z2PNK3CC.js} +2 -2
  8. package/dist/{eas-Y7HS7FXK.js → eas-DOC4QKDF.js} +3 -3
  9. package/dist/{governor-UGIUQYPB.js → governor-E6AU3UWV.js} +3 -3
  10. package/dist/index.js +110 -394
  11. package/dist/index.js.map +1 -1
  12. package/dist/{research-NCY3MCN4.js → research-MHN7UGIU.js} +5 -5
  13. package/dist/{research-IUHVRHR3.js → research-V63URK4C.js} +3 -3
  14. package/dist/{session-CQZ743DX.js → session-OJX2MILJ.js} +4 -4
  15. package/dist/{xmtp-MJ53JW2W.js → xmtp-ATRMY76G.js} +3 -3
  16. package/package.json +1 -1
  17. package/dist/chunk-N65F7HRF.js +0 -74
  18. package/dist/chunk-N65F7HRF.js.map +0 -1
  19. /package/dist/{chat-MQPTP4QO.js.map → chat-7CB4YGGP.js.map} +0 -0
  20. /package/dist/{chunk-EMDEQLUU.js.map → chunk-5ZC2A7UP.js.map} +0 -0
  21. /package/dist/{chunk-PRX5GLSN.js.map → chunk-ARD44YTT.js.map} +0 -0
  22. /package/dist/{chunk-KYABEFLH.js.map → chunk-FR4LYDPJ.js.map} +0 -0
  23. /package/dist/{chunk-EDH6ICCT.js.map → chunk-Z2PNK3CC.js.map} +0 -0
  24. /package/dist/{eas-Y7HS7FXK.js.map → eas-DOC4QKDF.js.map} +0 -0
  25. /package/dist/{governor-UGIUQYPB.js.map → governor-E6AU3UWV.js.map} +0 -0
  26. /package/dist/{research-NCY3MCN4.js.map → research-MHN7UGIU.js.map} +0 -0
  27. /package/dist/{research-IUHVRHR3.js.map → research-V63URK4C.js.map} +0 -0
  28. /package/dist/{session-CQZ743DX.js.map → session-OJX2MILJ.js.map} +0 -0
  29. /package/dist/{xmtp-MJ53JW2W.js.map → xmtp-ATRMY76G.js.map} +0 -0
package/dist/index.js CHANGED
@@ -29,7 +29,7 @@ import {
29
29
  setVotingPeriod,
30
30
  settleProposal,
31
31
  vote
32
- } from "./chunk-EMDEQLUU.js";
32
+ } from "./chunk-5ZC2A7UP.js";
33
33
  import {
34
34
  fetchMetadata,
35
35
  uploadMetadata
@@ -41,7 +41,7 @@ import {
41
41
  queryApprovals,
42
42
  queryJoinRequests,
43
43
  revokeAttestation
44
- } from "./chunk-KYABEFLH.js";
44
+ } from "./chunk-FR4LYDPJ.js";
45
45
  import {
46
46
  approveDepositor,
47
47
  deposit,
@@ -57,7 +57,7 @@ import {
57
57
  resolveVaultSyndicate,
58
58
  setTextRecord,
59
59
  setVaultAddress
60
- } from "./chunk-PRX5GLSN.js";
60
+ } from "./chunk-ARD44YTT.js";
61
61
  import {
62
62
  AERODROME,
63
63
  AGENT_REGISTRY,
@@ -78,8 +78,10 @@ import {
78
78
  import {
79
79
  getAccount,
80
80
  getPublicClient,
81
- getWalletClient
82
- } from "./chunk-N65F7HRF.js";
81
+ getWalletClient,
82
+ sendTxWithRetry,
83
+ writeContractWithRetry
84
+ } from "./chunk-L24NGLKY.js";
83
85
  import {
84
86
  VALID_NETWORKS,
85
87
  getChain,
@@ -108,7 +110,7 @@ import {
108
110
  import { config as loadDotenv } from "dotenv";
109
111
  import { createRequire } from "module";
110
112
  import { Command, Option } from "commander";
111
- import { parseUnits as parseUnits7, isAddress as isAddress5 } from "viem";
113
+ import { parseUnits as parseUnits5, isAddress as isAddress5 } from "viem";
112
114
  import chalk7 from "chalk";
113
115
  import ora7 from "ora";
114
116
  import { input, confirm, select } from "@inquirer/prompts";
@@ -184,10 +186,9 @@ async function cloneTemplate(template) {
184
186
  template,
185
187
  "0x5af43d82803e903d91602b57fd5bf3"
186
188
  ]);
187
- const wallet = getWalletClient();
188
189
  const account = getAccount();
189
190
  const chain = getChain();
190
- const hash = await wallet.sendTransaction({
191
+ const hash = await sendTxWithRetry({
191
192
  account,
192
193
  chain,
193
194
  data: creationCode,
@@ -711,8 +712,7 @@ function registerStrategyTemplateCommands(strategy2) {
711
712
  try {
712
713
  const { initData } = await buildInitDataForTemplate(templateKey, opts, vault);
713
714
  const account = getAccount();
714
- const wallet = getWalletClient();
715
- const initHash = await wallet.writeContract({
715
+ const initHash = await writeContractWithRetry({
716
716
  account,
717
717
  chain: getChain(),
718
718
  address: clone,
@@ -761,8 +761,7 @@ function registerStrategyTemplateCommands(strategy2) {
761
761
  assetAmount = built.assetAmount;
762
762
  extraApprovals = built.extraApprovals;
763
763
  const account2 = getAccount();
764
- const wallet = getWalletClient();
765
- const initHash = await wallet.writeContract({
764
+ const initHash = await writeContractWithRetry({
766
765
  account: account2,
767
766
  chain: getChain(),
768
767
  address: clone,
@@ -821,9 +820,9 @@ function registerStrategyTemplateCommands(strategy2) {
821
820
  console.error(chalk.red("Missing --name, --performance-fee, or --duration. Use --write-calls to skip proposal submission."));
822
821
  process.exit(1);
823
822
  }
824
- const { propose: propose2 } = await import("./governor-UGIUQYPB.js");
823
+ const { propose: propose2 } = await import("./governor-E6AU3UWV.js");
825
824
  const { pinJSON } = await import("./ipfs-6XVOOHSR.js");
826
- const { parseDuration: parseDuration2 } = await import("./governor-UGIUQYPB.js");
825
+ const { parseDuration: parseDuration2 } = await import("./governor-E6AU3UWV.js");
827
826
  const performanceFeeBps = BigInt(opts.performanceFee);
828
827
  if (performanceFeeBps < 0n || performanceFeeBps > 10000n) {
829
828
  console.error(chalk.red("--performance-fee must be 0-10000 (basis points)"));
@@ -1060,223 +1059,10 @@ async function getActiveSyndicates2(creator) {
1060
1059
  }
1061
1060
 
1062
1061
  // src/commands/venice.ts
1063
- import { parseUnits as parseUnits4, formatUnits as formatUnits2, isAddress as isAddress2 } from "viem";
1062
+ import { formatUnits as formatUnits2, isAddress as isAddress2 } from "viem";
1064
1063
  import chalk2 from "chalk";
1065
1064
  import ora2 from "ora";
1066
1065
 
1067
- // src/lib/quote.ts
1068
- import { encodeFunctionData as encodeFunctionData5, decodeFunctionResult, concat as concat2, pad, numberToHex } from "viem";
1069
- async function getQuote(params) {
1070
- const client = getPublicClient();
1071
- const calldata = encodeFunctionData5({
1072
- abi: UNISWAP_QUOTER_V2_ABI,
1073
- functionName: "quoteExactInputSingle",
1074
- args: [
1075
- {
1076
- tokenIn: params.tokenIn,
1077
- tokenOut: params.tokenOut,
1078
- amountIn: params.amountIn,
1079
- fee: params.fee,
1080
- sqrtPriceLimitX96: 0n
1081
- }
1082
- ]
1083
- });
1084
- const { data } = await client.call({
1085
- to: UNISWAP().QUOTER_V2,
1086
- data: calldata
1087
- });
1088
- if (!data) {
1089
- throw new Error("Quoter returned no data \u2014 pool may not exist for this pair/fee");
1090
- }
1091
- const [amountOut, sqrtPriceX96After, , gasEstimate] = decodeFunctionResult({
1092
- abi: UNISWAP_QUOTER_V2_ABI,
1093
- functionName: "quoteExactInputSingle",
1094
- data
1095
- });
1096
- return { amountOut, sqrtPriceX96After, gasEstimate };
1097
- }
1098
- function applySlippage(amountOut, slippageBps) {
1099
- return amountOut * BigInt(1e4 - slippageBps) / 10000n;
1100
- }
1101
- function encodeSwapPath(tokens, fees) {
1102
- if (tokens.length < 2 || fees.length !== tokens.length - 1) {
1103
- throw new Error("Invalid path: need at least 2 tokens and (tokens-1) fees");
1104
- }
1105
- const parts = [];
1106
- for (let i = 0; i < tokens.length; i++) {
1107
- parts.push(tokens[i].toLowerCase());
1108
- if (i < fees.length) {
1109
- parts.push(pad(numberToHex(fees[i]), { size: 3 }));
1110
- }
1111
- }
1112
- return concat2(parts);
1113
- }
1114
- async function getMultiHopQuote(params) {
1115
- const client = getPublicClient();
1116
- const calldata = encodeFunctionData5({
1117
- abi: UNISWAP_QUOTER_V2_ABI,
1118
- functionName: "quoteExactInput",
1119
- args: [params.path, params.amountIn]
1120
- });
1121
- const { data } = await client.call({
1122
- to: UNISWAP().QUOTER_V2,
1123
- data: calldata
1124
- });
1125
- if (!data) {
1126
- throw new Error("Quoter returned no data \u2014 pool may not exist for this path");
1127
- }
1128
- const [amountOut, , , gasEstimate] = decodeFunctionResult({
1129
- abi: UNISWAP_QUOTER_V2_ABI,
1130
- functionName: "quoteExactInput",
1131
- data
1132
- });
1133
- return { amountOut, sqrtPriceX96After: 0n, gasEstimate };
1134
- }
1135
-
1136
- // src/strategies/venice-fund.ts
1137
- import { encodeFunctionData as encodeFunctionData6, parseUnits as parseUnits3 } from "viem";
1138
- var ERC20_ABI2 = [
1139
- {
1140
- name: "approve",
1141
- type: "function",
1142
- inputs: [
1143
- { name: "spender", type: "address" },
1144
- { name: "amount", type: "uint256" }
1145
- ],
1146
- outputs: [{ name: "", type: "bool" }]
1147
- }
1148
- ];
1149
- var SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI = [
1150
- {
1151
- name: "exactInputSingle",
1152
- type: "function",
1153
- inputs: [
1154
- {
1155
- name: "params",
1156
- type: "tuple",
1157
- components: [
1158
- { name: "tokenIn", type: "address" },
1159
- { name: "tokenOut", type: "address" },
1160
- { name: "fee", type: "uint24" },
1161
- { name: "recipient", type: "address" },
1162
- { name: "amountIn", type: "uint256" },
1163
- { name: "amountOutMinimum", type: "uint256" },
1164
- { name: "sqrtPriceLimitX96", type: "uint160" }
1165
- ]
1166
- }
1167
- ],
1168
- outputs: [{ name: "amountOut", type: "uint256" }]
1169
- }
1170
- ];
1171
- var SWAP_ROUTER_EXACT_INPUT_ABI = [
1172
- {
1173
- name: "exactInput",
1174
- type: "function",
1175
- inputs: [
1176
- {
1177
- name: "params",
1178
- type: "tuple",
1179
- components: [
1180
- { name: "path", type: "bytes" },
1181
- { name: "recipient", type: "address" },
1182
- { name: "amountIn", type: "uint256" },
1183
- { name: "amountOutMinimum", type: "uint256" }
1184
- ]
1185
- }
1186
- ],
1187
- outputs: [{ name: "amountOut", type: "uint256" }]
1188
- }
1189
- ];
1190
- var STAKING_ABI = [
1191
- {
1192
- name: "stake",
1193
- type: "function",
1194
- inputs: [
1195
- { name: "recipient", type: "address" },
1196
- { name: "amount", type: "uint256" }
1197
- ],
1198
- outputs: []
1199
- }
1200
- ];
1201
- function buildFundBatch(config, vaultAddress, agents, assetAddress, assetDecimals, minVVV, swapPath) {
1202
- const ZERO2 = "0x0000000000000000000000000000000000000000";
1203
- if (VENICE().VVV === ZERO2 || VENICE().STAKING === ZERO2) {
1204
- throw new Error("Venice (VVV/sVVV) is not deployed on this network \u2014 venice fund requires Venice staking contracts");
1205
- }
1206
- const assetAmount = parseUnits3(config.amount, assetDecimals);
1207
- const isWeth = assetAddress.toLowerCase() === TOKENS().WETH.toLowerCase();
1208
- const calls = [];
1209
- calls.push({
1210
- target: assetAddress,
1211
- data: encodeFunctionData6({
1212
- abi: ERC20_ABI2,
1213
- functionName: "approve",
1214
- args: [UNISWAP().SWAP_ROUTER, assetAmount]
1215
- }),
1216
- value: 0n
1217
- });
1218
- if (isWeth) {
1219
- calls.push({
1220
- target: UNISWAP().SWAP_ROUTER,
1221
- data: encodeFunctionData6({
1222
- abi: SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI,
1223
- functionName: "exactInputSingle",
1224
- args: [
1225
- {
1226
- tokenIn: TOKENS().WETH,
1227
- tokenOut: VENICE().VVV,
1228
- fee: config.fee2,
1229
- recipient: vaultAddress,
1230
- amountIn: assetAmount,
1231
- amountOutMinimum: minVVV,
1232
- sqrtPriceLimitX96: 0n
1233
- }
1234
- ]
1235
- }),
1236
- value: 0n
1237
- });
1238
- } else {
1239
- calls.push({
1240
- target: UNISWAP().SWAP_ROUTER,
1241
- data: encodeFunctionData6({
1242
- abi: SWAP_ROUTER_EXACT_INPUT_ABI,
1243
- functionName: "exactInput",
1244
- args: [
1245
- {
1246
- path: swapPath,
1247
- recipient: vaultAddress,
1248
- amountIn: assetAmount,
1249
- amountOutMinimum: minVVV
1250
- }
1251
- ]
1252
- }),
1253
- value: 0n
1254
- });
1255
- }
1256
- calls.push({
1257
- target: VENICE().VVV,
1258
- data: encodeFunctionData6({
1259
- abi: ERC20_ABI2,
1260
- functionName: "approve",
1261
- args: [VENICE().STAKING, minVVV]
1262
- }),
1263
- value: 0n
1264
- });
1265
- const perAgent = minVVV / BigInt(agents.length);
1266
- for (const agent of agents) {
1267
- calls.push({
1268
- target: VENICE().STAKING,
1269
- data: encodeFunctionData6({
1270
- abi: STAKING_ABI,
1271
- functionName: "stake",
1272
- args: [agent, perAgent]
1273
- }),
1274
- value: 0n
1275
- });
1276
- }
1277
- return calls;
1278
- }
1279
-
1280
1066
  // src/lib/venice.ts
1281
1067
  var VENICE_API_BASE = "https://api.venice.ai/api/v1";
1282
1068
  async function provisionApiKey() {
@@ -1391,148 +1177,9 @@ async function listModels() {
1391
1177
  }
1392
1178
 
1393
1179
  // src/commands/venice.ts
1394
- import { readFileSync, writeFileSync as writeFileSync2 } from "fs";
1395
- var VALID_FEES = [500, 3e3, 1e4];
1180
+ import { readFileSync } from "fs";
1396
1181
  function registerVeniceCommands(program2) {
1397
- const venice = program2.command("venice").description("Venice private inference \u2014 stake VVV, provision API keys");
1398
- venice.command("fund").description("Swap vault profits \u2192 VVV \u2192 stake \u2192 distribute sVVV to agents").requiredOption("--vault <address>", "Vault address").requiredOption("--amount <amount>", "Deposit token amount to convert (e.g. 500)").option("--fee1 <tier>", "Fee tier for asset \u2192 WETH hop (500, 3000, 10000)", "3000").option("--fee2 <tier>", "Fee tier for WETH \u2192 VVV hop", "10000").option("--slippage <bps>", "Slippage tolerance in bps", "100").option("--execute", "Execute on-chain (default: simulate only)", false).option("--write-calls <path>", "Write batch calls to JSON file for proposal create (skips execution)").action(async (opts) => {
1399
- const vaultAddress = opts.vault;
1400
- if (!isAddress2(vaultAddress)) {
1401
- console.error(chalk2.red(`Invalid vault address: ${opts.vault}`));
1402
- process.exit(1);
1403
- }
1404
- const fee1 = Number(opts.fee1);
1405
- const fee2 = Number(opts.fee2);
1406
- if (!VALID_FEES.includes(fee1) || !VALID_FEES.includes(fee2)) {
1407
- console.error(chalk2.red(`Invalid fee tier. Valid: ${VALID_FEES.join(", ")}`));
1408
- process.exit(1);
1409
- }
1410
- const slippageBps = Number(opts.slippage);
1411
- const client = getPublicClient();
1412
- const spinner = ora2("Reading vault state...").start();
1413
- let assetAddress;
1414
- let assetDecimals;
1415
- let assetSymbol;
1416
- let totalDeposited;
1417
- let assetBalance;
1418
- let agents;
1419
- try {
1420
- [assetAddress, totalDeposited, agents] = await Promise.all([
1421
- client.readContract({ address: vaultAddress, abi: SYNDICATE_VAULT_ABI, functionName: "asset" }),
1422
- client.readContract({ address: vaultAddress, abi: SYNDICATE_VAULT_ABI, functionName: "totalDeposited" }),
1423
- client.readContract({ address: vaultAddress, abi: SYNDICATE_VAULT_ABI, functionName: "getAgentAddresses" })
1424
- ]);
1425
- [assetDecimals, assetSymbol, assetBalance] = await Promise.all([
1426
- client.readContract({ address: assetAddress, abi: ERC20_ABI, functionName: "decimals" }),
1427
- client.readContract({ address: assetAddress, abi: ERC20_ABI, functionName: "symbol" }),
1428
- client.readContract({ address: assetAddress, abi: ERC20_ABI, functionName: "balanceOf", args: [vaultAddress] })
1429
- ]);
1430
- spinner.stop();
1431
- } catch (err) {
1432
- spinner.fail("Failed to read vault state");
1433
- console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
1434
- process.exit(1);
1435
- }
1436
- if (agents.length === 0) {
1437
- console.error(chalk2.red("No agents registered in vault. Register agents first."));
1438
- process.exit(1);
1439
- }
1440
- const requestedAmount = parseUnits4(opts.amount, assetDecimals);
1441
- const profit = assetBalance > totalDeposited ? assetBalance - totalDeposited : 0n;
1442
- const isWeth = assetAddress.toLowerCase() === TOKENS().WETH.toLowerCase();
1443
- console.log();
1444
- console.log(chalk2.bold("Venice Fund"));
1445
- console.log(chalk2.dim("\u2500".repeat(40)));
1446
- console.log(` Asset: ${assetSymbol} (${assetDecimals} decimals)`);
1447
- console.log(` Amount: ${opts.amount} ${assetSymbol}`);
1448
- console.log(` Vault balance: ${formatUnits2(assetBalance, assetDecimals)} ${assetSymbol}`);
1449
- console.log(` Deposited: ${formatUnits2(totalDeposited, assetDecimals)} ${assetSymbol}`);
1450
- console.log(` Profit: ${formatUnits2(profit, assetDecimals)} ${assetSymbol}`);
1451
- console.log(` Agents: ${agents.length} (sVVV will be split equally)`);
1452
- console.log(` Routing: ${isWeth ? `WETH \u2192 VVV (fee ${fee2})` : `${assetSymbol} \u2192 WETH (fee ${fee1}) \u2192 VVV (fee ${fee2})`}`);
1453
- console.log(` Slippage: ${(slippageBps / 100).toFixed(2)}%`);
1454
- console.log(` Vault: ${vaultAddress}`);
1455
- console.log();
1456
- if (requestedAmount > profit) {
1457
- console.warn(chalk2.yellow(` Warning: amount (${opts.amount}) exceeds available profit (${formatUnits2(profit, assetDecimals)})`));
1458
- console.warn(chalk2.yellow(" This will use deposited capital, not just profits."));
1459
- console.log();
1460
- }
1461
- const quoteSpinner = ora2("Fetching Uniswap quote...").start();
1462
- let amountOut;
1463
- let minOut;
1464
- let swapPath = null;
1465
- try {
1466
- if (isWeth) {
1467
- const quote = await getQuote({
1468
- tokenIn: TOKENS().WETH,
1469
- tokenOut: VENICE().VVV,
1470
- amountIn: requestedAmount,
1471
- fee: fee2
1472
- });
1473
- amountOut = quote.amountOut;
1474
- } else {
1475
- swapPath = encodeSwapPath(
1476
- [assetAddress, TOKENS().WETH, VENICE().VVV],
1477
- [fee1, fee2]
1478
- );
1479
- const quote = await getMultiHopQuote({
1480
- path: swapPath,
1481
- amountIn: requestedAmount
1482
- });
1483
- amountOut = quote.amountOut;
1484
- }
1485
- minOut = applySlippage(amountOut, slippageBps);
1486
- quoteSpinner.succeed(
1487
- `Quote: ${formatUnits2(amountOut, 18)} VVV (min: ${formatUnits2(minOut, 18)}, per agent: ${formatUnits2(minOut / BigInt(agents.length), 18)})`
1488
- );
1489
- } catch (err) {
1490
- quoteSpinner.fail("Failed to fetch quote");
1491
- console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
1492
- process.exit(1);
1493
- }
1494
- const config = {
1495
- amount: opts.amount,
1496
- fee1,
1497
- fee2,
1498
- slippageBps
1499
- };
1500
- const calls = buildFundBatch(config, vaultAddress, agents, assetAddress, assetDecimals, minOut, swapPath);
1501
- console.log();
1502
- console.log(chalk2.bold(`Batch calls (${calls.length}):`));
1503
- console.log(formatBatch(calls));
1504
- console.log();
1505
- if (opts.writeCalls) {
1506
- const callsJson = calls.map((c) => ({
1507
- target: c.target,
1508
- data: c.data,
1509
- value: c.value.toString()
1510
- }));
1511
- writeFileSync2(opts.writeCalls, JSON.stringify(callsJson, null, 2));
1512
- const settlePath = `${opts.writeCalls}.settle.json`;
1513
- writeFileSync2(settlePath, "[]");
1514
- console.log(chalk2.green(`Execute calls written to: ${opts.writeCalls}`));
1515
- console.log(chalk2.green(`Settlement calls written to: ${settlePath}`));
1516
- console.log();
1517
- console.log(chalk2.dim("Use with: sherwood proposal create --execute-calls <path> --settle-calls <path>"));
1518
- return;
1519
- }
1520
- if (!opts.execute) {
1521
- console.log();
1522
- console.log(chalk2.yellow("Dry run complete. Add --execute to submit on-chain, or --write-calls <path> to export for proposals."));
1523
- return;
1524
- }
1525
- const execSpinner = ora2("Executing batch via vault...").start();
1526
- try {
1527
- const txHash = await executeBatch(calls);
1528
- execSpinner.succeed(`Batch executed: ${txHash}`);
1529
- console.log(chalk2.dim(` ${getExplorerUrl(txHash)}`));
1530
- } catch (err) {
1531
- execSpinner.fail("Execution failed");
1532
- console.error(chalk2.red(err instanceof Error ? err.message : String(err)));
1533
- process.exit(1);
1534
- }
1535
- });
1182
+ const venice = program2.command("venice").description("Venice private inference \u2014 provision API keys, run inference");
1536
1183
  venice.command("provision").description("Self-provision a Venice API key (requires sVVV in wallet)").action(async () => {
1537
1184
  const account = getAccount();
1538
1185
  const client = getPublicClient();
@@ -1547,7 +1194,7 @@ function registerVeniceCommands(program2) {
1547
1194
  if (sVvvBalance === 0n) {
1548
1195
  checkSpinner.fail("No sVVV found in wallet");
1549
1196
  console.log(chalk2.yellow(" Your wallet must hold staked VVV (sVVV) to provision a Venice API key."));
1550
- console.log(chalk2.yellow(" Run 'sherwood venice fund' first to distribute sVVV to agents."));
1197
+ console.log(chalk2.yellow(" Use the VeniceInferenceStrategy via a proposal to distribute sVVV to agents."));
1551
1198
  process.exit(1);
1552
1199
  }
1553
1200
  checkSpinner.succeed(`sVVV balance: ${formatUnits2(sVvvBalance, 18)}`);
@@ -1714,13 +1361,82 @@ ${opts.prompt}`;
1714
1361
  }
1715
1362
 
1716
1363
  // src/commands/allowance.ts
1717
- import { parseUnits as parseUnits6, formatUnits as formatUnits3, isAddress as isAddress3 } from "viem";
1364
+ import { parseUnits as parseUnits4, formatUnits as formatUnits3, isAddress as isAddress3 } from "viem";
1718
1365
  import chalk3 from "chalk";
1719
1366
  import ora3 from "ora";
1720
1367
 
1368
+ // src/lib/quote.ts
1369
+ import { encodeFunctionData as encodeFunctionData5, decodeFunctionResult, concat as concat2, pad, numberToHex } from "viem";
1370
+ async function getQuote(params) {
1371
+ const client = getPublicClient();
1372
+ const calldata = encodeFunctionData5({
1373
+ abi: UNISWAP_QUOTER_V2_ABI,
1374
+ functionName: "quoteExactInputSingle",
1375
+ args: [
1376
+ {
1377
+ tokenIn: params.tokenIn,
1378
+ tokenOut: params.tokenOut,
1379
+ amountIn: params.amountIn,
1380
+ fee: params.fee,
1381
+ sqrtPriceLimitX96: 0n
1382
+ }
1383
+ ]
1384
+ });
1385
+ const { data } = await client.call({
1386
+ to: UNISWAP().QUOTER_V2,
1387
+ data: calldata
1388
+ });
1389
+ if (!data) {
1390
+ throw new Error("Quoter returned no data \u2014 pool may not exist for this pair/fee");
1391
+ }
1392
+ const [amountOut, sqrtPriceX96After, , gasEstimate] = decodeFunctionResult({
1393
+ abi: UNISWAP_QUOTER_V2_ABI,
1394
+ functionName: "quoteExactInputSingle",
1395
+ data
1396
+ });
1397
+ return { amountOut, sqrtPriceX96After, gasEstimate };
1398
+ }
1399
+ function applySlippage(amountOut, slippageBps) {
1400
+ return amountOut * BigInt(1e4 - slippageBps) / 10000n;
1401
+ }
1402
+ function encodeSwapPath(tokens, fees) {
1403
+ if (tokens.length < 2 || fees.length !== tokens.length - 1) {
1404
+ throw new Error("Invalid path: need at least 2 tokens and (tokens-1) fees");
1405
+ }
1406
+ const parts = [];
1407
+ for (let i = 0; i < tokens.length; i++) {
1408
+ parts.push(tokens[i].toLowerCase());
1409
+ if (i < fees.length) {
1410
+ parts.push(pad(numberToHex(fees[i]), { size: 3 }));
1411
+ }
1412
+ }
1413
+ return concat2(parts);
1414
+ }
1415
+ async function getMultiHopQuote(params) {
1416
+ const client = getPublicClient();
1417
+ const calldata = encodeFunctionData5({
1418
+ abi: UNISWAP_QUOTER_V2_ABI,
1419
+ functionName: "quoteExactInput",
1420
+ args: [params.path, params.amountIn]
1421
+ });
1422
+ const { data } = await client.call({
1423
+ to: UNISWAP().QUOTER_V2,
1424
+ data: calldata
1425
+ });
1426
+ if (!data) {
1427
+ throw new Error("Quoter returned no data \u2014 pool may not exist for this path");
1428
+ }
1429
+ const [amountOut, , , gasEstimate] = decodeFunctionResult({
1430
+ abi: UNISWAP_QUOTER_V2_ABI,
1431
+ functionName: "quoteExactInput",
1432
+ data
1433
+ });
1434
+ return { amountOut, sqrtPriceX96After: 0n, gasEstimate };
1435
+ }
1436
+
1721
1437
  // src/strategies/allowance-disburse.ts
1722
- import { encodeFunctionData as encodeFunctionData7, parseUnits as parseUnits5 } from "viem";
1723
- var ERC20_ABI3 = [
1438
+ import { encodeFunctionData as encodeFunctionData6, parseUnits as parseUnits3 } from "viem";
1439
+ var ERC20_ABI2 = [
1724
1440
  {
1725
1441
  name: "approve",
1726
1442
  type: "function",
@@ -1740,7 +1456,7 @@ var ERC20_ABI3 = [
1740
1456
  outputs: [{ name: "", type: "bool" }]
1741
1457
  }
1742
1458
  ];
1743
- var SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI2 = [
1459
+ var SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI = [
1744
1460
  {
1745
1461
  name: "exactInputSingle",
1746
1462
  type: "function",
@@ -1762,7 +1478,7 @@ var SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI2 = [
1762
1478
  outputs: [{ name: "amountOut", type: "uint256" }]
1763
1479
  }
1764
1480
  ];
1765
- var SWAP_ROUTER_EXACT_INPUT_ABI2 = [
1481
+ var SWAP_ROUTER_EXACT_INPUT_ABI = [
1766
1482
  {
1767
1483
  name: "exactInput",
1768
1484
  type: "function",
@@ -1782,15 +1498,15 @@ var SWAP_ROUTER_EXACT_INPUT_ABI2 = [
1782
1498
  }
1783
1499
  ];
1784
1500
  function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDecimals, minUsdc, swapPath) {
1785
- const assetAmount = parseUnits5(config.amount, assetDecimals);
1501
+ const assetAmount = parseUnits3(config.amount, assetDecimals);
1786
1502
  const isUsdc = assetAddress.toLowerCase() === TOKENS().USDC.toLowerCase();
1787
1503
  const isWeth = assetAddress.toLowerCase() === TOKENS().WETH.toLowerCase();
1788
1504
  const calls = [];
1789
1505
  if (!isUsdc) {
1790
1506
  calls.push({
1791
1507
  target: assetAddress,
1792
- data: encodeFunctionData7({
1793
- abi: ERC20_ABI3,
1508
+ data: encodeFunctionData6({
1509
+ abi: ERC20_ABI2,
1794
1510
  functionName: "approve",
1795
1511
  args: [UNISWAP().SWAP_ROUTER, assetAmount]
1796
1512
  }),
@@ -1799,8 +1515,8 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
1799
1515
  if (isWeth) {
1800
1516
  calls.push({
1801
1517
  target: UNISWAP().SWAP_ROUTER,
1802
- data: encodeFunctionData7({
1803
- abi: SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI2,
1518
+ data: encodeFunctionData6({
1519
+ abi: SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI,
1804
1520
  functionName: "exactInputSingle",
1805
1521
  args: [
1806
1522
  {
@@ -1819,8 +1535,8 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
1819
1535
  } else {
1820
1536
  calls.push({
1821
1537
  target: UNISWAP().SWAP_ROUTER,
1822
- data: encodeFunctionData7({
1823
- abi: SWAP_ROUTER_EXACT_INPUT_ABI2,
1538
+ data: encodeFunctionData6({
1539
+ abi: SWAP_ROUTER_EXACT_INPUT_ABI,
1824
1540
  functionName: "exactInput",
1825
1541
  args: [
1826
1542
  {
@@ -1839,8 +1555,8 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
1839
1555
  for (const agent of agents) {
1840
1556
  calls.push({
1841
1557
  target: TOKENS().USDC,
1842
- data: encodeFunctionData7({
1843
- abi: ERC20_ABI3,
1558
+ data: encodeFunctionData6({
1559
+ abi: ERC20_ABI2,
1844
1560
  functionName: "transfer",
1845
1561
  args: [agent, perAgent]
1846
1562
  }),
@@ -1851,7 +1567,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
1851
1567
  }
1852
1568
 
1853
1569
  // src/commands/allowance.ts
1854
- var VALID_FEES2 = [500, 3e3, 1e4];
1570
+ var VALID_FEES = [500, 3e3, 1e4];
1855
1571
  function registerAllowanceCommands(program2) {
1856
1572
  const allowance = program2.command("allowance").description("Disburse vault profits to agent wallets");
1857
1573
  allowance.command("disburse").description("Swap vault profits \u2192 USDC \u2192 distribute to all agent operator wallets").requiredOption("--vault <address>", "Vault address").requiredOption("--amount <amount>", "Deposit token amount to convert & distribute (e.g. 500)").option("--fee <tier>", "Fee tier for asset \u2192 USDC swap (500, 3000, 10000)", "3000").option("--slippage <bps>", "Slippage tolerance in bps", "100").option("--execute", "Execute on-chain (default: simulate only)", false).action(async (opts) => {
@@ -1861,8 +1577,8 @@ function registerAllowanceCommands(program2) {
1861
1577
  process.exit(1);
1862
1578
  }
1863
1579
  const fee = Number(opts.fee);
1864
- if (!VALID_FEES2.includes(fee)) {
1865
- console.error(chalk3.red(`Invalid fee tier. Valid: ${VALID_FEES2.join(", ")}`));
1580
+ if (!VALID_FEES.includes(fee)) {
1581
+ console.error(chalk3.red(`Invalid fee tier. Valid: ${VALID_FEES.join(", ")}`));
1866
1582
  process.exit(1);
1867
1583
  }
1868
1584
  const slippageBps = Number(opts.slippage);
@@ -1895,7 +1611,7 @@ function registerAllowanceCommands(program2) {
1895
1611
  console.error(chalk3.red("No agents registered in vault. Register agents first."));
1896
1612
  process.exit(1);
1897
1613
  }
1898
- const requestedAmount = parseUnits6(opts.amount, assetDecimals);
1614
+ const requestedAmount = parseUnits4(opts.amount, assetDecimals);
1899
1615
  const profit = assetBalance > totalDeposited ? assetBalance - totalDeposited : 0n;
1900
1616
  const isUsdc = assetAddress.toLowerCase() === TOKENS().USDC.toLowerCase();
1901
1617
  const isWeth = assetAddress.toLowerCase() === TOKENS().WETH.toLowerCase();
@@ -2735,7 +2451,7 @@ try {
2735
2451
  var require2 = createRequire(import.meta.url);
2736
2452
  var { version: CLI_VERSION } = require2("../package.json");
2737
2453
  async function loadXmtp() {
2738
- return import("./xmtp-MJ53JW2W.js");
2454
+ return import("./xmtp-ATRMY76G.js");
2739
2455
  }
2740
2456
  async function loadCron() {
2741
2457
  return import("./cron-SKYKVZ6K.js");
@@ -3412,7 +3128,7 @@ var vaultCmd = program.command("vault");
3412
3128
  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)").action(async (opts) => {
3413
3129
  resolveVault(opts);
3414
3130
  const decimals = await getAssetDecimals();
3415
- const amount = parseUnits7(opts.amount, decimals);
3131
+ const amount = parseUnits5(opts.amount, decimals);
3416
3132
  const spinner = ora7(`Depositing ${opts.amount}...`).start();
3417
3133
  try {
3418
3134
  const hash = await deposit(amount);
@@ -3467,7 +3183,7 @@ vaultCmd.command("balance").description("Show LP share balance and asset value")
3467
3183
  var strategy = program.command("strategy").description("Strategy templates \u2014 list, clone, propose");
3468
3184
  registerStrategyTemplateCommands(strategy);
3469
3185
  program.command("providers").description("List available DeFi providers").action(async () => {
3470
- const { MessariProvider, NansenProvider } = await import("./research-IUHVRHR3.js");
3186
+ const { MessariProvider, NansenProvider } = await import("./research-V63URK4C.js");
3471
3187
  const providers = [new MoonwellProvider(), new UniswapProvider(), new MessariProvider(), new NansenProvider()];
3472
3188
  for (const p of providers) {
3473
3189
  const info = p.info();
@@ -3478,7 +3194,7 @@ ${info.name} (${info.type})`);
3478
3194
  }
3479
3195
  });
3480
3196
  try {
3481
- const { registerChatCommands } = await import("./chat-MQPTP4QO.js");
3197
+ const { registerChatCommands } = await import("./chat-7CB4YGGP.js");
3482
3198
  registerChatCommands(program);
3483
3199
  } catch {
3484
3200
  program.command("chat <name> [action] [actionArgs...]").description("Syndicate chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
@@ -3488,14 +3204,14 @@ try {
3488
3204
  process.exit(1);
3489
3205
  });
3490
3206
  }
3491
- var { registerSessionCommands } = await import("./session-CQZ743DX.js");
3207
+ var { registerSessionCommands } = await import("./session-OJX2MILJ.js");
3492
3208
  registerSessionCommands(program);
3493
3209
  registerVeniceCommands(program);
3494
3210
  registerAllowanceCommands(program);
3495
3211
  registerIdentityCommands(program);
3496
3212
  registerProposalCommands(program);
3497
3213
  registerGovernorCommands(program);
3498
- var { registerResearchCommands } = await import("./research-NCY3MCN4.js");
3214
+ var { registerResearchCommands } = await import("./research-MHN7UGIU.js");
3499
3215
  registerResearchCommands(program);
3500
3216
  var configCmd = program.command("config");
3501
3217
  configCmd.command("set").description("Save settings to ~/.sherwood/config.json (persists across sessions)").option("--private-key <key>", "Wallet private key (0x-prefixed)").option("--vault <address>", "Default SyndicateVault address").option("--rpc <url>", "Custom RPC URL for the active --chain network").option("--notify-to <id>", "Destination for cron summaries (Telegram chat ID, phone, etc.)").action((opts) => {