@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.
- package/dist/{abis-WJQ6IVYV.js → abis-2VBXBA7Y.js} +16 -2
- package/dist/{agent-FCGZL4GF.js → agent-KMLNSKBS.js} +11 -11
- package/dist/{chat-AKLYUJZV.js → chat-JW5Z3JRE.js} +13 -13
- package/dist/{chunk-6SAE2VDK.js → chunk-6IC2NRED.js} +2 -2
- package/dist/{chunk-HMFPP2PE.js → chunk-77MBGRE5.js} +52 -24
- package/dist/chunk-77MBGRE5.js.map +1 -0
- package/dist/{chunk-G5MXVAFC.js → chunk-D3GTHAJS.js} +5 -5
- package/dist/chunk-G5FOHSQW.js +338 -0
- package/dist/chunk-G5FOHSQW.js.map +1 -0
- package/dist/chunk-GAQMHH44.js +18 -0
- package/dist/chunk-GAQMHH44.js.map +1 -0
- package/dist/{chunk-FWQESFFM.js → chunk-GYGSKMZE.js} +91 -8
- package/dist/chunk-GYGSKMZE.js.map +1 -0
- package/dist/{chunk-J2IZWAEW.js → chunk-JCL2DEH3.js} +2048 -2
- package/dist/chunk-JCL2DEH3.js.map +1 -0
- package/dist/{chunk-BH3VTJ4F.js → chunk-JKSDCCVL.js} +6 -6
- package/dist/{chunk-EEI6FRTE.js → chunk-JLOROS5V.js} +3 -3
- package/dist/{chunk-6D3FNU75.js → chunk-JRGYI34A.js} +5 -5
- package/dist/chunk-KZGY7NT7.js +209 -0
- package/dist/chunk-KZGY7NT7.js.map +1 -0
- package/dist/{chunk-G3FUEM5N.js → chunk-LIW6K4OJ.js} +2 -2
- package/dist/{chunk-4ITTHKRX.js → chunk-P4LFNKSX.js} +5 -5
- package/dist/{chunk-3TZIOAPH.js → chunk-QUAVAJWE.js} +13 -2
- package/dist/chunk-QUAVAJWE.js.map +1 -0
- package/dist/chunk-QVXKYT2N.js +489 -0
- package/dist/chunk-QVXKYT2N.js.map +1 -0
- package/dist/chunk-UPRFO4YU.js +458 -0
- package/dist/chunk-UPRFO4YU.js.map +1 -0
- package/dist/{chunk-QFGZQYZA.js → chunk-WDPA2BYK.js} +1024 -87
- package/dist/chunk-WDPA2BYK.js.map +1 -0
- package/dist/{chunk-CWGP4VXZ.js → chunk-YIN6R66K.js} +7 -7
- package/dist/{chunk-D4BSBW3Q.js → chunk-Z53JZORT.js} +3 -3
- package/dist/{chunk-SCQAKMMI.js → chunk-ZPOPWFSP.js} +5 -5
- package/dist/{client-PYFE6YQR.js → client-DA434B67.js} +4 -4
- package/dist/{config-ZGFS4I7K.js → config-UZ2GIXAO.js} +6 -2
- package/dist/{eas-B4HR2HXX.js → eas-ZH7BDEOK.js} +7 -7
- package/dist/{governor-QFBN6RYS.js → governor-WHT2V2EU.js} +7 -7
- package/dist/identity-TRPUQEQK.js +19 -0
- package/dist/index.js +7758 -5862
- package/dist/index.js.map +1 -1
- package/dist/launchpad-3N4ZFL6J.js +26 -0
- package/dist/lighter-perp-template-VC4TB7AM.js +92 -0
- package/dist/lighter-preflight-GH3JKLR6.js +149 -0
- package/dist/lighter-preflight-GH3JKLR6.js.map +1 -0
- package/dist/{network-7445KSCF.js → network-EZ5X2BF7.js} +3 -3
- package/dist/network-EZ5X2BF7.js.map +1 -0
- package/dist/{price-EXZDYVDD.js → price-RX5J7GTO.js} +9 -7
- package/dist/{price-EXZDYVDD.js.map → price-RX5J7GTO.js.map} +1 -1
- package/dist/{providers-6UZKDFQD.js → providers-XEEFKITN.js} +5 -5
- package/dist/{research-T7A27OMB.js → research-PYMQ5VKH.js} +9 -9
- package/dist/{session-45NQAHFI.js → session-DE47TUEW.js} +15 -15
- package/dist/{trade-ZOVM433K.js → trade-3VMAQ75D.js} +20 -18
- package/dist/{trade-ZOVM433K.js.map → trade-3VMAQ75D.js.map} +1 -1
- package/dist/{vault-E7XD6DLD.js → vault-PXGG2E3K.js} +9 -9
- package/dist/vault-PXGG2E3K.js.map +1 -0
- package/dist/{xmtp-72IRK7JL.js → xmtp-5PTIIVAI.js} +7 -7
- package/package.json +1 -1
- package/dist/chunk-3TZIOAPH.js.map +0 -1
- package/dist/chunk-FWQESFFM.js.map +0 -1
- package/dist/chunk-HMFPP2PE.js.map +0 -1
- package/dist/chunk-J2IZWAEW.js.map +0 -1
- package/dist/chunk-QFGZQYZA.js.map +0 -1
- package/dist/identity-I2BG4IGT.js +0 -18
- /package/dist/{abis-WJQ6IVYV.js.map → abis-2VBXBA7Y.js.map} +0 -0
- /package/dist/{agent-FCGZL4GF.js.map → agent-KMLNSKBS.js.map} +0 -0
- /package/dist/{chat-AKLYUJZV.js.map → chat-JW5Z3JRE.js.map} +0 -0
- /package/dist/{chunk-6SAE2VDK.js.map → chunk-6IC2NRED.js.map} +0 -0
- /package/dist/{chunk-G5MXVAFC.js.map → chunk-D3GTHAJS.js.map} +0 -0
- /package/dist/{chunk-BH3VTJ4F.js.map → chunk-JKSDCCVL.js.map} +0 -0
- /package/dist/{chunk-EEI6FRTE.js.map → chunk-JLOROS5V.js.map} +0 -0
- /package/dist/{chunk-6D3FNU75.js.map → chunk-JRGYI34A.js.map} +0 -0
- /package/dist/{chunk-G3FUEM5N.js.map → chunk-LIW6K4OJ.js.map} +0 -0
- /package/dist/{chunk-4ITTHKRX.js.map → chunk-P4LFNKSX.js.map} +0 -0
- /package/dist/{chunk-CWGP4VXZ.js.map → chunk-YIN6R66K.js.map} +0 -0
- /package/dist/{chunk-D4BSBW3Q.js.map → chunk-Z53JZORT.js.map} +0 -0
- /package/dist/{chunk-SCQAKMMI.js.map → chunk-ZPOPWFSP.js.map} +0 -0
- /package/dist/{client-PYFE6YQR.js.map → client-DA434B67.js.map} +0 -0
- /package/dist/{config-ZGFS4I7K.js.map → config-UZ2GIXAO.js.map} +0 -0
- /package/dist/{eas-B4HR2HXX.js.map → eas-ZH7BDEOK.js.map} +0 -0
- /package/dist/{governor-QFBN6RYS.js.map → governor-WHT2V2EU.js.map} +0 -0
- /package/dist/{identity-I2BG4IGT.js.map → identity-TRPUQEQK.js.map} +0 -0
- /package/dist/{network-7445KSCF.js.map → launchpad-3N4ZFL6J.js.map} +0 -0
- /package/dist/{vault-E7XD6DLD.js.map → lighter-perp-template-VC4TB7AM.js.map} +0 -0
- /package/dist/{providers-6UZKDFQD.js.map → providers-XEEFKITN.js.map} +0 -0
- /package/dist/{research-T7A27OMB.js.map → research-PYMQ5VKH.js.map} +0 -0
- /package/dist/{session-45NQAHFI.js.map → session-DE47TUEW.js.map} +0 -0
- /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-
|
|
22
|
-
import "./chunk-
|
|
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-
|
|
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-
|
|
3
|
+
} from "./chunk-WDPA2BYK.js";
|
|
4
|
+
import "./chunk-G5FOHSQW.js";
|
|
5
|
+
import "./chunk-QVXKYT2N.js";
|
|
4
6
|
import {
|
|
5
7
|
SYNTHRA
|
|
6
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-GYGSKMZE.js";
|
|
7
9
|
import {
|
|
8
10
|
getPublicClient
|
|
9
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-Z53JZORT.js";
|
|
10
12
|
import {
|
|
11
13
|
getNetwork
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
14
|
-
import "./chunk-
|
|
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-
|
|
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":";;;;;;;;;;;;;;;;AAYA,SAAS,YAAY,mBAAmB;AAYxC,IAAM,OAAgB;AAMtB,eAAsB,qBAAqB,QAMnB;AACtB,QAAM,EAAE,OAAO,eAAe,OAAO,eAAe,QAAQ,IAAI;AAGhE,MAAI,MAAM,YAAY,MAAM,MAAM,YAAY,GAAG;AAC/C,WAAO,EAAE,OAAO,GAAK,WAAW,WAAW,KAAK,aAAa,GAAG,QAAQ,UAAU;AAAA,EACpF;AAEA,QAAM,UAAU,WAAW;AAC3B,QAAM,SAAS,gBAAgB;AAE/B,MAAI,YAAY,qBAAqB;AACnC,WAAO,aAAa,QAAQ,OAAO,eAAe,OAAO,eAAe,OAAO;AAAA,EACjF;AAEA,SAAO,aAAa,QAAQ,OAAO,eAAe,OAAO,eAAe,OAAO;AACjF;AAKA,eAAsB,sBAAsB,QAIT;AACjC,QAAM,EAAE,QAAQ,OAAO,cAAc,IAAI;AAEzC,QAAM,UAAU,MAAM,QAAQ;AAAA,IAC5B,OAAO;AAAA,MAAI,CAAC,MACV,qBAAqB;AAAA,QACnB,OAAO,EAAE;AAAA,QACT,eAAe,EAAE;AAAA,QACjB;AAAA,QACA;AAAA,QACA,SAAS,EAAE;AAAA,MACb,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,QAAQ,IAAI,CAAC,MAAO,EAAE,WAAW,cAAc,EAAE,QAAQ,IAAK;AACvE;AAQA,IAAM,iBAAiB;AAAA,EACrB;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ,CAAC;AAAA,IACT,SAAS;AAAA,MACP,EAAE,MAAM,gBAAgB,MAAM,UAAmB;AAAA,MACjD,EAAE,MAAM,QAAQ,MAAM,QAAiB;AAAA,MACvC,EAAE,MAAM,oBAAoB,MAAM,SAAkB;AAAA,MACpD,EAAE,MAAM,0BAA0B,MAAM,SAAkB;AAAA,MAC1D,EAAE,MAAM,8BAA8B,MAAM,SAAkB;AAAA,MAC9D,EAAE,MAAM,eAAe,MAAM,QAAiB;AAAA,MAC9C,EAAE,MAAM,YAAY,MAAM,OAAgB;AAAA,IAC5C;AAAA,IACA,iBAAiB;AAAA,EACnB;AACF;AAEA,IAAM,kBAAkB;AAAA,EACtB;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ,CAAC;AAAA,IACT,SAAS,CAAC,EAAE,MAAM,IAAI,MAAM,UAAmB,CAAC;AAAA,IAChD,iBAAiB;AAAA,EACnB;AACF;AAEA,IAAM,uBAAuB;AAAA,EAC3B;AAAA,IACE,MAAM;AAAA,IACN,MAAM;AAAA,IACN,QAAQ;AAAA,MACN,EAAE,MAAM,UAAU,MAAM,UAAmB;AAAA,MAC3C,EAAE,MAAM,UAAU,MAAM,UAAmB;AAAA,MAC3C,EAAE,MAAM,OAAO,MAAM,SAAkB;AAAA,IACzC;AAAA,IACA,SAAS,CAAC,EAAE,MAAM,IAAI,MAAM,UAAmB,CAAC;AAAA,IAChD,iBAAiB;AAAA,EACnB;AACF;AAUA,SAAS,sBACP,cACA,gBACA,gBACA,iBACQ;AACR,QAAM,MAAM,KAAK;AACjB,QAAM,QAAQ,OAAO,YAAY,IAAI;AAErC,QAAM,WAAW,QAAQ;AAEzB,QAAM,gBAAgB,OAAO,iBAAiB;AAC9C,QAAM,kBAAkB,WAAW;AAInC,SAAO,kBAAkB,kBAAkB,IAAI;AACjD;AAEA,eAAe,aACb,QACA,SACA,iBACA,UACA,kBACA,KACqB;AACrB,QAAM,cAAc,QAAQ,EAAE;AAC9B,MAAI,gBAAgB,MAAM;AACxB,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AAGA,QAAM,OAAO,MAAM,OAAO,aAAa;AAAA,IACrC,SAAS;AAAA,IACT,KAAK;AAAA,IACL,cAAc;AAAA,IACd,MAAM,CAAC,SAAS,UAAU,GAAG;AAAA,EAC/B,CAAC;AAED,MAAI,CAAC,QAAQ,SAAS,MAAM;AAC1B,UAAM,IAAI,MAAM,uBAAuB,OAAO,SAAI,QAAQ,QAAQ,GAAG,EAAE;AAAA,EACzE;AAGA,QAAM,CAAC,OAAO,MAAM,IAAI,MAAM,QAAQ,IAAI;AAAA,IACxC,OAAO,aAAa,EAAE,SAAS,MAAM,KAAK,gBAAgB,cAAc,QAAQ,CAAC;AAAA,IACjF,OAAO,aAAa,EAAE,SAAS,MAAM,KAAK,iBAAiB,cAAc,SAAS,CAAC;AAAA,EACrF,CAAC;AAED,QAAM,eAAe,MAAM,CAAC;AAC5B,MAAI,iBAAiB,IAAI;AACvB,UAAM,IAAI,MAAM,QAAQ,IAAI,qCAAqC;AAAA,EACnE;AAGA,QAAM,kBAAkB,QAAQ,YAAY,MAAM,OAAO,YAAY;AACrE,QAAM,aAAa,kBAAkB,kBAAkB;AACvD,QAAM,aAAa,kBAAkB,mBAAmB;AAExD,QAAM,QAAQ,sBAAsB,cAAc,YAAY,YAAY,eAAe;AAGzF,QAAM,WAAW,WAAW,KAAK,eAAe;AAChD,QAAM,YAAY,OAAO,KAAK,MAAM,QAAQ,OAAO,WAAW,KAAK,gBAAgB,CAAC,CAAC,CAAC;AAEtF,SAAO,EAAE,OAAO,WAAW,QAAQ,UAAU;AAC/C;AAIA,eAAe,aACb,QACA,SACA,iBACA,UACA,kBACA,KACqB;AACrB,QAAM,WAAW,WAAW,KAAK,eAAe;AAEhD,QAAM,EAAE,UAAU,IAAI,MAAM;AAAA,IAC1B,EAAE,SAAS,UAAU,UAAU,UAAU,SAAS,IAAI;AAAA,IACtD,EAAE,OAAO;AAAA,EACX;AAEA,QAAM,QAAQ,OAAO,YAAY,WAAW,gBAAgB,CAAC;AAC7D,SAAO,EAAE,OAAO,WAAW,QAAQ,UAAU;AAC/C;","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-
|
|
6
|
-
import "./chunk-
|
|
5
|
+
} from "./chunk-6IC2NRED.js";
|
|
6
|
+
import "./chunk-Z53JZORT.js";
|
|
7
7
|
import {
|
|
8
8
|
robinhoodTestnet
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
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-
|
|
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-
|
|
5
|
+
} from "./chunk-6IC2NRED.js";
|
|
6
6
|
import {
|
|
7
7
|
formatContractError,
|
|
8
8
|
getAccount
|
|
9
|
-
} from "./chunk-
|
|
10
|
-
import "./chunk-
|
|
11
|
-
import "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
116
|
-
const { getChain } = await import("./network-
|
|
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-
|
|
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-
|
|
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-
|
|
21
|
+
} from "./chunk-D3GTHAJS.js";
|
|
21
22
|
import {
|
|
22
23
|
SHERWOOD
|
|
23
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-GYGSKMZE.js";
|
|
24
25
|
import {
|
|
25
26
|
getPublicClient
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import "./chunk-
|
|
27
|
+
} from "./chunk-Z53JZORT.js";
|
|
28
|
+
import "./chunk-LIW6K4OJ.js";
|
|
28
29
|
import {
|
|
29
30
|
loadConfig
|
|
30
|
-
} from "./chunk-
|
|
31
|
+
} from "./chunk-QUAVAJWE.js";
|
|
31
32
|
import {
|
|
32
33
|
SYNDICATE_VAULT_ABI
|
|
33
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
317
|
-
const { getNotifyTo } = await import("./config-
|
|
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-
|
|
358
|
+
//# sourceMappingURL=session-DE47TUEW.js.map
|
|
@@ -1,36 +1,38 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getResearchProvider
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-6IC2NRED.js";
|
|
4
4
|
import "./chunk-EGJESQXZ.js";
|
|
5
5
|
import {
|
|
6
6
|
chatCompletion
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JLOROS5V.js";
|
|
8
8
|
import {
|
|
9
9
|
getQuote
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-WDPA2BYK.js";
|
|
11
|
+
import "./chunk-G5FOHSQW.js";
|
|
12
|
+
import "./chunk-QVXKYT2N.js";
|
|
11
13
|
import {
|
|
12
14
|
TOKENS
|
|
13
|
-
} from "./chunk-
|
|
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-
|
|
22
|
+
} from "./chunk-Z53JZORT.js";
|
|
21
23
|
import {
|
|
22
24
|
getChain,
|
|
23
25
|
getExplorerUrl,
|
|
24
26
|
getNetwork
|
|
25
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-LIW6K4OJ.js";
|
|
26
28
|
import {
|
|
27
29
|
getUniswapApiKey,
|
|
28
30
|
loadConfig,
|
|
29
31
|
saveConfig
|
|
30
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-QUAVAJWE.js";
|
|
31
33
|
import {
|
|
32
34
|
ERC20_ABI
|
|
33
|
-
} from "./chunk-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
879
|
-
const { getChainContracts } = await import("./config-
|
|
880
|
-
const { getChain: getActiveChain } = await import("./network-
|
|
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-
|
|
1007
|
-
const { getChainContracts } = await import("./config-
|
|
1008
|
-
const { getChain: getActiveChain } = await import("./network-
|
|
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-
|
|
1185
|
+
//# sourceMappingURL=trade-3VMAQ75D.js.map
|