@continuumdao/ctm-mpc-defi 0.2.44 → 0.2.46

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.
@@ -43,7 +43,7 @@ Do **not** answer from `ctm_continuum_dao_fetch_proposals` or backend `status` a
43
43
  - **`unknown`** — no on-chain overlay (missing governor/RPC, or a failed `state` read). Do not call these live.
44
44
  4. If `overlay` is `backend-only`, say you could not confirm live Governor state.
45
45
 
46
- For one proposal, call `ctm_continuum_dao_explain_proposal` and read `briefing` aloud (every action / Delta option, no-ops labeled signaling, C3 called out). Do not vote from this protocol skill.
46
+ For one proposal, call `ctm_continuum_dao_explain_proposal` and read `briefing` aloud (every action / Delta option, no-ops labeled signaling). `network.c3governor` is always present; call C3 out only when `network.name` is not Linea. Catalog ids **-2** and **-1** are the two proposals on the superseded Linea governor `0x4800F9f1dC1b6daCA841B71E0531F547D374168E`. Do not vote from this protocol skill.
47
47
 
48
48
  Operator presentation and vote policy live in the node catalogue (mpc-config): load skills **`continuum-dao-proposals`** and **`continuum-dao-vote-policy`** via `agent_load_skill`. To **create** a proposal in chat, load **`continuum-dao-compose-proposal`** (interactive only). Cron must never propose or load that skill — vote and governor Join only.
49
49
 
@@ -22,8 +22,9 @@ The MPC **executor address** (`keyGen.ethereumaddress`) is the Hyperliquid **use
22
22
  - **Spot ↔ Perp:** USDC is one asset split between **spot** and **perp margin** ledgers (not separate ERC20s). Move with `usdClassTransfer`.
23
23
  - **Vaults:** Deposit/withdraw USD into protocol vaults (withdraw includes accrued PnL).
24
24
  - **Staking:** Stake/unstake **HYPE** and delegate to validators.
25
+ - **Borrow / lend:** Manual HyperCore money market. Collateralize **HYPE** / **UBTC**; borrow or supply quote assets (**USDC**, **USDT0**, **USDH**). Current **supply APR** and **borrow APR** come from `ctm_hyperliquid_fetch_lend_markets`.
25
26
 
26
- Trading reads use Hyperliquid **REST `/info`**. Writes use **CoreWriter** on HyperEVM (not the signed `/exchange` API).
27
+ Trading reads use Hyperliquid **REST `/info`**. Most writes use **CoreWriter** on HyperEVM. Leverage, bridge withdraw, TP/SL brackets, and **borrow/lend** use signed **L1 `/exchange`** (EIP-712).
27
28
 
28
29
  ## Getting started (funding)
29
30
 
@@ -45,7 +46,7 @@ Positions and orders from MCP reflect **live HyperCore state** after prior txs a
45
46
  5. `ctm_hyperliquid_fetch_market_snapshot({ chainId, coin: "AAPL" })` — **`livePrice.midUsd`** is the current price; **`funding`** is official hourly HyperCore funding; `latestCandle` is the most recent bar; `candles` is capped (default 48). Throws if live price cannot be fetched.
46
47
  6. `ctm_hyperliquid_fetch_open_context({ chainId, executorAddress, coin: "Apple" })` — same resolution
47
48
  7. `ctm_hyperliquid_fetch_usd_class_balances({ chainId, executorAddress })` — spot vs perp USD if needed
48
- 8. **Gas** — `get_multi_sign_gas_options({ chainId })` + `useCustomGas` for **CoreWriter** tools only (plain limit, close, cancel, transfers, vault, stake). **Skip gas** for `build_update_leverage_multisign`, `build_bridge_withdraw_multisign`, and limit orders **with TP/SL triggers** (EIP-712 `/exchange`).
49
+ 8. **Gas** — `get_multi_sign_gas_options({ chainId })` + `useCustomGas` for **CoreWriter** tools only (plain limit, close, cancel, transfers, vault, stake). **Skip gas** for `build_update_leverage_multisign`, `build_bridge_withdraw_multisign`, `build_lend_multisign`, and limit orders **with TP/SL triggers** (EIP-712 `/exchange`).
49
50
  9. `ctm_hyperliquid_build_limit_order_multisign` → **`{ requestId }`**
50
51
  10. Base MPC lifecycle (shared gas/submit section below)
51
52
 
