@sherwoodagent/cli 0.88.2 → 0.89.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.
Files changed (87) hide show
  1. package/dist/{abis-WJQ6IVYV.js → abis-2VBXBA7Y.js} +16 -2
  2. package/dist/{agent-FCGZL4GF.js → agent-KMLNSKBS.js} +11 -11
  3. package/dist/{chat-AKLYUJZV.js → chat-JW5Z3JRE.js} +13 -13
  4. package/dist/{chunk-6SAE2VDK.js → chunk-6IC2NRED.js} +2 -2
  5. package/dist/{chunk-HMFPP2PE.js → chunk-77MBGRE5.js} +52 -24
  6. package/dist/chunk-77MBGRE5.js.map +1 -0
  7. package/dist/{chunk-G5MXVAFC.js → chunk-D3GTHAJS.js} +5 -5
  8. package/dist/chunk-G5FOHSQW.js +338 -0
  9. package/dist/chunk-G5FOHSQW.js.map +1 -0
  10. package/dist/chunk-GAQMHH44.js +18 -0
  11. package/dist/chunk-GAQMHH44.js.map +1 -0
  12. package/dist/{chunk-FWQESFFM.js → chunk-GYGSKMZE.js} +91 -8
  13. package/dist/chunk-GYGSKMZE.js.map +1 -0
  14. package/dist/{chunk-J2IZWAEW.js → chunk-JCL2DEH3.js} +2048 -2
  15. package/dist/chunk-JCL2DEH3.js.map +1 -0
  16. package/dist/{chunk-BH3VTJ4F.js → chunk-JKSDCCVL.js} +6 -6
  17. package/dist/{chunk-EEI6FRTE.js → chunk-JLOROS5V.js} +3 -3
  18. package/dist/{chunk-6D3FNU75.js → chunk-JRGYI34A.js} +5 -5
  19. package/dist/chunk-KZGY7NT7.js +209 -0
  20. package/dist/chunk-KZGY7NT7.js.map +1 -0
  21. package/dist/{chunk-G3FUEM5N.js → chunk-LIW6K4OJ.js} +2 -2
  22. package/dist/{chunk-4ITTHKRX.js → chunk-P4LFNKSX.js} +5 -5
  23. package/dist/{chunk-3TZIOAPH.js → chunk-QUAVAJWE.js} +13 -2
  24. package/dist/chunk-QUAVAJWE.js.map +1 -0
  25. package/dist/chunk-QVXKYT2N.js +489 -0
  26. package/dist/chunk-QVXKYT2N.js.map +1 -0
  27. package/dist/chunk-UPRFO4YU.js +458 -0
  28. package/dist/chunk-UPRFO4YU.js.map +1 -0
  29. package/dist/{chunk-QFGZQYZA.js → chunk-WDPA2BYK.js} +1024 -87
  30. package/dist/chunk-WDPA2BYK.js.map +1 -0
  31. package/dist/{chunk-CWGP4VXZ.js → chunk-YIN6R66K.js} +7 -7
  32. package/dist/{chunk-D4BSBW3Q.js → chunk-Z53JZORT.js} +3 -3
  33. package/dist/{chunk-SCQAKMMI.js → chunk-ZPOPWFSP.js} +5 -5
  34. package/dist/{client-PYFE6YQR.js → client-DA434B67.js} +4 -4
  35. package/dist/{config-ZGFS4I7K.js → config-UZ2GIXAO.js} +6 -2
  36. package/dist/{eas-B4HR2HXX.js → eas-ZH7BDEOK.js} +7 -7
  37. package/dist/{governor-QFBN6RYS.js → governor-WHT2V2EU.js} +7 -7
  38. package/dist/identity-TRPUQEQK.js +19 -0
  39. package/dist/index.js +7758 -5862
  40. package/dist/index.js.map +1 -1
  41. package/dist/launchpad-3N4ZFL6J.js +26 -0
  42. package/dist/lighter-perp-template-VC4TB7AM.js +92 -0
  43. package/dist/lighter-preflight-GH3JKLR6.js +149 -0
  44. package/dist/lighter-preflight-GH3JKLR6.js.map +1 -0
  45. package/dist/{network-7445KSCF.js → network-EZ5X2BF7.js} +3 -3
  46. package/dist/network-EZ5X2BF7.js.map +1 -0
  47. package/dist/{price-EXZDYVDD.js → price-RX5J7GTO.js} +9 -7
  48. package/dist/{price-EXZDYVDD.js.map → price-RX5J7GTO.js.map} +1 -1
  49. package/dist/{providers-6UZKDFQD.js → providers-XEEFKITN.js} +5 -5
  50. package/dist/{research-T7A27OMB.js → research-PYMQ5VKH.js} +9 -9
  51. package/dist/{session-45NQAHFI.js → session-DE47TUEW.js} +15 -15
  52. package/dist/{trade-ZOVM433K.js → trade-3VMAQ75D.js} +20 -18
  53. package/dist/{trade-ZOVM433K.js.map → trade-3VMAQ75D.js.map} +1 -1
  54. package/dist/{vault-E7XD6DLD.js → vault-PXGG2E3K.js} +9 -9
  55. package/dist/vault-PXGG2E3K.js.map +1 -0
  56. package/dist/{xmtp-72IRK7JL.js → xmtp-5PTIIVAI.js} +7 -7
  57. package/package.json +1 -1
  58. package/dist/chunk-3TZIOAPH.js.map +0 -1
  59. package/dist/chunk-FWQESFFM.js.map +0 -1
  60. package/dist/chunk-HMFPP2PE.js.map +0 -1
  61. package/dist/chunk-J2IZWAEW.js.map +0 -1
  62. package/dist/chunk-QFGZQYZA.js.map +0 -1
  63. package/dist/identity-I2BG4IGT.js +0 -18
  64. /package/dist/{abis-WJQ6IVYV.js.map → abis-2VBXBA7Y.js.map} +0 -0
  65. /package/dist/{agent-FCGZL4GF.js.map → agent-KMLNSKBS.js.map} +0 -0
  66. /package/dist/{chat-AKLYUJZV.js.map → chat-JW5Z3JRE.js.map} +0 -0
  67. /package/dist/{chunk-6SAE2VDK.js.map → chunk-6IC2NRED.js.map} +0 -0
  68. /package/dist/{chunk-G5MXVAFC.js.map → chunk-D3GTHAJS.js.map} +0 -0
  69. /package/dist/{chunk-BH3VTJ4F.js.map → chunk-JKSDCCVL.js.map} +0 -0
  70. /package/dist/{chunk-EEI6FRTE.js.map → chunk-JLOROS5V.js.map} +0 -0
  71. /package/dist/{chunk-6D3FNU75.js.map → chunk-JRGYI34A.js.map} +0 -0
  72. /package/dist/{chunk-G3FUEM5N.js.map → chunk-LIW6K4OJ.js.map} +0 -0
  73. /package/dist/{chunk-4ITTHKRX.js.map → chunk-P4LFNKSX.js.map} +0 -0
  74. /package/dist/{chunk-CWGP4VXZ.js.map → chunk-YIN6R66K.js.map} +0 -0
  75. /package/dist/{chunk-D4BSBW3Q.js.map → chunk-Z53JZORT.js.map} +0 -0
  76. /package/dist/{chunk-SCQAKMMI.js.map → chunk-ZPOPWFSP.js.map} +0 -0
  77. /package/dist/{client-PYFE6YQR.js.map → client-DA434B67.js.map} +0 -0
  78. /package/dist/{config-ZGFS4I7K.js.map → config-UZ2GIXAO.js.map} +0 -0
  79. /package/dist/{eas-B4HR2HXX.js.map → eas-ZH7BDEOK.js.map} +0 -0
  80. /package/dist/{governor-QFBN6RYS.js.map → governor-WHT2V2EU.js.map} +0 -0
  81. /package/dist/{identity-I2BG4IGT.js.map → identity-TRPUQEQK.js.map} +0 -0
  82. /package/dist/{network-7445KSCF.js.map → launchpad-3N4ZFL6J.js.map} +0 -0
  83. /package/dist/{vault-E7XD6DLD.js.map → lighter-perp-template-VC4TB7AM.js.map} +0 -0
  84. /package/dist/{providers-6UZKDFQD.js.map → providers-XEEFKITN.js.map} +0 -0
  85. /package/dist/{research-T7A27OMB.js.map → research-PYMQ5VKH.js.map} +0 -0
  86. /package/dist/{session-45NQAHFI.js.map → session-DE47TUEW.js.map} +0 -0
  87. /package/dist/{xmtp-72IRK7JL.js.map → xmtp-5PTIIVAI.js.map} +0 -0
