@continuumdao/ctm-mpc-defi 0.2.29 → 0.2.31

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 (60) hide show
  1. package/dist/agent/catalog.cjs +2892 -13
  2. package/dist/agent/catalog.cjs.map +1 -1
  3. package/dist/agent/catalog.d.ts +5454 -977
  4. package/dist/agent/catalog.js +2784 -15
  5. package/dist/agent/catalog.js.map +1 -1
  6. package/dist/agent/skills/aerodrome/SKILL.md +93 -0
  7. package/dist/agent/skills/compound-v3/SKILL.md +132 -0
  8. package/dist/agent/skills/continuum-dao/SKILL.md +139 -0
  9. package/dist/agent/skills/morpho/SKILL.md +16 -8
  10. package/dist/buildBatch-CngvebiD.d.ts +45 -0
  11. package/dist/chains/evm/index.d.ts +6 -44
  12. package/dist/core/index.cjs +44 -40
  13. package/dist/core/index.cjs.map +1 -1
  14. package/dist/core/index.d.ts +1 -1
  15. package/dist/core/index.js +44 -40
  16. package/dist/core/index.js.map +1 -1
  17. package/dist/{eip712Multisign-xhXpUYp3.d.ts → eip712Multisign-DCW7heqX.d.ts} +11 -8
  18. package/dist/index.cjs +183 -58
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.ts +5 -2
  21. package/dist/index.js +182 -58
  22. package/dist/index.js.map +1 -1
  23. package/dist/protocols/evm/aerodrome/index.cjs +3922 -0
  24. package/dist/protocols/evm/aerodrome/index.cjs.map +1 -0
  25. package/dist/protocols/evm/aerodrome/index.d.ts +792 -0
  26. package/dist/protocols/evm/aerodrome/index.js +3843 -0
  27. package/dist/protocols/evm/aerodrome/index.js.map +1 -0
  28. package/dist/protocols/evm/arcus/index.cjs +62 -55
  29. package/dist/protocols/evm/arcus/index.cjs.map +1 -1
  30. package/dist/protocols/evm/arcus/index.js +62 -55
  31. package/dist/protocols/evm/arcus/index.js.map +1 -1
  32. package/dist/protocols/evm/compound-v3/index.cjs +1542 -0
  33. package/dist/protocols/evm/compound-v3/index.cjs.map +1 -0
  34. package/dist/protocols/evm/compound-v3/index.d.ts +683 -0
  35. package/dist/protocols/evm/compound-v3/index.js +1488 -0
  36. package/dist/protocols/evm/compound-v3/index.js.map +1 -0
  37. package/dist/protocols/evm/continuum-dao/index.cjs +2237 -0
  38. package/dist/protocols/evm/continuum-dao/index.cjs.map +1 -0
  39. package/dist/protocols/evm/continuum-dao/index.d.ts +700 -0
  40. package/dist/protocols/evm/continuum-dao/index.js +2110 -0
  41. package/dist/protocols/evm/continuum-dao/index.js.map +1 -0
  42. package/dist/protocols/evm/hyperliquid/index.cjs +125 -110
  43. package/dist/protocols/evm/hyperliquid/index.cjs.map +1 -1
  44. package/dist/protocols/evm/hyperliquid/index.js +125 -110
  45. package/dist/protocols/evm/hyperliquid/index.js.map +1 -1
  46. package/dist/protocols/evm/morpho/index.cjs +746 -39
  47. package/dist/protocols/evm/morpho/index.cjs.map +1 -1
  48. package/dist/protocols/evm/morpho/index.d.ts +161 -14
  49. package/dist/protocols/evm/morpho/index.js +736 -42
  50. package/dist/protocols/evm/morpho/index.js.map +1 -1
  51. package/dist/protocols/evm/permit2/index.cjs +66 -59
  52. package/dist/protocols/evm/permit2/index.cjs.map +1 -1
  53. package/dist/protocols/evm/permit2/index.js +66 -59
  54. package/dist/protocols/evm/permit2/index.js.map +1 -1
  55. package/dist/protocols/evm/uniswap-v4/index.cjs +63 -56
  56. package/dist/protocols/evm/uniswap-v4/index.cjs.map +1 -1
  57. package/dist/protocols/evm/uniswap-v4/index.d.ts +1 -1
  58. package/dist/protocols/evm/uniswap-v4/index.js +63 -56
  59. package/dist/protocols/evm/uniswap-v4/index.js.map +1 -1
  60. package/package.json +20 -1
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: aerodrome
3
+ description: Aerodrome AMM on Base — Sugar discovery, swaps, basic LP, Slipstream CL, gauges, and MPC multisign.
4
+ ---
5
+
6
+ # Aerodrome (MCP)
7
+
8
+ Aerodrome is **Base-only (`chainId` 8453)**. Reads use the on-chain **LpSugar** aggregator. Writes build unsigned EVM batches (optional ERC-20 approve + Router / NFPM / gauge) for Continuum MPC.
9
+
10
+ Native ETH in the app and MCP is **`0x0000000000000000000000000000000000000000`**. Map to WETH (`0x4200000000000000000000000000000000000006`) at the Sugar/router boundary. Do not pass Curve’s `0xeeee…` placeholder.
11
+
12
+ ## Quote first (Coinbase B20 / AAPLc)
13
+
14
+ **Do not** dump listed tokens or `ctm_aerodrome_fetch_pools`. There is no Sugar token directory on MCP. Tickers resolve inside quote / discover.
15
+
16
+ For a price, **call `ctm_aerodrome_quote` immediately**:
17
+
18
+ ```
19
+ ctm_aerodrome_quote({ chainId: 8453, tokenIn: "USDC", tokenOut: "AAPLc", amountHuman: "1000" })
20
+ ```
21
+
22
+ - `tokenIn` / `tokenOut` accept **tickers** (`AAPLc`, `USDC`, `ETH`, `WETH`, `AERO`) or 0x addresses. Do **not** ask the user for a B20 contract address.
23
+ - B20 stocks are **8 decimals**. Omit `tokenInDecimals`.
24
+ - Quote output includes `amountOutHuman` and `priceImpactPercent` (0–100, vs a tiny same-route probe; `null` if the probe failed). State both before building a swap.
25
+ - To see **which pools exist** for a token (not a price): `ctm_aerodrome_discover_pools({ token: "AAPLc" })` — factory `getPool` vs USDC/WETH/AERO (optional `tokenOut`). Then quote.
26
+
27
+ Use `get_defi_protocol_supported_tokens` only as a slim ticker list (ETH, USDC, AERO, B20). `issued` for a stock is `totalSupply > 0` on quote/discover (unissued throws).
28
+
29
+ ## Before writes
30
+
31
+ 1. `load_defi_protocol({ protocolId: "aerodrome" })` — activates **market-data** (includes quote)
32
+ 2. `get_defi_protocol_supported_chains` — must include 8453 with a node `rpcGateway`
33
+ 3. Writes: `activate_tool_group` with `aerodrome:swap`, `aerodrome:lp`, or `aerodrome:rewards`
34
+
35
+ `aerodrome:trading` expands to swaps + lp + rewards (not market-data).
36
+
37
+ ## Confirm before creating a sign request
38
+
39
+ After the quote (include `amountOutHuman` and `priceImpactPercent`), **stop and ask** before any `ctm_aerodrome_build_*_multisign`:
40
+
41
+ 1. `get_multi_sign_gas_options({ chainId: 8453 })` — confirm `useCustomGas` **false** (live RPC, default) vs **true** (Custom Gas Config from the chain registry).
42
+ 2. Confirm the **30-minute** multiSignRequest deadline (members must agree, Get Sig, and broadcast before it expires). The on-chain router/NFPM deadline uses the same window. Omit `expiryDate` for 30 minutes; pass `expiryDate` as unix seconds only if they choose a different window.
43
+
44
+ Do not create the request until they confirm both.
45
+
46
+ ## Tool packs
47
+
48
+ | Pack | Tools | Sign request? |
49
+ |------|-------|----------------|
50
+ | market-data | `ctm_aerodrome_discover_pools`, `ctm_aerodrome_quote`, `ctm_aerodrome_fetch_positions`, `ctm_aerodrome_fetch_pools` (Sugar dump — avoid) | No |
51
+ | swaps | `ctm_aerodrome_build_swap_multisign` | Yes |
52
+ | lp | `quote_add_liquidity`, `quote_cl_deposit`, add/remove liquidity, CL mint/increase/decrease/burn, gauge stake/unstake | Quotes no; builds yes |
53
+ | rewards | claim fees, CL collect, claim emissions | Yes |
54
+
55
+ ## Liquidity (dialog parity)
56
+
57
+ Same as the Multi-Sign Liquidity tab:
58
+
59
+ ```
60
+ ctm_aerodrome_quote_add_liquidity({ chainId: 8453, tokenA: "ETH", tokenB: "USDC", amountAHuman: "0.01" })
61
+ ```
62
+
63
+ - One-sided: pass **either** `amountAHuman` or `amountBHuman`. The other side is filled from the current vAMM/sAMM reserves, or from Slipstream `slot0` when there is no v2 pool.
64
+ - Tickers work (`AAPLc`, `USDC`, `ETH`). B20 stocks are 8 decimals. Unissued stocks (`totalSupply == 0`) error the same as the dialog.
65
+ - **ETH / Coinbase stock has no pool.** `seedable` is `false` and `hint` tells you to pair the stock vs **USDC**. Do not first-deposit an empty vAMM.
66
+ - `kind: "cl"` means the ratio came from Slipstream. `ctm_aerodrome_build_add_liquidity_multisign` is **v2 only** — use `ctm_aerodrome_quote_cl_deposit` + `ctm_aerodrome_build_cl_mint_multisign` for that pool. AAPLc/USDC also has a small vAMM if you want basic LP.
67
+
68
+ ## Rewards (dialog parity)
69
+
70
+ Same as the Multi-Sign Rewards tab. **Start with** `ctm_aerodrome_fetch_positions` (account / keyGen). Rows are labeled (`vAMM-USDC/AERO`, `CL #id`) and dust-filtered.
71
+
72
+ | Dialog radio | Tool | Argument |
73
+ |--------------|------|----------|
74
+ | Fees from the pool | `ctm_aerodrome_build_claim_fees_multisign` | `pool` = `claimFees.pool` (`lp`) |
75
+ | Emissions from the gauge in AERO | `ctm_aerodrome_build_claim_emissions_multisign` | `gauge` = `claimEmissions.gauge`; Slipstream staked also needs `tokenId` + `cl: true` |
76
+
77
+ Skip emissions when `claimEmissions` is `null` (no gauge). Slipstream unstaked fees use `ctm_aerodrome_build_cl_collect_fees_multisign` with the NFT `id`.
78
+
79
+ ## Native ETH
80
+
81
+ | Phase | tokenIn / tokenA |
82
+ |-------|------------------|
83
+ | Quote / build | `0x0` or `eth` for native; ticker or ERC-20 otherwise |
84
+
85
+ ## Addresses
86
+
87
+ Loaded from official GitHub (`velodrome-finance/sugar` `deployments/base.env` and `aerodrome-finance/docs` security.mdx) with baked fallbacks. Do not invent addresses.
88
+
89
+ Coinbase B20 stocks (AAPLc, NVDAc, METAc, GOOGLc, SPCXc, …) trade on **Slipstream 3** (`clFactory3`) vs USDC. New official names are picked up from the [Base tokenized-stocks docs](https://docs.base.org/base-chain/asset-issuance/tokenized-stocks-on-base) and from Sugar tokens whose address uses the B20 ASSET prefix `0xb200…`. The docs fetch is optional: if that page is gone or unusable, discovery continues from the seed list + Sugar. `issued` is live `totalSupply() > 0` — do not hard-code unissued tickers. Quotes use factory `getPool` discovery + MixedRouteQuoterV3 (path bitmasks). Sugar `forSwaps` alone misses these pools. Native ETH → stock is typically WETH → USDC → stock.
90
+
91
+ ## Out of scope
92
+
93
+ veNFT lock/vote/rebases, Velodrome Superchain, Pool Launcher, incentives.
@@ -0,0 +1,132 @@
1
+ ---
2
+ name: compound-v3
3
+ description: Compound III (Comet) lending — supply, withdraw/borrow, repay, claim rewards, optional Bulker.
4
+ ---
5
+
6
+ # Compound III (MCP)
7
+
8
+ Each Compound III market is an isolated **Comet**. You always call the **Comet proxy** with the **CometInterface ABI**. Never the implementation or `CometExt` address.
9
+
10
+ | Concept | What it is | Agent needs to know |
11
+ |---------|------------|---------------------|
12
+ | **Comet proxy** | The only market address you call | From `ctm_compound_v3_fetch_markets` → `comet` |
13
+ | **Base asset** | The one asset you earn or borrow | `baseToken` on the market |
14
+ | **Collateral** | Other assets that back a borrow | `assets` where `role = collateral` |
15
+ | **Supply base** | Earn interest | Also **repays** if the account is borrowed |
16
+ | **Withdraw base** | Withdraw supplied base, or **borrow** if undercollateralized | Same `withdraw` tool |
17
+ | **Bulker** | Optional combined `invoke` | Not required for ETH wrap |
18
+
19
+ ## Before any action
20
+
21
+ 1. `load_defi_protocol({ protocolId: "compound-v3" })`
22
+ 2. `get_defi_protocol_skill({ protocolId: "compound-v3" })`
23
+ 3. `get_defi_protocol_supported_chains` — intersect with `get_chain_registry` (`rpcGateway` required)
24
+ 4. `get_defi_protocol_supported_tokens({ protocolId: "compound-v3", chainId })`
25
+ 5. `ctm_compound_v3_fetch_markets` → copy `comet`
26
+ 6. `ctm_compound_v3_fetch_account` before withdraw / repay / claim
27
+
28
+ ## Tool selection
29
+
30
+ Do **not** web-search Compound III markets, collaterals, or APRs. Load the protocol and use the fetch tools below.
31
+
32
+ | User intent | MCP tool |
33
+ |-------------|----------|
34
+ | List markets / what can I borrow against X | `ctm_compound_v3_fetch_markets` |
35
+ | Market detail (CFs, prices, APR) | `ctm_compound_v3_fetch_market` |
36
+ | Position + liquidation risk + claimable | `ctm_compound_v3_fetch_account` |
37
+ | Supply collateral or base (earn / repay) | `ctm_compound_v3_build_supply_multisign` |
38
+ | Withdraw or borrow base | `ctm_compound_v3_build_withdraw_multisign` |
39
+ | Repay debt | `ctm_compound_v3_build_repay_multisign` |
40
+ | Claim COMP / rewards | `ctm_compound_v3_build_claim_rewards_multisign` |
41
+ | Combined actions | `ctm_compound_v3_build_bulker_multisign` |
42
+
43
+ ## Common write inputs
44
+
45
+ | Field | Required | Notes |
46
+ |-------|----------|-------|
47
+ | `keyGenId` | yes | Preferred KeyGen |
48
+ | `chainId` | yes | EVM chain id |
49
+ | `purposeText` | yes | Human-readable reason |
50
+ | `comet` | yes | **Proxy** from fetch_markets |
51
+ | `asset` | yes (except claim) | Token; native ETH = `0x000…000` |
52
+ | `amountHuman` | yes (except claim) | Human amount |
53
+ | `isNative` | no | Wrap/unwrap ETH automatically |
54
+ | `useCustomGas` | no | Chain registry gas |
55
+
56
+ ## ETH wrap / unwrap (automatic)
57
+
58
+ If the user supplies or withdraws **native ETH** (`asset` is the zero address, or `isNative: true`):
59
+
60
+ - **Without Bulker:** `WETH.deposit` → approve → `Comet.supply` on the way in; `Comet.withdraw` → `WETH.withdraw` on the way out.
61
+ - **With Bulker:** native legs use `ACTION_SUPPLY_NATIVE_TOKEN` / `ACTION_WITHDRAW_NATIVE_TOKEN`.
62
+
63
+ Do **not** ask the user to wrap first. Do **not** require `useBulker` for ETH.
64
+
65
+ ## Workflows
66
+
67
+ ### What can I borrow against an asset (read-only)
68
+
69
+ Example: “What assets can I borrow against USDC on Ethereum using Compound III?”
70
+
71
+ 1. `load_defi_protocol({ protocolId: "compound-v3" })` then `get_defi_protocol_skill`.
72
+ 2. `ctm_compound_v3_fetch_markets` with `chainId` 1 (Ethereum). Do not guess collaterals from the web.
73
+ 3. Each Comet has **one borrowable base** and a list of **collateral** assets (`role`).
74
+ - “Borrow **against** USDC” → markets where USDC is `role = collateral`. The **base** of those markets is what you can borrow (e.g. cWETHv3 → WETH).
75
+ - “Borrow USDC” / “collateral to borrow USDC” → the market whose base is USDC (`cUSDCv3`). Assets with `role = collateral` are accepted collateral.
76
+ 4. `ctm_compound_v3_fetch_market` on the chosen `comet` for collateral factors and APRs.
77
+
78
+ ### Earn (supply base)
79
+
80
+ 1. `ctm_compound_v3_fetch_markets` — pick the Comet whose `baseToken` matches the token.
81
+ 2. `ctm_compound_v3_build_supply_multisign` with that `comet`, `asset`, `amountHuman`.
82
+
83
+ ### Borrow
84
+
85
+ 1. Supply collateral first (`build_supply_multisign` with a collateral `asset`).
86
+ 2. `ctm_compound_v3_fetch_account` — confirm `isBorrowCollateralized` and not `isLiquidatable`.
87
+ 3. `ctm_compound_v3_build_withdraw_multisign` with `asset` = **base token**. That withdraw **is** the borrow.
88
+
89
+ ### Repay then withdraw collateral
90
+
91
+ 1. `ctm_compound_v3_build_repay_multisign` (`asset` = base).
92
+ 2. `ctm_compound_v3_build_withdraw_multisign` (`asset` = collateral).
93
+
94
+ ### Combined (optional Bulker)
95
+
96
+ ```json
97
+ {
98
+ "keyGenId": "<keygen-id>",
99
+ "chainId": 1,
100
+ "purposeText": "Supply WETH collateral and borrow USDC on Compound III",
101
+ "comet": "0xc3d688B66703497DAA19211EEdff47f25384cdc3",
102
+ "steps": [
103
+ { "action": "supply", "asset": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", "amountHuman": "0.1" },
104
+ { "action": "withdraw", "asset": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", "amountHuman": "100" }
105
+ ]
106
+ }
107
+ ```
108
+
109
+ ## Example: supply 0.001 ETH on Ethereum cWETHv3
110
+
111
+ ```json
112
+ {
113
+ "keyGenId": "<keygen-id>",
114
+ "chainId": 1,
115
+ "purposeText": "Supply 0.001 ETH to Compound III cWETHv3",
116
+ "useCustomGas": true,
117
+ "comet": "0xA17581A9E3356d9A858b789D68B4d866e593aE94",
118
+ "asset": "0x0000000000000000000000000000000000000000",
119
+ "amountHuman": "0.001"
120
+ }
121
+ ```
122
+
123
+ ## Troubleshooting
124
+
125
+ | Symptom | Cause | Fix |
126
+ |---------|--------|-----|
127
+ | Unknown Comet | Guessed implementation address | Use `comet` from fetch_markets |
128
+ | Not collateralized | Withdraw/borrow exceeds CF | Supply more collateral or repay |
129
+ | Native max unwrap | `amountHuman: "max"` + ETH out | Pass an explicit amount |
130
+ | No RPC | Chain not in node registry | Add the chain with `rpcGateway` |
131
+
132
+ Supported live chains: Ethereum, Base, Arbitrum, Optimism, Polygon, Mantle, Unichain, Linea.
@@ -0,0 +1,139 @@
1
+ ---
2
+ name: continuum-dao
3
+ description: ContinuumDAO CTM lock, veCTM escrow, node attach, and Linea governance (Bravo/Delta propose, vote, execute, cancel).
4
+ ---
5
+
6
+ # ContinuumDAO (MCP)
7
+
8
+ ## Chains
9
+
10
+ - **Linea (59144) / Linea Sepolia (59141)** — create lock, escrow actions, attach veCTM, request detach, and governance.
11
+ - **Ethereum mainnet (`chainId: 1`)** — CTM hold/transfer only. Governance is Linea-only.
12
+
13
+ Addresses are placeholders until CTM / VotingEscrow / NodeProperties / Rewards / Governor are redeployed. Prefer live `GET https://app-api.continuumdao.org/protocol/dao|ve|networks` and pass `governor` when the constant is still zero. Do not submit write tools until the target address is non-zero.
14
+
15
+ ## Billing
16
+
17
+ These tools build protocol batches only. Do **not** prepend MPA billing legs (`register`, `deposit`, `syncBilling`). Fee payment stays on Compose / credit modals.
18
+
19
+ ## Governance encoding
20
+
21
+ One contract: `ContinuumDAO.propose`. Bravo vs Delta is encoding, not a separate function. Five UI types (Admin / Constitution / Decision / Election / Treasury) are backend tags; their **meaning** is the Constitution section **ContinuumDAO Proposals and Voting** (`get_continuum_doc` path `ContinuumDAO/Governance/Constitution`, `sectionId` `continuumdao-proposals-and-voting`). Load **`continuum-dao-proposal-standards`** and apply that fetch before choosing a type or appraising a proposal.
22
+
23
+ - **Bravo:** `targets[] / values[] / calldatas[]` are the actions; on-chain `description` is the title. Empty user actions insert one succeeding no-op (`target = KeyGen ETH`, `value = 0`, `calldata = 0x`) so `targets.length >= 1` and `targets[0] != address(0)`.
24
+ - **Delta:** slot 0 is metadata (`targets[0]=0`, `values[0]=0`, `calldatas[0]` = nOptions, nWinners, 1-indexed option starts). Remaining slots are flattened option actions. Empty options get the same no-op so start indices increment. Option **label** is required. Backend payload stores `actions: []` for empty options (user actions only).
25
+ - **Delta vote:** `weights` must be **nOptions + 1**. The last slot is baked-in NOTA. Do not ship nOptions-only params.
26
+ - **Queue is not implemented.** `queue()` reverts. Execute from `Succeeded`.
27
+
28
+ After a propose multi-sign request is **mined**, call `ctm_continuum_dao_register_proposal` (`POST /proposals/create`) so [app.continuumdao.org/governance](https://app.continuumdao.org/governance) stays in sync. If the POST fails, retry — do not revert the chain tx. `onchainId` comes from `hashProposal` or `ProposalCreated`.
29
+
30
+ `load_defi_protocol({ protocolId: "continuum-dao" })` loads escrow, attach, and governance together.
31
+
32
+ ## Chat: “What proposals are live now?”
33
+
34
+ Do **not** answer from `ctm_continuum_dao_fetch_proposals` or backend `status` alone.
35
+
36
+ 1. `load_defi_protocol({ protocolId: "continuum-dao" })` if not already loaded.
37
+ 2. `ctm_continuum_dao_fetch_live_proposals({ chainId: 59144, rpcUrl })` (Linea Sepolia: `59141`). Get `rpcUrl` from the chain registry. Pass `governor` when the constant is still zero (from `GET https://app-api.continuumdao.org/protocol/dao`).
38
+ 3. Read the returned `note`, then the buckets:
39
+ - **`live`** — `state === Active` (voting now). This is the answer to “live now.”
40
+ - **`pending`** — proposed, voting has not started.
41
+ - **`readyToExecute`** — `Succeeded`. No queue. Offer `ctm_continuum_dao_build_execute_multisign`.
42
+ - **`recentlyCompleted`** — Canceled / Defeated / Expired / Executed in this scan.
43
+ - **`unknown`** — no on-chain overlay (missing governor/RPC, or a failed `state` read). Do not call these live.
44
+ 4. If `overlay` is `backend-only`, say you could not confirm live Governor state.
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.
47
+
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
+
50
+ When a proposal has a `forumKey`, fetch that thread (`ctm_continuum_dao_forum_resolve` then `forum_fetch_thread` / `forum_fetch_post`) before voting. Check `section` on the thread against the proposal type. List recent posts with `forum_recent` (`hours` or `since`; privilege-filtered, whole forum; id, title, username, createdAt), or find matching posts with `forum_search` (title of a new thread or body text, case-insensitive; optional `hours` / `since`), then `forum_fetch_post` on a returned `id`. Walk a user's posts with `forum_user_post_ids` then `forum_fetch_post`. Writes need a `ticket` from forum EIP-712 login. `forum_unread` / `forum_mark_read` / `forum_mark_unread` are **interactive inbox** tools (NodeBB Unread is per topic). Confirm before `forum_mark_read` with `all: true`. `forum_delete` is **admin/moderator only** (not the post owner): exactly one of `pid`, `tid`/`url`, or `username`; optional `hours` / `since` (default all). Confirm with the operator before deleting. Never from cron.
51
+
52
+ **Classify first: Idea vs formal proposal.** An Idea/Suggestion is early discussion or feedback — not a Temperature Check. Post it with `forum_create_idea`. Do **not** use that URL as `forumKey`. A formal proposal belongs in a **Governance** section and must go on-chain.
53
+
54
+ | Type | Forum `section` | Typical vote |
55
+ |------|-----------------|--------------|
56
+ | Decision | `decision` | Bravo |
57
+ | Election | `election` | Delta |
58
+ | Treasury | `treasury` | Bravo |
59
+ | Constitution | `constitution` | Bravo (include the new Constitution text) |
60
+ | Admin | `admin` | Bravo |
61
+
62
+ **A proposal MUST have a Governance forum thread.** Never call `build_propose_*` or `register_proposal` with the homepage, an empty `forumKey`, or an Ideas thread. Required agent order:
63
+
64
+ 1. `forum_sign_in_eligible` then `build_forum_sign_in_multisign` (if no ticket).
65
+ 2. If it is only an idea: `forum_create_idea`. Stop (no propose).
66
+ 3. If it is a proposal: `forum_create_topic` with the matching Governance `section` (proposal-threshold veCTM). Keep the returned `url`.
67
+ 4. `build_propose_bravo_multisign` or `build_propose_delta_multisign` with that `url` as `forumKey`.
68
+ 5. After the propose tx is mined, `register_proposal` with the same `forumKey`.
69
+
70
+ `forumKey` must match `/topic/:tid` or `/t/:tid` on forum.continuumdao.org. Builders and `register_proposal` throw otherwise.
71
+
72
+ Forum KeyGen sign-in is EIP-712 multi-sign (no EVM tx). Always check eligibility first:
73
+
74
+ 1. `ctm_continuum_dao_forum_sign_in_eligible({ address })` — holder or attach-key veCTM vs `veCtmThresholdPower`. If `eligible` is false, stop. Do **not** compose a multi-sign request.
75
+ 2. `ctm_continuum_dao_build_forum_sign_in_multisign` also refuses ineligible addresses (same gate) so other nodes never enter the sign loop. Pass `nodeKey` (username = first 16 chars) or a `username` on first login.
76
+ 3. After the multi-sign request is signed, exchange the signature for a ticket (`/api/continuum/eip712/ticket`). Then `forum_reply` / `forum_react` / `forum_create_topic` / `forum_create_idea`.
77
+ 4. `ctm_continuum_dao_forum_sign_out({ ticket })` revokes the ticket and forum sessions. No multi-sign.
78
+
79
+ Forum sign-in and sign-out are **agent/MCP only**. There is no Sign in / Sign out control in the node-app Compose header.
80
+
81
+ Propose builders read live `proposalThreshold()` and refuse if `getVotes(KeyGen) < threshold`. On-chain rule (vectm `ContinuumDAO`): `max(1000 ether, 1% of past total voting power)`. Do not hardcode `1000`.
82
+
83
+ ## Tools
84
+
85
+ | Intent | Tool |
86
+ |--------|------|
87
+ | Create lock | `ctm_continuum_dao_build_create_lock_multisign` |
88
+ | Increase amount | `ctm_continuum_dao_build_increase_amount_multisign` |
89
+ | Increase unlock time | `ctm_continuum_dao_build_increase_unlock_time_multisign` |
90
+ | Split | `ctm_continuum_dao_build_split_multisign` |
91
+ | Merge | `ctm_continuum_dao_build_merge_multisign` |
92
+ | Withdraw | `ctm_continuum_dao_build_withdraw_multisign` |
93
+ | Liquidate | `ctm_continuum_dao_build_liquidate_multisign` |
94
+ | Delegate | `ctm_continuum_dao_build_delegate_multisign` |
95
+ | Undelegate (delegate to self) | `ctm_continuum_dao_build_undelegate_multisign` |
96
+ | Fetch current delegatee | `ctm_continuum_dao_fetch_delegates` |
97
+ | Transfer NFT | `ctm_continuum_dao_build_transfer_multisign` |
98
+ | Attach veCTM | `ctm_continuum_dao_build_attach_multisign` |
99
+ | Request detach | `ctm_continuum_dao_build_request_detach_multisign` |
100
+ | Propose Bravo | `ctm_continuum_dao_build_propose_bravo_multisign` |
101
+ | Propose Delta | `ctm_continuum_dao_build_propose_delta_multisign` |
102
+ | Vote Bravo | `ctm_continuum_dao_build_cast_vote_bravo_multisign` |
103
+ | Vote Delta (+ NOTA) | `ctm_continuum_dao_build_cast_vote_delta_multisign` |
104
+ | Execute | `ctm_continuum_dao_build_execute_multisign` |
105
+ | Cancel | `ctm_continuum_dao_build_cancel_multisign` |
106
+ | Register proposal (backend) | `ctm_continuum_dao_register_proposal` |
107
+ | Fetch live / pending / executable | `ctm_continuum_dao_fetch_live_proposals` |
108
+ | Explain / deconstruct one proposal | `ctm_continuum_dao_explain_proposal` |
109
+ | Fetch raw backend list | `ctm_continuum_dao_fetch_proposals` |
110
+ | Fetch one proposal | `ctm_continuum_dao_fetch_proposal` |
111
+ | Fetch on-chain state | `ctm_continuum_dao_fetch_proposal_state` |
112
+ | Fetch voting power | `ctm_continuum_dao_fetch_voting_power` |
113
+ | Forum sign-in eligible? | `ctm_continuum_dao_forum_sign_in_eligible` |
114
+ | Forum KeyGen sign-in | `ctm_continuum_dao_build_forum_sign_in_multisign` |
115
+ | Forum sign-out | `ctm_continuum_dao_forum_sign_out` |
116
+ | Resolve forum URL | `ctm_continuum_dao_forum_resolve` |
117
+ | Fetch forum thread | `ctm_continuum_dao_forum_fetch_thread` |
118
+ | Fetch one forum post | `ctm_continuum_dao_forum_fetch_post` |
119
+ | Search forum (title/body, optional recency) | `ctm_continuum_dao_forum_search` |
120
+ | Recent forum posts (id, title, username, createdAt; hours / since) | `ctm_continuum_dao_forum_recent` |
121
+ | Admin/mod delete post, thread, or user posts | `ctm_continuum_dao_forum_delete` |
122
+ | User post ids | `ctm_continuum_dao_forum_user_post_ids` |
123
+ | Forum reply count | `ctm_continuum_dao_forum_reply_count` |
124
+ | Forum reply | `ctm_continuum_dao_forum_reply` |
125
+ | Forum react | `ctm_continuum_dao_forum_react` |
126
+ | Create Governance proposal thread | `ctm_continuum_dao_forum_create_topic` |
127
+ | Post Idea / Suggestion | `ctm_continuum_dao_forum_create_idea` |
128
+ | Forum unread topics | `ctm_continuum_dao_forum_unread` |
129
+ | Forum mark topic read | `ctm_continuum_dao_forum_mark_read` |
130
+ | Forum mark topic unread | `ctm_continuum_dao_forum_mark_unread` |
131
+ | Forum me / sections | `ctm_continuum_dao_forum_me` / `ctm_continuum_dao_forum_sections` |
132
+
133
+ Attach requires the claimed `nodeWithdrawAuthority` KeyGen that owns the NFT. `groupId` is implicit from that KeyGen. You cannot replace an attached NFT — only governance detaches after `request detach`.
134
+
135
+ Attached locks block transfer / merge / split / withdraw on-chain (`checkNotAttached`).
136
+
137
+ Propose and vote use `getVotes` at the **KeyGen** address. If the KeyGen has delegated away (`fetch_delegates` → `self: false`), that power sits with the delegatee until `build_undelegate_multisign` (on-chain this is `delegate(self)`; there is no `undelegate()`). Attach-to-node is unrelated. Propose requires `getVotes(keyAddress) >= proposalThreshold()`. The live threshold is `max(1000e18 ve power, 1% of total voting power)`, not a flat 1000. `ctm_continuum_dao_build_propose_*` throws if the KeyGen is below the live bar.
138
+
139
+ All `ctm_continuum_dao_build_*_multisign` tools return `{ requestId }` on success (shared gas/submit section appended by the server).
@@ -66,14 +66,17 @@ Do **not** use `ctm_arcus_build_deposit_multisign` for yield — that funds perp
66
66
 
67
67
  ## Morpho Midnight (fixed rate / fixed term)
68
68
 
69
- Midnight is a separate order-book primitive (not Blue). Users **take** existing offers via MidnightBundles. Launch liquidity is strongest on **Base (8453)** (e.g. cbBTC/USDC maturities).
69
+ Midnight is a separate order-book primitive (not Blue). Users can **take** existing offers via MidnightBundles, or **post a lend offer** that parks the loan token in Morpho Blue (variable yield) until a borrower fills it. Launch liquidity is strongest on **Base (8453)** (e.g. cbBTC/USDC maturities).
70
70
 
71
71
  | Goal | Tool |
72
72
  |------|------|
73
73
  | List books | `ctm_morpho_fetch_midnight_books({ chainId: 8453, loan?, collateral?, side? })` |
74
74
  | Preview fill | `ctm_morpho_fetch_midnight_quote({ marketId, side: "asks"\|"bids", assets })` |
75
75
  | User positions | `ctm_morpho_fetch_midnight_positions({ user })` |
76
- | Lend (take asks) | `ctm_morpho_build_midnight_lend_multisign` |
76
+ | Open lend offers | `ctm_morpho_fetch_midnight_offers({ user, chainId? })` |
77
+ | Lend now (take asks) | `ctm_morpho_build_midnight_lend_multisign` |
78
+ | Lend offer (earn until filled) | `ctm_morpho_build_midnight_lend_offer_multisign` |
79
+ | Cancel lend offer + withdraw unused | `ctm_morpho_build_midnight_cancel_lend_offer_multisign` |
77
80
  | Borrow (collateral + take bids) | `ctm_morpho_build_midnight_borrow_multisign` |
78
81
  | Repay + withdraw collateral | `ctm_morpho_build_midnight_repay_multisign` |
79
82
 
@@ -81,11 +84,13 @@ Workflow:
81
84
 
82
85
  1. `ctm_morpho_fetch_midnight_books` — pick `marketId`, note `loanTokenAddress` / `primaryCollateralTokenAddress`, `lendApr` / `borrowApr`, maturity.
83
86
  2. Optional: `ctm_morpho_fetch_midnight_quote` with raw `assets` (loan token base units).
84
- 3. Lend: `ctm_morpho_build_midnight_lend_multisign({ marketId, amountHuman, … })`.
85
- 4. Borrow: `ctm_morpho_build_midnight_borrow_multisign({ marketId, borrowAmountHuman, collateralAmountHuman, collateralToken, … })`.
86
- 5. Exit: `ctm_morpho_fetch_midnight_positions` → `ctm_morpho_build_midnight_repay_multisign({ marketId })`.
87
+ 3. Immediate lend: `ctm_morpho_build_midnight_lend_multisign({ marketId, amountHuman, … })`.
88
+ 4. Limit lend that earns while waiting: `ctm_morpho_build_midnight_lend_offer_multisign({ marketId, amountHuman, lendAprPct? })`. Funds are supplied to the deepest Blue market for that loan token via BlueBuyCallback.
89
+ 5. Borrow: `ctm_morpho_build_midnight_borrow_multisign({ marketId, borrowAmountHuman, collateralAmountHuman, collateralToken, … })`.
90
+ 6. Exit a matched borrow: `ctm_morpho_fetch_midnight_positions` → `ctm_morpho_build_midnight_repay_multisign({ marketId })`.
91
+ 7. Cancel an unfilled offer: `ctm_morpho_fetch_midnight_offers` → `ctm_morpho_build_midnight_cancel_lend_offer_multisign({ group, callback, callbackData })`.
87
92
 
88
- Server re-quotes at build time and fills `taker` / `onBehalf` from the executor. Maker offer posting is not supported.
93
+ Server re-quotes at build time and fills `taker` / `maker` / `onBehalf` from the executor.
89
94
 
90
95
  ## MCP multisign tools
91
96
 
@@ -96,13 +101,16 @@ Server re-quotes at build time and fills `taker` / `onBehalf` from the executor.
96
101
  | `ctm_morpho_fetch_midnight_books` | List Midnight books |
97
102
  | `ctm_morpho_fetch_midnight_quote` | Quote Midnight fill |
98
103
  | `ctm_morpho_fetch_midnight_positions` | Midnight positions |
104
+ | `ctm_morpho_fetch_midnight_offers` | Open Midnight lend offers |
99
105
  | `ctm_morpho_build_vault_deposit_multisign` | Vault deposit (listed V1 or V2) |
100
106
  | `ctm_morpho_build_vault_withdraw_multisign` | Vault withdraw |
101
107
  | `ctm_morpho_build_blue_collateral_deposit_multisign` | Blue supplyCollateral |
102
108
  | `ctm_morpho_build_blue_borrow_multisign` | Blue borrow |
103
109
  | `ctm_morpho_build_blue_repay_multisign` | Blue repay |
104
110
  | `ctm_morpho_build_blue_collateral_withdraw_multisign` | Blue withdrawCollateral |
105
- | `ctm_morpho_build_midnight_lend_multisign` | Midnight lend |
111
+ | `ctm_morpho_build_midnight_lend_multisign` | Midnight lend now (take asks) |
112
+ | `ctm_morpho_build_midnight_lend_offer_multisign` | Midnight lend offer (Blue yield until filled) |
113
+ | `ctm_morpho_build_midnight_cancel_lend_offer_multisign` | Cancel Midnight lend offer |
106
114
  | `ctm_morpho_build_midnight_borrow_multisign` | Midnight borrow |
107
115
  | `ctm_morpho_build_midnight_repay_multisign` | Midnight repay + withdraw |
108
116
  | `ctm_morpho_build_merkl_claim_multisign` | Merkl claim |
@@ -116,7 +124,7 @@ Pass `marketId` from Morpho API for Blue/Midnight tools (not recomputed on-chain
116
124
  2. `ctm_morpho_fetch_earn_vaults` — pick `vaultAddress` and `underlyingAddress` by asset and/or name.
117
125
  3. `ctm_morpho_build_vault_deposit_multisign` — use each tool’s **input schema** (`keyGenId`, fetch output addresses, `amountHuman`, etc.). Server resolves `keyGen`, `executorAddress`, `rpcUrl`, `chainDetail`; agents must not pass those.
118
126
  4. Blue borrow/collateral: `marketId` from Morpho API; server resolves `marketParams`.
119
- 5. Midnight: books → quote → lend/borrow/repay builders as above.
127
+ 5. Midnight: books → quote → lend now, lend offer (earn until filled), borrow, or cancel/repay as above.
120
128
 
121
129
  ## Troubleshooting
122
130
 
@@ -0,0 +1,45 @@
1
+ import { Address, PublicClient } from 'viem';
2
+ import { M as MultisignBuildResult } from './types-PZrvtjv8.js';
3
+ import { f as finalizeMultisign } from './envelope-C_bfuKab.js';
4
+ import { b as EvmTxStep, a as EvmProtocolContext } from './types-RZWOTm8c.js';
5
+
6
+ type EvmBatchMetaBuilder = (args: {
7
+ step: EvmTxStep;
8
+ index: number;
9
+ gasLimit: bigint;
10
+ }) => Record<string, unknown>;
11
+ type EvmBuildBatchArgs = {
12
+ context: EvmProtocolContext;
13
+ steps: EvmTxStep[];
14
+ purposeSuffix?: string;
15
+ buildBatchMeta: EvmBatchMetaBuilder;
16
+ /** First leg msgRaw without 0x prefix; defaults to first step calldata */
17
+ firstMsgRawNo0x?: string;
18
+ destinationAddress?: Address;
19
+ /** Top-level `value` on bodyForSign when the payable amount is not on the first leg */
20
+ payableValueWei?: bigint;
21
+ resolveGasLimit?: (args: {
22
+ step: EvmTxStep;
23
+ index: number;
24
+ estimatedGas: bigint;
25
+ publicClient: PublicClient;
26
+ }) => Promise<bigint> | bigint;
27
+ /** Override default `estimateGas` (e.g. trade-API gas, skip post-approve deposit estimate). */
28
+ estimateGasForStep?: (args: {
29
+ step: EvmTxStep;
30
+ index: number;
31
+ publicClient: PublicClient;
32
+ executor: Address;
33
+ }) => Promise<bigint> | bigint;
34
+ };
35
+ /**
36
+ * Build unsigned EVM txs, estimate gas, serialize, hash — then assemble mpc-auth body via core envelope.
37
+ */
38
+ declare function buildEvmMultisignBatch(args: EvmBuildBatchArgs): Promise<MultisignBuildResult>;
39
+ declare const evmChainCategoryModule: {
40
+ category: "evm";
41
+ finalizeMultisign: typeof finalizeMultisign;
42
+ buildEvmMultisignBatch: typeof buildEvmMultisignBatch;
43
+ };
44
+
45
+ export { type EvmBatchMetaBuilder as E, type EvmBuildBatchArgs as a, buildEvmMultisignBatch as b, evmChainCategoryModule as e };
@@ -1,47 +1,9 @@
1
- import { b as EvmTxStep, a as EvmProtocolContext } from '../../types-RZWOTm8c.js';
2
- export { E as EvmChainDetail, i as isEvmNativeToken, m as matchEvmTokenKind } from '../../types-RZWOTm8c.js';
1
+ import { b as EvmTxStep } from '../../types-RZWOTm8c.js';
2
+ export { E as EvmChainDetail, a as EvmProtocolContext, i as isEvmNativeToken, m as matchEvmTokenKind } from '../../types-RZWOTm8c.js';
3
+ export { E as EvmBatchMetaBuilder, a as EvmBuildBatchArgs, b as buildEvmMultisignBatch, e as evmChainCategoryModule } from '../../buildBatch-CngvebiD.js';
3
4
  import { Address, PublicClient } from 'viem';
4
- import { M as MultisignBuildResult } from '../../types-PZrvtjv8.js';
5
- import { f as finalizeMultisign } from '../../envelope-C_bfuKab.js';
6
-
7
- type EvmBatchMetaBuilder = (args: {
8
- step: EvmTxStep;
9
- index: number;
10
- gasLimit: bigint;
11
- }) => Record<string, unknown>;
12
- type EvmBuildBatchArgs = {
13
- context: EvmProtocolContext;
14
- steps: EvmTxStep[];
15
- purposeSuffix?: string;
16
- buildBatchMeta: EvmBatchMetaBuilder;
17
- /** First leg msgRaw without 0x prefix; defaults to first step calldata */
18
- firstMsgRawNo0x?: string;
19
- destinationAddress?: Address;
20
- /** Top-level `value` on bodyForSign when the payable amount is not on the first leg */
21
- payableValueWei?: bigint;
22
- resolveGasLimit?: (args: {
23
- step: EvmTxStep;
24
- index: number;
25
- estimatedGas: bigint;
26
- publicClient: PublicClient;
27
- }) => Promise<bigint> | bigint;
28
- /** Override default `estimateGas` (e.g. trade-API gas, skip post-approve deposit estimate). */
29
- estimateGasForStep?: (args: {
30
- step: EvmTxStep;
31
- index: number;
32
- publicClient: PublicClient;
33
- executor: Address;
34
- }) => Promise<bigint> | bigint;
35
- };
36
- /**
37
- * Build unsigned EVM txs, estimate gas, serialize, hash — then assemble mpc-auth body via core envelope.
38
- */
39
- declare function buildEvmMultisignBatch(args: EvmBuildBatchArgs): Promise<MultisignBuildResult>;
40
- declare const evmChainCategoryModule: {
41
- category: "evm";
42
- finalizeMultisign: typeof finalizeMultisign;
43
- buildEvmMultisignBatch: typeof buildEvmMultisignBatch;
44
- };
5
+ import '../../types-PZrvtjv8.js';
6
+ import '../../envelope-C_bfuKab.js';
45
7
 
46
8
  /** Parse chain id for comparisons (decimal, 0x hex, CAIP-2 eip155:N, bigint). */
47
9
  declare function parseEvmChainIdToNumber(chainId: string | number | bigint | null | undefined): number;
@@ -91,4 +53,4 @@ declare function coingeckoPlatformForChainId(chainId: string | number): string |
91
53
  /** Curve router swap gas: chain cap when set, else 12/10 estimate bump. */
92
54
  declare function routerSwapGasLimitFromEstimate(estimatedGas: bigint, chainGasLimit?: number | null): bigint;
93
55
 
94
- export { COINGECKO_PLATFORM_BY_CHAIN_ID, type ConditionalApproveStep, type EvmBatchMetaBuilder, type EvmBuildBatchArgs, EvmProtocolContext, EvmTxStep, approveStepsToEvmTxSteps, buildConditionalErc20ApproveSteps, buildEvmMultisignBatch, coingeckoPlatformForChainId, evmChainCategoryModule, normalizeCurveRouterAmountString, normalizeHumanDecimalAmount, parseEvmChainIdToNumber, publicClientForRpc, resolveErc20Decimals, routerSwapGasLimitFromEstimate };
56
+ export { COINGECKO_PLATFORM_BY_CHAIN_ID, type ConditionalApproveStep, EvmTxStep, approveStepsToEvmTxSteps, buildConditionalErc20ApproveSteps, coingeckoPlatformForChainId, normalizeCurveRouterAmountString, normalizeHumanDecimalAmount, parseEvmChainIdToNumber, publicClientForRpc, resolveErc20Decimals, routerSwapGasLimitFromEstimate };
@@ -182,57 +182,60 @@ function eip712SignatureText(domain, primaryType) {
182
182
  function jsonStringifyForAudit(value) {
183
183
  return JSON.stringify(value, (_, v) => typeof v === "bigint" ? v.toString() : v);
184
184
  }
185
- function eip712MsgRawHex(typedData, delivery) {
186
- const envelope = {
185
+ function eip712LegEnvelope(typedData, delivery, digest) {
186
+ return {
187
187
  version: 1,
188
- ...typedData,
189
- delivery
190
- };
191
- return viem.stringToHex(jsonStringifyForAudit(envelope));
192
- }
193
- function buildEip712MultisignBody(args) {
194
- const { typedData, delivery } = args;
195
- const digest = viem.hashTypedData({
188
+ digest,
196
189
  domain: typedData.domain,
197
190
  types: typedData.types,
198
191
  primaryType: typedData.primaryType,
199
- message: typedData.message
200
- });
201
- const extraJSON = {
202
- signRequestKind: EIP712_SIGN_REQUEST_KIND,
203
- eip712: {
204
- version: 1,
205
- digest,
206
- domain: typedData.domain,
207
- types: typedData.types,
208
- primaryType: typedData.primaryType,
209
- message: typedData.message
210
- },
192
+ message: typedData.message,
211
193
  delivery
212
194
  };
195
+ }
196
+ function eip712MsgRawHex(envelope) {
197
+ return viem.stringToHex(jsonStringifyForAudit(envelope));
198
+ }
199
+ function buildEip712Multisign(args) {
200
+ if (args.legs.length < 1) {
201
+ throw new Error("buildEip712Multisign requires at least one leg");
202
+ }
203
+ const eip712 = [];
204
+ const legs = args.legs.map((leg) => {
205
+ const digest = viem.hashTypedData({
206
+ domain: leg.typedData.domain,
207
+ types: leg.typedData.types,
208
+ primaryType: leg.typedData.primaryType,
209
+ message: leg.typedData.message
210
+ });
211
+ const envelope = eip712LegEnvelope(leg.typedData, leg.delivery, digest);
212
+ eip712.push(envelope);
213
+ return {
214
+ msgHash: msgHashNo0x(digest),
215
+ msgRaw: eip712MsgRawHex(envelope),
216
+ destinationAddress: args.destinationAddress,
217
+ signatureText: eip712SignatureText(leg.typedData.domain, leg.typedData.primaryType),
218
+ audit: {
219
+ kind: "EIP712",
220
+ primaryType: leg.typedData.primaryType,
221
+ deliveryKind: leg.delivery.kind,
222
+ ...leg.audit ?? {}
223
+ },
224
+ feeSnapshot: {}
225
+ };
226
+ });
213
227
  return finalizeMultisign({
214
228
  keyGen: args.keyGen,
215
229
  purposeText: args.purposeText,
216
230
  purposeSuffix: args.purposeSuffix,
217
231
  destinationChainID: args.destinationChainID,
218
232
  destinationAddress: args.destinationAddress,
219
- extraJSON,
233
+ extraJSON: {
234
+ signRequestKind: EIP712_SIGN_REQUEST_KIND,
235
+ eip712
236
+ },
220
237
  expiryDate: args.expiryDate,
221
- legs: [
222
- {
223
- msgHash: msgHashNo0x(digest),
224
- msgRaw: eip712MsgRawHex(typedData, delivery),
225
- destinationAddress: args.destinationAddress,
226
- signatureText: eip712SignatureText(typedData.domain, typedData.primaryType),
227
- audit: {
228
- kind: "EIP712",
229
- primaryType: typedData.primaryType,
230
- deliveryKind: delivery.kind,
231
- ...args.audit ?? {}
232
- },
233
- feeSnapshot: {}
234
- }
235
- ]
238
+ legs
236
239
  });
237
240
  }
238
241
  var PAYLOAD_SIGN_ED25519_REQUEST_KIND = "payload_sign_ed25519";
@@ -295,7 +298,8 @@ var DEFI_PROTOCOLS_WITH_30MIN_EXPIRY = /* @__PURE__ */ new Set([
295
298
  "gmx",
296
299
  "hyperliquid",
297
300
  "arcus",
298
- "curve-dao"
301
+ "curve-dao",
302
+ "aerodrome"
299
303
  ]);
300
304
  function defiMultisignExpiryUnixSeconds(protocolId, explicitExpiryDate) {
301
305
  if (typeof explicitExpiryDate === "number" && Number.isFinite(explicitExpiryDate) && explicitExpiryDate > 0) {
@@ -315,7 +319,7 @@ exports.DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS = DEFAULT_DEFI_MULTISIGN_EXPIRY_SE
315
319
  exports.DEFI_PROTOCOLS_WITH_30MIN_EXPIRY = DEFI_PROTOCOLS_WITH_30MIN_EXPIRY;
316
320
  exports.EIP712_SIGN_REQUEST_KIND = EIP712_SIGN_REQUEST_KIND;
317
321
  exports.PAYLOAD_SIGN_ED25519_REQUEST_KIND = PAYLOAD_SIGN_ED25519_REQUEST_KIND;
318
- exports.buildEip712MultisignBody = buildEip712MultisignBody;
322
+ exports.buildEip712Multisign = buildEip712Multisign;
319
323
  exports.buildPayloadSignEd25519MultisignBody = buildPayloadSignEd25519MultisignBody;
320
324
  exports.coreChainCategoryModule = coreChainCategoryModule;
321
325
  exports.defiMultisignExpiryUnixSeconds = defiMultisignExpiryUnixSeconds;