@@ -69,6 +70,8 @@ Positions and orders from MCP reflect **live HyperCore state** after prior txs a
69
70
  | User vault equity | `ctm_hyperliquid_fetch_user_vault_equities` |
70
71
  | HYPE stake summary | `ctm_hyperliquid_fetch_staking_summary` |
71
72
  | Validator delegations | `ctm_hyperliquid_fetch_delegations` |
73
+ | Core lend markets + **current supply/borrow APR** | `ctm_hyperliquid_fetch_lend_markets` — activate `hyperliquid:lend` |
74
+ | Core lend positions + health + manual-borrow gate | `ctm_hyperliquid_fetch_lend_positions` |
72
75
 
73
76
  ### Multi-sign (writes)
74
77
 
@@ -87,6 +90,7 @@ Positions and orders from MCP reflect **live HyperCore state** after prior txs a
87
90
  | Delegate to validator | `ctm_hyperliquid_build_delegate_multisign` |
88
91
  | Undelegate | `ctm_hyperliquid_build_undelegate_multisign` |
89
92
  | Update per-market leverage | `ctm_hyperliquid_build_update_leverage_multisign` (EIP-712 — no gas) |
93
+ | Supply / withdraw / borrow / repay | `ctm_hyperliquid_build_lend_multisign` (EIP-712 — no gas) |
90
94
 
91
95
  ### EIP-712 vs CoreWriter (critical for agents)
92
96
 
@@ -95,6 +99,7 @@ Positions and orders from MCP reflect **live HyperCore state** after prior txs a
95
99
  | Plain limit / close / cancel / USD transfer / vault / stake | CoreWriter EVM tx | **Yes** — `get_multi_sign_gas_options`, pass `useCustomGas` |
96
100
  | `build_update_leverage_multisign` | EIP-712 → `/exchange` | **No** — trigger without txParams |
97
101
  | `build_bridge_withdraw_multisign` | EIP-712 → `/exchange` | **No** |
102
+ | `build_lend_multisign` | EIP-712 → `/exchange` | **No** — trigger without txParams |
98
103
  | Limit with `takeProfitTriggerPxHuman` and/or `stopLossTriggerPxHuman` | EIP-712 normalTpsl → `/exchange` | **No** — re-build if entry/TP/SL change |
99
104
 
100
105
  ## Common multisign inputs (all `build_*` tools)
@@ -203,6 +208,31 @@ Use `isLong: true` for a **long** position (submits sell reduce-only IoC):
203
208
 
204
209
  Check balances first with `ctm_hyperliquid_fetch_usd_class_balances`.
205
210
 
211
+ ## Borrow / lend (HyperCore)
212
+
213
+ Activate **`hyperliquid:lend`** (`activate_tool_group`). Do not fold this into vaults or perp market-data.
214
+
215
+ 1. `ctm_hyperliquid_fetch_lend_markets` — current **`supplyYearlyRate` / `borrowYearlyRate`** are **APR** (decimal; `0.05` = 5%). Also `supplyAprPercent` / `borrowAprPercent`. `role` is `collateral` (LTV > 0) or `quote`.
216
+ 2. `ctm_hyperliquid_fetch_lend_positions` — supplied/borrowed, `health`, `manualBorrowEnabled`. If `userAbstraction` is `portfolioMargin`, **do not** call `operation: "borrow"`.
217
+ 3. `ctm_hyperliquid_build_lend_multisign` with `operation`: `supply` | `withdraw` | `borrow` | `repay`.
218
+
219
+ Rules:
220
+
221
+ - **HYPE / UBTC** (`BTC` aliases to UBTC) supplied as collateral **do not earn interest**.
222
+ - **USDC / USDT0** (`USDT` aliases to USDT0) / **USDH** supplied earn utilization APR but **do not increase borrow capacity**.
223
+ - `amountMax: true` (or `amountHuman: "max"`) sends wire `amount: null` — full withdraw/repay.
224
+ - EIP-712 `/exchange` — **no `useCustomGas`**, trigger without txParams.
225
+
226
+ ```json
227
+ {
228
+ "chainId": 999,
229
+ "purposeText": "HL supply 100 USDC",
230
+ "coin": "USDC",
231
+ "operation": "supply",
232
+ "amountHuman": "100"
233
+ }
234
+ ```
235
+
206
236
  ## Vault / stake
207
237
 