@@ -0,0 +1,26 @@
1
+ import {
2
+ LAUNCHPAD_TEMPLATE_OPTIONS,
3
+ LAUNCH_PHASES,
4
+ STRATEGY_STATES,
5
+ addLaunchpadTemplateOptions,
6
+ claimBlocker,
7
+ readLaunchpad,
8
+ registerLaunchpadCommands
9
+ } from "./chunk-UPRFO4YU.js";
10
+ import "./chunk-QVXKYT2N.js";
11
+ import "./chunk-GAQMHH44.js";
12
+ import "./chunk-GYGSKMZE.js";
13
+ import "./chunk-Z53JZORT.js";
14
+ import "./chunk-LIW6K4OJ.js";
15
+ import "./chunk-QUAVAJWE.js";
16
+ import "./chunk-JCL2DEH3.js";
17
+ export {
18
+ LAUNCHPAD_TEMPLATE_OPTIONS,
19
+ LAUNCH_PHASES,
20
+ STRATEGY_STATES,
21
+ addLaunchpadTemplateOptions,
22
+ claimBlocker,
23
+ readLaunchpad,
24
+ registerLaunchpadCommands
25
+ };
26
+ //# sourceMappingURL=launchpad-3N4ZFL6J.js.map
@@ -0,0 +1,92 @@
1
+ import {
2
+ GOLDILOCKS_P,
3
+ LIGHTER_ACTION,
4
+ LIGHTER_DEFAULT_API_KEY_INDEX,
5
+ LIGHTER_MARKET_BUY_PRICE,
6
+ LIGHTER_MARKET_SELL_PRICE,
7
+ LIGHTER_MAX_API_KEY_INDEX,
8
+ LIGHTER_MAX_DEPOSIT,
9
+ LIGHTER_MAX_MARKETS,
10
+ LIGHTER_MAX_MARKET_INDEX,
11
+ LIGHTER_MIN_API_KEY_INDEX,
12
+ LIGHTER_MIN_DEPOSIT,
13
+ LIGHTER_PUBKEY_LEN,
14
+ LIGHTER_SIDE_ASK,
15
+ LIGHTER_SIDE_BID,
16
+ LIGHTER_TICKS_PER_USDG,
17
+ LIGHTER_USDG,
18
+ LIGHTER_USDG_DECIMALS,
19
+ LIGHTER_ZK_LIGHTER,
20
+ acknowledgeShortfallCalldata,
21
+ buildExecuteCalls,
22
+ buildInitData,
23
+ buildPostSettleRecoveryCalls,
24
+ buildSettleCalls,
25
+ deriveBurnPubKey,
26
+ encodeCancelAll,
27
+ encodeCloseMarket,
28
+ encodeClosePosition,
29
+ encodeRegisterKey,
30
+ encodeRotateKey,
31
+ guardrailActionCalldata,
32
+ initiateReturnCalldata,
33
+ isLighterPubKeyOnCurve,
34
+ parseLighterMarkets,
35
+ parseLighterTemplateFlags,
36
+ queueWithdrawCalldata,
37
+ recoverResidualsCalldata,
38
+ registerAgentKeyCalldata,
39
+ usdgToTicks,
40
+ usdgToTicksFloor,
41
+ validateLighterDeposit,
42
+ validateLighterKeyIndex,
43
+ validateLighterMarket,
44
+ validateLighterPubKey
45
+ } from "./chunk-G5FOHSQW.js";
46
+ import "./chunk-JCL2DEH3.js";
47
+ export {
48
+ GOLDILOCKS_P,
49
+ LIGHTER_ACTION,
50
+ LIGHTER_DEFAULT_API_KEY_INDEX,
51
+ LIGHTER_MARKET_BUY_PRICE,
52
+ LIGHTER_MARKET_SELL_PRICE,
53
+ LIGHTER_MAX_API_KEY_INDEX,
54
+ LIGHTER_MAX_DEPOSIT,
55
+ LIGHTER_MAX_MARKETS,
56
+ LIGHTER_MAX_MARKET_INDEX,
57
+ LIGHTER_MIN_API_KEY_INDEX,
58
+ LIGHTER_MIN_DEPOSIT,
59
+ LIGHTER_PUBKEY_LEN,
60
+ LIGHTER_SIDE_ASK,
61
+ LIGHTER_SIDE_BID,
62
+ LIGHTER_TICKS_PER_USDG,
63
+ LIGHTER_USDG,
64
+ LIGHTER_USDG_DECIMALS,
65
+ LIGHTER_ZK_LIGHTER,
66
+ acknowledgeShortfallCalldata,
67
+ buildExecuteCalls,
68
+ buildInitData,
69
+ buildPostSettleRecoveryCalls,
70
+ buildSettleCalls,
71
+ deriveBurnPubKey,
72
+ encodeCancelAll,
73
+ encodeCloseMarket,
74
+ encodeClosePosition,
75
+ encodeRegisterKey,
76
+ encodeRotateKey,
77
+ guardrailActionCalldata,
78
+ initiateReturnCalldata,
79
+ isLighterPubKeyOnCurve,
80
+ parseLighterMarkets,
81
+ parseLighterTemplateFlags,
82
+ queueWithdrawCalldata,
83
+ recoverResidualsCalldata,
84
+ registerAgentKeyCalldata,
85
+ usdgToTicks,
86
+ usdgToTicksFloor,
87
+ validateLighterDeposit,
88
+ validateLighterKeyIndex,
89
+ validateLighterMarket,
90
+ validateLighterPubKey
91
+ };
92
+ //# sourceMappingURL=lighter-perp-template-VC4TB7AM.js.map
@@ -0,0 +1,149 @@
1
+ import {
2
+ LIGHTER_API_PROFILES,
3
+ LighterApi,
4
+ resolveLighterApiBaseUrl
5
+ } from "./chunk-KZGY7NT7.js";
6
+ import {
7
+ LIGHTER_USDG,
8
+ LIGHTER_ZK_LIGHTER
9
+ } from "./chunk-G5FOHSQW.js";
10
+ import {
11
+ STRATEGY_VENUES
12
+ } from "./chunk-GYGSKMZE.js";
13
+ import "./chunk-LIW6K4OJ.js";
14
+ import "./chunk-QUAVAJWE.js";
15
+ import {
16
+ SYNDICATE_GOVERNOR_ABI,
17
+ SYNDICATE_VAULT_ABI
18
+ } from "./chunk-JCL2DEH3.js";
19
+
20
+ // src/lib/lighter-preflight.ts
21
+ import { formatUnits } from "viem";
22
+ var ZERO = "0x0000000000000000000000000000000000000000";
23
+ var TIER_REGISTRY_COUNTERPARTY_ABI = [
24
+ {
25
+ type: "function",
26
+ name: "isCounterpartyAllowed",
27
+ stateMutability: "view",
28
+ inputs: [{ name: "counterparty", type: "address" }],
29
+ outputs: [{ type: "bool" }]
30
+ }
31
+ ];
32
+ function resolveLighterVenue() {
33
+ const book = STRATEGY_VENUES().ZK_LIGHTER;
34
+ if (book !== ZERO && book.toLowerCase() !== LIGHTER_ZK_LIGHTER.toLowerCase()) {
35
+ throw new Error(
36
+ `STRATEGY_VENUES().ZK_LIGHTER (${book}) differs from the template's pinned ZK_LIGHTER (${LIGHTER_ZK_LIGHTER}) \u2014 address book drift`
37
+ );
38
+ }
39
+ return LIGHTER_ZK_LIGHTER;
40
+ }
41
+ function unknownMarkets(requested, live) {
42
+ const ids = new Set(live.map((m) => m.marketId));
43
+ return requested.filter((m) => !ids.has(m));
44
+ }
45
+ function recommendedDrawdownBps(deposit, vaultAssets, capBps = 9e3) {
46
+ if (vaultAssets === 0n) return capBps;
47
+ const bps = Number((deposit * 10000n + vaultAssets - 1n) / vaultAssets);
48
+ return Math.min(bps, capBps);
49
+ }
50
+ async function lighterProposePreflight(client, p) {
51
+ const warnings = [];
52
+ const asset = await client.readContract({ address: p.vault, abi: SYNDICATE_VAULT_ABI, functionName: "asset" });
53
+ if (asset.toLowerCase() !== LIGHTER_USDG.toLowerCase()) {
54
+ throw new Error(
55
+ `lighter-perp needs a USDG vault: vault ${p.vault} accounts in ${asset}, the template pins USDG ${LIGHTER_USDG} (initialize reverts AssetMismatch)`
56
+ );
57
+ }
58
+ const venue = resolveLighterVenue();
59
+ const governor = await client.readContract({ address: p.vault, abi: SYNDICATE_VAULT_ABI, functionName: "governor" });
60
+ const registry = governor === ZERO ? ZERO : await client.readContract({ address: governor, abi: SYNDICATE_GOVERNOR_ABI, functionName: "tierRegistry" });
61
+ if (registry === ZERO) {
62
+ throw new Error(`vault ${p.vault}'s governor resolves no TierRegistry (initialize reverts TierRegistryUnresolved)`);
63
+ }
64
+ let allowed = false;
65
+ try {
66
+ allowed = await client.readContract({
67
+ address: registry,
68
+ abi: TIER_REGISTRY_COUNTERPARTY_ABI,
69
+ functionName: "isCounterpartyAllowed",
70
+ args: [venue]
71
+ });
72
+ } catch {
73
+ allowed = false;
74
+ }
75
+ if (!allowed) {
76
+ throw new Error(
77
+ `TierRegistry ${registry} does not allow ZK_LIGHTER ${venue} as a counterparty (initialize reverts CounterpartyNotAllowed). The registry owner must setCounterpartyAllowed(ZK_LIGHTER, true) first.`
78
+ );
79
+ }
80
+ const api = p.api === void 0 ? new LighterApi(resolveLighterApiBaseUrl(p.network) ?? LIGHTER_API_PROFILES.rh) : p.api;
81
+ if (api) {
82
+ let live = null;
83
+ try {
84
+ live = await api.getMarkets();
85
+ } catch (err) {
86
+ warnings.push(`could not list Lighter markets (${err instanceof Error ? err.message : String(err)}) \u2014 market ids unchecked`);
87
+ }
88
+ if (live) {
89
+ const missing = unknownMarkets(p.markets, live);
90
+ if (missing.length > 0) {
91
+ throw new Error(
92
+ `--markets ${missing.join(",")} ${missing.length === 1 ? "is" : "are"} not a Lighter perp market (see \`sherwood lighter markets\`). initiateReturn only auto-closes the listed markets, so a typo leaves a real market unclosed.`
93
+ );
94
+ }
95
+ }
96
+ }
97
+ try {
98
+ const vaultAssets = await client.readContract({ address: p.vault, abi: SYNDICATE_VAULT_ABI, functionName: "totalAssets" });
99
+ const rec = recommendedDrawdownBps(p.depositAmount, vaultAssets);
100
+ if (p.maxDrawdownBps < rec) {
101
+ warnings.push(
102
+ `--max-drawdown-bps ${p.maxDrawdownBps} is below ${rec}: losing the whole ${formatUnits(p.depositAmount, 6)} USDG deposit (a perp liquidation) would drop the vault's price per share past the settle floor. settleProposal then reverts SettlePriceBelowFloor even after acknowledge-shortfall (the waiver relaxes the strategy's guard, not the governor's), and only unstick (90% cap) or the owner's emergency settle can finish the proposal.`
103
+ );
104
+ }
105
+ } catch {
106
+ warnings.push("could not read vault totalAssets \u2014 drawdown guidance skipped");
107
+ }
108
+ return warnings;
109
+ }
110
+ async function runLighterProposePreflight(vault, opts, maxDrawdownBps) {
111
+ const [{ getPublicClient }, { getNetwork }, chalk, tpl] = await Promise.all([
112
+ import("./client-DA434B67.js"),
113
+ import("./network-EZ5X2BF7.js"),
114
+ import("chalk").then((m) => m.default),
115
+ import("./lighter-perp-template-VC4TB7AM.js")
116
+ ]);
117
+ if (!opts.markets) throw new Error("lighter-perp: --markets <ids> is required");
118
+ const human = opts.deposit ?? opts.amount;
119
+ if (!human) throw new Error("lighter-perp: --deposit <usdg> is required");
120
+ const markets = tpl.parseLighterMarkets(String(opts.markets));
121
+ const depositAmount = tpl.validateLighterDeposit(tpl.usdgToTicks(human));
122
+ const warnings = await lighterProposePreflight(getPublicClient(), {
123
+ vault,
124
+ network: getNetwork(),
125
+ markets,
126
+ depositAmount,
127
+ maxDrawdownBps
128
+ });
129
+ for (const w of warnings) console.warn(chalk.yellow(` \u26A0 ${w}`));
130
+ }
131
+ function lighterNextSteps(clone) {
132
+ return [
133
+ "Next steps (Lighter perp \u2014 the exit is three steps, and only the last is in the proposal):",
134
+ ` 1. After execution: sherwood lighter register-key ${clone} (then the agent trades with the saved L2 key)`,
135
+ ` 2. To unwind: sherwood lighter initiate-return ${clone} (cancel + both-side close every market)`,
136
+ ` 3. Once flat: sherwood lighter queue-withdraw ${clone} --all (reads the true L2 balance; refuses with open positions)`,
137
+ ` 4. Before settle: sherwood lighter prepare-settle ${clone} (checks the drain matured, rotates the agent key to a burn key)`,
138
+ " 5. Then settle the proposal. Never put rescueTo(USDG) ahead of settle() in one batch."
139
+ ];
140
+ }
141
+ export {
142
+ lighterNextSteps,
143
+ lighterProposePreflight,
144
+ recommendedDrawdownBps,
145
+ resolveLighterVenue,
146
+ runLighterProposePreflight,
147
+ unknownMarkets
148
+ };
149
+ //# sourceMappingURL=lighter-preflight-GH3JKLR6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/lighter-preflight.ts"],"sourcesContent":["/**\n * `strategy propose lighter-perp` preflight — the chain / venue checks the pure\n * encoder cannot make, run BEFORE the clone is deployed so a proposal the\n * template would refuse costs no gas:\n *\n * 1. The vault's ERC-4626 asset is USDG (`_initialize` → AssetMismatch)\n * 2. vault → governor → tierRegistry resolves (→ TierRegistryUnresolved)\n * 3. that registry vouches for ZK_LIGHTER on the\n * counterparty axis (→ CounterpartyNotAllowed)\n * 4. every --markets id is a live Lighter perp market (API; best-effort)\n * 5. maxDrawdownBps guidance: a perp deposit can be lost outright, and an\n * acknowledged shortfall does NOT waive the governor's settle-price floor.\n *\n * Returns human-readable warnings; throws on anything that would revert.\n */\n\nimport type { Address } from \"viem\";\nimport { formatUnits } from \"viem\";\nimport { SYNDICATE_VAULT_ABI, SYNDICATE_GOVERNOR_ABI } from \"./abis.js\";\nimport { STRATEGY_VENUES } from \"./addresses.js\";\nimport { LighterApi, LIGHTER_API_PROFILES, resolveLighterApiBaseUrl, type LighterMarket } from \"./lighter-api.js\";\nimport type { Network } from \"./network.js\";\nimport type { ReadClient } from \"./lighter-strategy.js\";\nimport { LIGHTER_USDG, LIGHTER_ZK_LIGHTER } from \"../strategies/lighter-perp-template.js\";\n\nconst ZERO: Address = \"0x0000000000000000000000000000000000000000\";\n\nconst TIER_REGISTRY_COUNTERPARTY_ABI = [\n {\n type: \"function\",\n name: \"isCounterpartyAllowed\",\n stateMutability: \"view\",\n inputs: [{ name: \"counterparty\", type: \"address\" }],\n outputs: [{ type: \"bool\" }],\n },\n] as const;\n\n/** The venue the template is hard-wired to, cross-checked against the address book. */\nexport function resolveLighterVenue(): Address {\n const book = STRATEGY_VENUES().ZK_LIGHTER;\n if (book !== ZERO && book.toLowerCase() !== LIGHTER_ZK_LIGHTER.toLowerCase()) {\n throw new Error(\n `STRATEGY_VENUES().ZK_LIGHTER (${book}) differs from the template's pinned ZK_LIGHTER (${LIGHTER_ZK_LIGHTER}) — address book drift`,\n );\n }\n return LIGHTER_ZK_LIGHTER;\n}\n\n/** Markets not listed by the API. Empty = all known. */\nexport function unknownMarkets(requested: number[], live: LighterMarket[]): number[] {\n const ids = new Set(live.map((m) => m.marketId));\n return requested.filter((m) => !ids.has(m));\n}\n\n/**\n * The fraction of the vault a total loss of the deposit would wipe out, in bps\n * (capped at the governor's 90% stamp cap). A `maxDrawdownBps` below it means a\n * liquidation — even one the proposer acknowledges — makes `settleProposal`\n * revert `SettlePriceBelowFloor`, leaving `unstick` (90% cap) or the owner's\n * emergency settle.\n */\nexport function recommendedDrawdownBps(deposit: bigint, vaultAssets: bigint, capBps = 9000): number {\n if (vaultAssets === 0n) return capBps;\n const bps = Number((deposit * 10_000n + vaultAssets - 1n) / vaultAssets);\n return Math.min(bps, capBps);\n}\n\nexport async function lighterProposePreflight(\n client: ReadClient,\n p: {\n vault: Address;\n network: Network;\n markets: number[];\n depositAmount: bigint;\n maxDrawdownBps: number;\n api?: LighterApi | null;\n },\n): Promise<string[]> {\n const warnings: string[] = [];\n\n // 1. Asset bind.\n const asset = (await client.readContract({ address: p.vault, abi: SYNDICATE_VAULT_ABI, functionName: \"asset\" })) as Address;\n if (asset.toLowerCase() !== LIGHTER_USDG.toLowerCase()) {\n throw new Error(\n `lighter-perp needs a USDG vault: vault ${p.vault} accounts in ${asset}, the template pins USDG ${LIGHTER_USDG} (initialize reverts AssetMismatch)`,\n );\n }\n\n // 2 + 3. The same walk `_initialize` performs.\n const venue = resolveLighterVenue();\n const governor = (await client.readContract({ address: p.vault, abi: SYNDICATE_VAULT_ABI, functionName: \"governor\" })) as Address;\n const registry =\n governor === ZERO\n ? ZERO\n : ((await client.readContract({ address: governor, abi: SYNDICATE_GOVERNOR_ABI, functionName: \"tierRegistry\" })) as Address);\n if (registry === ZERO) {\n throw new Error(`vault ${p.vault}'s governor resolves no TierRegistry (initialize reverts TierRegistryUnresolved)`);\n }\n let allowed = false;\n try {\n allowed = (await client.readContract({\n address: registry,\n abi: TIER_REGISTRY_COUNTERPARTY_ABI,\n functionName: \"isCounterpartyAllowed\",\n args: [venue],\n })) as boolean;\n } catch {\n allowed = false;\n }\n if (!allowed) {\n throw new Error(\n `TierRegistry ${registry} does not allow ZK_LIGHTER ${venue} as a counterparty (initialize reverts CounterpartyNotAllowed). ` +\n \"The registry owner must setCounterpartyAllowed(ZK_LIGHTER, true) first.\",\n );\n }\n\n // 4. Market ids against the live venue. Market ids are sequencer config, the\n // same for every chain the template can run on, so the mainnet API is the\n // right oracle even on the fork.\n const api =\n p.api === undefined ? new LighterApi(resolveLighterApiBaseUrl(p.network) ?? LIGHTER_API_PROFILES.rh) : p.api;\n if (api) {\n let live: LighterMarket[] | null = null;\n try {\n live = await api.getMarkets();\n } catch (err) {\n warnings.push(`could not list Lighter markets (${err instanceof Error ? err.message : String(err)}) — market ids unchecked`);\n }\n if (live) {\n const missing = unknownMarkets(p.markets, live);\n if (missing.length > 0) {\n throw new Error(\n `--markets ${missing.join(\",\")} ${missing.length === 1 ? \"is\" : \"are\"} not a Lighter perp market ` +\n \"(see `sherwood lighter markets`). initiateReturn only auto-closes the listed markets, so a typo leaves a real market unclosed.\",\n );\n }\n }\n }\n\n // 5. Drawdown guidance.\n try {\n const vaultAssets = (await client.readContract({ address: p.vault, abi: SYNDICATE_VAULT_ABI, functionName: \"totalAssets\" })) as bigint;\n const rec = recommendedDrawdownBps(p.depositAmount, vaultAssets);\n if (p.maxDrawdownBps < rec) {\n warnings.push(\n `--max-drawdown-bps ${p.maxDrawdownBps} is below ${rec}: losing the whole ${formatUnits(p.depositAmount, 6)} USDG deposit ` +\n `(a perp liquidation) would drop the vault's price per share past the settle floor. settleProposal then reverts ` +\n \"SettlePriceBelowFloor even after acknowledge-shortfall (the waiver relaxes the strategy's guard, not the governor's), \" +\n \"and only unstick (90% cap) or the owner's emergency settle can finish the proposal.\",\n );\n }\n } catch {\n warnings.push(\"could not read vault totalAssets — drawdown guidance skipped\");\n }\n\n return warnings;\n}\n\n/**\n * The propose-command entry point: parse the lighter flags, run the checks\n * against the live chain, print the warnings. Throws on a hard failure (the\n * caller's preflight catch reports it and exits before any gas is spent).\n */\nexport async function runLighterProposePreflight(\n vault: Address,\n opts: Record<string, unknown>,\n maxDrawdownBps: number,\n): Promise<void> {\n const [{ getPublicClient }, { getNetwork }, chalk, tpl] = await Promise.all([\n import(\"./client.js\"),\n import(\"./network.js\"),\n import(\"chalk\").then((m) => m.default),\n import(\"../strategies/lighter-perp-template.js\"),\n ]);\n if (!opts.markets) throw new Error(\"lighter-perp: --markets <ids> is required\");\n const human = (opts.deposit ?? opts.amount) as string | undefined;\n if (!human) throw new Error(\"lighter-perp: --deposit <usdg> is required\");\n const markets = tpl.parseLighterMarkets(String(opts.markets));\n const depositAmount = tpl.validateLighterDeposit(tpl.usdgToTicks(human));\n const warnings = await lighterProposePreflight(getPublicClient() as unknown as ReadClient, {\n vault,\n network: getNetwork(),\n markets,\n depositAmount,\n maxDrawdownBps,\n });\n for (const w of warnings) console.warn(chalk.yellow(` ⚠ ${w}`));\n}\n\n/** Post-propose runbook for the three-step exit (printed after a successful propose). */\nexport function lighterNextSteps(clone: Address): string[] {\n return [\n \"Next steps (Lighter perp — the exit is three steps, and only the last is in the proposal):\",\n ` 1. After execution: sherwood lighter register-key ${clone} (then the agent trades with the saved L2 key)`,\n ` 2. To unwind: sherwood lighter initiate-return ${clone} (cancel + both-side close every market)`,\n ` 3. Once flat: sherwood lighter queue-withdraw ${clone} --all (reads the true L2 balance; refuses with open positions)`,\n ` 4. Before settle: sherwood lighter prepare-settle ${clone} (checks the drain matured, rotates the agent key to a burn key)`,\n \" 5. Then settle the proposal. Never put rescueTo(USDG) ahead of settle() in one batch.\",\n ];\n}\n"],"mappings":"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","names":[]}
@@ -18,8 +18,8 @@ import {
18
18
  robinhoodTestnet,
19
19
  setNetwork,
20
20
  withNetwork
21
- } from "./chunk-G3FUEM5N.js";
22
- import "./chunk-3TZIOAPH.js";
21
+ } from "./chunk-LIW6K4OJ.js";
22
+ import "./chunk-QUAVAJWE.js";
23
23
  export {
24
24
  CHAIN_REGISTRY,
25
25
  COORDINATION_ONLY_NETWORKS,
@@ -41,4 +41,4 @@ export {
41
41
  setNetwork,
42
42
  withNetwork
43
43
  };
44
- //# sourceMappingURL=network-7445KSCF.js.map
44
+ //# sourceMappingURL=network-EZ5X2BF7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,17 +1,19 @@
1
1
  import {
2
2
  quote
3
- } from "./chunk-QFGZQYZA.js";
3
+ } from "./chunk-WDPA2BYK.js";
4
+ import "./chunk-G5FOHSQW.js";
5
+ import "./chunk-QVXKYT2N.js";
4
6
  import {
5
7
  SYNTHRA
6
- } from "./chunk-FWQESFFM.js";
8
+ } from "./chunk-GYGSKMZE.js";
7
9
  import {
8
10
  getPublicClient
9
- } from "./chunk-D4BSBW3Q.js";
11
+ } from "./chunk-Z53JZORT.js";
10
12
  import {
11
13
  getNetwork
12
- } from "./chunk-G3FUEM5N.js";
13
- import "./chunk-3TZIOAPH.js";
14
- import "./chunk-J2IZWAEW.js";
14
+ } from "./chunk-LIW6K4OJ.js";
15
+ import "./chunk-QUAVAJWE.js";
16
+ import "./chunk-JCL2DEH3.js";
15
17
 
