@continuumdao/ctm-mpc-defi 0.2.51 → 0.2.52
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 +59 -27
- package/dist/agent/catalog.cjs.map +1 -1
- package/dist/agent/catalog.d.ts +87 -21
- package/dist/agent/catalog.js +59 -27
- package/dist/agent/catalog.js.map +1 -1
- package/dist/agent/skills/continuum-dao/SKILL.md +7 -6
- package/dist/protocols/evm/continuum-dao/index.cjs +37 -3
- package/dist/protocols/evm/continuum-dao/index.cjs.map +1 -1
- package/dist/protocols/evm/continuum-dao/index.d.ts +7 -0
- package/dist/protocols/evm/continuum-dao/index.js +37 -3
- package/dist/protocols/evm/continuum-dao/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -64,7 +64,7 @@ When a proposal has a `forumKey`, fetch that thread (`ctm_continuum_dao_forum_re
|
|
|
64
64
|
|
|
65
65
|
**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:
|
|
66
66
|
|
|
67
|
-
1. `
|
|
67
|
+
1. `get_forum_session` then `forum_me`. If `loggedIn`, reuse the ticket. Only if there is no session or `loggedIn` is false: `forum_sign_in_eligible` then `build_forum_sign_in_multisign`. Pass `address` on forum writes so the tool loads that node session before posting.
|
|
68
68
|
2. If it is only an idea: `forum_create_idea`. Stop (no propose).
|
|
69
69
|
3. If it is a proposal: `forum_create_topic` with the matching Governance `section` (proposal-threshold veCTM). Keep the returned `url`.
|
|
70
70
|
4. Compose actions with `ctm_continuum_dao_compose_proposal_action` (prefer ABI from `etherscan__get_contract_abi` with chainid 59144/59141, type-check values, preview table). Then offer `ctm_continuum_dao_simulate_proposal` — pass `account` for another EOA, or `keyGenId` / omit `account` for the preferred KeyGen. Write `foundry.files` and run `foundry__forge_script` on a Linea fork with no `--broadcast`. Do **not** treat isolated `eth_call` as success. Do **not** submit if `ok` is false or a forge script reverts.
|
|
@@ -73,12 +73,12 @@ When a proposal has a `forumKey`, fetch that thread (`ctm_continuum_dao_forum_re
|
|
|
73
73
|
|
|
74
74
|
`forumKey` must match `/topic/:tid` or `/t/:tid` on forum.continuumdao.org. Builders and `register_proposal` throw otherwise.
|
|
75
75
|
|
|
76
|
-
Forum KeyGen sign-in is EIP-712 multi-sign (no EVM tx). Always check
|
|
76
|
+
Forum KeyGen sign-in is EIP-712 multi-sign (no EVM tx). The ticket is stored on the node. Always check that session first:
|
|
77
77
|
|
|
78
|
-
1. `
|
|
79
|
-
2. `
|
|
80
|
-
3.
|
|
81
|
-
4. `ctm_continuum_dao_forum_sign_out({ ticket })`
|
|
78
|
+
1. `get_forum_session({ address })`. If `found` is true, `ctm_continuum_dao_forum_me({ ticket })`. If `loggedIn` is true, reuse that ticket. Do **not** compose a sign-in request.
|
|
79
|
+
2. If there is no session or `loggedIn` is false: `ctm_continuum_dao_forum_sign_in_eligible({ address })` — current `balanceOfNFT` on an owned or attached veCTM vs `veCtmThresholdPower` (200 veCTM). Governor `getVotes` and month-start `balanceOfNFTAt` do not count. Read `votingPower`, `threshold`, and `tokenId` from the result. If `eligible` is false, stop. Do **not** compose a multi-sign request.
|
|
80
|
+
3. `ctm_continuum_dao_build_forum_sign_in_multisign` uses the same gate and refuses ineligible addresses so other nodes never enter the sign loop. Ask the operator for a custom username (2–16 letters, numbers, `.` `_` `-`) and pass `username`. A KeyGen may choose a username the same way a wallet does. If they decline, call again with `useNodeKeyUsername: true` and `nodeKey`; the forum assigns the first 16 characters of the node key. Do not invent a username and do not skip the question. After Execute, the node stores the ticket. Call `get_forum_session` again, then `forum_reply` / `forum_react` / `forum_create_topic` / `forum_create_idea`.
|
|
81
|
+
4. `ctm_continuum_dao_forum_sign_out({ address, ticket })` deletes the node ticket (web chat and Telegram webhook turns share that row). `clear_forum_session({ address })` is the same delete. No multi-sign.
|
|
82
82
|
|
|
83
83
|
Forum sign-in and sign-out are **agent/MCP only**. There is no Sign in / Sign out control in the node-app Compose header.
|
|
84
84
|
|
|
@@ -119,6 +119,7 @@ Propose builders **hard-fail** if `getVotes(KeyGen) <` live `proposalThreshold()
|
|
|
119
119
|
| Fetch on-chain state | `ctm_continuum_dao_fetch_proposal_state` |
|
|
120
120
|
| Who voted and how | `ctm_continuum_dao_fetch_proposal_votes` |
|
|
121
121
|
| Fetch voting power | `ctm_continuum_dao_fetch_voting_power` |
|
|
122
|
+
| Forum session on this node | `get_forum_session` / `clear_forum_session` |
|
|
122
123
|
| Forum sign-in eligible? | `ctm_continuum_dao_forum_sign_in_eligible` |
|
|
123
124
|
| Forum KeyGen sign-in | `ctm_continuum_dao_build_forum_sign_in_multisign` |
|
|
124
125
|
| Forum sign-out | `ctm_continuum_dao_forum_sign_out` |
|
|
@@ -930,13 +930,33 @@ async function continuumDaoForumSignInEligible(args) {
|
|
|
930
930
|
const st = body.status && typeof body.status === "object" ? body.status : null;
|
|
931
931
|
const reason = typeof body.reason === "string" && body.reason || st && typeof st.message === "string" && st.message || void 0;
|
|
932
932
|
const ok = res.ok && Boolean(body.ok ?? body.eligible);
|
|
933
|
+
const votingPower = typeof body.votingPower === "string" ? body.votingPower : void 0;
|
|
934
|
+
const threshold = typeof body.threshold === "string" ? body.threshold : void 0;
|
|
935
|
+
const tokenId = typeof body.tokenId === "string" ? body.tokenId : void 0;
|
|
933
936
|
return {
|
|
934
937
|
ok,
|
|
935
938
|
eligible: ok,
|
|
936
939
|
address: typeof body.address === "string" ? body.address : address,
|
|
937
|
-
reason: ok ? void 0 : reason || "Address does not meet the veCTM threshold"
|
|
940
|
+
reason: ok ? void 0 : reason || "Address does not meet the veCTM threshold",
|
|
941
|
+
votingPower,
|
|
942
|
+
threshold,
|
|
943
|
+
tokenId
|
|
938
944
|
};
|
|
939
945
|
}
|
|
946
|
+
function assertForumSignInUsernameChoice(args) {
|
|
947
|
+
const nodeKey = args.nodeKey?.trim() || "";
|
|
948
|
+
const username = args.username?.trim() || "";
|
|
949
|
+
if (username && !FORUM_USERNAME_RE.test(username)) {
|
|
950
|
+
throw new Error(
|
|
951
|
+
"Ask the operator for a forum username of 2\u201316 letters, numbers, periods, underscores, or hyphens. If they want the node-key name, call again with useNodeKeyUsername true and nodeKey set."
|
|
952
|
+
);
|
|
953
|
+
}
|
|
954
|
+
if (!username && !(args.useNodeKeyUsername && nodeKey)) {
|
|
955
|
+
throw new Error(
|
|
956
|
+
"Ask the operator for a custom forum username (2\u201316 letters, numbers, . _ -). If they want the default, call again with useNodeKeyUsername true and nodeKey set. The username will be the first 16 characters of the node key."
|
|
957
|
+
);
|
|
958
|
+
}
|
|
959
|
+
}
|
|
940
960
|
async function continuumDaoForumSignInNonce(args) {
|
|
941
961
|
const qs2 = new URLSearchParams({
|
|
942
962
|
address: args.address,
|
|
@@ -945,6 +965,18 @@ async function continuumDaoForumSignInNonce(args) {
|
|
|
945
965
|
});
|
|
946
966
|
return forumFetch(`/api/continuum/eip712/nonce?${qs2}`, { forumUrl: args.forumUrl });
|
|
947
967
|
}
|
|
968
|
+
function forumSignInTypedExpiryUnix(message) {
|
|
969
|
+
const raw = message.expiresAt;
|
|
970
|
+
const n = typeof raw === "number" ? raw : typeof raw === "string" && raw.trim() !== "" ? Number(raw) : NaN;
|
|
971
|
+
if (!Number.isFinite(n) || n <= 0) return void 0;
|
|
972
|
+
return Math.floor(n > 1e12 ? n / 1e3 : n);
|
|
973
|
+
}
|
|
974
|
+
function forumSignInRequestExpiryUnix(message, explicit) {
|
|
975
|
+
const typed = forumSignInTypedExpiryUnix(message);
|
|
976
|
+
const caller = explicit != null && explicit > 0 ? Math.floor(explicit) : void 0;
|
|
977
|
+
if (typed != null && caller != null) return Math.min(typed, caller);
|
|
978
|
+
return typed ?? caller;
|
|
979
|
+
}
|
|
948
980
|
async function buildEvmMultisignBodyContinuumDaoForumSignIn(args) {
|
|
949
981
|
const owner = viem.getAddress(args.executorAddress);
|
|
950
982
|
const gate = await continuumDaoForumSignInEligible({ address: owner, forumUrl: args.forumUrl });
|
|
@@ -953,6 +985,7 @@ async function buildEvmMultisignBodyContinuumDaoForumSignIn(args) {
|
|
|
953
985
|
`${gate.reason || "Address does not meet the veCTM threshold"}. Do not start a multi-sign request.`
|
|
954
986
|
);
|
|
955
987
|
}
|
|
988
|
+
assertForumSignInUsernameChoice(args);
|
|
956
989
|
const typed = await continuumDaoForumSignInNonce({
|
|
957
990
|
address: owner,
|
|
958
991
|
nodeKey: args.nodeKey,
|
|
@@ -981,10 +1014,10 @@ async function buildEvmMultisignBodyContinuumDaoForumSignIn(args) {
|
|
|
981
1014
|
}
|
|
982
1015
|
}
|
|
983
1016
|
],
|
|
984
|
-
expiryDate: args.expiryDate
|
|
1017
|
+
expiryDate: forumSignInRequestExpiryUnix(typed.message, args.expiryDate)
|
|
985
1018
|
});
|
|
986
1019
|
}
|
|
987
|
-
var DEFAULT_FORUM_URL; exports.FORUM_GOVERNANCE_SECTIONS = void 0; exports.FORUM_IDEA_SECTION = void 0; exports.PROPOSAL_TYPE_TO_FORUM_SECTION = void 0; var IDEA_SECTION_ALIASES; exports.FORUM_LOGIN_DELIVERY_KIND = void 0;
|
|
1020
|
+
var DEFAULT_FORUM_URL; exports.FORUM_GOVERNANCE_SECTIONS = void 0; exports.FORUM_IDEA_SECTION = void 0; exports.PROPOSAL_TYPE_TO_FORUM_SECTION = void 0; var IDEA_SECTION_ALIASES; exports.FORUM_LOGIN_DELIVERY_KIND = void 0; var FORUM_USERNAME_RE;
|
|
988
1021
|
var init_forum = __esm({
|
|
989
1022
|
"src/protocols/evm/continuum-dao/forum.ts"() {
|
|
990
1023
|
init_eip712Multisign();
|
|
@@ -1006,6 +1039,7 @@ var init_forum = __esm({
|
|
|
1006
1039
|
};
|
|
1007
1040
|
IDEA_SECTION_ALIASES = /* @__PURE__ */ new Set(["ideas", "ideas-suggestions", "suggestions"]);
|
|
1008
1041
|
exports.FORUM_LOGIN_DELIVERY_KIND = "forumLogin";
|
|
1042
|
+
FORUM_USERNAME_RE = /^[A-Za-z0-9._-]{2,16}$/;
|
|
1009
1043
|
}
|
|
1010
1044
|
});
|
|
1011
1045
|
|