@sherwoodagent/cli 0.40.6 → 0.41.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/{addresses-J4NSZRGB.js → addresses-JBIU5U3T.js} +2 -2
- package/dist/{chat-EYCDCZUA.js → chat-K4LW776Q.js} +5 -5
- package/dist/{chunk-KHTM4GB5.js → chunk-3356CHRT.js} +2 -2
- package/dist/{chunk-FCM6SSL6.js → chunk-5SRJJLHL.js} +2 -2
- package/dist/{chunk-363E34JI.js → chunk-DSH4G5NY.js} +2 -2
- package/dist/{chunk-ZN6CUAX7.js → chunk-VMNB4ARO.js} +19 -5
- package/dist/chunk-VMNB4ARO.js.map +1 -0
- package/dist/{chunk-ITNGXYLB.js → chunk-XENKMSE4.js} +2 -2
- package/dist/{chunk-5OMMVOR6.js → chunk-ZUAYDBG6.js} +2 -2
- package/dist/{eas-MUKSLDIP.js → eas-MFKUDVXP.js} +3 -3
- package/dist/{governor-WA74WFOS.js → governor-Q57YKWO2.js} +3 -3
- package/dist/index.js +570 -285
- package/dist/index.js.map +1 -1
- package/dist/{price-ELYQKRSN.js → price-B63EDNB2.js} +2 -2
- package/dist/{research-HXOXZA4N.js → research-K62TKFLF.js} +3 -3
- package/dist/{session-NL6KF2Q5.js → session-2TBX4UTS.js} +5 -5
- package/dist/{trade-WMPWF6RT.js → trade-S3L2CNV4.js} +6 -6
- package/dist/{xmtp-7CZ5LB5O.js → xmtp-2AZ6H7DH.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-ZN6CUAX7.js.map +0 -1
- /package/dist/{addresses-J4NSZRGB.js.map → addresses-JBIU5U3T.js.map} +0 -0
- /package/dist/{chat-EYCDCZUA.js.map → chat-K4LW776Q.js.map} +0 -0
- /package/dist/{chunk-KHTM4GB5.js.map → chunk-3356CHRT.js.map} +0 -0
- /package/dist/{chunk-FCM6SSL6.js.map → chunk-5SRJJLHL.js.map} +0 -0
- /package/dist/{chunk-363E34JI.js.map → chunk-DSH4G5NY.js.map} +0 -0
- /package/dist/{chunk-ITNGXYLB.js.map → chunk-XENKMSE4.js.map} +0 -0
- /package/dist/{chunk-5OMMVOR6.js.map → chunk-ZUAYDBG6.js.map} +0 -0
- /package/dist/{eas-MUKSLDIP.js.map → eas-MFKUDVXP.js.map} +0 -0
- /package/dist/{governor-WA74WFOS.js.map → governor-Q57YKWO2.js.map} +0 -0
- /package/dist/{price-ELYQKRSN.js.map → price-B63EDNB2.js.map} +0 -0
- /package/dist/{research-HXOXZA4N.js.map → research-K62TKFLF.js.map} +0 -0
- /package/dist/{session-NL6KF2Q5.js.map → session-2TBX4UTS.js.map} +0 -0
- /package/dist/{trade-WMPWF6RT.js.map → trade-S3L2CNV4.js.map} +0 -0
- /package/dist/{xmtp-7CZ5LB5O.js.map → xmtp-2AZ6H7DH.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
getQuote,
|
|
10
10
|
listModels,
|
|
11
11
|
provisionApiKey
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-XENKMSE4.js";
|
|
13
13
|
import {
|
|
14
14
|
createApproval,
|
|
15
15
|
createJoinRequest,
|
|
@@ -19,14 +19,14 @@ import {
|
|
|
19
19
|
queryJoinRequests,
|
|
20
20
|
revokeAttestation,
|
|
21
21
|
stripReferrerPrefix
|
|
22
|
-
} from "./chunk-
|
|
22
|
+
} from "./chunk-5SRJJLHL.js";
|
|
23
23
|
import {
|
|
24
24
|
createSyndicate,
|
|
25
25
|
getActiveSyndicates,
|
|
26
26
|
getSyndicate,
|
|
27
27
|
subdomainExists,
|
|
28
28
|
updateMetadata
|
|
29
|
-
} from "./chunk-
|
|
29
|
+
} from "./chunk-3356CHRT.js";
|
|
30
30
|
import {
|
|
31
31
|
approveDepositor,
|
|
32
32
|
deposit,
|
|
@@ -49,7 +49,7 @@ import {
|
|
|
49
49
|
resolveVaultSyndicate,
|
|
50
50
|
setTextRecord,
|
|
51
51
|
setVaultAddress
|
|
52
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-DSH4G5NY.js";
|
|
53
53
|
import {
|
|
54
54
|
PROPOSAL_STATE,
|
|
55
55
|
PROPOSAL_STATES,
|
|
@@ -81,7 +81,7 @@ import {
|
|
|
81
81
|
setVotingPeriod,
|
|
82
82
|
settleProposal,
|
|
83
83
|
vote
|
|
84
|
-
} from "./chunk-
|
|
84
|
+
} from "./chunk-ZUAYDBG6.js";
|
|
85
85
|
import {
|
|
86
86
|
AERODROME,
|
|
87
87
|
AGENT_REGISTRY,
|
|
@@ -94,11 +94,12 @@ import {
|
|
|
94
94
|
TOKENS,
|
|
95
95
|
UNISWAP,
|
|
96
96
|
VENICE
|
|
97
|
-
} from "./chunk-
|
|
97
|
+
} from "./chunk-VMNB4ARO.js";
|
|
98
98
|
import {
|
|
99
99
|
formatContractError,
|
|
100
100
|
getAccount,
|
|
101
101
|
getPublicClient,
|
|
102
|
+
getWalletClient,
|
|
102
103
|
sendTxWithRetry,
|
|
103
104
|
waitForReceipt,
|
|
104
105
|
writeContractWithRetry
|
|
@@ -154,9 +155,9 @@ import {
|
|
|
154
155
|
import { config as loadDotenv } from "dotenv";
|
|
155
156
|
import { createRequire } from "module";
|
|
156
157
|
import { Command, Option } from "commander";
|
|
157
|
-
import { parseUnits as
|
|
158
|
-
import
|
|
159
|
-
import
|
|
158
|
+
import { parseUnits as parseUnits5, formatUnits as formatUnits5, isAddress as isAddress6 } from "viem";
|
|
159
|
+
import chalk9 from "chalk";
|
|
160
|
+
import ora8 from "ora";
|
|
160
161
|
import { input, confirm, select } from "@inquirer/prompts";
|
|
161
162
|
|
|
162
163
|
// src/providers/moonwell.ts
|
|
@@ -1444,9 +1445,9 @@ function registerStrategyTemplateCommands(strategy2) {
|
|
|
1444
1445
|
console.error(chalk.red("Missing --name, --performance-fee, or --duration. Use --write-calls to skip proposal submission."));
|
|
1445
1446
|
process.exit(1);
|
|
1446
1447
|
}
|
|
1447
|
-
const { propose: propose2 } = await import("./governor-
|
|
1448
|
+
const { propose: propose2 } = await import("./governor-Q57YKWO2.js");
|
|
1448
1449
|
const { pinJSON } = await import("./ipfs-IGXLLJCF.js");
|
|
1449
|
-
const { parseDuration: parseDuration2 } = await import("./governor-
|
|
1450
|
+
const { parseDuration: parseDuration2 } = await import("./governor-Q57YKWO2.js");
|
|
1450
1451
|
const performanceFeeBps = BigInt(opts.performanceFee);
|
|
1451
1452
|
if (performanceFeeBps < 0n || performanceFeeBps > 10000n) {
|
|
1452
1453
|
console.error(chalk.red("--performance-fee must be 0-10000 (basis points)"));
|
|
@@ -1553,7 +1554,7 @@ function registerStrategyTemplateCommands(strategy2) {
|
|
|
1553
1554
|
let prices = [];
|
|
1554
1555
|
let priceSource = null;
|
|
1555
1556
|
try {
|
|
1556
|
-
const { getTokenPricesInAsset } = await import("./price-
|
|
1557
|
+
const { getTokenPricesInAsset } = await import("./price-B63EDNB2.js");
|
|
1557
1558
|
prices = await getTokenPricesInAsset({
|
|
1558
1559
|
tokens: allocations.map((a, i) => ({
|
|
1559
1560
|
token: a.token,
|
|
@@ -1982,7 +1983,7 @@ function registerVeniceCommands(program2) {
|
|
|
1982
1983
|
console.log(chalk2.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
|
|
1983
1984
|
console.log(chalk2.dim(" Saved to ~/.sherwood/config.json"));
|
|
1984
1985
|
try {
|
|
1985
|
-
const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-
|
|
1986
|
+
const { createVeniceProvisionAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-MFKUDVXP.js");
|
|
1986
1987
|
const { uid } = await createVeniceProvisionAttestation(account.address);
|
|
1987
1988
|
if (uid !== "0x0000000000000000000000000000000000000000000000000000000000000000") {
|
|
1988
1989
|
console.log(chalk2.dim(` Attested: ${getEasScanUrl2(uid)}`));
|
|
@@ -2133,7 +2134,7 @@ ${opts.prompt}`;
|
|
|
2133
2134
|
console.log(chalk2.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
|
|
2134
2135
|
}
|
|
2135
2136
|
try {
|
|
2136
|
-
const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-
|
|
2137
|
+
const { createVeniceInferenceAttestation, getEasScanUrl: getEasScanUrl2 } = await import("./eas-MFKUDVXP.js");
|
|
2137
2138
|
const { keccak256, toHex, isAddress: isAddr } = await import("viem");
|
|
2138
2139
|
const { getChainContracts: getChainContracts2 } = await import("./config-LS7FKZL5.js");
|
|
2139
2140
|
const { getChain: getActiveChain } = await import("./network-KSMKPKNL.js");
|
|
@@ -2507,12 +2508,12 @@ function registerIdentityCommands(program2) {
|
|
|
2507
2508
|
identity.command("load").description("Load an existing ERC-8004 agent identity into your config").requiredOption("--id <tokenId>", "Agent token ID to load").action(async (opts) => {
|
|
2508
2509
|
const account = getAccount();
|
|
2509
2510
|
const client = getPublicClient();
|
|
2510
|
-
const
|
|
2511
|
+
const registry2 = AGENT_REGISTRY().IDENTITY_REGISTRY;
|
|
2511
2512
|
const tokenId = Number(opts.id);
|
|
2512
2513
|
const spinner = ora4(`Verifying ownership of agent #${tokenId}...`).start();
|
|
2513
2514
|
try {
|
|
2514
2515
|
const owner = await client.readContract({
|
|
2515
|
-
address:
|
|
2516
|
+
address: registry2,
|
|
2516
2517
|
abi: IDENTITY_REGISTRY_ABI,
|
|
2517
2518
|
functionName: "ownerOf",
|
|
2518
2519
|
args: [BigInt(tokenId)]
|
|
@@ -2533,12 +2534,12 @@ function registerIdentityCommands(program2) {
|
|
|
2533
2534
|
});
|
|
2534
2535
|
identity.command("status").description("Show your agent identity status").action(async () => {
|
|
2535
2536
|
const account = getAccount();
|
|
2536
|
-
const
|
|
2537
|
+
const registry2 = AGENT_REGISTRY().IDENTITY_REGISTRY;
|
|
2537
2538
|
const client = getPublicClient();
|
|
2538
2539
|
const spinner = ora4("Checking identity...").start();
|
|
2539
2540
|
try {
|
|
2540
2541
|
const balance = await client.readContract({
|
|
2541
|
-
address:
|
|
2542
|
+
address: registry2,
|
|
2542
2543
|
abi: IDENTITY_REGISTRY_ABI,
|
|
2543
2544
|
functionName: "balanceOf",
|
|
2544
2545
|
args: [account.address]
|
|
@@ -2549,12 +2550,12 @@ function registerIdentityCommands(program2) {
|
|
|
2549
2550
|
console.log(chalk4.bold("Agent Identity (ERC-8004)"));
|
|
2550
2551
|
console.log(chalk4.dim("\u2500".repeat(40)));
|
|
2551
2552
|
console.log(` Wallet: ${account.address}`);
|
|
2552
|
-
console.log(` Registry: ${
|
|
2553
|
+
console.log(` Registry: ${registry2}`);
|
|
2553
2554
|
console.log(` NFTs owned: ${balance.toString()}`);
|
|
2554
2555
|
if (savedId) {
|
|
2555
2556
|
try {
|
|
2556
2557
|
const owner = await client.readContract({
|
|
2557
|
-
address:
|
|
2558
|
+
address: registry2,
|
|
2558
2559
|
abi: IDENTITY_REGISTRY_ABI,
|
|
2559
2560
|
functionName: "ownerOf",
|
|
2560
2561
|
args: [BigInt(savedId)]
|
|
@@ -3265,7 +3266,7 @@ function printSimulationResult(result, callType) {
|
|
|
3265
3266
|
}
|
|
3266
3267
|
async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
|
|
3267
3268
|
try {
|
|
3268
|
-
const xmtp = await import("./xmtp-
|
|
3269
|
+
const xmtp = await import("./xmtp-2AZ6H7DH.js");
|
|
3269
3270
|
const { getAccount: getAccount2 } = await import("./client-HKAG55PQ.js");
|
|
3270
3271
|
const group = await xmtp.getGroup("", subdomain);
|
|
3271
3272
|
const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
|
|
@@ -4074,6 +4075,289 @@ function registerGovernorCommands(program2) {
|
|
|
4074
4075
|
});
|
|
4075
4076
|
}
|
|
4076
4077
|
|
|
4078
|
+
// src/commands/guardian-delegate.ts
|
|
4079
|
+
import chalk8 from "chalk";
|
|
4080
|
+
import ora7 from "ora";
|
|
4081
|
+
import { formatUnits as formatUnits4, isAddress as isAddress5, parseUnits as parseUnits4 } from "viem";
|
|
4082
|
+
var G4 = chalk8.green;
|
|
4083
|
+
var W4 = chalk8.white;
|
|
4084
|
+
var DIM4 = chalk8.gray;
|
|
4085
|
+
var BOLD4 = chalk8.white.bold;
|
|
4086
|
+
var LABEL4 = chalk8.green.bold;
|
|
4087
|
+
var WARN = chalk8.yellow;
|
|
4088
|
+
var SEP4 = () => console.log(DIM4("\u2500".repeat(60)));
|
|
4089
|
+
var GUARDIAN_REGISTRY_ABI = [
|
|
4090
|
+
// Guardian stake
|
|
4091
|
+
{ type: "function", name: "stakeAsGuardian", inputs: [{ type: "uint256" }, { type: "uint256" }], outputs: [], stateMutability: "nonpayable" },
|
|
4092
|
+
{ type: "function", name: "requestUnstakeGuardian", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
4093
|
+
{ type: "function", name: "cancelUnstakeGuardian", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
4094
|
+
{ type: "function", name: "claimUnstakeGuardian", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
4095
|
+
// Delegation
|
|
4096
|
+
{ type: "function", name: "delegateStake", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [], stateMutability: "nonpayable" },
|
|
4097
|
+
{ type: "function", name: "requestUnstakeDelegation", inputs: [{ type: "address" }], outputs: [], stateMutability: "nonpayable" },
|
|
4098
|
+
{ type: "function", name: "cancelUnstakeDelegation", inputs: [{ type: "address" }], outputs: [], stateMutability: "nonpayable" },
|
|
4099
|
+
{ type: "function", name: "claimUnstakeDelegation", inputs: [{ type: "address" }], outputs: [], stateMutability: "nonpayable" },
|
|
4100
|
+
// Commission
|
|
4101
|
+
{ type: "function", name: "setCommission", inputs: [{ type: "uint256" }], outputs: [], stateMutability: "nonpayable" },
|
|
4102
|
+
// Views
|
|
4103
|
+
{ type: "function", name: "guardianStake", inputs: [{ type: "address" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
4104
|
+
{ type: "function", name: "isActiveGuardian", inputs: [{ type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" },
|
|
4105
|
+
{ type: "function", name: "commissionOf", inputs: [{ type: "address" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
4106
|
+
{ type: "function", name: "delegationOf", inputs: [{ type: "address" }, { type: "address" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
4107
|
+
{ type: "function", name: "delegatedInbound", inputs: [{ type: "address" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
4108
|
+
// Guardian-fee claim (vault asset)
|
|
4109
|
+
{ type: "function", name: "claimProposalReward", inputs: [{ type: "uint256" }], outputs: [], stateMutability: "nonpayable" },
|
|
4110
|
+
{ type: "function", name: "claimDelegatorProposalReward", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [], stateMutability: "nonpayable" }
|
|
4111
|
+
];
|
|
4112
|
+
var ERC20_ABI2 = [
|
|
4113
|
+
{ type: "function", name: "approve", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [{ type: "bool" }], stateMutability: "nonpayable" },
|
|
4114
|
+
{ type: "function", name: "balanceOf", inputs: [{ type: "address" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
4115
|
+
{ type: "function", name: "decimals", inputs: [], outputs: [{ type: "uint8" }], stateMutability: "view" }
|
|
4116
|
+
];
|
|
4117
|
+
function requireAddress(name, addr) {
|
|
4118
|
+
if (addr === "0x0000000000000000000000000000000000000000") {
|
|
4119
|
+
console.error(chalk8.red(`${name} is not deployed on ${getNetwork()}. Update cli/src/lib/addresses.ts after deploy.`));
|
|
4120
|
+
process.exit(1);
|
|
4121
|
+
}
|
|
4122
|
+
return addr;
|
|
4123
|
+
}
|
|
4124
|
+
function registry() {
|
|
4125
|
+
return requireAddress("GUARDIAN_REGISTRY", SHERWOOD().GUARDIAN_REGISTRY);
|
|
4126
|
+
}
|
|
4127
|
+
function wood() {
|
|
4128
|
+
return requireAddress("WOOD_TOKEN", SHERWOOD().WOOD_TOKEN);
|
|
4129
|
+
}
|
|
4130
|
+
async function ensureWoodAllowance(amount) {
|
|
4131
|
+
const wallet = getWalletClient();
|
|
4132
|
+
const pc = getPublicClient();
|
|
4133
|
+
const addr = wallet.account.address;
|
|
4134
|
+
const current = await pc.readContract({
|
|
4135
|
+
address: wood(),
|
|
4136
|
+
abi: [{ type: "function", name: "allowance", inputs: [{ type: "address" }, { type: "address" }], outputs: [{ type: "uint256" }], stateMutability: "view" }],
|
|
4137
|
+
functionName: "allowance",
|
|
4138
|
+
args: [addr, registry()]
|
|
4139
|
+
});
|
|
4140
|
+
if (current >= amount) return;
|
|
4141
|
+
const spinner = ora7("Approving WOOD...").start();
|
|
4142
|
+
try {
|
|
4143
|
+
const hash = await wallet.writeContract({
|
|
4144
|
+
address: wood(),
|
|
4145
|
+
abi: ERC20_ABI2,
|
|
4146
|
+
functionName: "approve",
|
|
4147
|
+
args: [registry(), 2n ** 256n - 1n],
|
|
4148
|
+
chain: null,
|
|
4149
|
+
account: wallet.account
|
|
4150
|
+
});
|
|
4151
|
+
await pc.waitForTransactionReceipt({ hash });
|
|
4152
|
+
spinner.succeed("WOOD approval granted");
|
|
4153
|
+
} catch (err) {
|
|
4154
|
+
spinner.fail("WOOD approval failed");
|
|
4155
|
+
throw err;
|
|
4156
|
+
}
|
|
4157
|
+
}
|
|
4158
|
+
function registerGuardianCommands(program2) {
|
|
4159
|
+
const guardian = program2.command("guardian").description("Guardian staking, delegation, and rewards (V1.5)");
|
|
4160
|
+
guardian.command("status [address]").description("Show guardian stake + commission + active status for an address (default: caller)").action(async (addressArg) => {
|
|
4161
|
+
const pc = getPublicClient();
|
|
4162
|
+
let target;
|
|
4163
|
+
if (addressArg) {
|
|
4164
|
+
if (!isAddress5(addressArg)) {
|
|
4165
|
+
console.error(chalk8.red("Invalid address"));
|
|
4166
|
+
process.exit(1);
|
|
4167
|
+
}
|
|
4168
|
+
target = addressArg;
|
|
4169
|
+
} else {
|
|
4170
|
+
const wallet = getWalletClient();
|
|
4171
|
+
target = wallet.account.address;
|
|
4172
|
+
}
|
|
4173
|
+
const spinner = ora7("Loading...").start();
|
|
4174
|
+
try {
|
|
4175
|
+
const [stake, active, commission] = await Promise.all([
|
|
4176
|
+
pc.readContract({ address: registry(), abi: GUARDIAN_REGISTRY_ABI, functionName: "guardianStake", args: [target] }),
|
|
4177
|
+
pc.readContract({ address: registry(), abi: GUARDIAN_REGISTRY_ABI, functionName: "isActiveGuardian", args: [target] }),
|
|
4178
|
+
pc.readContract({ address: registry(), abi: GUARDIAN_REGISTRY_ABI, functionName: "commissionOf", args: [target] })
|
|
4179
|
+
]);
|
|
4180
|
+
const delegatedIn = await pc.readContract({
|
|
4181
|
+
address: registry(),
|
|
4182
|
+
abi: GUARDIAN_REGISTRY_ABI,
|
|
4183
|
+
functionName: "delegatedInbound",
|
|
4184
|
+
args: [target]
|
|
4185
|
+
});
|
|
4186
|
+
spinner.stop();
|
|
4187
|
+
console.log();
|
|
4188
|
+
console.log(LABEL4(" \u25C6 Guardian Status"));
|
|
4189
|
+
SEP4();
|
|
4190
|
+
console.log(W4(` Address: ${G4(target)}`));
|
|
4191
|
+
console.log(W4(` Active guardian: ${active ? G4("yes") : DIM4("no")}`));
|
|
4192
|
+
console.log(W4(` Own stake: ${BOLD4(formatUnits4(stake, 18))} WOOD`));
|
|
4193
|
+
console.log(W4(` Delegated inbound: ${BOLD4(formatUnits4(delegatedIn, 18))} WOOD`));
|
|
4194
|
+
console.log(W4(` Commission: ${BOLD4(`${Number(commission) / 100}%`)}`));
|
|
4195
|
+
SEP4();
|
|
4196
|
+
console.log();
|
|
4197
|
+
} catch (err) {
|
|
4198
|
+
spinner.fail("Failed to load");
|
|
4199
|
+
console.error(chalk8.red(formatContractError(err)));
|
|
4200
|
+
process.exit(1);
|
|
4201
|
+
}
|
|
4202
|
+
});
|
|
4203
|
+
guardian.command("stake <amount>").description("Stake as a guardian. Amount in WOOD (min = registry.minGuardianStake).").option("--agent-id <id>", "ERC-8004 agent ID to associate (first-stake only)", "0").action(async (amountStr, opts) => {
|
|
4204
|
+
const amount = parseUnits4(amountStr, 18);
|
|
4205
|
+
const agentId = BigInt(opts.agentId);
|
|
4206
|
+
await ensureWoodAllowance(amount);
|
|
4207
|
+
const wallet = getWalletClient();
|
|
4208
|
+
const pc = getPublicClient();
|
|
4209
|
+
const spinner = ora7(`Staking ${amountStr} WOOD...`).start();
|
|
4210
|
+
try {
|
|
4211
|
+
const hash = await wallet.writeContract({
|
|
4212
|
+
address: registry(),
|
|
4213
|
+
abi: GUARDIAN_REGISTRY_ABI,
|
|
4214
|
+
functionName: "stakeAsGuardian",
|
|
4215
|
+
args: [amount, agentId],
|
|
4216
|
+
chain: null,
|
|
4217
|
+
account: wallet.account
|
|
4218
|
+
});
|
|
4219
|
+
await pc.waitForTransactionReceipt({ hash });
|
|
4220
|
+
spinner.succeed(`Staked. Tx: ${hash}`);
|
|
4221
|
+
} catch (err) {
|
|
4222
|
+
spinner.fail("Stake failed");
|
|
4223
|
+
console.error(chalk8.red(formatContractError(err)));
|
|
4224
|
+
process.exit(1);
|
|
4225
|
+
}
|
|
4226
|
+
});
|
|
4227
|
+
guardian.command("unstake <action>").description("Unstake flow: 'request' | 'cancel' | 'claim' (7d cooldown)").action(async (action) => {
|
|
4228
|
+
const fn = { request: "requestUnstakeGuardian", cancel: "cancelUnstakeGuardian", claim: "claimUnstakeGuardian" }[action];
|
|
4229
|
+
if (!fn) {
|
|
4230
|
+
console.error(chalk8.red(`Unknown action '${action}'. Use request | cancel | claim.`));
|
|
4231
|
+
process.exit(1);
|
|
4232
|
+
}
|
|
4233
|
+
const wallet = getWalletClient();
|
|
4234
|
+
const pc = getPublicClient();
|
|
4235
|
+
const spinner = ora7(`${action}...`).start();
|
|
4236
|
+
try {
|
|
4237
|
+
const hash = await wallet.writeContract({ address: registry(), abi: GUARDIAN_REGISTRY_ABI, functionName: fn, args: [], chain: null, account: wallet.account });
|
|
4238
|
+
await pc.waitForTransactionReceipt({ hash });
|
|
4239
|
+
spinner.succeed(`${action} confirmed. Tx: ${hash}`);
|
|
4240
|
+
} catch (err) {
|
|
4241
|
+
spinner.fail(`${action} failed`);
|
|
4242
|
+
console.error(chalk8.red(formatContractError(err)));
|
|
4243
|
+
process.exit(1);
|
|
4244
|
+
}
|
|
4245
|
+
});
|
|
4246
|
+
guardian.command("delegate <delegate> <amount>").description("Delegate WOOD stake to a guardian. Amount in WOOD.").action(async (delegate, amountStr) => {
|
|
4247
|
+
if (!isAddress5(delegate)) {
|
|
4248
|
+
console.error(chalk8.red("Invalid delegate address"));
|
|
4249
|
+
process.exit(1);
|
|
4250
|
+
}
|
|
4251
|
+
const amount = parseUnits4(amountStr, 18);
|
|
4252
|
+
await ensureWoodAllowance(amount);
|
|
4253
|
+
const wallet = getWalletClient();
|
|
4254
|
+
const pc = getPublicClient();
|
|
4255
|
+
const spinner = ora7(`Delegating ${amountStr} WOOD to ${delegate}...`).start();
|
|
4256
|
+
try {
|
|
4257
|
+
const hash = await wallet.writeContract({ address: registry(), abi: GUARDIAN_REGISTRY_ABI, functionName: "delegateStake", args: [delegate, amount], chain: null, account: wallet.account });
|
|
4258
|
+
await pc.waitForTransactionReceipt({ hash });
|
|
4259
|
+
spinner.succeed(`Delegated. Tx: ${hash}`);
|
|
4260
|
+
} catch (err) {
|
|
4261
|
+
spinner.fail("Delegation failed");
|
|
4262
|
+
console.error(chalk8.red(formatContractError(err)));
|
|
4263
|
+
process.exit(1);
|
|
4264
|
+
}
|
|
4265
|
+
});
|
|
4266
|
+
guardian.command("undelegate <delegate> <action>").description("Unstake-delegation flow: 'request' | 'cancel' | 'claim'").action(async (delegate, action) => {
|
|
4267
|
+
if (!isAddress5(delegate)) {
|
|
4268
|
+
console.error(chalk8.red("Invalid delegate address"));
|
|
4269
|
+
process.exit(1);
|
|
4270
|
+
}
|
|
4271
|
+
const fn = { request: "requestUnstakeDelegation", cancel: "cancelUnstakeDelegation", claim: "claimUnstakeDelegation" }[action];
|
|
4272
|
+
if (!fn) {
|
|
4273
|
+
console.error(chalk8.red(`Unknown action '${action}'. Use request | cancel | claim.`));
|
|
4274
|
+
process.exit(1);
|
|
4275
|
+
}
|
|
4276
|
+
const wallet = getWalletClient();
|
|
4277
|
+
const pc = getPublicClient();
|
|
4278
|
+
const spinner = ora7(`${action}...`).start();
|
|
4279
|
+
try {
|
|
4280
|
+
const hash = await wallet.writeContract({ address: registry(), abi: GUARDIAN_REGISTRY_ABI, functionName: fn, args: [delegate], chain: null, account: wallet.account });
|
|
4281
|
+
await pc.waitForTransactionReceipt({ hash });
|
|
4282
|
+
spinner.succeed(`${action} confirmed. Tx: ${hash}`);
|
|
4283
|
+
} catch (err) {
|
|
4284
|
+
spinner.fail(`${action} failed`);
|
|
4285
|
+
console.error(chalk8.red(formatContractError(err)));
|
|
4286
|
+
process.exit(1);
|
|
4287
|
+
}
|
|
4288
|
+
});
|
|
4289
|
+
guardian.command("set-commission <bps>").description("Set your commission rate in bps (0-5000 = 0-50%). Raises capped cumulatively at 500 bps/epoch.").action(async (bpsStr) => {
|
|
4290
|
+
const bps = BigInt(bpsStr);
|
|
4291
|
+
if (bps > 5000n) {
|
|
4292
|
+
console.error(chalk8.red("Commission cannot exceed 5000 bps (50%)"));
|
|
4293
|
+
process.exit(1);
|
|
4294
|
+
}
|
|
4295
|
+
const wallet = getWalletClient();
|
|
4296
|
+
const pc = getPublicClient();
|
|
4297
|
+
const spinner = ora7(`Setting commission to ${Number(bps) / 100}%...`).start();
|
|
4298
|
+
try {
|
|
4299
|
+
const hash = await wallet.writeContract({ address: registry(), abi: GUARDIAN_REGISTRY_ABI, functionName: "setCommission", args: [bps], chain: null, account: wallet.account });
|
|
4300
|
+
await pc.waitForTransactionReceipt({ hash });
|
|
4301
|
+
spinner.succeed(`Commission set. Tx: ${hash}`);
|
|
4302
|
+
} catch (err) {
|
|
4303
|
+
spinner.fail("setCommission failed");
|
|
4304
|
+
console.error(chalk8.red(formatContractError(err)));
|
|
4305
|
+
process.exit(1);
|
|
4306
|
+
}
|
|
4307
|
+
});
|
|
4308
|
+
guardian.command("claim-proposal <proposalId>").description("Claim guardian-fee commission for a settled proposal you voted Approve on (vault asset).").action(async (pidStr) => {
|
|
4309
|
+
const pid = BigInt(pidStr);
|
|
4310
|
+
const wallet = getWalletClient();
|
|
4311
|
+
const pc = getPublicClient();
|
|
4312
|
+
const spinner = ora7("Claiming...").start();
|
|
4313
|
+
try {
|
|
4314
|
+
const hash = await wallet.writeContract({ address: registry(), abi: GUARDIAN_REGISTRY_ABI, functionName: "claimProposalReward", args: [pid], chain: null, account: wallet.account });
|
|
4315
|
+
await pc.waitForTransactionReceipt({ hash });
|
|
4316
|
+
spinner.succeed(`Claimed. Tx: ${hash}`);
|
|
4317
|
+
} catch (err) {
|
|
4318
|
+
spinner.fail("Claim failed");
|
|
4319
|
+
console.error(chalk8.red(formatContractError(err)));
|
|
4320
|
+
process.exit(1);
|
|
4321
|
+
}
|
|
4322
|
+
});
|
|
4323
|
+
guardian.command("claim-delegator <delegate> <proposalId>").description("Claim your delegator share of a delegate's guardian-fee pool for a specific proposal.").action(async (delegate, pidStr) => {
|
|
4324
|
+
if (!isAddress5(delegate)) {
|
|
4325
|
+
console.error(chalk8.red("Invalid delegate address"));
|
|
4326
|
+
process.exit(1);
|
|
4327
|
+
}
|
|
4328
|
+
const pid = BigInt(pidStr);
|
|
4329
|
+
const wallet = getWalletClient();
|
|
4330
|
+
const pc = getPublicClient();
|
|
4331
|
+
const spinner = ora7("Claiming delegator share...").start();
|
|
4332
|
+
try {
|
|
4333
|
+
const hash = await wallet.writeContract({ address: registry(), abi: GUARDIAN_REGISTRY_ABI, functionName: "claimDelegatorProposalReward", args: [delegate, pid], chain: null, account: wallet.account });
|
|
4334
|
+
await pc.waitForTransactionReceipt({ hash });
|
|
4335
|
+
spinner.succeed(`Claimed. Tx: ${hash}`);
|
|
4336
|
+
} catch (err) {
|
|
4337
|
+
spinner.fail("Claim failed");
|
|
4338
|
+
console.error(chalk8.red(formatContractError(err)));
|
|
4339
|
+
process.exit(1);
|
|
4340
|
+
}
|
|
4341
|
+
});
|
|
4342
|
+
guardian.command("claim-wood").description("Open merkl.xyz to claim WOOD epoch block-rewards (off-chain distribution).").action(async () => {
|
|
4343
|
+
const wallet = getWalletClient();
|
|
4344
|
+
const addr = wallet.account.address;
|
|
4345
|
+
const url = `https://merkl.angle.money/user/${addr}`;
|
|
4346
|
+
console.log();
|
|
4347
|
+
console.log(LABEL4(" \u25C6 Merkl Reward Claim"));
|
|
4348
|
+
SEP4();
|
|
4349
|
+
console.log(W4(" WOOD epoch block-rewards are distributed off-chain via Merkl."));
|
|
4350
|
+
console.log(W4(" Open this URL in your browser to view + claim pending rewards:"));
|
|
4351
|
+
console.log();
|
|
4352
|
+
console.log(G4(` ${url}`));
|
|
4353
|
+
console.log();
|
|
4354
|
+
console.log(WARN(" Note: guardian-fee rewards (vault assets) are claimed on-chain"));
|
|
4355
|
+
console.log(WARN(" via `sherwood guardian claim-proposal <pid>`."));
|
|
4356
|
+
SEP4();
|
|
4357
|
+
console.log();
|
|
4358
|
+
});
|
|
4359
|
+
}
|
|
4360
|
+
|
|
4077
4361
|
// src/index.ts
|
|
4078
4362
|
try {
|
|
4079
4363
|
loadDotenv();
|
|
@@ -4082,20 +4366,20 @@ try {
|
|
|
4082
4366
|
var require2 = createRequire(import.meta.url);
|
|
4083
4367
|
var { version: CLI_VERSION } = require2("../package.json");
|
|
4084
4368
|
async function loadXmtp() {
|
|
4085
|
-
return import("./xmtp-
|
|
4369
|
+
return import("./xmtp-2AZ6H7DH.js");
|
|
4086
4370
|
}
|
|
4087
4371
|
async function loadCron() {
|
|
4088
4372
|
return import("./cron-EOULYO3R.js");
|
|
4089
4373
|
}
|
|
4090
|
-
var
|
|
4091
|
-
var
|
|
4092
|
-
var
|
|
4093
|
-
var
|
|
4094
|
-
var
|
|
4095
|
-
var
|
|
4374
|
+
var G5 = chalk9.green;
|
|
4375
|
+
var W5 = chalk9.white;
|
|
4376
|
+
var DIM5 = chalk9.gray;
|
|
4377
|
+
var BOLD5 = chalk9.white.bold;
|
|
4378
|
+
var LABEL5 = chalk9.green.bold;
|
|
4379
|
+
var SEP5 = () => console.log(DIM5("\u2500".repeat(60)));
|
|
4096
4380
|
function validateAddress(value, name) {
|
|
4097
|
-
if (!
|
|
4098
|
-
console.error(
|
|
4381
|
+
if (!isAddress6(value)) {
|
|
4382
|
+
console.error(chalk9.red(`Invalid ${name} address: ${value}`));
|
|
4099
4383
|
process.exit(1);
|
|
4100
4384
|
}
|
|
4101
4385
|
return value;
|
|
@@ -4115,7 +4399,7 @@ program.name("sherwood").description("CLI for agent-managed investment syndicate
|
|
|
4115
4399
|
process.env.ENABLE_TESTNET = "true";
|
|
4116
4400
|
if (network !== "base") {
|
|
4117
4401
|
console.warn(
|
|
4118
|
-
|
|
4402
|
+
chalk9.yellow("[warn] --testnet ignored, --chain takes precedence")
|
|
4119
4403
|
);
|
|
4120
4404
|
} else {
|
|
4121
4405
|
network = "base-sepolia";
|
|
@@ -4123,39 +4407,39 @@ program.name("sherwood").description("CLI for agent-managed investment syndicate
|
|
|
4123
4407
|
}
|
|
4124
4408
|
setNetwork(network);
|
|
4125
4409
|
if (getNetwork() !== "base") {
|
|
4126
|
-
console.log(
|
|
4410
|
+
console.log(chalk9.yellow(`[${getNetwork()}]`));
|
|
4127
4411
|
}
|
|
4128
4412
|
});
|
|
4129
4413
|
var syndicate = program.command("syndicate");
|
|
4130
4414
|
syndicate.command("create").description("Create a new syndicate via the factory (interactive)").option("--subdomain <name>", "ENS subdomain (skip prompt)").option("--name <name>", "Syndicate name (skip prompt)").option("--agent-id <id>", "ERC-8004 agent identity token ID (skip prompt)").option("--asset <symbol-or-address>", "Vault asset: USDC, WETH, or a token address").option("--description <text>", "Short description").option("--metadata-uri <uri>", "Override metadata URI (skip IPFS upload)").option("--open-deposits", "Allow anyone to deposit (no whitelist)").option("--public-chat", "Enable dashboard spectator mode", false).option("-y, --yes", "Skip confirmation prompt (non-interactive mode)", false).action(async (opts) => {
|
|
4131
4415
|
try {
|
|
4132
4416
|
console.log();
|
|
4133
|
-
console.log(
|
|
4134
|
-
|
|
4417
|
+
console.log(LABEL5(" \u25C6 Create Syndicate"));
|
|
4418
|
+
SEP5();
|
|
4135
4419
|
const wallet = getAccount();
|
|
4136
|
-
console.log(
|
|
4137
|
-
console.log(
|
|
4138
|
-
|
|
4420
|
+
console.log(DIM5(` Wallet: ${wallet.address}`));
|
|
4421
|
+
console.log(DIM5(` Network: ${getChain().name}`));
|
|
4422
|
+
SEP5();
|
|
4139
4423
|
const savedAgentId = getAgentId();
|
|
4140
4424
|
const nonInteractive = opts.yes;
|
|
4141
4425
|
const name = opts.name || (nonInteractive ? (() => {
|
|
4142
4426
|
throw new Error("--name is required in non-interactive mode (-y)");
|
|
4143
4427
|
})() : await input({
|
|
4144
|
-
message:
|
|
4428
|
+
message: G5("Syndicate name"),
|
|
4145
4429
|
validate: (v) => v.length > 0 || "Name is required"
|
|
4146
4430
|
}));
|
|
4147
4431
|
const subdomain = opts.subdomain || (nonInteractive ? name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "") : await input({
|
|
4148
|
-
message:
|
|
4432
|
+
message: G5("ENS subdomain"),
|
|
4149
4433
|
default: name.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, ""),
|
|
4150
4434
|
validate: (v) => v.length >= 3 || "Must be at least 3 characters"
|
|
4151
4435
|
}));
|
|
4152
4436
|
const description = opts.description || (nonInteractive ? `${name} \u2014 a Sherwood syndicate` : await input({
|
|
4153
|
-
message:
|
|
4437
|
+
message: G5("Description"),
|
|
4154
4438
|
default: `${name} \u2014 a Sherwood syndicate`
|
|
4155
4439
|
}));
|
|
4156
|
-
const agentIdStr = opts.agentId || (savedAgentId ? nonInteractive ? String(savedAgentId) : await input({ message:
|
|
4440
|
+
const agentIdStr = opts.agentId || (savedAgentId ? nonInteractive ? String(savedAgentId) : await input({ message: G5("Agent ID (ERC-8004)"), default: String(savedAgentId) }) : nonInteractive ? "0" : await input({ message: G5("Agent ID (ERC-8004)"), validate: (v) => /^\d+$/.test(v) || "Must be a number" }));
|
|
4157
4441
|
const openDeposits = opts.openDeposits !== void 0 ? opts.openDeposits : nonInteractive ? true : await confirm({
|
|
4158
|
-
message:
|
|
4442
|
+
message: G5("Open deposits? (anyone can deposit)"),
|
|
4159
4443
|
default: true
|
|
4160
4444
|
});
|
|
4161
4445
|
const ASSET_SYMBOLS = {
|
|
@@ -4171,14 +4455,14 @@ syndicate.command("create").description("Create a new syndicate via the factory
|
|
|
4171
4455
|
asset = opts.asset;
|
|
4172
4456
|
} else {
|
|
4173
4457
|
const supported = Object.keys(ASSET_SYMBOLS).join(", ");
|
|
4174
|
-
console.error(
|
|
4458
|
+
console.error(chalk9.red(` Unknown asset "${opts.asset}". Use a symbol (${supported}) or a 0x address.`));
|
|
4175
4459
|
process.exit(1);
|
|
4176
4460
|
}
|
|
4177
4461
|
} else if (nonInteractive) {
|
|
4178
4462
|
asset = TOKENS().USDC !== "0x0000000000000000000000000000000000000000" ? ASSET_SYMBOLS.USDC : ASSET_SYMBOLS.WETH;
|
|
4179
4463
|
} else {
|
|
4180
4464
|
const assetChoice = await select({
|
|
4181
|
-
message:
|
|
4465
|
+
message: G5("Vault asset (what token do depositors provide?)"),
|
|
4182
4466
|
choices: [
|
|
4183
4467
|
{ name: "USDC", value: "USDC", description: "USD Coin (6 decimals)" },
|
|
4184
4468
|
{ name: "WETH", value: "WETH", description: "Wrapped Ether (18 decimals)" }
|
|
@@ -4193,26 +4477,26 @@ syndicate.command("create").description("Create a new syndicate via the factory
|
|
|
4193
4477
|
]);
|
|
4194
4478
|
const symbol = `sw${assetSymbol}`;
|
|
4195
4479
|
console.log();
|
|
4196
|
-
console.log(
|
|
4197
|
-
|
|
4198
|
-
console.log(
|
|
4199
|
-
console.log(
|
|
4200
|
-
console.log(
|
|
4201
|
-
console.log(
|
|
4202
|
-
console.log(
|
|
4203
|
-
console.log(
|
|
4204
|
-
console.log(
|
|
4205
|
-
|
|
4480
|
+
console.log(LABEL5(" \u25C6 Review"));
|
|
4481
|
+
SEP5();
|
|
4482
|
+
console.log(W5(` Name: ${BOLD5(name)}`));
|
|
4483
|
+
console.log(W5(` ENS: ${G5(`${subdomain}.sherwoodagent.eth`)}`));
|
|
4484
|
+
console.log(W5(` Description: ${DIM5(description)}`));
|
|
4485
|
+
console.log(W5(` Agent ID: #${agentIdStr}`));
|
|
4486
|
+
console.log(W5(` Asset: ${assetSymbol} (${asset.slice(0, 10)}...)`));
|
|
4487
|
+
console.log(W5(` Share token: ${symbol}`));
|
|
4488
|
+
console.log(W5(` Open deposits: ${openDeposits ? G5("yes") : chalk9.red("no (whitelist)")}`));
|
|
4489
|
+
SEP5();
|
|
4206
4490
|
if (!nonInteractive) {
|
|
4207
|
-
const go = await confirm({ message:
|
|
4491
|
+
const go = await confirm({ message: G5("Deploy syndicate?"), default: true });
|
|
4208
4492
|
if (!go) {
|
|
4209
|
-
console.log(
|
|
4493
|
+
console.log(DIM5(" Cancelled."));
|
|
4210
4494
|
return;
|
|
4211
4495
|
}
|
|
4212
4496
|
}
|
|
4213
4497
|
let metadataURI = opts.metadataUri || "";
|
|
4214
4498
|
if (!metadataURI) {
|
|
4215
|
-
const spinner2 =
|
|
4499
|
+
const spinner2 = ora8({ text: W5("Uploading metadata to IPFS..."), color: "green" }).start();
|
|
4216
4500
|
try {
|
|
4217
4501
|
const metadata = {
|
|
4218
4502
|
schema: "sherwood/syndicate/v1",
|
|
@@ -4226,9 +4510,9 @@ syndicate.command("create").description("Create a new syndicate via the factory
|
|
|
4226
4510
|
links: {}
|
|
4227
4511
|
};
|
|
4228
4512
|
metadataURI = await uploadMetadata(metadata);
|
|
4229
|
-
spinner2.succeed(
|
|
4513
|
+
spinner2.succeed(G5(`Metadata pinned: ${DIM5(metadataURI)}`));
|
|
4230
4514
|
} catch (err) {
|
|
4231
|
-
spinner2.warn(
|
|
4515
|
+
spinner2.warn(chalk9.yellow(`IPFS upload failed \u2014 using inline metadata`));
|
|
4232
4516
|
const json = JSON.stringify({ name, description, subdomain, asset: assetSymbol, openDeposits, createdBy: "@sherwoodagent/cli" });
|
|
4233
4517
|
metadataURI = `data:application/json;base64,${Buffer.from(json).toString("base64")}`;
|
|
4234
4518
|
}
|
|
@@ -4238,43 +4522,43 @@ syndicate.command("create").description("Create a new syndicate via the factory
|
|
|
4238
4522
|
const existingInfo = await getSyndicate(existingId);
|
|
4239
4523
|
const callerAddress = getAccount().address.toLowerCase();
|
|
4240
4524
|
if (existingInfo.creator.toLowerCase() !== callerAddress) {
|
|
4241
|
-
console.error(
|
|
4525
|
+
console.error(chalk9.red(`
|
|
4242
4526
|
\u2716 Subdomain '${subdomain}' is already taken by another syndicate.
|
|
4243
4527
|
`));
|
|
4244
4528
|
process.exit(1);
|
|
4245
4529
|
}
|
|
4246
|
-
console.log(
|
|
4530
|
+
console.log(chalk9.yellow(`
|
|
4247
4531
|
\u26A0 Syndicate '${subdomain}' already exists \u2014 resuming setup...
|
|
4248
4532
|
`));
|
|
4249
|
-
const spinner2 =
|
|
4533
|
+
const spinner2 = ora8({ text: W5("Resuming setup..."), color: "green" }).start();
|
|
4250
4534
|
const chainId2 = getChain().id;
|
|
4251
4535
|
setChainContract(chainId2, "vault", existingInfo.vault);
|
|
4252
4536
|
addSyndicate(chainId2, { subdomain, vault: existingInfo.vault, role: "creator" });
|
|
4253
4537
|
setPrimarySyndicate(chainId2, subdomain);
|
|
4254
|
-
spinner2.text =
|
|
4538
|
+
spinner2.text = W5("Checking agent registration...");
|
|
4255
4539
|
try {
|
|
4256
4540
|
setVaultAddress(existingInfo.vault);
|
|
4257
4541
|
const isAlreadyAgent = await isAgent(getAccount().address);
|
|
4258
4542
|
if (!isAlreadyAgent) {
|
|
4259
|
-
spinner2.text =
|
|
4543
|
+
spinner2.text = W5("Registering creator as agent...");
|
|
4260
4544
|
await registerAgent(BigInt(agentIdStr), getAccount().address);
|
|
4261
4545
|
}
|
|
4262
4546
|
} catch {
|
|
4263
4547
|
}
|
|
4264
|
-
spinner2.text =
|
|
4548
|
+
spinner2.text = W5("Checking chat group...");
|
|
4265
4549
|
try {
|
|
4266
4550
|
const xmtp = await loadXmtp();
|
|
4267
4551
|
const xmtpClient = await xmtp.getXmtpClient();
|
|
4268
4552
|
try {
|
|
4269
4553
|
await xmtp.getGroup(xmtpClient, subdomain);
|
|
4270
4554
|
} catch {
|
|
4271
|
-
spinner2.text =
|
|
4555
|
+
spinner2.text = W5("Creating chat group...");
|
|
4272
4556
|
const groupId = await xmtp.createSyndicateGroup(xmtpClient, subdomain, opts.publicChat);
|
|
4273
4557
|
await setTextRecord(subdomain, "xmtpGroupId", groupId, existingInfo.vault);
|
|
4274
4558
|
cacheGroupId(subdomain, groupId);
|
|
4275
4559
|
}
|
|
4276
4560
|
} catch {
|
|
4277
|
-
console.warn(
|
|
4561
|
+
console.warn(chalk9.yellow("\n \u26A0 Could not set up XMTP chat group"));
|
|
4278
4562
|
}
|
|
4279
4563
|
try {
|
|
4280
4564
|
const cron = await loadCron();
|
|
@@ -4283,20 +4567,20 @@ syndicate.command("create").description("Create a new syndicate via the factory
|
|
|
4283
4567
|
}
|
|
4284
4568
|
spinner2.stop();
|
|
4285
4569
|
console.log();
|
|
4286
|
-
console.log(
|
|
4287
|
-
|
|
4288
|
-
console.log(
|
|
4289
|
-
console.log(
|
|
4290
|
-
console.log(
|
|
4291
|
-
console.log(
|
|
4570
|
+
console.log(LABEL5(" \u25C6 Syndicate Setup Resumed"));
|
|
4571
|
+
SEP5();
|
|
4572
|
+
console.log(W5(` ID: ${G5(`#${existingId}`)}`));
|
|
4573
|
+
console.log(W5(` Vault: ${G5(existingInfo.vault)}`));
|
|
4574
|
+
console.log(W5(` ENS: ${G5(`${subdomain}.sherwoodagent.eth`)}`));
|
|
4575
|
+
console.log(W5(` Chat: ${DIM5(`sherwood chat ${subdomain}`)}`));
|
|
4292
4576
|
const refParam2 = getAgentId() ? `?ref=${getAgentId()}` : "";
|
|
4293
|
-
console.log(
|
|
4294
|
-
|
|
4295
|
-
console.log(
|
|
4577
|
+
console.log(W5(` Share: ${G5(`https://sherwood.sh/syndicate/${subdomain}${refParam2}`)}`));
|
|
4578
|
+
SEP5();
|
|
4579
|
+
console.log(G5(" \u2713 Syndicate saved to ~/.sherwood/config.json (set as primary)"));
|
|
4296
4580
|
console.log();
|
|
4297
4581
|
return;
|
|
4298
4582
|
}
|
|
4299
|
-
const spinner =
|
|
4583
|
+
const spinner = ora8({ text: W5("Deploying vault via factory..."), color: "green" }).start();
|
|
4300
4584
|
const result = await createSyndicate({
|
|
4301
4585
|
creatorAgentId: BigInt(agentIdStr),
|
|
4302
4586
|
metadataURI,
|
|
@@ -4311,7 +4595,7 @@ syndicate.command("create").description("Create a new syndicate via the factory
|
|
|
4311
4595
|
addSyndicate(chainId, { subdomain, vault: result.vault, role: "creator" });
|
|
4312
4596
|
setPrimarySyndicate(chainId, subdomain);
|
|
4313
4597
|
await new Promise((r) => setTimeout(r, 2e3));
|
|
4314
|
-
spinner.text =
|
|
4598
|
+
spinner.text = W5("Registering creator as agent...");
|
|
4315
4599
|
try {
|
|
4316
4600
|
setVaultAddress(result.vault);
|
|
4317
4601
|
const creatorAddress = getAccount().address;
|
|
@@ -4321,9 +4605,9 @@ syndicate.command("create").description("Create a new syndicate via the factory
|
|
|
4321
4605
|
// agentAddress = creator EOA (direct execution)
|
|
4322
4606
|
);
|
|
4323
4607
|
} catch (regErr) {
|
|
4324
|
-
console.warn(
|
|
4608
|
+
console.warn(chalk9.yellow("\n \u26A0 Could not auto-register creator as agent \u2014 register manually with `syndicate add`"));
|
|
4325
4609
|
}
|
|
4326
|
-
spinner.text =
|
|
4610
|
+
spinner.text = W5("Setting up chat...");
|
|
4327
4611
|
try {
|
|
4328
4612
|
const xmtp = await loadXmtp();
|
|
4329
4613
|
const xmtpClient = await xmtp.getXmtpClient();
|
|
@@ -4334,42 +4618,42 @@ syndicate.command("create").description("Create a new syndicate via the factory
|
|
|
4334
4618
|
} catch {
|
|
4335
4619
|
}
|
|
4336
4620
|
} catch {
|
|
4337
|
-
console.warn(
|
|
4338
|
-
console.warn(
|
|
4621
|
+
console.warn(chalk9.yellow("\n \u26A0 Could not create XMTP chat group"));
|
|
4622
|
+
console.warn(chalk9.dim(` Recover later with: sherwood chat ${subdomain} init`));
|
|
4339
4623
|
}
|
|
4340
4624
|
try {
|
|
4341
4625
|
const cron = await loadCron();
|
|
4342
4626
|
const cronResult = cron.registerSyndicateCrons(subdomain, isTestnet(), getNotifyTo());
|
|
4343
4627
|
if (cronResult.isOpenClaw && cronResult.registered) {
|
|
4344
|
-
console.log(
|
|
4628
|
+
console.log(G5(" \u2713 Participation crons registered (15m check + hourly summary)"));
|
|
4345
4629
|
} else if (!cronResult.isOpenClaw) {
|
|
4346
|
-
console.log(
|
|
4630
|
+
console.log(DIM5(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
|
|
4347
4631
|
}
|
|
4348
4632
|
} catch {
|
|
4349
4633
|
}
|
|
4350
4634
|
spinner.stop();
|
|
4351
4635
|
console.log();
|
|
4352
|
-
console.log(
|
|
4353
|
-
|
|
4354
|
-
console.log(
|
|
4355
|
-
console.log(
|
|
4356
|
-
console.log(
|
|
4357
|
-
console.log(
|
|
4358
|
-
console.log(
|
|
4359
|
-
console.log(
|
|
4636
|
+
console.log(LABEL5(" \u25C6 Syndicate Created"));
|
|
4637
|
+
SEP5();
|
|
4638
|
+
console.log(W5(` ID: ${G5(`#${result.syndicateId}`)}`));
|
|
4639
|
+
console.log(W5(` Vault: ${G5(result.vault)}`));
|
|
4640
|
+
console.log(W5(` ENS: ${G5(`${subdomain}.sherwoodagent.eth`)}`));
|
|
4641
|
+
console.log(W5(` Metadata: ${DIM5(metadataURI.length > 50 ? metadataURI.slice(0, 50) + "..." : metadataURI)}`));
|
|
4642
|
+
console.log(W5(` Explorer: ${DIM5(getExplorerUrl(result.hash))}`));
|
|
4643
|
+
console.log(W5(` Chat: ${DIM5(`sherwood chat ${subdomain}`)}`));
|
|
4360
4644
|
const refParam = getAgentId() ? `?ref=${getAgentId()}` : "";
|
|
4361
|
-
console.log(
|
|
4362
|
-
|
|
4363
|
-
console.log(
|
|
4645
|
+
console.log(W5(` Share: ${G5(`https://sherwood.sh/syndicate/${subdomain}${refParam}`)}`));
|
|
4646
|
+
SEP5();
|
|
4647
|
+
console.log(G5(" \u2713 Syndicate saved to ~/.sherwood/config.json (set as primary)"));
|
|
4364
4648
|
console.log();
|
|
4365
4649
|
} catch (err) {
|
|
4366
|
-
console.error(
|
|
4650
|
+
console.error(chalk9.red(`
|
|
4367
4651
|
\u2716 ${formatContractError(err)}`));
|
|
4368
4652
|
process.exit(1);
|
|
4369
4653
|
}
|
|
4370
4654
|
});
|
|
4371
4655
|
syndicate.command("list").description("List active syndicates (queries subgraph, falls back to on-chain)").option("--creator <address>", "Filter by creator address").action(async (opts) => {
|
|
4372
|
-
const spinner =
|
|
4656
|
+
const spinner = ora8("Loading syndicates...").start();
|
|
4373
4657
|
try {
|
|
4374
4658
|
let syndicates;
|
|
4375
4659
|
if (process.env.SUBGRAPH_URL) {
|
|
@@ -4388,39 +4672,39 @@ syndicate.command("list").description("List active syndicates (queries subgraph,
|
|
|
4388
4672
|
}
|
|
4389
4673
|
spinner.stop();
|
|
4390
4674
|
if (syndicates.length === 0) {
|
|
4391
|
-
console.log(
|
|
4675
|
+
console.log(chalk9.dim("No active syndicates found."));
|
|
4392
4676
|
return;
|
|
4393
4677
|
}
|
|
4394
4678
|
console.log();
|
|
4395
|
-
console.log(
|
|
4679
|
+
console.log(chalk9.bold(`Active Syndicates (${syndicates.length})`));
|
|
4396
4680
|
if (!process.env.SUBGRAPH_URL) {
|
|
4397
|
-
console.log(
|
|
4681
|
+
console.log(chalk9.dim(" (Set SUBGRAPH_URL for faster indexed queries)"));
|
|
4398
4682
|
}
|
|
4399
|
-
console.log(
|
|
4683
|
+
console.log(chalk9.dim("\u2500".repeat(70)));
|
|
4400
4684
|
for (const s of syndicates) {
|
|
4401
4685
|
const ts = typeof s.createdAt === "string" ? Number(s.createdAt) : Number(s.createdAt);
|
|
4402
4686
|
const date = new Date(ts * 1e3).toLocaleDateString();
|
|
4403
4687
|
const ensName = s.subdomain ? `${s.subdomain}.sherwoodagent.eth` : "";
|
|
4404
|
-
console.log(` #${s.id} ${
|
|
4405
|
-
if (ensName) console.log(` Vault: ${
|
|
4688
|
+
console.log(` #${s.id} ${chalk9.bold(ensName || String(s.vault))}`);
|
|
4689
|
+
if (ensName) console.log(` Vault: ${chalk9.cyan(String(s.vault))}`);
|
|
4406
4690
|
console.log(` Creator: ${s.creator}`);
|
|
4407
4691
|
console.log(` Created: ${date}`);
|
|
4408
4692
|
if (s.totalDeposits) {
|
|
4409
4693
|
console.log(` Deposits: ${s.totalDeposits} USDC`);
|
|
4410
4694
|
}
|
|
4411
4695
|
if (s.metadataURI) {
|
|
4412
|
-
console.log(` Metadata: ${
|
|
4696
|
+
console.log(` Metadata: ${chalk9.dim(s.metadataURI)}`);
|
|
4413
4697
|
}
|
|
4414
4698
|
console.log();
|
|
4415
4699
|
}
|
|
4416
4700
|
} catch (err) {
|
|
4417
4701
|
spinner.fail("Failed to load syndicates");
|
|
4418
|
-
console.error(
|
|
4702
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4419
4703
|
process.exit(1);
|
|
4420
4704
|
}
|
|
4421
4705
|
});
|
|
4422
4706
|
syndicate.command("info").description("Display syndicate details by ID or subdomain").argument("<id>", "Syndicate ID or subdomain name").action(async (idStr) => {
|
|
4423
|
-
const spinner =
|
|
4707
|
+
const spinner = ora8("Loading syndicate info...").start();
|
|
4424
4708
|
try {
|
|
4425
4709
|
let id;
|
|
4426
4710
|
if (/^\d+$/.test(idStr)) {
|
|
@@ -4432,33 +4716,33 @@ syndicate.command("info").description("Display syndicate details by ID or subdom
|
|
|
4432
4716
|
const info = await getSyndicate(id);
|
|
4433
4717
|
spinner.stop();
|
|
4434
4718
|
if (!info.vault || info.vault === "0x0000000000000000000000000000000000000000") {
|
|
4435
|
-
console.log(
|
|
4719
|
+
console.log(chalk9.red(`Syndicate #${id} not found.`));
|
|
4436
4720
|
process.exit(1);
|
|
4437
4721
|
}
|
|
4438
4722
|
const date = new Date(Number(info.createdAt) * 1e3).toLocaleDateString();
|
|
4439
4723
|
console.log();
|
|
4440
|
-
console.log(
|
|
4441
|
-
console.log(
|
|
4724
|
+
console.log(chalk9.bold(`Syndicate #${info.id}`));
|
|
4725
|
+
console.log(chalk9.dim("\u2500".repeat(40)));
|
|
4442
4726
|
if (info.subdomain) {
|
|
4443
|
-
console.log(` ENS: ${
|
|
4727
|
+
console.log(` ENS: ${chalk9.bold(`${info.subdomain}.sherwoodagent.eth`)}`);
|
|
4444
4728
|
}
|
|
4445
|
-
console.log(` Vault: ${
|
|
4729
|
+
console.log(` Vault: ${chalk9.cyan(info.vault)}`);
|
|
4446
4730
|
console.log(` Creator: ${info.creator}`);
|
|
4447
4731
|
console.log(` Created: ${date}`);
|
|
4448
|
-
console.log(` Active: ${info.active ?
|
|
4732
|
+
console.log(` Active: ${info.active ? chalk9.green("yes") : chalk9.red("no")}`);
|
|
4449
4733
|
if (info.metadataURI) {
|
|
4450
|
-
console.log(` Metadata: ${
|
|
4734
|
+
console.log(` Metadata: ${chalk9.dim(info.metadataURI)}`);
|
|
4451
4735
|
}
|
|
4452
4736
|
if (info.subdomain) {
|
|
4453
4737
|
const xmtpGroupId = getCachedGroupId(info.subdomain);
|
|
4454
4738
|
if (xmtpGroupId) {
|
|
4455
|
-
console.log(` XMTP Group: ${
|
|
4739
|
+
console.log(` XMTP Group: ${chalk9.cyan(xmtpGroupId)}`);
|
|
4456
4740
|
}
|
|
4457
4741
|
}
|
|
4458
4742
|
setVaultAddress(info.vault);
|
|
4459
4743
|
const vaultInfo = await getVaultInfo();
|
|
4460
4744
|
console.log();
|
|
4461
|
-
console.log(
|
|
4745
|
+
console.log(chalk9.bold(" Vault Stats"));
|
|
4462
4746
|
console.log(` Total Assets: ${vaultInfo.totalAssets}`);
|
|
4463
4747
|
console.log(` Agent Count: ${vaultInfo.agentCount}`);
|
|
4464
4748
|
console.log(` Redemptions Locked: ${vaultInfo.redemptionsLocked}`);
|
|
@@ -4466,12 +4750,12 @@ syndicate.command("info").description("Display syndicate details by ID or subdom
|
|
|
4466
4750
|
console.log();
|
|
4467
4751
|
} catch (err) {
|
|
4468
4752
|
spinner.fail("Failed to load syndicate info");
|
|
4469
|
-
console.error(
|
|
4753
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4470
4754
|
process.exit(1);
|
|
4471
4755
|
}
|
|
4472
4756
|
});
|
|
4473
4757
|
syndicate.command("update-metadata").description("Update syndicate metadata (creator only)").requiredOption("--id <id>", "Syndicate ID").option("--name <name>", "Syndicate name").option("--description <text>", "Short description").option("--uri <uri>", "Direct metadata URI (skips IPFS upload)").action(async (opts) => {
|
|
4474
|
-
const spinner =
|
|
4758
|
+
const spinner = ora8({ text: W5("Loading syndicate..."), color: "green" }).start();
|
|
4475
4759
|
try {
|
|
4476
4760
|
const syndicateId = BigInt(opts.id);
|
|
4477
4761
|
let metadataURI = opts.uri;
|
|
@@ -4483,7 +4767,7 @@ syndicate.command("update-metadata").description("Update syndicate metadata (cre
|
|
|
4483
4767
|
}
|
|
4484
4768
|
const name = opts.name || info.subdomain;
|
|
4485
4769
|
const description = opts.description || `${name} \u2014 a Sherwood syndicate on ${info.subdomain}.sherwoodagent.eth`;
|
|
4486
|
-
spinner.text =
|
|
4770
|
+
spinner.text = W5("Uploading metadata to IPFS...");
|
|
4487
4771
|
const metadata = {
|
|
4488
4772
|
schema: "sherwood/syndicate/v1",
|
|
4489
4773
|
name,
|
|
@@ -4494,48 +4778,48 @@ syndicate.command("update-metadata").description("Update syndicate metadata (cre
|
|
|
4494
4778
|
links: {}
|
|
4495
4779
|
};
|
|
4496
4780
|
metadataURI = await uploadMetadata(metadata);
|
|
4497
|
-
spinner.text =
|
|
4781
|
+
spinner.text = W5("Updating on-chain metadata...");
|
|
4498
4782
|
}
|
|
4499
4783
|
const hash = await updateMetadata(syndicateId, metadataURI);
|
|
4500
|
-
spinner.succeed(
|
|
4501
|
-
console.log(
|
|
4502
|
-
console.log(
|
|
4784
|
+
spinner.succeed(G5(`Metadata updated`));
|
|
4785
|
+
console.log(DIM5(` IPFS: ${metadataURI}`));
|
|
4786
|
+
console.log(DIM5(` ${getExplorerUrl(hash)}`));
|
|
4503
4787
|
} catch (err) {
|
|
4504
4788
|
spinner.fail("Metadata update failed");
|
|
4505
|
-
console.error(
|
|
4789
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4506
4790
|
process.exit(1);
|
|
4507
4791
|
}
|
|
4508
4792
|
});
|
|
4509
4793
|
syndicate.command("approve-depositor").description("Approve an address to deposit (owner only)").option("--vault <address>", "Vault address (default: from config)").requiredOption("--depositor <address>", "Address to approve").action(async (opts) => {
|
|
4510
4794
|
resolveVault(opts);
|
|
4511
|
-
const spinner =
|
|
4795
|
+
const spinner = ora8("Approving depositor...").start();
|
|
4512
4796
|
try {
|
|
4513
4797
|
const depositor = validateAddress(opts.depositor, "depositor");
|
|
4514
4798
|
const hash = await approveDepositor(depositor);
|
|
4515
4799
|
spinner.succeed(`Depositor approved: ${hash}`);
|
|
4516
|
-
console.log(
|
|
4800
|
+
console.log(chalk9.dim(` ${getExplorerUrl(hash)}`));
|
|
4517
4801
|
} catch (err) {
|
|
4518
4802
|
spinner.fail("Approval failed");
|
|
4519
|
-
console.error(
|
|
4803
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4520
4804
|
process.exit(1);
|
|
4521
4805
|
}
|
|
4522
4806
|
});
|
|
4523
4807
|
syndicate.command("remove-depositor").description("Remove an address from the depositor whitelist (owner only)").option("--vault <address>", "Vault address (default: from config)").requiredOption("--depositor <address>", "Address to remove").action(async (opts) => {
|
|
4524
4808
|
resolveVault(opts);
|
|
4525
|
-
const spinner =
|
|
4809
|
+
const spinner = ora8("Removing depositor...").start();
|
|
4526
4810
|
try {
|
|
4527
4811
|
const depositor = validateAddress(opts.depositor, "depositor");
|
|
4528
4812
|
const hash = await removeDepositor(depositor);
|
|
4529
4813
|
spinner.succeed(`Depositor removed: ${hash}`);
|
|
4530
|
-
console.log(
|
|
4814
|
+
console.log(chalk9.dim(` ${getExplorerUrl(hash)}`));
|
|
4531
4815
|
} catch (err) {
|
|
4532
4816
|
spinner.fail("Removal failed");
|
|
4533
|
-
console.error(
|
|
4817
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4534
4818
|
process.exit(1);
|
|
4535
4819
|
}
|
|
4536
4820
|
});
|
|
4537
4821
|
syndicate.command("add").description("Register an agent on a syndicate vault (creator only)").option("--vault <address>", "Vault address (default: from config)").option("--agent-id <id>", "Agent's ERC-8004 identity token ID (resolved from wallet if omitted)").requiredOption("--wallet <address>", "Agent wallet address").action(async (opts) => {
|
|
4538
|
-
const spinner =
|
|
4822
|
+
const spinner = ora8("Verifying creator...").start();
|
|
4539
4823
|
try {
|
|
4540
4824
|
resolveVault(opts);
|
|
4541
4825
|
const vaultAddress = getVaultAddress();
|
|
@@ -4550,15 +4834,15 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
|
|
|
4550
4834
|
if (opts.agentId) {
|
|
4551
4835
|
agentId = BigInt(opts.agentId);
|
|
4552
4836
|
} else {
|
|
4553
|
-
const { AGENT_REGISTRY: AGENT_REGISTRY2 } = await import("./addresses-
|
|
4554
|
-
const
|
|
4555
|
-
if (
|
|
4837
|
+
const { AGENT_REGISTRY: AGENT_REGISTRY2 } = await import("./addresses-JBIU5U3T.js");
|
|
4838
|
+
const registry2 = AGENT_REGISTRY2().IDENTITY_REGISTRY;
|
|
4839
|
+
if (registry2 === "0x0000000000000000000000000000000000000000") {
|
|
4556
4840
|
agentId = 0n;
|
|
4557
4841
|
} else {
|
|
4558
4842
|
spinner.text = "Looking up ERC-8004 identity from wallet...";
|
|
4559
4843
|
const client = getPublicClient();
|
|
4560
4844
|
const balance = await client.readContract({
|
|
4561
|
-
address:
|
|
4845
|
+
address: registry2,
|
|
4562
4846
|
abi: [{
|
|
4563
4847
|
name: "balanceOf",
|
|
4564
4848
|
type: "function",
|
|
@@ -4571,11 +4855,11 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
|
|
|
4571
4855
|
});
|
|
4572
4856
|
if (balance === 0n) {
|
|
4573
4857
|
spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
|
|
4574
|
-
console.error(
|
|
4858
|
+
console.error(chalk9.dim(" Mint one first: sherwood identity mint --name <name>"));
|
|
4575
4859
|
process.exit(1);
|
|
4576
4860
|
}
|
|
4577
4861
|
const tokenId = await client.readContract({
|
|
4578
|
-
address:
|
|
4862
|
+
address: registry2,
|
|
4579
4863
|
abi: [{
|
|
4580
4864
|
name: "tokenOfOwnerByIndex",
|
|
4581
4865
|
type: "function",
|
|
@@ -4587,13 +4871,13 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
|
|
|
4587
4871
|
args: [agentWallet, 0n]
|
|
4588
4872
|
});
|
|
4589
4873
|
agentId = tokenId;
|
|
4590
|
-
console.log(
|
|
4874
|
+
console.log(chalk9.dim(` Resolved agent ID: #${agentId}`));
|
|
4591
4875
|
}
|
|
4592
4876
|
}
|
|
4593
4877
|
spinner.text = "Registering agent...";
|
|
4594
4878
|
const hash = await registerAgent(agentId, agentWallet);
|
|
4595
4879
|
spinner.succeed(`Agent registered: ${hash}`);
|
|
4596
|
-
console.log(
|
|
4880
|
+
console.log(chalk9.dim(` ${getExplorerUrl(hash)}`));
|
|
4597
4881
|
try {
|
|
4598
4882
|
const xmtp = await loadXmtp();
|
|
4599
4883
|
const xmtpClient = await xmtp.getXmtpClient();
|
|
@@ -4605,14 +4889,14 @@ syndicate.command("add").description("Register an agent on a syndicate vault (cr
|
|
|
4605
4889
|
syndicate: subdomain,
|
|
4606
4890
|
timestamp: Math.floor(Date.now() / 1e3)
|
|
4607
4891
|
});
|
|
4608
|
-
console.log(
|
|
4892
|
+
console.log(chalk9.dim(` Added to chat: ${subdomain}`));
|
|
4609
4893
|
} catch {
|
|
4610
|
-
console.warn(
|
|
4611
|
-
console.warn(
|
|
4894
|
+
console.warn(chalk9.yellow(" \u26A0 Could not add agent to chat group"));
|
|
4895
|
+
console.warn(chalk9.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
|
|
4612
4896
|
}
|
|
4613
4897
|
} catch (err) {
|
|
4614
4898
|
spinner.fail("Registration failed");
|
|
4615
|
-
console.error(
|
|
4899
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4616
4900
|
process.exit(1);
|
|
4617
4901
|
}
|
|
4618
4902
|
});
|
|
@@ -4620,7 +4904,7 @@ syndicate.command("share").description("Print the shareable dashboard URL for yo
|
|
|
4620
4904
|
try {
|
|
4621
4905
|
const subdomain = opts.subdomain || getPrimarySyndicate(getChain().id)?.subdomain;
|
|
4622
4906
|
if (!subdomain) {
|
|
4623
|
-
console.error(
|
|
4907
|
+
console.error(chalk9.red(" No syndicate configured. Pass --subdomain <name> or run 'syndicate create/join' first."));
|
|
4624
4908
|
process.exit(1);
|
|
4625
4909
|
}
|
|
4626
4910
|
const syndicateInfo = await resolveSyndicate(subdomain);
|
|
@@ -4628,13 +4912,13 @@ syndicate.command("share").description("Print the shareable dashboard URL for yo
|
|
|
4628
4912
|
const refParam = agentId ? `?ref=${agentId}` : "";
|
|
4629
4913
|
const dashboardUrl = `https://sherwood.sh/syndicate/${subdomain}${refParam}`;
|
|
4630
4914
|
console.log();
|
|
4631
|
-
console.log(
|
|
4632
|
-
|
|
4633
|
-
console.log(
|
|
4634
|
-
console.log(
|
|
4635
|
-
console.log(
|
|
4636
|
-
console.log(
|
|
4637
|
-
|
|
4915
|
+
console.log(LABEL5(" \u25C6 Share Your Syndicate"));
|
|
4916
|
+
SEP5();
|
|
4917
|
+
console.log(W5(` Dashboard: ${G5(dashboardUrl)}`));
|
|
4918
|
+
console.log(W5(` ENS: ${DIM5(`${subdomain}.sherwoodagent.eth`)}`));
|
|
4919
|
+
console.log(W5(` Vault: ${DIM5(syndicateInfo.vault)}`));
|
|
4920
|
+
console.log(W5(` Join CLI: ${DIM5(`sherwood syndicate join --subdomain ${subdomain}`)}`));
|
|
4921
|
+
SEP5();
|
|
4638
4922
|
try {
|
|
4639
4923
|
const { exec } = await import("child_process");
|
|
4640
4924
|
const platform = (await import("os")).platform();
|
|
@@ -4642,17 +4926,17 @@ syndicate.command("share").description("Print the shareable dashboard URL for yo
|
|
|
4642
4926
|
const proc = exec(cmd);
|
|
4643
4927
|
proc.stdin?.write(dashboardUrl);
|
|
4644
4928
|
proc.stdin?.end();
|
|
4645
|
-
console.log(
|
|
4929
|
+
console.log(G5(" \u2713 Dashboard URL copied to clipboard"));
|
|
4646
4930
|
} catch {
|
|
4647
4931
|
}
|
|
4648
4932
|
console.log();
|
|
4649
4933
|
} catch (err) {
|
|
4650
|
-
console.error(
|
|
4934
|
+
console.error(chalk9.red(` \u2716 ${formatContractError(err)}`));
|
|
4651
4935
|
process.exit(1);
|
|
4652
4936
|
}
|
|
4653
4937
|
});
|
|
4654
4938
|
syndicate.command("join").description("Request to join a syndicate (creates an EAS attestation)").option("--subdomain <name>", "Syndicate subdomain to join").option("--ref <agentId>", "Referrer agent ID (from invite link)").option("--message <text>", "Message to the creator", "Requesting to join your syndicate").action(async (opts) => {
|
|
4655
|
-
const spinner =
|
|
4939
|
+
const spinner = ora8("Resolving syndicate...").start();
|
|
4656
4940
|
try {
|
|
4657
4941
|
const subdomain = opts.subdomain || getPrimarySyndicate(getChain().id)?.subdomain;
|
|
4658
4942
|
if (!subdomain) {
|
|
@@ -4674,17 +4958,17 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
|
|
|
4674
4958
|
try {
|
|
4675
4959
|
const xmtp = await loadXmtp();
|
|
4676
4960
|
await xmtp.getXmtpClient();
|
|
4677
|
-
console.log(
|
|
4961
|
+
console.log(chalk9.dim(" XMTP identity ready"));
|
|
4678
4962
|
} catch {
|
|
4679
|
-
console.warn(
|
|
4963
|
+
console.warn(chalk9.yellow(" \u26A0 Could not initialize XMTP identity"));
|
|
4680
4964
|
}
|
|
4681
4965
|
try {
|
|
4682
4966
|
const cron = await loadCron();
|
|
4683
4967
|
const cronResult = cron.registerSyndicateCrons(subdomain, isTestnet(), getNotifyTo());
|
|
4684
4968
|
if (cronResult.isOpenClaw && cronResult.registered) {
|
|
4685
|
-
console.log(
|
|
4969
|
+
console.log(chalk9.green(" \u2713 Participation crons registered"));
|
|
4686
4970
|
} else if (!cronResult.isOpenClaw) {
|
|
4687
|
-
console.log(
|
|
4971
|
+
console.log(chalk9.dim(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
|
|
4688
4972
|
}
|
|
4689
4973
|
} catch {
|
|
4690
4974
|
}
|
|
@@ -4697,14 +4981,14 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
|
|
|
4697
4981
|
);
|
|
4698
4982
|
if (existingRequest) {
|
|
4699
4983
|
spinner.succeed("You already have a pending join request for this syndicate");
|
|
4700
|
-
console.log(
|
|
4701
|
-
console.log(
|
|
4984
|
+
console.log(chalk9.dim(` Attestation: ${existingRequest.uid}`));
|
|
4985
|
+
console.log(chalk9.dim(` Submitted: ${new Date(existingRequest.time * 1e3).toLocaleString()}`));
|
|
4702
4986
|
try {
|
|
4703
4987
|
const xmtp = await loadXmtp();
|
|
4704
4988
|
await xmtp.getXmtpClient();
|
|
4705
|
-
console.log(
|
|
4989
|
+
console.log(chalk9.dim(" XMTP identity ready"));
|
|
4706
4990
|
} catch {
|
|
4707
|
-
console.warn(
|
|
4991
|
+
console.warn(chalk9.yellow(" \u26A0 Could not initialize XMTP identity"));
|
|
4708
4992
|
}
|
|
4709
4993
|
return;
|
|
4710
4994
|
}
|
|
@@ -4725,7 +5009,7 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
|
|
|
4725
5009
|
spinner.succeed("Join request created (XMTP identity ready)");
|
|
4726
5010
|
} catch {
|
|
4727
5011
|
spinner.succeed("Join request created");
|
|
4728
|
-
console.warn(
|
|
5012
|
+
console.warn(chalk9.yellow(" \u26A0 Could not initialize XMTP identity \u2014 creator may not be able to auto-add you to chat"));
|
|
4729
5013
|
}
|
|
4730
5014
|
addSyndicate(getChain().id, { subdomain, vault: syndicate2.vault, role: "agent" });
|
|
4731
5015
|
setPrimarySyndicate(getChain().id, subdomain);
|
|
@@ -4733,34 +5017,34 @@ syndicate.command("join").description("Request to join a syndicate (creates an E
|
|
|
4733
5017
|
const cron = await loadCron();
|
|
4734
5018
|
const cronResult = cron.registerSyndicateCrons(subdomain, isTestnet(), getNotifyTo());
|
|
4735
5019
|
if (cronResult.isOpenClaw && cronResult.registered) {
|
|
4736
|
-
console.log(
|
|
5020
|
+
console.log(G5(" \u2713 Participation crons registered (will activate after approval)"));
|
|
4737
5021
|
} else if (!cronResult.isOpenClaw) {
|
|
4738
|
-
console.log(
|
|
5022
|
+
console.log(DIM5(" Tip: Set up a scheduled process to run `sherwood session check " + subdomain + "` periodically"));
|
|
4739
5023
|
}
|
|
4740
5024
|
} catch {
|
|
4741
5025
|
}
|
|
4742
5026
|
console.log();
|
|
4743
|
-
console.log(
|
|
4744
|
-
|
|
4745
|
-
console.log(
|
|
4746
|
-
console.log(
|
|
4747
|
-
console.log(
|
|
4748
|
-
console.log(
|
|
4749
|
-
console.log(
|
|
4750
|
-
console.log(
|
|
4751
|
-
|
|
4752
|
-
console.log(
|
|
4753
|
-
console.log(
|
|
4754
|
-
console.log(
|
|
5027
|
+
console.log(LABEL5(" \u25C6 Join Request Submitted"));
|
|
5028
|
+
SEP5();
|
|
5029
|
+
console.log(W5(` Syndicate: ${G5(`${subdomain}.sherwoodagent.eth`)}`));
|
|
5030
|
+
console.log(W5(` Agent ID: #${agentId}`));
|
|
5031
|
+
console.log(W5(` Creator: ${DIM5(syndicate2.creator)}`));
|
|
5032
|
+
console.log(W5(` Attestation: ${DIM5(uid)}`));
|
|
5033
|
+
console.log(W5(` EAS Scan: ${DIM5(getEasScanUrl(uid))}`));
|
|
5034
|
+
console.log(W5(` Explorer: ${DIM5(getExplorerUrl(hash))}`));
|
|
5035
|
+
SEP5();
|
|
5036
|
+
console.log(G5(" \u2713 Syndicate saved to ~/.sherwood/config.json (set as primary)"));
|
|
5037
|
+
console.log(G5(" \u2713 The creator can review with:"));
|
|
5038
|
+
console.log(DIM5(` sherwood syndicate requests --subdomain ${subdomain}`));
|
|
4755
5039
|
console.log();
|
|
4756
5040
|
} catch (err) {
|
|
4757
5041
|
spinner.fail("Join request failed");
|
|
4758
|
-
console.error(
|
|
5042
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4759
5043
|
process.exit(1);
|
|
4760
5044
|
}
|
|
4761
5045
|
});
|
|
4762
5046
|
syndicate.command("requests").description("View pending join requests for a syndicate (creator only)").option("--subdomain <name>", "Syndicate subdomain").option("--vault <address>", "Vault address (default: from config)").action(async (opts) => {
|
|
4763
|
-
const spinner =
|
|
5047
|
+
const spinner = ora8("Loading join requests...").start();
|
|
4764
5048
|
try {
|
|
4765
5049
|
let creatorAddress;
|
|
4766
5050
|
let subdomain;
|
|
@@ -4796,39 +5080,39 @@ syndicate.command("requests").description("View pending join requests for a synd
|
|
|
4796
5080
|
);
|
|
4797
5081
|
spinner.stop();
|
|
4798
5082
|
if (requests.length === 0) {
|
|
4799
|
-
console.log(
|
|
5083
|
+
console.log(DIM5("\n No pending join requests.\n"));
|
|
4800
5084
|
return;
|
|
4801
5085
|
}
|
|
4802
5086
|
console.log();
|
|
4803
|
-
console.log(
|
|
4804
|
-
|
|
5087
|
+
console.log(LABEL5(` \u25C6 Pending Join Requests (${requests.length})`));
|
|
5088
|
+
SEP5();
|
|
4805
5089
|
for (let i = 0; i < requests.length; i++) {
|
|
4806
5090
|
const req = requests[i];
|
|
4807
5091
|
const date = new Date(req.time * 1e3).toLocaleString();
|
|
4808
5092
|
const referrer = parseReferrer(req.decoded.message);
|
|
4809
5093
|
const cleanMessage = stripReferrerPrefix(req.decoded.message);
|
|
4810
|
-
console.log(
|
|
4811
|
-
console.log(
|
|
5094
|
+
console.log(W5(` ${i + 1}. Agent #${req.decoded.agentId} ${DIM5(`(${req.attester})`)}`));
|
|
5095
|
+
console.log(DIM5(` Message: "${cleanMessage}"`));
|
|
4812
5096
|
if (referrer !== null) {
|
|
4813
|
-
console.log(
|
|
5097
|
+
console.log(G5(` Referred by: Agent #${referrer}`));
|
|
4814
5098
|
}
|
|
4815
|
-
console.log(
|
|
4816
|
-
console.log(
|
|
5099
|
+
console.log(DIM5(` Requested: ${date}`));
|
|
5100
|
+
console.log(DIM5(` Attestation: ${req.uid}`));
|
|
4817
5101
|
console.log();
|
|
4818
5102
|
}
|
|
4819
|
-
console.log(
|
|
4820
|
-
console.log(
|
|
4821
|
-
console.log(
|
|
4822
|
-
console.log(
|
|
5103
|
+
console.log(G5(" To approve:"));
|
|
5104
|
+
console.log(DIM5(` sherwood syndicate approve --agent-id <id> --wallet <addr>`));
|
|
5105
|
+
console.log(G5(" To reject:"));
|
|
5106
|
+
console.log(DIM5(` sherwood syndicate reject --attestation <uid>`));
|
|
4823
5107
|
console.log();
|
|
4824
5108
|
} catch (err) {
|
|
4825
5109
|
spinner.fail("Failed to load requests");
|
|
4826
|
-
console.error(
|
|
5110
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4827
5111
|
process.exit(1);
|
|
4828
5112
|
}
|
|
4829
5113
|
});
|
|
4830
5114
|
syndicate.command("approve").description("Approve an agent join request (registers agent + creates EAS approval)").option("--vault <address>", "Vault address (default: from config)").option("--subdomain <name>", "Syndicate subdomain (alternative to --vault)").requiredOption("--agent-id <id>", "Agent's ERC-8004 identity token ID").requiredOption("--wallet <address>", "Agent wallet address").action(async (opts) => {
|
|
4831
|
-
const spinner =
|
|
5115
|
+
const spinner = ora8("Verifying creator...").start();
|
|
4832
5116
|
try {
|
|
4833
5117
|
const approveSubdomain = opts.subdomain || getPrimarySyndicate(getChain().id)?.subdomain;
|
|
4834
5118
|
if (approveSubdomain && !opts.vault) {
|
|
@@ -4853,11 +5137,11 @@ syndicate.command("approve").description("Approve an agent join request (registe
|
|
|
4853
5137
|
agentWallet
|
|
4854
5138
|
);
|
|
4855
5139
|
agentWasRegistered = true;
|
|
4856
|
-
console.log(
|
|
5140
|
+
console.log(DIM5(` Agent registered: ${getExplorerUrl(regHash)}`));
|
|
4857
5141
|
} catch (regErr) {
|
|
4858
5142
|
const msg = regErr instanceof Error ? regErr.message : String(regErr);
|
|
4859
5143
|
if (msg.includes("0xe098d3ee") || msg.includes("AgentAlreadyRegistered")) {
|
|
4860
|
-
console.log(
|
|
5144
|
+
console.log(DIM5(" Agent already registered on vault \u2014 skipping"));
|
|
4861
5145
|
} else {
|
|
4862
5146
|
throw regErr;
|
|
4863
5147
|
}
|
|
@@ -4873,7 +5157,7 @@ syndicate.command("approve").description("Approve an agent join request (registe
|
|
|
4873
5157
|
let approvalUid;
|
|
4874
5158
|
if (alreadyApproved) {
|
|
4875
5159
|
approvalUid = alreadyApproved.uid;
|
|
4876
|
-
console.log(
|
|
5160
|
+
console.log(DIM5(` Approval attestation already exists \u2014 skipping`));
|
|
4877
5161
|
} else {
|
|
4878
5162
|
spinner.text = "Creating approval attestation...";
|
|
4879
5163
|
const result = await createApproval(
|
|
@@ -4896,48 +5180,48 @@ syndicate.command("approve").description("Approve an agent join request (registe
|
|
|
4896
5180
|
syndicate: subdomain,
|
|
4897
5181
|
timestamp: Math.floor(Date.now() / 1e3)
|
|
4898
5182
|
});
|
|
4899
|
-
console.log(
|
|
5183
|
+
console.log(DIM5(` Added to chat: ${subdomain}`));
|
|
4900
5184
|
} catch {
|
|
4901
|
-
console.warn(
|
|
4902
|
-
console.warn(
|
|
5185
|
+
console.warn(chalk9.yellow(" \u26A0 Could not add agent to chat group"));
|
|
5186
|
+
console.warn(chalk9.dim(` If no group exists, run: sherwood chat ${subdomain} init`));
|
|
4903
5187
|
}
|
|
4904
5188
|
spinner.succeed("Agent approved and registered");
|
|
4905
5189
|
console.log();
|
|
4906
|
-
console.log(
|
|
4907
|
-
|
|
4908
|
-
console.log(
|
|
4909
|
-
console.log(
|
|
4910
|
-
console.log(
|
|
4911
|
-
console.log(
|
|
4912
|
-
|
|
5190
|
+
console.log(LABEL5(" \u25C6 Agent Approved"));
|
|
5191
|
+
SEP5();
|
|
5192
|
+
console.log(W5(` Agent ID: #${opts.agentId}`));
|
|
5193
|
+
console.log(W5(` Wallet: ${G5(opts.wallet)}`));
|
|
5194
|
+
console.log(W5(` Approval: ${DIM5(approvalUid)}`));
|
|
5195
|
+
console.log(W5(` EAS Scan: ${DIM5(getEasScanUrl(approvalUid))}`));
|
|
5196
|
+
SEP5();
|
|
4913
5197
|
} catch (err) {
|
|
4914
5198
|
spinner.fail("Approval failed");
|
|
4915
|
-
console.error(
|
|
5199
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4916
5200
|
process.exit(1);
|
|
4917
5201
|
}
|
|
4918
5202
|
});
|
|
4919
5203
|
syndicate.command("reject").description("Reject a join request by revoking its attestation").requiredOption("--attestation <uid>", "Join request attestation UID to revoke").action(async (opts) => {
|
|
4920
|
-
const spinner =
|
|
5204
|
+
const spinner = ora8("Revoking attestation...").start();
|
|
4921
5205
|
try {
|
|
4922
5206
|
const hash = await revokeAttestation(
|
|
4923
5207
|
EAS_SCHEMAS().SYNDICATE_JOIN_REQUEST,
|
|
4924
5208
|
opts.attestation
|
|
4925
5209
|
);
|
|
4926
5210
|
spinner.succeed("Join request rejected");
|
|
4927
|
-
console.log(
|
|
5211
|
+
console.log(DIM5(` ${getExplorerUrl(hash)}`));
|
|
4928
5212
|
} catch (err) {
|
|
4929
5213
|
spinner.fail("Rejection failed");
|
|
4930
|
-
console.error(
|
|
5214
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
4931
5215
|
process.exit(1);
|
|
4932
5216
|
}
|
|
4933
5217
|
});
|
|
4934
5218
|
syndicate.command("leave").description("Leave a syndicate \u2014 removes participation crons and session state").option("--subdomain <name>", "Syndicate subdomain to leave").action(async (opts) => {
|
|
4935
5219
|
const subdomain = opts.subdomain || getPrimarySyndicate(getChain().id)?.subdomain;
|
|
4936
5220
|
if (!subdomain) {
|
|
4937
|
-
console.error(
|
|
5221
|
+
console.error(chalk9.red(" No syndicate configured. Pass --subdomain <name>."));
|
|
4938
5222
|
process.exit(1);
|
|
4939
5223
|
}
|
|
4940
|
-
const spinner =
|
|
5224
|
+
const spinner = ora8("Cleaning up...").start();
|
|
4941
5225
|
try {
|
|
4942
5226
|
let cronsRemoved = false;
|
|
4943
5227
|
try {
|
|
@@ -4950,17 +5234,17 @@ syndicate.command("leave").description("Leave a syndicate \u2014 removes partici
|
|
|
4950
5234
|
resetSession(subdomain);
|
|
4951
5235
|
spinner.succeed("Left syndicate");
|
|
4952
5236
|
if (cronsRemoved) {
|
|
4953
|
-
console.log(
|
|
5237
|
+
console.log(G5(" \u2713 Participation crons removed"));
|
|
4954
5238
|
}
|
|
4955
|
-
console.log(
|
|
5239
|
+
console.log(G5(" \u2713 Session state cleared"));
|
|
4956
5240
|
console.log();
|
|
4957
|
-
console.log(
|
|
4958
|
-
console.log(
|
|
4959
|
-
console.log(
|
|
5241
|
+
console.log(chalk9.dim(" Note: This does not remove you on-chain. To exit your position:"));
|
|
5242
|
+
console.log(chalk9.dim(" sherwood vault balance \u2014 check your LP share balance"));
|
|
5243
|
+
console.log(chalk9.dim(" Redeem shares via the vault contract or dashboard"));
|
|
4960
5244
|
console.log();
|
|
4961
5245
|
} catch (err) {
|
|
4962
5246
|
spinner.fail("Leave failed");
|
|
4963
|
-
console.error(
|
|
5247
|
+
console.error(chalk9.red(err instanceof Error ? err.message : String(err)));
|
|
4964
5248
|
process.exit(1);
|
|
4965
5249
|
}
|
|
4966
5250
|
});
|
|
@@ -4971,21 +5255,21 @@ syndicate.command("set-primary").description("Set the active syndicate for CLI c
|
|
|
4971
5255
|
if (!opts.subdomain && !opts.vault) {
|
|
4972
5256
|
const primary = getPrimarySyndicate(chainId);
|
|
4973
5257
|
if (memberships.length === 0) {
|
|
4974
|
-
console.log(
|
|
5258
|
+
console.log(DIM5("\n No syndicates saved. Create or join one first.\n"));
|
|
4975
5259
|
return;
|
|
4976
5260
|
}
|
|
4977
5261
|
console.log();
|
|
4978
|
-
console.log(
|
|
4979
|
-
|
|
5262
|
+
console.log(LABEL5(" \u25C6 Your Syndicates"));
|
|
5263
|
+
SEP5();
|
|
4980
5264
|
for (const m of memberships) {
|
|
4981
5265
|
const isPrimary = primary?.subdomain === m.subdomain;
|
|
4982
|
-
const marker = isPrimary ?
|
|
4983
|
-
console.log(
|
|
4984
|
-
console.log(
|
|
5266
|
+
const marker = isPrimary ? G5(" \u2605") : "";
|
|
5267
|
+
console.log(W5(` ${m.subdomain}.sherwoodagent.eth${marker} ${DIM5(`(${m.role})`)}`));
|
|
5268
|
+
console.log(DIM5(` vault: ${m.vault}`));
|
|
4985
5269
|
}
|
|
4986
|
-
|
|
5270
|
+
SEP5();
|
|
4987
5271
|
if (memberships.length > 1) {
|
|
4988
|
-
console.log(
|
|
5272
|
+
console.log(DIM5(" Switch with: sherwood syndicate set-primary --subdomain <name>"));
|
|
4989
5273
|
}
|
|
4990
5274
|
console.log();
|
|
4991
5275
|
return;
|
|
@@ -5011,15 +5295,15 @@ syndicate.command("set-primary").description("Set the active syndicate for CLI c
|
|
|
5011
5295
|
}
|
|
5012
5296
|
}
|
|
5013
5297
|
if (!target) {
|
|
5014
|
-
console.error(
|
|
5298
|
+
console.error(chalk9.red(" Could not resolve syndicate. Pass --subdomain or --vault."));
|
|
5015
5299
|
process.exit(1);
|
|
5016
5300
|
}
|
|
5017
5301
|
setPrimarySyndicate(chainId, target);
|
|
5018
|
-
console.log(
|
|
5302
|
+
console.log(G5(`
|
|
5019
5303
|
\u2713 Primary syndicate set to ${target}.sherwoodagent.eth
|
|
5020
5304
|
`));
|
|
5021
5305
|
} catch (err) {
|
|
5022
|
-
console.error(
|
|
5306
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
5023
5307
|
process.exit(1);
|
|
5024
5308
|
}
|
|
5025
5309
|
});
|
|
@@ -5027,18 +5311,18 @@ var vaultCmd = program.command("vault");
|
|
|
5027
5311
|
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) => {
|
|
5028
5312
|
resolveVault(opts);
|
|
5029
5313
|
const decimals = await getAssetDecimals();
|
|
5030
|
-
const amount =
|
|
5314
|
+
const amount = parseUnits5(opts.amount, decimals);
|
|
5031
5315
|
try {
|
|
5032
5316
|
if (!opts.useEth) {
|
|
5033
5317
|
await preflightDeposit(amount);
|
|
5034
5318
|
}
|
|
5035
5319
|
} catch (err) {
|
|
5036
|
-
console.error(
|
|
5320
|
+
console.error(chalk9.red(`
|
|
5037
5321
|
\u2716 ${err instanceof Error ? err.message : String(err)}
|
|
5038
5322
|
`));
|
|
5039
5323
|
process.exit(1);
|
|
5040
5324
|
}
|
|
5041
|
-
const spinner =
|
|
5325
|
+
const spinner = ora8(`Depositing ${opts.amount}...`).start();
|
|
5042
5326
|
try {
|
|
5043
5327
|
let hash;
|
|
5044
5328
|
if (opts.useEth) {
|
|
@@ -5048,22 +5332,22 @@ vaultCmd.command("deposit").description("Deposit into a vault").option("--vault
|
|
|
5048
5332
|
hash = await deposit(amount);
|
|
5049
5333
|
}
|
|
5050
5334
|
spinner.succeed(`Deposited: ${hash}`);
|
|
5051
|
-
console.log(
|
|
5335
|
+
console.log(chalk9.dim(` ${getExplorerUrl(hash)}`));
|
|
5052
5336
|
} catch (err) {
|
|
5053
5337
|
spinner.fail("Deposit failed");
|
|
5054
|
-
console.error(
|
|
5338
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
5055
5339
|
process.exit(1);
|
|
5056
5340
|
}
|
|
5057
5341
|
});
|
|
5058
5342
|
vaultCmd.command("info").description("Display vault state").option("--vault <address>", "Vault address (default: from config)").action(async (opts) => {
|
|
5059
5343
|
resolveVault(opts);
|
|
5060
|
-
const spinner =
|
|
5344
|
+
const spinner = ora8("Loading vault info...").start();
|
|
5061
5345
|
try {
|
|
5062
5346
|
const info = await getVaultInfo();
|
|
5063
5347
|
spinner.stop();
|
|
5064
5348
|
console.log();
|
|
5065
|
-
console.log(
|
|
5066
|
-
console.log(
|
|
5349
|
+
console.log(chalk9.bold("Vault Info"));
|
|
5350
|
+
console.log(chalk9.dim("\u2500".repeat(40)));
|
|
5067
5351
|
console.log(` Address: ${info.address}`);
|
|
5068
5352
|
console.log(` Total Assets: ${info.totalAssets}`);
|
|
5069
5353
|
console.log(` Agent Count: ${info.agentCount}`);
|
|
@@ -5072,26 +5356,26 @@ vaultCmd.command("info").description("Display vault state").option("--vault <add
|
|
|
5072
5356
|
console.log();
|
|
5073
5357
|
} catch (err) {
|
|
5074
5358
|
spinner.fail("Failed to load vault info");
|
|
5075
|
-
console.error(
|
|
5359
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
5076
5360
|
process.exit(1);
|
|
5077
5361
|
}
|
|
5078
5362
|
});
|
|
5079
5363
|
vaultCmd.command("balance").description("Show LP share balance and asset value").option("--vault <address>", "Vault address (default: from config)").option("--address <address>", "Address to check (default: your wallet)").action(async (opts) => {
|
|
5080
5364
|
resolveVault(opts);
|
|
5081
|
-
const spinner =
|
|
5365
|
+
const spinner = ora8("Loading balance...").start();
|
|
5082
5366
|
try {
|
|
5083
5367
|
const balance = await getBalance(opts.address);
|
|
5084
5368
|
spinner.stop();
|
|
5085
5369
|
console.log();
|
|
5086
|
-
console.log(
|
|
5087
|
-
console.log(
|
|
5370
|
+
console.log(chalk9.bold("LP Position"));
|
|
5371
|
+
console.log(chalk9.dim("\u2500".repeat(40)));
|
|
5088
5372
|
console.log(` Shares: ${balance.shares.toString()}`);
|
|
5089
5373
|
console.log(` Asset Value: ${balance.assetsValue}`);
|
|
5090
5374
|
console.log(` % of Vault: ${balance.percentOfVault}`);
|
|
5091
5375
|
console.log();
|
|
5092
5376
|
} catch (err) {
|
|
5093
5377
|
spinner.fail("Failed to load balance");
|
|
5094
|
-
console.error(
|
|
5378
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
5095
5379
|
process.exit(1);
|
|
5096
5380
|
}
|
|
5097
5381
|
});
|
|
@@ -5102,22 +5386,22 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
|
|
|
5102
5386
|
let shares;
|
|
5103
5387
|
try {
|
|
5104
5388
|
if (opts.shares) {
|
|
5105
|
-
shares =
|
|
5389
|
+
shares = parseUnits5(opts.shares, shareDecimals);
|
|
5106
5390
|
} else {
|
|
5107
5391
|
shares = await getShareBalance();
|
|
5108
5392
|
if (shares === 0n) {
|
|
5109
|
-
console.error(
|
|
5393
|
+
console.error(chalk9.red("\n \u2716 No shares to redeem.\n"));
|
|
5110
5394
|
process.exit(1);
|
|
5111
5395
|
}
|
|
5112
5396
|
}
|
|
5113
5397
|
} catch (err) {
|
|
5114
|
-
console.error(
|
|
5398
|
+
console.error(chalk9.red(`
|
|
5115
5399
|
\u2716 ${err instanceof Error ? err.message : String(err)}
|
|
5116
5400
|
`));
|
|
5117
5401
|
process.exit(1);
|
|
5118
5402
|
}
|
|
5119
|
-
if (opts.receiver && !
|
|
5120
|
-
console.error(
|
|
5403
|
+
if (opts.receiver && !isAddress6(opts.receiver)) {
|
|
5404
|
+
console.error(chalk9.red(`
|
|
5121
5405
|
\u2716 Invalid receiver address: ${opts.receiver}
|
|
5122
5406
|
`));
|
|
5123
5407
|
process.exit(1);
|
|
@@ -5125,24 +5409,24 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
|
|
|
5125
5409
|
try {
|
|
5126
5410
|
await preflightRedeem(shares);
|
|
5127
5411
|
} catch (err) {
|
|
5128
|
-
console.error(
|
|
5412
|
+
console.error(chalk9.red(`
|
|
5129
5413
|
\u2716 ${err instanceof Error ? err.message : String(err)}
|
|
5130
5414
|
`));
|
|
5131
5415
|
process.exit(1);
|
|
5132
5416
|
}
|
|
5133
|
-
const sharesDisplay =
|
|
5134
|
-
const spinner =
|
|
5417
|
+
const sharesDisplay = formatUnits5(shares, shareDecimals);
|
|
5418
|
+
const spinner = ora8(`Redeeming ${sharesDisplay} shares...`).start();
|
|
5135
5419
|
try {
|
|
5136
5420
|
const { hash, assetsOut } = await redeem(
|
|
5137
5421
|
shares,
|
|
5138
5422
|
opts.receiver
|
|
5139
5423
|
);
|
|
5140
5424
|
spinner.succeed(`Redeemed: ${hash}`);
|
|
5141
|
-
console.log(
|
|
5142
|
-
console.log(` Assets received: ${
|
|
5425
|
+
console.log(chalk9.dim(` ${getExplorerUrl(hash)}`));
|
|
5426
|
+
console.log(` Assets received: ${formatUnits5(assetsOut, assetDecimals)}`);
|
|
5143
5427
|
} catch (err) {
|
|
5144
5428
|
spinner.fail("Redeem failed");
|
|
5145
|
-
console.error(
|
|
5429
|
+
console.error(chalk9.red(formatContractError(err)));
|
|
5146
5430
|
process.exit(1);
|
|
5147
5431
|
}
|
|
5148
5432
|
});
|
|
@@ -5160,28 +5444,29 @@ ${info.name} (${info.type})`);
|
|
|
5160
5444
|
}
|
|
5161
5445
|
});
|
|
5162
5446
|
try {
|
|
5163
|
-
const { registerChatCommands } = await import("./chat-
|
|
5447
|
+
const { registerChatCommands } = await import("./chat-K4LW776Q.js");
|
|
5164
5448
|
registerChatCommands(program);
|
|
5165
5449
|
} catch {
|
|
5166
5450
|
program.command("chat <name> [action] [actionArgs...]").description("Syndicate chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
|
|
5167
|
-
console.error(
|
|
5168
|
-
console.error(
|
|
5169
|
-
console.error(
|
|
5451
|
+
console.error(chalk9.red("XMTP CLI not available."));
|
|
5452
|
+
console.error(chalk9.dim("Install with: npm install -g @xmtp/cli"));
|
|
5453
|
+
console.error(chalk9.dim("Or reinstall: npm i -g @sherwoodagent/cli"));
|
|
5170
5454
|
process.exit(1);
|
|
5171
5455
|
});
|
|
5172
5456
|
}
|
|
5173
|
-
var { registerSessionCommands } = await import("./session-
|
|
5457
|
+
var { registerSessionCommands } = await import("./session-2TBX4UTS.js");
|
|
5174
5458
|
registerSessionCommands(program);
|
|
5175
5459
|
registerVeniceCommands(program);
|
|
5176
5460
|
registerAllowanceCommands(program);
|
|
5177
5461
|
registerIdentityCommands(program);
|
|
5178
5462
|
registerProposalCommands(program);
|
|
5179
5463
|
registerGovernorCommands(program);
|
|
5180
|
-
|
|
5464
|
+
registerGuardianCommands(program);
|
|
5465
|
+
var { registerResearchCommands } = await import("./research-K62TKFLF.js");
|
|
5181
5466
|
registerResearchCommands(program);
|
|
5182
5467
|
var { registerAgentCommands } = await import("./agent-XBYSALOA.js");
|
|
5183
5468
|
registerAgentCommands(program);
|
|
5184
|
-
var { registerTradeCommands } = await import("./trade-
|
|
5469
|
+
var { registerTradeCommands } = await import("./trade-S3L2CNV4.js");
|
|
5185
5470
|
registerTradeCommands(program);
|
|
5186
5471
|
var configCmd = program.command("config");
|
|
5187
5472
|
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.)").option("--uniswap-api-key <key>", "Uniswap Trading API key (from developers.uniswap.org)").option("--venice-api-key <key>", "Venice AI inference API key").option("--xmtp-group <subdomain:groupId>", "Cache an XMTP group ID for a syndicate (e.g. my-fund:abc123)").action((opts) => {
|
|
@@ -5189,53 +5474,53 @@ configCmd.command("set").description("Save settings to ~/.sherwood/config.json (
|
|
|
5189
5474
|
if (opts.privateKey) {
|
|
5190
5475
|
setPrivateKey(opts.privateKey);
|
|
5191
5476
|
const account = getAccount();
|
|
5192
|
-
console.log(
|
|
5193
|
-
console.log(
|
|
5477
|
+
console.log(chalk9.green("Private key saved to ~/.sherwood/config.json"));
|
|
5478
|
+
console.log(chalk9.dim(` Wallet: ${account.address}`));
|
|
5194
5479
|
saved = true;
|
|
5195
5480
|
}
|
|
5196
5481
|
if (opts.vault) {
|
|
5197
5482
|
const chainId = getChain().id;
|
|
5198
5483
|
setChainContract(chainId, "vault", opts.vault);
|
|
5199
|
-
console.log(
|
|
5200
|
-
console.log(
|
|
5484
|
+
console.log(chalk9.green(`Vault saved to ~/.sherwood/config.json (chain ${chainId})`));
|
|
5485
|
+
console.log(chalk9.dim(` Vault: ${opts.vault}`));
|
|
5201
5486
|
saved = true;
|
|
5202
5487
|
}
|
|
5203
5488
|
if (opts.rpc) {
|
|
5204
5489
|
const network = getNetwork();
|
|
5205
5490
|
setConfigRpcUrl(network, opts.rpc);
|
|
5206
|
-
console.log(
|
|
5207
|
-
console.log(
|
|
5491
|
+
console.log(chalk9.green(`RPC URL saved for ${network}`));
|
|
5492
|
+
console.log(chalk9.dim(` RPC: ${opts.rpc}`));
|
|
5208
5493
|
saved = true;
|
|
5209
5494
|
}
|
|
5210
5495
|
if (opts.notifyTo) {
|
|
5211
5496
|
setNotifyTo(opts.notifyTo);
|
|
5212
|
-
console.log(
|
|
5213
|
-
console.log(
|
|
5497
|
+
console.log(chalk9.green("Notify destination saved to ~/.sherwood/config.json"));
|
|
5498
|
+
console.log(chalk9.dim(` Notify to: ${opts.notifyTo}`));
|
|
5214
5499
|
saved = true;
|
|
5215
5500
|
}
|
|
5216
5501
|
if (opts.uniswapApiKey) {
|
|
5217
5502
|
setUniswapApiKey(opts.uniswapApiKey);
|
|
5218
|
-
console.log(
|
|
5503
|
+
console.log(chalk9.green("Uniswap API key saved to ~/.sherwood/config.json"));
|
|
5219
5504
|
saved = true;
|
|
5220
5505
|
}
|
|
5221
5506
|
if (opts.veniceApiKey) {
|
|
5222
5507
|
setVeniceApiKey(opts.veniceApiKey);
|
|
5223
|
-
console.log(
|
|
5508
|
+
console.log(chalk9.green("Venice API key saved to ~/.sherwood/config.json"));
|
|
5224
5509
|
saved = true;
|
|
5225
5510
|
}
|
|
5226
5511
|
if (opts.xmtpGroup) {
|
|
5227
5512
|
const parts = opts.xmtpGroup.split(":");
|
|
5228
5513
|
if (parts.length !== 2 || !parts[0] || !parts[1]) {
|
|
5229
|
-
console.log(
|
|
5514
|
+
console.log(chalk9.red("Format: --xmtp-group <subdomain>:<groupId>"));
|
|
5230
5515
|
process.exit(1);
|
|
5231
5516
|
}
|
|
5232
5517
|
cacheGroupId(parts[0], parts[1]);
|
|
5233
|
-
console.log(
|
|
5234
|
-
console.log(
|
|
5518
|
+
console.log(chalk9.green(`XMTP group ID cached for ${parts[0]}`));
|
|
5519
|
+
console.log(chalk9.dim(` Group ID: ${parts[1]}`));
|
|
5235
5520
|
saved = true;
|
|
5236
5521
|
}
|
|
5237
5522
|
if (!saved) {
|
|
5238
|
-
console.log(
|
|
5523
|
+
console.log(chalk9.red("Provide at least one of: --private-key, --vault, --rpc, --notify-to, --uniswap-api-key, --venice-api-key, --xmtp-group"));
|
|
5239
5524
|
process.exit(1);
|
|
5240
5525
|
}
|
|
5241
5526
|
});
|
|
@@ -5246,25 +5531,25 @@ configCmd.command("show").description("Display current config for the active net
|
|
|
5246
5531
|
const config = loadConfig();
|
|
5247
5532
|
const customRpc = config.rpc?.[network];
|
|
5248
5533
|
console.log();
|
|
5249
|
-
console.log(
|
|
5250
|
-
console.log(
|
|
5251
|
-
console.log(` Network: ${
|
|
5252
|
-
console.log(` RPC: ${customRpc ?
|
|
5253
|
-
console.log(` Wallet: ${config.privateKey ?
|
|
5254
|
-
console.log(` Agent ID: ${config.agentId ??
|
|
5255
|
-
console.log(` Vault: ${contracts.vault ??
|
|
5256
|
-
console.log(` Uniswap: ${getUniswapApiKey() ?
|
|
5257
|
-
console.log(` Venice: ${getVeniceApiKey() ?
|
|
5534
|
+
console.log(chalk9.bold(`Sherwood Config`));
|
|
5535
|
+
console.log(chalk9.dim("\u2500".repeat(50)));
|
|
5536
|
+
console.log(` Network: ${chalk9.cyan(network)} (chain ${chainId})`);
|
|
5537
|
+
console.log(` RPC: ${customRpc ? chalk9.green(customRpc) : chalk9.dim("default")}`);
|
|
5538
|
+
console.log(` Wallet: ${config.privateKey ? chalk9.green("configured") : chalk9.dim("not set")}`);
|
|
5539
|
+
console.log(` Agent ID: ${config.agentId ?? chalk9.dim("not set")}`);
|
|
5540
|
+
console.log(` Vault: ${contracts.vault ?? chalk9.dim("not set")}`);
|
|
5541
|
+
console.log(` Uniswap: ${getUniswapApiKey() ? chalk9.green("API key configured") : chalk9.dim("not set")}`);
|
|
5542
|
+
console.log(` Venice: ${getVeniceApiKey() ? chalk9.green("API key configured") : chalk9.dim("not set")}`);
|
|
5258
5543
|
const groupEntries = Object.entries(config.groupCache || {}).filter(([, v]) => v);
|
|
5259
5544
|
if (groupEntries.length > 0) {
|
|
5260
5545
|
console.log();
|
|
5261
|
-
console.log(
|
|
5546
|
+
console.log(chalk9.bold(" XMTP Groups"));
|
|
5262
5547
|
for (const [sub, gid] of groupEntries) {
|
|
5263
|
-
console.log(` ${sub}: ${
|
|
5548
|
+
console.log(` ${sub}: ${chalk9.cyan(gid)}`);
|
|
5264
5549
|
}
|
|
5265
5550
|
}
|
|
5266
5551
|
console.log();
|
|
5267
|
-
console.log(
|
|
5552
|
+
console.log(chalk9.dim(" Config file: ~/.sherwood/config.json"));
|
|
5268
5553
|
console.log();
|
|
5269
5554
|
});
|
|
5270
5555
|
program.parse();
|