208
238
  - **Vault deposit/withdraw:** `vaultAddress` from `fetch_vaults`; `usdHuman` amount. Mainnet vault catalog fetch can take ~10–15s (large stats feed). Testnet catalog is empty.
@@ -11,10 +11,12 @@ Do **not** web-search rates. Do **not** use DefiLlama. HIP-3 / Arcus stock tradi
11
11
 
12
12
  ## Plan Mode
13
13
 
14
- If the operator started **Best yield** / plan mode `yield`: this thread **authors the plan file**. Ask for the asset first. Then `get_defi_protocol_skill({ protocolId: "yield-compare" })` **once** and write workstreams — do **not** `load_defi_protocol`, search Continuum tools, or spawn specialists on the parent. Execute runs one specialist per listed protocol. Research-only — no `ctm_*_build_*_multisign`. Table categories: `idle` / `lp` / `vault` / `perp_funding`. GMX and Hyperliquid only if they asked. Catalog MCP is context only.
14
+ If the operator started **Best yield** / plan mode `yield`: this thread **authors the plan file**. Ask for the asset first. Then `get_defi_protocol_skill({ protocolId: "yield-compare" })` **once** and write workstreams — do **not** `load_defi_protocol`, search Continuum tools, or spawn specialists on the parent. Execute runs one specialist per listed protocol. Research-only — no `ctm_*_build_*_multisign`. Table categories: `idle` / `lp` / `vault` / `perp_funding`. GMX and Hyperliquid vaults/funding only if they asked. Hyperliquid **Core lend** (USDC/USDT supply APR) is an **optional extra** for stables — mention in plan notes; add an Execute leaf only if they say yes or already asked about Hyperliquid / HL lend / Core lending. Catalog MCP is context only.
15
15
 
16
16
  For **USDC / USDT**, the authored plan notes **must** mention Morpho stock-backed USDC loans as an **optional extra** (isolated Blue/Midnight books against Coinbase B20 collateral such as AAPLc/NVDAc; thin liquidity; 24/5 oracles; Regulation S / non-US). Do **not** add a Morpho stock Execute workstream or call `ctm_morpho_fetch_stock_markets` unless the operator says yes or already asked about stocks / tokenized stocks / stock-backed loans.
17
17
 
18
+ For **USDC / USDT**, plan notes **must** also mention Hyperliquid Core lend as an **optional extra**: supply USDC/USDT0 on HyperCore to earn utilization **APR** (`ctm_hyperliquid_fetch_lend_markets`); HYPE/UBTC collateral earns nothing. Do **not** add a Hyperliquid Execute workstream or call `ctm_hyperliquid_fetch_lend_markets` unless the operator says yes or already asked about Hyperliquid / HL lend / Core lending. That leaf is research-only (`toolGroups: ["defi_discovery", "defi:hyperliquid:lend", "keygen", "keygen_messaging"]`) — report quote-token `supplyYearlyRate` as **APR** plus `borrowYearlyRate` as context; skip collateral rows; category `idle`. Do not treat Core lend as vault APR or perp funding.
19
+
18
20
  Each Execute protocol leaf must list `toolGroups: ["defi_discovery", "defi:<protocol>:market-data", "keygen", "keygen_messaging"]` (canonical ids: `aave-v4`, `compound-v3`, `euler-v2`, `morpho`, `maple-syrup`, `curve-dao`, `aerodrome`, `pendle`) and `budget: { maxRounds: 16, maxWallClockMs: 240000 }`. Slim leaves cannot search/activate packs — without `defi_discovery` they never see `load_defi_protocol` or official `ctm_*` fetch tools. Do **not** use `agent_bash` / `agent_read_file` / `agent_grep` on a yield leaf — call the official fetch (`ctm_aave_v4_fetch_markets`, `ctm_compound_v3_fetch_markets`, `ctm_morpho_fetch_earn_vaults`, `ctm_morpho_fetch_blue_markets` with `loan: "USDC"` / `"USDT"`, `ctm_aerodrome_fetch_lp_yields` on Base `8453`, `ctm_pendle_fetch_markets` / `ctm_pendle_search_assets`, …) then post `mpc-task-result`. Ticker filters (`underlying: "USDT"`, Morpho `loan: "USDC"`) are valid on Aave/Maple/Morpho fetches — do not invent ERC-20 addresses. Morpho leaf: report vault `netApy` and Blue `netSupplyApyLabel`; footnote `rewards[]` as variable extras — do not add them on top of net APY a second time. Skip empty Blue books (no supply TVL). `ctm_morpho_fetch_stock_markets` only after the operator says yes. Aave v4 is Ethereum-first (`1`; also 10 / 43114). Maple is Ethereum (`1`). Aerodrome is Base (`8453`) only. Pendle is any Core `chainId` ∩ node registry — research-only fetch, no build.
