@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.
Files changed (143) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +259 -0
  3. package/dist/cli-tool-generator.d.ts +22 -0
  4. package/dist/cli-tool-generator.d.ts.map +1 -0
  5. package/dist/cli-tool-generator.js +217 -0
  6. package/dist/cli-tool-generator.js.map +1 -0
  7. package/dist/cli.d.ts +3 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +76 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/contracts/space-info.d.ts +7 -0
  12. package/dist/contracts/space-info.d.ts.map +1 -0
  13. package/dist/contracts/space-info.js +34 -0
  14. package/dist/contracts/space-info.js.map +1 -0
  15. package/dist/fleet/index.d.ts +4 -0
  16. package/dist/fleet/index.d.ts.map +1 -0
  17. package/dist/fleet/index.js +7 -0
  18. package/dist/fleet/index.js.map +1 -0
  19. package/dist/fleet/manager.d.ts +70 -0
  20. package/dist/fleet/manager.d.ts.map +1 -0
  21. package/dist/fleet/manager.js +92 -0
  22. package/dist/fleet/manager.js.map +1 -0
  23. package/dist/fleet/resolve.d.ts +51 -0
  24. package/dist/fleet/resolve.d.ts.map +1 -0
  25. package/dist/fleet/resolve.js +140 -0
  26. package/dist/fleet/resolve.js.map +1 -0
  27. package/dist/fleet/send.d.ts +29 -0
  28. package/dist/fleet/send.d.ts.map +1 -0
  29. package/dist/fleet/send.js +81 -0
  30. package/dist/fleet/send.js.map +1 -0
  31. package/dist/helpers/index.d.ts +14 -0
  32. package/dist/helpers/index.d.ts.map +1 -0
  33. package/dist/helpers/index.js +28 -0
  34. package/dist/helpers/index.js.map +1 -0
  35. package/dist/index.d.ts +36 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +143 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/planet/acquire.d.ts +16 -0
  40. package/dist/planet/acquire.d.ts.map +1 -0
  41. package/dist/planet/acquire.js +27 -0
  42. package/dist/planet/acquire.js.map +1 -0
  43. package/dist/planet/exit.d.ts +17 -0
  44. package/dist/planet/exit.d.ts.map +1 -0
  45. package/dist/planet/exit.js +56 -0
  46. package/dist/planet/exit.js.map +1 -0
  47. package/dist/planet/index.d.ts +4 -0
  48. package/dist/planet/index.d.ts.map +1 -0
  49. package/dist/planet/index.js +6 -0
  50. package/dist/planet/index.js.map +1 -0
  51. package/dist/planet/manager.d.ts +106 -0
  52. package/dist/planet/manager.d.ts.map +1 -0
  53. package/dist/planet/manager.js +253 -0
  54. package/dist/planet/manager.js.map +1 -0
  55. package/dist/storage/interface.d.ts +93 -0
  56. package/dist/storage/interface.d.ts.map +1 -0
  57. package/dist/storage/interface.js +2 -0
  58. package/dist/storage/interface.js.map +1 -0
  59. package/dist/storage/json-storage.d.ts +28 -0
  60. package/dist/storage/json-storage.d.ts.map +1 -0
  61. package/dist/storage/json-storage.js +148 -0
  62. package/dist/storage/json-storage.js.map +1 -0
  63. package/dist/tools/acquire_planets.d.ts +7 -0
  64. package/dist/tools/acquire_planets.d.ts.map +1 -0
  65. package/dist/tools/acquire_planets.js +63 -0
  66. package/dist/tools/acquire_planets.js.map +1 -0
  67. package/dist/tools/exit_planets.d.ts +5 -0
  68. package/dist/tools/exit_planets.d.ts.map +1 -0
  69. package/dist/tools/exit_planets.js +31 -0
  70. package/dist/tools/exit_planets.js.map +1 -0
  71. package/dist/tools/get_my_planets.d.ts +5 -0
  72. package/dist/tools/get_my_planets.d.ts.map +1 -0
  73. package/dist/tools/get_my_planets.js +30 -0
  74. package/dist/tools/get_my_planets.js.map +1 -0
  75. package/dist/tools/get_pending_exits.d.ts +3 -0
  76. package/dist/tools/get_pending_exits.d.ts.map +1 -0
  77. package/dist/tools/get_pending_exits.js +37 -0
  78. package/dist/tools/get_pending_exits.js.map +1 -0
  79. package/dist/tools/get_pending_fleets.d.ts +3 -0
  80. package/dist/tools/get_pending_fleets.d.ts.map +1 -0
  81. package/dist/tools/get_pending_fleets.js +41 -0
  82. package/dist/tools/get_pending_fleets.js.map +1 -0
  83. package/dist/tools/get_planets_around.d.ts +7 -0
  84. package/dist/tools/get_planets_around.d.ts.map +1 -0
  85. package/dist/tools/get_planets_around.js +41 -0
  86. package/dist/tools/get_planets_around.js.map +1 -0
  87. package/dist/tools/index.d.ts +10 -0
  88. package/dist/tools/index.d.ts.map +1 -0
  89. package/dist/tools/index.js +11 -0
  90. package/dist/tools/index.js.map +1 -0
  91. package/dist/tools/resolve_fleet.d.ts +5 -0
  92. package/dist/tools/resolve_fleet.d.ts.map +1 -0
  93. package/dist/tools/resolve_fleet.js +37 -0
  94. package/dist/tools/resolve_fleet.js.map +1 -0
  95. package/dist/tools/send_fleet.d.ts +16 -0
  96. package/dist/tools/send_fleet.d.ts.map +1 -0
  97. package/dist/tools/send_fleet.js +62 -0
  98. package/dist/tools/send_fleet.js.map +1 -0
  99. package/dist/tools/verify_exit_status.d.ts +5 -0
  100. package/dist/tools/verify_exit_status.d.ts.map +1 -0
  101. package/dist/tools/verify_exit_status.js +39 -0
  102. package/dist/tools/verify_exit_status.js.map +1 -0
  103. package/dist/types.d.ts +126 -0
  104. package/dist/types.d.ts.map +1 -0
  105. package/dist/types.js +34 -0
  106. package/dist/types.js.map +1 -0
  107. package/dist/util/hashing.d.ts +33 -0
  108. package/dist/util/hashing.d.ts.map +1 -0
  109. package/dist/util/hashing.js +38 -0
  110. package/dist/util/hashing.js.map +1 -0
  111. package/dist/util/time.d.ts +43 -0
  112. package/dist/util/time.d.ts.map +1 -0
  113. package/dist/util/time.js +55 -0
  114. package/dist/util/time.js.map +1 -0
  115. package/package.json +78 -0
  116. package/src/cli-tool-generator.ts +287 -0
  117. package/src/cli.ts +109 -0
  118. package/src/contracts/space-info.ts +41 -0
  119. package/src/fleet/index.ts +8 -0
  120. package/src/fleet/manager.ts +140 -0
  121. package/src/fleet/resolve.ts +187 -0
  122. package/src/fleet/send.ts +112 -0
  123. package/src/helpers/index.ts +59 -0
  124. package/src/index.ts +181 -0
  125. package/src/planet/acquire.ts +41 -0
  126. package/src/planet/exit.ts +71 -0
  127. package/src/planet/index.ts +6 -0
  128. package/src/planet/manager.ts +335 -0
  129. package/src/storage/interface.ts +111 -0
  130. package/src/storage/json-storage.ts +184 -0
  131. package/src/tools/acquire_planets.ts +81 -0
  132. package/src/tools/exit_planets.ts +35 -0
  133. package/src/tools/get_my_planets.ts +30 -0
  134. package/src/tools/get_pending_exits.ts +37 -0
  135. package/src/tools/get_pending_fleets.ts +41 -0
  136. package/src/tools/get_planets_around.ts +44 -0
  137. package/src/tools/index.ts +10 -0
  138. package/src/tools/resolve_fleet.ts +37 -0
  139. package/src/tools/send_fleet.ts +68 -0
  140. package/src/tools/verify_exit_status.ts +43 -0
  141. package/src/types.ts +178 -0
  142. package/src/util/hashing.ts +60 -0
  143. 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
+ }