16
18
  // src/lib/price.ts
17
19
  import { parseUnits, formatUnits } from "viem";
@@ -133,4 +135,4 @@ export {
133
135
  getTokenPriceInAsset,
134
136
  getTokenPricesInAsset
135
137
  };
136
- //# sourceMappingURL=price-EXZDYVDD.js.map
138
+ //# sourceMappingURL=price-RX5J7GTO.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/lib/price.ts"],"sourcesContent":["/**\n * Network-aware price quoting for portfolio valuation.\n *\n * Dispatches to the right DEX quoter based on network:\n * - Base / Base Sepolia → Uniswap QuoterV2 (struct params, 4-tuple return)\n * - Robinhood testnet → Direct pool slot0 (Synthra QuoterV2 can't resolve\n * proxy-deployed pools via CREATE2, so we read sqrtPriceX96 from the pool)\n *\n * Uniswap quoter uses eth_call (not view — it reverts internally).\n */\n\nimport type { Address } from \"viem\";\nimport { parseUnits, formatUnits } from \"viem\";\nimport { getPublicClient } from \"./client.js\";\nimport { getNetwork } from \"./network.js\";\nimport { SYNTHRA } from \"./addresses.js\";\nimport { quote as swapRouterQuote } from \"./swap-router.js\";\n\nexport interface TokenPrice {\n price: number; // 1 token = X asset units (human-readable)\n amountOut: bigint; // raw quoter output\n source: \"uniswap\" | \"synthra\";\n}\n\nconst ZERO: Address = \"0x0000000000000000000000000000000000000000\";\n\n/**\n * Get the price of one token denominated in the strategy's asset.\n * Uses the appropriate DEX quoter for the current network.\n */\nexport async function getTokenPriceInAsset(params: {\n token: Address;\n tokenDecimals: number;\n asset: Address;\n assetDecimals: number;\n feeTier: number;\n}): Promise<TokenPrice> {\n const { token, tokenDecimals, asset, assetDecimals, feeTier } = params;\n\n // Short-circuit: token IS the asset\n if (token.toLowerCase() === asset.toLowerCase()) {\n return { price: 1.0, amountOut: parseUnits(\"1\", assetDecimals), source: \"uniswap\" };\n }\n\n const network = getNetwork();\n const client = getPublicClient();\n\n if (network === \"robinhood-testnet\") {\n return quoteSynthra(client, token, tokenDecimals, asset, assetDecimals, feeTier);\n }\n\n return quoteUniswap(client, token, tokenDecimals, asset, assetDecimals, feeTier);\n}\n\n/**\n * Batch price lookup — parallel, graceful failure (null per failed quote).\n */\nexport async function getTokenPricesInAsset(params: {\n tokens: { token: Address; tokenDecimals: number; feeTier: number }[];\n asset: Address;\n assetDecimals: number;\n}): Promise<(TokenPrice | null)[]> {\n const { tokens, asset, assetDecimals } = params;\n\n const results = await Promise.allSettled(\n tokens.map((t) =>\n getTokenPriceInAsset({\n token: t.token,\n tokenDecimals: t.tokenDecimals,\n asset,\n assetDecimals,\n feeTier: t.feeTier,\n }),\n ),\n );\n\n return results.map((r) => (r.status === \"fulfilled\" ? r.value : null));\n}\n\n// ── Synthra direct pool pricing (Robinhood testnet) ──\n//\n// The Synthra QuoterV2 can't resolve proxy-deployed pools via CREATE2 (same\n// issue that led to SynthraDirectAdapter). Instead we look up the pool via\n// factory.getPool(), read slot0.sqrtPriceX96, and derive the spot price.\n\nconst POOL_SLOT0_ABI = [\n {\n type: \"function\" as const,\n name: \"slot0\",\n inputs: [],\n outputs: [\n { name: \"sqrtPriceX96\", type: \"uint160\" as const },\n { name: \"tick\", type: \"int24\" as const },\n { name: \"observationIndex\", type: \"uint16\" as const },\n { name: \"observationCardinality\", type: \"uint16\" as const },\n { name: \"observationCardinalityNext\", type: \"uint16\" as const },\n { name: \"feeProtocol\", type: \"uint8\" as const },\n { name: \"unlocked\", type: \"bool\" as const },\n ],\n stateMutability: \"view\" as const,\n },\n] as const;\n\nconst POOL_TOKEN0_ABI = [\n {\n type: \"function\" as const,\n name: \"token0\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\" as const }],\n stateMutability: \"view\" as const,\n },\n] as const;\n\nconst FACTORY_GET_POOL_ABI = [\n {\n type: \"function\" as const,\n name: \"getPool\",\n inputs: [\n { name: \"tokenA\", type: \"address\" as const },\n { name: \"tokenB\", type: \"address\" as const },\n { name: \"fee\", type: \"uint24\" as const },\n ],\n outputs: [{ name: \"\", type: \"address\" as const }],\n stateMutability: \"view\" as const,\n },\n] as const;\n\n/**\n * Derive a spot price from a Uniswap V3 / Synthra V3 pool's sqrtPriceX96.\n *\n * sqrtPriceX96 = sqrt(token1/token0) × 2^96\n * price (token1 per token0) = (sqrtPriceX96 / 2^96)^2\n *\n * Returns the price of `tokenIn` denominated in `tokenOut`.\n */\nfunction priceFromSqrtPriceX96(\n sqrtPriceX96: bigint,\n token0Decimals: number,\n token1Decimals: number,\n tokenInIsToken0: boolean,\n): number {\n const Q96 = 2 ** 96;\n const ratio = Number(sqrtPriceX96) / Q96;\n // raw price = token1 per token0 (adjusted for same-decimal tokens only)\n const rawPrice = ratio * ratio;\n // decimal adjustment: token0Decimals - token1Decimals\n const decimalAdjust = 10 ** (token0Decimals - token1Decimals);\n const token1PerToken0 = rawPrice * decimalAdjust;\n\n // If tokenIn is token0, price = how many token1 per token0 → token1PerToken0\n // If tokenIn is token1, price = how many token0 per token1 → 1/token1PerToken0\n return tokenInIsToken0 ? token1PerToken0 : 1 / token1PerToken0;\n}\n\nasync function quoteSynthra(\n client: ReturnType<typeof getPublicClient>,\n tokenIn: Address,\n tokenInDecimals: number,\n tokenOut: Address,\n tokenOutDecimals: number,\n fee: number,\n): Promise<TokenPrice> {\n const factoryAddr = SYNTHRA().FACTORY;\n if (factoryAddr === ZERO) {\n throw new Error(\"Synthra Factory not deployed on this network\");\n }\n\n // 1. Resolve pool via factory.getPool()\n const pool = await client.readContract({\n address: factoryAddr,\n abi: FACTORY_GET_POOL_ABI,\n functionName: \"getPool\",\n args: [tokenIn, tokenOut, fee],\n });\n\n if (!pool || pool === ZERO) {\n throw new Error(`No Synthra pool for ${tokenIn}↔${tokenOut} fee=${fee}`);\n }\n\n // 2. Read slot0 and token0 from the pool\n const [slot0, token0] = await Promise.all([\n client.readContract({ address: pool, abi: POOL_SLOT0_ABI, functionName: \"slot0\" }),\n client.readContract({ address: pool, abi: POOL_TOKEN0_ABI, functionName: \"token0\" }),\n ]);\n\n const sqrtPriceX96 = slot0[0];\n if (sqrtPriceX96 === 0n) {\n throw new Error(`Pool ${pool} not initialized (sqrtPriceX96 = 0)`);\n }\n\n // 3. Determine token ordering\n const tokenInIsToken0 = tokenIn.toLowerCase() === token0.toLowerCase();\n const t0Decimals = tokenInIsToken0 ? tokenInDecimals : tokenOutDecimals;\n const t1Decimals = tokenInIsToken0 ? tokenOutDecimals : tokenInDecimals;\n\n const price = priceFromSqrtPriceX96(sqrtPriceX96, t0Decimals, t1Decimals, tokenInIsToken0);\n\n // Compute amountOut for 1 tokenIn\n const oneToken = parseUnits(\"1\", tokenInDecimals);\n const amountOut = BigInt(Math.round(price * Number(parseUnits(\"1\", tokenOutDecimals))));\n\n return { price, amountOut, source: \"synthra\" };\n}\n\n// ── Uniswap QuoterV2 (delegated to the SwapRouter) ──\n\nasync function quoteUniswap(\n client: ReturnType<typeof getPublicClient>,\n tokenIn: Address,\n tokenInDecimals: number,\n tokenOut: Address,\n tokenOutDecimals: number,\n fee: number,\n): Promise<TokenPrice> {\n const oneToken = parseUnits(\"1\", tokenInDecimals);\n\n const { amountOut } = await swapRouterQuote(\n { tokenIn, tokenOut, amountIn: oneToken, feeTier: fee },\n { client },\n );\n\n const price = Number(formatUnits(amountOut, tokenOutDecimals));\n return { price, amountOut, source: \"uniswap\" };\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/lib/price.ts"],"sourcesContent":["/**\n * Network-aware price quoting for portfolio valuation.\n *\n * Dispatches to the right DEX quoter based on network:\n * - Base / Base Sepolia → Uniswap QuoterV2 (struct params, 4-tuple return)\n * - Robinhood testnet → Direct pool slot0 (Synthra QuoterV2 can't resolve\n * proxy-deployed pools via CREATE2, so we read sqrtPriceX96 from the pool)\n *\n * Uniswap quoter uses eth_call (not view — it reverts internally).\n */\n\nimport type { Address } from \"viem\";\nimport { parseUnits, formatUnits } from \"viem\";\nimport { getPublicClient } from \"./client.js\";\nimport { getNetwork } from \"./network.js\";\nimport { SYNTHRA } from \"./addresses.js\";\nimport { quote as swapRouterQuote } from \"./swap-router.js\";\n\nexport interface TokenPrice {\n price: number; // 1 token = X asset units (human-readable)\n amountOut: bigint; // raw quoter output\n source: \"uniswap\" | \"synthra\";\n}\n\nconst ZERO: Address = \"0x0000000000000000000000000000000000000000\";\n\n/**\n * Get the price of one token denominated in the strategy's asset.\n * Uses the appropriate DEX quoter for the current network.\n */\nexport async function getTokenPriceInAsset(params: {\n token: Address;\n tokenDecimals: number;\n asset: Address;\n assetDecimals: number;\n feeTier: number;\n}): Promise<TokenPrice> {\n const { token, tokenDecimals, asset, assetDecimals, feeTier } = params;\n\n // Short-circuit: token IS the asset\n if (token.toLowerCase() === asset.toLowerCase()) {\n return { price: 1.0, amountOut: parseUnits(\"1\", assetDecimals), source: \"uniswap\" };\n }\n\n const network = getNetwork();\n const client = getPublicClient();\n\n if (network === \"robinhood-testnet\") {\n return quoteSynthra(client, token, tokenDecimals, asset, assetDecimals, feeTier);\n }\n\n return quoteUniswap(client, token, tokenDecimals, asset, assetDecimals, feeTier);\n}\n\n/**\n * Batch price lookup — parallel, graceful failure (null per failed quote).\n */\nexport async function getTokenPricesInAsset(params: {\n tokens: { token: Address; tokenDecimals: number; feeTier: number }[];\n asset: Address;\n assetDecimals: number;\n}): Promise<(TokenPrice | null)[]> {\n const { tokens, asset, assetDecimals } = params;\n\n const results = await Promise.allSettled(\n tokens.map((t) =>\n getTokenPriceInAsset({\n token: t.token,\n tokenDecimals: t.tokenDecimals,\n asset,\n assetDecimals,\n feeTier: t.feeTier,\n }),\n ),\n );\n\n return results.map((r) => (r.status === \"fulfilled\" ? r.value : null));\n}\n\n// ── Synthra direct pool pricing (Robinhood testnet) ──\n//\n// The Synthra QuoterV2 can't resolve proxy-deployed pools via CREATE2 (same\n// issue that led to SynthraDirectAdapter). Instead we look up the pool via\n// factory.getPool(), read slot0.sqrtPriceX96, and derive the spot price.\n\nconst POOL_SLOT0_ABI = [\n {\n type: \"function\" as const,\n name: \"slot0\",\n inputs: [],\n outputs: [\n { name: \"sqrtPriceX96\", type: \"uint160\" as const },\n { name: \"tick\", type: \"int24\" as const },\n { name: \"observationIndex\", type: \"uint16\" as const },\n { name: \"observationCardinality\", type: \"uint16\" as const },\n { name: \"observationCardinalityNext\", type: \"uint16\" as const },\n { name: \"feeProtocol\", type: \"uint8\" as const },\n { name: \"unlocked\", type: \"bool\" as const },\n ],\n stateMutability: \"view\" as const,\n },\n] as const;\n\nconst POOL_TOKEN0_ABI = [\n {\n type: \"function\" as const,\n name: \"token0\",\n inputs: [],\n outputs: [{ name: \"\", type: \"address\" as const }],\n stateMutability: \"view\" as const,\n },\n] as const;\n\nconst FACTORY_GET_POOL_ABI = [\n {\n type: \"function\" as const,\n name: \"getPool\",\n inputs: [\n { name: \"tokenA\", type: \"address\" as const },\n { name: \"tokenB\", type: \"address\" as const },\n { name: \"fee\", type: \"uint24\" as const },\n ],\n outputs: [{ name: \"\", type: \"address\" as const }],\n stateMutability: \"view\" as const,\n },\n] as const;\n\n/**\n * Derive a spot price from a Uniswap V3 / Synthra V3 pool's sqrtPriceX96.\n *\n * sqrtPriceX96 = sqrt(token1/token0) × 2^96\n * price (token1 per token0) = (sqrtPriceX96 / 2^96)^2\n *\n * Returns the price of `tokenIn` denominated in `tokenOut`.\n */\nfunction priceFromSqrtPriceX96(\n sqrtPriceX96: bigint,\n token0Decimals: number,\n token1Decimals: number,\n tokenInIsToken0: boolean,\n): number {\n const Q96 = 2 ** 96;\n const ratio = Number(sqrtPriceX96) / Q96;\n // raw price = token1 per token0 (adjusted for same-decimal tokens only)\n const rawPrice = ratio * ratio;\n // decimal adjustment: token0Decimals - token1Decimals\n const decimalAdjust = 10 ** (token0Decimals - token1Decimals);\n const token1PerToken0 = rawPrice * decimalAdjust;\n\n // If tokenIn is token0, price = how many token1 per token0 → token1PerToken0\n // If tokenIn is token1, price = how many token0 per token1 → 1/token1PerToken0\n return tokenInIsToken0 ? token1PerToken0 : 1 / token1PerToken0;\n}\n\nasync function quoteSynthra(\n client: ReturnType<typeof getPublicClient>,\n tokenIn: Address,\n tokenInDecimals: number,\n tokenOut: Address,\n tokenOutDecimals: number,\n fee: number,\n): Promise<TokenPrice> {\n const factoryAddr = SYNTHRA().FACTORY;\n if (factoryAddr === ZERO) {\n throw new Error(\"Synthra Factory not deployed on this network\");\n }\n\n // 1. Resolve pool via factory.getPool()\n const pool = await client.readContract({\n address: factoryAddr,\n abi: FACTORY_GET_POOL_ABI,\n functionName: \"getPool\",\n args: [tokenIn, tokenOut, fee],\n });\n\n if (!pool || pool === ZERO) {\n throw new Error(`No Synthra pool for ${tokenIn}↔${tokenOut} fee=${fee}`);\n }\n\n // 2. Read slot0 and token0 from the pool\n const [slot0, token0] = await Promise.all([\n client.readContract({ address: pool, abi: POOL_SLOT0_ABI, functionName: \"slot0\" }),\n client.readContract({ address: pool, abi: POOL_TOKEN0_ABI, functionName: \"token0\" }),\n ]);\n\n const sqrtPriceX96 = slot0[0];\n if (sqrtPriceX96 === 0n) {\n throw new Error(`Pool ${pool} not initialized (sqrtPriceX96 = 0)`);\n }\n\n // 3. Determine token ordering\n const tokenInIsToken0 = tokenIn.toLowerCase() === token0.toLowerCase();\n const t0Decimals = tokenInIsToken0 ? tokenInDecimals : tokenOutDecimals;\n const t1Decimals = tokenInIsToken0 ? tokenOutDecimals : tokenInDecimals;\n\n const price = priceFromSqrtPriceX96(sqrtPriceX96, t0Decimals, t1Decimals, tokenInIsToken0);\n\n // Compute amountOut for 1 tokenIn\n const oneToken = parseUnits(\"1\", tokenInDecimals);\n const amountOut = BigInt(Math.round(price * Number(parseUnits(\"1\", tokenOutDecimals))));\n\n return { price, amountOut, source: \"synthra\" };\n}\n\n// ── Uniswap QuoterV2 (delegated to the SwapRouter) ──\n\nasync function quoteUniswap(\n client: ReturnType<typeof getPublicClient>,\n tokenIn: Address,\n tokenInDecimals: number,\n tokenOut: Address,\n tokenOutDecimals: number,\n fee: number,\n): Promise<TokenPrice> {\n const oneToken = parseUnits(\"1\", tokenInDecimals);\n\n const { amountOut } = await swapRouterQuote(\n { tokenIn, tokenOut, amountIn: oneToken, feeTier: fee },\n { client },\n );\n\n const price = Number(formatUnits(amountOut, tokenOutDecimals));\n return { price, amountOut, source: \"uniswap\" };\n}\n"],"mappings":"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","names":[]}
@@ -2,12 +2,12 @@ import {
2
2
  MessariProvider,
3
3
  NansenProvider,
4
4
  getResearchProvider
5
- } from "./chunk-6SAE2VDK.js";
6
- import "./chunk-D4BSBW3Q.js";
5
+ } from "./chunk-6IC2NRED.js";
6
+ import "./chunk-Z53JZORT.js";
7
7
  import {
8
8
  robinhoodTestnet
9
- } from "./chunk-G3FUEM5N.js";
10
- import "./chunk-3TZIOAPH.js";
9
+ } from "./chunk-LIW6K4OJ.js";
10
+ import "./chunk-QUAVAJWE.js";
11
11
 
