dexe-mcp 0.5.3 → 0.5.7

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 (51) hide show
  1. package/CHANGELOG.md +149 -0
  2. package/README.md +24 -18
  3. package/dist/config.d.ts +27 -4
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +105 -9
  6. package/dist/config.js.map +1 -1
  7. package/dist/lib/blacklist.d.ts +22 -0
  8. package/dist/lib/blacklist.d.ts.map +1 -0
  9. package/dist/lib/blacklist.js +43 -0
  10. package/dist/lib/blacklist.js.map +1 -0
  11. package/dist/lib/signer.d.ts +17 -4
  12. package/dist/lib/signer.d.ts.map +1 -1
  13. package/dist/lib/signer.js +33 -16
  14. package/dist/lib/signer.js.map +1 -1
  15. package/dist/rpc.d.ts +10 -5
  16. package/dist/rpc.d.ts.map +1 -1
  17. package/dist/rpc.js +18 -10
  18. package/dist/rpc.js.map +1 -1
  19. package/dist/tools/daoDeploy.d.ts.map +1 -1
  20. package/dist/tools/daoDeploy.js +27 -6
  21. package/dist/tools/daoDeploy.js.map +1 -1
  22. package/dist/tools/flow.d.ts +3 -0
  23. package/dist/tools/flow.d.ts.map +1 -1
  24. package/dist/tools/flow.js +29 -14
  25. package/dist/tools/flow.js.map +1 -1
  26. package/dist/tools/getConfig.d.ts +10 -0
  27. package/dist/tools/getConfig.d.ts.map +1 -0
  28. package/dist/tools/getConfig.js +52 -0
  29. package/dist/tools/getConfig.js.map +1 -0
  30. package/dist/tools/index.d.ts.map +1 -1
  31. package/dist/tools/index.js +2 -0
  32. package/dist/tools/index.js.map +1 -1
  33. package/dist/tools/otc.d.ts.map +1 -1
  34. package/dist/tools/otc.js +28 -6
  35. package/dist/tools/otc.js.map +1 -1
  36. package/dist/tools/proposalBuild.d.ts.map +1 -1
  37. package/dist/tools/proposalBuild.js +11 -2
  38. package/dist/tools/proposalBuild.js.map +1 -1
  39. package/dist/tools/proposalBuildComplex.d.ts.map +1 -1
  40. package/dist/tools/proposalBuildComplex.js +49 -14
  41. package/dist/tools/proposalBuildComplex.js.map +1 -1
  42. package/dist/tools/proposalBuildMore.js +60 -20
  43. package/dist/tools/proposalBuildMore.js.map +1 -1
  44. package/dist/tools/proposalBuildOffchain.d.ts.map +1 -1
  45. package/dist/tools/proposalBuildOffchain.js +26 -15
  46. package/dist/tools/proposalBuildOffchain.js.map +1 -1
  47. package/dist/tools/txSend.d.ts +1 -1
  48. package/dist/tools/txSend.d.ts.map +1 -1
  49. package/dist/tools/txSend.js +37 -9
  50. package/dist/tools/txSend.js.map +1 -1
  51. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,154 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.7
