@conquest-eth/tools 0.0.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/LICENSE +21 -0
- package/README.md +259 -0
- package/dist/cli-tool-generator.d.ts +22 -0
- package/dist/cli-tool-generator.d.ts.map +1 -0
- package/dist/cli-tool-generator.js +217 -0
- package/dist/cli-tool-generator.js.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +76 -0
- package/dist/cli.js.map +1 -0
- package/dist/contracts/space-info.d.ts +7 -0
- package/dist/contracts/space-info.d.ts.map +1 -0
- package/dist/contracts/space-info.js +34 -0
- package/dist/contracts/space-info.js.map +1 -0
- package/dist/fleet/index.d.ts +4 -0
- package/dist/fleet/index.d.ts.map +1 -0
- package/dist/fleet/index.js +7 -0
- package/dist/fleet/index.js.map +1 -0
- package/dist/fleet/manager.d.ts +70 -0
- package/dist/fleet/manager.d.ts.map +1 -0
- package/dist/fleet/manager.js +92 -0
- package/dist/fleet/manager.js.map +1 -0
- package/dist/fleet/resolve.d.ts +51 -0
- package/dist/fleet/resolve.d.ts.map +1 -0
- package/dist/fleet/resolve.js +140 -0
- package/dist/fleet/resolve.js.map +1 -0
- package/dist/fleet/send.d.ts +29 -0
- package/dist/fleet/send.d.ts.map +1 -0
- package/dist/fleet/send.js +81 -0
- package/dist/fleet/send.js.map +1 -0
- package/dist/helpers/index.d.ts +14 -0
- package/dist/helpers/index.d.ts.map +1 -0
- package/dist/helpers/index.js +28 -0
- package/dist/helpers/index.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/dist/planet/acquire.d.ts +16 -0
- package/dist/planet/acquire.d.ts.map +1 -0
- package/dist/planet/acquire.js +27 -0
- package/dist/planet/acquire.js.map +1 -0
- package/dist/planet/exit.d.ts +17 -0
- package/dist/planet/exit.d.ts.map +1 -0
- package/dist/planet/exit.js +56 -0
- package/dist/planet/exit.js.map +1 -0
- package/dist/planet/index.d.ts +4 -0
- package/dist/planet/index.d.ts.map +1 -0
- package/dist/planet/index.js +6 -0
- package/dist/planet/index.js.map +1 -0
- package/dist/planet/manager.d.ts +106 -0
- package/dist/planet/manager.d.ts.map +1 -0
- package/dist/planet/manager.js +253 -0
- package/dist/planet/manager.js.map +1 -0
- package/dist/storage/interface.d.ts +93 -0
- package/dist/storage/interface.d.ts.map +1 -0
- package/dist/storage/interface.js +2 -0
- package/dist/storage/interface.js.map +1 -0
- package/dist/storage/json-storage.d.ts +28 -0
- package/dist/storage/json-storage.d.ts.map +1 -0
- package/dist/storage/json-storage.js +148 -0
- package/dist/storage/json-storage.js.map +1 -0
- package/dist/tools/acquire_planets.d.ts +7 -0
- package/dist/tools/acquire_planets.d.ts.map +1 -0
- package/dist/tools/acquire_planets.js +63 -0
- package/dist/tools/acquire_planets.js.map +1 -0
- package/dist/tools/exit_planets.d.ts +5 -0
- package/dist/tools/exit_planets.d.ts.map +1 -0
- package/dist/tools/exit_planets.js +31 -0
- package/dist/tools/exit_planets.js.map +1 -0
- package/dist/tools/get_my_planets.d.ts +5 -0
- package/dist/tools/get_my_planets.d.ts.map +1 -0
- package/dist/tools/get_my_planets.js +30 -0
- package/dist/tools/get_my_planets.js.map +1 -0
- package/dist/tools/get_pending_exits.d.ts +3 -0
- package/dist/tools/get_pending_exits.d.ts.map +1 -0
- package/dist/tools/get_pending_exits.js +37 -0
- package/dist/tools/get_pending_exits.js.map +1 -0
- package/dist/tools/get_pending_fleets.d.ts +3 -0
- package/dist/tools/get_pending_fleets.d.ts.map +1 -0
- package/dist/tools/get_pending_fleets.js +41 -0
- package/dist/tools/get_pending_fleets.js.map +1 -0
- package/dist/tools/get_planets_around.d.ts +7 -0
- package/dist/tools/get_planets_around.d.ts.map +1 -0
- package/dist/tools/get_planets_around.js +41 -0
- package/dist/tools/get_planets_around.js.map +1 -0
- package/dist/tools/index.d.ts +10 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +11 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/resolve_fleet.d.ts +5 -0
- package/dist/tools/resolve_fleet.d.ts.map +1 -0
- package/dist/tools/resolve_fleet.js +37 -0
- package/dist/tools/resolve_fleet.js.map +1 -0
- package/dist/tools/send_fleet.d.ts +16 -0
- package/dist/tools/send_fleet.d.ts.map +1 -0
- package/dist/tools/send_fleet.js +62 -0
- package/dist/tools/send_fleet.js.map +1 -0
- package/dist/tools/verify_exit_status.d.ts +5 -0
- package/dist/tools/verify_exit_status.d.ts.map +1 -0
- package/dist/tools/verify_exit_status.js +39 -0
- package/dist/tools/verify_exit_status.js.map +1 -0
- package/dist/types.d.ts +126 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +34 -0
- package/dist/types.js.map +1 -0
- package/dist/util/hashing.d.ts +33 -0
- package/dist/util/hashing.d.ts.map +1 -0
- package/dist/util/hashing.js +38 -0
- package/dist/util/hashing.js.map +1 -0
- package/dist/util/time.d.ts +43 -0
- package/dist/util/time.d.ts.map +1 -0
- package/dist/util/time.js +55 -0
- package/dist/util/time.js.map +1 -0
- package/package.json +78 -0
- package/src/cli-tool-generator.ts +287 -0
- package/src/cli.ts +109 -0
- package/src/contracts/space-info.ts +41 -0
- package/src/fleet/index.ts +8 -0
- package/src/fleet/manager.ts +140 -0
- package/src/fleet/resolve.ts +187 -0
- package/src/fleet/send.ts +112 -0
- package/src/helpers/index.ts +59 -0
- package/src/index.ts +181 -0
- package/src/planet/acquire.ts +41 -0
- package/src/planet/exit.ts +71 -0
- package/src/planet/index.ts +6 -0
- package/src/planet/manager.ts +335 -0
- package/src/storage/interface.ts +111 -0
- package/src/storage/json-storage.ts +184 -0
- package/src/tools/acquire_planets.ts +81 -0
- package/src/tools/exit_planets.ts +35 -0
- package/src/tools/get_my_planets.ts +30 -0
- package/src/tools/get_pending_exits.ts +37 -0
- package/src/tools/get_pending_fleets.ts +41 -0
- package/src/tools/get_planets_around.ts +44 -0
- package/src/tools/index.ts +10 -0
- package/src/tools/resolve_fleet.ts +37 -0
- package/src/tools/send_fleet.ts +68 -0
- package/src/tools/verify_exit_status.ts +43 -0
- package/src/types.ts +178 -0
- package/src/util/hashing.ts +60 -0
- package/src/util/time.ts +66 -0
package/dist/types.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
// Helper function to create a tool with automatic type inference
|
|
2
|
+
export function createTool(config) {
|
|
3
|
+
return config;
|
|
4
|
+
}
|
|
5
|
+
// Convert ToolResult to CallToolResult format
|
|
6
|
+
export function convertToCallToolResult(result) {
|
|
7
|
+
// Import stringifyWithBigInt to handle BigInt serialization
|
|
8
|
+
const stringifyWithBigInt = (obj, space) => {
|
|
9
|
+
return JSON.stringify(obj, (_key, value) => (typeof value === 'bigint' ? value.toString() : value), space);
|
|
10
|
+
};
|
|
11
|
+
if (result.success === false) {
|
|
12
|
+
return {
|
|
13
|
+
content: [
|
|
14
|
+
{
|
|
15
|
+
type: 'text',
|
|
16
|
+
text: stringifyWithBigInt({
|
|
17
|
+
error: result.error,
|
|
18
|
+
...(result.stack ? { stack: result.stack } : {}),
|
|
19
|
+
}),
|
|
20
|
+
},
|
|
21
|
+
],
|
|
22
|
+
isError: true,
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
content: [
|
|
27
|
+
{
|
|
28
|
+
type: 'text',
|
|
29
|
+
text: stringifyWithBigInt(result.result, 2),
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAsIA,iEAAiE;AACjE,MAAM,UAAU,UAAU,CAA6B,MAItD;IACA,OAAO,MAAM,CAAC;AACf,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,uBAAuB,CAAC,MAAkB;IACzD,4DAA4D;IAC5D,MAAM,mBAAmB,GAAG,CAAC,GAAQ,EAAE,KAAc,EAAU,EAAE;QAChE,OAAO,IAAI,CAAC,SAAS,CACpB,GAAG,EACH,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,EACvE,KAAK,CACL,CAAC;IACH,CAAC,CAAC;IAEF,IAAI,MAAM,CAAC,OAAO,KAAK,KAAK,EAAE,CAAC;QAC9B,OAAO;YACN,OAAO,EAAE;gBACR;oBACC,IAAI,EAAE,MAAe;oBACrB,IAAI,EAAE,mBAAmB,CAAC;wBACzB,KAAK,EAAE,MAAM,CAAC,KAAK;wBACnB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAC,KAAK,EAAE,MAAM,CAAC,KAAK,EAAC,CAAC,CAAC,CAAC,EAAE,CAAC;qBAC9C,CAAC;iBACF;aACD;YACD,OAAO,EAAE,IAAI;SACb,CAAC;IACH,CAAC;IAED,OAAO;QACN,OAAO,EAAE;YACR;gBACC,IAAI,EAAE,MAAe;gBACrB,IAAI,EAAE,mBAAmB,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;aAC3C;SACD;KACD,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Address } from 'viem';
|
|
2
|
+
/**
|
|
3
|
+
* Compute the toHash used in fleet commit phase
|
|
4
|
+
* This hashes the destination planet and secret together
|
|
5
|
+
*
|
|
6
|
+
* @param toPlanetId - The destination planet location ID
|
|
7
|
+
* @param secret - The secret value to commit to
|
|
8
|
+
* @returns The hash commitment (keccak256 hash)
|
|
9
|
+
*/
|
|
10
|
+
export declare function computeToHash(toPlanetId: bigint, secret: `0x${string}`, options: {
|
|
11
|
+
gift: boolean;
|
|
12
|
+
specific: Address;
|
|
13
|
+
arrivalTimeWanted: bigint;
|
|
14
|
+
}): `0x${string}`;
|
|
15
|
+
/**
|
|
16
|
+
* Compute the fleet ID from send transaction parameters
|
|
17
|
+
* The fleet ID is computed from: toHash, from, fleetSender, operator
|
|
18
|
+
* This matches what the contract emits in the FleetSent event
|
|
19
|
+
*
|
|
20
|
+
* @param toHash - The hash commitment to destination and secret
|
|
21
|
+
* @param fromPlanetId - The source planet location ID
|
|
22
|
+
* @param fleetSender - The address that owns the fleet
|
|
23
|
+
* @param operator - The address that committed the transaction
|
|
24
|
+
* @returns The fleet ID (keccak256 hash)
|
|
25
|
+
*/
|
|
26
|
+
export declare function computeFleetId(toHash: `0x${string}`, fromPlanetId: bigint, fleetSender: Address, operator: Address): `0x${string}`;
|
|
27
|
+
/**
|
|
28
|
+
* Generate a random secret for fleet commitment
|
|
29
|
+
*
|
|
30
|
+
* @returns A cryptographically random 32-byte hex string
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateSecret(): `0x${string}`;
|
|
33
|
+
//# sourceMappingURL=hashing.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hashing.d.ts","sourceRoot":"","sources":["../../src/util/hashing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAGlC;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAC5B,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,KAAK,MAAM,EAAE,EACrB,OAAO,EAAE;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,OAAO,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAC,GACpE,KAAK,MAAM,EAAE,CAQf;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC7B,MAAM,EAAE,KAAK,MAAM,EAAE,EACrB,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,OAAO,EACpB,QAAQ,EAAE,OAAO,GACf,KAAK,MAAM,EAAE,CAOf;AAED;;;;GAIG;AACH,wBAAgB,cAAc,IAAI,KAAK,MAAM,EAAE,CAI9C"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { encodePacked, keccak256 } from 'viem';
|
|
2
|
+
/**
|
|
3
|
+
* Compute the toHash used in fleet commit phase
|
|
4
|
+
* This hashes the destination planet and secret together
|
|
5
|
+
*
|
|
6
|
+
* @param toPlanetId - The destination planet location ID
|
|
7
|
+
* @param secret - The secret value to commit to
|
|
8
|
+
* @returns The hash commitment (keccak256 hash)
|
|
9
|
+
*/
|
|
10
|
+
export function computeToHash(toPlanetId, secret, options) {
|
|
11
|
+
const toHash = keccak256(encodePacked(['bytes32', 'uint256', 'bool', 'address', 'uint256'], [secret, toPlanetId, options.gift, options.specific, options.arrivalTimeWanted]));
|
|
12
|
+
return toHash;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Compute the fleet ID from send transaction parameters
|
|
16
|
+
* The fleet ID is computed from: toHash, from, fleetSender, operator
|
|
17
|
+
* This matches what the contract emits in the FleetSent event
|
|
18
|
+
*
|
|
19
|
+
* @param toHash - The hash commitment to destination and secret
|
|
20
|
+
* @param fromPlanetId - The source planet location ID
|
|
21
|
+
* @param fleetSender - The address that owns the fleet
|
|
22
|
+
* @param operator - The address that committed the transaction
|
|
23
|
+
* @returns The fleet ID (keccak256 hash)
|
|
24
|
+
*/
|
|
25
|
+
export function computeFleetId(toHash, fromPlanetId, fleetSender, operator) {
|
|
26
|
+
return keccak256(encodePacked(['bytes32', 'uint256', 'address', 'address'], [toHash, BigInt(fromPlanetId), fleetSender, operator]));
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Generate a random secret for fleet commitment
|
|
30
|
+
*
|
|
31
|
+
* @returns A cryptographically random 32-byte hex string
|
|
32
|
+
*/
|
|
33
|
+
export function generateSecret() {
|
|
34
|
+
const randomBytes = new Uint8Array(32);
|
|
35
|
+
crypto.getRandomValues(randomBytes);
|
|
36
|
+
return `0x${Buffer.from(randomBytes).toString('hex')}`;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=hashing.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hashing.js","sourceRoot":"","sources":["../../src/util/hashing.ts"],"names":[],"mappings":"AACA,OAAO,EAAsB,YAAY,EAAE,SAAS,EAAc,MAAM,MAAM,CAAC;AAE/E;;;;;;;GAOG;AACH,MAAM,UAAU,aAAa,CAC5B,UAAkB,EAClB,MAAqB,EACrB,OAAsE;IAEtE,MAAM,MAAM,GAAG,SAAS,CACvB,YAAY,CACX,CAAC,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC,EACpD,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAC/E,CACD,CAAC;IACF,OAAO,MAAM,CAAC;AACf,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,cAAc,CAC7B,MAAqB,EACrB,YAAoB,EACpB,WAAoB,EACpB,QAAiB;IAEjB,OAAO,SAAS,CACf,YAAY,CACX,CAAC,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,CAAC,EAC5C,CAAC,MAAM,EAAE,MAAM,CAAC,YAAY,CAAC,EAAE,WAAW,EAAE,QAAQ,CAAC,CACrD,CACD,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc;IAC7B,MAAM,WAAW,GAAG,IAAI,UAAU,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC;IACpC,OAAO,KAAK,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;AACxD,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get current timestamp in seconds
|
|
3
|
+
*/
|
|
4
|
+
export declare function getCurrentTimestamp(): number;
|
|
5
|
+
/**
|
|
6
|
+
* Calculate estimated arrival time based on distance and timePerDistance
|
|
7
|
+
*
|
|
8
|
+
* @param distance - The distance between planets
|
|
9
|
+
* @param timePerDistance - Time multiplier from contract config (seconds per distance unit)
|
|
10
|
+
* @param genesis - Genesis timestamp from contract config
|
|
11
|
+
* @returns Estimated arrival time in seconds
|
|
12
|
+
*/
|
|
13
|
+
export declare function calculateEstimatedArrivalTime(params: {
|
|
14
|
+
startTime: bigint;
|
|
15
|
+
distance: bigint;
|
|
16
|
+
timePerDistance: bigint;
|
|
17
|
+
}): number;
|
|
18
|
+
/**
|
|
19
|
+
* Calculate when the resolve window opens
|
|
20
|
+
* A fleet can be resolved after it arrives and the resolve window has passed
|
|
21
|
+
*
|
|
22
|
+
* @param estimatedArrivalTime - When the fleet is estimated to arrive
|
|
23
|
+
* @param resolveWindow - The resolve window duration in seconds from contract config
|
|
24
|
+
* @returns The timestamp when the fleet can be resolved
|
|
25
|
+
*/
|
|
26
|
+
export declare function calculateResolveWindowOpen(estimatedArrivalTime: number, resolveWindow: bigint): number;
|
|
27
|
+
/**
|
|
28
|
+
* Check if a fleet can be resolved now
|
|
29
|
+
*
|
|
30
|
+
* @param estimatedArrivalTime - When the fleet was estimated to arrive
|
|
31
|
+
* @param resolveWindow - The resolve window duration in seconds
|
|
32
|
+
* @returns True if the fleet can be resolved now
|
|
33
|
+
*/
|
|
34
|
+
export declare function canResolveNow(estimatedArrivalTime: number, resolveWindow: bigint): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Format timestamp as ISO string
|
|
37
|
+
*/
|
|
38
|
+
export declare function formatTimestamp(timestamp: number): string;
|
|
39
|
+
/**
|
|
40
|
+
* Parse ISO string to timestamp
|
|
41
|
+
*/
|
|
42
|
+
export declare function parseTimestamp(isoString: string): number;
|
|
43
|
+
//# sourceMappingURL=time.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/util/time.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAED;;;;;;;GAOG;AACH,wBAAgB,6BAA6B,CAAC,MAAM,EAAE;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;CACxB,GAAG,MAAM,CAIT;AAED;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACzC,oBAAoB,EAAE,MAAM,EAC5B,aAAa,EAAE,MAAM,GACnB,MAAM,CAER;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,oBAAoB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,GAAG,OAAO,CAI1F;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,CAExD"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get current timestamp in seconds
|
|
3
|
+
*/
|
|
4
|
+
export function getCurrentTimestamp() {
|
|
5
|
+
return Math.floor(Date.now() / 1000);
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Calculate estimated arrival time based on distance and timePerDistance
|
|
9
|
+
*
|
|
10
|
+
* @param distance - The distance between planets
|
|
11
|
+
* @param timePerDistance - Time multiplier from contract config (seconds per distance unit)
|
|
12
|
+
* @param genesis - Genesis timestamp from contract config
|
|
13
|
+
* @returns Estimated arrival time in seconds
|
|
14
|
+
*/
|
|
15
|
+
export function calculateEstimatedArrivalTime(params) {
|
|
16
|
+
const { startTime, distance, timePerDistance } = params;
|
|
17
|
+
const travelTime = Number(distance) * Number(timePerDistance);
|
|
18
|
+
return Number(startTime) + travelTime;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Calculate when the resolve window opens
|
|
22
|
+
* A fleet can be resolved after it arrives and the resolve window has passed
|
|
23
|
+
*
|
|
24
|
+
* @param estimatedArrivalTime - When the fleet is estimated to arrive
|
|
25
|
+
* @param resolveWindow - The resolve window duration in seconds from contract config
|
|
26
|
+
* @returns The timestamp when the fleet can be resolved
|
|
27
|
+
*/
|
|
28
|
+
export function calculateResolveWindowOpen(estimatedArrivalTime, resolveWindow) {
|
|
29
|
+
return estimatedArrivalTime + Number(resolveWindow);
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Check if a fleet can be resolved now
|
|
33
|
+
*
|
|
34
|
+
* @param estimatedArrivalTime - When the fleet was estimated to arrive
|
|
35
|
+
* @param resolveWindow - The resolve window duration in seconds
|
|
36
|
+
* @returns True if the fleet can be resolved now
|
|
37
|
+
*/
|
|
38
|
+
export function canResolveNow(estimatedArrivalTime, resolveWindow) {
|
|
39
|
+
const currentTime = getCurrentTimestamp();
|
|
40
|
+
const resolveWindowOpen = calculateResolveWindowOpen(estimatedArrivalTime, resolveWindow);
|
|
41
|
+
return currentTime >= resolveWindowOpen;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Format timestamp as ISO string
|
|
45
|
+
*/
|
|
46
|
+
export function formatTimestamp(timestamp) {
|
|
47
|
+
return new Date(timestamp * 1000).toISOString();
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Parse ISO string to timestamp
|
|
51
|
+
*/
|
|
52
|
+
export function parseTimestamp(isoString) {
|
|
53
|
+
return Math.floor(new Date(isoString).getTime() / 1000);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=time.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"time.js","sourceRoot":"","sources":["../../src/util/time.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,UAAU,mBAAmB;IAClC,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,6BAA6B,CAAC,MAI7C;IACA,MAAM,EAAC,SAAS,EAAE,QAAQ,EAAE,eAAe,EAAC,GAAG,MAAM,CAAC;IACtD,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC;IAC9D,OAAO,MAAM,CAAC,SAAS,CAAC,GAAG,UAAU,CAAC;AACvC,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,0BAA0B,CACzC,oBAA4B,EAC5B,aAAqB;IAErB,OAAO,oBAAoB,GAAG,MAAM,CAAC,aAAa,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,oBAA4B,EAAE,aAAqB;IAChF,MAAM,WAAW,GAAG,mBAAmB,EAAE,CAAC;IAC1C,MAAM,iBAAiB,GAAG,0BAA0B,CAAC,oBAAoB,EAAE,aAAa,CAAC,CAAC;IAC1F,OAAO,WAAW,IAAI,iBAAiB,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,SAAiB;IAChD,OAAO,IAAI,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;AACjD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,CAAC;AACzD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@conquest-eth/tools",
|
|
3
|
+
"version": "0.0.0",
|
|
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
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
45
|
+
"commander": "^14.0.3",
|
|
46
|
+
"conquest-eth-v0-contracts": "workspace:*",
|
|
47
|
+
"eip-1193": "^0.6.5",
|
|
48
|
+
"ldenv": "^0.3.16",
|
|
49
|
+
"remote-procedure-call": "^0.1.1",
|
|
50
|
+
"tools-ethereum": "^0.0.1",
|
|
51
|
+
"viem": "^2.45.1",
|
|
52
|
+
"zod": "^4.3.6"
|
|
53
|
+
},
|
|
54
|
+
"devDependencies": {
|
|
55
|
+
"@changesets/cli": "^2.29.8",
|
|
56
|
+
"@modelcontextprotocol/inspector": "^0.19.0",
|
|
57
|
+
"@types/node": "^25.2.0",
|
|
58
|
+
"as-soon": "^0.1.5",
|
|
59
|
+
"prettier": "^3.8.0",
|
|
60
|
+
"reloaderoo": "^1.1.5",
|
|
61
|
+
"tsx": "^4.21.0",
|
|
62
|
+
"typescript": "^5.3.3",
|
|
63
|
+
"vitest": "^4.0.18"
|
|
64
|
+
},
|
|
65
|
+
"scripts": {
|
|
66
|
+
"prepublishOnly": "pnpm format:check && pnpm build",
|
|
67
|
+
"release": "pnpm prepublishOnly && git push --all && pnpm changeset publish && git push --tags",
|
|
68
|
+
"format": "prettier --write .",
|
|
69
|
+
"format:check": "prettier --check .",
|
|
70
|
+
"build": "tsc",
|
|
71
|
+
"dev": "as-soon -w src pnpm build",
|
|
72
|
+
"test": "vitest run",
|
|
73
|
+
"test:watch": "vitest",
|
|
74
|
+
"mcp:inspector": "mcp-inspector",
|
|
75
|
+
"reloaderoo": "reloaderoo",
|
|
76
|
+
"start": "reloaderoo proxy --log-level debug -- node ./dist/cli.js --rpc-url http://localhost:8545 --game-contract 0x322813fd9a801c5507c9de605d63cea4f2ce6c44 mcp --ethereum"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
@@ -0,0 +1,287 @@
|
|
|
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
|
+
}
|