12
12
  // src/providers/index.ts
13
13
  function listProviders() {
@@ -28,4 +28,4 @@ export {
28
28
  getResearchProvider,
29
29
  listProviders
30
30
  };
31
- //# sourceMappingURL=providers-6UZKDFQD.js.map
31
+ //# sourceMappingURL=providers-XEEFKITN.js.map
@@ -2,13 +2,13 @@ import {
2
2
  MESSARI_COST_ESTIMATE,
3
3
  NANSEN_COST_ESTIMATE,
4
4
  getResearchProvider
5
- } from "./chunk-6SAE2VDK.js";
5
+ } from "./chunk-6IC2NRED.js";
6
6
  import {
7
7
  formatContractError,
8
8
  getAccount
9
- } from "./chunk-D4BSBW3Q.js";
10
- import "./chunk-G3FUEM5N.js";
11
- import "./chunk-3TZIOAPH.js";
9
+ } from "./chunk-Z53JZORT.js";
10
+ import "./chunk-LIW6K4OJ.js";
11
+ import "./chunk-QUAVAJWE.js";
12
12
 
13
13
  // src/commands/research.ts
14
14
  import chalk from "chalk";
@@ -16,7 +16,7 @@ import ora from "ora";
16
16
  import { confirm } from "@inquirer/prompts";