4
+
5
+ Last broadcast sweep: **57 / 57 green** on Polaris (BSC testnet 97), 2026-05-12.
6
+
7
+ ### Swarm coverage — 41 → 57 scenarios
8
+
9
+ - New broadcast-lifecycle scenarios for the three v0.5.6 builder rewrites: `S52-withdraw-treasury-execute`, `S53-apply-to-dao-execute`, `S54-reward-multiplier-execute`. Each runs the wrapper builder → `dexe_proposal_create` custom flow on the swarm fixture DAO and asserts the proposal lands in Voting / SucceededFor / ExecutedFor. Validates the Bug #29 / #30 / #31 fixes end-to-end against on-chain state, not just calldata shape.
10
+ - New broadcast scenarios for the most-used proposal types: `S55-token-transfer-execute`, `S56-blacklist-execute`, `S57-add-expert-execute`. Same build → create → state pattern.
11
+ - Refreshed `S18-withdraw-treasury-build` to pass the now-required `token` argument; refreshed `S31-reward-multiplier-build` to use Polaris's `nftMultiplier` (replacing retired Glacier address) and PRECISION-scaled multipliers (`1.5x => 1.5e25`) per v0.5.6's stricter validator.
12
+ - Replaced retired Glacier fixture with fresh **Polaris** testnet DAO (LINEAR, 50% quorum, deployed 2026-05-12). Sentinel (validator chamber) unchanged. README updated.
13
+
14
+ ### Swarm tooling
15
+
16
+ - **`scripts/swarm/preflight.ts` now counts deposited tokens alongside the wallet balance.** A wallet with funds locked behind in-flight proposals had `ERC20.balanceOf=0` even though its governance power was intact in UserKeeper; the old check aborted nightly runs on a non-issue. Each token row now also reads `UserKeeper.tokenBalance(user, Personal)` from the parallel DAO and adds the deposited surplus to the threshold check. Falls back to wallet-only when the helper call reverts.
17
+ - **`scripts/swarm/nightly.sh` sanitizes the SUMMARY_LINE before posting to public targets.** The orchestrator's machine-greppable summary line ends with the absolute report path, which leaks the operator's filesystem layout when the repo is public. Local stdout still gets the full line; webhook + GitHub-issue posts get a stripped variant (runId + N/M + mode + chainTag, no path).
18
+
19
+ ### Multi-chain config (chain-mixup guard)
20
+
21
+ - New optional env vars `DEXE_RPC_URL_TESTNET` + `DEXE_RPC_URL_MAINNET` + `DEXE_DEFAULT_CHAIN_ID`. Configure one or both; the MCP can now route reads and broadcasts to whichever chain a tool call requests, without an MCP restart.
22
+ - Write/composite tools accept an optional `chainId` arg: `dexe_tx_send`, `dexe_tx_status`, `dexe_dao_build_deploy`, `dexe_proposal_create`, `dexe_proposal_vote_and_execute`, `dexe_otc_dao_open_sale`, `dexe_otc_buyer_buy`, `dexe_otc_buyer_claim_all`. Omitting the arg uses the default chain. Requesting a chain with no configured RPC fails fast with a clear error before any tx is built or signed.
23
+ - Legacy `DEXE_RPC_URL` + `DEXE_CHAIN_ID` still works and stacks with the new vars — the legacy entry registers as one more chain in the pool. When `DEXE_CHAIN_ID` is omitted, the chain id is best-effort inferred from the URL hostname.
24
+ - New `dexe_get_config` diagnostic tool: returns the resolved chain set, the default chain, signer status, and IPFS/subgraph configuration. Call it at session start to orient before any write.
25
+ - Provider and signer are now per-chain caches (`RpcProvider`, `SignerManager`) so multi-chain usage doesn't churn through new connections.
26
+
27
+ ## 0.5.6
28
+
29
+ Three Stage A mainnet bug fixes — all surfaced on `DexeClientDemo`
30
+ (BSC `0xCAe3…5B41`) and tracked as bugs #29 / #30 / #31.
31
+
32
+ ### Fixed
33
+
34
+ - **Bug #30 — `dexe_proposal_build_withdraw_treasury` emitted wrong
35
+ selector.** Builder targeted `GovPool.withdraw(address,uint256,uint256[])`
36
+ (selector `0xfb8c5ef0`), which is the user-deposit-withdraw function on
37
+ GovPool, not a treasury transfer. `proposal_create` rejected it with
38
+ `Gov: invalid internal data`. Rewritten to emit one external
39
+ `ERC20.transfer(receiver, amount)` action per token and/or one
40
+ `ERC721.transferFrom(govPool, receiver, tokenId)` action per NFT —
41
+ treasury sits in the GovPool address as a regular ERC20/721 balance, so
42
+ withdrawal is just a plain external token call. New schema: drop the
43
+ single `(amount, nftIds)` shape; supply `token`+`amount` and/or
44
+ `nftAddress`+`nftIds`. At least one must be non-empty.
45
+
46
+ - **Bug #29 — `apply_to_dao` / `token_transfer` / `withdraw_treasury` had
47
+ no blacklist precheck.** `ERC20Gov.transfer` reverts on a blacklisted
48
+ recipient, and a proposal that passes voting then fails `execute()` sits
49
+ in `SucceededFor` permanently with no recovery. When `DEXE_RPC_URL` is
50
+ set, the three builders now `isBlacklisted(receiver)` against the token
51
+ before encoding and refuse to build with a clear error if the recipient
52
+ is blacklisted. When the token isn't ERC20Gov (call reverts) or RPC is
53
+ absent, the precheck soft-skips with a note in the result detail —
54
+ build always proceeds. New helper: `src/lib/blacklist.ts`.
55
+
56
+ - **Bug #31 — `dexe_proposal_build_reward_multiplier` mint/change_token
57
+ reverted silently.** `ERC721_MULTIPLIER_ABI` declared `duration` as
58
+ `uint256`, but `ERC721Multiplier.mint(address,uint256,uint64,string)`
59
+ uses `uint64`. ethers derives the selector from the canonical signature,
60
+ so the wrong-typed arg produced a different selector → no-match →
61
+ silent revert with no returndata when GovPool.execute called into the
62
+ multiplier (the contract has no `MAX_MULTIPLIER` check, so the original
63
+ scale-mismatch hypothesis was wrong). Fixed the ABI to `uint64
64
+ duration`. Builder now also rejects `multiplier=0`, multiplier values
65
+ below `PRECISION/100` (likely forgot the 1e25 scale), `duration > 2^64
66
+ − 1`, and `duration=0` for mint. Tool description spells out
67
+ `PRECISION = 1e25` and `duration = seconds (uint64)`.
68
+
69
+ ## 0.5.5
70
+
71
+ Doc + RPC hygiene. Two issues surfaced after publishing 0.5.4:
72
+
73
+ ### Fixed
74
+
75
+ - **Internal RPC URL leaked into examples.** Three files referenced
76
+ `https://mbsc1.dexe.io/rpc`, an internal DeXe endpoint not intended for
77
+ public traffic. Replaced with the canonical public BSC RPC
78
+ `https://bsc-dataseed.binance.org` in:
79
+ - `docs/ENVIRONMENT.md` (3 occurrences — quick-start block, env table
80
+ example, BSC mainnet chain config)
81
+ - `tests/swarm/README.md` (`SWARM_RPC_URL_MAINNET` example)
82
+ - `tests/compat/FORM-GUIDE.md` (network-capture hint)
83
+ - `.env.example` (2 occurrences — `DEXE_RPC_URL` core block,
84
+ `SWARM_RPC_URL_MAINNET` swarm block)
85
+ - `scripts/swarm/test-mainnet-deploy.mjs` + `test-offchain-mainnet.mjs`
86
+ (now read `process.env.DEXE_RPC_URL` first, fall back to public BSC RPC)
87
+ Existing installs that copy-pasted the snippet still work — both URLs
88
+ serve BSC mainnet — but the public one carries no internal-infra hint.
89
+ - **README links broken on npmjs.com.** Relative links like
90
+ `./docs/TOOLS.md` work on GitHub but npm does NOT resolve them against the
91
+ repo URL — npm renders the README at the package home and a relative link
92
+ resolves to a non-existent path on `npmjs.com`. Converted all in-README
93
+ links to absolute GitHub URLs:
94
+ `./docs/X.md` → `https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/X.md`
95
+ Same pattern applied to the swarm-runbook + LICENSE links.
96
+
97
+ ### Scope of exposure
98
+
99
+ Verified via `npm pack --dry-run`: the internal URL was **never shipped in
100
+ any npm tarball**. `package.json`'s `files` array only includes `dist/`,
101
+ `README.md`, `CHANGELOG.md`, `FUTURE.md`, and `.mcp.example.json` — all of
102
+ which used the public BSC RPC. The leak was confined to GitHub-only
103
+ artifacts (`docs/`, `tests/`, gitignored `.env.example` + swarm probe
104
+ scripts). No npm-deprecation needed.
105
+
106
+ ### Notes
107
+
108
+ - Git history retains the original URL — full history rewrite via
109
+ `git filter-repo` was considered and declined: rewrites every commit SHA,
110
+ breaks PR refs and external clones, and the URL is an endpoint, not a
111
+ credential. Forward-fix is sufficient.
112
+
113
+ ## 0.5.4
114
+
115
+ Off-chain backend + DAO deploy hardening. Two latent bugs surfaced during
116
+ mainnet client-demo lifecycle on `0xCAe32Fa6e6D1C223Ed1047caA58F7fC0b2D65B41`
117
+ (BSC) — both fixed at the boundary so callers don't have to know.
118
+
119
+ ### Fixed
120
+
121
+ - **`dexe_dao_build_deploy`** (`src/tools/daoDeploy.ts`) — pre-flight reject
122
+ when `tokenParams.cap == mintedTotal` while creating a new gov token.
123
+ ERC20Gov init reverted silently inside `_initGovPool` with the generic
124
+ `Address: low-level delegate call failed`, hiding the real cause behind a
125
+ 10M-gas wasted tx. The validator now throws a clear message:
126
+ `cap must be strictly greater than mintedTotal; pass cap=0 for uncapped, or
127
+ cap > mintedTotal`. Tool description updated.
128
+ - **`dexe_proposal_build_offchain_single_option` / `_multi_option` /
129
+ `_for_against`** (`src/tools/proposalBuildOffchain.ts`) — backend rejected
130
+ every off-chain proposal with HTTP 400 `proposal type was not found` because
131
+ the builders sent `attributes.type = String(Math.floor(Date.now()/1000))`
132
+ (unix timestamp) instead of a registered template name. Constants now wired
133
+ per voting type:
134
+ - `default_single_option_type` for `voting_type=one_of`
135
+ - `default_multi_option_type` for `voting_type=multiple_of`
136
+ - `default_for_against_type` for `voting_type=for_against`
137
+ - **Off-chain quorum percentages** — same three builders. The backend stores
138
+ `*_percent` as fractions (`0.5` = 50%), but the inputs accept whole-number
139
+ percentages (`50` = 50%) for ergonomic parity with the frontend form.
140
+ Boundary now divides by 100 once, via a new `pctToFraction` helper.
141
+
142
+ ### Verified
143
+
144
+ - Smoke-tested all three off-chain builders: `outer.type` and
145
+ `custom_parameters.type` carry the correct constants; quorum fractions match
146
+ backend examples (live proposal #58 created end-to-end against
147
+ `https://api.dexe.io`).
148
+ - DAO deploy: `cap == mintedTotal` rejected pre-flight with the new message;
149
+ `cap > mintedTotal` and `cap == 0` (uncapped) pass the check.
150
+ - `tsc` clean, no project-test regressions.
151
+
3
152
  ## 0.5.3
