@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
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import {z} from 'zod';
|
|
2
|
+
import {createTool} from '../tool-handling/types.js';
|
|
3
|
+
import type {ConquestEnv} from '../types.js';
|
|
4
|
+
|
|
5
|
+
const schema = z.object({
|
|
6
|
+
coordinates: z
|
|
7
|
+
.array(
|
|
8
|
+
z.object({
|
|
9
|
+
x: z.number().describe('X coordinate of the planet'),
|
|
10
|
+
y: z.number().describe('Y coordinate of the planet'),
|
|
11
|
+
}),
|
|
12
|
+
)
|
|
13
|
+
.optional()
|
|
14
|
+
.describe(
|
|
15
|
+
'Optional array of planet coordinates to withdraw tokens from. If not provided, automatically withdraws from all planets that have completed exits and are ready for withdrawal.',
|
|
16
|
+
),
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
export const withdraw = createTool<typeof schema, ConquestEnv>({
|
|
20
|
+
description:
|
|
21
|
+
'Withdraw staked tokens from planets that have completed their exit process. If coordinates are provided, withdraws from those specific planets. If no coordinates are provided, automatically finds and withdraws from all planets with completed exits that have not been withdrawn yet.',
|
|
22
|
+
schema,
|
|
23
|
+
execute: async (env, {coordinates}) => {
|
|
24
|
+
try {
|
|
25
|
+
// If coordinates are provided, withdraw from specific planets
|
|
26
|
+
if (coordinates && coordinates.length > 0) {
|
|
27
|
+
// Convert x,y coordinates to planet IDs
|
|
28
|
+
const planetIdsBigInt: bigint[] = [];
|
|
29
|
+
for (const coord of coordinates) {
|
|
30
|
+
const planetId = env.planetManager.getPlanetIdByCoordinates(coord.x, coord.y);
|
|
31
|
+
if (planetId === undefined) {
|
|
32
|
+
throw new Error(`No planet found at coordinates (${coord.x}, ${coord.y})`);
|
|
33
|
+
}
|
|
34
|
+
planetIdsBigInt.push(planetId);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Call withdraw method
|
|
38
|
+
const result = await env.planetManager.withdraw(planetIdsBigInt);
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
success: true,
|
|
42
|
+
result: {
|
|
43
|
+
transactionHash: result.hash,
|
|
44
|
+
coordinates: coordinates,
|
|
45
|
+
planetsWithdrawn: result.planetsWithdrawn.map((id) => id.toString()),
|
|
46
|
+
},
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// No coordinates provided - automatically find and withdraw all ready exits
|
|
51
|
+
const withdrawableExits = await env.planetManager.getWithdrawableExits();
|
|
52
|
+
|
|
53
|
+
if (withdrawableExits.length === 0) {
|
|
54
|
+
return {
|
|
55
|
+
success: true,
|
|
56
|
+
result: {
|
|
57
|
+
message: 'No planets with completed exits ready for withdrawal',
|
|
58
|
+
planetsWithdrawn: [],
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Get coordinates for the withdrawable planets (for return value)
|
|
64
|
+
const withdrawableCoordinates = withdrawableExits
|
|
65
|
+
.map((exit) => {
|
|
66
|
+
const planet = env.planetManager.getPlanetInfo(exit.planetId);
|
|
67
|
+
return planet ? {x: planet.location.x, y: planet.location.y} : null;
|
|
68
|
+
})
|
|
69
|
+
.filter((c): c is {x: number; y: number} => c !== null);
|
|
70
|
+
|
|
71
|
+
// Withdraw all
|
|
72
|
+
const result = await env.planetManager.withdrawAll();
|
|
73
|
+
|
|
74
|
+
if (!result) {
|
|
75
|
+
return {
|
|
76
|
+
success: true,
|
|
77
|
+
result: {
|
|
78
|
+
message: 'No planets with completed exits ready for withdrawal',
|
|
79
|
+
planetsWithdrawn: [],
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return {
|
|
85
|
+
success: true,
|
|
86
|
+
result: {
|
|
87
|
+
transactionHash: result.hash,
|
|
88
|
+
coordinates: withdrawableCoordinates,
|
|
89
|
+
planetsWithdrawn: result.planetsWithdrawn.map((id) => id.toString()),
|
|
90
|
+
message: `Successfully withdrew tokens from ${result.planetsWithdrawn.length} planet(s)`,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
} catch (error) {
|
|
94
|
+
return {
|
|
95
|
+
success: false,
|
|
96
|
+
error: error instanceof Error ? error.message : String(error),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
});
|
package/src/types.ts
CHANGED
|
@@ -1,11 +1,36 @@
|
|
|
1
1
|
import type {Address, PublicClient, WalletClient} from 'viem';
|
|
2
|
-
import type {PlanetInfo} from 'conquest-eth-v0-contracts';
|
|
2
|
+
import type {PlanetInfo, SpaceInfo} from 'conquest-eth-v0-contracts';
|
|
3
3
|
import type {Abi_IOuterSpace} from 'conquest-eth-v0-contracts/abis/IOuterSpace.js';
|
|
4
|
-
import type {CallToolResult} from '@modelcontextprotocol/sdk/types.js';
|
|
5
|
-
import {z} from 'zod';
|
|
6
4
|
import type {FleetManager} from './fleet/manager.js';
|
|
7
5
|
import type {PlanetManager} from './planet/manager.js';
|
|
8
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Configuration options for creating the ConquestEnv
|
|
9
|
+
*/
|
|
10
|
+
export interface EnvFactoryOptions {
|
|
11
|
+
/** RPC URL for the Ethereum network */
|
|
12
|
+
rpcUrl: string;
|
|
13
|
+
/** Contract address of the game */
|
|
14
|
+
gameContract: `0x${string}`;
|
|
15
|
+
/** Optional private key for sending transactions */
|
|
16
|
+
privateKey?: `0x${string}`;
|
|
17
|
+
/** Path to storage directory (default: './data') */
|
|
18
|
+
storagePath?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Environment type for Conquest tools
|
|
23
|
+
* Contains the managers needed for tool execution
|
|
24
|
+
*/
|
|
25
|
+
export interface ConquestEnv {
|
|
26
|
+
fleetManager: FleetManager;
|
|
27
|
+
planetManager: PlanetManager;
|
|
28
|
+
spaceInfo: SpaceInfo;
|
|
29
|
+
contractConfig: ContractConfig;
|
|
30
|
+
clients: ClientsWithOptionalWallet;
|
|
31
|
+
options: EnvFactoryOptions;
|
|
32
|
+
}
|
|
33
|
+
|
|
9
34
|
export interface StorageConfig {
|
|
10
35
|
type: 'json' | 'sqlite';
|
|
11
36
|
dataDir?: string; // Default: `${cwd}/data`
|
|
@@ -32,7 +57,9 @@ export interface ContractConfig {
|
|
|
32
57
|
timePerDistance: bigint;
|
|
33
58
|
exitDuration: bigint;
|
|
34
59
|
acquireNumSpaceships: number;
|
|
35
|
-
|
|
60
|
+
stakingToken: `0x${string}`;
|
|
61
|
+
numTokensPerNativeToken: bigint;
|
|
62
|
+
[key: string]: bigint | number | `0x${string}`;
|
|
36
63
|
}
|
|
37
64
|
|
|
38
65
|
export interface ExternalPlanet {
|
|
@@ -66,6 +93,8 @@ export interface PendingExit {
|
|
|
66
93
|
completed: boolean; // Whether exit has completed
|
|
67
94
|
interrupted: boolean; // Whether exit was interrupted by attack
|
|
68
95
|
lastCheckedAt: number; // Last time status was verified against contract
|
|
96
|
+
withdrawn: boolean; // Whether tokens have been withdrawn
|
|
97
|
+
withdrawnAt?: number; // Timestamp when tokens were withdrawn
|
|
69
98
|
}
|
|
70
99
|
|
|
71
100
|
export interface PlanetWithDistance {
|
|
@@ -109,70 +138,3 @@ export interface FleetResolution {
|
|
|
109
138
|
fleetSender: `0x${string}`; // Address that sent the fleet
|
|
110
139
|
operator: `0x${string}`; // Address that committed the transaction
|
|
111
140
|
}
|
|
112
|
-
|
|
113
|
-
// Tool types for MCP server refactoring
|
|
114
|
-
export type ToolEnvironment = {
|
|
115
|
-
// Function to send status updates during tool execution (required)
|
|
116
|
-
sendStatus: (message: string) => Promise<void>;
|
|
117
|
-
// Fleet manager for fleet operations
|
|
118
|
-
fleetManager: FleetManager;
|
|
119
|
-
// Planet manager for planet operations
|
|
120
|
-
planetManager: PlanetManager;
|
|
121
|
-
};
|
|
122
|
-
|
|
123
|
-
// Result returned by tool execute functions
|
|
124
|
-
export type ToolResult =
|
|
125
|
-
| {success: true; result: Record<string, any>}
|
|
126
|
-
| {success: false; error: string; stack?: string};
|
|
127
|
-
|
|
128
|
-
// Tool definition with execute, schema, and description
|
|
129
|
-
export type Tool<S extends z.ZodObject<any> = z.ZodObject<any>> = {
|
|
130
|
-
description: string;
|
|
131
|
-
schema: S;
|
|
132
|
-
execute: (env: ToolEnvironment, params: z.infer<S>) => Promise<ToolResult>;
|
|
133
|
-
};
|
|
134
|
-
|
|
135
|
-
// Helper function to create a tool with automatic type inference
|
|
136
|
-
export function createTool<S extends z.ZodObject<any>>(config: {
|
|
137
|
-
description: string;
|
|
138
|
-
schema: S;
|
|
139
|
-
execute: (env: ToolEnvironment, params: z.infer<S>) => Promise<ToolResult>;
|
|
140
|
-
}): Tool<S> {
|
|
141
|
-
return config;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
// Convert ToolResult to CallToolResult format
|
|
145
|
-
export function convertToCallToolResult(result: ToolResult): CallToolResult {
|
|
146
|
-
// Import stringifyWithBigInt to handle BigInt serialization
|
|
147
|
-
const stringifyWithBigInt = (obj: any, space?: number): string => {
|
|
148
|
-
return JSON.stringify(
|
|
149
|
-
obj,
|
|
150
|
-
(_key, value) => (typeof value === 'bigint' ? value.toString() : value),
|
|
151
|
-
space,
|
|
152
|
-
);
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
if (result.success === false) {
|
|
156
|
-
return {
|
|
157
|
-
content: [
|
|
158
|
-
{
|
|
159
|
-
type: 'text' as const,
|
|
160
|
-
text: stringifyWithBigInt({
|
|
161
|
-
error: result.error,
|
|
162
|
-
...(result.stack ? {stack: result.stack} : {}),
|
|
163
|
-
}),
|
|
164
|
-
},
|
|
165
|
-
],
|
|
166
|
-
isError: true,
|
|
167
|
-
};
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
return {
|
|
171
|
-
content: [
|
|
172
|
-
{
|
|
173
|
-
type: 'text' as const,
|
|
174
|
-
text: stringifyWithBigInt(result.result, 2),
|
|
175
|
-
},
|
|
176
|
-
],
|
|
177
|
-
};
|
|
178
|
-
}
|
package/src/util/time.ts
CHANGED
|
@@ -5,52 +5,6 @@ export function getCurrentTimestamp(): number {
|
|
|
5
5
|
return Math.floor(Date.now() / 1000);
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* Calculate estimated arrival time based on distance and timePerDistance
|
|
10
|
-
*
|
|
11
|
-
* @param distance - The distance between planets
|
|
12
|
-
* @param timePerDistance - Time multiplier from contract config (seconds per distance unit)
|
|
13
|
-
* @param genesis - Genesis timestamp from contract config
|
|
14
|
-
* @returns Estimated arrival time in seconds
|
|
15
|
-
*/
|
|
16
|
-
export function calculateEstimatedArrivalTime(params: {
|
|
17
|
-
startTime: bigint;
|
|
18
|
-
distance: bigint;
|
|
19
|
-
timePerDistance: bigint;
|
|
20
|
-
}): number {
|
|
21
|
-
const {startTime, distance, timePerDistance} = params;
|
|
22
|
-
const travelTime = Number(distance) * Number(timePerDistance);
|
|
23
|
-
return Number(startTime) + travelTime;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Calculate when the resolve window opens
|
|
28
|
-
* A fleet can be resolved after it arrives and the resolve window has passed
|
|
29
|
-
*
|
|
30
|
-
* @param estimatedArrivalTime - When the fleet is estimated to arrive
|
|
31
|
-
* @param resolveWindow - The resolve window duration in seconds from contract config
|
|
32
|
-
* @returns The timestamp when the fleet can be resolved
|
|
33
|
-
*/
|
|
34
|
-
export function calculateResolveWindowOpen(
|
|
35
|
-
estimatedArrivalTime: number,
|
|
36
|
-
resolveWindow: bigint,
|
|
37
|
-
): number {
|
|
38
|
-
return estimatedArrivalTime + Number(resolveWindow);
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Check if a fleet can be resolved now
|
|
43
|
-
*
|
|
44
|
-
* @param estimatedArrivalTime - When the fleet was estimated to arrive
|
|
45
|
-
* @param resolveWindow - The resolve window duration in seconds
|
|
46
|
-
* @returns True if the fleet can be resolved now
|
|
47
|
-
*/
|
|
48
|
-
export function canResolveNow(estimatedArrivalTime: number, resolveWindow: bigint): boolean {
|
|
49
|
-
const currentTime = getCurrentTimestamp();
|
|
50
|
-
const resolveWindowOpen = calculateResolveWindowOpen(estimatedArrivalTime, resolveWindow);
|
|
51
|
-
return currentTime >= resolveWindowOpen;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
8
|
/**
|
|
55
9
|
* Format timestamp as ISO string
|
|
56
10
|
*/
|
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
import {Command} from 'commander';
|
|
2
|
-
import {z} from 'zod';
|
|
3
|
-
import type {Tool, ToolEnvironment, StorageConfig} from './types.js';
|
|
4
|
-
import {getClients} from 'tools-ethereum/helpers';
|
|
5
|
-
import {getChain} from 'tools-ethereum/helpers';
|
|
6
|
-
import {createSpaceInfo} from './contracts/space-info.js';
|
|
7
|
-
import {JsonFleetStorage} from './storage/json-storage.js';
|
|
8
|
-
import {FleetManager} from './fleet/manager.js';
|
|
9
|
-
import {PlanetManager} from './planet/manager.js';
|
|
10
|
-
import type {ClientsWithOptionalWallet, ContractConfig, GameContract} from './types.js';
|
|
11
|
-
import {SpaceInfo} from 'conquest-eth-v0-contracts';
|
|
12
|
-
import {Abi_IOuterSpace} from 'conquest-eth-v0-contracts/abis/IOuterSpace.js';
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* CLI configuration parameters
|
|
16
|
-
*/
|
|
17
|
-
export interface CliConfig {
|
|
18
|
-
chain: any;
|
|
19
|
-
privateKey?: `0x${string}`;
|
|
20
|
-
gameContract: `0x${string}`;
|
|
21
|
-
ethereum?: boolean;
|
|
22
|
-
storageConfig: StorageConfig;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
/**
|
|
26
|
-
* Convert Zod schema field to commander.js option definition
|
|
27
|
-
*/
|
|
28
|
-
function zodFieldToOption(name: string, field: z.ZodTypeAny): string {
|
|
29
|
-
if (field instanceof z.ZodBoolean) {
|
|
30
|
-
return `--${name}`;
|
|
31
|
-
}
|
|
32
|
-
return `--${name} <value>`;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Parse option value based on Zod type
|
|
37
|
-
*/
|
|
38
|
-
function parseOptionValue(field: z.ZodTypeAny, value: any): any {
|
|
39
|
-
if (field instanceof z.ZodArray) {
|
|
40
|
-
return typeof value === 'string' ? value.split(',').map((v) => v.trim()) : value;
|
|
41
|
-
}
|
|
42
|
-
if (field instanceof z.ZodNumber) {
|
|
43
|
-
return Number(value);
|
|
44
|
-
}
|
|
45
|
-
if (field instanceof z.ZodBoolean) {
|
|
46
|
-
return value === true || value === 'true';
|
|
47
|
-
}
|
|
48
|
-
return value;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Extract description from Zod schema field
|
|
53
|
-
*/
|
|
54
|
-
function getFieldDescription(field: z.ZodTypeAny): string {
|
|
55
|
-
return (field as any).description || 'No description available';
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Check if a Zod field is optional
|
|
60
|
-
*/
|
|
61
|
-
function isOptionalField(field: z.ZodTypeAny): boolean {
|
|
62
|
-
return field instanceof z.ZodOptional || field.isOptional?.();
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* Create a CLI tool environment for executing tools
|
|
67
|
-
*/
|
|
68
|
-
async function createCliToolEnvironment(config: CliConfig): Promise<ToolEnvironment> {
|
|
69
|
-
const {gameContract: gameContractAddress, chain, storageConfig} = config;
|
|
70
|
-
|
|
71
|
-
// Get clients
|
|
72
|
-
const clients = getClients({chain, privateKey: config.privateKey}) as ClientsWithOptionalWallet;
|
|
73
|
-
|
|
74
|
-
// Initialize game contract
|
|
75
|
-
const gameContract: GameContract = {
|
|
76
|
-
address: gameContractAddress,
|
|
77
|
-
abi: Abi_IOuterSpace,
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
// Initialize SpaceInfo
|
|
81
|
-
const {spaceInfo, contractConfig} = await createSpaceInfo(clients, gameContract);
|
|
82
|
-
|
|
83
|
-
// Initialize storage
|
|
84
|
-
const storage = new JsonFleetStorage(storageConfig.dataDir || './data');
|
|
85
|
-
|
|
86
|
-
// Initialize managers
|
|
87
|
-
const fleetManager = new FleetManager(clients, gameContract, spaceInfo, contractConfig, storage);
|
|
88
|
-
const planetManager = new PlanetManager(
|
|
89
|
-
clients,
|
|
90
|
-
gameContract,
|
|
91
|
-
spaceInfo,
|
|
92
|
-
contractConfig,
|
|
93
|
-
storage,
|
|
94
|
-
);
|
|
95
|
-
|
|
96
|
-
return {
|
|
97
|
-
fleetManager,
|
|
98
|
-
planetManager,
|
|
99
|
-
sendStatus: async (message: string) => {
|
|
100
|
-
console.log(`[Status] ${message}`);
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Parse and validate parameters against Zod schema
|
|
107
|
-
*/
|
|
108
|
-
async function parseAndValidateParams(
|
|
109
|
-
schema: z.ZodObject<any>,
|
|
110
|
-
options: Record<string, any>,
|
|
111
|
-
): Promise<any> {
|
|
112
|
-
try {
|
|
113
|
-
return await schema.parseAsync(options);
|
|
114
|
-
} catch (error) {
|
|
115
|
-
if (error instanceof z.ZodError) {
|
|
116
|
-
console.error('Parameter validation error:');
|
|
117
|
-
for (const err of error.issues) {
|
|
118
|
-
console.error(` - ${err.path.join('.')}: ${err.message}`);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
throw error;
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Format tool result for CLI output
|
|
127
|
-
*/
|
|
128
|
-
function formatToolResult(result: {
|
|
129
|
-
success: boolean;
|
|
130
|
-
result?: any;
|
|
131
|
-
error?: string;
|
|
132
|
-
stack?: string;
|
|
133
|
-
}): void {
|
|
134
|
-
if (result.success) {
|
|
135
|
-
console.log(JSON.stringify(result.result, null, 2));
|
|
136
|
-
} else {
|
|
137
|
-
console.error(
|
|
138
|
-
JSON.stringify(
|
|
139
|
-
{error: result.error, ...(result.stack ? {stack: result.stack} : {})},
|
|
140
|
-
null,
|
|
141
|
-
2,
|
|
142
|
-
),
|
|
143
|
-
);
|
|
144
|
-
process.exit(1);
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* Generate a single tool command from tool definition
|
|
150
|
-
*/
|
|
151
|
-
export function generateToolCommand(
|
|
152
|
-
program: Command,
|
|
153
|
-
toolName: string,
|
|
154
|
-
tool: Tool<z.ZodObject<any>>,
|
|
155
|
-
): void {
|
|
156
|
-
const shape = tool.schema.shape;
|
|
157
|
-
const cmd = program.command(toolName).description(tool.description);
|
|
158
|
-
|
|
159
|
-
// Add options for each schema field
|
|
160
|
-
for (const [fieldName, field] of Object.entries(shape)) {
|
|
161
|
-
const actualField = isOptionalField(field as z.ZodTypeAny)
|
|
162
|
-
? (field as z.ZodOptional<any>).unwrap()
|
|
163
|
-
: field;
|
|
164
|
-
|
|
165
|
-
// Handle nested objects by flattening them
|
|
166
|
-
if (actualField instanceof z.ZodObject) {
|
|
167
|
-
const nestedShape = actualField.shape;
|
|
168
|
-
for (const [nestedKey, nestedField] of Object.entries(nestedShape)) {
|
|
169
|
-
const optionName = `${fieldName}-${nestedKey}`;
|
|
170
|
-
const optionDef = zodFieldToOption(optionName, nestedField);
|
|
171
|
-
const description = getFieldDescription(nestedField);
|
|
172
|
-
cmd.option(optionDef, description);
|
|
173
|
-
}
|
|
174
|
-
} else {
|
|
175
|
-
const optionDef = zodFieldToOption(fieldName, actualField);
|
|
176
|
-
const description = getFieldDescription(actualField);
|
|
177
|
-
|
|
178
|
-
if (isOptionalField(field as z.ZodTypeAny)) {
|
|
179
|
-
cmd.option(optionDef, description);
|
|
180
|
-
} else {
|
|
181
|
-
cmd.requiredOption(optionDef, description);
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
cmd.action(async (options: Record<string, any>) => {
|
|
187
|
-
try {
|
|
188
|
-
const globalOptions = program.opts();
|
|
189
|
-
|
|
190
|
-
// Get global options
|
|
191
|
-
const rpcUrl = options.rpcUrl || globalOptions.rpcUrl || process.env.RPC_URL;
|
|
192
|
-
const gameContract =
|
|
193
|
-
options.gameContract || globalOptions.gameContract || process.env.GAME_CONTRACT;
|
|
194
|
-
const ethereum =
|
|
195
|
-
options.ethereum ?? globalOptions.ethereum ?? process.env.ETHEREUM_TOOLS === 'true';
|
|
196
|
-
const privateKey = options.privateKey || globalOptions.privateKey || process.env.PRIVATE_KEY;
|
|
197
|
-
const storageType =
|
|
198
|
-
options.storage || globalOptions.storage || process.env.STORAGE_TYPE || 'json';
|
|
199
|
-
const storagePath =
|
|
200
|
-
options.storagePath || globalOptions.storagePath || process.env.STORAGE_PATH || './data';
|
|
201
|
-
|
|
202
|
-
// Validate required options
|
|
203
|
-
if (!rpcUrl) {
|
|
204
|
-
console.error('Error: --rpc-url option or RPC_URL environment variable is required');
|
|
205
|
-
process.exit(1);
|
|
206
|
-
}
|
|
207
|
-
if (!gameContract) {
|
|
208
|
-
console.error(
|
|
209
|
-
'Error: --game-contract option or GAME_CONTRACT environment variable is required',
|
|
210
|
-
);
|
|
211
|
-
process.exit(1);
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
// Get chain
|
|
215
|
-
const chain = await getChain(rpcUrl);
|
|
216
|
-
|
|
217
|
-
// Parse and validate parameters
|
|
218
|
-
const params: Record<string, any> = {};
|
|
219
|
-
for (const [fieldName, field] of Object.entries(shape)) {
|
|
220
|
-
const actualField = isOptionalField(field as z.ZodTypeAny)
|
|
221
|
-
? (field as z.ZodOptional<any>).unwrap()
|
|
222
|
-
: field;
|
|
223
|
-
|
|
224
|
-
if (actualField instanceof z.ZodObject) {
|
|
225
|
-
// Handle nested object - reconstruct from flattened options
|
|
226
|
-
const nestedResult: Record<string, any> = {};
|
|
227
|
-
const nestedShape = actualField.shape;
|
|
228
|
-
for (const [nestedKey, nestedField] of Object.entries(nestedShape)) {
|
|
229
|
-
const optionName = `${fieldName}-${nestedKey}`;
|
|
230
|
-
if (options[optionName] !== undefined) {
|
|
231
|
-
nestedResult[nestedKey] = parseOptionValue(nestedField, options[optionName]);
|
|
232
|
-
}
|
|
233
|
-
}
|
|
234
|
-
params[fieldName] = nestedResult;
|
|
235
|
-
} else {
|
|
236
|
-
const value = options[fieldName];
|
|
237
|
-
if (value !== undefined) {
|
|
238
|
-
params[fieldName] = parseOptionValue(actualField, value);
|
|
239
|
-
}
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
const validatedParams = await parseAndValidateParams(tool.schema, params);
|
|
244
|
-
|
|
245
|
-
// Create environment and execute
|
|
246
|
-
const env = await createCliToolEnvironment({
|
|
247
|
-
chain,
|
|
248
|
-
privateKey: privateKey as `0x${string}`,
|
|
249
|
-
gameContract: gameContract as `0x${string}`,
|
|
250
|
-
ethereum,
|
|
251
|
-
storageConfig: {
|
|
252
|
-
type: storageType as 'json' | 'sqlite',
|
|
253
|
-
dataDir: storagePath,
|
|
254
|
-
},
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
const result = await tool.execute(env, validatedParams);
|
|
258
|
-
formatToolResult(result);
|
|
259
|
-
} catch (error) {
|
|
260
|
-
if (error instanceof Error) {
|
|
261
|
-
console.error(
|
|
262
|
-
JSON.stringify(
|
|
263
|
-
{error: error.message, ...(error.stack ? {stack: error.stack} : {})},
|
|
264
|
-
null,
|
|
265
|
-
2,
|
|
266
|
-
),
|
|
267
|
-
);
|
|
268
|
-
} else {
|
|
269
|
-
console.error(JSON.stringify({error: String(error)}, null, 2));
|
|
270
|
-
}
|
|
271
|
-
process.exit(1);
|
|
272
|
-
}
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
/**
|
|
277
|
-
* Register all tool commands from a tools object
|
|
278
|
-
*/
|
|
279
|
-
export function registerAllToolCommands(program: Command, tools: Record<string, Tool>): void {
|
|
280
|
-
for (const [toolName, tool] of Object.entries(tools)) {
|
|
281
|
-
// Skip the file that's not a tool
|
|
282
|
-
if (toolName === 'default') continue;
|
|
283
|
-
|
|
284
|
-
// Keep snake_case for CLI command names (1:1 mapping with tool names)
|
|
285
|
-
generateToolCommand(program, toolName, tool);
|
|
286
|
-
}
|
|
287
|
-
}
|
package/src/helpers/index.ts
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
import type {Tool, ToolEnvironment} from '../types.js';
|
|
2
|
-
import type {McpServer} from '@modelcontextprotocol/sdk/server/mcp.js';
|
|
3
|
-
import type {FleetManager} from '../fleet/manager.js';
|
|
4
|
-
import type {PlanetManager} from '../planet/manager.js';
|
|
5
|
-
import {convertToCallToolResult} from '../types.js';
|
|
6
|
-
|
|
7
|
-
// Helper function to handle BigInt serialization in JSON.stringify
|
|
8
|
-
export function stringifyWithBigInt(obj: any, space?: number): string {
|
|
9
|
-
return JSON.stringify(
|
|
10
|
-
obj,
|
|
11
|
-
(_key, value) => (typeof value === 'bigint' ? value.toString() : value),
|
|
12
|
-
space,
|
|
13
|
-
);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// Create tool environment with sendStatus
|
|
17
|
-
export function createToolEnvironment(
|
|
18
|
-
server: McpServer,
|
|
19
|
-
fleetManager: FleetManager,
|
|
20
|
-
planetManager: PlanetManager,
|
|
21
|
-
): ToolEnvironment {
|
|
22
|
-
return {
|
|
23
|
-
sendStatus: async (_message: string) => {
|
|
24
|
-
// TODO: Implement progress notifications when sessionId is available
|
|
25
|
-
// For now, this is a no-op since we don't have sessionId in the current architecture
|
|
26
|
-
},
|
|
27
|
-
fleetManager,
|
|
28
|
-
planetManager,
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// Register tool with MCP server
|
|
33
|
-
export function registerTool({
|
|
34
|
-
server,
|
|
35
|
-
name,
|
|
36
|
-
tool,
|
|
37
|
-
fleetManager,
|
|
38
|
-
planetManager,
|
|
39
|
-
}: {
|
|
40
|
-
server: McpServer;
|
|
41
|
-
name: string;
|
|
42
|
-
tool: Tool<any>;
|
|
43
|
-
fleetManager: FleetManager;
|
|
44
|
-
planetManager: PlanetManager;
|
|
45
|
-
}): void {
|
|
46
|
-
server.registerTool(
|
|
47
|
-
name,
|
|
48
|
-
{
|
|
49
|
-
description: tool.description,
|
|
50
|
-
inputSchema: tool.schema as any,
|
|
51
|
-
},
|
|
52
|
-
async (params: unknown) => {
|
|
53
|
-
const env = createToolEnvironment(server, fleetManager, planetManager);
|
|
54
|
-
|
|
55
|
-
const result = await tool.execute(env, params as any);
|
|
56
|
-
return convertToCallToolResult(result);
|
|
57
|
-
},
|
|
58
|
-
);
|
|
59
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import {z} from 'zod';
|
|
2
|
-
import {createTool} from '../types.js';
|
|
3
|
-
|
|
4
|
-
export const get_my_planets = createTool({
|
|
5
|
-
description: 'Get all planets owned by the current user address.',
|
|
6
|
-
schema: z.object({
|
|
7
|
-
radius: z.number().max(50).describe('Search radius around origin (0,0) to find planets'),
|
|
8
|
-
}),
|
|
9
|
-
execute: async (env, {radius}) => {
|
|
10
|
-
try {
|
|
11
|
-
const planets = await env.planetManager.getMyPlanets(radius);
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
success: true,
|
|
15
|
-
result: {
|
|
16
|
-
planets: planets.map(({info, state}) => ({
|
|
17
|
-
planetId: info.location.id.toString(),
|
|
18
|
-
location: info.location,
|
|
19
|
-
...state,
|
|
20
|
-
})),
|
|
21
|
-
},
|
|
22
|
-
};
|
|
23
|
-
} catch (error) {
|
|
24
|
-
return {
|
|
25
|
-
success: false,
|
|
26
|
-
error: error instanceof Error ? error.message : String(error),
|
|
27
|
-
};
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
});
|