@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
|
@@ -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
|
+
});
|