@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
@@ -0,0 +1,111 @@
1
+ import type {Address} from 'viem';
2
+ import {PendingExit, PendingFleet} from '../types.js';
3
+
4
+ /**
5
+ * Storage interface for managing fleets and planet exits
6
+ * Provides methods to persist and retrieve game state data
7
+ */
8
+ export interface FleetStorage {
9
+ // Fleet operations
10
+
11
+ /**
12
+ * Save a pending fleet to storage
13
+ * @param fleet - The fleet to save
14
+ */
15
+ saveFleet(fleet: PendingFleet): Promise<void>;
16
+
17
+ /**
18
+ * Retrieve a fleet by its ID
19
+ * @param fleetId - The fleet ID to retrieve
20
+ * @returns The fleet or null if not found
21
+ */
22
+ getFleet(fleetId: string): Promise<PendingFleet | null>;
23
+
24
+ /**
25
+ * Get all pending fleets for a specific sender
26
+ * @param sender - The address of the fleet sender
27
+ * @returns Array of pending fleets
28
+ */
29
+ getPendingFleetsBySender(sender: Address): Promise<PendingFleet[]>;
30
+
31
+ /**
32
+ * Get all fleets that can be resolved (not yet resolved)
33
+ * @returns Array of resolvable fleets
34
+ */
35
+ getResolvableFleets(): Promise<PendingFleet[]>;
36
+
37
+ /**
38
+ * Mark a fleet as resolved
39
+ * @param fleetId - The fleet ID to mark as resolved
40
+ * @param resolvedAt - The timestamp when the fleet was resolved
41
+ */
42
+ markResolved(fleetId: string, resolvedAt: number): Promise<void>;
43
+
44
+ /**
45
+ * Clean up old resolved fleets from storage
46
+ * @param olderThan - Unix timestamp; fleets resolved before this time will be removed
47
+ */
48
+ cleanupOldResolvedFleets(olderThan: number): Promise<void>;
49
+
50
+ /**
51
+ * Get all fleets in storage
52
+ * @returns Array of all fleets
53
+ */
54
+ getAllFleets(): Promise<PendingFleet[]>;
55
+
56
+ // Exit operations
57
+
58
+ /**
59
+ * Save a pending exit to storage
60
+ * @param exit - The exit to save
61
+ */
62
+ savePendingExit(exit: PendingExit): Promise<void>;
63
+
64
+ /**
65
+ * Retrieve a pending exit by planet ID
66
+ * @param planetId - The planet location ID
67
+ * @returns The pending exit or null if not found
68
+ */
69
+ getPendingExit(planetId: bigint): Promise<PendingExit | null>;
70
+
71
+ /**
72
+ * Get all pending exits for a specific player
73
+ * @param player - The address of the player
74
+ * @returns Array of pending exits
75
+ */
76
+ getPendingExitsByPlayer(player: Address): Promise<PendingExit[]>;
77
+
78
+ /**
79
+ * Update the status of a pending exit
80
+ * @param planetId - The planet location ID
81
+ * @param updates - Partial updates to apply to the exit record
82
+ */
83
+ updateExitStatus(planetId: bigint, updates: Partial<PendingExit>): Promise<void>;
84
+
85
+ /**
86
+ * Mark an exit as completed
87
+ * @param planetId - The planet location ID
88
+ * @param completedAt - The timestamp when the exit completed
89
+ */
90
+ markExitCompleted(planetId: bigint, completedAt: number): Promise<void>;
91
+
92
+ /**
93
+ * Mark an exit as interrupted by an attack
94
+ * @param planetId - The planet location ID
95
+ * @param interruptedAt - The timestamp when the exit was interrupted
96
+ * @param newOwner - The address of the new owner who interrupted the exit
97
+ */
98
+ markExitInterrupted(planetId: bigint, interruptedAt: number, newOwner: Address): Promise<void>;
99
+
100
+ /**
101
+ * Clean up old completed exits from storage
102
+ * @param olderThan - Unix timestamp; exits completed before this time will be removed
103
+ */
104
+ cleanupOldCompletedExits(olderThan: number): Promise<void>;
105
+
106
+ /**
107
+ * Get all pending exits in storage
108
+ * @returns Array of all pending exits
109
+ */
110
+ getAllPendingExits(): Promise<PendingExit[]>;
111
+ }
@@ -0,0 +1,184 @@
1
+ import {promises as fs} from 'fs';
2
+ import path from 'path';
3
+ import type {Address} from 'viem';
4
+ import type {FleetStorage} from './interface.js';
5
+ import {PendingExit, PendingFleet} from '../types.js';
6
+ import {stringifyWithBigInt} from '../helpers/index.js';
7
+
8
+ interface StorageData {
9
+ fleets: Record<string, PendingFleet>;
10
+ exits: Record<string, PendingExit>;
11
+ }
12
+
13
+ export class JsonFleetStorage implements FleetStorage {
14
+ private dataPath: string;
15
+ private data: StorageData;
16
+ private initialized = false;
17
+
18
+ constructor(dataDir: string = './data') {
19
+ this.dataPath = path.join(dataDir, 'conquest-data.json');
20
+ this.data = {fleets: {}, exits: {}};
21
+ }
22
+
23
+ async initialize(): Promise<void> {
24
+ if (this.initialized) {
25
+ return;
26
+ }
27
+ // Load from disk or create new
28
+ try {
29
+ await fs.mkdir(path.dirname(this.dataPath), {recursive: true});
30
+ const content = await fs.readFile(this.dataPath, 'utf-8');
31
+ const data = JSON.parse(content);
32
+ // Convert BigInt strings back to BigInt
33
+ for (const fleetId in data.fleets) {
34
+ const fleet = data.fleets[fleetId];
35
+ fleet.fromPlanetId = BigInt(fleet.fromPlanetId);
36
+ fleet.toPlanetId = BigInt(fleet.toPlanetId);
37
+ fleet.arrivalTimeWanted = BigInt(fleet.arrivalTimeWanted);
38
+ }
39
+ for (const planetId in data.exits) {
40
+ const exit = data.exits[planetId];
41
+ exit.planetId = BigInt(exit.planetId);
42
+ }
43
+ this.data = data;
44
+ } catch (error) {
45
+ // File doesn't exist, create new
46
+ await this.save();
47
+ }
48
+ this.initialized = true;
49
+ }
50
+
51
+ private async ensureInitialized(): Promise<void> {
52
+ if (!this.initialized) {
53
+ await this.initialize();
54
+ }
55
+ }
56
+
57
+ private async save(): Promise<void> {
58
+ await fs.writeFile(this.dataPath, stringifyWithBigInt(this.data, 2));
59
+ }
60
+
61
+ // Fleet operations
62
+ async saveFleet(fleet: PendingFleet): Promise<void> {
63
+ await this.ensureInitialized();
64
+ this.data.fleets[fleet.fleetId] = fleet;
65
+ await this.save();
66
+ }
67
+
68
+ async getFleet(fleetId: string): Promise<PendingFleet | null> {
69
+ await this.ensureInitialized();
70
+ return this.data.fleets[fleetId] || null;
71
+ }
72
+
73
+ async getPendingFleetsBySender(sender: Address): Promise<PendingFleet[]> {
74
+ await this.ensureInitialized();
75
+ return Object.values(this.data.fleets).filter(
76
+ (fleet) => fleet.fleetSender.toLowerCase() === sender.toLowerCase() && !fleet.resolved,
77
+ );
78
+ }
79
+
80
+ async getResolvableFleets(): Promise<PendingFleet[]> {
81
+ await this.ensureInitialized();
82
+ const now = Math.floor(Date.now() / 1000);
83
+ return Object.values(this.data.fleets).filter(
84
+ (fleet) => !fleet.resolved && fleet.estimatedArrivalTime <= now,
85
+ );
86
+ }
87
+
88
+ async markResolved(fleetId: string, resolvedAt: number): Promise<void> {
89
+ await this.ensureInitialized();
90
+ const fleet = this.data.fleets[fleetId];
91
+ if (fleet) {
92
+ fleet.resolved = true;
93
+ fleet.resolvedAt = resolvedAt;
94
+ await this.save();
95
+ }
96
+ }
97
+
98
+ async cleanupOldResolvedFleets(olderThan: number): Promise<void> {
99
+ await this.ensureInitialized();
100
+ const now = Math.floor(Date.now() / 1000);
101
+ for (const fleetId in this.data.fleets) {
102
+ const fleet = this.data.fleets[fleetId];
103
+ if (fleet.resolved && fleet.resolvedAt && fleet.resolvedAt < now - olderThan) {
104
+ delete this.data.fleets[fleetId];
105
+ }
106
+ }
107
+ await this.save();
108
+ }
109
+
110
+ async getAllFleets(): Promise<PendingFleet[]> {
111
+ await this.ensureInitialized();
112
+ return Object.values(this.data.fleets);
113
+ }
114
+
115
+ // Exit operations
116
+ async savePendingExit(exit: PendingExit): Promise<void> {
117
+ await this.ensureInitialized();
118
+ this.data.exits[exit.planetId.toString()] = exit;
119
+ await this.save();
120
+ }
121
+
122
+ async getPendingExit(planetId: bigint): Promise<PendingExit | null> {
123
+ await this.ensureInitialized();
124
+ return this.data.exits[planetId.toString()] || null;
125
+ }
126
+
127
+ async getPendingExitsByPlayer(player: Address): Promise<PendingExit[]> {
128
+ await this.ensureInitialized();
129
+ return Object.values(this.data.exits).filter(
130
+ (exit) => exit.player.toLowerCase() === player.toLowerCase() && !exit.completed,
131
+ );
132
+ }
133
+
134
+ async updateExitStatus(planetId: bigint, updates: Partial<PendingExit>): Promise<void> {
135
+ await this.ensureInitialized();
136
+ const exit = this.data.exits[planetId.toString()];
137
+ if (exit) {
138
+ Object.assign(exit, updates);
139
+ await this.save();
140
+ }
141
+ }
142
+
143
+ async markExitCompleted(planetId: bigint, completedAt: number): Promise<void> {
144
+ await this.ensureInitialized();
145
+ const exit = this.data.exits[planetId.toString()];
146
+ if (exit) {
147
+ exit.completed = true;
148
+ exit.lastCheckedAt = completedAt;
149
+ await this.save();
150
+ }
151
+ }
152
+
153
+ async markExitInterrupted(
154
+ planetId: bigint,
155
+ interruptedAt: number,
156
+ newOwner: Address,
157
+ ): Promise<void> {
158
+ await this.ensureInitialized();
159
+ const exit = this.data.exits[planetId.toString()];
160
+ if (exit) {
161
+ exit.interrupted = true;
162
+ exit.lastCheckedAt = interruptedAt;
163
+ exit.owner = newOwner;
164
+ await this.save();
165
+ }
166
+ }
167
+
168
+ async cleanupOldCompletedExits(olderThan: number): Promise<void> {
169
+ await this.ensureInitialized();
170
+ const now = Math.floor(Date.now() / 1000);
171
+ for (const planetId in this.data.exits) {
172
+ const exit = this.data.exits[planetId];
173
+ if (exit.completed && exit.lastCheckedAt < now - olderThan) {
174
+ delete this.data.exits[planetId];
175
+ }
176
+ }
177
+ await this.save();
178
+ }
179
+
180
+ async getAllPendingExits(): Promise<PendingExit[]> {
181
+ await this.ensureInitialized();
182
+ return Object.values(this.data.exits);
183
+ }
184
+ }
@@ -0,0 +1,81 @@
1
+ import {z} from 'zod';
2
+ import {createTool} from '../types.js';
3
+ import {stringifyWithBigInt} from '../helpers/index.js';
4
+
5
+ export const acquire_planets = createTool({
6
+ description:
7
+ 'Acquire (stake) multiple planets in the Conquest game. This allows you to take ownership of unclaimed planets.',
8
+ schema: z.object({
9
+ planetIds: z
10
+ .array(z.union([z.string(), z.number()]))
11
+ .describe('Array of planet location IDs to acquire (as hex strings or numbers)'),
12
+ amountToMint: z
13
+ .number()
14
+ .optional()
15
+ .describe(
16
+ 'Amount of native token to spend to acquire the planets. If not provided, will be calculated automatically based on planet stats.',
17
+ ),
18
+ tokenAmount: z
19
+ .number()
20
+ .optional()
21
+ .describe(
22
+ 'Amount of staking token to spend to acquire the planets. If not provided, will be calculated automatically based on planet stats.',
23
+ ),
24
+ }),
25
+ execute: async (env, {planetIds, amountToMint, tokenAmount}) => {
26
+ try {
27
+ // Convert planet IDs to BigInt
28
+ const planetIdsBigInt = planetIds.map((id) =>
29
+ typeof id === 'string' ? BigInt(id) : BigInt(id),
30
+ );
31
+
32
+ let result: {
33
+ hash: `0x${string}`;
34
+ planetsAcquired: bigint[];
35
+ amountToMint: bigint;
36
+ tokenAmount: bigint;
37
+ };
38
+
39
+ // If BOTH amounts are provided, use them; otherwise use auto-calculation
40
+ if (amountToMint !== undefined && tokenAmount !== undefined) {
41
+ // Use provided amounts
42
+ // TODO decimal handling, for now BigInt()
43
+ const acquireResult = await env.planetManager.acquire(
44
+ planetIdsBigInt,
45
+ BigInt(amountToMint),
46
+ BigInt(tokenAmount),
47
+ );
48
+ result = {
49
+ hash: acquireResult.hash,
50
+ planetsAcquired: acquireResult.planetsAcquired,
51
+ amountToMint: BigInt(amountToMint),
52
+ tokenAmount: BigInt(tokenAmount),
53
+ };
54
+ } else {
55
+ // Use auto-calculation
56
+ const autoResult = await env.planetManager.acquireWithAutoCalc(planetIdsBigInt);
57
+ result = {
58
+ hash: autoResult.hash,
59
+ planetsAcquired: autoResult.planetsAcquired,
60
+ amountToMint: autoResult.costs.amountToMint,
61
+ tokenAmount: autoResult.costs.tokenAmount,
62
+ };
63
+ }
64
+
65
+ return {
66
+ success: true,
67
+ result: {
68
+ transactionHash: result.hash,
69
+ planetsAcquired: result.planetsAcquired,
70
+ amountToMint: result.amountToMint,
71
+ tokenAmount: result.tokenAmount,
72
+ },
73
+ };
74
+ } catch (error) {
75
+ return {
76
+ success: false,
77
+ error: error instanceof Error ? error.message : String(error),
78
+ };
79
+ }
80
+ },
81
+ });
@@ -0,0 +1,35 @@
1
+ import {z} from 'zod';
2
+ import {createTool} from '../types.js';
3
+
4
+ export const exit_planets = createTool({
5
+ description:
6
+ 'Exit (unstake) multiple planets to retrieve staked tokens. The exit process takes time and must be completed later.',
7
+ schema: z.object({
8
+ planetIds: z
9
+ .array(z.union([z.string(), z.number()]))
10
+ .describe('Array of planet location IDs to exit (as hex strings or numbers)'),
11
+ }),
12
+ execute: async (env, {planetIds}) => {
13
+ try {
14
+ // Convert planet IDs to BigInt
15
+ const planetIdsBigInt = planetIds.map((id) =>
16
+ typeof id === 'string' ? BigInt(id) : BigInt(id),
17
+ );
18
+
19
+ const result = await env.planetManager.exit(planetIdsBigInt);
20
+
21
+ return {
22
+ success: true,
23
+ result: {
24
+ transactionHash: result.hash,
25
+ exitsInitiated: result.exitsInitiated,
26
+ },
27
+ };
28
+ } catch (error) {
29
+ return {
30
+ success: false,
31
+ error: error instanceof Error ? error.message : String(error),
32
+ };
33
+ }
34
+ },
35
+ });
@@ -0,0 +1,30 @@
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
+ });
@@ -0,0 +1,37 @@
1
+ import {z} from 'zod';
2
+ import {createTool} from '../types.js';
3
+
4
+ export const get_pending_exits = createTool({
5
+ description: 'Get all pending exit (unstake) operations for your planets.',
6
+ schema: z.object({
7
+ // No properties needed for this tool
8
+ }),
9
+ execute: async (env) => {
10
+ try {
11
+ const exits = await env.planetManager.getMyPendingExits();
12
+
13
+ return {
14
+ success: true,
15
+ result: {
16
+ exits: exits.map((exit) => ({
17
+ planetId: exit.planetId,
18
+ player: exit.player,
19
+ exitStartTime: exit.exitStartTime,
20
+ exitDuration: exit.exitDuration,
21
+ exitCompleteTime: exit.exitCompleteTime,
22
+ numSpaceships: exit.numSpaceships,
23
+ owner: exit.owner,
24
+ completed: exit.completed,
25
+ interrupted: exit.interrupted,
26
+ lastCheckedAt: exit.lastCheckedAt,
27
+ })),
28
+ },
29
+ };
30
+ } catch (error) {
31
+ return {
32
+ success: false,
33
+ error: error instanceof Error ? error.message : String(error),
34
+ };
35
+ }
36
+ },
37
+ });
@@ -0,0 +1,41 @@
1
+ import {z} from 'zod';
2
+ import {createTool} from '../types.js';
3
+
4
+ export const get_pending_fleets = createTool({
5
+ description: 'Get all pending fleets sent from your planets.',
6
+ schema: z.object({
7
+ // No properties needed for this tool
8
+ }),
9
+ execute: async (env) => {
10
+ try {
11
+ const fleets = await env.fleetManager.getMyPendingFleets();
12
+
13
+ return {
14
+ success: true,
15
+ result: {
16
+ fleets: fleets.map((fleet) => ({
17
+ fleetId: fleet.fleetId,
18
+ fromPlanetId: fleet.fromPlanetId,
19
+ toPlanetId: fleet.toPlanetId,
20
+ quantity: fleet.quantity,
21
+ secret: fleet.secret,
22
+ gift: fleet.gift,
23
+ specific: fleet.specific,
24
+ arrivalTimeWanted: fleet.arrivalTimeWanted,
25
+ fleetSender: fleet.fleetSender,
26
+ operator: fleet.operator,
27
+ committedAt: fleet.committedAt,
28
+ estimatedArrivalTime: fleet.estimatedArrivalTime,
29
+ resolved: fleet.resolved,
30
+ resolvedAt: fleet.resolvedAt,
31
+ })),
32
+ },
33
+ };
34
+ } catch (error) {
35
+ return {
36
+ success: false,
37
+ error: error instanceof Error ? error.message : String(error),
38
+ };
39
+ }
40
+ },
41
+ });
@@ -0,0 +1,44 @@
1
+ import {z} from 'zod';
2
+ import {createTool} from '../types.js';
3
+
4
+ export const get_planets_around = createTool({
5
+ description:
6
+ 'Get planets around a specific location within a certain radius. Useful for finding targets for fleet movement.',
7
+ schema: z.object({
8
+ centerX: z.number().describe('X coordinate of the center point'),
9
+ centerY: z.number().describe('Y coordinate of the center point'),
10
+ radius: z
11
+ .number()
12
+ .max(50)
13
+ .describe('Radius in distance units to search around the center point'),
14
+ }),
15
+ execute: async (env, {centerX, centerY, radius}) => {
16
+ try {
17
+ const planets = await env.planetManager.getPlanetsAround(centerX, centerY, radius);
18
+
19
+ return {
20
+ success: true,
21
+ result: {
22
+ center: {
23
+ x: centerX,
24
+ y: centerY,
25
+ },
26
+ radius,
27
+ planets: planets.map(({info, state}) => ({
28
+ planetId: info.location.id,
29
+ distance: Math.sqrt(
30
+ Math.pow(info.location.x - centerX, 2) + Math.pow(info.location.y - centerY, 2),
31
+ ),
32
+ location: info.location,
33
+ ...state,
34
+ })),
35
+ },
36
+ };
37
+ } catch (error) {
38
+ return {
39
+ success: false,
40
+ error: error instanceof Error ? error.message : String(error),
41
+ };
42
+ }
43
+ },
44
+ });
@@ -0,0 +1,10 @@
1
+ // Export all tools for auto-registration
2
+ export {acquire_planets} from './acquire_planets.js';
3
+ export {send_fleet} from './send_fleet.js';
4
+ export {resolve_fleet} from './resolve_fleet.js';
5
+ export {exit_planets} from './exit_planets.js';
6
+ export {get_pending_exits} from './get_pending_exits.js';
7
+ export {verify_exit_status} from './verify_exit_status.js';
8
+ export {get_my_planets} from './get_my_planets.js';
9
+ export {get_planets_around} from './get_planets_around.js';
10
+ export {get_pending_fleets} from './get_pending_fleets.js';
@@ -0,0 +1,37 @@
1
+ import {z} from 'zod';
2
+ import {createTool} from '../types.js';
3
+
4
+ export const resolve_fleet = createTool({
5
+ description:
6
+ 'Resolve a previously sent fleet. This must be called after the fleet arrival time + resolve window to reveal the destination and secret.',
7
+ schema: z.object({
8
+ fleetId: z.string().describe('Fleet ID to resolve'),
9
+ }),
10
+ execute: async (env, {fleetId}) => {
11
+ try {
12
+ const result = await env.fleetManager.resolve(fleetId);
13
+
14
+ if (result.resolved) {
15
+ return {
16
+ success: true,
17
+ result: {
18
+ fleetId: result.fleet.fleetId,
19
+ fromPlanetId: result.fleet.fromPlanetId,
20
+ toPlanetId: result.fleet.toPlanetId,
21
+ quantity: result.fleet.quantity,
22
+ },
23
+ };
24
+ } else {
25
+ return {
26
+ success: false,
27
+ error: result.reason,
28
+ };
29
+ }
30
+ } catch (error) {
31
+ return {
32
+ success: false,
33
+ error: error instanceof Error ? error.message : String(error),
34
+ };
35
+ }
36
+ },
37
+ });
@@ -0,0 +1,68 @@
1
+ import {z} from 'zod';
2
+ import {createTool} from '../types.js';
3
+ import {zeroAddress} from 'viem';
4
+
5
+ export const send_fleet = createTool({
6
+ description:
7
+ 'Send a fleet from one planet to another in the Conquest game. The fleet will travel through space and can be resolved after arrival.',
8
+ schema: z.object({
9
+ from: z.object({x: z.number(), y: z.number()}).describe('Source planet coordinates {x, y}'),
10
+ to: z.object({x: z.number(), y: z.number()}).describe('Destination planet coordinates {x, y}'),
11
+ quantity: z.number().describe('Number of spaceships to send'),
12
+ arrivalTimeWanted: z
13
+ .number()
14
+ .optional()
15
+ .describe(
16
+ 'Desired arrival time (timestamp in seconds). If not specified, will be calculated based on distance.',
17
+ ),
18
+ gift: z
19
+ .boolean()
20
+ .optional()
21
+ .describe('Whether the fleet is a gift (sent without requiring arrival)'),
22
+ specific: z.string().optional().describe('Additional specific data for the fleet'),
23
+ }),
24
+ execute: async (env, {from, to, quantity, arrivalTimeWanted, gift, specific}) => {
25
+ try {
26
+ // Convert coordinates to planet IDs
27
+ const fromPlanetId = env.planetManager.getPlanetIdByCoordinates(from.x, from.y);
28
+ if (!fromPlanetId) {
29
+ return {
30
+ success: false,
31
+ error: `No planet found at source coordinates (${from.x}, ${from.y})`,
32
+ };
33
+ }
34
+
35
+ const toPlanetId = env.planetManager.getPlanetIdByCoordinates(to.x, to.y);
36
+ if (!toPlanetId) {
37
+ return {
38
+ success: false,
39
+ error: `No planet found at destination coordinates (${to.x}, ${to.y})`,
40
+ };
41
+ }
42
+
43
+ const result = await env.fleetManager.send(fromPlanetId, toPlanetId, quantity, {
44
+ arrivalTimeWanted:
45
+ typeof arrivalTimeWanted === 'undefined' ? undefined : BigInt(arrivalTimeWanted),
46
+ gift: gift ?? false,
47
+ specific: (specific as `0x${string}`) ?? zeroAddress,
48
+ });
49
+
50
+ return {
51
+ success: true,
52
+ result: {
53
+ fleetId: result.fleetId,
54
+ from: result.fromPlanetId,
55
+ to: result.toPlanetId,
56
+ quantity: result.quantity,
57
+ arrivalTimeWanted: result.arrivalTimeWanted,
58
+ secret: result.secret,
59
+ },
60
+ };
61
+ } catch (error) {
62
+ return {
63
+ success: false,
64
+ error: error instanceof Error ? error.message : String(error),
65
+ };
66
+ }
67
+ },
68
+ });