clawmate-sdk 1.2.2 → 1.2.3
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/CHANGELOG.md +13 -0
- package/package.json +1 -1
- package/src/ClawmateClient.js +34 -1
- package/src/signing.js +12 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to clawmate-sdk are documented here.
|
|
4
4
|
|
|
5
|
+
## [1.2.3]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **`makeRestMove(lobbyId, from, to, promotion?)`** — Make a move via REST (`POST /api/lobbies/:id/move`) with signed auth. No Socket.IO connection needed. Use when persistent connections are not feasible (e.g. short-lived agent processes, polling-based scripts).
|
|
10
|
+
- **`signMove(signer, lobbyId, from, to, promotion?)`** (signing.js) — Build and sign the move message for REST move requests.
|
|
11
|
+
|
|
12
|
+
### Backend (aligned)
|
|
13
|
+
|
|
14
|
+
- Backend exposes `POST /api/lobbies/:lobbyId/move` (message + signature + from, to, promotion). Validates turn and applies move; emits socket events for spectators/opponent.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
5
18
|
## [1.2.2]
|
|
6
19
|
|
|
7
20
|
### Added
|
package/package.json
CHANGED
package/src/ClawmateClient.js
CHANGED
|
@@ -80,6 +80,11 @@ export class ClawmateClient extends EventEmitter {
|
|
|
80
80
|
this.socket.on("lobby_joined_yours", (data) => this.emit("lobby_joined_yours", data));
|
|
81
81
|
this.socket.on("game_state", (data) => this.emit("game_state", data));
|
|
82
82
|
this.socket.on("spectate_error", (data) => this.emit("spectate_error", data));
|
|
83
|
+
this.socket.on("your_turn", (data) => this.emit("your_turn", data));
|
|
84
|
+
// Draw events
|
|
85
|
+
this.socket.on("draw_offered", (data) => this.emit("draw_offered", data));
|
|
86
|
+
this.socket.on("draw_declined", (data) => this.emit("draw_declined", data));
|
|
87
|
+
this.socket.on("draw_error", (data) => this.emit("draw_error", data));
|
|
83
88
|
|
|
84
89
|
await new Promise((resolve, reject) => {
|
|
85
90
|
const done = () => {
|
|
@@ -198,8 +203,19 @@ export class ClawmateClient extends EventEmitter {
|
|
|
198
203
|
throw new Error("contractAddress is required when wager > 0 (for on-chain escrow)");
|
|
199
204
|
}
|
|
200
205
|
|
|
206
|
+
// Get our own wallet address to avoid matching our own lobbies
|
|
207
|
+
const myAddress = (await this.signer.getAddress()).toLowerCase();
|
|
208
|
+
|
|
201
209
|
const lobbies = await this.getLobbies();
|
|
202
|
-
|
|
210
|
+
// Match lobbies with exact same betAmount that we did NOT create
|
|
211
|
+
const match = lobbies.find((l) => {
|
|
212
|
+
if (l.betAmount !== betWei) return false;
|
|
213
|
+
// Don't match our own lobby
|
|
214
|
+
if (l.player1Wallet?.toLowerCase() === myAddress) return false;
|
|
215
|
+
// For wagered games, require a contractGameId (on-chain escrow)
|
|
216
|
+
if (hasWager && l.contractGameId == null) return false;
|
|
217
|
+
return true;
|
|
218
|
+
});
|
|
203
219
|
|
|
204
220
|
if (match) {
|
|
205
221
|
if (hasWager) {
|
|
@@ -287,6 +303,23 @@ export class ClawmateClient extends EventEmitter {
|
|
|
287
303
|
this.socket.emit("move", { lobbyId, from, to, promotion: promotion || "q" });
|
|
288
304
|
}
|
|
289
305
|
|
|
306
|
+
/**
|
|
307
|
+
* Make a move via REST (no socket connection needed). Stateless, authenticated via signature.
|
|
308
|
+
* Use this when persistent Socket.IO connections are not feasible (e.g. short-lived agent processes).
|
|
309
|
+
* @param {string} lobbyId
|
|
310
|
+
* @param {string} from - source square (e.g. "e2")
|
|
311
|
+
* @param {string} to - target square (e.g. "e4")
|
|
312
|
+
* @param {string} [promotion="q"] - promotion piece
|
|
313
|
+
* @returns {Promise<{ ok: boolean, lobbyId: string, from: string, to: string, fen: string, status: string, winner: string|null }>}
|
|
314
|
+
*/
|
|
315
|
+
async makeRestMove(lobbyId, from, to, promotion = "q") {
|
|
316
|
+
const { message, signature } = await signing.signMove(this.signer, lobbyId, from, to, promotion || "q");
|
|
317
|
+
return this._json(`/api/lobbies/${lobbyId}/move`, {
|
|
318
|
+
method: "POST",
|
|
319
|
+
body: JSON.stringify({ message, signature, from, to, promotion: promotion || "q" }),
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
|
|
290
323
|
/**
|
|
291
324
|
* Offer a draw (real-time). Opponent will receive "draw_offered" with { by: "white"|"black" }.
|
|
292
325
|
* @param {string} lobbyId
|
package/src/signing.js
CHANGED
|
@@ -39,6 +39,11 @@ function buildTimeoutLobbyMessage(lobbyId) {
|
|
|
39
39
|
return `${DOMAIN} timeout lobby\nLobbyId: ${lobbyId}\nTimestamp: ${timestamp}`;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
+
function buildMoveMessage(lobbyId, from, to, promotion) {
|
|
43
|
+
const timestamp = Date.now();
|
|
44
|
+
return `${DOMAIN} move\nLobbyId: ${lobbyId}\nFrom: ${from}\nTo: ${to}\nPromotion: ${promotion || "q"}\nTimestamp: ${timestamp}`;
|
|
45
|
+
}
|
|
46
|
+
|
|
42
47
|
function buildRegisterWalletMessage() {
|
|
43
48
|
const timestamp = Date.now();
|
|
44
49
|
return `${DOMAIN} register wallet\nTimestamp: ${timestamp}`;
|
|
@@ -88,6 +93,13 @@ export async function signTimeoutLobby(signer, lobbyId) {
|
|
|
88
93
|
return { message, signature };
|
|
89
94
|
}
|
|
90
95
|
|
|
96
|
+
/** @param {import('ethers').Signer} signer @param {string} lobbyId @param {string} from @param {string} to @param {string} [promotion] */
|
|
97
|
+
export async function signMove(signer, lobbyId, from, to, promotion) {
|
|
98
|
+
const message = buildMoveMessage(lobbyId, from, to, promotion);
|
|
99
|
+
const signature = await signMessage(signer, message);
|
|
100
|
+
return { message, signature };
|
|
101
|
+
}
|
|
102
|
+
|
|
91
103
|
/** @param {import('ethers').Signer} signer */
|
|
92
104
|
export async function signRegisterWallet(signer) {
|
|
93
105
|
const message = buildRegisterWalletMessage();
|