@conquest-eth/tools 0.0.0 → 0.0.2
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/README.md +20 -51
- package/dist/cli-tool-generator.d.ts +2 -1
- package/dist/cli-tool-generator.d.ts.map +1 -1
- package/dist/cli.js +61 -32
- package/dist/cli.js.map +1 -1
- package/dist/contracts/space-info.d.ts.map +1 -1
- package/dist/contracts/space-info.js +22 -1
- package/dist/contracts/space-info.js.map +1 -1
- package/dist/fleet/resolve.d.ts +1 -1
- package/dist/fleet/resolve.d.ts.map +1 -1
- package/dist/fleet/resolve.js +5 -4
- package/dist/fleet/resolve.js.map +1 -1
- package/dist/fleet/send.d.ts.map +1 -1
- package/dist/fleet/send.js +8 -8
- package/dist/fleet/send.js.map +1 -1
- package/dist/index.d.ts +6 -32
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -128
- package/dist/index.js.map +1 -1
- package/dist/mcp.d.ts +14 -0
- package/dist/mcp.d.ts.map +1 -0
- package/dist/mcp.js +29 -0
- package/dist/mcp.js.map +1 -0
- package/dist/planet/acquire.d.ts +3 -2
- package/dist/planet/acquire.d.ts.map +1 -1
- package/dist/planet/acquire.js +6 -4
- package/dist/planet/acquire.js.map +1 -1
- package/dist/planet/exit.d.ts.map +1 -1
- package/dist/planet/exit.js +1 -0
- package/dist/planet/exit.js.map +1 -1
- package/dist/planet/manager.d.ts +63 -0
- package/dist/planet/manager.d.ts.map +1 -1
- package/dist/planet/manager.js +125 -2
- package/dist/planet/manager.js.map +1 -1
- package/dist/planet/withdraw.d.ts +17 -0
- package/dist/planet/withdraw.d.ts.map +1 -0
- package/dist/planet/withdraw.js +25 -0
- package/dist/planet/withdraw.js.map +1 -0
- package/dist/storage/interface.d.ts +6 -0
- package/dist/storage/interface.d.ts.map +1 -1
- package/dist/storage/json-storage.d.ts +1 -0
- package/dist/storage/json-storage.d.ts.map +1 -1
- package/dist/storage/json-storage.js +10 -1
- package/dist/storage/json-storage.js.map +1 -1
- package/dist/tool-handling/cli-tool-generator.d.ts +22 -0
- package/dist/tool-handling/cli-tool-generator.d.ts.map +1 -0
- package/dist/tool-handling/cli-tool-generator.js +345 -0
- package/dist/tool-handling/cli-tool-generator.js.map +1 -0
- package/dist/tool-handling/cli.d.ts +19 -0
- package/dist/tool-handling/cli.d.ts.map +1 -0
- package/dist/tool-handling/cli.js +472 -0
- package/dist/tool-handling/cli.js.map +1 -0
- package/dist/tool-handling/index.d.ts +15 -0
- package/dist/tool-handling/index.d.ts.map +1 -0
- package/dist/tool-handling/index.js +32 -0
- package/dist/tool-handling/index.js.map +1 -0
- package/dist/tool-handling/mcp.d.ts +22 -0
- package/dist/tool-handling/mcp.d.ts.map +1 -0
- package/dist/tool-handling/mcp.js +88 -0
- package/dist/tool-handling/mcp.js.map +1 -0
- package/dist/tool-handling/types.d.ts +72 -0
- package/dist/tool-handling/types.d.ts.map +1 -0
- package/dist/tool-handling/types.js +10 -0
- package/dist/tool-handling/types.js.map +1 -0
- package/dist/tools/acquire_planets.d.ts +7 -5
- package/dist/tools/acquire_planets.d.ts.map +1 -1
- package/dist/tools/acquire_planets.js +28 -42
- package/dist/tools/acquire_planets.js.map +1 -1
- package/dist/tools/exit_planets.d.ts +7 -3
- package/dist/tools/exit_planets.d.ts.map +1 -1
- package/dist/tools/exit_planets.js +20 -9
- package/dist/tools/exit_planets.js.map +1 -1
- package/dist/tools/get_my_planets.d.ts +3 -2
- package/dist/tools/get_my_planets.d.ts.map +1 -1
- package/dist/tools/get_my_planets.js +5 -4
- package/dist/tools/get_my_planets.js.map +1 -1
- package/dist/tools/get_native_token_balance.d.ts +6 -0
- package/dist/tools/get_native_token_balance.d.ts.map +1 -0
- package/dist/tools/get_native_token_balance.js +64 -0
- package/dist/tools/get_native_token_balance.js.map +1 -0
- package/dist/tools/get_pending_exits.d.ts +2 -1
- package/dist/tools/get_pending_exits.d.ts.map +1 -1
- package/dist/tools/get_pending_exits.js +5 -4
- package/dist/tools/get_pending_exits.js.map +1 -1
- package/dist/tools/get_pending_fleets.d.ts +2 -1
- package/dist/tools/get_pending_fleets.d.ts.map +1 -1
- package/dist/tools/get_pending_fleets.js +5 -4
- package/dist/tools/get_pending_fleets.js.map +1 -1
- package/dist/tools/get_planets_around.d.ts +8 -4
- package/dist/tools/get_planets_around.d.ts.map +1 -1
- package/dist/tools/get_planets_around.js +40 -15
- package/dist/tools/get_planets_around.js.map +1 -1
- package/dist/tools/get_play_token_balance.d.ts +6 -0
- package/dist/tools/get_play_token_balance.d.ts.map +1 -0
- package/dist/tools/get_play_token_balance.js +80 -0
- package/dist/tools/get_play_token_balance.js.map +1 -0
- package/dist/tools/index.d.ts +7 -1
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +7 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/missiv_get_user.d.ts +6 -0
- package/dist/tools/missiv_get_user.d.ts.map +1 -0
- package/dist/tools/missiv_get_user.js +50 -0
- package/dist/tools/missiv_get_user.js.map +1 -0
- package/dist/tools/missiv_register.d.ts +6 -0
- package/dist/tools/missiv_register.d.ts.map +1 -0
- package/dist/tools/missiv_register.js +103 -0
- package/dist/tools/missiv_register.js.map +1 -0
- package/dist/tools/resolve_fleet.d.ts +3 -2
- package/dist/tools/resolve_fleet.d.ts.map +1 -1
- package/dist/tools/resolve_fleet.js +5 -4
- package/dist/tools/resolve_fleet.js.map +1 -1
- package/dist/tools/send_fleet.d.ts +3 -2
- package/dist/tools/send_fleet.d.ts.map +1 -1
- package/dist/tools/send_fleet.js +16 -15
- package/dist/tools/send_fleet.js.map +1 -1
- package/dist/tools/simulate.d.ts +14 -0
- package/dist/tools/simulate.d.ts.map +1 -0
- package/dist/tools/simulate.js +123 -0
- package/dist/tools/simulate.js.map +1 -0
- package/dist/tools/simulate_multiple.d.ts +17 -0
- package/dist/tools/simulate_multiple.d.ts.map +1 -0
- package/dist/tools/simulate_multiple.js +166 -0
- package/dist/tools/simulate_multiple.js.map +1 -0
- package/dist/tools/verify_exit_status.d.ts +5 -3
- package/dist/tools/verify_exit_status.d.ts.map +1 -1
- package/dist/tools/verify_exit_status.js +12 -8
- package/dist/tools/verify_exit_status.js.map +1 -1
- package/dist/tools/withdraw.d.ts +9 -0
- package/dist/tools/withdraw.d.ts.map +1 -0
- package/dist/tools/withdraw.js +86 -0
- package/dist/tools/withdraw.js.map +1 -0
- package/dist/types.d.ts +31 -28
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -33
- package/dist/types.js.map +1 -1
- package/dist/util/time.d.ts +0 -30
- package/dist/util/time.d.ts.map +1 -1
- package/dist/util/time.js +0 -36
- package/dist/util/time.js.map +1 -1
- package/package.json +80 -77
- package/src/cli.ts +88 -59
- package/src/contracts/space-info.ts +24 -1
- package/src/fleet/resolve.ts +5 -4
- package/src/fleet/send.ts +9 -8
- package/src/index.ts +28 -162
- package/src/mcp.ts +46 -0
- package/src/planet/acquire.ts +6 -6
- package/src/planet/exit.ts +1 -0
- package/src/planet/manager.ts +163 -0
- package/src/planet/withdraw.ts +33 -0
- package/src/storage/interface.ts +7 -0
- package/src/storage/json-storage.ts +11 -1
- package/src/tool-handling/cli.ts +559 -0
- package/src/tool-handling/index.ts +45 -0
- package/src/tool-handling/mcp.ts +127 -0
- package/src/tool-handling/types.ts +86 -0
- package/src/tools/acquire_planets.ts +34 -60
- package/src/tools/exit_planets.ts +25 -12
- package/src/tools/get_native_token_balance.ts +72 -0
- package/src/tools/get_pending_exits.ts +8 -5
- package/src/tools/get_pending_fleets.ts +8 -5
- package/src/tools/get_planets_around.ts +45 -16
- package/src/tools/get_play_token_balance.ts +90 -0
- package/src/tools/index.ts +7 -1
- package/src/tools/missiv_get_user.ts +68 -0
- package/src/tools/missiv_register.ts +122 -0
- package/src/tools/resolve_fleet.ts +8 -5
- package/src/tools/send_fleet.ts +21 -18
- package/src/tools/simulate.ts +141 -0
- package/src/tools/simulate_multiple.ts +197 -0
- package/src/tools/verify_exit_status.ts +15 -11
- package/src/tools/withdraw.ts +100 -0
- package/src/types.ts +33 -71
- package/src/util/time.ts +0 -46
- package/src/cli-tool-generator.ts +0 -287
- package/src/helpers/index.ts +0 -59
- package/src/tools/get_my_planets.ts +0 -30
package/package.json
CHANGED
|
@@ -1,78 +1,81 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
2
|
+
"name": "@conquest-eth/tools",
|
|
3
|
+
"version": "0.0.2",
|
|
4
|
+
"description": "Tools for Conquest.eth, including mcp server",
|
|
5
|
+
"author": "Ronan Sandford",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"mcp",
|
|
9
|
+
"ethereum",
|
|
10
|
+
"tools",
|
|
11
|
+
"cli",
|
|
12
|
+
"conquest.eth"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "git+https://github.com/wighawag/tools-conquest-eth-v0.git"
|
|
17
|
+
},
|
|
18
|
+
"homepage": "https://github.com/wighawag/tools-conquest-eth-v0#readme",
|
|
19
|
+
"bugs": {
|
|
20
|
+
"url": "https://github.com/wighawag/tools-conquest-eth-v0/issues"
|
|
21
|
+
},
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"type": "module",
|
|
26
|
+
"main": "./dist/index.js",
|
|
27
|
+
"module": "./dist/index.js",
|
|
28
|
+
"types": "./dist/index.d.ts",
|
|
29
|
+
"exports": {
|
|
30
|
+
".": {
|
|
31
|
+
"types": "./dist/index.d.ts",
|
|
32
|
+
"import": "./dist/index.js"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"bin": {
|
|
36
|
+
"conquest": "dist/cli.js"
|
|
37
|
+
},
|
|
38
|
+
"files": [
|
|
39
|
+
"dist",
|
|
40
|
+
"src"
|
|
41
|
+
],
|
|
42
|
+
"sideEffects": false,
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@ethersproject/signing-key": "5.7.0",
|
|
45
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
46
|
+
"@noble/hashes": "^1.6.1",
|
|
47
|
+
"@noble/secp256k1": "^2.1.0",
|
|
48
|
+
"commander": "^14.0.3",
|
|
49
|
+
"eip-1193": "^0.6.5",
|
|
50
|
+
"ldenv": "^0.3.16",
|
|
51
|
+
"remote-procedure-call": "^0.1.1",
|
|
52
|
+
"tools-ethereum": "^0.0.7",
|
|
53
|
+
"viem": "^2.45.1",
|
|
54
|
+
"zod": "^4.3.6",
|
|
55
|
+
"conquest-eth-v0-contracts": "0.0.1"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@modelcontextprotocol/inspector": "^0.19.0",
|
|
59
|
+
"@rocketh/node": "^0.18.2",
|
|
60
|
+
"@types/node": "^25.2.0",
|
|
61
|
+
"as-soon": "^0.1.5",
|
|
62
|
+
"prettier": "^3.8.0",
|
|
63
|
+
"prool": "^0.2.2",
|
|
64
|
+
"reloaderoo": "^1.1.5",
|
|
65
|
+
"tsx": "^4.21.0",
|
|
66
|
+
"typescript": "^5.3.3",
|
|
67
|
+
"vitest": "^4.0.18"
|
|
68
|
+
},
|
|
69
|
+
"scripts": {
|
|
70
|
+
"release": "pnpm prepublishOnly && git push --all && pnpm changeset publish && git push --tags",
|
|
71
|
+
"format": "prettier --write .",
|
|
72
|
+
"format:check": "prettier --check .",
|
|
73
|
+
"build": "tsc",
|
|
74
|
+
"dev": "as-soon -w src pnpm build",
|
|
75
|
+
"test": "vitest run",
|
|
76
|
+
"test:watch": "vitest",
|
|
77
|
+
"mcp:inspector": "mcp-inspector",
|
|
78
|
+
"reloaderoo": "reloaderoo",
|
|
79
|
+
"start": "reloaderoo proxy --log-level debug -- node ./dist/cli.js --rpc-url http://localhost:8545 --game-contract 0x322813fd9a801c5507c9de605d63cea4f2ce6c44 mcp --ethereum"
|
|
80
|
+
}
|
|
81
|
+
}
|
package/src/cli.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {StdioServerTransport} from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
-
import {createServer} from './index.js';
|
|
4
3
|
import {Command} from 'commander';
|
|
5
4
|
import pkg from '../package.json' with {type: 'json'};
|
|
6
|
-
import {getChain} from 'tools-ethereum/helpers';
|
|
7
5
|
import {loadEnv} from 'ldenv';
|
|
8
6
|
import * as tools from './tools/index.js';
|
|
9
|
-
import {registerAllToolCommands} from './
|
|
7
|
+
import {type EnvFactory, registerAllToolCommands} from './tool-handling/cli.js';
|
|
8
|
+
import type {ConquestEnv} from './types.js';
|
|
9
|
+
import {createServer} from './mcp.js';
|
|
10
|
+
import {createConquestEnv} from './index.js';
|
|
10
11
|
|
|
11
12
|
loadEnv();
|
|
12
13
|
|
|
@@ -15,6 +16,9 @@ const program = new Command();
|
|
|
15
16
|
// Get the binary name from package.json
|
|
16
17
|
const binName = Object.keys(pkg.bin || {})[0];
|
|
17
18
|
|
|
19
|
+
// ----------------------------------------------------------------------------
|
|
20
|
+
// GLOBAL OPTIONS
|
|
21
|
+
// ----------------------------------------------------------------------------
|
|
18
22
|
program
|
|
19
23
|
.name(binName)
|
|
20
24
|
.description(pkg.description || 'Conquest.eth CLI - MCP server and direct tool execution')
|
|
@@ -32,16 +36,65 @@ program
|
|
|
32
36
|
'Path to storage directory',
|
|
33
37
|
process.env.STORAGE_PATH || './data',
|
|
34
38
|
)
|
|
35
|
-
.option(
|
|
36
|
-
'--private-key <key>',
|
|
37
|
-
'Private key for sending transactions',
|
|
38
|
-
process.env.PRIVATE_KEY || '',
|
|
39
|
-
)
|
|
40
39
|
.action(() => {
|
|
41
40
|
program.help();
|
|
42
41
|
});
|
|
43
42
|
|
|
43
|
+
function gatherGlobalOptions(program: Command) {
|
|
44
|
+
const globalOptions = program.opts();
|
|
45
|
+
const rpcUrl = globalOptions.rpcUrl;
|
|
46
|
+
const gameContract = globalOptions.gameContract;
|
|
47
|
+
|
|
48
|
+
const storage = globalOptions.storage;
|
|
49
|
+
const storagePath = globalOptions.storagePath;
|
|
50
|
+
|
|
51
|
+
// Validate required options
|
|
52
|
+
if (!rpcUrl) {
|
|
53
|
+
console.error('Error: --rpc-url option or RPC_URL environment variable is required');
|
|
54
|
+
process.exit(1);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (!gameContract) {
|
|
58
|
+
console.error(
|
|
59
|
+
'Error: --game-contract option or GAME_CONTRACT environment variable is required',
|
|
60
|
+
);
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const privateKey = process.env.PRIVATE_KEY as `0x${string}`;
|
|
65
|
+
// Warn if private key is not provided for write operations
|
|
66
|
+
if (!privateKey) {
|
|
67
|
+
console.warn('Warning: PRIVATE_KEY environment variable is required for sending transactions');
|
|
68
|
+
} else if (!privateKey.startsWith('0x')) {
|
|
69
|
+
console.error('Error: PRIVATE_KEY must start with 0x');
|
|
70
|
+
process.exit(1);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
return {rpcUrl, gameContract, privateKey, storage, storagePath};
|
|
74
|
+
}
|
|
75
|
+
// ----------------------------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
// ----------------------------------------------------------------------------
|
|
78
|
+
// FACTORY THAT GENERATE THE Conquest Environment Used By Tools
|
|
79
|
+
// ----------------------------------------------------------------------------
|
|
80
|
+
/**
|
|
81
|
+
* Factory function to create the ConquestEnv from CLI options
|
|
82
|
+
*/
|
|
83
|
+
const envFactory: EnvFactory<ConquestEnv> = async () => {
|
|
84
|
+
const {rpcUrl, gameContract, privateKey, storage, storagePath} = gatherGlobalOptions(program);
|
|
85
|
+
|
|
86
|
+
return createConquestEnv({
|
|
87
|
+
rpcUrl,
|
|
88
|
+
gameContract,
|
|
89
|
+
privateKey,
|
|
90
|
+
storagePath,
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
// ----------------------------------------------------------------------------
|
|
94
|
+
|
|
95
|
+
// ----------------------------------------------------------------------------
|
|
44
96
|
// MCP subcommand - starts the MCP server
|
|
97
|
+
// ----------------------------------------------------------------------------
|
|
45
98
|
program
|
|
46
99
|
.command('mcp')
|
|
47
100
|
.description('Start the MCP server')
|
|
@@ -50,60 +103,36 @@ program
|
|
|
50
103
|
'Whether to also provide tools-ethereum tools',
|
|
51
104
|
process.env.ETHEREUM_TOOLS === 'true',
|
|
52
105
|
)
|
|
53
|
-
.action(async () => {
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
const gameContract = options.gameContract;
|
|
59
|
-
const ethereum = mcpOptions.ethereum ?? process.env.ETHEREUM_TOOLS === 'true';
|
|
60
|
-
const privateKey = options.privateKey;
|
|
61
|
-
const storage = options.storage;
|
|
62
|
-
const storagePath = options.storagePath;
|
|
63
|
-
|
|
64
|
-
// Validate required options
|
|
65
|
-
if (!rpcUrl) {
|
|
66
|
-
console.error('Error: --rpc-url option or RPC_URL environment variable is required');
|
|
67
|
-
process.exit(1);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
if (!gameContract) {
|
|
71
|
-
console.error(
|
|
72
|
-
'Error: --game-contract option or GAME_CONTRACT environment variable is required',
|
|
73
|
-
);
|
|
74
|
-
process.exit(1);
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
// Warn if private key is not provided for write operations
|
|
78
|
-
if (!privateKey) {
|
|
79
|
-
console.warn(
|
|
80
|
-
'Warning: PRIVATE_KEY environment variable is required for sending transactions',
|
|
81
|
-
);
|
|
82
|
-
} else if (!privateKey.startsWith('0x')) {
|
|
83
|
-
console.error('Error: PRIVATE_KEY must start with 0x');
|
|
84
|
-
process.exit(1);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
const chain = await getChain(rpcUrl);
|
|
106
|
+
.action(async (options) => {
|
|
107
|
+
const env = await envFactory();
|
|
108
|
+
|
|
109
|
+
const ethereum = options.ethereum ?? process.env.ETHEREUM_TOOLS === 'true';
|
|
110
|
+
|
|
88
111
|
const transport = new StdioServerTransport();
|
|
89
|
-
const server = createServer(
|
|
90
|
-
{
|
|
91
|
-
chain,
|
|
92
|
-
privateKey: privateKey as `0x${string}`,
|
|
93
|
-
gameContract: gameContract as `0x${string}`,
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
ethereum,
|
|
97
|
-
storageConfig: {
|
|
98
|
-
type: storage as 'json' | 'sqlite',
|
|
99
|
-
dataDir: storagePath,
|
|
100
|
-
},
|
|
101
|
-
},
|
|
102
|
-
);
|
|
112
|
+
const server = await createServer(env, {ethereum});
|
|
103
113
|
await server.connect(transport);
|
|
104
114
|
});
|
|
115
|
+
// ----------------------------------------------------------------------------
|
|
116
|
+
|
|
117
|
+
// ----------------------------------------------------------------------------
|
|
118
|
+
// Register all tool commands dynamically with the CLI config
|
|
119
|
+
registerAllToolCommands(program, tools, envFactory);
|
|
120
|
+
// ----------------------------------------------------------------------------
|
|
121
|
+
|
|
122
|
+
// ----------------------------------------------------------------------------
|
|
123
|
+
// HANDLE unknown command
|
|
124
|
+
// ----------------------------------------------------------------------------
|
|
125
|
+
const args = process.argv.slice(2);
|
|
126
|
+
const registeredCommands = program.commands.map((cmd) => cmd.name());
|
|
127
|
+
|
|
128
|
+
// Check if the first argument is a known command or a global flag
|
|
129
|
+
const isKnown = registeredCommands.includes(args[0]) || args[0]?.startsWith('-');
|
|
105
130
|
|
|
106
|
-
|
|
107
|
-
|
|
131
|
+
if (args.length > 0 && !isKnown) {
|
|
132
|
+
console.error(`error: unknown command: ${args[0]}`);
|
|
133
|
+
program.outputHelp();
|
|
134
|
+
process.exit(1);
|
|
135
|
+
}
|
|
136
|
+
// ----------------------------------------------------------------------------
|
|
108
137
|
|
|
109
138
|
program.parse(process.argv);
|
|
@@ -1,6 +1,17 @@
|
|
|
1
1
|
import {SpaceInfo} from 'conquest-eth-v0-contracts';
|
|
2
2
|
import type {ClientsWithOptionalWallet, ContractConfig, GameContract} from '../types.js';
|
|
3
3
|
|
|
4
|
+
// Minimal ABI for reading numTokensPerNativeTokenAt18Decimals from PlayToken
|
|
5
|
+
const PlayTokenAbi = [
|
|
6
|
+
{
|
|
7
|
+
name: 'numTokensPerNativeTokenAt18Decimals',
|
|
8
|
+
type: 'function',
|
|
9
|
+
stateMutability: 'view',
|
|
10
|
+
inputs: [],
|
|
11
|
+
outputs: [{type: 'uint256'}],
|
|
12
|
+
},
|
|
13
|
+
] as const;
|
|
14
|
+
|
|
4
15
|
export async function createSpaceInfo(
|
|
5
16
|
clients: ClientsWithOptionalWallet,
|
|
6
17
|
gameContract: GameContract,
|
|
@@ -11,19 +22,31 @@ export async function createSpaceInfo(
|
|
|
11
22
|
functionName: 'getConfig',
|
|
12
23
|
});
|
|
13
24
|
|
|
25
|
+
// Extract stakingToken address and fetch numTokensPerNativeToken from PlayToken contract
|
|
26
|
+
const stakingToken = config.stakingToken as `0x${string}`;
|
|
27
|
+
const numTokensPerNativeToken = await clients.publicClient.readContract({
|
|
28
|
+
address: stakingToken,
|
|
29
|
+
abi: PlayTokenAbi,
|
|
30
|
+
functionName: 'numTokensPerNativeTokenAt18Decimals',
|
|
31
|
+
});
|
|
32
|
+
|
|
14
33
|
const contractConfig: ContractConfig = {
|
|
15
34
|
genesis: BigInt(config.genesis),
|
|
16
35
|
resolveWindow: BigInt(config.resolveWindow),
|
|
17
36
|
timePerDistance: BigInt(config.timePerDistance),
|
|
18
37
|
exitDuration: BigInt(config.exitDuration),
|
|
19
38
|
acquireNumSpaceships: Number(config.acquireNumSpaceships),
|
|
39
|
+
stakingToken,
|
|
40
|
+
numTokensPerNativeToken: BigInt(numTokensPerNativeToken),
|
|
20
41
|
};
|
|
21
42
|
|
|
22
43
|
// Create SpaceInfo instance with config
|
|
44
|
+
// Note: The contract's getConfig() returns timePerDistance already divided by 4 (see OuterSpaceFacetBase constructor).
|
|
45
|
+
// SpaceInfo also divides by 4 internally, so we need to multiply by 4 here to compensate.
|
|
23
46
|
const spaceInfo = new SpaceInfo({
|
|
24
47
|
genesis: config.genesis as `0x${string}`,
|
|
25
48
|
resolveWindow: Number(config.resolveWindow),
|
|
26
|
-
timePerDistance: Number(config.timePerDistance),
|
|
49
|
+
timePerDistance: Number(config.timePerDistance) * 4,
|
|
27
50
|
exitDuration: Number(config.exitDuration),
|
|
28
51
|
acquireNumSpaceships: Number(config.acquireNumSpaceships),
|
|
29
52
|
productionSpeedUp: Number(config.productionSpeedUp),
|
package/src/fleet/resolve.ts
CHANGED
|
@@ -166,7 +166,7 @@ export async function resolveFleetWithSpaceInfo(
|
|
|
166
166
|
}
|
|
167
167
|
|
|
168
168
|
/**
|
|
169
|
-
* Get fleets that can be resolved (
|
|
169
|
+
* Get fleets that can be resolved (arrived and still within resolve window)
|
|
170
170
|
*
|
|
171
171
|
* @param storage - Storage instance for tracking pending fleets
|
|
172
172
|
* @param resolveWindow - The resolve window duration in seconds from contract config
|
|
@@ -180,8 +180,9 @@ export async function getResolvableFleets(
|
|
|
180
180
|
const fleets = await storage.getResolvableFleets();
|
|
181
181
|
|
|
182
182
|
return fleets.filter((fleet) => {
|
|
183
|
-
//
|
|
184
|
-
const
|
|
185
|
-
|
|
183
|
+
// Fleet can be resolved after arrival but before resolve window closes
|
|
184
|
+
const arrivalTime = fleet.estimatedArrivalTime;
|
|
185
|
+
const resolveWindowEnd = arrivalTime + Number(resolveWindow);
|
|
186
|
+
return !fleet.resolved && currentTime >= arrivalTime && currentTime < resolveWindowEnd;
|
|
186
187
|
});
|
|
187
188
|
}
|
package/src/fleet/send.ts
CHANGED
|
@@ -3,7 +3,6 @@ import type {SpaceInfo} from 'conquest-eth-v0-contracts';
|
|
|
3
3
|
import type {FleetStorage} from '../storage/interface.js';
|
|
4
4
|
import type {Clients, ContractConfig, GameContract, PendingFleet} from '../types.js';
|
|
5
5
|
import {computeFleetId, computeToHash, generateSecret} from '../util/hashing.js';
|
|
6
|
-
import {calculateEstimatedArrivalTime, getCurrentTimestamp} from '../util/time.js';
|
|
7
6
|
|
|
8
7
|
/**
|
|
9
8
|
* Send a fleet to a destination planet
|
|
@@ -56,12 +55,14 @@ export async function sendFleet(
|
|
|
56
55
|
// Generate secret if not provided
|
|
57
56
|
const secret = options?.secret || generateSecret();
|
|
58
57
|
|
|
59
|
-
//
|
|
60
|
-
const
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
58
|
+
// Get current blockchain timestamp (not local time) for accurate arrival calculation
|
|
59
|
+
const block = await clients.publicClient.getBlock();
|
|
60
|
+
const blockTimestamp = Number(block.timestamp);
|
|
61
|
+
|
|
62
|
+
// Calculate estimated arrival time using SpaceInfo which accounts for planet speed
|
|
63
|
+
// The travel time formula is: distance * (timePerDistance * 10000) / speed
|
|
64
|
+
const travelTime = spaceInfo.timeToArrive(fromPlanet, toPlanet);
|
|
65
|
+
const estimatedArrivalTime = blockTimestamp + travelTime;
|
|
65
66
|
|
|
66
67
|
const parameters = {
|
|
67
68
|
gift: options?.gift ?? false,
|
|
@@ -94,7 +95,7 @@ export async function sendFleet(
|
|
|
94
95
|
arrivalTimeWanted: parameters.arrivalTimeWanted,
|
|
95
96
|
fleetSender,
|
|
96
97
|
operator,
|
|
97
|
-
committedAt:
|
|
98
|
+
committedAt: blockTimestamp,
|
|
98
99
|
estimatedArrivalTime,
|
|
99
100
|
resolved: false,
|
|
100
101
|
};
|
package/src/index.ts
CHANGED
|
@@ -1,181 +1,47 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import pkg from '../package.json' with {type: 'json'};
|
|
3
|
-
import {Implementation} from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
-
import {Chain} from 'viem';
|
|
5
|
-
import {ServerOptions} from '@modelcontextprotocol/sdk/server';
|
|
6
|
-
import {createServer as createMCPEthereumServer} from 'tools-ethereum';
|
|
7
|
-
import {getClients} from 'tools-ethereum/helpers';
|
|
1
|
+
import {getClients, getChain} from 'tools-ethereum/helpers';
|
|
8
2
|
import {createSpaceInfo} from './contracts/space-info.js';
|
|
9
3
|
import {JsonFleetStorage} from './storage/json-storage.js';
|
|
10
4
|
import {FleetManager} from './fleet/manager.js';
|
|
11
5
|
import {PlanetManager} from './planet/manager.js';
|
|
12
|
-
import type {
|
|
13
|
-
|
|
6
|
+
import type {
|
|
7
|
+
ClientsWithOptionalWallet,
|
|
8
|
+
ConquestEnv,
|
|
9
|
+
EnvFactoryOptions,
|
|
10
|
+
GameContract,
|
|
11
|
+
} from './types.js';
|
|
14
12
|
|
|
15
|
-
// Import refactored tools
|
|
16
|
-
import * as tools from './tools/index.js';
|
|
17
|
-
import {registerTool, stringifyWithBigInt} from './helpers/index.js';
|
|
18
13
|
import {Abi_IOuterSpace} from 'conquest-eth-v0-contracts/abis/IOuterSpace.js';
|
|
19
14
|
|
|
20
15
|
/**
|
|
21
|
-
*
|
|
16
|
+
* Factory function to create the ConquestEnv
|
|
17
|
+
* This is shared between CLI and MCP server
|
|
22
18
|
*
|
|
23
|
-
* @param
|
|
24
|
-
* @
|
|
25
|
-
* @param params.privateKey - Optional private key for signing transactions (wallet operations)
|
|
26
|
-
* @param params.gameContract - The game contract address
|
|
27
|
-
* @param options - Optional server configuration
|
|
28
|
-
* @param options.ethereum - Whether to include Ethereum MCP tools (default: false)
|
|
29
|
-
* @param options.rpcURL - Optional custom RPC URL
|
|
30
|
-
* @param options.serverOptions - Optional MCP server options
|
|
31
|
-
* @param options.serverInfo - Optional server metadata to override defaults
|
|
32
|
-
* @param options.storageConfig - Storage configuration for fleets and exits
|
|
33
|
-
* @param options.storageConfig.type - Storage type ('json' or 'sqlite')
|
|
34
|
-
* @param options.storageConfig.dataDir - Optional data directory path
|
|
35
|
-
* @returns Configured MCP server instance with Conquest game tools registered
|
|
19
|
+
* @param options - Configuration options for creating the environment
|
|
20
|
+
* @returns ConquestEnv with fleetManager and planetManager
|
|
36
21
|
*/
|
|
37
|
-
export function
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
},
|
|
46
|
-
) {
|
|
47
|
-
const {gameContract: gameContractAddress, ...mcpEthereumParams} = params;
|
|
48
|
-
const clients = getClients(params, options) as ClientsWithOptionalWallet;
|
|
22
|
+
export async function createConquestEnv(options: EnvFactoryOptions): Promise<ConquestEnv> {
|
|
23
|
+
const {rpcUrl, gameContract: gameContractAddress, privateKey, storagePath = './data'} = options;
|
|
24
|
+
|
|
25
|
+
const chain = await getChain(rpcUrl);
|
|
26
|
+
const clients = getClients({
|
|
27
|
+
chain,
|
|
28
|
+
privateKey,
|
|
29
|
+
}) as ClientsWithOptionalWallet;
|
|
49
30
|
|
|
50
31
|
const gameContract: GameContract = {
|
|
51
32
|
address: gameContractAddress,
|
|
52
33
|
abi: Abi_IOuterSpace,
|
|
53
34
|
};
|
|
54
35
|
|
|
55
|
-
const
|
|
56
|
-
const
|
|
57
|
-
? createMCPEthereumServer(mcpEthereumParams, {
|
|
58
|
-
...options,
|
|
59
|
-
serverInfo: {name, version: pkg.version, ...options?.serverInfo},
|
|
60
|
-
})
|
|
61
|
-
: new McpServer(
|
|
62
|
-
options?.serverInfo || {
|
|
63
|
-
name,
|
|
64
|
-
version: pkg.version,
|
|
65
|
-
},
|
|
66
|
-
options?.serverOptions || {capabilities: {logging: {}}},
|
|
67
|
-
);
|
|
68
|
-
|
|
69
|
-
// Initialize SpaceInfo and contractConfig
|
|
70
|
-
let spaceInfo: SpaceInfo | null = null;
|
|
71
|
-
let contractConfig: ContractConfig | null = null;
|
|
36
|
+
const {spaceInfo, contractConfig} = await createSpaceInfo(clients, gameContract);
|
|
37
|
+
const storage = new JsonFleetStorage(storagePath);
|
|
72
38
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
39
|
+
return {
|
|
40
|
+
fleetManager: new FleetManager(clients, gameContract, spaceInfo, contractConfig, storage),
|
|
41
|
+
planetManager: new PlanetManager(clients, gameContract, spaceInfo, contractConfig, storage),
|
|
42
|
+
spaceInfo,
|
|
43
|
+
contractConfig,
|
|
44
|
+
clients,
|
|
45
|
+
options,
|
|
80
46
|
};
|
|
81
|
-
|
|
82
|
-
// Initialize storage
|
|
83
|
-
const storageConfig = options?.storageConfig || {type: 'json', dataDir: './data'};
|
|
84
|
-
const storage = new JsonFleetStorage(storageConfig.dataDir || './data');
|
|
85
|
-
|
|
86
|
-
// Initialize managers (will be initialized after spaceInfo is ready)
|
|
87
|
-
let fleetManager: FleetManager | null = null;
|
|
88
|
-
let planetManager: PlanetManager | null = null;
|
|
89
|
-
|
|
90
|
-
// Helper to ensure managers are initialized
|
|
91
|
-
const ensureManagersInitialized = async () => {
|
|
92
|
-
const {spaceInfo: si, contractConfig: cc} = await initSpaceInfo();
|
|
93
|
-
|
|
94
|
-
// Initialize fleetManager even without walletClient for read-only operations
|
|
95
|
-
if (!fleetManager && si && cc) {
|
|
96
|
-
fleetManager = new FleetManager(clients, gameContract, si, cc, storage);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Initialize planetManager even without walletClient for read-only operations
|
|
100
|
-
if (!planetManager && si && cc) {
|
|
101
|
-
planetManager = new PlanetManager(clients, gameContract, si, cc, storage);
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
if (!fleetManager) {
|
|
105
|
-
throw new Error('Fleet manager not initialized');
|
|
106
|
-
}
|
|
107
|
-
if (!planetManager) {
|
|
108
|
-
throw new Error('Planet manager not initialized');
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return {fleetManager, planetManager};
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
// Auto-register all tools
|
|
115
|
-
for (const [name, tool] of Object.entries(tools)) {
|
|
116
|
-
// Skip the file that's not a tool
|
|
117
|
-
if (name === 'default') continue;
|
|
118
|
-
|
|
119
|
-
server.registerTool(
|
|
120
|
-
name,
|
|
121
|
-
{
|
|
122
|
-
description: tool.description,
|
|
123
|
-
inputSchema: tool.schema,
|
|
124
|
-
},
|
|
125
|
-
async (args: unknown) => {
|
|
126
|
-
try {
|
|
127
|
-
const {fleetManager, planetManager} = await ensureManagersInitialized();
|
|
128
|
-
|
|
129
|
-
const env = {
|
|
130
|
-
sendStatus: async (_message: string) => {
|
|
131
|
-
// TODO: Implement progress notifications when sessionId is available
|
|
132
|
-
},
|
|
133
|
-
fleetManager,
|
|
134
|
-
planetManager,
|
|
135
|
-
};
|
|
136
|
-
|
|
137
|
-
const result = await tool.execute(env, args as any);
|
|
138
|
-
|
|
139
|
-
// Convert ToolResult to CallToolResult
|
|
140
|
-
if (result.success === false) {
|
|
141
|
-
return {
|
|
142
|
-
content: [
|
|
143
|
-
{
|
|
144
|
-
type: 'text' as const,
|
|
145
|
-
text: stringifyWithBigInt({
|
|
146
|
-
error: result.error,
|
|
147
|
-
...(result.stack ? {stack: result.stack} : {}),
|
|
148
|
-
}),
|
|
149
|
-
},
|
|
150
|
-
],
|
|
151
|
-
isError: true,
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
return {
|
|
156
|
-
content: [
|
|
157
|
-
{
|
|
158
|
-
type: 'text' as const,
|
|
159
|
-
text: stringifyWithBigInt(result.result, 2),
|
|
160
|
-
},
|
|
161
|
-
],
|
|
162
|
-
};
|
|
163
|
-
} catch (error) {
|
|
164
|
-
return {
|
|
165
|
-
content: [
|
|
166
|
-
{
|
|
167
|
-
type: 'text' as const,
|
|
168
|
-
text: stringifyWithBigInt({
|
|
169
|
-
error: error instanceof Error ? error.message : String(error),
|
|
170
|
-
}),
|
|
171
|
-
},
|
|
172
|
-
],
|
|
173
|
-
isError: true,
|
|
174
|
-
};
|
|
175
|
-
}
|
|
176
|
-
},
|
|
177
|
-
);
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
return server;
|
|
181
47
|
}
|