dexe-mcp 0.5.8 → 0.7.0
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/CHANGELOG.md +707 -536
- package/README.md +291 -270
- package/SECURITY.md +100 -46
- package/dist/config.d.ts +19 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +79 -0
- package/dist/config.js.map +1 -1
- package/dist/governor/adapter.d.ts +90 -0
- package/dist/governor/adapter.d.ts.map +1 -0
- package/dist/governor/adapter.js +169 -0
- package/dist/governor/adapter.js.map +1 -0
- package/dist/governor/configs/compound.json +32 -0
- package/dist/governor/configs/optimism.json +28 -0
- package/dist/governor/configs/uniswap.json +32 -0
- package/dist/governor/encoder.d.ts +59 -0
- package/dist/governor/encoder.d.ts.map +1 -0
- package/dist/governor/encoder.js +290 -0
- package/dist/governor/encoder.js.map +1 -0
- package/dist/governor/index.d.ts +11 -0
- package/dist/governor/index.d.ts.map +1 -0
- package/dist/governor/index.js +20 -0
- package/dist/governor/index.js.map +1 -0
- package/dist/governor/loader.d.ts +42 -0
- package/dist/governor/loader.d.ts.map +1 -0
- package/dist/governor/loader.js +103 -0
- package/dist/governor/loader.js.map +1 -0
- package/dist/governor/tally.d.ts +48 -0
- package/dist/governor/tally.d.ts.map +1 -0
- package/dist/governor/tally.js +103 -0
- package/dist/governor/tally.js.map +1 -0
- package/dist/governor/tools/build.d.ts +3 -0
- package/dist/governor/tools/build.d.ts.map +1 -0
- package/dist/governor/tools/build.js +137 -0
- package/dist/governor/tools/build.js.map +1 -0
- package/dist/governor/tools/extras.d.ts +4 -0
- package/dist/governor/tools/extras.d.ts.map +1 -0
- package/dist/governor/tools/extras.js +197 -0
- package/dist/governor/tools/extras.js.map +1 -0
- package/dist/governor/tools/read.d.ts +4 -0
- package/dist/governor/tools/read.d.ts.map +1 -0
- package/dist/governor/tools/read.js +174 -0
- package/dist/governor/tools/read.js.map +1 -0
- package/dist/governor/tools/simulate.d.ts +6 -0
- package/dist/governor/tools/simulate.d.ts.map +1 -0
- package/dist/governor/tools/simulate.js +191 -0
- package/dist/governor/tools/simulate.js.map +1 -0
- package/dist/lib/broadcastGuards.d.ts +41 -0
- package/dist/lib/broadcastGuards.d.ts.map +1 -0
- package/dist/lib/broadcastGuards.js +85 -0
- package/dist/lib/broadcastGuards.js.map +1 -0
- package/dist/lib/ethersProvider.d.ts +96 -0
- package/dist/lib/ethersProvider.d.ts.map +1 -0
- package/dist/lib/ethersProvider.js +170 -0
- package/dist/lib/ethersProvider.js.map +1 -0
- package/dist/lib/signer.d.ts +2 -0
- package/dist/lib/signer.d.ts.map +1 -1
- package/dist/lib/signer.js +4 -0
- package/dist/lib/signer.js.map +1 -1
- package/dist/lib/walletconnect.d.ts +62 -0
- package/dist/lib/walletconnect.d.ts.map +1 -0
- package/dist/lib/walletconnect.js +184 -0
- package/dist/lib/walletconnect.js.map +1 -0
- package/dist/tools/flow.d.ts.map +1 -1
- package/dist/tools/flow.js +13 -0
- package/dist/tools/flow.js.map +1 -1
- package/dist/tools/getConfig.d.ts.map +1 -1
- package/dist/tools/getConfig.js +27 -0
- package/dist/tools/getConfig.js.map +1 -1
- package/dist/tools/inbox.js +8 -8
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +11 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/predict.js +17 -17
- package/dist/tools/safe.d.ts +5 -0
- package/dist/tools/safe.d.ts.map +1 -0
- package/dist/tools/safe.js +264 -0
- package/dist/tools/safe.js.map +1 -0
- package/dist/tools/simulate.d.ts +7 -0
- package/dist/tools/simulate.d.ts.map +1 -1
- package/dist/tools/simulate.js +8 -0
- package/dist/tools/simulate.js.map +1 -1
- package/dist/tools/subgraph.js +162 -162
- package/dist/tools/txSend.d.ts +2 -1
- package/dist/tools/txSend.d.ts.map +1 -1
- package/dist/tools/txSend.js +111 -3
- package/dist/tools/txSend.js.map +1 -1
- package/dist/tools/walletconnectStatus.d.ts +18 -0
- package/dist/tools/walletconnectStatus.d.ts.map +1 -0
- package/dist/tools/walletconnectStatus.js +132 -0
- package/dist/tools/walletconnectStatus.js.map +1 -0
- package/package.json +96 -92
package/dist/tools/subgraph.js
CHANGED
|
@@ -28,174 +28,174 @@ const ENV_HINT = {
|
|
|
28
28
|
subgraphInteractionsUrl: "DEXE_SUBGRAPH_INTERACTIONS_URL",
|
|
29
29
|
};
|
|
30
30
|
// ---------- queries ----------
|
|
31
|
-
const DAO_LIST_QUERY = /* GraphQL */ `
|
|
32
|
-
query getGovPoolsList($offset: Int!, $limit: Int!, $queryString: String!) {
|
|
33
|
-
daoPools(
|
|
34
|
-
skip: $offset
|
|
35
|
-
first: $limit
|
|
36
|
-
where: { name_contains_nocase: $queryString }
|
|
37
|
-
orderBy: votersCount
|
|
38
|
-
orderDirection: desc
|
|
39
|
-
) {
|
|
40
|
-
id
|
|
41
|
-
name
|
|
42
|
-
erc20Token
|
|
43
|
-
erc721Token
|
|
44
|
-
votersCount
|
|
45
|
-
proposalCount
|
|
46
|
-
totalCurrentTokenDelegated
|
|
47
|
-
totalCurrentTokenDelegatees
|
|
48
|
-
creationTime
|
|
49
|
-
creationBlock
|
|
50
|
-
}
|
|
51
|
-
}
|
|
31
|
+
const DAO_LIST_QUERY = /* GraphQL */ `
|
|
32
|
+
query getGovPoolsList($offset: Int!, $limit: Int!, $queryString: String!) {
|
|
33
|
+
daoPools(
|
|
34
|
+
skip: $offset
|
|
35
|
+
first: $limit
|
|
36
|
+
where: { name_contains_nocase: $queryString }
|
|
37
|
+
orderBy: votersCount
|
|
38
|
+
orderDirection: desc
|
|
39
|
+
) {
|
|
40
|
+
id
|
|
41
|
+
name
|
|
42
|
+
erc20Token
|
|
43
|
+
erc721Token
|
|
44
|
+
votersCount
|
|
45
|
+
proposalCount
|
|
46
|
+
totalCurrentTokenDelegated
|
|
47
|
+
totalCurrentTokenDelegatees
|
|
48
|
+
creationTime
|
|
49
|
+
creationBlock
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
52
|
`;
|
|
53
|
-
const DAO_MEMBERS_QUERY = /* GraphQL */ `
|
|
54
|
-
query getVotersInPool($poolId: String!, $offset: Int!, $limit: Int!) {
|
|
55
|
-
voterInPools(skip: $offset, first: $limit, where: { pool: $poolId }) {
|
|
56
|
-
id
|
|
57
|
-
APR
|
|
58
|
-
currentDelegateesCount
|
|
59
|
-
currentDelegatorsCount
|
|
60
|
-
engagedProposalsCount
|
|
61
|
-
joinedTimestamp
|
|
62
|
-
receivedDelegation
|
|
63
|
-
receivedNFTDelegation
|
|
64
|
-
receivedTreasuryDelegation
|
|
65
|
-
totalClaimedUSD
|
|
66
|
-
totalLockedUSD
|
|
67
|
-
totalPersonalVotingRewardUSD
|
|
68
|
-
totalMicropoolVotingRewardUSD
|
|
69
|
-
totalTreasuryVotingRewardUSD
|
|
70
|
-
expertNft {
|
|
71
|
-
id
|
|
72
|
-
tokenId
|
|
73
|
-
}
|
|
74
|
-
voter {
|
|
75
|
-
id
|
|
76
|
-
totalProposalsCreated
|
|
77
|
-
totalVotedProposals
|
|
78
|
-
totalVotes
|
|
79
|
-
currentVotesReceived
|
|
80
|
-
currentVotesDelegated
|
|
81
|
-
totalClaimedUSD
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
}
|
|
53
|
+
const DAO_MEMBERS_QUERY = /* GraphQL */ `
|
|
54
|
+
query getVotersInPool($poolId: String!, $offset: Int!, $limit: Int!) {
|
|
55
|
+
voterInPools(skip: $offset, first: $limit, where: { pool: $poolId }) {
|
|
56
|
+
id
|
|
57
|
+
APR
|
|
58
|
+
currentDelegateesCount
|
|
59
|
+
currentDelegatorsCount
|
|
60
|
+
engagedProposalsCount
|
|
61
|
+
joinedTimestamp
|
|
62
|
+
receivedDelegation
|
|
63
|
+
receivedNFTDelegation
|
|
64
|
+
receivedTreasuryDelegation
|
|
65
|
+
totalClaimedUSD
|
|
66
|
+
totalLockedUSD
|
|
67
|
+
totalPersonalVotingRewardUSD
|
|
68
|
+
totalMicropoolVotingRewardUSD
|
|
69
|
+
totalTreasuryVotingRewardUSD
|
|
70
|
+
expertNft {
|
|
71
|
+
id
|
|
72
|
+
tokenId
|
|
73
|
+
}
|
|
74
|
+
voter {
|
|
75
|
+
id
|
|
76
|
+
totalProposalsCreated
|
|
77
|
+
totalVotedProposals
|
|
78
|
+
totalVotes
|
|
79
|
+
currentVotesReceived
|
|
80
|
+
currentVotesDelegated
|
|
81
|
+
totalClaimedUSD
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
85
|
`;
|
|
86
|
-
const DELEGATION_MAP_QUERY = /* GraphQL */ `
|
|
87
|
-
query getDefaultDelegationsFromPool($offset: Int!, $limit: Int!, $delegatorIn: [String!]) {
|
|
88
|
-
voterInPoolPairs(
|
|
89
|
-
skip: $offset
|
|
90
|
-
first: $limit
|
|
91
|
-
where: { delegator_: { voter_in: $delegatorIn } }
|
|
92
|
-
) {
|
|
93
|
-
id
|
|
94
|
-
creationTimestamp
|
|
95
|
-
delegatedAmount
|
|
96
|
-
delegatedNfts
|
|
97
|
-
delegatedUSD
|
|
98
|
-
delegatedVotes
|
|
99
|
-
delegatee {
|
|
100
|
-
expertNft {
|
|
101
|
-
id
|
|
102
|
-
}
|
|
103
|
-
voter {
|
|
104
|
-
id
|
|
105
|
-
}
|
|
106
|
-
totalClaimedUSD
|
|
107
|
-
}
|
|
108
|
-
delegator {
|
|
109
|
-
voter {
|
|
110
|
-
id
|
|
111
|
-
}
|
|
112
|
-
pool {
|
|
113
|
-
id
|
|
114
|
-
erc20Token
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
86
|
+
const DELEGATION_MAP_QUERY = /* GraphQL */ `
|
|
87
|
+
query getDefaultDelegationsFromPool($offset: Int!, $limit: Int!, $delegatorIn: [String!]) {
|
|
88
|
+
voterInPoolPairs(
|
|
89
|
+
skip: $offset
|
|
90
|
+
first: $limit
|
|
91
|
+
where: { delegator_: { voter_in: $delegatorIn } }
|
|
92
|
+
) {
|
|
93
|
+
id
|
|
94
|
+
creationTimestamp
|
|
95
|
+
delegatedAmount
|
|
96
|
+
delegatedNfts
|
|
97
|
+
delegatedUSD
|
|
98
|
+
delegatedVotes
|
|
99
|
+
delegatee {
|
|
100
|
+
expertNft {
|
|
101
|
+
id
|
|
102
|
+
}
|
|
103
|
+
voter {
|
|
104
|
+
id
|
|
105
|
+
}
|
|
106
|
+
totalClaimedUSD
|
|
107
|
+
}
|
|
108
|
+
delegator {
|
|
109
|
+
voter {
|
|
110
|
+
id
|
|
111
|
+
}
|
|
112
|
+
pool {
|
|
113
|
+
id
|
|
114
|
+
erc20Token
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
119
|
`;
|
|
120
|
-
const DELEGATION_INCOMING_QUERY = /* GraphQL */ `
|
|
121
|
-
query getPoolIncomingDelegations($offset: Int!, $limit: Int!, $voterIn: [String!]) {
|
|
122
|
-
voterInPoolPairs(
|
|
123
|
-
skip: $offset
|
|
124
|
-
first: $limit
|
|
125
|
-
where: { delegatee_: { voter_in: $voterIn } }
|
|
126
|
-
) {
|
|
127
|
-
id
|
|
128
|
-
delegatedAmount
|
|
129
|
-
delegatedNfts
|
|
130
|
-
delegatedUSD
|
|
131
|
-
delegatedVotes
|
|
132
|
-
delegator {
|
|
133
|
-
voter {
|
|
134
|
-
id
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
delegatee {
|
|
138
|
-
voter {
|
|
139
|
-
id
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
}
|
|
120
|
+
const DELEGATION_INCOMING_QUERY = /* GraphQL */ `
|
|
121
|
+
query getPoolIncomingDelegations($offset: Int!, $limit: Int!, $voterIn: [String!]) {
|
|
122
|
+
voterInPoolPairs(
|
|
123
|
+
skip: $offset
|
|
124
|
+
first: $limit
|
|
125
|
+
where: { delegatee_: { voter_in: $voterIn } }
|
|
126
|
+
) {
|
|
127
|
+
id
|
|
128
|
+
delegatedAmount
|
|
129
|
+
delegatedNfts
|
|
130
|
+
delegatedUSD
|
|
131
|
+
delegatedVotes
|
|
132
|
+
delegator {
|
|
133
|
+
voter {
|
|
134
|
+
id
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
delegatee {
|
|
138
|
+
voter {
|
|
139
|
+
id
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
144
|
`;
|
|
145
|
-
const VALIDATORS_QUERY = /* GraphQL */ `
|
|
146
|
-
query getDaoPoolValidators($offset: Int!, $limit: Int!, $address: String!) {
|
|
147
|
-
validatorInPools(
|
|
148
|
-
skip: $offset
|
|
149
|
-
first: $limit
|
|
150
|
-
orderBy: balance
|
|
151
|
-
orderDirection: desc
|
|
152
|
-
where: { pool: $address }
|
|
153
|
-
) {
|
|
154
|
-
id
|
|
155
|
-
balance
|
|
156
|
-
validatorAddress
|
|
157
|
-
}
|
|
158
|
-
}
|
|
145
|
+
const VALIDATORS_QUERY = /* GraphQL */ `
|
|
146
|
+
query getDaoPoolValidators($offset: Int!, $limit: Int!, $address: String!) {
|
|
147
|
+
validatorInPools(
|
|
148
|
+
skip: $offset
|
|
149
|
+
first: $limit
|
|
150
|
+
orderBy: balance
|
|
151
|
+
orderDirection: desc
|
|
152
|
+
where: { pool: $address }
|
|
153
|
+
) {
|
|
154
|
+
id
|
|
155
|
+
balance
|
|
156
|
+
validatorAddress
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
159
|
`;
|
|
160
|
-
const USER_ACTIVITY_QUERY = /* GraphQL */ `
|
|
161
|
-
query getUserTransactions($offset: Int!, $limit: Int!, $address: Bytes!) {
|
|
162
|
-
transactions(
|
|
163
|
-
skip: $offset
|
|
164
|
-
first: $limit
|
|
165
|
-
where: { user: $address }
|
|
166
|
-
orderBy: timestamp
|
|
167
|
-
orderDirection: desc
|
|
168
|
-
) {
|
|
169
|
-
id
|
|
170
|
-
type
|
|
171
|
-
user
|
|
172
|
-
timestamp
|
|
173
|
-
interactionsCount
|
|
174
|
-
}
|
|
175
|
-
}
|
|
160
|
+
const USER_ACTIVITY_QUERY = /* GraphQL */ `
|
|
161
|
+
query getUserTransactions($offset: Int!, $limit: Int!, $address: Bytes!) {
|
|
162
|
+
transactions(
|
|
163
|
+
skip: $offset
|
|
164
|
+
first: $limit
|
|
165
|
+
where: { user: $address }
|
|
166
|
+
orderBy: timestamp
|
|
167
|
+
orderDirection: desc
|
|
168
|
+
) {
|
|
169
|
+
id
|
|
170
|
+
type
|
|
171
|
+
user
|
|
172
|
+
timestamp
|
|
173
|
+
interactionsCount
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
176
|
`;
|
|
177
|
-
const EXPERTS_QUERY = /* GraphQL */ `
|
|
178
|
-
query getLocalExpertsByPool($offset: Int!, $limit: Int!, $daoAddress: Bytes!) {
|
|
179
|
-
voterInPools(
|
|
180
|
-
skip: $offset
|
|
181
|
-
first: $limit
|
|
182
|
-
where: { pool_: { id: $daoAddress }, expertNft_: { id_not: null } }
|
|
183
|
-
) {
|
|
184
|
-
id
|
|
185
|
-
receivedTreasuryDelegation
|
|
186
|
-
receivedDelegation
|
|
187
|
-
voter {
|
|
188
|
-
id
|
|
189
|
-
}
|
|
190
|
-
expertNft {
|
|
191
|
-
id
|
|
192
|
-
tokenId
|
|
193
|
-
}
|
|
194
|
-
pool {
|
|
195
|
-
id
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
|
-
}
|
|
177
|
+
const EXPERTS_QUERY = /* GraphQL */ `
|
|
178
|
+
query getLocalExpertsByPool($offset: Int!, $limit: Int!, $daoAddress: Bytes!) {
|
|
179
|
+
voterInPools(
|
|
180
|
+
skip: $offset
|
|
181
|
+
first: $limit
|
|
182
|
+
where: { pool_: { id: $daoAddress }, expertNft_: { id_not: null } }
|
|
183
|
+
) {
|
|
184
|
+
id
|
|
185
|
+
receivedTreasuryDelegation
|
|
186
|
+
receivedDelegation
|
|
187
|
+
voter {
|
|
188
|
+
id
|
|
189
|
+
}
|
|
190
|
+
expertNft {
|
|
191
|
+
id
|
|
192
|
+
tokenId
|
|
193
|
+
}
|
|
194
|
+
pool {
|
|
195
|
+
id
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
199
|
`;
|
|
200
200
|
// ---------- register ----------
|
|
201
201
|
export function registerSubgraphTools(server, ctx) {
|
package/dist/tools/txSend.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import type { SignerManager } from "../lib/signer.js";
|
|
3
|
+
import type { WalletConnectManager } from "../lib/walletconnect.js";
|
|
3
4
|
import { type DexeConfig } from "../config.js";
|
|
4
|
-
export declare function registerTxTools(server: McpServer, config: DexeConfig, signer: SignerManager): void;
|
|
5
|
+
export declare function registerTxTools(server: McpServer, config: DexeConfig, signer: SignerManager, wc: WalletConnectManager): void;
|
|
5
6
|
//# sourceMappingURL=txSend.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"txSend.d.ts","sourceRoot":"","sources":["../../src/tools/txSend.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"txSend.d.ts","sourceRoot":"","sources":["../../src/tools/txSend.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAgB,KAAK,UAAU,EAAE,MAAM,cAAc,CAAC;AAG7D,wBAAgB,eAAe,CAC7B,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,aAAa,EACrB,EAAE,EAAE,oBAAoB,GACvB,IAAI,CAkRN"}
|
package/dist/tools/txSend.js
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
|
+
import { JsonRpcProvider } from "ethers";
|
|
2
3
|
import { resolveChain } from "../config.js";
|
|
3
|
-
|
|
4
|
+
import { runBroadcastGuards, BroadcastGuardError } from "../lib/broadcastGuards.js";
|
|
5
|
+
export function registerTxTools(server, config, signer, wc) {
|
|
6
|
+
// WalletConnect is the dispatch path only when there is no hot key to sign with.
|
|
7
|
+
const wcActive = () => !signer.hasSigner() && wc.isConfigured();
|
|
4
8
|
server.tool("dexe_tx_send", "Sign and broadcast a transaction using the configured DEXE_PRIVATE_KEY. " +
|
|
5
9
|
"Pass the TxPayload fields returned by any dexe_*_build_* tool. " +
|
|
6
10
|
"Waits for on-chain confirmation and returns the receipt. " +
|
|
@@ -30,7 +34,110 @@ export function registerTxTools(server, config, signer) {
|
|
|
30
34
|
.describe("Confirmations to wait (0 = fire-and-forget)"),
|
|
31
35
|
}, async ({ to, data, value, chainId, gasLimit, waitConfirmations }) => {
|
|
32
36
|
const chain = resolveChain(config, chainId);
|
|
37
|
+
// ---- WalletConnect dispatch path (no hot key) ----------------------
|
|
38
|
+
// The phone wallet signs AND broadcasts; we only see the hash. Guards
|
|
39
|
+
// (B6/B7/B9/B10) still run, keyed on the connected account as `from`.
|
|
40
|
+
if (wcActive()) {
|
|
41
|
+
if (!wc.isConnected()) {
|
|
42
|
+
return {
|
|
43
|
+
content: [
|
|
44
|
+
{
|
|
45
|
+
type: "text",
|
|
46
|
+
text: JSON.stringify({
|
|
47
|
+
status: "rejected",
|
|
48
|
+
reason: "WalletConnect mode is active but no session is connected. Call dexe_wc_connect and approve on your phone first.",
|
|
49
|
+
chainId: chain.chainId,
|
|
50
|
+
}, null, 2),
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
isError: true,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
const from = wc.account();
|
|
57
|
+
try {
|
|
58
|
+
await runBroadcastGuards({ to, data, value, chainId: chain.chainId, from }, config);
|
|
59
|
+
}
|
|
60
|
+
catch (e) {
|
|
61
|
+
if (e instanceof BroadcastGuardError) {
|
|
62
|
+
return {
|
|
63
|
+
content: [
|
|
64
|
+
{
|
|
65
|
+
type: "text",
|
|
66
|
+
text: JSON.stringify({ status: "rejected", guard: e.guard, reason: e.message, chainId: chain.chainId }, null, 2),
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
isError: true,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
throw e;
|
|
73
|
+
}
|
|
74
|
+
let txHash;
|
|
75
|
+
try {
|
|
76
|
+
txHash = await wc.sendTransaction({ to, data, value, chainId: chain.chainId, gasLimit });
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
return {
|
|
80
|
+
content: [
|
|
81
|
+
{
|
|
82
|
+
type: "text",
|
|
83
|
+
text: JSON.stringify({ status: "rejected", reason: e instanceof Error ? e.message : String(e), chainId: chain.chainId }, null, 2),
|
|
84
|
+
},
|
|
85
|
+
],
|
|
86
|
+
isError: true,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
if (waitConfirmations === 0) {
|
|
90
|
+
return {
|
|
91
|
+
content: [
|
|
92
|
+
{
|
|
93
|
+
type: "text",
|
|
94
|
+
text: JSON.stringify({ txHash, from, chainId: chain.chainId, signer: "walletconnect", status: "submitted" }, null, 2),
|
|
95
|
+
},
|
|
96
|
+
],
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
// Wait via a read provider — WC returned the hash, the wallet broadcast it.
|
|
100
|
+
const provider = new JsonRpcProvider(chain.rpcUrl);
|
|
101
|
+
const receipt = await provider.waitForTransaction(txHash, waitConfirmations);
|
|
102
|
+
const result = receipt
|
|
103
|
+
? {
|
|
104
|
+
txHash: receipt.hash,
|
|
105
|
+
from,
|
|
106
|
+
chainId: chain.chainId,
|
|
107
|
+
signer: "walletconnect",
|
|
108
|
+
blockNumber: receipt.blockNumber,
|
|
109
|
+
gasUsed: receipt.gasUsed.toString(),
|
|
110
|
+
status: receipt.status,
|
|
111
|
+
}
|
|
112
|
+
: { txHash, from, chainId: chain.chainId, signer: "walletconnect", status: "unknown" };
|
|
113
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
114
|
+
}
|
|
115
|
+
// ---- hot-key (EOA) dispatch path -----------------------------------
|
|
33
116
|
const wallet = signer.requireSigner(chain.chainId);
|
|
117
|
+
// Signer broadcast guards (B6/B7/B9/B10) — no-ops unless their env vars
|
|
118
|
+
// are set. Run before spending any gas.
|
|
119
|
+
try {
|
|
120
|
+
await runBroadcastGuards({ to, data, value, chainId: chain.chainId, from: wallet.address }, config);
|
|
121
|
+
}
|
|
122
|
+
catch (e) {
|
|
123
|
+
if (e instanceof BroadcastGuardError) {
|
|
124
|
+
return {
|
|
125
|
+
content: [
|
|
126
|
+
{
|
|
127
|
+
type: "text",
|
|
128
|
+
text: JSON.stringify({
|
|
129
|
+
status: "rejected",
|
|
130
|
+
guard: e.guard,
|
|
131
|
+
reason: e.message,
|
|
132
|
+
chainId: chain.chainId,
|
|
133
|
+
}, null, 2),
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
isError: true,
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
throw e;
|
|
140
|
+
}
|
|
34
141
|
const tx = await wallet.sendTransaction({
|
|
35
142
|
to,
|
|
36
143
|
data,
|
|
@@ -86,8 +193,9 @@ export function registerTxTools(server, config, signer) {
|
|
|
86
193
|
.describe("Chain id to look up the receipt on. Defaults to the MCP's default chain."),
|
|
87
194
|
}, async ({ txHash, chainId }) => {
|
|
88
195
|
const chain = resolveChain(config, chainId);
|
|
89
|
-
|
|
90
|
-
|
|
196
|
+
// Read-only lookup — no signer needed, so this works in WalletConnect/
|
|
197
|
+
// readonly modes too.
|
|
198
|
+
const provider = new JsonRpcProvider(chain.rpcUrl);
|
|
91
199
|
const receipt = await provider.getTransactionReceipt(txHash);
|
|
92
200
|
if (!receipt) {
|
|
93
201
|
return {
|
package/dist/tools/txSend.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"txSend.js","sourceRoot":"","sources":["../../src/tools/txSend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"txSend.js","sourceRoot":"","sources":["../../src/tools/txSend.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
|
+
import type { DexeConfig } from "../config.js";
|
|
3
|
+
import type { SignerManager } from "../lib/signer.js";
|
|
4
|
+
import type { WalletConnectManager } from "../lib/walletconnect.js";
|
|
5
|
+
/**
|
|
6
|
+
* C12 — WalletConnect tools.
|
|
7
|
+
*
|
|
8
|
+
* Phase A shipped `dexe_wc_status` as a config echo. Phase B adds the live relay
|
|
9
|
+
* session: `dexe_wc_connect` (returns a pairing URI for the phone to scan) and
|
|
10
|
+
* `dexe_wc_disconnect`, and `dexe_wc_status` now reports the live session state.
|
|
11
|
+
*
|
|
12
|
+
* WalletConnect activates as the signer only when DEXE_WALLETCONNECT_PROJECT_ID
|
|
13
|
+
* is set AND no DEXE_PRIVATE_KEY is present (a hot key, or Safe, takes
|
|
14
|
+
* precedence). When active, `dexe_tx_send` forwards every tx to the phone wallet
|
|
15
|
+
* for approval — the wallet signs and broadcasts, so no key ever enters the MCP.
|
|
16
|
+
*/
|
|
17
|
+
export declare function registerWalletConnectTools(server: McpServer, config: DexeConfig, signer: SignerManager, wc: WalletConnectManager): void;
|
|
18
|
+
//# sourceMappingURL=walletconnectStatus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"walletconnectStatus.d.ts","sourceRoot":"","sources":["../../src/tools/walletconnectStatus.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACzE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,yBAAyB,CAAC;AAEpE;;;;;;;;;;;GAWG;AACH,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,SAAS,EACjB,MAAM,EAAE,UAAU,EAClB,MAAM,EAAE,aAAa,EACrB,EAAE,EAAE,oBAAoB,GACvB,IAAI,CAwJN"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
/**
|
|
3
|
+
* C12 — WalletConnect tools.
|
|
4
|
+
*
|
|
5
|
+
* Phase A shipped `dexe_wc_status` as a config echo. Phase B adds the live relay
|
|
6
|
+
* session: `dexe_wc_connect` (returns a pairing URI for the phone to scan) and
|
|
7
|
+
* `dexe_wc_disconnect`, and `dexe_wc_status` now reports the live session state.
|
|
8
|
+
*
|
|
9
|
+
* WalletConnect activates as the signer only when DEXE_WALLETCONNECT_PROJECT_ID
|
|
10
|
+
* is set AND no DEXE_PRIVATE_KEY is present (a hot key, or Safe, takes
|
|
11
|
+
* precedence). When active, `dexe_tx_send` forwards every tx to the phone wallet
|
|
12
|
+
* for approval — the wallet signs and broadcasts, so no key ever enters the MCP.
|
|
13
|
+
*/
|
|
14
|
+
export function registerWalletConnectTools(server, config, signer, wc) {
|
|
15
|
+
const resolveSignerMode = () => {
|
|
16
|
+
const safeServiceUrl = process.env.DEXE_SAFE_TX_SERVICE_URL?.trim() || undefined;
|
|
17
|
+
return signer.hasSigner()
|
|
18
|
+
? safeServiceUrl
|
|
19
|
+
? "safe"
|
|
20
|
+
: "eoa"
|
|
21
|
+
: wc.isConfigured()
|
|
22
|
+
? "walletconnect"
|
|
23
|
+
: "readonly";
|
|
24
|
+
};
|
|
25
|
+
server.tool("dexe_wc_status", "Diagnostic: returns the resolved WalletConnect config plus the live session state " +
|
|
26
|
+
"(connected?, account, chain, topic, peer wallet, last error). Read-only. WalletConnect " +
|
|
27
|
+
"activates only when DEXE_WALLETCONNECT_PROJECT_ID is set AND no DEXE_PRIVATE_KEY is present.", {
|
|
28
|
+
chainId: z.number().int().positive().optional().describe("Unused; reserved."),
|
|
29
|
+
}, async () => {
|
|
30
|
+
const signerMode = resolveSignerMode();
|
|
31
|
+
const session = wc.status();
|
|
32
|
+
const result = {
|
|
33
|
+
signerMode,
|
|
34
|
+
active: signerMode === "walletconnect",
|
|
35
|
+
projectIdConfigured: wc.isConfigured(),
|
|
36
|
+
relayUrl: config.walletConnectRelayUrl ?? null,
|
|
37
|
+
approvalTimeoutMs: config.walletConnectApprovalTimeoutMs ?? null,
|
|
38
|
+
session,
|
|
39
|
+
note: !wc.isConfigured()
|
|
40
|
+
? "No DEXE_WALLETCONNECT_PROJECT_ID set. Get a free id at https://cloud.reown.com to enable WalletConnect mode."
|
|
41
|
+
: signerMode !== "walletconnect"
|
|
42
|
+
? "WalletConnect project id is set but inactive — DEXE_PRIVATE_KEY (or Safe) takes precedence."
|
|
43
|
+
: session.connected
|
|
44
|
+
? "Connected. dexe_tx_send will forward transactions to the phone wallet for approval."
|
|
45
|
+
: session.connecting
|
|
46
|
+
? "Pairing in progress — approve the session on your phone, then re-check status."
|
|
47
|
+
: "WalletConnect is the active signer mode. Call dexe_wc_connect to start a phone session.",
|
|
48
|
+
};
|
|
49
|
+
return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }] };
|
|
50
|
+
});
|
|
51
|
+
server.tool("dexe_wc_connect", "Start a WalletConnect session. Returns a pairing URI to render as a QR code or paste into " +
|
|
52
|
+
"the phone wallet (MetaMask / Trust / Rainbow). The session is approved on the phone; this " +
|
|
53
|
+
"tool returns as soon as the URI is ready — poll dexe_wc_status until `connected` is true. " +
|
|
54
|
+
"Requires WalletConnect to be the active signerMode (project id set, no private key).", {
|
|
55
|
+
chainId: z
|
|
56
|
+
.number()
|
|
57
|
+
.int()
|
|
58
|
+
.positive()
|
|
59
|
+
.optional()
|
|
60
|
+
.describe("Chain to request in the session namespace. Defaults to the MCP's default chain."),
|
|
61
|
+
}, async ({ chainId }) => {
|
|
62
|
+
if (!wc.isConfigured()) {
|
|
63
|
+
return {
|
|
64
|
+
content: [
|
|
65
|
+
{
|
|
66
|
+
type: "text",
|
|
67
|
+
text: JSON.stringify({
|
|
68
|
+
status: "error",
|
|
69
|
+
reason: "WalletConnect not configured. Set DEXE_WALLETCONNECT_PROJECT_ID (https://cloud.reown.com).",
|
|
70
|
+
}, null, 2),
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
isError: true,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
if (signer.hasSigner()) {
|
|
77
|
+
return {
|
|
78
|
+
content: [
|
|
79
|
+
{
|
|
80
|
+
type: "text",
|
|
81
|
+
text: JSON.stringify({
|
|
82
|
+
status: "error",
|
|
83
|
+
reason: "DEXE_PRIVATE_KEY is set, so WalletConnect is inactive (hot key takes precedence). Unset the key to use WalletConnect mode.",
|
|
84
|
+
}, null, 2),
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
isError: true,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
try {
|
|
91
|
+
const { uri, chainId: resolved } = await wc.connect(chainId);
|
|
92
|
+
return {
|
|
93
|
+
content: [
|
|
94
|
+
{
|
|
95
|
+
type: "text",
|
|
96
|
+
text: JSON.stringify({
|
|
97
|
+
status: "pairing",
|
|
98
|
+
uri,
|
|
99
|
+
chainId: resolved,
|
|
100
|
+
next: "Render `uri` as a QR (e.g. https://api.qrserver.com/v1/create-qr-code/?data=<uri>) or paste into the wallet, approve, then poll dexe_wc_status.",
|
|
101
|
+
}, null, 2),
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
return {
|
|
108
|
+
content: [
|
|
109
|
+
{
|
|
110
|
+
type: "text",
|
|
111
|
+
text: JSON.stringify({ status: "error", reason: e instanceof Error ? e.message : String(e) }, null, 2),
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
isError: true,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
server.tool("dexe_wc_disconnect", "Tear down the active WalletConnect session. Safe to call when not connected (returns disconnected:false).", {
|
|
119
|
+
_placeholder: z.boolean().optional().describe("Unused; tool takes no input."),
|
|
120
|
+
}, async () => {
|
|
121
|
+
const disconnected = await wc.disconnect();
|
|
122
|
+
return {
|
|
123
|
+
content: [
|
|
124
|
+
{
|
|
125
|
+
type: "text",
|
|
126
|
+
text: JSON.stringify({ status: "ok", disconnected }, null, 2),
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
};
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=walletconnectStatus.js.map
|