19
21
 
20
22
  ## Units and caveats
@@ -52,6 +54,7 @@ Call `get_defi_protocol_skill({ protocolId: "yield-compare" })` for this map, th
52
54
  3. `ctm_pendle_fetch_markets` — optional PT / YT / LP implied APY if they asked about Pendle (research-only)
53
55
  4. `ctm_gmx_fetch_gm_apy` / `ctm_hyperliquid_fetch_vault_apys` / perp funding — **only if they asked** about GMX, HL vaults, or funding
54
56
  5. Morpho stock-backed USDC loans — **optional extra in plan notes only**. Call `ctm_morpho_fetch_stock_markets` only if they say yes.
57
+ 6. Hyperliquid Core lend (`ctm_hyperliquid_fetch_lend_markets`) — **optional extra in plan notes**. Call only if they say yes or already asked about Hyperliquid / HL lend. Quote tokens only (USDC / USDT0); **APR** not APY. HYPE/UBTC collateral is not idle yield.
55
58
 
56
59
  ### USDS
57
60
 
@@ -64,6 +64,8 @@ var UNSET = {
64
64
  };
65
65
  var CTM_TOKEN_ADDRESS = viem.getAddress("0x2026027054F5beBCEB650aBD62dC623e327658e7");
66
66
  var VOTING_ESCROW_LINEA_ADDRESS = viem.getAddress("0x221EC90B3B083A8501A37bdeb7035CeaedF3C31f");
