clarityxo-sdk 0.2.0 → 0.4.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/README.md +2 -0
- package/dist/chunk-2P6NUM7A.mjs +350 -0
- package/dist/cli/index.js +13 -5
- package/dist/cli/index.mjs +14 -6
- package/dist/index.d.mts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +23 -0
- package/dist/index.mjs +12 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -197,6 +197,8 @@ The SDK includes utility functions for board analysis:
|
|
|
197
197
|
6. Format: `npm run format`
|
|
198
198
|
7. Submit a PR
|
|
199
199
|
|
|
200
|
+
If you'd like to contribute a bugfix or small improvement, open an issue first with a short description of the change. For larger features, open a discussion or draft PR so we can coordinate before significant design work.
|
|
201
|
+
|
|
200
202
|
## License
|
|
201
203
|
|
|
202
204
|
MIT
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
// src/constants.ts
|
|
2
|
+
var CONTRACT_NAME = "tictactoe";
|
|
3
|
+
var CONTRACT_ADDRESS = "SP30VGN68PSGVWGNMD0HH2WQMM5T486EK3YGP7Z3Y.clarity-xo-game";
|
|
4
|
+
var MAINNET_API = "https://api.mainnet.hiro.so";
|
|
5
|
+
var TESTNET_API = "https://api.testnet.hiro.so";
|
|
6
|
+
var DEFAULT_LEADERBOARD_API = "https://clarityxo.onrender.com";
|
|
7
|
+
var DEFAULT_NETWORK = "testnet";
|
|
8
|
+
var CONTRACT_FUNCTIONS = {
|
|
9
|
+
START_NEW_GAME: "start-new-game",
|
|
10
|
+
MAKE_MOVE: "make-move",
|
|
11
|
+
RESIGN_GAME: "resign-game",
|
|
12
|
+
GET_BOARD_STATE: "get-board-state",
|
|
13
|
+
GET_GAME_STATUS: "get-game-status",
|
|
14
|
+
GET_WINNER: "get-winner",
|
|
15
|
+
GET_CURRENT_TURN: "get-current-turn",
|
|
16
|
+
IS_VALID_MOVE: "is-valid-move"
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
// src/contract/read.ts
|
|
20
|
+
import { callReadOnlyFunction, uintCV } from "@stacks/transactions";
|
|
21
|
+
|
|
22
|
+
// src/utils/network.ts
|
|
23
|
+
import { StacksMainnet, StacksTestnet } from "@stacks/network";
|
|
24
|
+
function getStacksNetwork(network) {
|
|
25
|
+
return network === "mainnet" ? new StacksMainnet() : new StacksTestnet();
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// src/utils/cv.ts
|
|
29
|
+
function parseBoardCV(cv) {
|
|
30
|
+
const rows = cv;
|
|
31
|
+
const board = [
|
|
32
|
+
[null, null, null],
|
|
33
|
+
[null, null, null],
|
|
34
|
+
[null, null, null]
|
|
35
|
+
];
|
|
36
|
+
for (let i = 0; i < 3; i++) {
|
|
37
|
+
const row = rows.list[i].list;
|
|
38
|
+
for (let j = 0; j < 3; j++) {
|
|
39
|
+
const cell = row[j];
|
|
40
|
+
if (cell.type === "some") {
|
|
41
|
+
board[i][j] = cell.value.value;
|
|
42
|
+
} else {
|
|
43
|
+
board[i][j] = null;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return board;
|
|
48
|
+
}
|
|
49
|
+
function parseGameStatusCV(cv) {
|
|
50
|
+
const value = cv.value;
|
|
51
|
+
if (value === "active") return "active";
|
|
52
|
+
if (value === "finished") return "finished";
|
|
53
|
+
if (value === "not-started") return "not-started";
|
|
54
|
+
throw new Error(`Invalid game status: ${value}`);
|
|
55
|
+
}
|
|
56
|
+
function parseWinnerCV(cv) {
|
|
57
|
+
const value = cv.value;
|
|
58
|
+
if (value === "player") return "player";
|
|
59
|
+
if (value === "ai") return "ai";
|
|
60
|
+
if (value === "draw") return "draw";
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
function parseTurnCV(cv) {
|
|
64
|
+
const value = cv.value;
|
|
65
|
+
if (value === "player") return "player";
|
|
66
|
+
if (value === "ai") return "ai";
|
|
67
|
+
throw new Error(`Invalid turn: ${value}`);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// src/contract/read.ts
|
|
71
|
+
async function getBoardState(config) {
|
|
72
|
+
const network = getStacksNetwork(config.network);
|
|
73
|
+
const contractName = config.contractName || CONTRACT_NAME;
|
|
74
|
+
const contractAddress = config.contractAddress || CONTRACT_ADDRESS;
|
|
75
|
+
const cv = await callReadOnlyFunction({
|
|
76
|
+
network,
|
|
77
|
+
contractAddress,
|
|
78
|
+
contractName,
|
|
79
|
+
functionName: CONTRACT_FUNCTIONS.GET_BOARD_STATE,
|
|
80
|
+
functionArgs: [],
|
|
81
|
+
senderAddress: contractAddress
|
|
82
|
+
// arbitrary
|
|
83
|
+
});
|
|
84
|
+
return parseBoardCV(cv);
|
|
85
|
+
}
|
|
86
|
+
async function getGameStatus(config) {
|
|
87
|
+
const network = getStacksNetwork(config.network);
|
|
88
|
+
const contractName = config.contractName || CONTRACT_NAME;
|
|
89
|
+
const contractAddress = config.contractAddress || CONTRACT_ADDRESS;
|
|
90
|
+
const cv = await callReadOnlyFunction({
|
|
91
|
+
network,
|
|
92
|
+
contractAddress,
|
|
93
|
+
contractName,
|
|
94
|
+
functionName: CONTRACT_FUNCTIONS.GET_GAME_STATUS,
|
|
95
|
+
functionArgs: [],
|
|
96
|
+
senderAddress: contractAddress
|
|
97
|
+
});
|
|
98
|
+
return parseGameStatusCV(cv);
|
|
99
|
+
}
|
|
100
|
+
async function getWinner(config) {
|
|
101
|
+
const network = getStacksNetwork(config.network);
|
|
102
|
+
const contractName = config.contractName || CONTRACT_NAME;
|
|
103
|
+
const contractAddress = config.contractAddress || CONTRACT_ADDRESS;
|
|
104
|
+
const cv = await callReadOnlyFunction({
|
|
105
|
+
network,
|
|
106
|
+
contractAddress,
|
|
107
|
+
contractName,
|
|
108
|
+
functionName: CONTRACT_FUNCTIONS.GET_WINNER,
|
|
109
|
+
functionArgs: [],
|
|
110
|
+
senderAddress: contractAddress
|
|
111
|
+
});
|
|
112
|
+
return parseWinnerCV(cv);
|
|
113
|
+
}
|
|
114
|
+
async function getCurrentTurn(config) {
|
|
115
|
+
const network = getStacksNetwork(config.network);
|
|
116
|
+
const contractName = config.contractName || CONTRACT_NAME;
|
|
117
|
+
const contractAddress = config.contractAddress || CONTRACT_ADDRESS;
|
|
118
|
+
const cv = await callReadOnlyFunction({
|
|
119
|
+
network,
|
|
120
|
+
contractAddress,
|
|
121
|
+
contractName,
|
|
122
|
+
functionName: CONTRACT_FUNCTIONS.GET_CURRENT_TURN,
|
|
123
|
+
functionArgs: [],
|
|
124
|
+
senderAddress: contractAddress
|
|
125
|
+
});
|
|
126
|
+
return parseTurnCV(cv);
|
|
127
|
+
}
|
|
128
|
+
async function isValidMove(config, row, col) {
|
|
129
|
+
const network = getStacksNetwork(config.network);
|
|
130
|
+
const contractName = config.contractName || CONTRACT_NAME;
|
|
131
|
+
const contractAddress = config.contractAddress || CONTRACT_ADDRESS;
|
|
132
|
+
const cv = await callReadOnlyFunction({
|
|
133
|
+
network,
|
|
134
|
+
contractAddress,
|
|
135
|
+
contractName,
|
|
136
|
+
functionName: CONTRACT_FUNCTIONS.IS_VALID_MOVE,
|
|
137
|
+
functionArgs: [uintCV(row), uintCV(col)],
|
|
138
|
+
senderAddress: contractAddress
|
|
139
|
+
});
|
|
140
|
+
return cv.value;
|
|
141
|
+
}
|
|
142
|
+
async function getFullGameState(config) {
|
|
143
|
+
const [board, status, winner, currentTurn] = await Promise.all([
|
|
144
|
+
getBoardState(config),
|
|
145
|
+
getGameStatus(config),
|
|
146
|
+
getWinner(config),
|
|
147
|
+
getCurrentTurn(config)
|
|
148
|
+
]);
|
|
149
|
+
return { board, status, winner, currentTurn };
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// src/contract/write.ts
|
|
153
|
+
import { makeContractCall, broadcastTransaction, uintCV as uintCV2 } from "@stacks/transactions";
|
|
154
|
+
async function startNewGame(config) {
|
|
155
|
+
if (!config.senderKey || !config.senderAddress) {
|
|
156
|
+
throw new Error("senderKey and senderAddress are required for write operations");
|
|
157
|
+
}
|
|
158
|
+
const network = getStacksNetwork(config.network);
|
|
159
|
+
const contractName = config.contractName || CONTRACT_NAME;
|
|
160
|
+
const contractAddress = config.contractAddress || CONTRACT_ADDRESS;
|
|
161
|
+
const tx = await makeContractCall({
|
|
162
|
+
network,
|
|
163
|
+
contractAddress,
|
|
164
|
+
contractName,
|
|
165
|
+
functionName: CONTRACT_FUNCTIONS.START_NEW_GAME,
|
|
166
|
+
functionArgs: [],
|
|
167
|
+
senderKey: config.senderKey,
|
|
168
|
+
anchorMode: "any"
|
|
169
|
+
});
|
|
170
|
+
const broadcastResponse = await broadcastTransaction(tx, network);
|
|
171
|
+
return { txId: broadcastResponse.txid };
|
|
172
|
+
}
|
|
173
|
+
async function makeMove(config, row, col) {
|
|
174
|
+
if (!config.senderKey || !config.senderAddress) {
|
|
175
|
+
throw new Error("senderKey and senderAddress are required for write operations");
|
|
176
|
+
}
|
|
177
|
+
const network = getStacksNetwork(config.network);
|
|
178
|
+
const contractName = config.contractName || CONTRACT_NAME;
|
|
179
|
+
const contractAddress = config.contractAddress || CONTRACT_ADDRESS;
|
|
180
|
+
const tx = await makeContractCall({
|
|
181
|
+
network,
|
|
182
|
+
contractAddress,
|
|
183
|
+
contractName,
|
|
184
|
+
functionName: CONTRACT_FUNCTIONS.MAKE_MOVE,
|
|
185
|
+
functionArgs: [uintCV2(row), uintCV2(col)],
|
|
186
|
+
senderKey: config.senderKey,
|
|
187
|
+
anchorMode: "any"
|
|
188
|
+
});
|
|
189
|
+
const broadcastResponse = await broadcastTransaction(tx, network);
|
|
190
|
+
return { txId: broadcastResponse.txid };
|
|
191
|
+
}
|
|
192
|
+
async function resignGame(config) {
|
|
193
|
+
if (!config.senderKey || !config.senderAddress) {
|
|
194
|
+
throw new Error("senderKey and senderAddress are required for write operations");
|
|
195
|
+
}
|
|
196
|
+
const network = getStacksNetwork(config.network);
|
|
197
|
+
const contractName = config.contractName || CONTRACT_NAME;
|
|
198
|
+
const contractAddress = config.contractAddress || CONTRACT_ADDRESS;
|
|
199
|
+
const tx = await makeContractCall({
|
|
200
|
+
network,
|
|
201
|
+
contractAddress,
|
|
202
|
+
contractName,
|
|
203
|
+
functionName: CONTRACT_FUNCTIONS.RESIGN_GAME,
|
|
204
|
+
functionArgs: [],
|
|
205
|
+
senderKey: config.senderKey,
|
|
206
|
+
anchorMode: "any"
|
|
207
|
+
});
|
|
208
|
+
const broadcastResponse = await broadcastTransaction(tx, network);
|
|
209
|
+
return { txId: broadcastResponse.txid };
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// src/leaderboard/api.ts
|
|
213
|
+
function getBaseUrl(config) {
|
|
214
|
+
return config.leaderboardApiUrl || DEFAULT_LEADERBOARD_API;
|
|
215
|
+
}
|
|
216
|
+
async function getLeaderboard(config, month) {
|
|
217
|
+
const baseUrl = getBaseUrl(config);
|
|
218
|
+
const response = await fetch(`${baseUrl}/api/leaderboard?month=${month}`);
|
|
219
|
+
if (!response.ok) {
|
|
220
|
+
throw new Error(`Failed to fetch leaderboard: ${response.statusText}`);
|
|
221
|
+
}
|
|
222
|
+
return response.json();
|
|
223
|
+
}
|
|
224
|
+
async function submitResult(config, result) {
|
|
225
|
+
const baseUrl = getBaseUrl(config);
|
|
226
|
+
const response = await fetch(`${baseUrl}/api/leaderboard/result`, {
|
|
227
|
+
method: "POST",
|
|
228
|
+
headers: { "Content-Type": "application/json" },
|
|
229
|
+
body: JSON.stringify(result)
|
|
230
|
+
});
|
|
231
|
+
if (!response.ok) {
|
|
232
|
+
throw new Error(`Failed to submit result: ${response.statusText}`);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
async function syncLeaderboard(config) {
|
|
236
|
+
const baseUrl = getBaseUrl(config);
|
|
237
|
+
const response = await fetch(`${baseUrl}/api/sync`, {
|
|
238
|
+
method: "POST"
|
|
239
|
+
});
|
|
240
|
+
if (!response.ok) {
|
|
241
|
+
throw new Error(`Failed to sync leaderboard: ${response.statusText}`);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async function healthCheck(config) {
|
|
245
|
+
const baseUrl = getBaseUrl(config);
|
|
246
|
+
try {
|
|
247
|
+
const response = await fetch(`${baseUrl}/health`);
|
|
248
|
+
return response.ok;
|
|
249
|
+
} catch {
|
|
250
|
+
return false;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
async function getPlayerStats(config, playerAddress, month) {
|
|
254
|
+
const currentMonth = month || (/* @__PURE__ */ new Date()).toISOString().slice(0, 7);
|
|
255
|
+
const leaderboard = await getLeaderboard(config, currentMonth);
|
|
256
|
+
const entry = leaderboard.entries.find((e) => e.player === playerAddress);
|
|
257
|
+
if (!entry) {
|
|
258
|
+
return null;
|
|
259
|
+
}
|
|
260
|
+
const totalGames = entry.wins + entry.losses + entry.draws;
|
|
261
|
+
const winRate = totalGames > 0 ? entry.wins / totalGames * 100 : 0;
|
|
262
|
+
return {
|
|
263
|
+
...entry,
|
|
264
|
+
totalGames,
|
|
265
|
+
winRate: Math.round(winRate * 100) / 100
|
|
266
|
+
// Round to 2 decimal places
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// src/client.ts
|
|
271
|
+
var ClarityXOClient = class {
|
|
272
|
+
constructor(config) {
|
|
273
|
+
this.config = config;
|
|
274
|
+
}
|
|
275
|
+
config;
|
|
276
|
+
// Game state
|
|
277
|
+
getBoardState() {
|
|
278
|
+
return getBoardState(this.config);
|
|
279
|
+
}
|
|
280
|
+
getGameStatus() {
|
|
281
|
+
return getGameStatus(this.config);
|
|
282
|
+
}
|
|
283
|
+
getWinner() {
|
|
284
|
+
return getWinner(this.config);
|
|
285
|
+
}
|
|
286
|
+
getCurrentTurn() {
|
|
287
|
+
return getCurrentTurn(this.config);
|
|
288
|
+
}
|
|
289
|
+
isValidMove(row, col) {
|
|
290
|
+
return isValidMove(this.config, row, col);
|
|
291
|
+
}
|
|
292
|
+
getFullGameState() {
|
|
293
|
+
return getFullGameState(this.config);
|
|
294
|
+
}
|
|
295
|
+
// Transactions
|
|
296
|
+
startNewGame() {
|
|
297
|
+
return startNewGame(this.config);
|
|
298
|
+
}
|
|
299
|
+
makeMove(row, col) {
|
|
300
|
+
return makeMove(this.config, row, col);
|
|
301
|
+
}
|
|
302
|
+
resignGame() {
|
|
303
|
+
return resignGame(this.config);
|
|
304
|
+
}
|
|
305
|
+
// Leaderboard
|
|
306
|
+
getLeaderboard(month) {
|
|
307
|
+
return getLeaderboard(this.config, month);
|
|
308
|
+
}
|
|
309
|
+
submitResult(result) {
|
|
310
|
+
return submitResult(this.config, result);
|
|
311
|
+
}
|
|
312
|
+
syncLeaderboard() {
|
|
313
|
+
return syncLeaderboard(this.config);
|
|
314
|
+
}
|
|
315
|
+
healthCheck() {
|
|
316
|
+
return healthCheck(this.config);
|
|
317
|
+
}
|
|
318
|
+
getPlayerStats(playerAddress, month) {
|
|
319
|
+
return getPlayerStats(this.config, playerAddress, month);
|
|
320
|
+
}
|
|
321
|
+
};
|
|
322
|
+
function createClient(config) {
|
|
323
|
+
return new ClarityXOClient(config);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
export {
|
|
327
|
+
CONTRACT_NAME,
|
|
328
|
+
CONTRACT_ADDRESS,
|
|
329
|
+
MAINNET_API,
|
|
330
|
+
TESTNET_API,
|
|
331
|
+
DEFAULT_LEADERBOARD_API,
|
|
332
|
+
DEFAULT_NETWORK,
|
|
333
|
+
CONTRACT_FUNCTIONS,
|
|
334
|
+
getBoardState,
|
|
335
|
+
getGameStatus,
|
|
336
|
+
getWinner,
|
|
337
|
+
getCurrentTurn,
|
|
338
|
+
isValidMove,
|
|
339
|
+
getFullGameState,
|
|
340
|
+
startNewGame,
|
|
341
|
+
makeMove,
|
|
342
|
+
resignGame,
|
|
343
|
+
getLeaderboard,
|
|
344
|
+
submitResult,
|
|
345
|
+
syncLeaderboard,
|
|
346
|
+
healthCheck,
|
|
347
|
+
getPlayerStats,
|
|
348
|
+
ClarityXOClient,
|
|
349
|
+
createClient
|
|
350
|
+
};
|
package/dist/cli/index.js
CHANGED
|
@@ -359,10 +359,10 @@ function isValidStacksAddress(address) {
|
|
|
359
359
|
}
|
|
360
360
|
function validateContractAddress(address) {
|
|
361
361
|
if (!address) {
|
|
362
|
-
throw new Error("Contract address is required");
|
|
362
|
+
throw new Error("Contract address is required. Pass it via --contract <address> or set it in your config.");
|
|
363
363
|
}
|
|
364
364
|
if (!isValidStacksAddress(address)) {
|
|
365
|
-
throw new Error("Invalid Stacks address format");
|
|
365
|
+
throw new Error("Invalid Stacks address format. Ensure the address starts with SP (mainnet) or ST (testnet).");
|
|
366
366
|
}
|
|
367
367
|
}
|
|
368
368
|
function validateNetwork(network) {
|
|
@@ -372,13 +372,13 @@ function validateNetwork(network) {
|
|
|
372
372
|
}
|
|
373
373
|
function validateWriteConfig(key, address) {
|
|
374
374
|
if (!key) {
|
|
375
|
-
throw new Error("--key (sender private key) is required for write operations");
|
|
375
|
+
throw new Error("--key (sender private key) is required for write operations. Provide it via --key <private-key>.");
|
|
376
376
|
}
|
|
377
377
|
if (!address) {
|
|
378
|
-
throw new Error("--address (sender address) is required for write operations");
|
|
378
|
+
throw new Error("--address (sender address) is required for write operations. Provide it via --address <sender-address>.");
|
|
379
379
|
}
|
|
380
380
|
if (!isValidStacksAddress(address)) {
|
|
381
|
-
throw new Error("Invalid sender address format");
|
|
381
|
+
throw new Error("Invalid sender address format. Ensure it is a valid Stacks address.");
|
|
382
382
|
}
|
|
383
383
|
}
|
|
384
384
|
|
|
@@ -616,6 +616,14 @@ command6.description("Start a new game").option("--contract [address]", "Contrac
|
|
|
616
616
|
process.exit(1);
|
|
617
617
|
}
|
|
618
618
|
});
|
|
619
|
+
command6.addHelpText(
|
|
620
|
+
"after",
|
|
621
|
+
`
|
|
622
|
+
Examples:
|
|
623
|
+
clarityxo start --contract <contract-address> --key <private-key> --address <sender-address>
|
|
624
|
+
clarityxo start --network testnet --key <private-key> --address <sender-address>
|
|
625
|
+
`
|
|
626
|
+
);
|
|
619
627
|
var start_default = command6;
|
|
620
628
|
|
|
621
629
|
// src/cli/commands/resign.ts
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
createClient
|
|
4
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-2P6NUM7A.mjs";
|
|
5
5
|
|
|
6
6
|
// src/cli/index.ts
|
|
7
7
|
import { Command as Command8 } from "commander";
|
|
@@ -17,10 +17,10 @@ function isValidStacksAddress(address) {
|
|
|
17
17
|
}
|
|
18
18
|
function validateContractAddress(address) {
|
|
19
19
|
if (!address) {
|
|
20
|
-
throw new Error("Contract address is required");
|
|
20
|
+
throw new Error("Contract address is required. Pass it via --contract <address> or set it in your config.");
|
|
21
21
|
}
|
|
22
22
|
if (!isValidStacksAddress(address)) {
|
|
23
|
-
throw new Error("Invalid Stacks address format");
|
|
23
|
+
throw new Error("Invalid Stacks address format. Ensure the address starts with SP (mainnet) or ST (testnet).");
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
function validateNetwork(network) {
|
|
@@ -30,13 +30,13 @@ function validateNetwork(network) {
|
|
|
30
30
|
}
|
|
31
31
|
function validateWriteConfig(key, address) {
|
|
32
32
|
if (!key) {
|
|
33
|
-
throw new Error("--key (sender private key) is required for write operations");
|
|
33
|
+
throw new Error("--key (sender private key) is required for write operations. Provide it via --key <private-key>.");
|
|
34
34
|
}
|
|
35
35
|
if (!address) {
|
|
36
|
-
throw new Error("--address (sender address) is required for write operations");
|
|
36
|
+
throw new Error("--address (sender address) is required for write operations. Provide it via --address <sender-address>.");
|
|
37
37
|
}
|
|
38
38
|
if (!isValidStacksAddress(address)) {
|
|
39
|
-
throw new Error("Invalid sender address format");
|
|
39
|
+
throw new Error("Invalid sender address format. Ensure it is a valid Stacks address.");
|
|
40
40
|
}
|
|
41
41
|
}
|
|
42
42
|
|
|
@@ -274,6 +274,14 @@ command6.description("Start a new game").option("--contract [address]", "Contrac
|
|
|
274
274
|
process.exit(1);
|
|
275
275
|
}
|
|
276
276
|
});
|
|
277
|
+
command6.addHelpText(
|
|
278
|
+
"after",
|
|
279
|
+
`
|
|
280
|
+
Examples:
|
|
281
|
+
clarityxo start --contract <contract-address> --key <private-key> --address <sender-address>
|
|
282
|
+
clarityxo start --network testnet --key <private-key> --address <sender-address>
|
|
283
|
+
`
|
|
284
|
+
);
|
|
277
285
|
var start_default = command6;
|
|
278
286
|
|
|
279
287
|
// src/cli/commands/resign.ts
|
package/dist/index.d.mts
CHANGED
|
@@ -22,7 +22,7 @@ type Turn = 'player' | 'ai';
|
|
|
22
22
|
interface GameState {
|
|
23
23
|
board: Board;
|
|
24
24
|
status: GameStatus;
|
|
25
|
-
winner:
|
|
25
|
+
winner: Winner;
|
|
26
26
|
currentTurn: Turn;
|
|
27
27
|
}
|
|
28
28
|
interface LeaderboardEntry {
|
|
@@ -52,6 +52,7 @@ interface GameResult {
|
|
|
52
52
|
outcome: 'win' | 'loss' | 'draw';
|
|
53
53
|
month: string;
|
|
54
54
|
}
|
|
55
|
+
type Winner = 'player' | 'ai' | 'draw' | null;
|
|
55
56
|
interface ClarityXOConfig {
|
|
56
57
|
network: Network;
|
|
57
58
|
contractAddress?: string;
|
|
@@ -92,6 +93,7 @@ declare const CONTRACT_ADDRESS = "SP30VGN68PSGVWGNMD0HH2WQMM5T486EK3YGP7Z3Y.clar
|
|
|
92
93
|
declare const MAINNET_API = "https://api.mainnet.hiro.so";
|
|
93
94
|
declare const TESTNET_API = "https://api.testnet.hiro.so";
|
|
94
95
|
declare const DEFAULT_LEADERBOARD_API = "https://clarityxo.onrender.com";
|
|
96
|
+
declare const DEFAULT_NETWORK: 'testnet' | 'mainnet';
|
|
95
97
|
declare const CONTRACT_FUNCTIONS: {
|
|
96
98
|
readonly START_NEW_GAME: "start-new-game";
|
|
97
99
|
readonly MAKE_MOVE: "make-move";
|
|
@@ -134,4 +136,6 @@ declare function getBoardString(board: Board): string;
|
|
|
134
136
|
declare function cloneBoard(board: Board): Board;
|
|
135
137
|
declare function makeMoveOnBoard(board: Board, row: number, col: number, player: CellValue): Board;
|
|
136
138
|
|
|
137
|
-
|
|
139
|
+
declare function debug(message: string, ...args: unknown[]): void;
|
|
140
|
+
|
|
141
|
+
export { type Board, CONTRACT_ADDRESS, CONTRACT_FUNCTIONS, CONTRACT_NAME, type CellValue, ClarityXOClient, type ClarityXOConfig, DEFAULT_LEADERBOARD_API, DEFAULT_NETWORK, type GameResult, type GameState, type GameStatus, type LeaderboardEntry, type LeaderboardMonth, MAINNET_API, type Network, type PlayerStats, TESTNET_API, type Turn, type Winner, checkWin, cloneBoard, createClient, debug, getAvailableMoves, getBoardState, getBoardString, getCurrentTurn, getFullGameState, getGameStatus, getLeaderboard, getPlayerStats, getWinner, healthCheck, isBoardFull, isDraw, isValidMove, makeMove, makeMoveOnBoard, resignGame, startNewGame, submitResult, syncLeaderboard };
|
package/dist/index.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ type Turn = 'player' | 'ai';
|
|
|
22
22
|
interface GameState {
|
|
23
23
|
board: Board;
|
|
24
24
|
status: GameStatus;
|
|
25
|
-
winner:
|
|
25
|
+
winner: Winner;
|
|
26
26
|
currentTurn: Turn;
|
|
27
27
|
}
|
|
28
28
|
interface LeaderboardEntry {
|
|
@@ -52,6 +52,7 @@ interface GameResult {
|
|
|
52
52
|
outcome: 'win' | 'loss' | 'draw';
|
|
53
53
|
month: string;
|
|
54
54
|
}
|
|
55
|
+
type Winner = 'player' | 'ai' | 'draw' | null;
|
|
55
56
|
interface ClarityXOConfig {
|
|
56
57
|
network: Network;
|
|
57
58
|
contractAddress?: string;
|
|
@@ -92,6 +93,7 @@ declare const CONTRACT_ADDRESS = "SP30VGN68PSGVWGNMD0HH2WQMM5T486EK3YGP7Z3Y.clar
|
|
|
92
93
|
declare const MAINNET_API = "https://api.mainnet.hiro.so";
|
|
93
94
|
declare const TESTNET_API = "https://api.testnet.hiro.so";
|
|
94
95
|
declare const DEFAULT_LEADERBOARD_API = "https://clarityxo.onrender.com";
|
|
96
|
+
declare const DEFAULT_NETWORK: 'testnet' | 'mainnet';
|
|
95
97
|
declare const CONTRACT_FUNCTIONS: {
|
|
96
98
|
readonly START_NEW_GAME: "start-new-game";
|
|
97
99
|
readonly MAKE_MOVE: "make-move";
|
|
@@ -134,4 +136,6 @@ declare function getBoardString(board: Board): string;
|
|
|
134
136
|
declare function cloneBoard(board: Board): Board;
|
|
135
137
|
declare function makeMoveOnBoard(board: Board, row: number, col: number, player: CellValue): Board;
|
|
136
138
|
|
|
137
|
-
|
|
139
|
+
declare function debug(message: string, ...args: unknown[]): void;
|
|
140
|
+
|
|
141
|
+
export { type Board, CONTRACT_ADDRESS, CONTRACT_FUNCTIONS, CONTRACT_NAME, type CellValue, ClarityXOClient, type ClarityXOConfig, DEFAULT_LEADERBOARD_API, DEFAULT_NETWORK, type GameResult, type GameState, type GameStatus, type LeaderboardEntry, type LeaderboardMonth, MAINNET_API, type Network, type PlayerStats, TESTNET_API, type Turn, type Winner, checkWin, cloneBoard, createClient, debug, getAvailableMoves, getBoardState, getBoardString, getCurrentTurn, getFullGameState, getGameStatus, getLeaderboard, getPlayerStats, getWinner, healthCheck, isBoardFull, isDraw, isValidMove, makeMove, makeMoveOnBoard, resignGame, startNewGame, submitResult, syncLeaderboard };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
2
3
|
var __defProp = Object.defineProperty;
|
|
3
4
|
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
5
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
5
7
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
8
|
var __export = (target, all) => {
|
|
7
9
|
for (var name in all)
|
|
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
15
17
|
}
|
|
16
18
|
return to;
|
|
17
19
|
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
18
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
29
|
|
|
20
30
|
// src/index.ts
|
|
@@ -25,11 +35,13 @@ __export(index_exports, {
|
|
|
25
35
|
CONTRACT_NAME: () => CONTRACT_NAME,
|
|
26
36
|
ClarityXOClient: () => ClarityXOClient,
|
|
27
37
|
DEFAULT_LEADERBOARD_API: () => DEFAULT_LEADERBOARD_API,
|
|
38
|
+
DEFAULT_NETWORK: () => DEFAULT_NETWORK,
|
|
28
39
|
MAINNET_API: () => MAINNET_API,
|
|
29
40
|
TESTNET_API: () => TESTNET_API,
|
|
30
41
|
checkWin: () => checkWin,
|
|
31
42
|
cloneBoard: () => cloneBoard,
|
|
32
43
|
createClient: () => createClient,
|
|
44
|
+
debug: () => debug,
|
|
33
45
|
getAvailableMoves: () => getAvailableMoves,
|
|
34
46
|
getBoardState: () => getBoardState,
|
|
35
47
|
getBoardString: () => getBoardString,
|
|
@@ -61,6 +73,7 @@ var CONTRACT_ADDRESS = "SP30VGN68PSGVWGNMD0HH2WQMM5T486EK3YGP7Z3Y.clarity-xo-gam
|
|
|
61
73
|
var MAINNET_API = "https://api.mainnet.hiro.so";
|
|
62
74
|
var TESTNET_API = "https://api.testnet.hiro.so";
|
|
63
75
|
var DEFAULT_LEADERBOARD_API = "https://clarityxo.onrender.com";
|
|
76
|
+
var DEFAULT_NETWORK = "testnet";
|
|
64
77
|
var CONTRACT_FUNCTIONS = {
|
|
65
78
|
START_NEW_GAME: "start-new-game",
|
|
66
79
|
MAKE_MOVE: "make-move",
|
|
@@ -428,6 +441,14 @@ function makeMoveOnBoard(board, row, col, player) {
|
|
|
428
441
|
newBoard[row][col] = player;
|
|
429
442
|
return newBoard;
|
|
430
443
|
}
|
|
444
|
+
|
|
445
|
+
// src/utils/log.ts
|
|
446
|
+
var import_chalk = __toESM(require("chalk"));
|
|
447
|
+
function debug(message, ...args) {
|
|
448
|
+
if (process.env.DEBUG && process.env.DEBUG !== "0") {
|
|
449
|
+
console.debug(import_chalk.default.gray("[clarityxo]"), message, ...args);
|
|
450
|
+
}
|
|
451
|
+
}
|
|
431
452
|
// Annotate the CommonJS export names for ESM import in node:
|
|
432
453
|
0 && (module.exports = {
|
|
433
454
|
CONTRACT_ADDRESS,
|
|
@@ -435,11 +456,13 @@ function makeMoveOnBoard(board, row, col, player) {
|
|
|
435
456
|
CONTRACT_NAME,
|
|
436
457
|
ClarityXOClient,
|
|
437
458
|
DEFAULT_LEADERBOARD_API,
|
|
459
|
+
DEFAULT_NETWORK,
|
|
438
460
|
MAINNET_API,
|
|
439
461
|
TESTNET_API,
|
|
440
462
|
checkWin,
|
|
441
463
|
cloneBoard,
|
|
442
464
|
createClient,
|
|
465
|
+
debug,
|
|
443
466
|
getAvailableMoves,
|
|
444
467
|
getBoardState,
|
|
445
468
|
getBoardString,
|
package/dist/index.mjs
CHANGED
|
@@ -4,6 +4,7 @@ import {
|
|
|
4
4
|
CONTRACT_NAME,
|
|
5
5
|
ClarityXOClient,
|
|
6
6
|
DEFAULT_LEADERBOARD_API,
|
|
7
|
+
DEFAULT_NETWORK,
|
|
7
8
|
MAINNET_API,
|
|
8
9
|
TESTNET_API,
|
|
9
10
|
createClient,
|
|
@@ -21,7 +22,7 @@ import {
|
|
|
21
22
|
startNewGame,
|
|
22
23
|
submitResult,
|
|
23
24
|
syncLeaderboard
|
|
24
|
-
} from "./chunk-
|
|
25
|
+
} from "./chunk-2P6NUM7A.mjs";
|
|
25
26
|
|
|
26
27
|
// src/utils/board.ts
|
|
27
28
|
function checkWin(board, player) {
|
|
@@ -75,17 +76,27 @@ function makeMoveOnBoard(board, row, col, player) {
|
|
|
75
76
|
newBoard[row][col] = player;
|
|
76
77
|
return newBoard;
|
|
77
78
|
}
|
|
79
|
+
|
|
80
|
+
// src/utils/log.ts
|
|
81
|
+
import chalk from "chalk";
|
|
82
|
+
function debug(message, ...args) {
|
|
83
|
+
if (process.env.DEBUG && process.env.DEBUG !== "0") {
|
|
84
|
+
console.debug(chalk.gray("[clarityxo]"), message, ...args);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
78
87
|
export {
|
|
79
88
|
CONTRACT_ADDRESS,
|
|
80
89
|
CONTRACT_FUNCTIONS,
|
|
81
90
|
CONTRACT_NAME,
|
|
82
91
|
ClarityXOClient,
|
|
83
92
|
DEFAULT_LEADERBOARD_API,
|
|
93
|
+
DEFAULT_NETWORK,
|
|
84
94
|
MAINNET_API,
|
|
85
95
|
TESTNET_API,
|
|
86
96
|
checkWin,
|
|
87
97
|
cloneBoard,
|
|
88
98
|
createClient,
|
|
99
|
+
debug,
|
|
89
100
|
getAvailableMoves,
|
|
90
101
|
getBoardState,
|
|
91
102
|
getBoardString,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clarityxo-sdk",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "TypeScript SDK and CLI for the ClarityXO on-chain Tic-Tac-Toe game on Stacks",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -10,14 +10,15 @@
|
|
|
10
10
|
},
|
|
11
11
|
"exports": {
|
|
12
12
|
".": {
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
13
14
|
"import": "./dist/index.mjs",
|
|
14
|
-
"require": "./dist/index.js"
|
|
15
|
-
"types": "./dist/index.d.ts"
|
|
15
|
+
"require": "./dist/index.js"
|
|
16
16
|
}
|
|
17
17
|
},
|
|
18
18
|
"scripts": {
|
|
19
19
|
"build": "tsup",
|
|
20
20
|
"dev": "tsup --watch",
|
|
21
|
+
"prepare": "npm run build",
|
|
21
22
|
"test": "vitest",
|
|
22
23
|
"lint": "eslint src --ext .ts",
|
|
23
24
|
"format": "prettier --write src"
|