@continuumdao/ctm-mpc-defi 0.2.34 → 0.2.36
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/catalog.cjs +1562 -45
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +5995 -2960
- package/dist/agent/catalog.js +1502 -46
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/aave-v4/SKILL.md +19 -4
- package/dist/agent/skills/aerodrome/SKILL.md +2 -2
- package/dist/agent/skills/compound-v3/SKILL.md +2 -2
- package/dist/agent/skills/curve-dao/SKILL.md +14 -0
- package/dist/agent/skills/ethena/SKILL.md +3 -1
- package/dist/agent/skills/euler-v2/SKILL.md +1 -1
- package/dist/agent/skills/gmx/SKILL.md +1 -1
- package/dist/agent/skills/hyperliquid/SKILL.md +7 -5
- package/dist/agent/skills/lido/SKILL.md +3 -0
- package/dist/agent/skills/maple-syrup/SKILL.md +35 -3
- package/dist/agent/skills/morpho/SKILL.md +1 -1
- package/dist/agent/skills/pendle/SKILL.md +63 -0
- package/dist/agent/skills/sky/SKILL.md +2 -0
- package/dist/agent/skills/yield-compare/SKILL.md +81 -0
- package/dist/core/index.cjs +2 -1
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.js +2 -1
- package/dist/core/index.js.map +1 -1
- package/dist/index.cjs +257 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +257 -28
- package/dist/index.js.map +1 -1
- package/dist/protocols/evm/aave-v4/index.cjs +170 -0
- package/dist/protocols/evm/aave-v4/index.cjs.map +1 -1
- package/dist/protocols/evm/aave-v4/index.d.ts +59 -1
- package/dist/protocols/evm/aave-v4/index.js +164 -1
- package/dist/protocols/evm/aave-v4/index.js.map +1 -1
- package/dist/protocols/evm/aerodrome/index.cjs +1308 -901
- package/dist/protocols/evm/aerodrome/index.cjs.map +1 -1
- package/dist/protocols/evm/aerodrome/index.d.ts +69 -2
- package/dist/protocols/evm/aerodrome/index.js +1217 -807
- package/dist/protocols/evm/aerodrome/index.js.map +1 -1
- package/dist/protocols/evm/compound-v3/index.cjs +82 -6
- package/dist/protocols/evm/compound-v3/index.cjs.map +1 -1
- package/dist/protocols/evm/compound-v3/index.d.ts +89 -1
- package/dist/protocols/evm/compound-v3/index.js +80 -7
- package/dist/protocols/evm/compound-v3/index.js.map +1 -1
- package/dist/protocols/evm/curve-dao/index.cjs +447 -18
- package/dist/protocols/evm/curve-dao/index.cjs.map +1 -1
- package/dist/protocols/evm/curve-dao/index.d.ts +108 -1
- package/dist/protocols/evm/curve-dao/index.js +440 -19
- package/dist/protocols/evm/curve-dao/index.js.map +1 -1
- package/dist/protocols/evm/ethena/index.cjs +89 -0
- package/dist/protocols/evm/ethena/index.cjs.map +1 -1
- package/dist/protocols/evm/ethena/index.d.ts +17 -1
- package/dist/protocols/evm/ethena/index.js +89 -2
- package/dist/protocols/evm/ethena/index.js.map +1 -1
- package/dist/protocols/evm/euler-v2/index.cjs +29 -0
- package/dist/protocols/evm/euler-v2/index.cjs.map +1 -1
- package/dist/protocols/evm/euler-v2/index.d.ts +21 -1
- package/dist/protocols/evm/euler-v2/index.js +29 -1
- package/dist/protocols/evm/euler-v2/index.js.map +1 -1
- package/dist/protocols/evm/gmx/index.cjs +83 -1
- package/dist/protocols/evm/gmx/index.cjs.map +1 -1
- package/dist/protocols/evm/gmx/index.d.ts +22 -2
- package/dist/protocols/evm/gmx/index.js +80 -2
- package/dist/protocols/evm/gmx/index.js.map +1 -1
- package/dist/protocols/evm/hyperliquid/index.cjs +67 -11
- package/dist/protocols/evm/hyperliquid/index.cjs.map +1 -1
- package/dist/protocols/evm/hyperliquid/index.d.ts +39 -2
- package/dist/protocols/evm/hyperliquid/index.js +64 -12
- package/dist/protocols/evm/hyperliquid/index.js.map +1 -1
- package/dist/protocols/evm/lido/index.cjs +13 -0
- package/dist/protocols/evm/lido/index.cjs.map +1 -1
- package/dist/protocols/evm/lido/index.d.ts +9 -1
- package/dist/protocols/evm/lido/index.js +13 -1
- package/dist/protocols/evm/lido/index.js.map +1 -1
- package/dist/protocols/evm/maple/index.cjs +129 -1
- package/dist/protocols/evm/maple/index.cjs.map +1 -1
- package/dist/protocols/evm/maple/index.d.ts +45 -1
- package/dist/protocols/evm/maple/index.js +124 -3
- package/dist/protocols/evm/maple/index.js.map +1 -1
- package/dist/protocols/evm/morpho/index.cjs +34 -7
- package/dist/protocols/evm/morpho/index.cjs.map +1 -1
- package/dist/protocols/evm/morpho/index.d.ts +23 -1
- package/dist/protocols/evm/morpho/index.js +34 -8
- package/dist/protocols/evm/morpho/index.js.map +1 -1
- package/dist/protocols/evm/pendle/index.cjs +1530 -0
- package/dist/protocols/evm/pendle/index.cjs.map +1 -0
- package/dist/protocols/evm/pendle/index.d.ts +463 -0
- package/dist/protocols/evm/pendle/index.js +1463 -0
- package/dist/protocols/evm/pendle/index.js.map +1 -0
- package/dist/protocols/evm/sky/index.cjs +52 -0
- package/dist/protocols/evm/sky/index.cjs.map +1 -1
- package/dist/protocols/evm/sky/index.d.ts +16 -1
- package/dist/protocols/evm/sky/index.js +50 -1
- package/dist/protocols/evm/sky/index.js.map +1 -1
- package/package.json +6 -1
|
@@ -13,7 +13,7 @@ Aave v4 organizes liquidity into **hubs** (market segments) and **spokes** (on-c
|
|
|
13
13
|
|---------|------------|---------------------|
|
|
14
14
|
| **Hub** | Off-chain market segment (Core, Plus, Prime) | Maps to UI `marketId`: `main` → Plus, `core` → Core, `bluechip` → Prime |
|
|
15
15
|
| **Spoke** | On-chain contract (`supply`, `withdraw`, `borrow`, `repay`) | **Do not guess.** The MCP server resolves spoke from the Aave v4 API using `chainId` + `underlying` + `marketId` |
|
|
16
|
-
| **Reserve** | One asset in one hub (underlying + APY + spoke) |
|
|
16
|
+
| **Reserve** | One asset in one hub (underlying + APY + spoke) | From `ctm_aave_v4_fetch_markets` — do not web-search rates |
|
|
17
17
|
| **Position** | User’s supplies/debt on a spoke | Withdraw/borrow/repay risk depends on health factor on that spoke |
|
|
18
18
|
|
|
19
19
|
**Important:** The UI market (`main`) and the hub that lists an asset can differ. Example on Ethereum: WETH is in **Core**, not Plus, even when the user picks “main”. The server auto-picks the hub that actually lists the asset.
|
|
@@ -24,17 +24,22 @@ Aave v4 organizes liquidity into **hubs** (market segments) and **spokes** (on-c
|
|
|
24
24
|
2. `get_defi_protocol_supported_chains` — intersect with `get_chain_registry` (node must have `rpcGateway` per chain)
|
|
25
25
|
3. `get_defi_protocol_supported_tokens({ protocolId: "aave-v4", chainId })` — listed underlyings + `nativeWrapped`
|
|
26
26
|
4. `get_token_registry` — map symbols (USDC, WETH, stETH) to addresses
|
|
27
|
+
5. `ctm_aave_v4_fetch_markets` — live supply/borrow APY per reserve (not web search)
|
|
27
28
|
|
|
28
29
|
## Tool selection
|
|
29
30
|
|
|
31
|
+
Do **not** web-search Aave APRs, APYs, or reserves. Load the protocol and use the fetch tools below.
|
|
32
|
+
|
|
30
33
|
| User intent | MCP tool |
|
|
31
34
|
|-------------|----------|
|
|
35
|
+
| List reserves / lending APRs / compare rates | `ctm_aave_v4_fetch_markets` |
|
|
36
|
+
| One asset’s APY (optionally one hub) | `ctm_aave_v4_fetch_market` |
|
|
32
37
|
| Supply / deposit (lend) | `ctm_aave_v4_build_deposit_multisign` |
|
|
33
38
|
| Withdraw supplied balance | `ctm_aave_v4_build_withdraw_multisign` |
|
|
34
39
|
| Borrow against collateral | `ctm_aave_v4_build_borrow_multisign` |
|
|
35
40
|
| Repay debt | `ctm_aave_v4_build_repay_multisign` |
|
|
36
41
|
|
|
37
|
-
## Common inputs
|
|
42
|
+
## Common write inputs
|
|
38
43
|
|
|
39
44
|
| Field | Required | Notes |
|
|
40
45
|
|-------|----------|-------|
|
|
@@ -75,11 +80,21 @@ Aave v4 organizes liquidity into **hubs** (market segments) and **spokes** (on-c
|
|
|
75
80
|
|
|
76
81
|
## Basic workflows (teach users)
|
|
77
82
|
|
|
83
|
+
### Compare lending APRs (read-only)
|
|
84
|
+
|
|
85
|
+
Example: “How do Aave lending APRs compare to Compound on Ethereum?”
|
|
86
|
+
|
|
87
|
+
1. `load_defi_protocol({ protocolId: "aave-v4" })` then `get_defi_protocol_skill`.
|
|
88
|
+
2. `ctm_aave_v4_fetch_markets` with `chainId` 1. Optional `marketId` (`main` / `core` / `bluechip`) or `underlying` to filter.
|
|
89
|
+
3. Each row is one live spoke on a hub (unused zero-liquidity listings omitted): `supplyApyPercent`, `borrowApyPercent`, `utilizationPercent`, `availableLiquidity`. The same asset can appear on more than one spoke.
|
|
90
|
+
4. Aave reports **APY** (compounded). Compound v3 reports **APR** — say so when comparing.
|
|
91
|
+
5. Copy `underlying` + `marketId` for a later deposit/borrow. Do not invent rates from the web.
|
|
92
|
+
|
|
78
93
|
### Lend only (supply)
|
|
79
94
|
|
|
80
95
|
1. Confirm chain in registry and Aave-supported.
|
|
81
|
-
2. Resolve token address (
|
|
82
|
-
3. `ctm_aave_v4_build_deposit_multisign` with `underlying`, `amountHuman`, `marketId`
|
|
96
|
+
2. Resolve token address (`ctm_aave_v4_fetch_markets` or `get_defi_protocol_supported_tokens`).
|
|
97
|
+
3. `ctm_aave_v4_build_deposit_multisign` with `underlying`, `amountHuman`, `marketId` from the fetch row.
|
|
83
98
|
4. Complete sign lifecycle → `{ requestId }`.
|
|
84
99
|
|
|
85
100
|
### Borrow against collateral
|
|
@@ -11,7 +11,7 @@ Native ETH in the app and MCP is **`0x0000000000000000000000000000000000000000`*
|
|
|
11
11
|
|
|
12
12
|
## Quote first (Coinbase B20 / AAPLc)
|
|
13
13
|
|
|
14
|
-
**Do not** dump
|
|
14
|
+
**Do not** dump LpSugar or paginate factories. `ctm_aerodrome_fetch_pools` and `ctm_aerodrome_fetch_lp_yields` return **at most ~100 important pairs**. Optional `query` only shrinks that set. B20 stock LP yields are `ctm_aerodrome_fetch_stock_lp_yields` only. Tickers resolve inside quote / discover.
|
|
15
15
|
|
|
16
16
|
For a price, **call `ctm_aerodrome_quote` immediately**:
|
|
17
17
|
|
|
@@ -47,7 +47,7 @@ Do not create the request until they confirm both.
|
|
|
47
47
|
|
|
48
48
|
| Pack | Tools | Sign request? |
|
|
49
49
|
|------|-------|----------------|
|
|
50
|
-
| market-data | `ctm_aerodrome_discover_pools`, `ctm_aerodrome_quote`, `ctm_aerodrome_fetch_positions`, `ctm_aerodrome_fetch_pools` (
|
|
50
|
+
| market-data | `ctm_aerodrome_discover_pools`, `ctm_aerodrome_quote`, `ctm_aerodrome_fetch_positions`, `ctm_aerodrome_fetch_pools` / `fetch_lp_yields` (~100 main pairs), `fetch_stock_lp_yields` (B20 only) | No |
|
|
51
51
|
| swaps | `ctm_aerodrome_build_swap_multisign` | Yes |
|
|
52
52
|
| lp | `quote_add_liquidity`, `quote_cl_deposit`, add/remove liquidity, CL mint/increase/decrease/burn, gauge stake/unstake | Quotes no; builds yes |
|
|
53
53
|
| rewards | claim fees, CL collect, claim emissions | Yes |
|
|
@@ -27,12 +27,12 @@ Each Compound III market is an isolated **Comet**. You always call the **Comet p
|
|
|
27
27
|
|
|
28
28
|
## Tool selection
|
|
29
29
|
|
|
30
|
-
Do **not** web-search Compound III markets, collaterals, or APRs. Load the protocol and use the fetch tools below.
|
|
30
|
+
Do **not** web-search Compound III markets, collaterals, or APRs. Load the protocol and use the fetch tools below. Each market row has **base** `supplyAprPercent` / `borrowAprPercent` plus optional `supplyRewardAprPercent` / `borrowRewardAprPercent` (COMP incentive; extra and variable; null if unpriced).
|
|
31
31
|
|
|
32
32
|
| User intent | MCP tool |
|
|
33
33
|
|-------------|----------|
|
|
34
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` |
|
|
35
|
+
| Market detail (CFs, prices, base APR + COMP incentive APR) | `ctm_compound_v3_fetch_market` |
|
|
36
36
|
| Position + liquidation risk + claimable | `ctm_compound_v3_fetch_account` |
|
|
37
37
|
| Supply collateral or base (earn / repay) | `ctm_compound_v3_build_supply_multisign` |
|
|
38
38
|
| Withdraw or borrow base | `ctm_compound_v3_build_withdraw_multisign` |
|
|
@@ -18,6 +18,20 @@ Curve swaps on Continuum use **Curve Router NG** (`@curvefi/api`): the SDK loads
|
|
|
18
18
|
|
|
19
19
|
There is no separate “hub” or “spoke” — routing is entirely determined by Curve’s pool connectivity on that chain.
|
|
20
20
|
|
|
21
|
+
## Important pools and LP (not a factory dump)
|
|
22
|
+
|
|
23
|
+
Do **not** call `fetchAllCurvePools`, invent a “list all Curve pools” tool, or paginate factories. The only list tools are:
|
|
24
|
+
|
|
25
|
+
| Goal | Tool |
|
|
26
|
+
|------|------|
|
|
27
|
+
| ~100 TVL-ranked pools + APY/TVL | `ctm_curve_dao_fetch_important_pools` |
|
|
28
|
+
| Same set with `baseApy` / `gauge_crv_apy` | `ctm_curve_dao_fetch_lp_yields` |
|
|
29
|
+
| Quote add / remove LP | `ctm_curve_dao_quote_add_liquidity` / `_remove_liquidity` |
|
|
30
|
+
| Build add / remove | `ctm_curve_dao_build_add_liquidity_multisign` / `_remove_liquidity_multisign` |
|
|
31
|
+
| Gauge stake (needed for advertised `gauge_crv_apy`) | `ctm_curve_dao_build_gauge_deposit_multisign` (`withdraw: true` to unstake) |
|
|
32
|
+
|
|
33
|
+
Optional `query` / `pool` only **shrink** the ~100-row set. `gauge_crv_apy` requires staking the LP token in the gauge; otherwise quote fee APY only.
|
|
34
|
+
|
|
21
35
|
## Before any swap
|
|
22
36
|
|
|
23
37
|
1. `load_defi_protocol({ protocolId: "curve-dao" })`
|
|
@@ -7,4 +7,6 @@ description: Ethena USDe stake, redeem, cooldown, and claim on Ethereum mainnet.
|
|
|
7
7
|
|
|
8
8
|
Stake/redeem MCP tools target **mainnet (chainId 1)**. USDe/sUSDe are also listed on several L2s including **Robinhood Chain (4663)** for asset recognition/transfers — use `get_defi_protocol_supported_tokens` for addresses.
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
Do **not** web-search sUSDe APY. Use `ctm_ethena_fetch_susde_apy` (Ethena yield feed + vault share price). Unstake has a cooldown (`cooldownDurationSec`).
|
|
11
|
+
|
|
12
|
+
Tools: `ctm_ethena_fetch_susde_apy`, `ctm_ethena_build_stake_multisign`, `_redeem_`, `_cooldown_`, `_claim_`. Write tools return `{ requestId }` on success (shared gas/submit section appended by the server).
|
|
@@ -5,6 +5,6 @@ description: Euler v2 isolated lend/borrow, vault withdraw, and collateral opera
|
|
|
5
5
|
|
|
6
6
|
# Euler v2 (MCP)
|
|
7
7
|
|
|
8
|
-
Supported chains from `get_defi_protocol_supported_chains` (Euler V3 API, Goldsky `euler-simple-*` fallback). Underlyings from `get_defi_protocol_supported_tokens` (V3 EVK / Earn vaults)
|
|
8
|
+
Supported chains from `get_defi_protocol_supported_chains` (Euler V3 API, Goldsky `euler-simple-*` fallback). Underlyings from `get_defi_protocol_supported_tokens` (V3 EVK / Earn vaults). Isolated lend: `ctm_euler_v2_fetch_lend_vaults`. Earn vaults (curated APY): `ctm_euler_v2_fetch_earn_vaults`. Do **not** web-search Euler APYs. Copy `evaultAddress` onto build tools.
|
|
9
9
|
|
|
10
10
|
Tools include isolated lend/borrow, collateral deposit/withdraw, vault withdraw, borrow repay. All `ctm_euler_v2_build_*_multisign` tools return `{ requestId }` on success (shared gas/submit section appended by the server).
|
|
@@ -13,7 +13,7 @@ Perpetuals on Arbitrum (42161) and Avalanche (43114) via `@gmx-io/sdk` v2 **clas
|
|
|
13
13
|
|
|
14
14
|
1. `load_defi_protocol({ protocolId: "gmx" })`
|
|
15
15
|
2. `ctm_gmx_fetch_markets({ chainId })` — pick `symbol` e.g. `ETH/USD [WETH-USDC]`; each row includes `maxLeverageLabel`
|
|
16
|
-
3. `ctm_gmx_fetch_market_prices({ chainId, symbol, collateralSymbol })` — index/collateral USD mark
|
|
16
|
+
3. `ctm_gmx_fetch_market_prices({ chainId, symbol, collateralSymbol })` — index/collateral USD mark plus official funding (`fundingFactorPerSecond`, `longsPayShorts`, hourly/APR labels; borrow-per-second is a cost caveat)
|
|
17
17
|
4. `ctm_gmx_fetch_ohlcv({ chainId, symbol, timeframe: "15m" })` — tabular OHLCV candles (USD index); then **`continuum__prepare_chart_from_rows`** if the operator wants a chart
|
|
18
18
|
5. `ctm_gmx_fetch_positions({ chainId, executorAddress })` — for close flows
|
|
19
19
|
6. `get_multi_sign_gas_options({ chainId })` — confirm `useCustomGas` with the user
|
|
@@ -42,7 +42,7 @@ Positions and orders from MCP reflect **live HyperCore state** after prior txs a
|
|
|
42
42
|
2. `get_defi_protocol_skill` — this file (+ shared gas/submit section appended)
|
|
43
43
|
3. Confirm chain **999** or **998** in `get_chain_registry` with RPC
|
|
44
44
|
4. `ctm_hyperliquid_search_markets({ chainId: 999, query: "AAPL" })` or `query: "Apple"` — resolves canonical `coin` (e.g. `xyz:AAPL`); use when user gives a ticker or company name
|
|
45
|
-
5. `ctm_hyperliquid_fetch_market_snapshot({ chainId, coin: "AAPL" })` — **`livePrice.midUsd`** is the current price; `latestCandle` is the most recent bar; `candles` is capped (default 48). Throws if live price cannot be fetched.
|
|
45
|
+
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
46
|
6. `ctm_hyperliquid_fetch_open_context({ chainId, executorAddress, coin: "Apple" })` — same resolution
|
|
47
47
|
7. `ctm_hyperliquid_fetch_usd_class_balances({ chainId, executorAddress })` — spot vs perp USD if needed
|
|
48
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`).
|
|
@@ -55,15 +55,17 @@ Positions and orders from MCP reflect **live HyperCore state** after prior txs a
|
|
|
55
55
|
|
|
56
56
|
| User intent | MCP tool |
|
|
57
57
|
|-------------|----------|
|
|
58
|
-
| List
|
|
58
|
+
| List native crypto perp markets | `ctm_hyperliquid_fetch_markets` |
|
|
59
|
+
| List HIP-3 stock perps (AAPL, TSLA, …) | `ctm_hyperliquid_fetch_stock_markets` |
|
|
59
60
|
| **Find market by ticker or name** (AAPL, Apple, BTC) | `ctm_hyperliquid_search_markets` |
|
|
60
|
-
| **Live price** (mark/mid) + short recent bars | `ctm_hyperliquid_fetch_market_snapshot` — use **`snapshot.livePrice.midUsd`** |
|
|
61
|
+
| **Live price** (mark/mid) + hourly **funding** + short recent bars | `ctm_hyperliquid_fetch_market_snapshot` — use **`snapshot.livePrice.midUsd`** and **`snapshot.funding`** |
|
|
61
62
|
| **OHLCV history** (e.g. 15m for last 7 days) | `ctm_hyperliquid_fetch_ohlcv` — then **`continuum__prepare_chart_from_rows`** if user wants a chart |
|
|
62
63
|
| Account + capacity for one coin | `ctm_hyperliquid_fetch_open_context` |
|
|
63
64
|
| Open positions | `ctm_hyperliquid_fetch_positions` |
|
|
64
65
|
| Open orders | `ctm_hyperliquid_fetch_open_orders` |
|
|
65
66
|
| Spot vs perp USDC | `ctm_hyperliquid_fetch_usd_class_balances` |
|
|
66
|
-
| Vault catalog (+ APR) | `ctm_hyperliquid_fetch_vaults` |
|
|
67
|
+
| Vault catalog (+ APR, TVL-sorted) | `ctm_hyperliquid_fetch_vaults` |
|
|
68
|
+
| Vault APRs for yield compare (APR desc, HLP first) | `ctm_hyperliquid_fetch_vault_apys` |
|
|
67
69
|
| User vault equity | `ctm_hyperliquid_fetch_user_vault_equities` |
|
|
68
70
|
| HYPE stake summary | `ctm_hyperliquid_fetch_staking_summary` |
|
|
69
71
|
| Validator delegations | `ctm_hyperliquid_fetch_delegations` |
|
|
@@ -289,7 +291,7 @@ Default overlays (EMA 50, RSI 14, volume pane) are applied inside `prepare_chart
|
|
|
289
291
|
|
|
290
292
|
## HIP-3 dexes
|
|
291
293
|
|
|
292
|
-
HIP-3 builder perps (e.g. **XYZ**
|
|
294
|
+
HIP-3 builder perps (e.g. **XYZ** / `xyz:AAPL`) are **trading**, not a savings APR. `ctm_hyperliquid_fetch_markets` is **native crypto only**. Use `ctm_hyperliquid_fetch_stock_markets` for equities. `search_markets` still searches **both**. Idle USDC vault yield: `ctm_hyperliquid_fetch_vault_apys` (not HIP-3).
|
|
293
295
|
|
|
294
296
|
- Coin names use `{dex}:{symbol}` — e.g. **`xyz:AAPL`**, not `xyzAAPL` or bare `AAPL` on the wire.
|
|
295
297
|
- **`search_markets`** is the right tool when the user says a ticker or company name (`AAPL`, `Apple`, `Tesla`). It searches **all dexes** using Hyperliquid annotations (display names + keywords).
|
|
@@ -14,8 +14,11 @@ Use `get_defi_protocol_supported_chains` / `get_defi_protocol_supported_tokens`
|
|
|
14
14
|
|
|
15
15
|
## Tools
|
|
16
16
|
|
|
17
|
+
Do **not** web-search Lido staking APRs. Use `ctm_lido_fetch_steth_apr` (official Lido API, recent stETH APR).
|
|
18
|
+
|
|
17
19
|
| Intent | Tool |
|
|
18
20
|
|--------|------|
|
|
21
|
+
| stETH staking APR | `ctm_lido_fetch_steth_apr` |
|
|
19
22
|
| Stake ETH | `ctm_lido_build_submit_multisign` |
|
|
20
23
|
| Queue stETH withdrawal | `ctm_lido_build_request_withdrawals_multisign` |
|
|
21
24
|
| Claim withdrawal | `ctm_lido_build_claim_withdrawal_multisign` |
|
|
@@ -1,10 +1,42 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: maple-syrup
|
|
3
|
-
description: Maple Syrup pool deposit and redeem
|
|
3
|
+
description: Maple Syrup pool deposit and redeem — live APY from fetch tools, then multisign.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Maple Syrup (MCP)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Syrup pools (syrupUSDC, syrupUSDT, syrupUSDG) on **Ethereum (1)** and Sepolia (11155111). Yield is **APY** from Maple GraphQL (`weeklyApy` / `monthlyApy`, formula `raw / 1e28`).
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
## Before any action
|
|
11
|
+
|
|
12
|
+
1. `load_defi_protocol({ protocolId: "maple-syrup" })`
|
|
13
|
+
2. `get_defi_protocol_skill({ protocolId: "maple-syrup" })`
|
|
14
|
+
3. `get_defi_protocol_supported_chains` — intersect with `get_chain_registry` (`rpcGateway` required for writes)
|
|
15
|
+
4. `ctm_maple_fetch_markets` — live APY + `pool` / `syrupRouter` / `asset` (not web search)
|
|
16
|
+
|
|
17
|
+
## Tool selection
|
|
18
|
+
|
|
19
|
+
Do **not** web-search Maple APYs or pool addresses. Load the protocol and use the fetch tools below.
|
|
20
|
+
|
|
21
|
+
| User intent | MCP tool |
|
|
22
|
+
|-------------|----------|
|
|
23
|
+
| List Syrup pools / lending APYs | `ctm_maple_fetch_markets` |
|
|
24
|
+
| One pool (by `pool` or `underlying`) | `ctm_maple_fetch_market` |
|
|
25
|
+
| Deposit underlying | `ctm_maple_build_deposit_multisign` |
|
|
26
|
+
| Request redeem | `ctm_maple_build_request_redeem_multisign` |
|
|
27
|
+
|
|
28
|
+
## Compare lending APYs (read-only)
|
|
29
|
+
|
|
30
|
+
1. `load_defi_protocol({ protocolId: "maple-syrup" })` then `get_defi_protocol_skill`.
|
|
31
|
+
2. `ctm_maple_fetch_markets` with `chainId` 1. Optional `underlying` to filter (e.g. USDC).
|
|
32
|
+
3. Each row is one live Syrup pool: `weeklyApyPercent`, `monthlyApyPercent`, `totalAssets`.
|
|
33
|
+
4. Unused zero-TVL listings are omitted. Maple reports **APY**.
|
|
34
|
+
5. Copy `pool`, `syrupRouter`, and `asset` for a later deposit/redeem.
|
|
35
|
+
|
|
36
|
+
## Write inputs
|
|
37
|
+
|
|
38
|
+
Deposit: `keyGenId`, `chainId`, `purposeText`, `syrupRouter`, `pool`, `asset`, `amountHuman` from the fetch row.
|
|
39
|
+
|
|
40
|
+
Redeem: `keyGenId`, `chainId`, `purposeText`, `pool`, `sharesHuman`, `receiver`.
|
|
41
|
+
|
|
42
|
+
Each build tool returns `{ requestId }` on success.
|
|
@@ -23,7 +23,7 @@ Morpho integration: **listed earn vaults** (V1 + V2, unified), **Blue** variable
|
|
|
23
23
|
`underlying` accepts **symbol** (e.g. `USDC`, `WETH`) or **ERC-20 address**.
|
|
24
24
|
`query` is **case-insensitive** on vault name, symbol, address, and underlying symbol.
|
|
25
25
|
|
|
26
|
-
Use returned `vaultAddress` and `underlyingAddress` for deposit multisign. Each row includes `totalDepositsUsd`, `liquidityUsd`, `netApy` / `netApy7d` / `netApy30d` / `netApy90d`, `performanceFee`, and `exposure[]` (allocated markets/strategies with % of TVL).
|
|
26
|
+
Use returned `vaultAddress` and `underlyingAddress` for deposit multisign. Each row includes `totalDepositsUsd`, `liquidityUsd`, `netApy` / `netApy7d` / `netApy30d` / `netApy90d`, `performanceFee`, `rewards[]` (extra incentive APR from Morpho `allRewards`), and `exposure[]` (allocated markets/strategies with % of TVL). Blue rows also include `netSupplyApyLabel` and `rewards[]`. Incentive APR is extra and variable.
|
|
27
27
|
|
|
28
28
|
## Robinhood Earn (USDG yield on chain 4663)
|
|
29
29
|
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pendle
|
|
3
|
+
description: Pendle V2 — live PT/YT/SY markets, Convert mint/redeem/swap/LP, and on-chain SY/YT/LP reward redeem. Official Core API only.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Pendle V2 (MCP)
|
|
7
|
+
|
|
8
|
+
Pendle is **any `chainId` returned by `GET /v1/chains` that the node has in `get_chain_registry`**. Do not hardcode a tiny chain allowlist. Do **not** hardcode router or market addresses — Convert `routes[0].tx.to` is the spender.
|
|
9
|
+
|
|
10
|
+
Official base: `https://api-v2.pendle.finance/core`. Do **not** use the unofficial BFF (`api-v2.pendle.finance/bff`), deprecated Convert GET v2, or `/v1/markets/points-market`.
|
|
11
|
+
|
|
12
|
+
**Trade Points is not a separate venue.** Point campaigns live on `points[]` from `ctm_pendle_fetch_markets`. Trading them is a YT (or PT) swap on the same Convert path.
|
|
13
|
+
|
|
14
|
+
## Catalog budget
|
|
15
|
+
|
|
16
|
+
Pendle bills Computing Units per request. Listings are cheap (1 CU/page). Convert is expensive (5+ CU) — **never use Convert as a price ticker**.
|
|
17
|
+
|
|
18
|
+
- `ctm_pendle_fetch_markets` — scan Core pages (oldest-first), **drop matured YT**, hard cap 100 live markets, TVL-ranked. Optional `query` / `pointsOnly` shrink that set. Search by address to reach an expired market for PT redeem / remove LP.
|
|
19
|
+
- `ctm_pendle_search_assets` — required for long-tail. Address / `chainId-0x` uses `ids=` (prefers live). Ticker scans cached chain pages and prefers active markets.
|
|
20
|
+
- `ctm_pendle_fetch_prices` — only for ids in the current list or search hits.
|
|
21
|
+
- `ctm_pendle_fetch_positions` — this wallet’s LP (including matured), ~4 CU. Activate `pendle:lp`.
|
|
22
|
+
|
|
23
|
+
## Before writes
|
|
24
|
+
|
|
25
|
+
1. `load_defi_protocol({ protocolId: "pendle" })` — activates **market-data only**
|
|
26
|
+
2. `get_defi_protocol_supported_chains` — must include the operator's `chainId` with a node `rpcGateway`
|
|
27
|
+
3. Writes: `activate_tool_group` with `pendle:mint`, `pendle:swap`, `pendle:lp`, or `pendle:rewards`
|
|
28
|
+
|
|
29
|
+
`pendle:trading` expands to swaps + lp + mint-redeem + rewards (not market-data).
|
|
30
|
+
|
|
31
|
+
## Confirm before creating a sign request
|
|
32
|
+
|
|
33
|
+
After the quote (include outputs, `priceImpact`, implied/effective APY), **stop and ask** before any `ctm_pendle_build_*_multisign`:
|
|
34
|
+
|
|
35
|
+
1. `get_multi_sign_gas_options({ chainId })` — confirm `useCustomGas` **false** (live RPC, default) vs **true** (Custom Gas Config).
|
|
36
|
+
2. Confirm the **30-minute** multiSignRequest deadline (members must agree, Get Sig, and broadcast before it expires). Convert v3 does **not** take an on-chain router deadline — omit `expiryDate` for 30 minutes.
|
|
37
|
+
|
|
38
|
+
Always call convert at build time (or pass a fresh `convertSnapshot` from the quote just shown). Do not create the request until they confirm both.
|
|
39
|
+
|
|
40
|
+
## Tool packs
|
|
41
|
+
|
|
42
|
+
| Pack | Tools | Sign request? |
|
|
43
|
+
|------|-------|----------------|
|
|
44
|
+
| market-data | `ctm_pendle_fetch_markets`, `ctm_pendle_fetch_prices`, `ctm_pendle_search_assets` | No |
|
|
45
|
+
| mint-redeem | quote + build mint/redeem PT+YT and SY | Quotes no; builds yes |
|
|
46
|
+
| swaps | `ctm_pendle_quote_swap` + `ctm_pendle_build_swap_multisign` (also how you trade points) | Quote no; build yes |
|
|
47
|
+
| lp | `ctm_pendle_fetch_positions` (your LP, including matured); quote + add/remove LP | Fetch no; quotes no; builds yes |
|
|
48
|
+
| rewards | `ctm_pendle_build_redeem_rewards_multisign` (on-chain SY/YT/LP). `ctm_pendle_fetch_merkle_rewards` is list-only | Redeem yes; airdrop list no |
|
|
49
|
+
|
|
50
|
+
## Native token
|
|
51
|
+
|
|
52
|
+
Pendle Convert uses `0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee`. Also accept `0x0` / `eth`. Slippage on tools is **0–100 exclusive percent**; Convert maps that to 0–1.
|
|
53
|
+
|
|
54
|
+
## Rewards
|
|
55
|
+
|
|
56
|
+
- **On-chain (sign this):** `ctm_pendle_build_redeem_rewards_multisign` collects interest and incentives from SY, YT, and LP (usually PENDLE). Same as the Multi-Sign Rewards tab. Pass `sys` / `yts` / `markets` from a **live** market.
|
|
57
|
+
- **Airdrops (do not claim here):** `ctm_pendle_fetch_merkle_rewards` only lists rows. Core has no proofs. Tell the user to claim those on [app.pendle.finance](https://app.pendle.finance). Do not invent a distributor or claim tx.
|
|
58
|
+
- Matured markets: mint / YT swap / add LP fail. Redeem PT (no YT) and remove LP still work. `ctm_pendle_fetch_positions` lists leftover LP on matured markets — do not rely on the live catalog.
|
|
59
|
+
- Holdings: `ctm_pendle_fetch_positions` is the wallet LP list (Core dashboard, ~4 CU). It is not the node token list. Copy `market` + `lpAmountHuman` into remove-LP quote. Do not use the snapshot’s claimable amounts as a redeem quote.
|
|
60
|
+
|
|
61
|
+
## Out of scope
|
|
62
|
+
|
|
63
|
+
sPENDLE / vePENDLE staking and governance, Boros.
|
|
@@ -7,4 +7,6 @@ description: Sky Lockstake and sUSDS deposit/redeem on Ethereum mainnet.
|
|
|
7
7
|
|
|
8
8
|
Mainnet only. Tools for Lockstake stake/draw/wipe/close/reward and sUSDS deposit/redeem.
|
|
9
9
|
|
|
10
|
+
Do **not** web-search Sky Savings Rate. Use `ctm_sky_fetch_susds_rate` (on-chain `sUSDS.ssr()`). Then `ctm_sky_build_susds_deposit_multisign` to deposit USDS.
|
|
11
|
+
|
|
10
12
|
Use `get_defi_protocol_supported_chains` and base registry for USDS/SKY addresses. All `ctm_sky_build_*_multisign` tools return `{ requestId }` on success (shared gas/submit section appended by the server).
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: yield-compare
|
|
3
|
+
description: Route ETH and major stables to per-protocol MCP fetch tools. No mega-aggregator. Do not web-search rates.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Yield compare (routing skill)
|
|
7
|
+
|
|
8
|
+
There is **no** `ctm_defi_fetch_all_yields`. Call the **per-protocol fetch tools** below, then compare APR vs APY, lockups, and incentive extras yourself.
|
|
9
|
+
|
|
10
|
+
Do **not** web-search rates. Do **not** use DefiLlama. HIP-3 / Arcus stock trading is **not** idle-stable yield. Perp funding is optional carry — include it only when the operator asked about perps, funding, HL vaults, or GM pools.
|
|
11
|
+
|
|
12
|
+
## Plan Mode
|
|
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.
|
|
15
|
+
|
|
16
|
+
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_aerodrome_fetch_lp_yields` on Base `8453`, `ctm_pendle_fetch_markets` / `ctm_pendle_search_assets`, …) then post `mpc-task-result`. Ticker filters (`underlying: "USDT"`) are valid on Aave/Maple/Morpho fetches — do not invent ERC-20 addresses. 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.
|
|
17
|
+
|
|
18
|
+
## Units and caveats
|
|
19
|
+
|
|
20
|
+
- **APR vs APY** — say which. Aave/Morpho/Maple/Sky/Ethena are typically APY; Compound base is APR; GMX/Hyperliquid vaults publish APR.
|
|
21
|
+
- **Incentives** are extra and variable (Compound `supplyRewardAprPercent`, Morpho `rewards[]`).
|
|
22
|
+
- **Lockups** — Ethena sUSDe cooldown, Maple redeem, Lido withdrawal queue, Curve/Aerodrome gauge stake for advertised gauge APR.
|
|
23
|
+
|
|
24
|
+
## Perp funding (carry — not idle)
|
|
25
|
+
|
|
26
|
+
Include **only if the operator asked** about perps, funding carry, Hyperliquid vaults, or GMX GM. Not required for idle USDC/USDT lending. Label `perp_funding`. Requires an open perp; the sign can flip.
|
|
27
|
+
|
|
28
|
+
- **Hyperliquid:** `ctm_hyperliquid_fetch_market_snapshot` — official hourly `funding`. HIP-3 funding only if they asked about stocks. Vaults: `ctm_hyperliquid_fetch_vault_apys`.
|
|
29
|
+
- **GMX:** `ctm_gmx_fetch_markets` then `ctm_gmx_fetch_market_prices` for funding; `ctm_gmx_fetch_gm_apy` for GM pools.
|
|
30
|
+
- Do **not** invent Arcus funding.
|
|
31
|
+
|
|
32
|
+
## Asset → tools
|
|
33
|
+
|
|
34
|
+
Call `get_defi_protocol_skill({ protocolId: "yield-compare" })` for this map, then `load_defi_protocol` for each protocol you actually fetch. Ethereum unless noted.
|
|
35
|
+
|
|
36
|
+
### ETH / WETH
|
|
37
|
+
|
|
38
|
+
1. `ctm_lido_fetch_steth_apr` — stETH staking APR
|
|
39
|
+
2. `ctm_aave_v4_fetch_markets` / `ctm_compound_v3_fetch_markets` / `ctm_euler_v2_fetch_lend_vaults` / `ctm_morpho_fetch_earn_vaults` (WETH)
|
|
40
|
+
3. `ctm_gmx_fetch_gm_apy` — GM ETH-sided (Arbitrum) **only if they asked about GMX / GM / LP**
|
|
41
|
+
4. `ctm_curve_dao_fetch_lp_yields` — ETH/stETH-style pools in the ~100 catalog
|
|
42
|
+
5. `ctm_aerodrome_fetch_lp_yields` — WETH pairs on **Base**
|
|
43
|
+
6. `ctm_pendle_fetch_markets` / `ctm_pendle_search_assets` — optional PT / YT / LP implied APY (research-only; no build)
|
|
44
|
+
7. Perp funding / HL vaults — **only if they asked** (see Perp funding)
|
|
45
|
+
|
|
46
|
+
### USDC / USDT
|
|
47
|
+
|
|
48
|
+
1. Aave / Compound / Euler lend / Morpho earn / Maple (`ctm_maple_fetch_markets`)
|
|
49
|
+
2. `ctm_aerodrome_fetch_lp_yields` (Base) and `ctm_curve_dao_fetch_lp_yields` if they want DEX LP
|
|
50
|
+
3. `ctm_pendle_fetch_markets` — optional PT / YT / LP implied APY if they asked about Pendle (research-only)
|
|
51
|
+
4. `ctm_gmx_fetch_gm_apy` / `ctm_hyperliquid_fetch_vault_apys` / perp funding — **only if they asked** about GMX, HL vaults, or funding
|
|
52
|
+
|
|
53
|
+
### USDS
|
|
54
|
+
|
|
55
|
+
1. `ctm_sky_fetch_susds_rate` first
|
|
56
|
+
2. Then lending markets that list USDS (Aave / Morpho / Euler)
|
|
57
|
+
|
|
58
|
+
### USDe
|
|
59
|
+
|
|
60
|
+
1. `ctm_ethena_fetch_susde_apy` first (cooldown on unstake)
|
|
61
|
+
2. Then Morpho/Aave if listed
|
|
62
|
+
3. Optional `ctm_pendle_search_assets` for USDe PT/YT/LP (research-only)
|
|
63
|
+
|
|
64
|
+
### USDG (Robinhood 4663)
|
|
65
|
+
|
|
66
|
+
1. `ctm_morpho_fetch_earn_vaults` with `query: "robinhood earn"` — **not** Arcus deposit (trading collateral, no yield)
|
|
67
|
+
|
|
68
|
+
### DAI / crvUSD
|
|
69
|
+
|
|
70
|
+
Aave / Morpho / Euler / `ctm_curve_dao_fetch_lp_yields`
|
|
71
|
+
|
|
72
|
+
## DEX / stocks
|
|
73
|
+
|
|
74
|
+
- Main-pair LP only: Aerodrome `fetch_lp_yields`, Curve `fetch_lp_yields` (~100 each). Optional Pendle LP implied APY via `ctm_pendle_fetch_markets` (research-only).
|
|
75
|
+
- Stock LP: `ctm_aerodrome_fetch_stock_lp_yields` (B20) **only if the user asked about stocks**.
|
|
76
|
+
- Hyperliquid HIP-3: `ctm_hyperliquid_fetch_stock_markets` is **trading**, not idle savings. Include HIP-3 **funding** only if they asked about stocks.
|
|
77
|
+
|
|
78
|
+
## Euler earn vs isolated lend
|
|
79
|
+
|
|
80
|
+
- Isolated lend: `ctm_euler_v2_fetch_lend_vaults`
|
|
81
|
+
- Curated earn vaults: `ctm_euler_v2_fetch_earn_vaults`
|
package/dist/core/index.cjs
CHANGED
|
@@ -306,7 +306,8 @@ var DEFI_PROTOCOLS_WITH_30MIN_EXPIRY = /* @__PURE__ */ new Set([
|
|
|
306
306
|
"hyperliquid",
|
|
307
307
|
"arcus",
|
|
308
308
|
"curve-dao",
|
|
309
|
-
"aerodrome"
|
|
309
|
+
"aerodrome",
|
|
310
|
+
"pendle"
|
|
310
311
|
]);
|
|
311
312
|
function defiMultisignExpiryUnixSeconds(protocolId, explicitExpiryDate) {
|
|
312
313
|
if (typeof explicitExpiryDate === "number" && Number.isFinite(explicitExpiryDate) && explicitExpiryDate > 0) {
|
package/dist/core/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/core/purpose.ts","../../src/core/envelope.ts","../../src/core/registry.ts","../../src/core/defiProxy.ts","../../src/core/eip712Multisign.ts","../../src/core/payloadSignEd25519Multisign.ts","../../src/core/expiry.ts"],"names":["getClientIdFromKeyGenResult","r","stringToHex","hashTypedData"],"mappings":"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","file":"index.cjs","sourcesContent":["/** Merge user purpose text with an optional batch / protocol suffix. */\nexport function mergePurposeText(purposeText: string | undefined, purposeSuffix?: string): string {\n const t = (purposeText ?? '').trim()\n const suffix = (purposeSuffix ?? '').trim()\n if (!suffix) return t\n return t ? `${t}\\n\\n${suffix}` : suffix\n}\n","import type { ChainCategory, MultisignBuildResult, KeyGenSubset } from './types.js'\nimport { getClientIdFromKeyGenResult } from '@continuumdao/continuum-node-sdk'\nimport { mergePurposeText } from './purpose.js'\n\nexport interface MultisignLeg {\n msgHash: string\n msgRaw: string\n destinationAddress: string\n signatureText: string\n audit: Record<string, unknown>\n feeSnapshot: Record<string, unknown>\n proposalTxParams?: Record<string, unknown>\n /** Payable value wei string for first leg only when relevant */\n valueWei?: bigint\n}\n\nexport interface ChainCategoryBuildInput {\n keyGen: KeyGenSubset\n purposeText: string\n purposeSuffix?: string\n destinationChainID: string\n legs: MultisignLeg[]\n extraJSON?: Record<string, unknown>\n /** Top-level destination address (first leg destination if omitted) */\n destinationAddress?: string\n /** Unix seconds (UTC) for mpc-auth multiSignRequest expiryDate. */\n expiryDate?: number\n}\n\nexport interface ChainCategoryModule {\n category: ChainCategory\n finalizeMultisign(input: ChainCategoryBuildInput): MultisignBuildResult\n}\n\n/**\n * Assemble mpc-auth `bodyForSign` from category-built legs.\n * Supports single-tx and batch (messageHashes / messageRawBatch / proposalTxParams).\n */\nexport function finalizeMultisign(input: ChainCategoryBuildInput): MultisignBuildResult {\n const { keyGen, destinationChainID, legs } = input\n if (legs.length === 0) {\n throw new Error('finalizeMultisign requires at least one leg')\n }\n\n const ph = (keyGen.pubkeyhex ?? '').trim()\n if (!ph) throw new Error('keyGen pubKey (pubkeyhex) is required')\n\n const keyList = keyGen.keylist ?? []\n const clientId = getClientIdFromKeyGenResult(keyGen)\n const first = legs[0]!\n\n const messageHashes = legs.map((l) => l.msgHash)\n const messageRawBatch = legs.map((l) => l.msgRaw)\n const batchMeta = legs.map((l) => ({\n destinationAddress: l.destinationAddress,\n signatureText: l.signatureText,\n ...l.audit,\n }))\n\n const proposalTxParams = legs\n .map((l) => l.proposalTxParams)\n .filter((p): p is Record<string, unknown> => p != null && typeof p === 'object')\n\n const extraPayload: Record<string, unknown> = {\n batchMeta,\n ...(input.extraJSON ?? {}),\n }\n const extraJSON = JSON.stringify(extraPayload, (_, v) => (typeof v === 'bigint' ? v.toString() : v))\n\n const bodyForSign: Record<string, unknown> = {\n keyList,\n pubKey: ph,\n msgHash: messageHashes[0],\n msgRaw: first.msgRaw,\n destinationChainID,\n destinationAddress: input.destinationAddress ?? first.destinationAddress,\n extraJSON,\n signatureText: first.signatureText,\n purpose: mergePurposeText(input.purposeText, input.purposeSuffix),\n ...first.feeSnapshot,\n }\n\n if (legs.length > 1) {\n bodyForSign.messageHashes = messageHashes\n bodyForSign.messageRawBatch = messageRawBatch\n }\n\n if (proposalTxParams.length > 0) {\n bodyForSign.proposalTxParams = proposalTxParams\n }\n\n const valueWei = first.valueWei\n if (valueWei != null && valueWei > 0n) {\n bodyForSign.value = valueWei.toString()\n }\n\n if (clientId) bodyForSign.clientId = clientId\n\n if (input.expiryDate != null && input.expiryDate > 0) {\n bodyForSign.expiryDate = Math.floor(input.expiryDate)\n }\n\n return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) }\n}\n\nexport const coreChainCategoryModule: ChainCategoryModule = {\n category: 'evm',\n finalizeMultisign,\n}\n","import type { ProtocolModule } from './types.js'\n\nconst modules: ProtocolModule[] = []\n\nexport function registerProtocolModule(mod: ProtocolModule): void {\n const existing = modules.findIndex((m) => m.id === mod.id)\n if (existing >= 0) {\n modules[existing] = mod\n } else {\n modules.push(mod)\n }\n}\n\nexport function getProtocolModules(): readonly ProtocolModule[] {\n return modules\n}\n\nexport function getProtocolModule(id: string): ProtocolModule | undefined {\n return modules.find((m) => m.id === id)\n}\n\nexport function getActionsByChainCategory(category: string): ProtocolModule['actions'] {\n return modules.filter((m) => m.chainCategory === category).flatMap((m) => m.actions)\n}\n","/**\n * Optional browser → Next.js API proxy paths for DeFi upstream calls.\n * Set once from continuumdao-node-app client bootstrap.\n */\n\nlet aaveGraphqlProxyUrl: string | undefined\nlet eulerGraphqlProxyUrl: string | undefined\nlet mapleGraphqlProxyUrl: string | undefined\nlet morphoGraphqlProxyUrl: string | undefined\nlet coingeckoProxyUrl: string | undefined\n\nexport function setAaveGraphqlProxyUrl(url: string | undefined): void {\n aaveGraphqlProxyUrl = url?.trim() || undefined\n}\n\nexport function getAaveGraphqlProxyUrl(): string | undefined {\n return aaveGraphqlProxyUrl\n}\n\nexport function setEulerGraphqlProxyUrl(url: string | undefined): void {\n eulerGraphqlProxyUrl = url?.trim() || undefined\n}\n\nexport function getEulerGraphqlProxyUrl(): string | undefined {\n return eulerGraphqlProxyUrl\n}\n\n/** Browser → Next.js base path for Euler V3 REST (`/v3/evk/vaults`, …). */\nlet eulerV3ApiProxyBase: string | undefined\n\nexport function setEulerV3ApiProxyBase(url: string | undefined): void {\n eulerV3ApiProxyBase = url?.trim().replace(/\\/$/, '') || undefined\n}\n\nexport function getEulerV3ApiProxyBase(): string | undefined {\n return eulerV3ApiProxyBase\n}\n\nexport function setMapleGraphqlProxyUrl(url: string | undefined): void {\n mapleGraphqlProxyUrl = url?.trim() || undefined\n}\n\nexport function getMapleGraphqlProxyUrl(): string | undefined {\n return mapleGraphqlProxyUrl\n}\n\nexport function setMorphoGraphqlProxyUrl(url: string | undefined): void {\n morphoGraphqlProxyUrl = url?.trim() || undefined\n}\n\nexport function getMorphoGraphqlProxyUrl(): string | undefined {\n return morphoGraphqlProxyUrl\n}\n\n/** Browser → Next.js base path for Morpho Midnight REST (replaces api.morpho.org/v0/midnight). */\nlet morphoMidnightRestProxyUrl: string | undefined\n\nexport function setMorphoMidnightRestProxyUrl(url: string | undefined): void {\n morphoMidnightRestProxyUrl = url?.trim() || undefined\n}\n\nexport function getMorphoMidnightRestProxyUrl(): string | undefined {\n return morphoMidnightRestProxyUrl\n}\n\nexport function setCoingeckoProxyUrl(url: string | undefined): void {\n coingeckoProxyUrl = url?.trim() || undefined\n}\n\nexport function getCoingeckoProxyUrl(): string | undefined {\n return coingeckoProxyUrl\n}\n\nexport async function postJsonViaOptionalProxy<T>(args: {\n directUrl: string\n body: unknown\n proxyUrl?: string\n proxyEnvelope?: unknown\n}): Promise<T> {\n const proxy = args.proxyUrl?.trim()\n if (proxy) {\n const r = await fetch(proxy, {\n method: 'POST',\n headers: {'content-type': 'application/json'},\n body: JSON.stringify(args.proxyEnvelope ?? args.body),\n })\n if (!r.ok) {\n const t = await r.text().catch(() => '')\n throw new Error(t ? `Proxy HTTP ${r.status}: ${t.slice(0, 200)}` : `Proxy HTTP ${r.status}`)\n }\n return (await r.json()) as T\n }\n const r = await fetch(args.directUrl, {\n method: 'POST',\n headers: {'content-type': 'application/json'},\n body: JSON.stringify(args.body),\n })\n if (!r.ok) {\n const t = await r.text().catch(() => '')\n throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`)\n }\n return (await r.json()) as T\n}\n\nexport async function getJsonViaOptionalProxy<T>(args: {\n directUrl: string\n /** When set, GET this URL instead of directUrl (same path semantics as caller built). */\n proxyUrl?: string\n}): Promise<T> {\n const url = args.proxyUrl?.trim() || args.directUrl\n const r = await fetch(url, { method: 'GET', headers: { accept: 'application/json' } })\n if (!r.ok) {\n const t = await r.text().catch(() => '')\n throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`)\n }\n return (await r.json()) as T\n}\n","import { hashTypedData, stringToHex, type TypedDataDomain } from 'viem'\nimport type { KeyGenSubset, MultisignBuildResult } from './types.js'\nimport { finalizeMultisign } from './envelope.js'\n\nexport const EIP712_SIGN_REQUEST_KIND = 'eip712' as const\n\nexport type Eip712TypedDataField = { name: string; type: string }\n\nexport type Eip712TypedDataPayload = {\n domain: TypedDataDomain\n types: Record<string, readonly Eip712TypedDataField[] | Eip712TypedDataField[]>\n primaryType: string\n message: Record<string, unknown>\n}\n\nexport type Eip712MultisignDelivery = Record<string, unknown> & { kind: string }\n\nexport type BuildEip712MultisignLeg = {\n typedData: Eip712TypedDataPayload\n delivery: Eip712MultisignDelivery\n audit?: Record<string, unknown>\n}\n\nexport type BuildEip712MultisignArgs = {\n keyGen: KeyGenSubset\n purposeText: string\n purposeSuffix?: string\n /** Chain id stored on the sign request (protocol context; may differ from EIP-712 domain chainId). */\n destinationChainID: string\n destinationAddress: string\n legs: readonly BuildEip712MultisignLeg[]\n expiryDate?: number\n}\n\nfunction msgHashNo0x(digest: `0x${string}`): string {\n return digest.startsWith('0x') ? digest.slice(2) : digest\n}\n\nfunction eip712SignatureText(domain: TypedDataDomain, primaryType: string): string {\n return JSON.stringify({\n kind: 'EIP-712',\n ...(typeof domain.name === 'string' ? { name: domain.name } : {}),\n primaryType,\n })\n}\n\nfunction jsonStringifyForAudit(value: unknown): string {\n return JSON.stringify(value, (_, v) => (typeof v === 'bigint' ? v.toString() : v))\n}\n\nfunction eip712LegEnvelope(\n typedData: Eip712TypedDataPayload,\n delivery: Eip712MultisignDelivery,\n digest: `0x${string}`,\n): Record<string, unknown> {\n return {\n version: 1,\n digest,\n domain: typedData.domain,\n types: typedData.types,\n primaryType: typedData.primaryType,\n message: typedData.message,\n delivery,\n }\n}\n\nfunction eip712MsgRawHex(envelope: Record<string, unknown>): string {\n return stringToHex(jsonStringifyForAudit(envelope))\n}\n\n/**\n * Build an mpc-auth multiSignRequest body for one or more EIP-712 digests (no EVM tx broadcast).\n * `extraJSON.eip712` is always an array. N=1 uses `msgHash`/`msgRaw`; N>=2 uses `messageHashes`/`messageRawBatch`.\n */\nexport function buildEip712Multisign(args: BuildEip712MultisignArgs): MultisignBuildResult {\n if (args.legs.length < 1) {\n throw new Error('buildEip712Multisign requires at least one leg')\n }\n\n const eip712: Record<string, unknown>[] = []\n const legs = args.legs.map((leg) => {\n const digest = hashTypedData({\n domain: leg.typedData.domain,\n types: leg.typedData.types,\n primaryType: leg.typedData.primaryType,\n message: leg.typedData.message,\n })\n const envelope = eip712LegEnvelope(leg.typedData, leg.delivery, digest)\n eip712.push(envelope)\n return {\n msgHash: msgHashNo0x(digest),\n msgRaw: eip712MsgRawHex(envelope),\n destinationAddress: args.destinationAddress,\n signatureText: eip712SignatureText(leg.typedData.domain, leg.typedData.primaryType),\n audit: {\n kind: 'EIP712',\n primaryType: leg.typedData.primaryType,\n deliveryKind: leg.delivery.kind,\n ...(leg.audit ?? {}),\n },\n feeSnapshot: {},\n }\n })\n\n return finalizeMultisign({\n keyGen: args.keyGen,\n purposeText: args.purposeText,\n purposeSuffix: args.purposeSuffix,\n destinationChainID: args.destinationChainID,\n destinationAddress: args.destinationAddress,\n extraJSON: {\n signRequestKind: EIP712_SIGN_REQUEST_KIND,\n eip712,\n },\n expiryDate: args.expiryDate,\n legs,\n })\n}\n","import { stringToHex } from 'viem'\nimport type { KeyGenSubset, MultisignBuildResult } from './types.js'\nimport { finalizeMultisign } from './envelope.js'\n\nexport const PAYLOAD_SIGN_ED25519_REQUEST_KIND = 'payload_sign_ed25519' as const\n\nexport type PayloadSignEd25519Delivery = Record<string, unknown> & { kind: string }\n\nexport type BuildPayloadSignEd25519MultisignBodyArgs = {\n keyGen: KeyGenSubset\n purposeText: string\n purposeSuffix?: string\n destinationChainID: string\n destinationAddress: string\n /** UTF-8 bytes to sign (Arcus canonical JSON). */\n messageUtf8: string\n /** secp256k1 pub key hex for billing when signing with paired ed25519 KeyGen. */\n billingKeyGenPubKey?: string\n delivery: PayloadSignEd25519Delivery\n audit?: Record<string, unknown>\n expiryDate?: number\n signatureText?: string\n}\n\nfunction msgHashNo0xFromBytes(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString('hex')\n}\n\nfunction payloadMsgRawHex(messageUtf8: string, delivery: PayloadSignEd25519Delivery): string {\n const envelope = {\n version: 1,\n messageUtf8,\n delivery,\n }\n return stringToHex(JSON.stringify(envelope))\n}\n\n/**\n * Build mpc-auth multiSignRequest for Ed25519 FROST signing over variable-length UTF-8 (Arcus Scheme 1).\n * `msgHash` is hex of the raw message bytes (not SHA-256); mpc-auth givre worker signs these bytes directly.\n */\nexport function buildPayloadSignEd25519MultisignBody(\n args: BuildPayloadSignEd25519MultisignBodyArgs,\n): MultisignBuildResult {\n const messageBytes = Buffer.from(args.messageUtf8, 'utf8')\n const msgHash = msgHashNo0xFromBytes(messageBytes)\n\n const extraJSON: Record<string, unknown> = {\n signRequestKind: PAYLOAD_SIGN_ED25519_REQUEST_KIND,\n payloadSignEd25519: {\n version: 1,\n messageHex: msgHash,\n messageLength: messageBytes.length,\n },\n delivery: args.delivery,\n }\n if (args.billingKeyGenPubKey?.trim()) {\n extraJSON.billingKeyGenPubKey = args.billingKeyGenPubKey.trim()\n }\n\n return finalizeMultisign({\n keyGen: args.keyGen,\n purposeText: args.purposeText,\n purposeSuffix: args.purposeSuffix,\n destinationChainID: args.destinationChainID,\n destinationAddress: args.destinationAddress,\n extraJSON,\n expiryDate: args.expiryDate,\n legs: [\n {\n msgHash,\n msgRaw: payloadMsgRawHex(args.messageUtf8, args.delivery),\n destinationAddress: args.destinationAddress,\n signatureText: args.signatureText ?? 'Arcus Ed25519 payload sign',\n audit: {\n kind: 'PAYLOAD_SIGN_ED25519',\n deliveryKind: args.delivery.kind,\n messageLength: messageBytes.length,\n ...(args.audit ?? {}),\n },\n feeSnapshot: {},\n },\n ],\n })\n}\n","/** Default MPC sign-request agreement window for fast-moving DeFi protocols (30 minutes). */\nexport const DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS = 30 * 60\n\n/** Protocol ids that default to 30-minute expiry when `expiryDate` is omitted on multisign MCP tools. */\nexport const DEFI_PROTOCOLS_WITH_30MIN_EXPIRY = new Set([\n 'uniswap-v4',\n 'gmx',\n 'hyperliquid',\n 'arcus',\n 'curve-dao',\n 'aerodrome',\n])\n\nexport function defiMultisignExpiryUnixSeconds(\n protocolId: string | undefined,\n explicitExpiryDate?: number | null,\n): number | undefined {\n if (typeof explicitExpiryDate === 'number' && Number.isFinite(explicitExpiryDate) && explicitExpiryDate > 0) {\n return Math.floor(explicitExpiryDate)\n }\n if (protocolId && DEFI_PROTOCOLS_WITH_30MIN_EXPIRY.has(protocolId)) {\n return Math.floor(Date.now() / 1000) + DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS\n }\n return undefined\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/core/purpose.ts","../../src/core/envelope.ts","../../src/core/registry.ts","../../src/core/defiProxy.ts","../../src/core/eip712Multisign.ts","../../src/core/payloadSignEd25519Multisign.ts","../../src/core/expiry.ts"],"names":["getClientIdFromKeyGenResult","r","stringToHex","hashTypedData"],"mappings":"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","file":"index.cjs","sourcesContent":["/** Merge user purpose text with an optional batch / protocol suffix. */\nexport function mergePurposeText(purposeText: string | undefined, purposeSuffix?: string): string {\n const t = (purposeText ?? '').trim()\n const suffix = (purposeSuffix ?? '').trim()\n if (!suffix) return t\n return t ? `${t}\\n\\n${suffix}` : suffix\n}\n","import type { ChainCategory, MultisignBuildResult, KeyGenSubset } from './types.js'\nimport { getClientIdFromKeyGenResult } from '@continuumdao/continuum-node-sdk'\nimport { mergePurposeText } from './purpose.js'\n\nexport interface MultisignLeg {\n msgHash: string\n msgRaw: string\n destinationAddress: string\n signatureText: string\n audit: Record<string, unknown>\n feeSnapshot: Record<string, unknown>\n proposalTxParams?: Record<string, unknown>\n /** Payable value wei string for first leg only when relevant */\n valueWei?: bigint\n}\n\nexport interface ChainCategoryBuildInput {\n keyGen: KeyGenSubset\n purposeText: string\n purposeSuffix?: string\n destinationChainID: string\n legs: MultisignLeg[]\n extraJSON?: Record<string, unknown>\n /** Top-level destination address (first leg destination if omitted) */\n destinationAddress?: string\n /** Unix seconds (UTC) for mpc-auth multiSignRequest expiryDate. */\n expiryDate?: number\n}\n\nexport interface ChainCategoryModule {\n category: ChainCategory\n finalizeMultisign(input: ChainCategoryBuildInput): MultisignBuildResult\n}\n\n/**\n * Assemble mpc-auth `bodyForSign` from category-built legs.\n * Supports single-tx and batch (messageHashes / messageRawBatch / proposalTxParams).\n */\nexport function finalizeMultisign(input: ChainCategoryBuildInput): MultisignBuildResult {\n const { keyGen, destinationChainID, legs } = input\n if (legs.length === 0) {\n throw new Error('finalizeMultisign requires at least one leg')\n }\n\n const ph = (keyGen.pubkeyhex ?? '').trim()\n if (!ph) throw new Error('keyGen pubKey (pubkeyhex) is required')\n\n const keyList = keyGen.keylist ?? []\n const clientId = getClientIdFromKeyGenResult(keyGen)\n const first = legs[0]!\n\n const messageHashes = legs.map((l) => l.msgHash)\n const messageRawBatch = legs.map((l) => l.msgRaw)\n const batchMeta = legs.map((l) => ({\n destinationAddress: l.destinationAddress,\n signatureText: l.signatureText,\n ...l.audit,\n }))\n\n const proposalTxParams = legs\n .map((l) => l.proposalTxParams)\n .filter((p): p is Record<string, unknown> => p != null && typeof p === 'object')\n\n const extraPayload: Record<string, unknown> = {\n batchMeta,\n ...(input.extraJSON ?? {}),\n }\n const extraJSON = JSON.stringify(extraPayload, (_, v) => (typeof v === 'bigint' ? v.toString() : v))\n\n const bodyForSign: Record<string, unknown> = {\n keyList,\n pubKey: ph,\n msgHash: messageHashes[0],\n msgRaw: first.msgRaw,\n destinationChainID,\n destinationAddress: input.destinationAddress ?? first.destinationAddress,\n extraJSON,\n signatureText: first.signatureText,\n purpose: mergePurposeText(input.purposeText, input.purposeSuffix),\n ...first.feeSnapshot,\n }\n\n if (legs.length > 1) {\n bodyForSign.messageHashes = messageHashes\n bodyForSign.messageRawBatch = messageRawBatch\n }\n\n if (proposalTxParams.length > 0) {\n bodyForSign.proposalTxParams = proposalTxParams\n }\n\n const valueWei = first.valueWei\n if (valueWei != null && valueWei > 0n) {\n bodyForSign.value = valueWei.toString()\n }\n\n if (clientId) bodyForSign.clientId = clientId\n\n if (input.expiryDate != null && input.expiryDate > 0) {\n bodyForSign.expiryDate = Math.floor(input.expiryDate)\n }\n\n return { bodyForSign, messageToSign: JSON.stringify(bodyForSign) }\n}\n\nexport const coreChainCategoryModule: ChainCategoryModule = {\n category: 'evm',\n finalizeMultisign,\n}\n","import type { ProtocolModule } from './types.js'\n\nconst modules: ProtocolModule[] = []\n\nexport function registerProtocolModule(mod: ProtocolModule): void {\n const existing = modules.findIndex((m) => m.id === mod.id)\n if (existing >= 0) {\n modules[existing] = mod\n } else {\n modules.push(mod)\n }\n}\n\nexport function getProtocolModules(): readonly ProtocolModule[] {\n return modules\n}\n\nexport function getProtocolModule(id: string): ProtocolModule | undefined {\n return modules.find((m) => m.id === id)\n}\n\nexport function getActionsByChainCategory(category: string): ProtocolModule['actions'] {\n return modules.filter((m) => m.chainCategory === category).flatMap((m) => m.actions)\n}\n","/**\n * Optional browser → Next.js API proxy paths for DeFi upstream calls.\n * Set once from continuumdao-node-app client bootstrap.\n */\n\nlet aaveGraphqlProxyUrl: string | undefined\nlet eulerGraphqlProxyUrl: string | undefined\nlet mapleGraphqlProxyUrl: string | undefined\nlet morphoGraphqlProxyUrl: string | undefined\nlet coingeckoProxyUrl: string | undefined\n\nexport function setAaveGraphqlProxyUrl(url: string | undefined): void {\n aaveGraphqlProxyUrl = url?.trim() || undefined\n}\n\nexport function getAaveGraphqlProxyUrl(): string | undefined {\n return aaveGraphqlProxyUrl\n}\n\nexport function setEulerGraphqlProxyUrl(url: string | undefined): void {\n eulerGraphqlProxyUrl = url?.trim() || undefined\n}\n\nexport function getEulerGraphqlProxyUrl(): string | undefined {\n return eulerGraphqlProxyUrl\n}\n\n/** Browser → Next.js base path for Euler V3 REST (`/v3/evk/vaults`, …). */\nlet eulerV3ApiProxyBase: string | undefined\n\nexport function setEulerV3ApiProxyBase(url: string | undefined): void {\n eulerV3ApiProxyBase = url?.trim().replace(/\\/$/, '') || undefined\n}\n\nexport function getEulerV3ApiProxyBase(): string | undefined {\n return eulerV3ApiProxyBase\n}\n\nexport function setMapleGraphqlProxyUrl(url: string | undefined): void {\n mapleGraphqlProxyUrl = url?.trim() || undefined\n}\n\nexport function getMapleGraphqlProxyUrl(): string | undefined {\n return mapleGraphqlProxyUrl\n}\n\nexport function setMorphoGraphqlProxyUrl(url: string | undefined): void {\n morphoGraphqlProxyUrl = url?.trim() || undefined\n}\n\nexport function getMorphoGraphqlProxyUrl(): string | undefined {\n return morphoGraphqlProxyUrl\n}\n\n/** Browser → Next.js base path for Morpho Midnight REST (replaces api.morpho.org/v0/midnight). */\nlet morphoMidnightRestProxyUrl: string | undefined\n\nexport function setMorphoMidnightRestProxyUrl(url: string | undefined): void {\n morphoMidnightRestProxyUrl = url?.trim() || undefined\n}\n\nexport function getMorphoMidnightRestProxyUrl(): string | undefined {\n return morphoMidnightRestProxyUrl\n}\n\nexport function setCoingeckoProxyUrl(url: string | undefined): void {\n coingeckoProxyUrl = url?.trim() || undefined\n}\n\nexport function getCoingeckoProxyUrl(): string | undefined {\n return coingeckoProxyUrl\n}\n\nexport async function postJsonViaOptionalProxy<T>(args: {\n directUrl: string\n body: unknown\n proxyUrl?: string\n proxyEnvelope?: unknown\n}): Promise<T> {\n const proxy = args.proxyUrl?.trim()\n if (proxy) {\n const r = await fetch(proxy, {\n method: 'POST',\n headers: {'content-type': 'application/json'},\n body: JSON.stringify(args.proxyEnvelope ?? args.body),\n })\n if (!r.ok) {\n const t = await r.text().catch(() => '')\n throw new Error(t ? `Proxy HTTP ${r.status}: ${t.slice(0, 200)}` : `Proxy HTTP ${r.status}`)\n }\n return (await r.json()) as T\n }\n const r = await fetch(args.directUrl, {\n method: 'POST',\n headers: {'content-type': 'application/json'},\n body: JSON.stringify(args.body),\n })\n if (!r.ok) {\n const t = await r.text().catch(() => '')\n throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`)\n }\n return (await r.json()) as T\n}\n\nexport async function getJsonViaOptionalProxy<T>(args: {\n directUrl: string\n /** When set, GET this URL instead of directUrl (same path semantics as caller built). */\n proxyUrl?: string\n}): Promise<T> {\n const url = args.proxyUrl?.trim() || args.directUrl\n const r = await fetch(url, { method: 'GET', headers: { accept: 'application/json' } })\n if (!r.ok) {\n const t = await r.text().catch(() => '')\n throw new Error(t ? `HTTP ${r.status}: ${t.slice(0, 200)}` : `HTTP ${r.status}`)\n }\n return (await r.json()) as T\n}\n","import { hashTypedData, stringToHex, type TypedDataDomain } from 'viem'\nimport type { KeyGenSubset, MultisignBuildResult } from './types.js'\nimport { finalizeMultisign } from './envelope.js'\n\nexport const EIP712_SIGN_REQUEST_KIND = 'eip712' as const\n\nexport type Eip712TypedDataField = { name: string; type: string }\n\nexport type Eip712TypedDataPayload = {\n domain: TypedDataDomain\n types: Record<string, readonly Eip712TypedDataField[] | Eip712TypedDataField[]>\n primaryType: string\n message: Record<string, unknown>\n}\n\nexport type Eip712MultisignDelivery = Record<string, unknown> & { kind: string }\n\nexport type BuildEip712MultisignLeg = {\n typedData: Eip712TypedDataPayload\n delivery: Eip712MultisignDelivery\n audit?: Record<string, unknown>\n}\n\nexport type BuildEip712MultisignArgs = {\n keyGen: KeyGenSubset\n purposeText: string\n purposeSuffix?: string\n /** Chain id stored on the sign request (protocol context; may differ from EIP-712 domain chainId). */\n destinationChainID: string\n destinationAddress: string\n legs: readonly BuildEip712MultisignLeg[]\n expiryDate?: number\n}\n\nfunction msgHashNo0x(digest: `0x${string}`): string {\n return digest.startsWith('0x') ? digest.slice(2) : digest\n}\n\nfunction eip712SignatureText(domain: TypedDataDomain, primaryType: string): string {\n return JSON.stringify({\n kind: 'EIP-712',\n ...(typeof domain.name === 'string' ? { name: domain.name } : {}),\n primaryType,\n })\n}\n\nfunction jsonStringifyForAudit(value: unknown): string {\n return JSON.stringify(value, (_, v) => (typeof v === 'bigint' ? v.toString() : v))\n}\n\nfunction eip712LegEnvelope(\n typedData: Eip712TypedDataPayload,\n delivery: Eip712MultisignDelivery,\n digest: `0x${string}`,\n): Record<string, unknown> {\n return {\n version: 1,\n digest,\n domain: typedData.domain,\n types: typedData.types,\n primaryType: typedData.primaryType,\n message: typedData.message,\n delivery,\n }\n}\n\nfunction eip712MsgRawHex(envelope: Record<string, unknown>): string {\n return stringToHex(jsonStringifyForAudit(envelope))\n}\n\n/**\n * Build an mpc-auth multiSignRequest body for one or more EIP-712 digests (no EVM tx broadcast).\n * `extraJSON.eip712` is always an array. N=1 uses `msgHash`/`msgRaw`; N>=2 uses `messageHashes`/`messageRawBatch`.\n */\nexport function buildEip712Multisign(args: BuildEip712MultisignArgs): MultisignBuildResult {\n if (args.legs.length < 1) {\n throw new Error('buildEip712Multisign requires at least one leg')\n }\n\n const eip712: Record<string, unknown>[] = []\n const legs = args.legs.map((leg) => {\n const digest = hashTypedData({\n domain: leg.typedData.domain,\n types: leg.typedData.types,\n primaryType: leg.typedData.primaryType,\n message: leg.typedData.message,\n })\n const envelope = eip712LegEnvelope(leg.typedData, leg.delivery, digest)\n eip712.push(envelope)\n return {\n msgHash: msgHashNo0x(digest),\n msgRaw: eip712MsgRawHex(envelope),\n destinationAddress: args.destinationAddress,\n signatureText: eip712SignatureText(leg.typedData.domain, leg.typedData.primaryType),\n audit: {\n kind: 'EIP712',\n primaryType: leg.typedData.primaryType,\n deliveryKind: leg.delivery.kind,\n ...(leg.audit ?? {}),\n },\n feeSnapshot: {},\n }\n })\n\n return finalizeMultisign({\n keyGen: args.keyGen,\n purposeText: args.purposeText,\n purposeSuffix: args.purposeSuffix,\n destinationChainID: args.destinationChainID,\n destinationAddress: args.destinationAddress,\n extraJSON: {\n signRequestKind: EIP712_SIGN_REQUEST_KIND,\n eip712,\n },\n expiryDate: args.expiryDate,\n legs,\n })\n}\n","import { stringToHex } from 'viem'\nimport type { KeyGenSubset, MultisignBuildResult } from './types.js'\nimport { finalizeMultisign } from './envelope.js'\n\nexport const PAYLOAD_SIGN_ED25519_REQUEST_KIND = 'payload_sign_ed25519' as const\n\nexport type PayloadSignEd25519Delivery = Record<string, unknown> & { kind: string }\n\nexport type BuildPayloadSignEd25519MultisignBodyArgs = {\n keyGen: KeyGenSubset\n purposeText: string\n purposeSuffix?: string\n destinationChainID: string\n destinationAddress: string\n /** UTF-8 bytes to sign (Arcus canonical JSON). */\n messageUtf8: string\n /** secp256k1 pub key hex for billing when signing with paired ed25519 KeyGen. */\n billingKeyGenPubKey?: string\n delivery: PayloadSignEd25519Delivery\n audit?: Record<string, unknown>\n expiryDate?: number\n signatureText?: string\n}\n\nfunction msgHashNo0xFromBytes(bytes: Uint8Array): string {\n return Buffer.from(bytes).toString('hex')\n}\n\nfunction payloadMsgRawHex(messageUtf8: string, delivery: PayloadSignEd25519Delivery): string {\n const envelope = {\n version: 1,\n messageUtf8,\n delivery,\n }\n return stringToHex(JSON.stringify(envelope))\n}\n\n/**\n * Build mpc-auth multiSignRequest for Ed25519 FROST signing over variable-length UTF-8 (Arcus Scheme 1).\n * `msgHash` is hex of the raw message bytes (not SHA-256); mpc-auth givre worker signs these bytes directly.\n */\nexport function buildPayloadSignEd25519MultisignBody(\n args: BuildPayloadSignEd25519MultisignBodyArgs,\n): MultisignBuildResult {\n const messageBytes = Buffer.from(args.messageUtf8, 'utf8')\n const msgHash = msgHashNo0xFromBytes(messageBytes)\n\n const extraJSON: Record<string, unknown> = {\n signRequestKind: PAYLOAD_SIGN_ED25519_REQUEST_KIND,\n payloadSignEd25519: {\n version: 1,\n messageHex: msgHash,\n messageLength: messageBytes.length,\n },\n delivery: args.delivery,\n }\n if (args.billingKeyGenPubKey?.trim()) {\n extraJSON.billingKeyGenPubKey = args.billingKeyGenPubKey.trim()\n }\n\n return finalizeMultisign({\n keyGen: args.keyGen,\n purposeText: args.purposeText,\n purposeSuffix: args.purposeSuffix,\n destinationChainID: args.destinationChainID,\n destinationAddress: args.destinationAddress,\n extraJSON,\n expiryDate: args.expiryDate,\n legs: [\n {\n msgHash,\n msgRaw: payloadMsgRawHex(args.messageUtf8, args.delivery),\n destinationAddress: args.destinationAddress,\n signatureText: args.signatureText ?? 'Arcus Ed25519 payload sign',\n audit: {\n kind: 'PAYLOAD_SIGN_ED25519',\n deliveryKind: args.delivery.kind,\n messageLength: messageBytes.length,\n ...(args.audit ?? {}),\n },\n feeSnapshot: {},\n },\n ],\n })\n}\n","/** Default MPC sign-request agreement window for fast-moving DeFi protocols (30 minutes). */\nexport const DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS = 30 * 60\n\n/** Protocol ids that default to 30-minute expiry when `expiryDate` is omitted on multisign MCP tools. */\nexport const DEFI_PROTOCOLS_WITH_30MIN_EXPIRY = new Set([\n 'uniswap-v4',\n 'gmx',\n 'hyperliquid',\n 'arcus',\n 'curve-dao',\n 'aerodrome',\n 'pendle',\n])\n\nexport function defiMultisignExpiryUnixSeconds(\n protocolId: string | undefined,\n explicitExpiryDate?: number | null,\n): number | undefined {\n if (typeof explicitExpiryDate === 'number' && Number.isFinite(explicitExpiryDate) && explicitExpiryDate > 0) {\n return Math.floor(explicitExpiryDate)\n }\n if (protocolId && DEFI_PROTOCOLS_WITH_30MIN_EXPIRY.has(protocolId)) {\n return Math.floor(Date.now() / 1000) + DEFAULT_DEFI_MULTISIGN_EXPIRY_SECONDS\n }\n return undefined\n}\n"]}
|
package/dist/core/index.js
CHANGED
|
@@ -305,7 +305,8 @@ var DEFI_PROTOCOLS_WITH_30MIN_EXPIRY = /* @__PURE__ */ new Set([
|
|
|
305
305
|
"hyperliquid",
|
|
306
306
|
"arcus",
|
|
307
307
|
"curve-dao",
|
|
308
|
-
"aerodrome"
|
|
308
|
+
"aerodrome",
|
|
309
|
+
"pendle"
|
|
309
310
|
]);
|
|
310
311
|
function defiMultisignExpiryUnixSeconds(protocolId, explicitExpiryDate) {
|
|
311
312
|
if (typeof explicitExpiryDate === "number" && Number.isFinite(explicitExpiryDate) && explicitExpiryDate > 0) {
|