theref-sdk 0.1.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/dist/index.mjs ADDED
@@ -0,0 +1,602 @@
1
+ // src/client/TheRefClient.ts
2
+ import { createClient, createAccount, generatePrivateKey, chains } from "genlayer-js";
3
+ import { TransactionStatus } from "genlayer-js/types";
4
+
5
+ // src/utils/networks.ts
6
+ var NETWORKS = {
7
+ bradbury: {
8
+ id: "bradbury",
9
+ rpc: "https://rpc-bradbury.genlayer.com",
10
+ chainId: 4221,
11
+ addresses: {
12
+ CORE: "0xA29CfFC83d32fe924cFf1F1bDCf21555CCC96206",
13
+ LB: "0x5D417F296b17656c9b950236feE66F63E22d8A54",
14
+ ORG: "0x440b28afc1804fc1E4AA8f5b559C18F7bCf43B3A",
15
+ FEE: "0x88A0A4d573fD9C63433E457e94d266D7904278C2",
16
+ TRN: "0xbcc0E82a17491297E0c4938606624Fa04e6abA1B"
17
+ }
18
+ },
19
+ studionet: {
20
+ id: "studionet",
21
+ rpc: "https://studio.genlayer.com/api",
22
+ chainId: 61999,
23
+ addresses: {
24
+ CORE: "0x88CAA18419714aA38CdF53c0E603141c48fa3238",
25
+ LB: "0x8A2d05Df048A64cc6B83682a431ade05030e4BBB",
26
+ ORG: "0x265ef96A5230F13836c553D7DD2B9D7c3fE14aE1",
27
+ FEE: "0x0000000000000000000000000000000000000000",
28
+ TRN: "0x44f7c1bDa293B9cdBD79a6dfb66bD45696dEa4A6"
29
+ }
30
+ }
31
+ };
32
+ var DEFAULT_WS_URL = "wss://ws.theref.fun";
33
+ function resolveNetwork(network) {
34
+ if (typeof network === "string") return NETWORKS[network];
35
+ return network;
36
+ }
37
+ function gidToNum(gid) {
38
+ return parseInt(gid.replace(/^0+/, "") || "0", 36) || 1;
39
+ }
40
+
41
+ // src/adapters/normalizer.ts
42
+ function adaptChess(move) {
43
+ if (typeof move === "string") {
44
+ if (/^[a-h][1-8]$|^[NBRQK][a-h]?[1-8]?x?[a-h][1-8][+#]?$|^O-O(-O)?[+#]?$/.test(move)) {
45
+ return move;
46
+ }
47
+ }
48
+ if (typeof move === "object" && move !== null && !Array.isArray(move)) {
49
+ const m = move;
50
+ if (m.from && m.to) {
51
+ const promo = m.promotion ? `=${String(m.promotion).toUpperCase()}` : "";
52
+ const piece = m.piece ? `${String(m.piece).toUpperCase()} ` : "";
53
+ return `${piece}${m.from}${m.promotion ? "" : ""}${m.to}${promo}`.trim();
54
+ }
55
+ if (m.piece && m.from && m.to) {
56
+ const pieceMap = {
57
+ knight: "N",
58
+ bishop: "B",
59
+ rook: "R",
60
+ queen: "Q",
61
+ king: "K",
62
+ pawn: ""
63
+ };
64
+ const p = pieceMap[String(m.piece).toLowerCase()] ?? "";
65
+ return `${p}${m.to}`;
66
+ }
67
+ if (m.uci && typeof m.uci === "string") {
68
+ return `${m.uci.slice(0, 2)}-${m.uci.slice(2, 4)}`;
69
+ }
70
+ }
71
+ if (Array.isArray(move) && move.length === 4 && move.every((n) => typeof n === "number")) {
72
+ const files = "abcdefgh";
73
+ return `${files[move[0]]}${move[1] + 1}-${files[move[2]]}${move[3] + 1}`;
74
+ }
75
+ return null;
76
+ }
77
+ function adaptRPS(move) {
78
+ const choices = {
79
+ rock: "Rock",
80
+ paper: "Paper",
81
+ scissors: "Scissors",
82
+ r: "Rock",
83
+ p: "Paper",
84
+ s: "Scissors",
85
+ "0": "Rock",
86
+ "1": "Paper",
87
+ "2": "Scissors",
88
+ stone: "Rock",
89
+ shears: "Scissors",
90
+ lizard: "Lizard",
91
+ spock: "Spock"
92
+ // RPSLS variant
93
+ };
94
+ if (typeof move === "string") {
95
+ const normalized = choices[move.toLowerCase().trim()];
96
+ if (normalized) return normalized;
97
+ }
98
+ if (typeof move === "number") {
99
+ const normalized = choices[String(move)];
100
+ if (normalized) return normalized;
101
+ }
102
+ if (typeof move === "object" && !Array.isArray(move) && move !== null) {
103
+ const m = move;
104
+ const choice = m.choice ?? m.action ?? m.move ?? m.pick;
105
+ if (choice) return adaptRPS(choice);
106
+ }
107
+ return null;
108
+ }
109
+ function adaptCombat(move) {
110
+ if (typeof move === "object" && !Array.isArray(move) && move !== null) {
111
+ const m = move;
112
+ const parts = [];
113
+ if (m.player || m.character || m.unit) {
114
+ parts.push(String(m.player ?? m.character ?? m.unit));
115
+ }
116
+ const action = m.action ?? m.move ?? m.skill ?? m.ability ?? m.attack ?? m.spell ?? m.card;
117
+ if (action) parts.push(`uses ${action}`);
118
+ const target = m.target ?? m.enemy ?? m.opponent;
119
+ if (target) parts.push(`on ${target}`);
120
+ if (m.power !== void 0) parts.push(`(power: ${m.power})`);
121
+ if (m.damage !== void 0) parts.push(`(damage: ${m.damage})`);
122
+ if (m.mana_cost !== void 0) parts.push(`(mana: ${m.mana_cost})`);
123
+ if (m.combo) parts.push(`via combo: ${Array.isArray(m.combo) ? m.combo.join("+") : m.combo}`);
124
+ if (m.type) parts.push(`[${m.type} type]`);
125
+ if (m.element) parts.push(`[${m.element}]`);
126
+ if (m.special) parts.push(`special: ${m.special}`);
127
+ if (m.position) parts.push(`at ${JSON.stringify(m.position)}`);
128
+ if (parts.length > 0) return parts.join(" ");
129
+ }
130
+ return null;
131
+ }
132
+ function adaptStrategy(move) {
133
+ if (typeof move === "object" && !Array.isArray(move) && move !== null) {
134
+ const m = move;
135
+ const parts = [];
136
+ const action = m.action ?? m.command ?? m.order;
137
+ if (action) parts.push(String(action));
138
+ const unit = m.unit ?? m.piece ?? m.troop ?? m.building;
139
+ if (unit) parts.push(String(unit));
140
+ if (m.from && m.to) {
141
+ parts.push(`from ${JSON.stringify(m.from)} to ${JSON.stringify(m.to)}`);
142
+ } else if (m.position ?? m.target ?? m.location) {
143
+ parts.push(`at ${JSON.stringify(m.position ?? m.target ?? m.location)}`);
144
+ }
145
+ if (m.attack) parts.push(`attacking with ${m.attack}`);
146
+ if (m.defend) parts.push(`defending with ${m.defend}`);
147
+ if (m.resource !== void 0) parts.push(`(cost: ${m.resource})`);
148
+ if (parts.length > 0) return parts.join(" ");
149
+ }
150
+ return null;
151
+ }
152
+ function adaptTrivia(move) {
153
+ if (typeof move === "object" && !Array.isArray(move) && move !== null) {
154
+ const m = move;
155
+ const answer = m.answer ?? m.response ?? m.text ?? m.value;
156
+ if (answer !== void 0) return String(answer);
157
+ }
158
+ return null;
159
+ }
160
+ function adaptDebate(move) {
161
+ if (typeof move === "object" && !Array.isArray(move) && move !== null) {
162
+ const m = move;
163
+ const parts = [];
164
+ if (m.position) parts.push(`Position: ${m.position}`);
165
+ if (m.argument) parts.push(`Argument: ${m.argument}`);
166
+ if (m.evidence) parts.push(`Evidence: ${m.evidence}`);
167
+ if (m.rebuttal) parts.push(`Rebuttal: ${m.rebuttal}`);
168
+ if (parts.length > 0) return parts.join(". ");
169
+ }
170
+ return null;
171
+ }
172
+ function flattenObject(obj, prefix = "") {
173
+ return Object.entries(obj).map(([key, val]) => {
174
+ const label = prefix ? `${prefix}.${key}` : key;
175
+ if (val === null || val === void 0) return null;
176
+ if (typeof val === "object" && !Array.isArray(val)) {
177
+ return flattenObject(val, label);
178
+ }
179
+ if (Array.isArray(val)) {
180
+ return `${label}: [${val.map((v) => String(v)).join(", ")}]`;
181
+ }
182
+ return `${label}: ${val}`;
183
+ }).filter(Boolean).join(", ");
184
+ }
185
+ function normalizeMove(move, gameHint) {
186
+ if (typeof move === "string") {
187
+ return { raw: move, text: move.trim(), adapter: "passthrough" };
188
+ }
189
+ if (typeof move === "number") {
190
+ return { raw: move, text: String(move), adapter: "number" };
191
+ }
192
+ if (typeof move === "boolean") {
193
+ return { raw: move, text: move ? "Yes" : "No", adapter: "boolean" };
194
+ }
195
+ if (move === null || move === void 0) {
196
+ return { raw: move, text: "No move", adapter: "null" };
197
+ }
198
+ const hint = gameHint?.toLowerCase() ?? "";
199
+ if (hint.includes("chess")) {
200
+ const result = adaptChess(move);
201
+ if (result) return { raw: move, text: result, adapter: "chess" };
202
+ }
203
+ if (hint.includes("rock") || hint.includes("rps") || hint.includes("scissors")) {
204
+ const result = adaptRPS(move);
205
+ if (result) return { raw: move, text: result, adapter: "rps" };
206
+ }
207
+ if (hint.includes("trivia") || hint.includes("quiz") || hint.includes("question")) {
208
+ const result = adaptTrivia(move);
209
+ if (result) return { raw: move, text: result, adapter: "trivia" };
210
+ }
211
+ if (hint.includes("debate") || hint.includes("argument")) {
212
+ const result = adaptDebate(move);
213
+ if (result) return { raw: move, text: result, adapter: "debate" };
214
+ }
215
+ if (typeof move === "object") {
216
+ const chess = adaptChess(move);
217
+ if (chess) return { raw: move, text: chess, adapter: "chess" };
218
+ const rps = adaptRPS(move);
219
+ if (rps) return { raw: move, text: rps, adapter: "rps" };
220
+ const combat = adaptCombat(move);
221
+ if (combat) return { raw: move, text: combat, adapter: "combat" };
222
+ const strategy = adaptStrategy(move);
223
+ if (strategy) return { raw: move, text: strategy, adapter: "strategy" };
224
+ const trivia = adaptTrivia(move);
225
+ if (trivia) return { raw: move, text: trivia, adapter: "trivia" };
226
+ const debate = adaptDebate(move);
227
+ if (debate) return { raw: move, text: debate, adapter: "debate" };
228
+ if (Array.isArray(move)) {
229
+ const text = move.map((m) => normalizeMove(m).text).join(", ");
230
+ return { raw: move, text, adapter: "array" };
231
+ }
232
+ const flat = flattenObject(move);
233
+ return { raw: move, text: flat, adapter: "generic-object" };
234
+ }
235
+ return { raw: move, text: String(move), adapter: "fallback" };
236
+ }
237
+
238
+ // src/client/TheRefClient.ts
239
+ var TheRefClient = class {
240
+ constructor(config) {
241
+ this.network = resolveNetwork(config.network);
242
+ this.retries = config.retries ?? 300;
243
+ this.pollInterval = config.pollInterval ?? 5e3;
244
+ this.wsUrl = config.wsUrl ?? DEFAULT_WS_URL;
245
+ const chain = this.network.chainId === 4221 ? chains.testnetBradbury : chains.studionet;
246
+ let account;
247
+ if (config.privateKey) {
248
+ account = createAccount(config.privateKey);
249
+ } else if (config.walletAddress) {
250
+ account = config.walletAddress;
251
+ } else {
252
+ account = createAccount(generatePrivateKey());
253
+ }
254
+ this.glClient = createClient({
255
+ chain,
256
+ endpoint: this.network.rpc,
257
+ account
258
+ });
259
+ }
260
+ // ── Internal helpers ────────────────────────────────────────────────────────
261
+ async write(address, method, args, value = 0n) {
262
+ const tx = await this.glClient.writeContract({
263
+ address,
264
+ functionName: method,
265
+ args,
266
+ value
267
+ });
268
+ const receipt = await this.glClient.waitForTransactionReceipt({
269
+ hash: tx,
270
+ status: TransactionStatus.ACCEPTED,
271
+ retries: this.retries
272
+ });
273
+ const leader = receipt?.consensus_data?.leader_receipt?.[0];
274
+ const payload = String(
275
+ leader?.result?.payload?.readable ?? receipt?.data?.result ?? ""
276
+ ).replace(/^"|"$/g, "");
277
+ return { payload, txHash: String(tx) };
278
+ }
279
+ async read(address, method, args = []) {
280
+ return this.glClient.readContract({
281
+ address,
282
+ functionName: method,
283
+ args
284
+ });
285
+ }
286
+ get CORE() {
287
+ return this.network.addresses.CORE;
288
+ }
289
+ get LB() {
290
+ return this.network.addresses.LB;
291
+ }
292
+ get TRN() {
293
+ return this.network.addresses.TRN;
294
+ }
295
+ mapGameState(raw) {
296
+ return {
297
+ gameId: raw.game_id ?? "",
298
+ gameName: raw.game_name ?? "",
299
+ status: raw.status ?? "waiting",
300
+ player1: raw.player1 ?? "",
301
+ player2: raw.player2 ?? "",
302
+ agent1: raw.agent1 ?? "",
303
+ agent2: raw.agent2 ?? "",
304
+ maxRounds: Number(raw.max_rounds ?? 0),
305
+ roundCount: Number(raw.round_count ?? 0),
306
+ judgedThrough: Number(raw.judged_through ?? 0),
307
+ rules: raw.rules ?? "",
308
+ winner: raw.winner ?? "",
309
+ score: raw.score ?? {},
310
+ playerTypes: raw.player_types ?? {},
311
+ caller: raw.caller ?? "",
312
+ rounds: (raw.rounds ?? []).map((r) => ({
313
+ roundNumber: r.round_number,
314
+ movePlayer1: r.move_player1 ?? "",
315
+ movePlayer2: r.move_player2 ?? "",
316
+ result: r.result ?? "pending",
317
+ reasonType: r.reason_type ?? "normal",
318
+ invalidPlayer: r.invalid_player ?? "none",
319
+ reasoning: r.reasoning ?? "",
320
+ confidence: Number(r.confidence ?? 0),
321
+ status: r.status ?? "pending"
322
+ }))
323
+ };
324
+ }
325
+ // ── Game API ────────────────────────────────────────────────────────────────
326
+ /**
327
+ * Create a new game. Returns the game ID.
328
+ */
329
+ async createGame(options) {
330
+ const { payload } = await this.write(this.CORE, "start_game", [
331
+ options.name,
332
+ options.visibility ?? "public",
333
+ options.maxRounds ?? 3,
334
+ options.rules ?? "",
335
+ options.player1,
336
+ options.player2 ?? "",
337
+ options.agent1 ?? 0,
338
+ options.agent2 ?? 0
339
+ ]);
340
+ return payload;
341
+ }
342
+ /**
343
+ * Submit a move for a player. Accepts ANY move format — string, object, array, etc.
344
+ * The SDK automatically normalizes it to a string the AI judge can understand.
345
+ */
346
+ async submitMove(gameId, playerName, move, gameHint) {
347
+ const normalized = normalizeMove(move, gameHint);
348
+ const { txHash } = await this.write(this.CORE, "submit_move", [
349
+ gidToNum(gameId),
350
+ playerName,
351
+ normalized.text
352
+ ]);
353
+ return { txHash, normalizedMove: normalized.text };
354
+ }
355
+ /**
356
+ * Judge the game — triggers AI consensus on all pending rounds.
357
+ */
358
+ async judgeGame(gameId) {
359
+ const { payload, txHash } = await this.write(
360
+ this.CORE,
361
+ "judge_game",
362
+ [gidToNum(gameId)]
363
+ );
364
+ const state = await this.getGameState(gameId);
365
+ return {
366
+ winner: state.winner,
367
+ isDraw: state.status === "draw",
368
+ score: state.score,
369
+ rounds: state.rounds,
370
+ txHash,
371
+ payload
372
+ };
373
+ }
374
+ /**
375
+ * End an open-ended game (max_rounds = 0). Only callable by the game creator.
376
+ */
377
+ async endGame(gameId) {
378
+ const { payload, txHash } = await this.write(
379
+ this.CORE,
380
+ "end_game",
381
+ [gidToNum(gameId)]
382
+ );
383
+ const state = await this.getGameState(gameId);
384
+ return {
385
+ winner: state.winner,
386
+ isDraw: state.status === "draw",
387
+ score: state.score,
388
+ rounds: state.rounds,
389
+ txHash,
390
+ payload
391
+ };
392
+ }
393
+ /**
394
+ * Get the full game state.
395
+ */
396
+ async getGameState(gameId) {
397
+ const raw = await this.read(this.CORE, "get_game_state", [gameId]);
398
+ return this.mapGameState(raw);
399
+ }
400
+ /**
401
+ * Get all active games.
402
+ */
403
+ async getActiveGames() {
404
+ const raw = await this.read(this.CORE, "get_active_games");
405
+ return (raw ?? []).map(this.mapGameState);
406
+ }
407
+ /**
408
+ * Get total number of games.
409
+ */
410
+ async getTotalGames() {
411
+ const result = await this.read(this.CORE, "get_total_games");
412
+ return Number(result ?? 0);
413
+ }
414
+ // ── Polling helpers ─────────────────────────────────────────────────────────
415
+ /**
416
+ * Wait until both players have submitted their move for a given round.
417
+ * Polls every `pollInterval` ms.
418
+ */
419
+ async waitForBothMoves(gameId, roundNumber) {
420
+ while (true) {
421
+ const state = await this.getGameState(gameId);
422
+ const round = state.rounds.find((r) => r.roundNumber === roundNumber);
423
+ if (round?.movePlayer1 && round?.movePlayer2) return round;
424
+ await this.sleep(this.pollInterval);
425
+ }
426
+ }
427
+ /**
428
+ * Wait until the opponent has submitted their move for a round.
429
+ * isPlayer1: true if you are player1, false if player2.
430
+ */
431
+ async waitForOpponentMove(gameId, roundNumber, isPlayer1) {
432
+ while (true) {
433
+ const state = await this.getGameState(gameId);
434
+ const round = state.rounds.find((r) => r.roundNumber === roundNumber);
435
+ const opponentMove = isPlayer1 ? round?.movePlayer2 : round?.movePlayer1;
436
+ if (opponentMove) return opponentMove;
437
+ await this.sleep(this.pollInterval);
438
+ }
439
+ }
440
+ /**
441
+ * Wait until the game reaches a specific status.
442
+ */
443
+ async waitForStatus(gameId, status) {
444
+ while (true) {
445
+ const state = await this.getGameState(gameId);
446
+ if (state.status === status) return state;
447
+ if (state.status === "completed" || state.status === "draw") return state;
448
+ await this.sleep(this.pollInterval);
449
+ }
450
+ }
451
+ /**
452
+ * Play a full game automatically.
453
+ * moveFn is called for each round — return your move in any format.
454
+ */
455
+ async playGame(gameId, playerName, isPlayer1, moveFn, gameHint) {
456
+ let state = await this.getGameState(gameId);
457
+ const maxRounds = state.maxRounds || 999;
458
+ for (let round = 1; round <= maxRounds; round++) {
459
+ state = await this.getGameState(gameId);
460
+ if (state.status !== "active") break;
461
+ if (!isPlayer1) {
462
+ await this.waitForOpponentMove(gameId, round, false);
463
+ }
464
+ state = await this.getGameState(gameId);
465
+ const move = await moveFn(state, round);
466
+ await this.submitMove(gameId, playerName, move, gameHint);
467
+ if (isPlayer1) {
468
+ await this.waitForOpponentMove(gameId, round, true);
469
+ }
470
+ state = await this.getGameState(gameId);
471
+ if (state.roundCount >= maxRounds) break;
472
+ }
473
+ return this.judgeGame(gameId);
474
+ }
475
+ // ── Leaderboard API ─────────────────────────────────────────────────────────
476
+ async getLeaderboard(gameName, playerType = "all") {
477
+ const raw = await this.read(this.LB, "get_leaderboard", [gameName, playerType]);
478
+ return (raw ?? []).map((e) => ({
479
+ player: e.player ?? "",
480
+ wins: Number(e.wins ?? 0),
481
+ losses: Number(e.losses ?? 0),
482
+ draws: Number(e.draws ?? 0),
483
+ score: Number(e.score ?? 0),
484
+ playerType: e.player_type ?? "human"
485
+ }));
486
+ }
487
+ async getTopPlayers(gameName, n = 10) {
488
+ const raw = await this.read(this.LB, "get_top_players", [gameName, n]);
489
+ return (raw ?? []).map((e) => ({
490
+ player: e.player ?? "",
491
+ wins: Number(e.wins ?? 0),
492
+ losses: Number(e.losses ?? 0),
493
+ draws: Number(e.draws ?? 0),
494
+ score: Number(e.score ?? 0),
495
+ playerType: e.player_type ?? "human"
496
+ }));
497
+ }
498
+ async getPlayerStats(gameName, playerName, playerType = "all") {
499
+ try {
500
+ const raw = await this.read(this.LB, "get_player_stats", [gameName, playerName, playerType]);
501
+ if (!raw) return null;
502
+ return {
503
+ player: raw.player ?? playerName,
504
+ wins: Number(raw.wins ?? 0),
505
+ losses: Number(raw.losses ?? 0),
506
+ draws: Number(raw.draws ?? 0),
507
+ score: Number(raw.score ?? 0),
508
+ games: Number(raw.games ?? 0),
509
+ playerType: raw.player_type ?? playerType
510
+ };
511
+ } catch {
512
+ return null;
513
+ }
514
+ }
515
+ // ── Tournament API ──────────────────────────────────────────────────────────
516
+ async createTournament(options) {
517
+ const { payload } = await this.write(this.TRN, "create_tournament", [
518
+ options.name,
519
+ options.gameName,
520
+ options.format,
521
+ options.maxPlayers,
522
+ 0,
523
+ // entry fee — always free
524
+ options.prizeSplit ?? [70, 30],
525
+ options.rules ?? "",
526
+ options.roundsPerMatch ?? 1
527
+ ]);
528
+ return payload;
529
+ }
530
+ async joinTournament(tid, playerName, playerType = "human") {
531
+ await this.write(this.TRN, "join_tournament", [tid, playerName, playerType]);
532
+ }
533
+ async startTournament(tid) {
534
+ await this.write(this.TRN, "start_tournament", [tid]);
535
+ }
536
+ async getTournament(tid) {
537
+ try {
538
+ const raw = await this.read(this.TRN, "get_tournament", [tid]);
539
+ if (!raw) return null;
540
+ return {
541
+ tid: raw.tid ?? tid,
542
+ name: raw.name ?? "",
543
+ gameName: raw.game_name ?? "",
544
+ format: raw.format ?? "",
545
+ maxPlayers: Number(raw.max_players ?? 0),
546
+ status: raw.status ?? "",
547
+ players: raw.players ?? [],
548
+ bracket: (raw.bracket ?? []).map((m) => ({
549
+ matchId: m.match_id,
550
+ round: m.round,
551
+ player1: m.player1,
552
+ player2: m.player2,
553
+ gameId: m.game_id,
554
+ winner: m.winner,
555
+ status: m.status
556
+ })),
557
+ winner: raw.winner ?? ""
558
+ };
559
+ } catch {
560
+ return null;
561
+ }
562
+ }
563
+ async listTournaments() {
564
+ const raw = await this.read(this.TRN, "list_tournaments");
565
+ return (raw ?? []).map((t) => ({
566
+ tid: t.tid ?? "",
567
+ name: t.name ?? "",
568
+ gameName: t.game_name ?? "",
569
+ format: t.format ?? "",
570
+ maxPlayers: Number(t.max_players ?? 0),
571
+ status: t.status ?? "",
572
+ players: t.players ?? [],
573
+ bracket: [],
574
+ winner: t.winner ?? ""
575
+ }));
576
+ }
577
+ async recordMatchResult(tid, matchId, winner) {
578
+ await this.write(this.TRN, "record_match_result", [tid, matchId, winner]);
579
+ }
580
+ // ── Utils ───────────────────────────────────────────────────────────────────
581
+ /** Normalize any move to a string without submitting */
582
+ normalizeMove(move, gameHint) {
583
+ return normalizeMove(move, gameHint);
584
+ }
585
+ /** Sleep helper */
586
+ sleep(ms) {
587
+ return new Promise((resolve) => setTimeout(resolve, ms));
588
+ }
589
+ };
590
+
591
+ // src/index.ts
592
+ function createTheRef(config) {
593
+ return new TheRefClient(config);
594
+ }
595
+ export {
596
+ NETWORKS,
597
+ TheRefClient,
598
+ createTheRef,
599
+ gidToNum,
600
+ normalizeMove,
601
+ resolveNetwork
602
+ };
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "theref-sdk",
3
+ "version": "0.1.0",
4
+ "description": "Universal SDK for TheRef — the decentralized AI game referee on GenLayer",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.mjs",
12
+ "require": "./dist/index.js"
13
+ }
14
+ },
15
+ "scripts": {
16
+ "build": "tsup src/index.ts --format cjs,esm --dts",
17
+ "dev": "tsup src/index.ts --format cjs,esm --dts --watch",
18
+ "test": "jest"
19
+ },
20
+ "keywords": ["genlayer", "theref", "ai", "gaming", "blockchain", "sdk", "agent"],
21
+ "author": "0xZaid10",
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "genlayer-js": "latest",
25
+ "ws": "^8.18.0"
26
+ },
27
+ "devDependencies": {
28
+ "tsup": "^8.0.0",
29
+ "typescript": "^5.0.0",
30
+ "@types/ws": "^8.5.0",
31
+ "@types/node": "^20.0.0"
32
+ },
33
+ "peerDependencies": {
34
+ "genlayer-js": "latest"
35
+ }
36
+ }
Binary file