@sherwoodagent/cli 0.89.2 → 0.90.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/{agent-K5ZKUS47.js → agent-QU2OSWS4.js} +4 -4
- package/dist/{chat-QVDOCCJN.js → chat-PFXIL6WT.js} +9 -9
- package/dist/{chunk-QEX2TWJV.js → chunk-2SIUEMPV.js} +2 -2
- package/dist/{chunk-TWJXGEBZ.js → chunk-5XMQQ4LX.js} +2 -2
- package/dist/{chunk-JLOROS5V.js → chunk-74QYNLJE.js} +2 -2
- package/dist/{chunk-VD65GJOY.js → chunk-DQZJULNP.js} +2 -2
- package/dist/{chunk-Z53JZORT.js → chunk-I7NYU4JB.js} +28 -4
- package/dist/chunk-I7NYU4JB.js.map +1 -0
- package/dist/{chunk-OYP35TFK.js → chunk-J3JMMJLN.js} +3 -3
- package/dist/{chunk-LVGYGXAV.js → chunk-KPTKX226.js} +2 -2
- package/dist/{chunk-TGWTRG3V.js → chunk-KRASHQRB.js} +6 -6
- package/dist/{chunk-VVCSD2M6.js → chunk-KXUA5BEH.js} +2 -2
- package/dist/{chunk-6IC2NRED.js → chunk-WIUPOQNS.js} +2 -2
- package/dist/{chunk-H6AJMPLT.js → chunk-XQHRKFFH.js} +49 -10
- package/dist/chunk-XQHRKFFH.js.map +1 -0
- package/dist/{chunk-MIW4CBSU.js → chunk-ZCRVHITI.js} +10 -10
- package/dist/{client-DA434B67.js → client-3BFK7TNL.js} +2 -2
- package/dist/{eas-F6KOWI4W.js → eas-YTAAJSLU.js} +3 -3
- package/dist/{governor-6HCXMRIA.js → governor-53PNPDCZ.js} +3 -3
- package/dist/{identity-2JEZE7DV.js → identity-M6UIVBNX.js} +5 -5
- package/dist/index.js +432 -218
- package/dist/index.js.map +1 -1
- package/dist/{launchpad-XM4546BO.js → launchpad-LHMBN4TV.js} +3 -3
- package/dist/{lighter-preflight-7J3IO27F.js → lighter-preflight-R7C6HY3M.js} +6 -6
- package/dist/{price-4FGWEPKX.js → price-PBFF6NFU.js} +4 -4
- package/dist/{providers-XEEFKITN.js → providers-22A42FKP.js} +3 -3
- package/dist/{research-CJOSSD4U.js → research-ZH34O7YL.js} +5 -5
- package/dist/{session-775NKMGH.js → session-GSWEE4M3.js} +7 -7
- package/dist/{trade-PCK3LONN.js → trade-SHK7GKSI.js} +10 -10
- package/dist/{vault-NLMVWYDF.js → vault-3T6UHCPE.js} +6 -6
- package/dist/{xmtp-H5GTOJ43.js → xmtp-EOMKXRTB.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-H6AJMPLT.js.map +0 -1
- package/dist/chunk-Z53JZORT.js.map +0 -1
- /package/dist/{agent-K5ZKUS47.js.map → agent-QU2OSWS4.js.map} +0 -0
- /package/dist/{chat-QVDOCCJN.js.map → chat-PFXIL6WT.js.map} +0 -0
- /package/dist/{chunk-QEX2TWJV.js.map → chunk-2SIUEMPV.js.map} +0 -0
- /package/dist/{chunk-TWJXGEBZ.js.map → chunk-5XMQQ4LX.js.map} +0 -0
- /package/dist/{chunk-JLOROS5V.js.map → chunk-74QYNLJE.js.map} +0 -0
- /package/dist/{chunk-VD65GJOY.js.map → chunk-DQZJULNP.js.map} +0 -0
- /package/dist/{chunk-OYP35TFK.js.map → chunk-J3JMMJLN.js.map} +0 -0
- /package/dist/{chunk-LVGYGXAV.js.map → chunk-KPTKX226.js.map} +0 -0
- /package/dist/{chunk-TGWTRG3V.js.map → chunk-KRASHQRB.js.map} +0 -0
- /package/dist/{chunk-VVCSD2M6.js.map → chunk-KXUA5BEH.js.map} +0 -0
- /package/dist/{chunk-6IC2NRED.js.map → chunk-WIUPOQNS.js.map} +0 -0
- /package/dist/{chunk-MIW4CBSU.js.map → chunk-ZCRVHITI.js.map} +0 -0
- /package/dist/{client-DA434B67.js.map → client-3BFK7TNL.js.map} +0 -0
- /package/dist/{eas-F6KOWI4W.js.map → eas-YTAAJSLU.js.map} +0 -0
- /package/dist/{governor-6HCXMRIA.js.map → governor-53PNPDCZ.js.map} +0 -0
- /package/dist/{identity-2JEZE7DV.js.map → identity-M6UIVBNX.js.map} +0 -0
- /package/dist/{launchpad-XM4546BO.js.map → launchpad-LHMBN4TV.js.map} +0 -0
- /package/dist/{lighter-preflight-7J3IO27F.js.map → lighter-preflight-R7C6HY3M.js.map} +0 -0
- /package/dist/{price-4FGWEPKX.js.map → price-PBFF6NFU.js.map} +0 -0
- /package/dist/{providers-XEEFKITN.js.map → providers-22A42FKP.js.map} +0 -0
- /package/dist/{research-CJOSSD4U.js.map → research-ZH34O7YL.js.map} +0 -0
- /package/dist/{session-775NKMGH.js.map → session-GSWEE4M3.js.map} +0 -0
- /package/dist/{trade-PCK3LONN.js.map → trade-SHK7GKSI.js.map} +0 -0
- /package/dist/{vault-NLMVWYDF.js.map → vault-3T6UHCPE.js.map} +0 -0
- /package/dist/{xmtp-H5GTOJ43.js.map → xmtp-EOMKXRTB.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -15,14 +15,17 @@ import {
|
|
|
15
15
|
checkApiKeyValid,
|
|
16
16
|
listModels,
|
|
17
17
|
provisionApiKey
|
|
18
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-74QYNLJE.js";
|
|
19
19
|
import {
|
|
20
20
|
createFund,
|
|
21
21
|
getActiveFunds,
|
|
22
22
|
getFund,
|
|
23
23
|
subdomainExists,
|
|
24
24
|
updateMetadata
|
|
25
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-DQZJULNP.js";
|
|
26
|
+
import {
|
|
27
|
+
addLaunchpadTemplateOptions
|
|
28
|
+
} from "./chunk-KXUA5BEH.js";
|
|
26
29
|
import {
|
|
27
30
|
FORK_UNOBSERVABLE_REASON,
|
|
28
31
|
LIGHTER_API_PROFILES,
|
|
@@ -54,8 +57,8 @@ import {
|
|
|
54
57
|
removeDepositor,
|
|
55
58
|
setAgentFeeBps,
|
|
56
59
|
setVaultAddress
|
|
57
|
-
} from "./chunk-
|
|
58
|
-
import "./chunk-
|
|
60
|
+
} from "./chunk-J3JMMJLN.js";
|
|
61
|
+
import "./chunk-KRASHQRB.js";
|
|
59
62
|
import {
|
|
60
63
|
CL_DEFAULTS,
|
|
61
64
|
DEFAULT_FEE_TIER,
|
|
@@ -89,7 +92,22 @@ import {
|
|
|
89
92
|
selectBestFeeTier,
|
|
90
93
|
twapTickFromCumulatives,
|
|
91
94
|
v3SingleHopExtraData
|
|
92
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-ZCRVHITI.js";
|
|
96
|
+
import {
|
|
97
|
+
CLAIM_SETTLE_BUFFER_SECONDS,
|
|
98
|
+
DEFAULT_DEADLINE_MARGIN_SECONDS,
|
|
99
|
+
LaunchpadInputError,
|
|
100
|
+
buildLaunchpadInitParams,
|
|
101
|
+
decideLaunchDrawdown,
|
|
102
|
+
defaultMaxFeeIn,
|
|
103
|
+
liveFeeCost,
|
|
104
|
+
parseAmountFlag,
|
|
105
|
+
parseDeadline,
|
|
106
|
+
parseDurationSeconds,
|
|
107
|
+
parseSettleSlippageBps,
|
|
108
|
+
parseVenue,
|
|
109
|
+
sameAddr
|
|
110
|
+
} from "./chunk-T5NA6KOF.js";
|
|
93
111
|
import {
|
|
94
112
|
DEFAULT_ISSUING_CHAIN_ID,
|
|
95
113
|
STRATEGY_FACTORY_ABI,
|
|
@@ -109,6 +127,7 @@ import {
|
|
|
109
127
|
encodeJoinRequest,
|
|
110
128
|
encodeMgmtSplit,
|
|
111
129
|
encodePerfSplit,
|
|
130
|
+
encodePrepareOwnerStake,
|
|
112
131
|
encodePropose,
|
|
113
132
|
encodeRedeem,
|
|
114
133
|
encodeRegisterAgent,
|
|
@@ -123,12 +142,12 @@ import {
|
|
|
123
142
|
registerIdentityCommands,
|
|
124
143
|
stripVidTag,
|
|
125
144
|
verifyVidTag
|
|
126
|
-
} from "./chunk-
|
|
145
|
+
} from "./chunk-XQHRKFFH.js";
|
|
127
146
|
import {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
} from "./chunk-
|
|
147
|
+
emitCalldata,
|
|
148
|
+
isCalldataOnly,
|
|
149
|
+
setCalldataOnly
|
|
150
|
+
} from "./chunk-GAQMHH44.js";
|
|
132
151
|
import {
|
|
133
152
|
createApproval,
|
|
134
153
|
createJoinRequest,
|
|
@@ -138,13 +157,13 @@ import {
|
|
|
138
157
|
queryJoinRequests,
|
|
139
158
|
revokeJoinRequest,
|
|
140
159
|
stripReferrerPrefix
|
|
141
|
-
} from "./chunk-
|
|
160
|
+
} from "./chunk-2SIUEMPV.js";
|
|
142
161
|
import {
|
|
143
162
|
resolveFund,
|
|
144
163
|
resolveVaultFund,
|
|
145
164
|
searchFundAcrossChains,
|
|
146
165
|
setTextRecord
|
|
147
|
-
} from "./chunk-
|
|
166
|
+
} from "./chunk-KPTKX226.js";
|
|
148
167
|
import {
|
|
149
168
|
PROPOSAL_STATE,
|
|
150
169
|
PROPOSAL_STATES,
|
|
@@ -183,50 +202,7 @@ import {
|
|
|
183
202
|
setVotingPeriod,
|
|
184
203
|
settleProposal,
|
|
185
204
|
vote
|
|
186
|
-
} from "./chunk-
|
|
187
|
-
import {
|
|
188
|
-
LIGHTER_DEFAULT_API_KEY_INDEX,
|
|
189
|
-
LIGHTER_MAX_DEPOSIT,
|
|
190
|
-
acknowledgeShortfallCalldata,
|
|
191
|
-
buildPostSettleRecoveryCalls,
|
|
192
|
-
deriveBurnPubKey,
|
|
193
|
-
encodeCancelAll,
|
|
194
|
-
encodeClosePosition,
|
|
195
|
-
encodeRotateKey,
|
|
196
|
-
guardrailActionCalldata,
|
|
197
|
-
initiateReturnCalldata,
|
|
198
|
-
isLighterPubKeyOnCurve,
|
|
199
|
-
queueWithdrawCalldata,
|
|
200
|
-
recoverResidualsCalldata,
|
|
201
|
-
registerAgentKeyCalldata,
|
|
202
|
-
usdgToTicksFloor,
|
|
203
|
-
validateLighterKeyIndex,
|
|
204
|
-
validateLighterMarket,
|
|
205
|
-
validateLighterPubKey
|
|
206
|
-
} from "./chunk-TCUSM4V7.js";
|
|
207
|
-
import {
|
|
208
|
-
addLaunchpadTemplateOptions
|
|
209
|
-
} from "./chunk-VVCSD2M6.js";
|
|
210
|
-
import {
|
|
211
|
-
CLAIM_SETTLE_BUFFER_SECONDS,
|
|
212
|
-
DEFAULT_DEADLINE_MARGIN_SECONDS,
|
|
213
|
-
LaunchpadInputError,
|
|
214
|
-
buildLaunchpadInitParams,
|
|
215
|
-
decideLaunchDrawdown,
|
|
216
|
-
defaultMaxFeeIn,
|
|
217
|
-
liveFeeCost,
|
|
218
|
-
parseAmountFlag,
|
|
219
|
-
parseDeadline,
|
|
220
|
-
parseDurationSeconds,
|
|
221
|
-
parseSettleSlippageBps,
|
|
222
|
-
parseVenue,
|
|
223
|
-
sameAddr
|
|
224
|
-
} from "./chunk-T5NA6KOF.js";
|
|
225
|
-
import {
|
|
226
|
-
emitCalldata,
|
|
227
|
-
isCalldataOnly,
|
|
228
|
-
setCalldataOnly
|
|
229
|
-
} from "./chunk-GAQMHH44.js";
|
|
205
|
+
} from "./chunk-5XMQQ4LX.js";
|
|
230
206
|
import {
|
|
231
207
|
AERODROME,
|
|
232
208
|
LAUNCH_ADAPTERS,
|
|
@@ -247,7 +223,7 @@ import {
|
|
|
247
223
|
sendTxWithRetry,
|
|
248
224
|
waitForReceipt,
|
|
249
225
|
writeContractWithRetry
|
|
250
|
-
} from "./chunk-
|
|
226
|
+
} from "./chunk-I7NYU4JB.js";
|
|
251
227
|
import {
|
|
252
228
|
DEFAULT_NETWORK,
|
|
253
229
|
VALID_NETWORKS,
|
|
@@ -284,6 +260,26 @@ import {
|
|
|
284
260
|
setUniswapApiKey,
|
|
285
261
|
setVeniceApiKey
|
|
286
262
|
} from "./chunk-QUAVAJWE.js";
|
|
263
|
+
import {
|
|
264
|
+
LIGHTER_DEFAULT_API_KEY_INDEX,
|
|
265
|
+
LIGHTER_MAX_DEPOSIT,
|
|
266
|
+
acknowledgeShortfallCalldata,
|
|
267
|
+
buildPostSettleRecoveryCalls,
|
|
268
|
+
deriveBurnPubKey,
|
|
269
|
+
encodeCancelAll,
|
|
270
|
+
encodeClosePosition,
|
|
271
|
+
encodeRotateKey,
|
|
272
|
+
guardrailActionCalldata,
|
|
273
|
+
initiateReturnCalldata,
|
|
274
|
+
isLighterPubKeyOnCurve,
|
|
275
|
+
queueWithdrawCalldata,
|
|
276
|
+
recoverResidualsCalldata,
|
|
277
|
+
registerAgentKeyCalldata,
|
|
278
|
+
usdgToTicksFloor,
|
|
279
|
+
validateLighterKeyIndex,
|
|
280
|
+
validateLighterMarket,
|
|
281
|
+
validateLighterPubKey
|
|
282
|
+
} from "./chunk-TCUSM4V7.js";
|
|
287
283
|
import {
|
|
288
284
|
BASE_STRATEGY_ABI,
|
|
289
285
|
ERC20_ABI,
|
|
@@ -297,6 +293,11 @@ import {
|
|
|
297
293
|
SYNDICATE_VAULT_ABI,
|
|
298
294
|
VENICE_STAKING_ABI
|
|
299
295
|
} from "./chunk-SCWNKVNW.js";
|
|
296
|
+
import {
|
|
297
|
+
fetchMetadata,
|
|
298
|
+
mergeFundMetadata,
|
|
299
|
+
uploadMetadata
|
|
300
|
+
} from "./chunk-YMB4RJOR.js";
|
|
300
301
|
|
|
301
302
|
// src/index.ts
|
|
302
303
|
import { config as loadDotenv } from "dotenv";
|
|
@@ -522,7 +523,7 @@ var HYPERLIQUID_GRID_STRATEGY_ABI = [
|
|
|
522
523
|
];
|
|
523
524
|
|
|
524
525
|
// src/commands/strategy-template-lib.ts
|
|
525
|
-
import { parseUnits as parseUnits3, formatUnits as formatUnits4, isAddress as isAddress4, erc20Abi as erc20Abi3 } from "viem";
|
|
526
|
+
import { parseUnits as parseUnits3, formatUnits as formatUnits4, isAddress as isAddress4, erc20Abi as erc20Abi3, encodeFunctionData, maxUint256 } from "viem";
|
|
526
527
|
import chalk3 from "chalk";
|
|
527
528
|
|
|
528
529
|
// src/lib/proposer-bond-error.ts
|
|
@@ -560,7 +561,8 @@ var STAKED_WOOD_ABI = [
|
|
|
560
561
|
{ type: "function", name: "claimUnstakeGuardian", inputs: [], outputs: [], stateMutability: "nonpayable" },
|
|
561
562
|
// Views
|
|
562
563
|
{ type: "function", name: "guardianStake", inputs: [{ type: "address" }], outputs: [{ type: "uint256" }], stateMutability: "view" },
|
|
563
|
-
{ type: "function", name: "isActiveGuardian", inputs: [{ type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" }
|
|
564
|
+
{ type: "function", name: "isActiveGuardian", inputs: [{ type: "address" }], outputs: [{ type: "bool" }], stateMutability: "view" },
|
|
565
|
+
{ type: "function", name: "minOwnerStake", inputs: [], outputs: [{ type: "uint256" }], stateMutability: "view" }
|
|
564
566
|
];
|
|
565
567
|
var ERC20_ABI2 = [
|
|
566
568
|
{ type: "function", name: "approve", inputs: [{ type: "address" }, { type: "uint256" }], outputs: [{ type: "bool" }], stateMutability: "nonpayable" },
|
|
@@ -692,6 +694,19 @@ function registerGuardianCommands(program2) {
|
|
|
692
694
|
"Bond WOOD as a prospective vault owner \u2014 required before `vault create`. Amount in WOOD (min = swood.minOwnerStake, default 10000)."
|
|
693
695
|
).action(async (amountStr) => {
|
|
694
696
|
const amount = parseUnits(amountStr, 18);
|
|
697
|
+
if (isCalldataOnly()) {
|
|
698
|
+
const min = await getPublicClient().readContract({
|
|
699
|
+
address: swood(),
|
|
700
|
+
abi: STAKED_WOOD_ABI,
|
|
701
|
+
functionName: "minOwnerStake"
|
|
702
|
+
});
|
|
703
|
+
if (amount < min) {
|
|
704
|
+
console.error(chalk.red(`Owner stake must be at least ${formatUnits2(min, 18)} WOOD (StakedWood.minOwnerStake).`));
|
|
705
|
+
process.exit(1);
|
|
706
|
+
}
|
|
707
|
+
emitCalldata(encodePrepareOwnerStake({ amount }, getChain().id));
|
|
708
|
+
return;
|
|
709
|
+
}
|
|
695
710
|
await ensureWoodAllowance(amount);
|
|
696
711
|
const wallet = getWalletClient();
|
|
697
712
|
const pc = getPublicClient();
|
|
@@ -1805,84 +1820,120 @@ function capsForCalls(calls, strategy2, maxCapital) {
|
|
|
1805
1820
|
return seen === 1 ? share + remainder : share;
|
|
1806
1821
|
});
|
|
1807
1822
|
}
|
|
1808
|
-
async function
|
|
1823
|
+
async function pinProposalMetadata(meta) {
|
|
1824
|
+
const { pinJSON } = await import("./ipfs-M56BLMCW.js");
|
|
1809
1825
|
try {
|
|
1810
|
-
const
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1826
|
+
const uri = await pinJSON(meta, meta.name);
|
|
1827
|
+
console.error(chalk3.dim(` Metadata pinned: ${uri}`));
|
|
1828
|
+
return uri;
|
|
1829
|
+
} catch {
|
|
1830
|
+
console.error(
|
|
1831
|
+
chalk3.yellow(" IPFS pin failed \u2014 using inline metadata. The app renders only ipfs:// metadata; pass --metadata-uri to override.")
|
|
1832
|
+
);
|
|
1833
|
+
const inline = JSON.stringify({ ...meta, createdBy: "@sherwoodagent/cli" });
|
|
1834
|
+
return `data:application/json;base64,${Buffer.from(inline).toString("base64")}`;
|
|
1835
|
+
}
|
|
1836
|
+
}
|
|
1837
|
+
var BOND_GOVERNOR_VIEWS = [
|
|
1838
|
+
{ type: "function", name: "bondEscrow", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" },
|
|
1839
|
+
{ type: "function", name: "exposureLedger", inputs: [], outputs: [{ type: "address" }], stateMutability: "view" }
|
|
1840
|
+
];
|
|
1841
|
+
var PROPOSER_BOND_WOOD_ABI = [
|
|
1842
|
+
{
|
|
1843
|
+
type: "function",
|
|
1844
|
+
name: "proposerBondWood",
|
|
1845
|
+
inputs: [
|
|
1846
|
+
{ name: "asset", type: "address" },
|
|
1847
|
+
{ name: "requiredCoverage", type: "uint256" }
|
|
1848
|
+
],
|
|
1849
|
+
outputs: [{ type: "uint256" }],
|
|
1850
|
+
stateMutability: "view"
|
|
1851
|
+
}
|
|
1852
|
+
];
|
|
1853
|
+
async function quoteProposerBond(vault, requiredCoverage, asset) {
|
|
1854
|
+
const publicClient = getPublicClient();
|
|
1855
|
+
const governor = await getGovernorOf(vault);
|
|
1856
|
+
const escrow = await publicClient.readContract({
|
|
1857
|
+
address: governor,
|
|
1858
|
+
abi: BOND_GOVERNOR_VIEWS,
|
|
1859
|
+
functionName: "bondEscrow"
|
|
1860
|
+
});
|
|
1861
|
+
if (!escrow || escrow === ZERO2) return null;
|
|
1862
|
+
let quotedBond = 0n;
|
|
1863
|
+
try {
|
|
1864
|
+
const ledger = await publicClient.readContract({
|
|
1829
1865
|
address: governor,
|
|
1830
|
-
abi:
|
|
1831
|
-
functionName: "
|
|
1866
|
+
abi: BOND_GOVERNOR_VIEWS,
|
|
1867
|
+
functionName: "exposureLedger"
|
|
1832
1868
|
});
|
|
1833
|
-
if (
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
functionName: "exposureLedger"
|
|
1869
|
+
if (ledger && ledger !== ZERO2 && requiredCoverage > 0n) {
|
|
1870
|
+
quotedBond = await publicClient.readContract({
|
|
1871
|
+
address: ledger,
|
|
1872
|
+
abi: PROPOSER_BOND_WOOD_ABI,
|
|
1873
|
+
functionName: "proposerBondWood",
|
|
1874
|
+
args: [asset, requiredCoverage]
|
|
1840
1875
|
});
|
|
1841
|
-
if (ledger && ledger !== ZERO2 && requiredCoverage > 0n) {
|
|
1842
|
-
quotedBond = await publicClient.readContract({
|
|
1843
|
-
address: ledger,
|
|
1844
|
-
abi: [
|
|
1845
|
-
{
|
|
1846
|
-
type: "function",
|
|
1847
|
-
name: "proposerBondWood",
|
|
1848
|
-
inputs: [
|
|
1849
|
-
{ name: "asset", type: "address" },
|
|
1850
|
-
{ name: "requiredCoverage", type: "uint256" }
|
|
1851
|
-
],
|
|
1852
|
-
outputs: [{ type: "uint256" }],
|
|
1853
|
-
stateMutability: "view"
|
|
1854
|
-
}
|
|
1855
|
-
],
|
|
1856
|
-
functionName: "proposerBondWood",
|
|
1857
|
-
args: [asset, requiredCoverage]
|
|
1858
|
-
});
|
|
1859
|
-
}
|
|
1860
|
-
} catch {
|
|
1861
|
-
}
|
|
1862
|
-
console.log(
|
|
1863
|
-
chalk3.dim(
|
|
1864
|
-
` Quoted proposer bond: ${formatUnits4(quotedBond, 18)} WOOD (via ExposureLedger.proposerBondWood; ~1% of extractable value at default proposerBondBps, WOOD-denominated and price-dependent \u2014 not a fixed WOOD amount)`
|
|
1865
|
-
)
|
|
1866
|
-
);
|
|
1867
|
-
console.log(chalk3.dim(` Proposer bond escrow: ${escrow} \u2014 ensuring WOOD allowance`));
|
|
1868
|
-
if (quotedBond > 0n) {
|
|
1869
|
-
const wood2 = SHERWOOD().WOOD_TOKEN;
|
|
1870
|
-
const holder = getAccount().address;
|
|
1871
|
-
const balance = await publicClient.readContract({
|
|
1872
|
-
address: wood2,
|
|
1873
|
-
abi: erc20Abi3,
|
|
1874
|
-
functionName: "balanceOf",
|
|
1875
|
-
args: [holder]
|
|
1876
|
-
});
|
|
1877
|
-
if (balance < quotedBond) {
|
|
1878
|
-
throw new InsufficientProposerBondWood(quotedBond, balance);
|
|
1879
|
-
}
|
|
1880
1876
|
}
|
|
1881
|
-
|
|
1877
|
+
} catch {
|
|
1878
|
+
}
|
|
1879
|
+
return { escrow, quotedBond };
|
|
1880
|
+
}
|
|
1881
|
+
function bondQuoteLines(quote) {
|
|
1882
|
+
return [
|
|
1883
|
+
` Quoted proposer bond: ${formatUnits4(quote.quotedBond, 18)} WOOD (via ExposureLedger.proposerBondWood; ~1% of extractable value at default proposerBondBps, WOOD-denominated and price-dependent \u2014 not a fixed WOOD amount)`,
|
|
1884
|
+
` Proposer bond escrow: ${quote.escrow}`
|
|
1885
|
+
];
|
|
1886
|
+
}
|
|
1887
|
+
async function requireBondWood(holder, quotedBond) {
|
|
1888
|
+
if (quotedBond === 0n) return;
|
|
1889
|
+
const balance = await getPublicClient().readContract({
|
|
1890
|
+
address: SHERWOOD().WOOD_TOKEN,
|
|
1891
|
+
abi: erc20Abi3,
|
|
1892
|
+
functionName: "balanceOf",
|
|
1893
|
+
args: [holder]
|
|
1894
|
+
});
|
|
1895
|
+
if (balance < quotedBond) throw new InsufficientProposerBondWood(quotedBond, balance);
|
|
1896
|
+
}
|
|
1897
|
+
async function ensureProposerBondAllowance(vault, requiredCoverage, asset) {
|
|
1898
|
+
try {
|
|
1899
|
+
const quote = await quoteProposerBond(vault, requiredCoverage, asset);
|
|
1900
|
+
if (!quote) return;
|
|
1901
|
+
for (const line of bondQuoteLines(quote)) console.log(chalk3.dim(line));
|
|
1902
|
+
await requireBondWood(getAccount().address, quote.quotedBond);
|
|
1903
|
+
await ensureWoodAllowance(2n ** 255n, quote.escrow, "WOOD (proposer bond)");
|
|
1882
1904
|
} catch (err) {
|
|
1883
1905
|
if (err instanceof InsufficientProposerBondWood) throw err;
|
|
1884
1906
|
}
|
|
1885
1907
|
}
|
|
1908
|
+
async function proposerBondApprovalTxs(vault, requiredCoverage, asset, proposer, chainId) {
|
|
1909
|
+
let quote;
|
|
1910
|
+
try {
|
|
1911
|
+
quote = await quoteProposerBond(vault, requiredCoverage, asset);
|
|
1912
|
+
} catch {
|
|
1913
|
+
return [];
|
|
1914
|
+
}
|
|
1915
|
+
if (!quote) return [];
|
|
1916
|
+
for (const line of bondQuoteLines(quote)) console.error(chalk3.dim(line));
|
|
1917
|
+
const wood2 = SHERWOOD().WOOD_TOKEN;
|
|
1918
|
+
if (proposer) {
|
|
1919
|
+
await requireBondWood(proposer, quote.quotedBond);
|
|
1920
|
+
const allowance = await getPublicClient().readContract({
|
|
1921
|
+
address: wood2,
|
|
1922
|
+
abi: erc20Abi3,
|
|
1923
|
+
functionName: "allowance",
|
|
1924
|
+
args: [proposer, quote.escrow]
|
|
1925
|
+
});
|
|
1926
|
+
if (allowance >= 2n ** 255n) return [];
|
|
1927
|
+
}
|
|
1928
|
+
return [
|
|
1929
|
+
{
|
|
1930
|
+
to: wood2,
|
|
1931
|
+
data: encodeFunctionData({ abi: erc20Abi3, functionName: "approve", args: [quote.escrow, maxUint256] }),
|
|
1932
|
+
value: "0x0",
|
|
1933
|
+
chainId
|
|
1934
|
+
}
|
|
1935
|
+
];
|
|
1936
|
+
}
|
|
1886
1937
|
|
|
1887
1938
|
// src/commands/strategy-propose.ts
|
|
1888
1939
|
import { formatUnits as formatUnits5, isAddress as isAddress5, erc20Abi as erc20Abi4 } from "viem";
|
|
@@ -1919,7 +1970,7 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
1919
1970
|
if (isCalldataOnly()) {
|
|
1920
1971
|
const missing = [];
|
|
1921
1972
|
if (!opts.proposer) missing.push("--proposer <address> (the external signer)");
|
|
1922
|
-
if (!opts.metadataUri) missing.push("--metadata-uri <uri>
|
|
1973
|
+
if (!opts.metadataUri && !opts.name) missing.push("--name <name> (or --metadata-uri <uri>)");
|
|
1923
1974
|
if (!opts.duration) missing.push("--duration <d>");
|
|
1924
1975
|
if (missing.length > 0) {
|
|
1925
1976
|
console.error(chalk4.red(`--calldata-only requires: ${missing.join(", ")}`));
|
|
@@ -1984,7 +2035,7 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
1984
2035
|
}
|
|
1985
2036
|
}
|
|
1986
2037
|
if (templateKey === "lighter-perp") {
|
|
1987
|
-
const { runLighterProposePreflight } = await import("./lighter-preflight-
|
|
2038
|
+
const { runLighterProposePreflight } = await import("./lighter-preflight-R7C6HY3M.js");
|
|
1988
2039
|
await runLighterProposePreflight(vault, opts, maxDrawdownBps);
|
|
1989
2040
|
}
|
|
1990
2041
|
} catch (err) {
|
|
@@ -1992,7 +2043,7 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
1992
2043
|
process.exit(1);
|
|
1993
2044
|
}
|
|
1994
2045
|
if (!opts.agent) opts.agent = proposer;
|
|
1995
|
-
const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-
|
|
2046
|
+
const { parseDuration: parseDuration3, getGovernorOf: getGovernorOf2 } = await import("./governor-53PNPDCZ.js");
|
|
1996
2047
|
const strategyDuration2 = parseDuration3(opts.duration);
|
|
1997
2048
|
const chainId = getChain().id;
|
|
1998
2049
|
try {
|
|
@@ -2015,12 +2066,23 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
2015
2066
|
built.assetAmount,
|
|
2016
2067
|
built.extraApprovals
|
|
2017
2068
|
);
|
|
2069
|
+
const metadataURI2 = opts.metadataUri || await pinProposalMetadata({
|
|
2070
|
+
name: opts.name,
|
|
2071
|
+
description: opts.description || "",
|
|
2072
|
+
proposer,
|
|
2073
|
+
vault,
|
|
2074
|
+
strategyClone: deploy.clone,
|
|
2075
|
+
template: def.key,
|
|
2076
|
+
strategyDuration: Number(strategyDuration2),
|
|
2077
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
2078
|
+
});
|
|
2079
|
+
const bondTxs = await proposerBondApprovalTxs(vault, built.assetAmount, built.asset, proposer, chainId);
|
|
2018
2080
|
const proposeAction = encodePropose(
|
|
2019
2081
|
{
|
|
2020
2082
|
vault,
|
|
2021
2083
|
governor,
|
|
2022
2084
|
strategy: deploy.clone,
|
|
2023
|
-
metadataURI:
|
|
2085
|
+
metadataURI: metadataURI2,
|
|
2024
2086
|
strategyDuration: strategyDuration2,
|
|
2025
2087
|
// Same envelope + cap shape the broadcasting path uses, so the
|
|
2026
2088
|
// emitted calldata is the transaction that path would send.
|
|
@@ -2033,14 +2095,14 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
2033
2095
|
chainId
|
|
2034
2096
|
);
|
|
2035
2097
|
emitCalldata({
|
|
2036
|
-
txs: [...deploy.txs, ...proposeAction.txs],
|
|
2098
|
+
txs: [...bondTxs, ...deploy.txs, ...proposeAction.txs],
|
|
2037
2099
|
preconditions: [...deploy.preconditions, ...proposeAction.preconditions],
|
|
2038
2100
|
// Surface the deterministic clone + salt as structured fields (also
|
|
2039
2101
|
// baked into tx 2's `strategy` arg + the execute/settle calls).
|
|
2040
2102
|
clone: deploy.clone,
|
|
2041
2103
|
salt: deploy.salt,
|
|
2042
|
-
description: `Keyless ${def.name} proposal on ${vault}: (
|
|
2043
|
-
note: "Broadcast SEQUENTIALLY
|
|
2104
|
+
description: `Keyless ${def.name} proposal on ${vault}: ` + (bondTxs.length ? "WOOD.approve(proposer-bond escrow); " : "") + `deploy clone at ${deploy.clone} (deterministic CREATE2, salt ${deploy.salt}); governor.propose referencing it.`,
|
|
2105
|
+
note: "Broadcast SEQUENTIALLY from the --proposer wallet, waiting for each tx to confirm before the next. " + (bondTxs.length ? "The first tx approves WOOD to the proposer-bond escrow \u2014 propose pulls the bond from the proposer and reverts without it. " : "") + "If cloneAndInitDeterministic reverts \u2014 proposer not a registered agent, proposer != signer, template not allowlisted, or vault unregistered \u2014 do NOT send propose: it would create a proposal referencing an undeployed strategy. The factory requires proposer == msg.sender, and msg.sender must be a vault owner/agent. The clone address is pinned by (factory, template, vault, salt) and is already baked into the propose tx + the execute/settle calls. The factory binds the salt to the vault and only the vault's owner/agents may deploy there, so the predicted address can't be front-run."
|
|
2044
2106
|
});
|
|
2045
2107
|
} catch (err) {
|
|
2046
2108
|
console.error(chalk4.red(err instanceof Error ? err.message : String(err)));
|
|
@@ -2110,7 +2172,7 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
2110
2172
|
}
|
|
2111
2173
|
}
|
|
2112
2174
|
if (templateKey === "lighter-perp") {
|
|
2113
|
-
const { runLighterProposePreflight } = await import("./lighter-preflight-
|
|
2175
|
+
const { runLighterProposePreflight } = await import("./lighter-preflight-R7C6HY3M.js");
|
|
2114
2176
|
await runLighterProposePreflight(vault, opts, maxDrawdownBps);
|
|
2115
2177
|
}
|
|
2116
2178
|
preflightSpinner.succeed("Preflight OK");
|
|
@@ -2227,9 +2289,9 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
2227
2289
|
console.error(chalk4.red("Missing --name or --duration. Use --write-calls to skip proposal submission."));
|
|
2228
2290
|
process.exit(1);
|
|
2229
2291
|
}
|
|
2230
|
-
const { propose: propose2 } = await import("./governor-
|
|
2292
|
+
const { propose: propose2 } = await import("./governor-53PNPDCZ.js");
|
|
2231
2293
|
const { pinJSON } = await import("./ipfs-M56BLMCW.js");
|
|
2232
|
-
const { parseDuration: parseDuration2 } = await import("./governor-
|
|
2294
|
+
const { parseDuration: parseDuration2 } = await import("./governor-53PNPDCZ.js");
|
|
2233
2295
|
const strategyDuration = parseDuration2(opts.duration);
|
|
2234
2296
|
const metaSpinner = ora2("Pinning metadata to IPFS...").start();
|
|
2235
2297
|
let metadataURI;
|
|
@@ -2261,7 +2323,7 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
2261
2323
|
metadataURI = `data:application/json;base64,${Buffer.from(inline).toString("base64")}`;
|
|
2262
2324
|
}
|
|
2263
2325
|
try {
|
|
2264
|
-
const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-
|
|
2326
|
+
const { getAgentFeeBps: getAgentFeeBps2 } = await import("./vault-3T6UHCPE.js");
|
|
2265
2327
|
const feeBps = await getAgentFeeBps2(vault);
|
|
2266
2328
|
console.log(
|
|
2267
2329
|
chalk4.yellow(
|
|
@@ -2312,7 +2374,7 @@ function registerStrategyProposeCommands(strategy2) {
|
|
|
2312
2374
|
console.log(chalk4.yellow(` asset.approve(${clone}, <repaymentAmount>)`));
|
|
2313
2375
|
}
|
|
2314
2376
|
if (templateKey === "lighter-perp") {
|
|
2315
|
-
const { lighterNextSteps } = await import("./lighter-preflight-
|
|
2377
|
+
const { lighterNextSteps } = await import("./lighter-preflight-R7C6HY3M.js");
|
|
2316
2378
|
console.log();
|
|
2317
2379
|
for (const line of lighterNextSteps(clone)) console.log(chalk4.yellow(line));
|
|
2318
2380
|
}
|
|
@@ -2584,7 +2646,7 @@ function registerStrategyTemplateCommands(strategy2) {
|
|
|
2584
2646
|
let prices = [];
|
|
2585
2647
|
let priceSource = null;
|
|
2586
2648
|
try {
|
|
2587
|
-
const { getTokenPricesInAsset } = await import("./price-
|
|
2649
|
+
const { getTokenPricesInAsset } = await import("./price-PBFF6NFU.js");
|
|
2588
2650
|
prices = await getTokenPricesInAsset({
|
|
2589
2651
|
tokens: allocations.map((a, i) => ({
|
|
2590
2652
|
token: a.token,
|
|
@@ -3001,7 +3063,7 @@ function registerVeniceCommands(program2) {
|
|
|
3001
3063
|
console.log(chalk6.dim(` Key: ${apiKey.slice(0, 8)}...${apiKey.slice(-4)}`));
|
|
3002
3064
|
console.log(chalk6.dim(" Saved to ~/.sherwood/config.json"));
|
|
3003
3065
|
try {
|
|
3004
|
-
const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-
|
|
3066
|
+
const { createVeniceProvisionAttestation, getEasScanUrl } = await import("./eas-YTAAJSLU.js");
|
|
3005
3067
|
const attestation = await createVeniceProvisionAttestation(account.address);
|
|
3006
3068
|
if (attestation) {
|
|
3007
3069
|
console.log(chalk6.dim(` Attested: ${getEasScanUrl(attestation.uid)}`));
|
|
@@ -3357,7 +3419,7 @@ ${opts.prompt}`;
|
|
|
3357
3419
|
console.log(chalk6.dim(`Model: ${result.model} | Tokens: ${result.usage.promptTokens} in, ${result.usage.completionTokens} out, ${result.usage.totalTokens} total`));
|
|
3358
3420
|
}
|
|
3359
3421
|
try {
|
|
3360
|
-
const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-
|
|
3422
|
+
const { createVeniceInferenceAttestation, getEasScanUrl } = await import("./eas-YTAAJSLU.js");
|
|
3361
3423
|
const { keccak256: keccak2562, toHex, isAddress: isAddr } = await import("viem");
|
|
3362
3424
|
const { getChainContracts: getChainContracts2 } = await import("./config-UZ2GIXAO.js");
|
|
3363
3425
|
const { getChain: getActiveChain } = await import("./network-EZ5X2BF7.js");
|
|
@@ -3389,7 +3451,7 @@ import chalk7 from "chalk";
|
|
|
3389
3451
|
import ora5 from "ora";
|
|
3390
3452
|
|
|
3391
3453
|
// src/strategies/allowance-disburse.ts
|
|
3392
|
-
import { encodeFunctionData, parseUnits as parseUnits7 } from "viem";
|
|
3454
|
+
import { encodeFunctionData as encodeFunctionData2, parseUnits as parseUnits7 } from "viem";
|
|
3393
3455
|
function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDecimals2, minUsdc, swapPath) {
|
|
3394
3456
|
const assetAmount = parseUnits7(config.amount, assetDecimals2);
|
|
3395
3457
|
const isUsdc = assetAddress.toLowerCase() === TOKENS().USDC.toLowerCase();
|
|
@@ -3398,7 +3460,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
|
|
|
3398
3460
|
if (!isUsdc) {
|
|
3399
3461
|
calls.push({
|
|
3400
3462
|
target: assetAddress,
|
|
3401
|
-
data:
|
|
3463
|
+
data: encodeFunctionData2({
|
|
3402
3464
|
abi: ERC20_ABI,
|
|
3403
3465
|
functionName: "approve",
|
|
3404
3466
|
args: [UNISWAP().SWAP_ROUTER, assetAmount]
|
|
@@ -3408,7 +3470,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
|
|
|
3408
3470
|
if (isWeth) {
|
|
3409
3471
|
calls.push({
|
|
3410
3472
|
target: UNISWAP().SWAP_ROUTER,
|
|
3411
|
-
data:
|
|
3473
|
+
data: encodeFunctionData2({
|
|
3412
3474
|
abi: SWAP_ROUTER_EXACT_INPUT_SINGLE_ABI,
|
|
3413
3475
|
functionName: "exactInputSingle",
|
|
3414
3476
|
args: [
|
|
@@ -3428,7 +3490,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
|
|
|
3428
3490
|
} else {
|
|
3429
3491
|
calls.push({
|
|
3430
3492
|
target: UNISWAP().SWAP_ROUTER,
|
|
3431
|
-
data:
|
|
3493
|
+
data: encodeFunctionData2({
|
|
3432
3494
|
abi: SWAP_ROUTER_ABI,
|
|
3433
3495
|
functionName: "exactInput",
|
|
3434
3496
|
args: [
|
|
@@ -3448,7 +3510,7 @@ function buildDisburseBatch(config, vaultAddress, agents, assetAddress, assetDec
|
|
|
3448
3510
|
for (const agent of agents) {
|
|
3449
3511
|
calls.push({
|
|
3450
3512
|
target: TOKENS().USDC,
|
|
3451
|
-
data:
|
|
3513
|
+
data: encodeFunctionData2({
|
|
3452
3514
|
abi: ERC20_ABI,
|
|
3453
3515
|
functionName: "transfer",
|
|
3454
3516
|
args: [agent, perAgent]
|
|
@@ -3658,13 +3720,13 @@ function registerAllowanceCommands(program2) {
|
|
|
3658
3720
|
}
|
|
3659
3721
|
|
|
3660
3722
|
// src/commands/proposal.ts
|
|
3661
|
-
import { isAddress as isAddress9, encodeFunctionData as
|
|
3723
|
+
import { isAddress as isAddress9, encodeFunctionData as encodeFunctionData4, formatUnits as formatUnits9, parseUnits as parseUnits9 } from "viem";
|
|
3662
3724
|
import chalk9 from "chalk";
|
|
3663
3725
|
import ora6 from "ora";
|
|
3664
3726
|
import { readFileSync as readFileSync2 } from "fs";
|
|
3665
3727
|
|
|
3666
3728
|
// src/lib/simulate.ts
|
|
3667
|
-
import { decodeFunctionData as decodeFunctionData2, encodeFunctionData as
|
|
3729
|
+
import { decodeFunctionData as decodeFunctionData2, encodeFunctionData as encodeFunctionData3 } from "viem";
|
|
3668
3730
|
import chalk8 from "chalk";
|
|
3669
3731
|
|
|
3670
3732
|
// src/lib/risk.ts
|
|
@@ -4224,7 +4286,7 @@ async function simulateViaEthCall(vault, calls) {
|
|
|
4224
4286
|
const governor = await getGovernorOf(vault);
|
|
4225
4287
|
const client = getPublicClient();
|
|
4226
4288
|
const uncapped = calls.map(() => MAX_UINT256);
|
|
4227
|
-
const input2 =
|
|
4289
|
+
const input2 = encodeFunctionData3({
|
|
4228
4290
|
abi: SYNDICATE_VAULT_ABI,
|
|
4229
4291
|
functionName: "executeGovernorBatch",
|
|
4230
4292
|
args: [
|
|
@@ -4356,8 +4418,8 @@ function printSimulationResult(result, callType) {
|
|
|
4356
4418
|
}
|
|
4357
4419
|
async function sendSimulationAlert(subdomain, proposalId, vault, execResult, settleResult) {
|
|
4358
4420
|
try {
|
|
4359
|
-
const xmtp = await import("./xmtp-
|
|
4360
|
-
const { getAccount: getAccount2 } = await import("./client-
|
|
4421
|
+
const xmtp = await import("./xmtp-EOMKXRTB.js");
|
|
4422
|
+
const { getAccount: getAccount2 } = await import("./client-3BFK7TNL.js");
|
|
4361
4423
|
const group = await xmtp.getGroup("", subdomain);
|
|
4362
4424
|
const allRisks = [...execResult.risks, ...settleResult?.risks ?? []];
|
|
4363
4425
|
const criticals = allRisks.filter((r) => r.level === "critical");
|
|
@@ -4605,7 +4667,7 @@ function registerProposalCommands(program2) {
|
|
|
4605
4667
|
).option(
|
|
4606
4668
|
"--settle-caps <list>",
|
|
4607
4669
|
"Comma-separated per-settlement-call outflow caps in asset units. Default: 0 for every call, because a settlement returns assets to the vault rather than sending them."
|
|
4608
|
-
).option("--metadata-uri <uri>", "Override \u2014 skip IPFS upload and use this URI directly").option("--simulate", "Simulate calls via Tenderly before submitting").option("--force", "Submit even if simulation fails (requires --simulate)").action(async (opts) => {
|
|
4670
|
+
).option("--metadata-uri <uri>", "Override \u2014 skip IPFS upload and use this URI directly").option("--proposer <address>", "With --calldata-only: the wallet that will send propose (recorded in metadata; enables the proposer-bond balance/allowance preflight)").option("--simulate", "Simulate calls via Tenderly before submitting").option("--force", "Submit even if simulation fails (requires --simulate)").action(async (opts) => {
|
|
4609
4671
|
try {
|
|
4610
4672
|
const vault = opts.vault;
|
|
4611
4673
|
if (!isAddress9(vault)) {
|
|
@@ -4625,46 +4687,72 @@ function registerProposalCommands(program2) {
|
|
|
4625
4687
|
strategy2 = opts.strategy;
|
|
4626
4688
|
}
|
|
4627
4689
|
if (isCalldataOnly()) {
|
|
4628
|
-
|
|
4629
|
-
|
|
4630
|
-
|
|
4631
|
-
|
|
4632
|
-
)
|
|
4633
|
-
|
|
4634
|
-
|
|
4690
|
+
let proposer;
|
|
4691
|
+
if (opts.proposer) {
|
|
4692
|
+
if (!isAddress9(opts.proposer)) {
|
|
4693
|
+
console.error(chalk9.red(`Invalid --proposer address: ${opts.proposer}`));
|
|
4694
|
+
process.exit(1);
|
|
4695
|
+
}
|
|
4696
|
+
proposer = opts.proposer;
|
|
4635
4697
|
}
|
|
4636
4698
|
const calldataEnvelope = await resolveRiskEnvelope(opts, vault);
|
|
4637
4699
|
const capDecimals2 = await assetDecimals(vault);
|
|
4700
|
+
const chainId = getChain().id;
|
|
4638
4701
|
try {
|
|
4639
|
-
|
|
4640
|
-
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4648
|
-
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
|
|
4652
|
-
|
|
4653
|
-
|
|
4654
|
-
|
|
4655
|
-
|
|
4656
|
-
|
|
4657
|
-
|
|
4658
|
-
|
|
4659
|
-
|
|
4660
|
-
|
|
4661
|
-
|
|
4662
|
-
|
|
4663
|
-
|
|
4664
|
-
|
|
4665
|
-
|
|
4666
|
-
|
|
4702
|
+
const metadataURI2 = opts.metadataUri || await pinProposalMetadata({
|
|
4703
|
+
schema: "sherwood/proposal/v1",
|
|
4704
|
+
name: opts.name,
|
|
4705
|
+
description: opts.description,
|
|
4706
|
+
chain: getNetwork(),
|
|
4707
|
+
strategies: [],
|
|
4708
|
+
terms: {},
|
|
4709
|
+
links: {},
|
|
4710
|
+
...proposer ? { proposer } : {},
|
|
4711
|
+
vault,
|
|
4712
|
+
strategyDuration: Number(strategyDuration),
|
|
4713
|
+
createdAt: Math.floor(Date.now() / 1e3)
|
|
4714
|
+
});
|
|
4715
|
+
const bondTxs = await proposerBondApprovalTxs(
|
|
4716
|
+
vault,
|
|
4717
|
+
calldataEnvelope.maxCapital,
|
|
4718
|
+
await getAssetAddress(vault),
|
|
4719
|
+
proposer,
|
|
4720
|
+
chainId
|
|
4721
|
+
);
|
|
4722
|
+
const proposeAction = encodePropose(
|
|
4723
|
+
{
|
|
4724
|
+
vault,
|
|
4725
|
+
governor: await getGovernorOf(vault),
|
|
4726
|
+
strategy: strategy2,
|
|
4727
|
+
metadataURI: metadataURI2,
|
|
4728
|
+
strategyDuration,
|
|
4729
|
+
envelope: calldataEnvelope,
|
|
4730
|
+
executeCalls,
|
|
4731
|
+
executeCallCaps: resolveCaps(
|
|
4732
|
+
opts.executeCaps,
|
|
4733
|
+
executeCalls.length,
|
|
4734
|
+
calldataEnvelope.maxCapital,
|
|
4735
|
+
"--execute-caps",
|
|
4736
|
+
capDecimals2
|
|
4737
|
+
),
|
|
4738
|
+
settlementCalls: settleCalls,
|
|
4739
|
+
settlementCallCaps: resolveCaps(
|
|
4740
|
+
opts.settleCaps,
|
|
4741
|
+
settleCalls.length,
|
|
4742
|
+
0n,
|
|
4743
|
+
"--settle-caps",
|
|
4744
|
+
capDecimals2
|
|
4745
|
+
)
|
|
4746
|
+
},
|
|
4747
|
+
chainId
|
|
4667
4748
|
);
|
|
4749
|
+
emitCalldata({
|
|
4750
|
+
...proposeAction,
|
|
4751
|
+
txs: [...bondTxs, ...proposeAction.txs],
|
|
4752
|
+
...bondTxs.length ? {
|
|
4753
|
+
note: "Send in order from the proposing agent's wallet: the WOOD approval to the proposer-bond escrow first \u2014 propose pulls the bond and reverts without it." + (proposeAction.note ? ` ${proposeAction.note}` : "")
|
|
4754
|
+
} : {}
|
|
4755
|
+
});
|
|
4668
4756
|
} catch (err) {
|
|
4669
4757
|
console.error(chalk9.red(err instanceof Error ? err.message : String(err)));
|
|
4670
4758
|
process.exit(1);
|
|
@@ -5301,7 +5389,7 @@ function registerProposalCommands(program2) {
|
|
|
5301
5389
|
process.exit(1);
|
|
5302
5390
|
}
|
|
5303
5391
|
const asset = await getAssetAddress(vault);
|
|
5304
|
-
const noopCalldata =
|
|
5392
|
+
const noopCalldata = encodeFunctionData4({
|
|
5305
5393
|
abi: ERC20_ABI,
|
|
5306
5394
|
functionName: "balanceOf",
|
|
5307
5395
|
args: [vault]
|
|
@@ -5679,7 +5767,7 @@ function registerProposalCommands(program2) {
|
|
|
5679
5767
|
txs: [
|
|
5680
5768
|
{
|
|
5681
5769
|
to: governor,
|
|
5682
|
-
data:
|
|
5770
|
+
data: encodeFunctionData4({
|
|
5683
5771
|
abi: SYNDICATE_GOVERNOR_ABI,
|
|
5684
5772
|
functionName: "reclaimProposerBond",
|
|
5685
5773
|
args: [proposalId]
|
|
@@ -5858,6 +5946,20 @@ var VAULT_QUEUE_ABI = [
|
|
|
5858
5946
|
inputs: [],
|
|
5859
5947
|
outputs: [{ name: "", type: "address" }]
|
|
5860
5948
|
},
|
|
5949
|
+
{
|
|
5950
|
+
name: "redemptionsLocked",
|
|
5951
|
+
type: "function",
|
|
5952
|
+
stateMutability: "view",
|
|
5953
|
+
inputs: [],
|
|
5954
|
+
outputs: [{ name: "", type: "bool" }]
|
|
5955
|
+
},
|
|
5956
|
+
{
|
|
5957
|
+
name: "depositsLocked",
|
|
5958
|
+
type: "function",
|
|
5959
|
+
stateMutability: "view",
|
|
5960
|
+
inputs: [],
|
|
5961
|
+
outputs: [{ name: "", type: "bool" }]
|
|
5962
|
+
},
|
|
5861
5963
|
{
|
|
5862
5964
|
type: "event",
|
|
5863
5965
|
name: "DepositRequested",
|
|
@@ -5938,6 +6040,103 @@ var QUEUE_ABI = [
|
|
|
5938
6040
|
}
|
|
5939
6041
|
];
|
|
5940
6042
|
var KIND_LABELS = ["Redeem", "Deposit"];
|
|
6043
|
+
var KIND_REDEEM = 0;
|
|
6044
|
+
var NEVER_STAMPS = /* @__PURE__ */ new Set([
|
|
6045
|
+
PROPOSAL_STATE.Rejected,
|
|
6046
|
+
PROPOSAL_STATE.Expired,
|
|
6047
|
+
PROPOSAL_STATE.Cancelled,
|
|
6048
|
+
PROPOSAL_STATE.Settled
|
|
6049
|
+
]);
|
|
6050
|
+
function classifyRequest(args) {
|
|
6051
|
+
const { request: r, stamped, proposalState } = args;
|
|
6052
|
+
if (r.claimed) return { kind: "claimed" };
|
|
6053
|
+
if (r.cancelled) return { kind: "cancelled" };
|
|
6054
|
+
if (r.kind === KIND_REDEEM) {
|
|
6055
|
+
if (!stamped) {
|
|
6056
|
+
if (proposalState !== void 0 && NEVER_STAMPS.has(proposalState)) {
|
|
6057
|
+
return { kind: "stranded", pid: r.pid, state: PROPOSAL_STATES[proposalState] ?? `state ${proposalState}` };
|
|
6058
|
+
}
|
|
6059
|
+
return { kind: "waiting", pid: r.pid };
|
|
6060
|
+
}
|
|
6061
|
+
return args.redemptionsLocked ? { kind: "locked" } : { kind: "claimable" };
|
|
6062
|
+
}
|
|
6063
|
+
return args.depositsLocked ? { kind: "locked" } : { kind: "claimable" };
|
|
6064
|
+
}
|
|
6065
|
+
function formatRequestStatus(status) {
|
|
6066
|
+
switch (status.kind) {
|
|
6067
|
+
case "claimed":
|
|
6068
|
+
return "claimed";
|
|
6069
|
+
case "cancelled":
|
|
6070
|
+
return "cancelled";
|
|
6071
|
+
case "claimable":
|
|
6072
|
+
return "claimable";
|
|
6073
|
+
case "waiting":
|
|
6074
|
+
return `waiting for pid ${status.pid} to settle`;
|
|
6075
|
+
case "stranded":
|
|
6076
|
+
return `stranded (pid ${status.pid} ended ${status.state} \u2014 cancel it)`;
|
|
6077
|
+
case "locked":
|
|
6078
|
+
return "waiting for vault to unlock";
|
|
6079
|
+
}
|
|
6080
|
+
}
|
|
6081
|
+
function claimRefusal(status, vault, id) {
|
|
6082
|
+
const cancelCmd = `sherwood queue cancel --vault ${vault} --id ${id}`;
|
|
6083
|
+
switch (status.kind) {
|
|
6084
|
+
case "claimable":
|
|
6085
|
+
return void 0;
|
|
6086
|
+
case "claimed":
|
|
6087
|
+
return `Request #${id} has already been claimed.`;
|
|
6088
|
+
case "cancelled":
|
|
6089
|
+
return `Request #${id} was cancelled \u2014 its escrow was already returned.`;
|
|
6090
|
+
case "stranded":
|
|
6091
|
+
return `Request #${id} is stranded: pid ${status.pid} ended ${status.state} without settling, so no claim price will ever be stamped (claim would revert NotSettled).
|
|
6092
|
+
Get the shares back with:
|
|
6093
|
+
${cancelCmd}
|
|
6094
|
+
then redeem directly.`;
|
|
6095
|
+
case "waiting":
|
|
6096
|
+
return `Request #${id} is waiting for pid ${status.pid} to settle \u2014 no claim price is stamped yet (claim would revert NotSettled). Retry after it settles.
|
|
6097
|
+
If pid ${status.pid} ends Rejected/Expired/Cancelled instead, run:
|
|
6098
|
+
${cancelCmd}`;
|
|
6099
|
+
case "locked":
|
|
6100
|
+
return `Request #${id} cannot be claimed while the vault is locked by an open proposal (claim would revert VaultLocked). Retry once it settles.`;
|
|
6101
|
+
}
|
|
6102
|
+
}
|
|
6103
|
+
async function loadRequestStatuses(vault, queue, requests) {
|
|
6104
|
+
const client = getPublicClient();
|
|
6105
|
+
const [redemptionsLocked, depositsLocked] = await Promise.all([
|
|
6106
|
+
client.readContract({ address: vault, abi: VAULT_QUEUE_ABI, functionName: "redemptionsLocked" }),
|
|
6107
|
+
client.readContract({ address: vault, abi: VAULT_QUEUE_ABI, functionName: "depositsLocked" })
|
|
6108
|
+
]);
|
|
6109
|
+
const pids = [
|
|
6110
|
+
...new Set(
|
|
6111
|
+
requests.filter((r) => r.kind === KIND_REDEEM && !r.claimed && !r.cancelled).map((r) => r.pid)
|
|
6112
|
+
)
|
|
6113
|
+
];
|
|
6114
|
+
const stampedByPid = /* @__PURE__ */ new Map();
|
|
6115
|
+
const stateByPid = /* @__PURE__ */ new Map();
|
|
6116
|
+
await Promise.all(
|
|
6117
|
+
pids.map(async (pid) => {
|
|
6118
|
+
const sp = await client.readContract({
|
|
6119
|
+
address: queue,
|
|
6120
|
+
abi: QUEUE_ABI,
|
|
6121
|
+
functionName: "getSettlePrice",
|
|
6122
|
+
args: [pid]
|
|
6123
|
+
});
|
|
6124
|
+
stampedByPid.set(pid, sp.stamped);
|
|
6125
|
+
if (!sp.stamped) {
|
|
6126
|
+
stateByPid.set(pid, await getProposalState(vault, pid).catch(() => void 0));
|
|
6127
|
+
}
|
|
6128
|
+
})
|
|
6129
|
+
);
|
|
6130
|
+
return requests.map(
|
|
6131
|
+
(request) => classifyRequest({
|
|
6132
|
+
request,
|
|
6133
|
+
stamped: stampedByPid.get(request.pid) ?? false,
|
|
6134
|
+
proposalState: stateByPid.get(request.pid),
|
|
6135
|
+
redemptionsLocked,
|
|
6136
|
+
depositsLocked
|
|
6137
|
+
})
|
|
6138
|
+
);
|
|
6139
|
+
}
|
|
5941
6140
|
function resolveVaultAddress(opt) {
|
|
5942
6141
|
if (!opt || !isAddress10(opt)) {
|
|
5943
6142
|
console.error(chalk10.red(`Invalid or missing --vault address: ${opt ?? "(none)"}`));
|
|
@@ -6097,9 +6296,17 @@ function registerQueueCommands(program2) {
|
|
|
6097
6296
|
const vault = resolveVaultAddress(opts.vault);
|
|
6098
6297
|
const account = getAccount();
|
|
6099
6298
|
const id = BigInt(opts.id);
|
|
6100
|
-
const spinner = ora7(`
|
|
6299
|
+
const spinner = ora7(`Checking request #${id}...`).start();
|
|
6101
6300
|
try {
|
|
6102
6301
|
const queueAddr = await getQueueAddress(vault);
|
|
6302
|
+
const [status] = await loadRequestStatuses(vault, queueAddr, [await readRequest(queueAddr, id)]);
|
|
6303
|
+
const refusal = claimRefusal(status, vault, id);
|
|
6304
|
+
if (refusal) {
|
|
6305
|
+
spinner.fail(`Not claimable: ${formatRequestStatus(status)}`);
|
|
6306
|
+
console.error(chalk10.yellow(refusal));
|
|
6307
|
+
process.exit(1);
|
|
6308
|
+
}
|
|
6309
|
+
spinner.text = `Claiming request #${id}...`;
|
|
6103
6310
|
const hash = await writeContractWithRetry({
|
|
6104
6311
|
account,
|
|
6105
6312
|
chain: getChain(),
|
|
@@ -6164,20 +6371,21 @@ function registerQueueCommands(program2) {
|
|
|
6164
6371
|
return;
|
|
6165
6372
|
}
|
|
6166
6373
|
const requests = await Promise.all(ids.map((id) => readRequest(queueAddr, id)));
|
|
6374
|
+
const statuses = await loadRequestStatuses(vault, queueAddr, requests);
|
|
6167
6375
|
spinner.stop();
|
|
6168
6376
|
console.log();
|
|
6169
6377
|
console.log(chalk10.bold(`Queue requests (${ids.length}) \u2014 ${account.address}`));
|
|
6170
|
-
console.log(chalk10.dim("\u2500".repeat(
|
|
6378
|
+
console.log(chalk10.dim("\u2500".repeat(100)));
|
|
6171
6379
|
console.log(
|
|
6172
6380
|
chalk10.dim(
|
|
6173
|
-
` ${"id".padEnd(6)}${"kind".padEnd(9)}${"amount".padEnd(26)}${"pid".padEnd(6)}${"claimed".padEnd(9)}cancelled`
|
|
6381
|
+
` ${"id".padEnd(6)}${"kind".padEnd(9)}${"amount".padEnd(26)}${"pid".padEnd(6)}${"claimed".padEnd(9)}${"cancelled".padEnd(11)}status`
|
|
6174
6382
|
)
|
|
6175
6383
|
);
|
|
6176
6384
|
ids.forEach((id, i) => {
|
|
6177
6385
|
const r = requests[i];
|
|
6178
6386
|
const label = KIND_LABELS[r.kind] ?? `kind ${r.kind}`;
|
|
6179
6387
|
console.log(
|
|
6180
|
-
` ${String(id).padEnd(6)}${label.padEnd(9)}${String(r.amount).padEnd(26)}${String(r.pid).padEnd(6)}${String(r.claimed).padEnd(9)}${r.cancelled}`
|
|
6388
|
+
` ${String(id).padEnd(6)}${label.padEnd(9)}${String(r.amount).padEnd(26)}${String(r.pid).padEnd(6)}${String(r.claimed).padEnd(9)}${String(r.cancelled).padEnd(11)}${formatRequestStatus(statuses[i])}`
|
|
6181
6389
|
);
|
|
6182
6390
|
});
|
|
6183
6391
|
console.log();
|
|
@@ -9969,9 +10177,9 @@ try {
|
|
|
9969
10177
|
} catch {
|
|
9970
10178
|
}
|
|
9971
10179
|
var require2 = createRequire(import.meta.url);
|
|
9972
|
-
var CLI_VERSION = "0.
|
|
10180
|
+
var CLI_VERSION = "0.90.0";
|
|
9973
10181
|
async function loadXmtp() {
|
|
9974
|
-
return import("./xmtp-
|
|
10182
|
+
return import("./xmtp-EOMKXRTB.js");
|
|
9975
10183
|
}
|
|
9976
10184
|
async function loadCron() {
|
|
9977
10185
|
return import("./cron-E3UAZF5B.js");
|
|
@@ -10026,6 +10234,10 @@ program.name("sherwood").description("CLI for agent-managed onchain vaults").ver
|
|
|
10026
10234
|
).hook("preAction", (thisCommand) => {
|
|
10027
10235
|
const opts = thisCommand.optsWithGlobals();
|
|
10028
10236
|
setCalldataOnly(Boolean(opts.calldataOnly));
|
|
10237
|
+
if (opts.calldataOnly) {
|
|
10238
|
+
console.log = console.error;
|
|
10239
|
+
console.info = console.error;
|
|
10240
|
+
}
|
|
10029
10241
|
setNetwork(opts.chain);
|
|
10030
10242
|
});
|
|
10031
10243
|
var LEGACY_GROUP_ALIASES = ["fund", "syndicate"];
|
|
@@ -10167,20 +10379,22 @@ vaultCmd.command("create").description("Launch a new vault via the factory (inte
|
|
|
10167
10379
|
}
|
|
10168
10380
|
}
|
|
10169
10381
|
if (isCalldataOnly()) {
|
|
10170
|
-
|
|
10171
|
-
|
|
10172
|
-
|
|
10173
|
-
|
|
10174
|
-
|
|
10175
|
-
|
|
10176
|
-
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
getChain().id
|
|
10182
|
-
)
|
|
10382
|
+
const action = encodeCreateFund(
|
|
10383
|
+
{
|
|
10384
|
+
creatorAgentId: agentIdStr,
|
|
10385
|
+
metadataURI,
|
|
10386
|
+
asset,
|
|
10387
|
+
name,
|
|
10388
|
+
symbol,
|
|
10389
|
+
openDeposits,
|
|
10390
|
+
subdomain
|
|
10391
|
+
},
|
|
10392
|
+
getChain().id
|
|
10183
10393
|
);
|
|
10394
|
+
emitCalldata({
|
|
10395
|
+
...action,
|
|
10396
|
+
note: `${action.note} Bond first with \`sherwood --calldata-only guardian prepare-owner-stake <amount>\`. After this tx confirms, register the creator as an agent (the factory does not, and proposing requires it): read the vault with \`sherwood vault info ${subdomain}\`, then send \`sherwood --calldata-only vault add --vault <vault> --wallet <creator> --agent-id ${agentIdStr}\`.`
|
|
10397
|
+
});
|
|
10184
10398
|
return;
|
|
10185
10399
|
}
|
|
10186
10400
|
const existingId = await subdomainExists(subdomain);
|
|
@@ -10642,7 +10856,7 @@ vaultCmd.command("add").description("Register an agent on a vault (creator only)
|
|
|
10642
10856
|
agentId = BigInt(opts.agentId);
|
|
10643
10857
|
} else {
|
|
10644
10858
|
spinner.text = "Looking up ERC-8004 identity from wallet...";
|
|
10645
|
-
const { lookupAgentIdByWallet } = await import("./identity-
|
|
10859
|
+
const { lookupAgentIdByWallet } = await import("./identity-M6UIVBNX.js");
|
|
10646
10860
|
const resolved = await lookupAgentIdByWallet(agentWallet);
|
|
10647
10861
|
if (resolved === null) {
|
|
10648
10862
|
spinner.fail("Agent wallet does not own an ERC-8004 identity NFT");
|
|
@@ -11345,7 +11559,7 @@ vaultCmd.command("redeem").description("Redeem vault shares for the underlying a
|
|
|
11345
11559
|
var strategy = program.command("strategy").description("Strategy templates \u2014 list, clone, propose");
|
|
11346
11560
|
registerStrategyTemplateCommands(strategy);
|
|
11347
11561
|
program.command("providers").description("List available providers (research + swap routing)").action(async () => {
|
|
11348
|
-
const { listProviders } = await import("./providers-
|
|
11562
|
+
const { listProviders } = await import("./providers-22A42FKP.js");
|
|
11349
11563
|
for (const info2 of listProviders()) {
|
|
11350
11564
|
console.log(`
|
|
11351
11565
|
${info2.name} (${info2.type})`);
|
|
@@ -11355,7 +11569,7 @@ ${info2.name} (${info2.type})`);
|
|
|
11355
11569
|
}
|
|
11356
11570
|
});
|
|
11357
11571
|
try {
|
|
11358
|
-
const { registerChatCommands } = await import("./chat-
|
|
11572
|
+
const { registerChatCommands } = await import("./chat-PFXIL6WT.js");
|
|
11359
11573
|
registerChatCommands(program);
|
|
11360
11574
|
} catch {
|
|
11361
11575
|
program.command("chat <name> [action] [actionArgs...]").description("Vault chat (XMTP) \u2014 requires @xmtp/cli").action(() => {
|
|
@@ -11365,7 +11579,7 @@ try {
|
|
|
11365
11579
|
process.exit(1);
|
|
11366
11580
|
});
|
|
11367
11581
|
}
|
|
11368
|
-
var { registerSessionCommands } = await import("./session-
|
|
11582
|
+
var { registerSessionCommands } = await import("./session-GSWEE4M3.js");
|
|
11369
11583
|
registerSessionCommands(program);
|
|
11370
11584
|
registerVeniceCommands(program);
|
|
11371
11585
|
registerAllowanceCommands(program);
|
|
@@ -11374,15 +11588,15 @@ registerProposalCommands(program);
|
|
|
11374
11588
|
registerQueueCommands(program);
|
|
11375
11589
|
registerGovernorCommands(program);
|
|
11376
11590
|
registerGuardianCommands(program);
|
|
11377
|
-
var { registerResearchCommands } = await import("./research-
|
|
11591
|
+
var { registerResearchCommands } = await import("./research-ZH34O7YL.js");
|
|
11378
11592
|
registerResearchCommands(program);
|
|
11379
|
-
var { registerAgentCommands } = await import("./agent-
|
|
11593
|
+
var { registerAgentCommands } = await import("./agent-QU2OSWS4.js");
|
|
11380
11594
|
registerAgentCommands(program);
|
|
11381
|
-
var { registerTradeCommands } = await import("./trade-
|
|
11595
|
+
var { registerTradeCommands } = await import("./trade-SHK7GKSI.js");
|
|
11382
11596
|
registerTradeCommands(program);
|
|
11383
11597
|
registerGridCommand(program);
|
|
11384
11598
|
registerLighterCommands(program);
|
|
11385
|
-
var { registerLaunchpadCommands } = await import("./launchpad-
|
|
11599
|
+
var { registerLaunchpadCommands } = await import("./launchpad-LHMBN4TV.js");
|
|
11386
11600
|
registerLaunchpadCommands(program);
|
|
11387
11601
|
var configCmd = program.command("config");
|
|
11388
11602
|
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 vault 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("--anthropic-api-key <key>", "Anthropic Claude API key (for LLM judge)").option("--xmtp-group <subdomain:groupId>", "Cache an XMTP group ID for a vault (e.g. my-vault:abc123)").action((opts) => {
|