17
17
  import { isAddress } from "viem";
18
18
  async function loadXmtp() {
19
- return import("./xmtp-72IRK7JL.js");
19
+ return import("./xmtp-5PTIIVAI.js");
20
20
  }
21
21
  var COST_ESTIMATES = {
22
22
  messari: MESSARI_COST_ESTIMATE,
@@ -83,7 +83,7 @@ function formatValue(value) {
83
83
  }
84
84
  async function postResearch(fundName, result, prompt) {
85
85
  const { pinJSON } = await import("./ipfs-M56BLMCW.js");
86
- const { createResearchAttestation, getEasScanUrl } = await import("./eas-B4HR2HXX.js");
86
+ const { createResearchAttestation, getEasScanUrl } = await import("./eas-ZH7BDEOK.js");
87
87
  const xmtp = await loadXmtp();
88
88
  const pinSpinner = ora("Pinning research result to IPFS...").start();
89
89
  let resultUri;
@@ -112,8 +112,8 @@ async function postResearch(fundName, result, prompt) {
112
112
  const easSpinner = ora("Creating EAS attestation...").start();
113
113
  let attestationUid;
114
114
  try {
115
- const { getChainContracts } = await import("./config-ZGFS4I7K.js");
116
- const { getChain } = await import("./network-7445KSCF.js");
115
+ const { getChainContracts } = await import("./config-UZ2GIXAO.js");
116
+ const { getChain } = await import("./network-EZ5X2BF7.js");
117
117
  const vaultRecipient = getChainContracts(getChain().id).vault;
118
118
  const attestation = await createResearchAttestation(
119
119
  result.provider,
@@ -315,4 +315,4 @@ function registerResearchCommands(program) {
315
315
  export {
316
316
  registerResearchCommands
317
317
  };
318
- //# sourceMappingURL=research-T7A27OMB.js.map
318
+ //# sourceMappingURL=research-PYMQ5VKH.js.map
@@ -4,9 +4,6 @@ import {
4
4
  resetSession,
5
5
  updateSession
6
6
  } from "./chunk-5DWB5Y7G.js";
7
- import {
8
- resolveFund
9
- } from "./chunk-4ITTHKRX.js";
10
7
  import {
11
8
  enrichProposalEvents,
12
9
  getCurrentBlock,
@@ -14,29 +11,32 @@ import {
14
11
  getGuardianRegistryEvents,
15
12
  getStakedWoodEvents,
16
13
  getVaultEvents
17
- } from "./chunk-BH3VTJ4F.js";
14
+ } from "./chunk-JKSDCCVL.js";
15
+ import "./chunk-YMB4RJOR.js";
16
+ import {
17
+ resolveFund
18
+ } from "./chunk-P4LFNKSX.js";
18
19
  import {
19
20
  getGovernorOf
20
- } from "./chunk-G5MXVAFC.js";
21
+ } from "./chunk-D3GTHAJS.js";
21
22
  import {
22
23
  SHERWOOD
23
- } from "./chunk-FWQESFFM.js";
24
+ } from "./chunk-GYGSKMZE.js";
24
25
  import {
25
26
  getPublicClient
26
- } from "./chunk-D4BSBW3Q.js";
27
- import "./chunk-G3FUEM5N.js";
27
+ } from "./chunk-Z53JZORT.js";
28
+ import "./chunk-LIW6K4OJ.js";
28
29
  import {
29
30
  loadConfig
30
- } from "./chunk-3TZIOAPH.js";
31
+ } from "./chunk-QUAVAJWE.js";
31
32
  import {
32
33
  SYNDICATE_VAULT_ABI
33
- } from "./chunk-J2IZWAEW.js";
34
- import "./chunk-YMB4RJOR.js";
34
+ } from "./chunk-JCL2DEH3.js";
35
35
 
36
36
  // src/commands/session.ts
37
37
  import chalk from "chalk";
38
38
  async function loadXmtp() {
39
- return import("./xmtp-72IRK7JL.js");
39
+ return import("./xmtp-5PTIIVAI.js");
40
40
  }
41
41
  async function resolveGovernor(vaultAddress) {
42
42
  const client = getPublicClient();
@@ -313,8 +313,8 @@ function registerSessionCommands(program) {
313
313
  );
314
314
  session.command("cron <name>").description("Manage participation crons (OpenClaw agents)").option("--remove", "Remove participation crons", false).option("--status", "Show cron status", false).action(async (name, opts) => {
315
315
  const { isOpenClaw, registerFundCrons, unregisterFundCrons, getFundCronStatus } = await import("./cron-E3UAZF5B.js");
316
- const { isTestnet } = await import("./network-7445KSCF.js");
317
- const { getNotifyTo } = await import("./config-ZGFS4I7K.js");
316
+ const { isTestnet } = await import("./network-EZ5X2BF7.js");
317
+ const { getNotifyTo } = await import("./config-UZ2GIXAO.js");
318
318
  if (!isOpenClaw()) {
319
319
  console.log(chalk.yellow("Not running on OpenClaw \u2014 cron commands unavailable"));
320
320
  console.log(chalk.dim(` Set up your own scheduler: sherwood session check ${name} --stream`));
@@ -355,4 +355,4 @@ function registerSessionCommands(program) {
355
355
  export {
356
356
  registerSessionCommands
357
357
  };
358
- //# sourceMappingURL=session-45NQAHFI.js.map
358
+ //# sourceMappingURL=session-DE47TUEW.js.map
@@ -1,36 +1,38 @@
1
1
  import {
2
2
  getResearchProvider
3
- } from "./chunk-6SAE2VDK.js";
3
+ } from "./chunk-6IC2NRED.js";
4
4
  import "./chunk-EGJESQXZ.js";
5
5
  import {
6
6
  chatCompletion
7
- } from "./chunk-EEI6FRTE.js";
7
+ } from "./chunk-JLOROS5V.js";
8
8
  import {
9
9
  getQuote
10
- } from "./chunk-QFGZQYZA.js";
10
+ } from "./chunk-WDPA2BYK.js";
11
+ import "./chunk-G5FOHSQW.js";
12
+ import "./chunk-QVXKYT2N.js";
11
13
  import {
12
14
  TOKENS
13
- } from "./chunk-FWQESFFM.js";
15
+ } from "./chunk-GYGSKMZE.js";
14
16
  import {
15
17
  formatContractError,
16
18
  getAccount,
17
19
  getPublicClient,
18
20
  sendTxWithRetry,
19
21
  waitForReceipt
20
- } from "./chunk-D4BSBW3Q.js";
22
+ } from "./chunk-Z53JZORT.js";
21
23
  import {
22
24
  getChain,
23
25
  getExplorerUrl,
24
26
  getNetwork
25
- } from "./chunk-G3FUEM5N.js";
27
+ } from "./chunk-LIW6K4OJ.js";
26
28
  import {
27
29
  getUniswapApiKey,
28
30
  loadConfig,
29
31
  saveConfig
30
- } from "./chunk-3TZIOAPH.js";
32
+ } from "./chunk-QUAVAJWE.js";
31
33
  import {
32
34
  ERC20_ABI
33
- } from "./chunk-J2IZWAEW.js";
35
+ } from "./chunk-JCL2DEH3.js";
34
36
 
