@1upmonster/types 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024 1upmonster
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,3 @@
1
+ export * from "./tenant.js";
2
+ export * from "./versus.js";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,3 @@
1
+ export * from "./tenant.js";
2
+ export * from "./versus.js";
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
@@ -0,0 +1,24 @@
1
+ export interface Tenant {
2
+ id: string;
3
+ name: string;
4
+ ownerWallet: string;
5
+ createdAt: number;
6
+ }
7
+ export interface Game {
8
+ id: string;
9
+ tenantId: string;
10
+ name: string;
11
+ createdAt: number;
12
+ }
13
+ export interface ApiKey {
14
+ id: string;
15
+ name: string;
16
+ created_at: number;
17
+ }
18
+ export interface CreatedApiKey {
19
+ id: string;
20
+ gameId: string;
21
+ name: string;
22
+ key: string;
23
+ }
24
+ //# sourceMappingURL=tenant.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant.d.ts","sourceRoot":"","sources":["../src/tenant.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,MAAM;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;CACb"}
package/dist/tenant.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=tenant.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tenant.js","sourceRoot":"","sources":["../src/tenant.ts"],"names":[],"mappings":""}
@@ -0,0 +1,196 @@
1
+ export type EloType = "u8" | "u16" | "u32" | "u64" | "i8" | "i16" | "i32" | "i64";
2
+ export type EloAggregate = "average" | "max" | "min";
3
+ export type EloRpcFailBehavior = "reject" | "use_default" | "use_cached";
4
+ export type ExpireBehavior = "expire" | "match_any";
5
+ export interface PdaAccountConfig {
6
+ type: "pda";
7
+ /** Seeds as strings; use "{wallet}" as placeholder for the player's pubkey */
8
+ seeds: string[];
9
+ programId: string;
10
+ }
11
+ export interface StaticAccountConfig {
12
+ type: "static";
13
+ /** Use "{wallet}" as placeholder for the player's pubkey */
14
+ address: string;
15
+ }
16
+ export type EloAccountConfig = PdaAccountConfig | StaticAccountConfig;
17
+ export interface EloSourceConfig {
18
+ account: EloAccountConfig;
19
+ offset: number;
20
+ type: EloType;
21
+ endian: "little" | "big";
22
+ default: number;
23
+ rpcFailBehavior: EloRpcFailBehavior;
24
+ /**
25
+ * Byte offset of the authority field (32-byte Solana pubkey) within the same
26
+ * account. When set, the API verifies that account[authorityOffset..+32]
27
+ * matches the authenticated wallet before accepting the queue entry.
28
+ * Omit only if the account address itself is sufficient proof of ownership
29
+ * (e.g. a PDA uniquely derived from {wallet} with no shared seeds).
30
+ */
31
+ authorityOffset?: number;
32
+ /**
33
+ * The Solana program ID that must own the ELO account.
34
+ * For PDA configs this defaults to `account.programId` automatically.
35
+ * For static configs this must be set explicitly to prevent players from
36
+ * substituting arbitrary accounts with fake ELO data.
37
+ */
38
+ ownerProgramId?: string;
39
+ }
40
+ export type EloComputationMethod = "fixed" | "k_factor";
41
+ export interface EloComputationConfig {
42
+ /** "fixed": all teams get ±value regardless of rating gap.
43
+ * "k_factor": standard ELO formula; requires matchFormat.teams === 2. */
44
+ method: EloComputationMethod;
45
+ /** fixed: flat delta per player (e.g. 25).
46
+ * k_factor: K value (e.g. 32). Must be a positive finite number. */
47
+ value: number;
48
+ }
49
+ export interface MatchFormat {
50
+ /** Players per team. 1 = 1v1, 5 = 5v5 */
51
+ playersPerTeam: number;
52
+ /** Number of teams. Always 2 for now */
53
+ teams: number;
54
+ /** How to compute team ELO from individual ratings (irrelevant for 1v1) */
55
+ eloAggregate: EloAggregate;
56
+ }
57
+ export type ParticipantRole = "player" | "processor" | "spectator" | "agent";
58
+ export interface RoomParticipant {
59
+ walletPubkey: string;
60
+ role: ParticipantRole;
61
+ /** Team index (0-based). Only set for role="player" */
62
+ teamIndex?: number;
63
+ }
64
+ export interface GameProcessorConfig {
65
+ /**
66
+ * Wallet pubkey of the processor. Must match the walletPubkey in the
67
+ * processor's room JWT — this is the whitelist check in the Room DO.
68
+ */
69
+ walletAddress: string;
70
+ /**
71
+ * HTTPS URL the platform POSTs to when a match is finalized.
72
+ * Payload: { matchId, roomUrl, roomToken, participants, expiresAt }
73
+ * Must be https:// — never called over plain HTTP.
74
+ */
75
+ callbackUrl: string;
76
+ }
77
+ /**
78
+ * A single authoritative state update from the game processor.
79
+ * The platform only requires `seqId` — all other fields are opaque
80
+ * and defined by the game dev (e.g. Redux-style { type, payload }).
81
+ * The Room DO buffers these by seqId for client desync recovery.
82
+ */
83
+ export interface GameStateUpdate {
84
+ seqId: number;
85
+ [key: string]: unknown;
86
+ }
87
+ export interface VersusConfig {
88
+ gameId: string;
89
+ eloSource: EloSourceConfig;
90
+ matchFormat: MatchFormat;
91
+ /** Max seconds in queue before expiry (default: 120) */
92
+ queueTtl: number;
93
+ /** Max match duration in seconds (default: 3600) */
94
+ matchTtl: number;
95
+ /** Seconds to accept a found match (default: 15) */
96
+ acceptWindow: number;
97
+ /** What to do when queue TTL expires (default: "expire") */
98
+ expireBehavior: ExpireBehavior;
99
+ /**
100
+ * Optional game processor. When set the Room DO routes player game_message
101
+ * events exclusively to the processor instead of relaying P2P.
102
+ * Omit for pure P2P relay mode (default, backwards-compatible).
103
+ */
104
+ processor?: GameProcessorConfig;
105
+ /**
106
+ * How to compute ELO deltas for this game.
107
+ * Defaults to { method: "fixed", value: 25 } when absent.
108
+ * "k_factor" requires matchFormat.teams === 2.
109
+ */
110
+ eloComputation?: EloComputationConfig;
111
+ }
112
+ /** Actual states stored in queue_entries.state in the Queue DO SQLite table */
113
+ export type PlayerState = "queued" | "matched" | "left" | "expired";
114
+ export interface QueueEntry {
115
+ walletPubkey: string;
116
+ elo: number;
117
+ region: string;
118
+ queuedAt: number;
119
+ state: PlayerState;
120
+ }
121
+ export interface MatchTeam {
122
+ players: QueueEntry[];
123
+ avgElo: number;
124
+ }
125
+ export interface Match {
126
+ id: string;
127
+ gameId: string;
128
+ teams: MatchTeam[];
129
+ /**
130
+ * Participants manifest — built at finalizeMatch time. Used by the Room DO
131
+ * as the authoritative whitelist + routing table.
132
+ * Falls back to teams-derived player list for legacy matches (empty array).
133
+ */
134
+ participants: RoomParticipant[];
135
+ /**
136
+ * ELO stakes for each team, indexed by teamIndex.
137
+ * ifWin: delta applied to each player on the winning team.
138
+ * ifLose: delta applied to each player on the losing team (negative for standard ELO).
139
+ * Empty array for legacy matches that predate this field.
140
+ */
141
+ eloDeltas: Array<{
142
+ ifWin: number;
143
+ ifLose: number;
144
+ }>;
145
+ roomUrl: string;
146
+ createdAt: number;
147
+ /** Unix ms — all players must accept before this time */
148
+ acceptDeadline: number;
149
+ expiresAt: number;
150
+ state: "pending_accept" | "active" | "expired" | "completed";
151
+ }
152
+ export type ClientMessageType = "ping" | "ready" | "accept_match" | "decline_match" | "game_message" | "initial_game_state" | "game_state_update" | "game_over" | "catch_up";
153
+ export type ServerMessageType = "pong" | "queue_expired" | "match_found" | "match_declined" | "match_ready" | "room_ready" | "game_message" | "opponent_disconnected" | "match_expired" | "error" | "room_metadata" | "initial_game_state" | "game_state_update" | "game_over" | "catch_up";
154
+ export interface ClientMessage<T = unknown> {
155
+ type: ClientMessageType;
156
+ payload?: T;
157
+ }
158
+ export interface ServerMessage<T = unknown> {
159
+ type: ServerMessageType;
160
+ payload?: T;
161
+ }
162
+ export interface MatchFoundPayload {
163
+ matchId: string;
164
+ opponents: Array<{
165
+ walletPubkey: string;
166
+ elo: number;
167
+ }>;
168
+ acceptDeadline: number;
169
+ }
170
+ export interface MatchReadyPayload {
171
+ matchId: string;
172
+ /** HS256 token — use as ?token= when connecting to the room WebSocket */
173
+ roomToken: string;
174
+ roomUrl: string;
175
+ }
176
+ export interface GameMessagePayload {
177
+ from: string;
178
+ data: unknown;
179
+ }
180
+ export interface MatchDeclinedPayload {
181
+ reason: "declined" | "timeout";
182
+ /** Wallet that declined or timed out */
183
+ walletPubkey: string;
184
+ }
185
+ export interface RoomMetadataPayload {
186
+ match: Match;
187
+ participants: RoomParticipant[];
188
+ }
189
+ export interface CatchUpPayload {
190
+ actions: GameStateUpdate[];
191
+ }
192
+ export interface CatchUpRequestPayload {
193
+ fromSeq: number;
194
+ toSeq: number;
195
+ }
196
+ //# sourceMappingURL=versus.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versus.d.ts","sourceRoot":"","sources":["../src/versus.ts"],"names":[],"mappings":"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"}
package/dist/versus.js ADDED
@@ -0,0 +1,5 @@
1
+ // ---------------------------------------------------------------------------
2
+ // ELO configuration
3
+ // ---------------------------------------------------------------------------
4
+ export {};
5
+ //# sourceMappingURL=versus.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"versus.js","sourceRoot":"","sources":["../src/versus.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,oBAAoB;AACpB,8EAA8E"}
package/package.json ADDED
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "@1upmonster/types",
3
+ "version": "0.1.0",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "import": "./dist/index.js",
9
+ "types": "./dist/index.d.ts"
10
+ }
11
+ },
12
+ "publishConfig": {
13
+ "access": "public"
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "devDependencies": {
19
+ "typescript": "^5.7.2"
20
+ },
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "typecheck": "tsc --noEmit",
24
+ "clean": "rm -rf dist"
25
+ }
26
+ }