4
153
 
5
154
  `getProposals` ABI fix for the post-upgrade GovPool layout. On-chain
package/README.md CHANGED
@@ -6,9 +6,9 @@ MCP server that gives AI agents **full DeXe Protocol DAO operations coverage**
6
6
 
7
7
  **Two write modes, calldata-default.** Every write tool returns a ready-to-sign `TxPayload = { to, data, value, chainId, description }` that the agent's wallet (MetaMask, Safe, hardware, etc.) signs and submits — no key in the MCP. Power users who *want* the server to sign and broadcast can opt in by setting `DEXE_PRIVATE_KEY`; that unlocks `dexe_tx_send`, `dexe_tx_status`, and the auto-broadcast branch of `dexe_proposal_create` / `dexe_proposal_vote_and_execute`. Default stays calldata-only.
8
8
 
9
- **125 tools** across 14 groups. Call `dexe_proposal_catalog` at runtime for the full proposal-type map, or browse the [catalog](#tool-catalog) below.
9
+ **126 tools** across 14 groups. Call `dexe_proposal_catalog` at runtime for the full proposal-type map, or browse the [catalog](#tool-catalog) below.
10
10
 
11
- > **End-to-end coverage.** Every proposal-builder tool ships with a swarm-test scenario that exercises it on BSC testnet. Latest pass: **41/41 scenarios green**, ~200 broadcasts validated against two fixture DAOs (Glacier 50%-quorum + Sentinel 5%-quorum-with-validators). See [Swarm test harness](#swarm-test-harness) below.
11
+ > **End-to-end coverage.** Every proposal-builder tool ships with a swarm-test scenario that exercises it on BSC testnet. Latest pass (2026-05-12): **57 scenarios shipped**, broadcasts validated against two fixture DAOs (Polaris 50%-quorum + Sentinel 5%-quorum-with-validators). See [Swarm test harness](#swarm-test-harness) below.
12
12
 
13
13
  ## Prerequisites
14
14
 
@@ -66,9 +66,9 @@ Minimum config to get **read-only** access to a BSC mainnet DAO:
66
66
  }
67
67
  ```
68
68
 
69
- Add `DEXE_PINATA_JWT` for IPFS uploads, `DEXE_BACKEND_API_URL` for off-chain proposals, and per-chain subgraph URLs for `dexe_proposal_voters` and the DAO-list reads. Full matrix → [`docs/ENVIRONMENT.md`](./docs/ENVIRONMENT.md).
69
+ Add `DEXE_PINATA_JWT` for IPFS uploads, `DEXE_BACKEND_API_URL` for off-chain proposals, and per-chain subgraph URLs for `dexe_proposal_voters` and the DAO-list reads. Full matrix → [`docs/ENVIRONMENT.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/ENVIRONMENT.md).
70
70
 
71
- Three first-call examples (full set in [`docs/USAGE.md`](./docs/USAGE.md)):
71
+ Three first-call examples (full set in [`docs/USAGE.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/USAGE.md)):
72
72
 
73
73
  ```jsonc
74
74
  // 1) discover available proposal types
@@ -94,7 +94,7 @@ Most tools don't need the protocol checkout at all — read/proposal/vote/deploy
94
94
 
95
95
  ## Environment variables
96
96
 
97
- All optional. Tools that need a missing variable fail with a clear message pointing at exactly what to set. Full matrix + per-tool requirements → [`docs/ENVIRONMENT.md`](./docs/ENVIRONMENT.md).
97
+ All optional. Tools that need a missing variable fail with a clear message pointing at exactly what to set. Full matrix + per-tool requirements → [`docs/ENVIRONMENT.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/ENVIRONMENT.md).
98
98
 
99
99
  | Variable | Required for | Purpose |
100
100
  |----------|--------------|---------|
@@ -113,11 +113,11 @@ All optional. Tools that need a missing variable fail with a clear message point
113
113
 
114
114
  ## Documentation
115
115
 
116
- Full docs in [`docs/`](./docs):
116
+ Full docs in [`docs/`](https://github.com/edward-arinin-web-dev/dexe-mcp/tree/main/docs):
117
117
 
118
- - [`docs/TOOLS.md`](./docs/TOOLS.md) — complete catalog of all 125 tools, organized by category, with one-line descriptions and required envs per tool.
119
- - [`docs/USAGE.md`](./docs/USAGE.md) — 10 worked examples (deploy DAO, create proposals, vote, delegate, validator chamber, decode calldata, off-chain proposals, multicall batching). Copy-pasteable JSON.
120
- - [`docs/ENVIRONMENT.md`](./docs/ENVIRONMENT.md) — full env-var reference: minimum block to get started, per-category requirements, calldata vs signer mode, chain-specific config, IPFS gateway rationale, subgraph migration, swarm harness envs, common pitfalls.
118
+ - [`docs/TOOLS.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/TOOLS.md) — complete catalog of all 126 tools, organized by category, with one-line descriptions and required envs per tool.
119
+ - [`docs/USAGE.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/USAGE.md) — 10 worked examples (deploy DAO, create proposals, vote, delegate, validator chamber, decode calldata, off-chain proposals, multicall batching). Copy-pasteable JSON.
120
+ - [`docs/ENVIRONMENT.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/ENVIRONMENT.md) — full env-var reference: minimum block to get started, per-category requirements, calldata vs signer mode, chain-specific config, IPFS gateway rationale, subgraph migration, swarm harness envs, common pitfalls.
121
121
 
122
122
  ## Tool surface (high-level)
123
123
 
@@ -133,14 +133,14 @@ Full docs in [`docs/`](./docs):
133
133
  | Internal validator wrappers | 4 | `_change_validator_balances`, `_change_validator_settings`, `_monthly_withdraw`, `_offchain_internal_proposal` |
134
134
  | Off-chain backend | 8 | `_offchain_single_option/_multi_option/_for_against/_settings`, auth flow (`_auth_request_nonce`, `_auth_login_request`), `_offchain_build_vote/_cancel_vote` |
135
135
  | Vote / stake / delegate / execute / claim | 16 | `_vote_build_*` family — every direct EOA write on GovPool / Validators |
136
- | Composite signing flows | 4 | `_proposal_create`, `_proposal_vote_and_execute`, `_tx_send`, `_tx_status` (all opt-in via `DEXE_PRIVATE_KEY`) |
136
+ | Composite signing flows | 5 | `_proposal_create`, `_proposal_vote_and_execute`, `_tx_send`, `_tx_status`, `_get_config` (signing tools opt-in via `DEXE_PRIVATE_KEY`; `_get_config` is read-only diagnostic for the multi-chain config) |
137
137
  | Subgraph reads | 7 | DAO list, members, experts, user activity, delegation map, distribution status, OTC sale tiers per DAO (decentralized network endpoints + RPC fallback) |
138
138
  | Merkle utility | 2 | `dexe_merkle_build`, `dexe_merkle_proof` — OZ `StandardMerkleTree`-compatible (sorted-pair commutative keccak, double-hash leaf) |
139
- | OTC composites | 4 | `dexe_otc_dao_open_sale`, `_buyer_status`, `_buyer_buy`, `_buyer_claim_all` — full project-owner + buyer flows over `TokenSaleProposal`. See [`docs/OTC.md`](./docs/OTC.md) |
140
- | Simulator | 3 | `dexe_sim_calldata`, `_sim_proposal`, `_sim_buy` — `eth_call`-based preflight with revert-reason decoding. See [`docs/SIMULATOR.md`](./docs/SIMULATOR.md) |
141
- | Multi-DAO inbox + forecast | 2 | `dexe_user_inbox` — pending items across N DAOs (unvoted proposals, claimable rewards, locked deposits). `_proposal_forecast` — pass-rate prediction with quorum projection + risk flags. See [`docs/INBOX.md`](./docs/INBOX.md) |
139
+ | OTC composites | 4 | `dexe_otc_dao_open_sale`, `_buyer_status`, `_buyer_buy`, `_buyer_claim_all` — full project-owner + buyer flows over `TokenSaleProposal`. See [`docs/OTC.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/OTC.md) |
140
+ | Simulator | 3 | `dexe_sim_calldata`, `_sim_proposal`, `_sim_buy` — `eth_call`-based preflight with revert-reason decoding. See [`docs/SIMULATOR.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/SIMULATOR.md) |
141
+ | Multi-DAO inbox + forecast | 2 | `dexe_user_inbox` — pending items across N DAOs (unvoted proposals, claimable rewards, locked deposits). `_proposal_forecast` — pass-rate prediction with quorum projection + risk flags. See [`docs/INBOX.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/INBOX.md) |
142
142
 
143
- Total: **125**. Per-tool descriptions, args, return shapes → [`docs/TOOLS.md`](./docs/TOOLS.md).
143
+ Total: **126**. Per-tool descriptions, args, return shapes → [`docs/TOOLS.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/docs/TOOLS.md).
144
144
 
145
145
  ## Swarm test harness
146
146
 
@@ -149,7 +149,7 @@ tool against real BSC-testnet DAOs. Scenarios are JSON specs; the orchestrator
149
149
  loads them, resolves agent wallets, and runs each step through either an inline
150
150
  ethers dispatcher or the dexe-mcp stdio bridge.
151
151
 
152
- **41 scenarios shipped** covering:
152
+ **57 scenarios shipped** covering:
153
153
 
154
154
  - Reset + delegation chains (S00, S01, S06, S14)
155
155
  - Validator chamber pass / veto / full lifecycle (S02, S03, S07)
@@ -163,6 +163,12 @@ ethers dispatcher or the dexe-mcp stdio bridge.
163
163
  delegate/revoke from expert, reward multiplier (4 modes), change voting
164
164
  settings, new proposal type, change math model, custom ABI, manual calldata,
165
165
  create staking tier, off-chain validator + for/against + settings) (S16–S40)
166
+ - OTC multi-tier sale flows: open sale, buyer buy native + merkle (S41–S46)
167
+ - Simulator + inbox + per-DAO reads (S47, S48, S50, S51)
168
+ - **Broadcast lifecycle for the v0.5.6 builder rewrites: `withdraw_treasury`,
169
+ `apply_to_dao`, `reward_multiplier mint` (S52–S54)**
170
+ - **Broadcast lifecycle for the most-used proposal types: `token_transfer`,
171
+ `blacklist`, `add_expert` (S55–S57)**
166
172
 
167
173
  ```bash
168
174
  # 1) generate 9 wallets (8 agents + funder), fund the funder from your wallet
@@ -174,8 +180,8 @@ npm run swarm:run # full sweep, all scenarios
174
180
  npm run swarm:run -- --scenarios=S00-reset,S01-delegation-chain-3hop --dry-run
175
181
  ```
176
182
 
177
- Setup runbook: [`tests/swarm/README.md`](tests/swarm/README.md).
178
- Scenario schema: [`tests/swarm/scenarios/_schema.md`](tests/swarm/scenarios/_schema.md).
183
+ Setup runbook: [`tests/swarm/README.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/tests/swarm/README.md).
184
+ Scenario schema: [`tests/swarm/scenarios/_schema.md`](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/tests/swarm/scenarios/_schema.md).
179
185
  Per-role agent prompts: `tests/swarm/prompts/`.
180
186
 
181
187
  ## Contributing
@@ -191,4 +197,4 @@ npm run dev # watch mode
191
197
 
192
198
  ## License
193
199
 
194
- MIT. See [LICENSE](./LICENSE).
200
+ MIT. See [LICENSE](https://github.com/edward-arinin-web-dev/dexe-mcp/blob/main/LICENSE).
package/dist/config.d.ts CHANGED
@@ -1,15 +1,32 @@
1
+ export interface ChainConfig {
2
+ chainId: number;
3
+ rpcUrl: string;
4
+ /** Optional `ContractsRegistry` override scoped to this chain. */
5
+ registryOverride?: string;
6
+ }
1
7
  export interface DexeConfig {
2
8
  /** Absolute, normalized path to the DeXe-Protocol checkout (may not exist yet). */
3
9
  protocolPath: string;
4
- /** Optional JSON-RPC endpoint for on-chain gov tools. */
10
+ /** All chains configured via env. Empty when no RPC is set. Frozen. */
11
+ chains: ReadonlyMap<number, ChainConfig>;
12
+ /**
13
+ * Default chain id used when a tool call omits `chainId`. Always resolves to
14
+ * a configured chain when `chains` is non-empty. When `chains` is empty,
15
+ * defaults to 56 for legacy single-chain code paths that don't need an RPC.
16
+ */
17
+ defaultChainId: number;
18
+ /**
19
+ * Back-compat alias for `chains.get(defaultChainId)?.rpcUrl`. Always reflects
20
+ * the default chain's RPC. New code should call `getProvider(chainId)` instead.
21
+ */
5
22
  rpcUrl?: string;
6
- /** Chain id the RPC points at. Defaults to 56 (BSC mainnet, DeXe home). */
23
+ /** Back-compat alias for `defaultChainId`. */
7
24
  chainId: number;
8
- /** Override for `ContractsRegistry` root address. */
25
+ /** Back-compat: registry override resolved against the default chain. */
9
26
  registryOverride?: string;
10
27
  /** Pinata JWT for IPFS uploads (reads work without it via gateway). */
11
28
  pinataJwt?: string;
12
- /** GraphQL endpoint URLs for The Graph subgraphs. */
29
+ /** GraphQL endpoint URLs for The Graph subgraphs (chain-agnostic in env). */
13
30
  subgraphPoolsUrl?: string;
14
31
  subgraphValidatorsUrl?: string;
15
32
  subgraphInteractionsUrl?: string;
@@ -25,4 +42,10 @@ export interface DexeConfig {
25
42
  * that lazily from inside build/test tools.
26
43
  */
27
44
  export declare function loadConfig(): Promise<DexeConfig>;
45
+ /**
46
+ * Resolve a chain config given an optional `chainId`. When omitted, returns
47
+ * the default chain. Throws with a clear message when the requested chain is
48
+ * not configured.
49
+ */
50
+ export declare function resolveChain(config: DexeConfig, chainId?: number): ChainConfig;
28
51
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;IACrB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,qDAAqD;IACrD,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CAgEtD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,UAAU;IACzB,mFAAmF;IACnF,YAAY,EAAE,MAAM,CAAC;IAErB,uEAAuE;IACvE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;IACzC;;;;OAIG;IACH,cAAc,EAAE,MAAM,CAAC;IAEvB;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,yEAAyE;IACzE,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAE1B,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,qBAAqB,CAAC,EAAE,MAAM,CAAC;IAC/B,uBAAuB,CAAC,EAAE,MAAM,CAAC;IACjC,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CA4ItD;AAcD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,WAAW,CAW9E"}
package/dist/config.js CHANGED
@@ -18,23 +18,88 @@ export async function loadConfig() {
18
18
  else if (!isBuildReady(protocolPath)) {
19
19
  process.stderr.write(`[dexe-mcp] DeXe-Protocol checkout at ${protocolPath} is incomplete (missing node_modules or hardhat.config) — will be prepared on first dexe_compile call.\n`);
20
20
  }
21
- const rpcUrl = process.env.DEXE_RPC_URL?.trim() || undefined;
22
- let chainId = 56;
21
+ // ---- collect every configured chain ------------------------------------
22
+ // Priority:
23
+ // 1) DEXE_RPC_URL_TESTNET → chain 97
24
+ // 2) DEXE_RPC_URL_MAINNET → chain 56
25
+ // 3) Legacy DEXE_RPC_URL + DEXE_CHAIN_ID → register that chain
26
+ // All three may coexist; later entries with the same chainId override earlier.
27
+ const chains = new Map();
28
+ const registryOverride = process.env.DEXE_CONTRACTS_REGISTRY?.trim() || undefined;
29
+ const rpcTestnet = process.env.DEXE_RPC_URL_TESTNET?.trim() || undefined;
30
+ if (rpcTestnet) {
31
+ chains.set(97, { chainId: 97, rpcUrl: rpcTestnet });
32
+ }
33
+ const rpcMainnet = process.env.DEXE_RPC_URL_MAINNET?.trim() || undefined;
34
+ if (rpcMainnet) {
35
+ chains.set(56, { chainId: 56, rpcUrl: rpcMainnet });
36
+ }
37
+ // Legacy single-chain env (still supported)
38
+ const legacyRpc = process.env.DEXE_RPC_URL?.trim() || undefined;
39
+ let legacyChainId;
23
40
  if (process.env.DEXE_CHAIN_ID) {
24
41
  const n = Number(process.env.DEXE_CHAIN_ID);
25
42
  if (!Number.isFinite(n) || n <= 0) {
26
43
  fatal(`DEXE_CHAIN_ID must be a positive integer, got: ${process.env.DEXE_CHAIN_ID}`);
27
44
  }
28
- chainId = n;
45
+ legacyChainId = n;
46
+ }
47
+ if (legacyRpc) {
48
+ // Resolve legacy chainId. If unset, infer from URL hostname; fall back to 56.
49
+ const inferred = legacyChainId ?? inferChainIdFromRpcUrl(legacyRpc) ?? 56;
50
+ // Apply registryOverride only when this is the legacy chain (per-chain
51
+ // override via DEXE_CONTRACTS_REGISTRY has always been single-chain).
52
+ chains.set(inferred, {
53
+ chainId: inferred,
54
+ rpcUrl: legacyRpc,
55
+ registryOverride,
56
+ });
57
+ }
58
+ // ---- resolve default chain ---------------------------------------------
59
+ let defaultChainId;
60
+ const explicitDefault = process.env.DEXE_DEFAULT_CHAIN_ID?.trim();
61
+ if (explicitDefault) {
62
+ const n = Number(explicitDefault);
63
+ if (!Number.isFinite(n) || n <= 0) {
64
+ fatal(`DEXE_DEFAULT_CHAIN_ID must be a positive integer, got: ${explicitDefault}`);
65
+ }
66
+ if (!chains.has(n)) {
67
+ const configured = [...chains.keys()].sort().join(", ") || "none";
68
+ fatal(`DEXE_DEFAULT_CHAIN_ID=${n} but no RPC configured for that chain. Configured: [${configured}]. Set DEXE_RPC_URL_${n === 97 ? "TESTNET" : n === 56 ? "MAINNET" : "<chain>"} or legacy DEXE_RPC_URL.`);
69
+ }
70
+ defaultChainId = n;
71
+ }
72
+ else if (chains.size === 1) {
73
+ defaultChainId = [...chains.keys()][0];
74
+ }
75
+ else if (chains.size > 1) {
76
+ // Multi-chain without explicit default → prefer testnet for safety, else lowest chainId.
77
+ const sorted = [...chains.keys()].sort((a, b) => a - b);
78
+ defaultChainId = chains.has(97) ? 97 : sorted[0];
79
+ process.stderr.write(`[dexe-mcp] multiple chains configured without DEXE_DEFAULT_CHAIN_ID; defaulting to ${defaultChainId === 97 ? "testnet (97)" : `chain ${defaultChainId}`} for safety. Set DEXE_DEFAULT_CHAIN_ID to override.\n`);
80
+ }
81
+ else {
82
+ // No chains configured — keep legacy fallback so non-RPC tools still load.
83
+ defaultChainId = legacyChainId ?? 56;
84
+ }
85
+ // ---- emit one-line summary of the resolved chain set --------------------
86
+ if (chains.size > 0) {
87
+ const summary = [...chains.values()]
88
+ .sort((a, b) => a.chainId - b.chainId)
89
+ .map(c => `${c.chainId}${c.chainId === defaultChainId ? "*" : ""}`)
90
+ .join(", ");
91
+ process.stderr.write(`[dexe-mcp] chains: [${summary}] (default marked with *)\n`);
92
+ }
93
+ else {
94
+ process.stderr.write("[dexe-mcp] no RPC configured — read/write tools that touch a chain will fail with a clear error.\n");
29
95
  }
30
- const registryOverride = process.env.DEXE_CONTRACTS_REGISTRY?.trim() || undefined;
31
96
  const pinataJwt = process.env.DEXE_PINATA_JWT?.trim() || undefined;
32
97
  const subgraphPoolsUrl = process.env.DEXE_SUBGRAPH_POOLS_URL?.trim() || undefined;
33
98
  const subgraphValidatorsUrl = process.env.DEXE_SUBGRAPH_VALIDATORS_URL?.trim() || undefined;
34
99
  const subgraphInteractionsUrl = process.env.DEXE_SUBGRAPH_INTERACTIONS_URL?.trim() || undefined;
35
100
  const privateKey = process.env.DEXE_PRIVATE_KEY?.trim() || undefined;
36
- if (privateKey && !rpcUrl) {
37
- fatal("DEXE_PRIVATE_KEY requires DEXE_RPC_URL to be set (signing needs an RPC endpoint).");
101
+ if (privateKey && chains.size === 0) {
102
+ fatal("DEXE_PRIVATE_KEY requires at least one of DEXE_RPC_URL / DEXE_RPC_URL_TESTNET / DEXE_RPC_URL_MAINNET to be set (signing needs an RPC endpoint).");
38
103
  }
39
104
  if (privateKey) {
40
105
  const { Wallet } = await import("ethers");
@@ -49,11 +114,14 @@ export async function loadConfig() {
49
114
  }
50
115
  forkBlock = n;
51
116
  }
117
+ const defaultChain = chains.get(defaultChainId);
52
118
  return Object.freeze({
53
119
  protocolPath,
54
- rpcUrl,
55
- chainId,
56
- registryOverride,
120
+ chains: Object.freeze(new Map(chains)),
121
+ defaultChainId,
122
+ chainId: defaultChainId,
123
+ rpcUrl: defaultChain?.rpcUrl,
124
+ registryOverride: defaultChain?.registryOverride ?? registryOverride,
57
125
  pinataJwt,
58
126
  subgraphPoolsUrl,
59
127
  subgraphValidatorsUrl,
@@ -62,6 +130,34 @@ export async function loadConfig() {
62
130
  privateKey,
63
131
  });
64
132
  }
133
+ /**
134
+ * Best-effort chain-id inference from a JSON-RPC URL. Used only when legacy
135
+ * `DEXE_RPC_URL` is set without `DEXE_CHAIN_ID`. Returns undefined when
136
+ * unknown — caller falls back to 56.
137
+ */
138
+ function inferChainIdFromRpcUrl(url) {
139
+ const u = url.toLowerCase();
140
+ if (u.includes("prebsc") || u.includes("testnet"))
141
+ return 97;
142
+ if (u.includes("bsc") || u.includes("binance"))
143
+ return 56;
144
+ return undefined;
145
+ }
146
+ /**
147
+ * Resolve a chain config given an optional `chainId`. When omitted, returns
148
+ * the default chain. Throws with a clear message when the requested chain is
149
+ * not configured.
150
+ */
151
+ export function resolveChain(config, chainId) {
152
+ const target = chainId ?? config.defaultChainId;
153
+ const chain = config.chains.get(target);
154
+ if (!chain) {
155
+ const configured = [...config.chains.keys()].sort().join(", ") || "none";
156
+ throw new Error(`No RPC configured for chainId=${target}. Configured chains: [${configured}]. ` +
157
+ `Set DEXE_RPC_URL_${target === 97 ? "TESTNET" : target === 56 ? "MAINNET" : "<chain>"} in the MCP env block.`);
158
+ }
159
+ return chain;
160
+ }
65
161
  function fatal(msg) {
66
162
  // stderr only — stdout is the MCP protocol channel.
67
163
  process.stderr.write(`[dexe-mcp] fatal: ${msg}\n`);
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AA4CnE;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,YAAY,GAAG,OAAO,CAAC,mBAAmB,EAAE,CAAC,CAAC;IAEpD,0EAA0E;IAC1E,0EAA0E;IAC1E,gEAAgE;IAChE,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,kDAAkD,YAAY,mDAAmD,CAClH,CAAC;IACJ,CAAC;SAAM,IAAI,CAAC,YAAY,CAAC,YAAY,CAAC,EAAE,CAAC;QACvC,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,wCAAwC,YAAY,0GAA0G,CAC/J,CAAC;IACJ,CAAC;IAED,2EAA2E;IAC3E,YAAY;IACZ,uCAAuC;IACvC,uCAAuC;IACvC,iEAAiE;IACjE,+EAA+E;IAC/E,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC9C,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAElF,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IACzE,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IACzE,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IACtD,CAAC;IAED,4CAA4C;IAC5C,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAChE,IAAI,aAAiC,CAAC;IACtC,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC9B,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;QAC5C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,KAAK,CAAC,kDAAkD,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,aAAa,GAAG,CAAC,CAAC;IACpB,CAAC;IACD,IAAI,SAAS,EAAE,CAAC;QACd,8EAA8E;QAC9E,MAAM,QAAQ,GAAG,aAAa,IAAI,sBAAsB,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;QAC1E,uEAAuE;QACvE,sEAAsE;QACtE,MAAM,CAAC,GAAG,CAAC,QAAQ,EAAE;YACnB,OAAO,EAAE,QAAQ;YACjB,MAAM,EAAE,SAAS;YACjB,gBAAgB;SACjB,CAAC,CAAC;IACL,CAAC;IAED,2EAA2E;IAC3E,IAAI,cAAsB,CAAC;IAC3B,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,EAAE,CAAC;IAClE,IAAI,eAAe,EAAE,CAAC;QACpB,MAAM,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;QAClC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,KAAK,CAAC,0DAA0D,eAAe,EAAE,CAAC,CAAC;QACrF,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;YACnB,MAAM,UAAU,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;YAClE,KAAK,CACH,yBAAyB,CAAC,uDAAuD,UAAU,uBAAuB,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,0BAA0B,CACpM,CAAC;QACJ,CAAC;QACD,cAAc,GAAG,CAAC,CAAC;IACrB,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QAC7B,cAAc,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,CAAE,CAAC;IAC1C,CAAC;SAAM,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QAC3B,yFAAyF;QACzF,MAAM,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QACxD,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC;QAClD,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,sFAAsF,cAAc,KAAK,EAAE,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,cAAc,EAAE,uDAAuD,CAChN,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,2EAA2E;QAC3E,cAAc,GAAG,aAAa,IAAI,EAAE,CAAC;IACvC,CAAC;IAED,4EAA4E;IAC5E,IAAI,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACpB,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;aACjC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;aACrC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,KAAK,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC;aAClE,IAAI,CAAC,IAAI,CAAC,CAAC;QACd,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,OAAO,6BAA6B,CAAC,CAAC;IACpF,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oGAAoG,CACrG,CAAC;IACJ,CAAC;IAED,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IACnE,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAClF,MAAM,qBAAqB,GAAG,OAAO,CAAC,GAAG,CAAC,4BAA4B,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAC5F,MAAM,uBAAuB,GAAG,OAAO,CAAC,GAAG,CAAC,8BAA8B,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IAEhG,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,gBAAgB,EAAE,IAAI,EAAE,IAAI,SAAS,CAAC;IACrE,IAAI,UAAU,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACpC,KAAK,CACH,iJAAiJ,CAClJ,CAAC;IACJ,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,IAAI,MAAM,CAAC,UAAU,CAAC,CAAC,OAAO,CAAC;QAC5C,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,kCAAkC,IAAI,IAAI,CAAC,CAAC;IACnE,CAAC;IAED,IAAI,SAA6B,CAAC;IAClC,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAChC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;YACjC,KAAK,CAAC,wDAAwD,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC,CAAC;QAC/F,CAAC;QACD,SAAS,GAAG,CAAC,CAAC;IAChB,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;IAEhD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,YAAY;QACZ,MAAM,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QACtC,cAAc;QACd,OAAO,EAAE,cAAc;QACvB,MAAM,EAAE,YAAY,EAAE,MAAM;QAC5B,gBAAgB,EAAE,YAAY,EAAE,gBAAgB,IAAI,gBAAgB;QACpE,SAAS;QACT,gBAAgB;QAChB,qBAAqB;QACrB,uBAAuB;QACvB,SAAS;QACT,UAAU;KACX,CAAe,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,SAAS,sBAAsB,CAAC,GAAW;IACzC,MAAM,CAAC,GAAG,GAAG,CAAC,WAAW,EAAE,CAAC;IAC5B,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IAC7D,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,CAAC;IAC1D,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,MAAkB,EAAE,OAAgB;IAC/D,MAAM,MAAM,GAAG,OAAO,IAAI,MAAM,CAAC,cAAc,CAAC;IAChD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IACxC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,UAAU,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC;QACzE,MAAM,IAAI,KAAK,CACb,iCAAiC,MAAM,yBAAyB,UAAU,KAAK;YAC7E,oBAAoB,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,wBAAwB,CAChH,CAAC;IACJ,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,KAAK,CAAC,GAAW;IACxB,oDAAoD;IACpD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAAC;IACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { DexeConfig } from "../config.js";
2
+ export type BlacklistCheck = {
3
+ status: "blacklisted";
4
+ token: string;
5
+ account: string;
6
+ } | {
7
+ status: "clean";
8
+ token: string;
9
+ account: string;
10
+ } | {
11
+ status: "skipped";
12
+ reason: string;
13
+ };
14
+ /**
15
+ * Best-effort `isBlacklisted(account)` lookup. Returns `skipped` when the RPC
16
+ * is unset or the call reverts (e.g. token isn't ERC20Gov). Build steps that
17
+ * use this should treat `skipped` as "go ahead" and only block on
18
+ * `blacklisted`.
19
+ */
20
+ export declare function checkBlacklist(config: DexeConfig, token: string, account: string): Promise<BlacklistCheck>;
21
+ export declare function blacklistError(token: string, account: string): string;
22
+ //# sourceMappingURL=blacklist.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blacklist.d.ts","sourceRoot":"","sources":["../../src/lib/blacklist.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAM/C,MAAM,MAAM,cAAc,GACtB;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACzD;IAAE,MAAM,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1C;;;;;GAKG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,EAClB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,cAAc,CAAC,CAwBzB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAOrE"}
@@ -0,0 +1,43 @@
1
+ import { Contract } from "ethers";
2
+ import { RpcProvider } from "../rpc.js";
3
+ const ERC20_GOV_BLACKLIST_ABI = [
4
+ "function isBlacklisted(address account) view returns (bool)",
5
+ ];
6
+ /**
7
+ * Best-effort `isBlacklisted(account)` lookup. Returns `skipped` when the RPC
8
+ * is unset or the call reverts (e.g. token isn't ERC20Gov). Build steps that
9
+ * use this should treat `skipped` as "go ahead" and only block on
10
+ * `blacklisted`.
11
+ */
12
+ export async function checkBlacklist(config, token, account) {
13
+ if (!config.rpcUrl) {
14
+ return { status: "skipped", reason: "DEXE_RPC_URL not set — skipping blacklist precheck" };
15
+ }
16
+ let provider;
17
+ try {
18
+ provider = new RpcProvider(config).requireProvider();
19
+ }
20
+ catch (err) {
21
+ return { status: "skipped", reason: err instanceof Error ? err.message : String(err) };
22
+ }
23
+ try {
24
+ const contract = new Contract(token, ERC20_GOV_BLACKLIST_ABI, provider);
25
+ const flag = await contract.isBlacklisted(account);
26
+ return flag
27
+ ? { status: "blacklisted", token, account }
28
+ : { status: "clean", token, account };
29
+ }
30
+ catch (err) {
31
+ return {
32
+ status: "skipped",
33
+ reason: `isBlacklisted() unavailable on ${token} (${err instanceof Error ? err.message : String(err)})`,
34
+ };
35
+ }
36
+ }
37
+ export function blacklistError(token, account) {
38
+ return (`Refusing to build: recipient ${account} is blacklisted on ERC20Gov ${token}. ` +
39
+ `If broadcast, GovPool.execute would revert with "ERC20Gov: account is blacklisted" ` +
40
+ `and the proposal would sit in SucceededFor permanently. Un-blacklist first ` +
41
+ `(dexe_proposal_build_blacklist with isBlacklisted=false) or pick a different recipient.`);
42
+ }
43
+ //# sourceMappingURL=blacklist.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blacklist.js","sourceRoot":"","sources":["../../src/lib/blacklist.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAmB,MAAM,QAAQ,CAAC;AACnD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,MAAM,uBAAuB,GAAG;IAC9B,6DAA6D;CACrD,CAAC;AAOX;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,MAAkB,EAClB,KAAa,EACb,OAAe;IAEf,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,oDAAoD,EAAE,CAAC;IAC7F,CAAC;IACD,IAAI,QAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,QAAQ,GAAG,IAAI,WAAW,CAAC,MAAM,CAAC,CAAC,eAAe,EAAE,CAAC;IACvD,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC;IACzF,CAAC;IACD,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,IAAI,QAAQ,CAAC,KAAK,EAAE,uBAA8C,EAAE,QAAQ,CAE5F,CAAC;QACF,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QACnD,OAAO,IAAI;YACT,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,KAAK,EAAE,OAAO,EAAE;YAC3C,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IAC1C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,kCAAkC,KAAK,KAAK,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG;SACxG,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,OAAe;IAC3D,OAAO,CACL,gCAAgC,OAAO,+BAA+B,KAAK,IAAI;QAC/E,qFAAqF;QACrF,6EAA6E;QAC7E,yFAAyF,CAC1F,CAAC;AACJ,CAAC"}
@@ -1,12 +1,25 @@
1
1
  import { Wallet } from "ethers";
2
- import type { DexeConfig } from "../config.js";
2
+ import { type DexeConfig } from "../config.js";
3
+ /**
4
+ * Per-chain signer cache. The private key is chain-agnostic; only the
5
+ * provider differs per chain.
6
+ */
3
7
  export declare class SignerManager {
4
- private wallet;
8
+ private readonly cache;
5
9
  private readonly key;
6
- private readonly rpcUrl;
10
+ private readonly config;
7
11
  constructor(config: DexeConfig);
8
12
  hasSigner(): boolean;
13
+ /**
14
+ * Address of the configured signer (chain-agnostic — same EOA across chains).
15
+ * Throws if no `DEXE_PRIVATE_KEY` is set.
16
+ */
9
17
  getAddress(): string;
10
- requireSigner(): Wallet;
18
+ /**
19
+ * Return a signer bound to the requested chain's RPC. When `chainId` is
20
+ * omitted the default chain is used.
21
+ */
22
+ requireSigner(chainId?: number): Wallet;
23
+ private failNoKey;
11
24
  }
12
25
  //# sourceMappingURL=signer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/lib/signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,MAAM,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C,qBAAa,aAAa;IACxB,OAAO,CAAC,MAAM,CAAuB;IACrC,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAqB;gBAEhC,MAAM,EAAE,UAAU;IAK9B,SAAS,IAAI,OAAO;IAIpB,UAAU,IAAI,MAAM;IAIpB,aAAa,IAAI,MAAM;CAgBxB"}
1
+ {"version":3,"file":"signer.d.ts","sourceRoot":"","sources":["../../src/lib/signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAmB,MAAM,EAAE,MAAM,QAAQ,CAAC;AACjD,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAE7D;;;GAGG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA6B;IACnD,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAqB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAa;gBAExB,MAAM,EAAE,UAAU;IAK9B,SAAS,IAAI,OAAO;IAIpB;;;OAGG;IACH,UAAU,IAAI,MAAM;IAKpB;;;OAGG;IACH,aAAa,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM;IAYvC,OAAO,CAAC,SAAS;CAMlB"}