35
37
  // src/commands/trade.ts
36
38
  import chalk from "chalk";
@@ -555,7 +557,7 @@ async function getCurrentPrice(tokenAddress, tokenDecimals, feeTier) {
555
557
  // src/commands/trade.ts
556
558
  var uniswap = new UniswapProvider();
557
559
  async function loadXmtp() {
558
- return import("./xmtp-72IRK7JL.js");
560
+ return import("./xmtp-5PTIIVAI.js");
559
561
  }
560
562
  var ETH_ADDRESS = "0x0000000000000000000000000000000000000000";
561
563
  var KNOWN_MEMECOINS = {
@@ -752,7 +754,7 @@ function registerTradeCommands(program) {
752
754
  }
753
755
  const wrapSpinner = ora("Wrapping ETH \u2192 WETH...").start();
754
756
  try {
755
- const { writeContractWithRetry: writeContractWithRetry2, waitForReceipt: waitForReceiptFn } = await import("./client-PYFE6YQR.js");
757
+ const { writeContractWithRetry: writeContractWithRetry2, waitForReceipt: waitForReceiptFn } = await import("./client-DA434B67.js");
756
758
  const wethAddr = TOKENS().WETH;
757
759
  const wrapHash = await writeContractWithRetry2({
758
760
  address: wethAddr,
@@ -761,7 +763,7 @@ function registerTradeCommands(program) {
761
763
  args: [],
762
764
  value: inputAmount,
763
765
  account,
764
- chain: (await import("./network-7445KSCF.js")).getChain()
766
+ chain: (await import("./network-EZ5X2BF7.js")).getChain()
765
767
  });
766
768
  await waitForReceiptFn(wrapHash);
767
769
  wrapSpinner.succeed(`Wrapped ${opts.amount} ETH \u2192 WETH`);
@@ -875,9 +877,9 @@ function registerTradeCommands(program) {
875
877
  }
876
878
  console.log(` Tx: ${chalk.dim(getExplorerUrl(txHash))}`);
877
879
  try {
878
- const { createTradeAttestation, getEasScanUrl } = await import("./eas-B4HR2HXX.js");
879
- const { getChainContracts } = await import("./config-ZGFS4I7K.js");
880
- const { getChain: getActiveChain } = await import("./network-7445KSCF.js");
880
+ const { createTradeAttestation, getEasScanUrl } = await import("./eas-ZH7BDEOK.js");
881
+ const { getChainContracts } = await import("./config-UZ2GIXAO.js");
882
+ const { getChain: getActiveChain } = await import("./network-EZ5X2BF7.js");
881
883
  const vaultRecipient = getChainContracts(getActiveChain().id).vault;
882
884
  const attestation = await createTradeAttestation(
883
885
  inputAddr,
@@ -1003,9 +1005,9 @@ function registerTradeCommands(program) {
1003
1005
  }
1004
1006
  console.log(` Tx: ${chalk.dim(getExplorerUrl(txHash))}`);
1005
1007
  try {
1006
- const { createTradeAttestation, getEasScanUrl } = await import("./eas-B4HR2HXX.js");
1007
- const { getChainContracts } = await import("./config-ZGFS4I7K.js");
1008
- const { getChain: getActiveChain } = await import("./network-7445KSCF.js");
1008
+ const { createTradeAttestation, getEasScanUrl } = await import("./eas-ZH7BDEOK.js");
1009
+ const { getChainContracts } = await import("./config-UZ2GIXAO.js");
1010
+ const { getChain: getActiveChain } = await import("./network-EZ5X2BF7.js");
1009
1011
  const vaultRecipient = getChainContracts(getActiveChain().id).vault;
1010
1012
  const attestation = await createTradeAttestation(
1011
1013
  tokenAddr,
@@ -1180,4 +1182,4 @@ function sleep(ms) {
1180
1182
  export {
1181
1183
  registerTradeCommands
1182
1184
  };
1183
- //# sourceMappingURL=trade-ZOVM433K.js.map
1185
+ //# sourceMappingURL=trade-3VMAQ75D.js.map