67
+ var CONTINUUM_DAO_LINEA_GOVERNOR_ADDRESS = viem.getAddress("0x76FF2CB03175900F1D83328C82D27EA9aeaF2355");
68
+ var CONTINUUM_DAO_LINEA_GOVERNOR_LEGACY_ADDRESS = viem.getAddress("0x4800F9f1dC1b6daCA841B71E0531F547D374168E");
67
69
  var CONTINUUM_DAO_DEPLOYMENTS = {
68
70
  [CONTINUUM_DAO_LINEA_CHAIN_ID]: {
69
71
  ...UNSET,
@@ -2559,17 +2561,40 @@ async function continuumDaoFetchProposalCount(args) {
2559
2561
  const count = await client.readContract({ address: gov, abi: governorReadAbi, functionName: "proposalCount" });
2560
2562
  return { count: count.toString() };
2561
2563
  }
2562
- async function continuumDaoFetchProposals(args) {
2563
- const start = args.start ?? 0;
2564
- const end = args.end ?? start + 20;
2564
+ function resolveProposalCatalogRange(catalog, args) {
2565
+ const hasBounds = Number.isFinite(catalog.minIndex) && Number.isFinite(catalog.maxIndex);
2566
+ const minIndex = hasBounds ? Number(catalog.minIndex) : 0;
2567
+ const maxIndex = hasBounds ? Number(catalog.maxIndex) : 0;
2568
+ if (!hasBounds) {
2569
+ const start = args?.start ?? 0;
2570
+ const end = args?.end ?? start + 20;
2571
+ return { start, end };
2572
+ }
2573
+ return {
2574
+ start: args?.start ?? minIndex,
2575
+ end: args?.end ?? maxIndex + 1
2576
+ };
2577
+ }
2578
+ async function postProposalCatalog(body) {
2565
2579
  const res = await fetch(`${CONTINUUM_DAO_GOVERNANCE_API}/proposals`, {
2566
2580
  method: "POST",
2567
2581
  headers: { "Content-Type": "application/json" },
2568
- body: JSON.stringify({ start, end })
2582
+ body: JSON.stringify(body)
2569
2583
  });
2570
2584
  if (!res.ok) throw new Error(`proposals: ${res.status} ${await res.text()}`);
2571
2585
  return await res.json();
2572
2586
  }
2587
+ async function continuumDaoFetchProposals(args = {}) {
2588
+ const bounds = await postProposalCatalog({});
2589
+ const { start, end } = resolveProposalCatalogRange(bounds, args);
2590
+ const listed = await postProposalCatalog({ start, end });
2591
+ return {
2592
+ ...listed,
2593
+ total: listed.total ?? bounds.total,
2594
+ minIndex: listed.minIndex ?? bounds.minIndex,
2595
+ maxIndex: listed.maxIndex ?? bounds.maxIndex
2596
+ };
2597
+ }
2573
2598
  var GOVERNOR_STATE = {
2574
2599
  Pending: 0,
2575
2600
  Active: 1,
@@ -2610,13 +2635,19 @@ function parseBackendProposal(raw) {
2610
2635
  if (!onchainId) return null;
2611
2636
  const idRaw = row.id;
2612
2637
  const id = typeof idRaw === "number" ? idRaw : Number(idRaw);
2638
+ const governorRaw = String(row.governorAddress ?? row.governor_address ?? "").trim();
2613
2639
  return {
2614
2640
  id: Number.isFinite(id) ? id : void 0,
2615
2641
  onchainId,
2616
2642
  title: String(row.title ?? "Untitled"),
2617
- configuration: typeof row.configuration === "number" ? row.configuration : void 0
2643
+ configuration: typeof row.configuration === "number" ? row.configuration : void 0,
2644
+ governorAddress: isConfiguredAddress(governorRaw) ? viem.getAddress(governorRaw) : void 0
2618
2645
  };
2619
2646
  }
2647
+ function isLegacyContinuumDaoGovernor(addr) {
2648
+ if (!addr || !isConfiguredAddress(addr)) return false;
2649
+ return viem.getAddress(addr) === CONTINUUM_DAO_LINEA_GOVERNOR_LEGACY_ADDRESS;
2650
+ }
2620
2651
  function summarizeLiveProposals(result) {
2621
2652
  if (result.overlay === "backend-only") {
2622
2653
  return `Scanned ${result.scanned} backend proposal(s) but could not overlay ContinuumDAO.state. Do not call them live. Pass Linea chainId + rpcUrl + a non-zero governor.`;
@@ -2641,9 +2672,11 @@ async function mapPool(items, concurrency, fn) {
2641
2672
  async function continuumDaoFetchLiveProposals(args) {
2642
2673
  const limit = Math.min(Math.max(Number(args.limit) || 40, 1), 100);
2643
2674
  const completedLimit = Math.min(Math.max(Number(args.completedLimit) || 8, 0), 20);
2644
- const listed = await continuumDaoFetchProposals({ start: 0, end: limit });
2675
+ const listed = await continuumDaoFetchProposals();
2645
2676
  const rawList = Array.isArray(listed.proposals) ? listed.proposals : [];
2646
2677
  const parsed = rawList.map(parseBackendProposal).filter((p) => p != null);
2678
+ const ordered = [...parsed].sort((a, b) => (a.id ?? 0) - (b.id ?? 0));
2679
+ const latest = ordered.length > limit ? ordered.slice(ordered.length - limit) : ordered;
2647
2680
  const chainId = args.chainId != null && String(args.chainId).trim() !== "" ? Number(args.chainId) : NaN;
2648
2681
  const rpcUrl = (args.rpcUrl ?? "").trim();
2649
2682
  let overlay = "backend-only";
@@ -2655,13 +2688,13 @@ async function continuumDaoFetchLiveProposals(args) {
2655
2688
  } catch {
2656
2689
  overlay = "backend-only";
2657
2690
  }
2658
- const rows = overlay === "on-chain" ? await mapPool(parsed, 6, async (p) => {
2691
+ const rows = overlay === "on-chain" ? await mapPool(latest, 6, async (p) => {
2659
2692
  try {
2660
2693
  const st = await continuumDaoFetchProposalState({
2661
2694
  chainId,
2662
2695
  rpcUrl,
2663
2696
  proposalId: p.onchainId,
2664
- governor: args.governor
2697
+ governor: p.governorAddress ?? args.governor
2665
2698
  });
2666
2699
  return {
2667
2700
  ...p,
@@ -2675,7 +2708,7 @@ async function continuumDaoFetchLiveProposals(args) {
2675
2708
  } catch {
2676
2709
  return { ...p, state: null, stateLabel: "Unknown", bucket: "unknown" };
2677
2710
  }
2678
- }) : parsed.map((p) => ({ ...p, state: null, stateLabel: "Unknown", bucket: "unknown" }));
2711
+ }) : latest.map((p) => ({ ...p, state: null, stateLabel: "Unknown", bucket: "unknown" }));
2679
2712
  const live = rows.filter((r) => r.bucket === "live");
2680
2713
  const pending = rows.filter((r) => r.bucket === "pending");
2681
2714
  const readyToExecute = rows.filter((r) => r.bucket === "readyToExecute");
@@ -2736,13 +2769,28 @@ function isGovNoOpAction(action) {
2736
2769
  const emptyData = data === "" || data === "0x";
2737
2770
  return (value === "" || value === "0") && sig === "" && emptyData;
2738
2771
  }
2772
+ var LINEA_HOME_CHAIN_IDS = /* @__PURE__ */ new Set(["59144", "59141"]);
2773
+ function isLineaHomeNetwork(net) {
2774
+ const name = `${net.name ?? ""} ${net.label ?? ""}`.toLowerCase();
2775
+ if (name.includes("linea")) return true;
2776
+ return LINEA_HOME_CHAIN_IDS.has(String(net.chainId ?? ""));
2777
+ }
2778
+ function isRemoteC3Action(net) {
2779
+ const c3 = (net.c3governor ?? "").trim();
2780
+ const hasC3 = Boolean(c3 && c3 !== "0x0000000000000000000000000000000000000000");
2781
+ return hasC3 && !isLineaHomeNetwork(net);
2782
+ }
2739
2783
  function explainGovAction(raw) {
2740
2784
  const a = asRecord2(raw) ?? {};
2741
2785
  const net = asRecord2(a.network) ?? {};
2742
2786
  const networkLabel = str(net.label || net.name, "Unknown network");
2743
2787
  const chainId = str(net.chainId);
2744
- const c3 = str(net.c3governor);
2745
- const viaC3 = Boolean(c3 && c3 !== "0x0000000000000000000000000000000000000000");
2788
+ const viaC3 = isRemoteC3Action({
2789
+ name: str(net.name),
2790
+ label: str(net.label),
2791
+ chainId,
2792
+ c3governor: str(net.c3governor)
2793
+ });
2746
2794
  const target = str(a.target);
2747
2795
  const value = str(a.value, "0");
2748
2796
  const signature = str(a.signature);
@@ -2774,6 +2822,8 @@ function explainProposalRecord(raw) {
2774
2822
  if (!row) throw new Error("explain_proposal: empty proposal");
2775
2823
  const onchainId = str(row.onchainId ?? row.onchain_id ?? row.proposalId);
2776
2824
  if (!onchainId) throw new Error("explain_proposal: missing onchainId");
2825
+ const idNum = typeof row.id === "number" ? row.id : Number(row.id);
2826
+ const governorAddress = str(row.governorAddress ?? row.governor_address).trim() || void 0;
2777
2827
  const configuration = Number(row.configuration) === 1 ? "delta" : "bravo";
2778
2828
  const nWinners = row.nWinners != null ? Number(row.nWinners) : void 0;
2779
2829
  const actionsRaw = Array.isArray(row.actions) ? row.actions : [];
@@ -2801,6 +2851,11 @@ function explainProposalRecord(raw) {
2801
2851
  const lines = [];
2802
2852
  lines.push(`#${row.id ?? "\u2014"} ${str(row.title, "Untitled")} (${t}, ${configuration === "delta" ? "Delta" : "Bravo"}).`);
2803
2853
  lines.push(`Proposer ${str(row.proposer) || "\u2014"} (any EOA or contract \u2014 not required to be a KeyGen).`);
2854
+ if (governorAddress) {
2855
+ lines.push(
2856
+ isLegacyContinuumDaoGovernor(governorAddress) ? `Governor ${governorAddress} (superseded Linea DAO; catalog ids are negative).` : `Governor ${governorAddress}.`
2857
+ );
2858
+ }
2804
2859
  if (str(row.forumKey)) lines.push(`Forum: ${str(row.forumKey)}`);
2805
2860
  if (configuration === "bravo") {
2806
2861
  lines.push("If this passes, the DAO will execute, in order:");
@@ -2820,7 +2875,7 @@ function explainProposalRecord(raw) {
2820
2875
  }
2821
2876
  lines.push("Queue is not implemented. Vote while Active; execute from Succeeded.");
2822
2877
  return {
2823
- id: typeof row.id === "number" ? row.id : Number(row.id) || void 0,
2878
+ id: Number.isFinite(idNum) ? idNum : void 0,
2824
2879
  onchainId,
2825
2880
  title: str(row.title, "Untitled"),
2826
2881
  description: str(row.description),
@@ -2829,6 +2884,7 @@ function explainProposalRecord(raw) {
2829
2884
  typeLabel: t,
2830
2885
  configuration,
2831
2886
  nWinners: Number.isFinite(nWinners) ? nWinners : void 0,
2887
+ governorAddress,
2832
2888
  briefing: lines.join("\n"),
2833
2889
  actions,
2834
2890
  options,
@@ -2851,7 +2907,7 @@ async function continuumDaoExplainProposal(args) {
2851
2907
  }
2852
2908
  const want = (args.onchainId ?? "").trim();
2853
2909
  if (!want) throw new Error("explain_proposal: pass id or onchainId");
2854
- const listed = await continuumDaoFetchProposals({ start: 0, end: 80 });
2910
+ const listed = await continuumDaoFetchProposals();
2855
2911
  const rawList = Array.isArray(listed.proposals) ? listed.proposals : [];
2856
2912
  const hit = rawList.find((p) => {
2857
2913
  const row = asRecord2(p);
@@ -2931,6 +2987,8 @@ exports.CONTINUUM_DAO_GOV_EVM_TYPES = CONTINUUM_DAO_GOV_EVM_TYPES;
2931
2987
  exports.CONTINUUM_DAO_INCREASE_AMOUNT_FALLBACK = CONTINUUM_DAO_INCREASE_AMOUNT_FALLBACK;
2932
2988
  exports.CONTINUUM_DAO_INCREASE_UNLOCK_FALLBACK = CONTINUUM_DAO_INCREASE_UNLOCK_FALLBACK;
2933
2989
  exports.CONTINUUM_DAO_LINEA_CHAIN_ID = CONTINUUM_DAO_LINEA_CHAIN_ID;
2990
+ exports.CONTINUUM_DAO_LINEA_GOVERNOR_ADDRESS = CONTINUUM_DAO_LINEA_GOVERNOR_ADDRESS;
2991
+ exports.CONTINUUM_DAO_LINEA_GOVERNOR_LEGACY_ADDRESS = CONTINUUM_DAO_LINEA_GOVERNOR_LEGACY_ADDRESS;
2934
2992
  exports.CONTINUUM_DAO_LINEA_SEPOLIA_CHAIN_ID = CONTINUUM_DAO_LINEA_SEPOLIA_CHAIN_ID;
2935
2993
  exports.CONTINUUM_DAO_LIQUIDATE_FALLBACK = CONTINUUM_DAO_LIQUIDATE_FALLBACK;
2936
2994
  exports.CONTINUUM_DAO_MERGE_FALLBACK = CONTINUUM_DAO_MERGE_FALLBACK;
@@ -3068,6 +3126,9 @@ exports.isContinuumDaoVeCtmOnAssetsChain = isContinuumDaoVeCtmOnAssetsChain;
3068
3126
  exports.isCtmTokenSymbol = isCtmTokenSymbol;
3069
3127
  exports.isForumIdeaSection = isForumIdeaSection;
3070
3128
  exports.isGovNoOpAction = isGovNoOpAction;
3129
+ exports.isLegacyContinuumDaoGovernor = isLegacyContinuumDaoGovernor;
3130
+ exports.isLineaHomeNetwork = isLineaHomeNetwork;
3131
+ exports.isRemoteC3Action = isRemoteC3Action;
3071
3132
  exports.isVotingEscrowContinuumName = isVotingEscrowContinuumName;
3072
3133
  exports.listContinuumDaoDefaultAssets = listContinuumDaoDefaultAssets;
3073
3134
  exports.maxLockDurationSeconds = maxLockDurationSeconds;
@@ -3088,6 +3149,7 @@ exports.readCtmBalanceWei = readCtmBalanceWei;
3088
3149
  exports.readMinimumLockWei = readMinimumLockWei;
3089
3150
  exports.readVeCtmLockState = readVeCtmLockState;
3090
3151
  exports.resolveAttachGroupId = resolveAttachGroupId;
3152
+ exports.resolveProposalCatalogRange = resolveProposalCatalogRange;
3091
3153
  exports.summarizeLiveProposals = summarizeLiveProposals;
3092
3154
  exports.votingEscrowAddressOnEvmChain = votingEscrowAddressOnEvmChain;
3093
3155
  //# sourceMappingURL=index.cjs.map