@flayerlabs/gamemode-gate 0.2.0 → 0.3.1
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 +37 -4
- package/dist/demo.d.ts.map +1 -1
- package/dist/demo.js +2 -0
- package/dist/demo.js.map +1 -1
- package/dist/economy.d.ts +9 -0
- package/dist/economy.d.ts.map +1 -1
- package/dist/economy.js +1 -1
- package/dist/economy.js.map +1 -1
- package/dist/game-registry.d.ts.map +1 -1
- package/dist/game-registry.js +4 -1
- package/dist/game-registry.js.map +1 -1
- package/dist/game-server-awards.d.ts +37 -0
- package/dist/game-server-awards.d.ts.map +1 -1
- package/dist/game-server-awards.js +49 -0
- package/dist/game-server-awards.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/player-join-tickets.d.ts +29 -0
- package/dist/player-join-tickets.d.ts.map +1 -0
- package/dist/player-join-tickets.js +112 -0
- package/dist/player-join-tickets.js.map +1 -0
- package/dist/registry.d.ts +5 -9
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +24 -4
- package/dist/registry.js.map +1 -1
- package/dist/room.d.ts +4 -3
- package/dist/room.d.ts.map +1 -1
- package/dist/room.js +27 -11
- package/dist/room.js.map +1 -1
- package/dist/server.d.ts +2 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +91 -13
- package/dist/server.js.map +1 -1
- package/dist/sessions.d.ts +2 -0
- package/dist/sessions.d.ts.map +1 -1
- package/dist/sessions.js +4 -0
- package/dist/sessions.js.map +1 -1
- package/dist/store.d.ts +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +14 -0
- package/dist/store.js.map +1 -1
- package/package.json +2 -2
- package/src/demo.ts +2 -0
- package/src/economy.ts +10 -1
- package/src/game-registry.ts +10 -2
- package/src/game-server-awards.ts +86 -0
- package/src/index.ts +5 -0
- package/src/player-join-tickets.ts +151 -0
- package/src/registry.ts +34 -10
- package/src/room.ts +31 -11
- package/src/server.ts +105 -14
- package/src/sessions.ts +5 -0
- package/src/store.ts +14 -0
package/dist/registry.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { parseGameServerOrigins, } from '@flayerlabs/gamemode-spec/embed';
|
|
1
2
|
export class InvalidRegistration extends Error {
|
|
2
3
|
constructor(message) {
|
|
3
4
|
super(message);
|
|
@@ -69,16 +70,29 @@ export function gateOrigin(value) {
|
|
|
69
70
|
}
|
|
70
71
|
return url.origin;
|
|
71
72
|
}
|
|
73
|
+
/** Validate the reviewed origins a creator-owned authoritative game server may use. */
|
|
74
|
+
export function gameServerOrigins(value) {
|
|
75
|
+
const origins = parseGameServerOrigins(value);
|
|
76
|
+
if (origins === null) {
|
|
77
|
+
throw new InvalidRegistration('game server origins must be at most four distinct public HTTPS origins');
|
|
78
|
+
}
|
|
79
|
+
return origins;
|
|
80
|
+
}
|
|
72
81
|
/** The profile for a registration. The websocket address is derived, never supplied separately. */
|
|
73
82
|
export function securityProfile(registration) {
|
|
74
83
|
// Revalidated here on purpose: this is the value that leaves for another system, and checking it
|
|
75
84
|
// at the boundary costs nothing.
|
|
76
85
|
const origin = gateOrigin(registration.gateOrigin);
|
|
86
|
+
const servers = gameServerOrigins(registration.gameServerOrigins);
|
|
77
87
|
return {
|
|
78
88
|
kind: 'game',
|
|
79
89
|
// Same host, same port, different scheme. Deriving it means the two can never name different
|
|
80
90
|
// servers, which a second hand-entered field eventually would.
|
|
81
|
-
connect: {
|
|
91
|
+
connect: {
|
|
92
|
+
https: origin,
|
|
93
|
+
wss: `wss://${new URL(origin).host}`,
|
|
94
|
+
...(servers.length === 0 ? {} : { gameServerOrigins: servers }),
|
|
95
|
+
},
|
|
82
96
|
};
|
|
83
97
|
}
|
|
84
98
|
function id(value, what) {
|
|
@@ -108,12 +122,14 @@ export function checkRegistration(entry) {
|
|
|
108
122
|
if (typeof entry?.coin !== 'string' || !ADDRESS.test(entry.coin)) {
|
|
109
123
|
throw new InvalidRegistration('coin must be a wallet address');
|
|
110
124
|
}
|
|
125
|
+
const servers = gameServerOrigins(entry.gameServerOrigins);
|
|
111
126
|
return {
|
|
112
127
|
chainId: chainId(entry.chainId),
|
|
113
128
|
coin: entry.coin.toLowerCase(),
|
|
114
129
|
gameId: id(entry.gameId, 'game'),
|
|
115
130
|
deployId: deployId(entry.deployId),
|
|
116
131
|
gateOrigin: gateOrigin(entry.gateOrigin),
|
|
132
|
+
...(servers.length === 0 ? {} : { gameServerOrigins: servers }),
|
|
117
133
|
};
|
|
118
134
|
}
|
|
119
135
|
/**
|
|
@@ -121,14 +137,17 @@ export function checkRegistration(entry) {
|
|
|
121
137
|
*/
|
|
122
138
|
export async function pinGameRegistration(pool, entry) {
|
|
123
139
|
const checked = checkRegistration(entry);
|
|
124
|
-
const
|
|
140
|
+
const servers = checked.gameServerOrigins ?? [];
|
|
141
|
+
const result = await pool.query(`insert into registrations (chain_id, coin, game_id, gate_origin, deploy_id, game_server_origins)
|
|
142
|
+
values ($1, $2, $3, $4, $5, $6)
|
|
125
143
|
on conflict (chain_id, coin) do update set
|
|
126
144
|
updated_at = registrations.updated_at
|
|
127
145
|
where registrations.disabled_at is null
|
|
128
146
|
and registrations.game_id = excluded.game_id
|
|
129
147
|
and registrations.gate_origin = excluded.gate_origin
|
|
130
148
|
and registrations.deploy_id = excluded.deploy_id
|
|
131
|
-
|
|
149
|
+
and registrations.game_server_origins = excluded.game_server_origins
|
|
150
|
+
returning coin`, [checked.chainId, checked.coin, checked.gameId, checked.gateOrigin, checked.deployId, servers]);
|
|
132
151
|
if (result.rows.length === 0)
|
|
133
152
|
throw new RegistrationConflict();
|
|
134
153
|
return checked;
|
|
@@ -138,7 +157,7 @@ export async function resolveGameRegistration(pool, requestedChainId, coin) {
|
|
|
138
157
|
if (typeof coin !== 'string' || !ADDRESS.test(coin)) {
|
|
139
158
|
throw new InvalidRegistration('coin must be a wallet address');
|
|
140
159
|
}
|
|
141
|
-
const result = await pool.query(`select chain_id::text, coin, game_id, gate_origin, deploy_id
|
|
160
|
+
const result = await pool.query(`select chain_id::text, coin, game_id, gate_origin, deploy_id, game_server_origins
|
|
142
161
|
from registrations where chain_id = $1 and coin = $2 and disabled_at is null`, [checkedChainId, coin.toLowerCase()]);
|
|
143
162
|
const row = result.rows[0];
|
|
144
163
|
return row
|
|
@@ -148,6 +167,7 @@ export async function resolveGameRegistration(pool, requestedChainId, coin) {
|
|
|
148
167
|
gameId: row.game_id,
|
|
149
168
|
gateOrigin: row.gate_origin,
|
|
150
169
|
deployId: row.deploy_id,
|
|
170
|
+
gameServerOrigins: row.game_server_origins,
|
|
151
171
|
})
|
|
152
172
|
: null;
|
|
153
173
|
}
|
package/dist/registry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
|
package/dist/room.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Pool } from 'pg';
|
|
2
2
|
import type { Command, Decision, GameModule, PlayerId, Refusal, RoundWindow } from '@flayerlabs/gamemode-spec';
|
|
3
|
-
import type { LaunchContext } from '@flayerlabs/gamemode-spec/live';
|
|
3
|
+
import type { LaunchContext, RoundTerms } from '@flayerlabs/gamemode-spec/live';
|
|
4
4
|
/**
|
|
5
5
|
* Everything except a wake.
|
|
6
6
|
*
|
|
@@ -29,8 +29,7 @@ export declare class Room<Config, State, Event, Action, PublicView, PlayerView>
|
|
|
29
29
|
private round;
|
|
30
30
|
readonly window: RoundWindow;
|
|
31
31
|
readonly launch: LaunchContext;
|
|
32
|
-
readonly
|
|
33
|
-
readonly maxPointsPerPlayer: number;
|
|
32
|
+
readonly terms: RoundTerms;
|
|
34
33
|
readonly scoreAuthority: ScoreAuthority;
|
|
35
34
|
private seq;
|
|
36
35
|
/**
|
|
@@ -46,6 +45,8 @@ export declare class Room<Config, State, Event, Action, PublicView, PlayerView>
|
|
|
46
45
|
window: RoundWindow;
|
|
47
46
|
weiPerPoint: bigint;
|
|
48
47
|
walletCapWei: bigint;
|
|
48
|
+
pointsPerDollar: number;
|
|
49
|
+
usdPerEth: number;
|
|
49
50
|
maxPointsPerPlayer: number;
|
|
50
51
|
scoreAuthority: ScoreAuthority;
|
|
51
52
|
poolId: string;
|
package/dist/room.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"room.d.ts","sourceRoot":"","sources":["../src/room.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAE/B,OAAO,KAAK,EAAS,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACtH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"room.d.ts","sourceRoot":"","sources":["../src/room.ts"],"names":[],"mappings":"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"}
|
package/dist/room.js
CHANGED
|
@@ -18,8 +18,7 @@ export class Room {
|
|
|
18
18
|
round;
|
|
19
19
|
window;
|
|
20
20
|
launch;
|
|
21
|
-
|
|
22
|
-
maxPointsPerPlayer;
|
|
21
|
+
terms;
|
|
23
22
|
scoreAuthority;
|
|
24
23
|
seq;
|
|
25
24
|
/**
|
|
@@ -27,15 +26,14 @@ export class Room {
|
|
|
27
26
|
* inside a process by running both through the same serial tail.
|
|
28
27
|
*/
|
|
29
28
|
pending = Promise.resolve();
|
|
30
|
-
constructor(pool, game, id, round, window, launch,
|
|
29
|
+
constructor(pool, game, id, round, window, launch, terms, scoreAuthority, seq) {
|
|
31
30
|
this.pool = pool;
|
|
32
31
|
this.game = game;
|
|
33
32
|
this.id = id;
|
|
34
33
|
this.round = round;
|
|
35
34
|
this.window = window;
|
|
36
35
|
this.launch = launch;
|
|
37
|
-
this.
|
|
38
|
-
this.maxPointsPerPlayer = maxPointsPerPlayer;
|
|
36
|
+
this.terms = terms;
|
|
39
37
|
this.scoreAuthority = scoreAuthority;
|
|
40
38
|
this.seq = seq;
|
|
41
39
|
}
|
|
@@ -58,16 +56,26 @@ export class Room {
|
|
|
58
56
|
closesAt: round.window.closesAt,
|
|
59
57
|
booksCloseAt,
|
|
60
58
|
});
|
|
59
|
+
const terms = Object.freeze({
|
|
60
|
+
maxPointsPerPlayer: round.maxPointsPerPlayer,
|
|
61
|
+
walletCapWei: round.walletCapWei,
|
|
62
|
+
weiPerPoint: round.weiPerPoint,
|
|
63
|
+
pointsPerDollar: round.pointsPerDollar,
|
|
64
|
+
usdPerEth: round.usdPerEth,
|
|
65
|
+
});
|
|
61
66
|
const started = Round.start(game, round.config, round.seed, round.window);
|
|
62
67
|
await pool.query(`insert into rounds (
|
|
63
|
-
id, game_id, wei_per_point, wallet_cap_wei,
|
|
68
|
+
id, game_id, wei_per_point, wallet_cap_wei, points_per_dollar, usd_per_eth,
|
|
69
|
+
max_points_per_player, score_authority,
|
|
64
70
|
pool_id, opens_at, closes_at, books_close_at,
|
|
65
71
|
coin_address, coin_name, coin_symbol, coin_image_url, state, seq
|
|
66
|
-
) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, 0)`, [
|
|
72
|
+
) values ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, 0)`, [
|
|
67
73
|
round.id,
|
|
68
74
|
game.id,
|
|
69
75
|
round.weiPerPoint.toString(),
|
|
70
76
|
round.walletCapWei.toString(),
|
|
77
|
+
round.pointsPerDollar,
|
|
78
|
+
round.usdPerEth,
|
|
71
79
|
round.maxPointsPerPlayer,
|
|
72
80
|
round.scoreAuthority,
|
|
73
81
|
round.poolId,
|
|
@@ -80,11 +88,12 @@ export class Room {
|
|
|
80
88
|
launch.imageUrl,
|
|
81
89
|
serialise(game.id, started.snapshot()),
|
|
82
90
|
]);
|
|
83
|
-
return new Room(pool, game, round.id, started, round.window, launch,
|
|
91
|
+
return new Room(pool, game, round.id, started, round.window, launch, terms, round.scoreAuthority, 0);
|
|
84
92
|
}
|
|
85
93
|
/** Pick up a round that already exists. Returns null if there is no such round. */
|
|
86
94
|
static async load(pool, game, id) {
|
|
87
95
|
const result = await pool.query(`select state, seq, pool_id, opens_at, closes_at, books_close_at, wei_per_point,
|
|
96
|
+
wallet_cap_wei, points_per_dollar, usd_per_eth,
|
|
88
97
|
max_points_per_player, score_authority, game_id,
|
|
89
98
|
coin_address, coin_name, coin_symbol, coin_image_url
|
|
90
99
|
from rounds where id = $1`, [id]);
|
|
@@ -104,7 +113,14 @@ export class Room {
|
|
|
104
113
|
...window,
|
|
105
114
|
booksCloseAt: Number(row.books_close_at),
|
|
106
115
|
});
|
|
107
|
-
|
|
116
|
+
const terms = Object.freeze({
|
|
117
|
+
maxPointsPerPlayer: Number(row.max_points_per_player),
|
|
118
|
+
walletCapWei: toBigInt(row.wallet_cap_wei),
|
|
119
|
+
weiPerPoint: toBigInt(row.wei_per_point),
|
|
120
|
+
pointsPerDollar: Number(row.points_per_dollar),
|
|
121
|
+
usdPerEth: Number(row.usd_per_eth),
|
|
122
|
+
});
|
|
123
|
+
return new Room(pool, game, id, Round.resume(game, row.state, window), window, launch, terms, row.score_authority, row.seq);
|
|
108
124
|
}
|
|
109
125
|
/**
|
|
110
126
|
* Apply one command and commit everything it caused.
|
|
@@ -167,12 +183,12 @@ export class Room {
|
|
|
167
183
|
// Same transaction as the state that earned them. Points credited without the state that
|
|
168
184
|
// justifies them, or the reverse, is a ledger nobody can reconcile.
|
|
169
185
|
const points = Math.floor(award.points);
|
|
170
|
-
if (points > this.maxPointsPerPlayer) {
|
|
186
|
+
if (points > this.terms.maxPointsPerPlayer) {
|
|
171
187
|
throw new Error(`${this.game.id}: awards exceeded the declared maximum for ${award.player}`);
|
|
172
188
|
}
|
|
173
189
|
const credited = await tx.query(`insert into balances (round_id, player, points) values ($1, $2, $3)
|
|
174
190
|
on conflict (round_id, player) do update set points = balances.points + excluded.points
|
|
175
|
-
where balances.points + excluded.points <= $4`, [this.id, award.player, points, this.maxPointsPerPlayer]);
|
|
191
|
+
where balances.points + excluded.points <= $4`, [this.id, award.player, points, this.terms.maxPointsPerPlayer]);
|
|
176
192
|
if (credited.rowCount !== 1) {
|
|
177
193
|
throw new Error(`${this.game.id}: awards exceeded the declared maximum for ${award.player}`);
|
|
178
194
|
}
|
package/dist/room.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"room.js","sourceRoot":"","sources":["../src/room.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAC;AAGxD,OAAO,EAAE,SAAS,EAAE,MAAM,2BAA2B,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAYrD;;;;;;;;;GASG;AACH,MAAM,OAAO,IAAI;IAQI;IACA;IACR;IACD;IACC;IACA;IACA;IACA;
|
|
1
|
+
{"version":3,"file":"room.js","sourceRoot":"","sources":["../src/room.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -69,6 +69,8 @@ export interface GameServerGateOptions extends GateBaseOptions {
|
|
|
69
69
|
maxPointsPerPlayer: number | MaxPointsForLaunch;
|
|
70
70
|
/** Dedicated server-to-server token. Never expose it to browser game code. */
|
|
71
71
|
awardToken: string;
|
|
72
|
+
/** Reviewed HTTPS origins that may receive player join tickets. The gate origin is always allowed. */
|
|
73
|
+
gameServerOrigins?: readonly string[];
|
|
72
74
|
}
|
|
73
75
|
/** Where an admission check is being made. Enough to tell a sign-in from a spend. */
|
|
74
76
|
export interface AdmissionRequest {
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAgB,EAAE,KAAK,eAAe,EAA0C,MAAM,SAAS,CAAC;AAGhG,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,IAAI,CAAC;AAC/B,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/dist/server.js
CHANGED
|
@@ -10,9 +10,28 @@ import { resolveEconomy } from './economy.js';
|
|
|
10
10
|
import { encodeHookData } from './chain/signer.js';
|
|
11
11
|
import { hasBearerToken } from './bearer.js';
|
|
12
12
|
import { GameServerAwards } from './game-server-awards.js';
|
|
13
|
+
import { issuePlayerJoinTicket } from './player-join-tickets.js';
|
|
14
|
+
import { gameServerOrigins } from './registry.js';
|
|
13
15
|
const ADMIT_ALL = () => ({ ok: true });
|
|
14
16
|
/** What the socket says, which is only the truth when nothing is proxying in front of the gate. */
|
|
15
17
|
const ipOf = (request) => request.ip || null;
|
|
18
|
+
/** Wei has no JSON form, so terms cross as decimal strings, exactly as the economy balance does. */
|
|
19
|
+
const wireTerms = (terms) => ({
|
|
20
|
+
maxPointsPerPlayer: terms.maxPointsPerPlayer,
|
|
21
|
+
walletCapWei: terms.walletCapWei.toString(),
|
|
22
|
+
weiPerPoint: terms.weiPerPoint.toString(),
|
|
23
|
+
pointsPerDollar: terms.pointsPerDollar,
|
|
24
|
+
usdPerEth: terms.usdPerEth,
|
|
25
|
+
});
|
|
26
|
+
/** The same encoding for the per-player balance, wherever it leaves the process. */
|
|
27
|
+
const wireEconomy = (balance) => ({
|
|
28
|
+
weiPerPoint: balance.weiPerPoint.toString(),
|
|
29
|
+
earnedWei: balance.earnedWei.toString(),
|
|
30
|
+
heldWei: balance.heldWei.toString(),
|
|
31
|
+
spentWei: balance.spentWei.toString(),
|
|
32
|
+
availableWei: balance.availableWei.toString(),
|
|
33
|
+
holdExpiresAt: balance.holdExpiresAt,
|
|
34
|
+
});
|
|
16
35
|
/** How often each open room is nudged so a deadline nobody is watching still fires. */
|
|
17
36
|
const TICK_MS = 250;
|
|
18
37
|
/**
|
|
@@ -67,8 +86,9 @@ export function createGameServerGate(options) {
|
|
|
67
86
|
const config = typeof maximum === 'function'
|
|
68
87
|
? async (launch) => ({ maxPointsPerPlayer: await maximum(launch) })
|
|
69
88
|
: { maxPointsPerPlayer: maximum };
|
|
70
|
-
const
|
|
71
|
-
|
|
89
|
+
const ticketAudiences = new Set([options.sessions.origin, ...gameServerOrigins(options.gameServerOrigins)]);
|
|
90
|
+
const { gameId, maxPointsPerPlayer: _maximum, awardToken, gameServerOrigins: _origins, ...base } = options;
|
|
91
|
+
return createGateRuntime({ ...base, game: gameServerModule(gameId), config }, 'external-server', { token: awardToken, awards: new GameServerAwards(options.pool, gameId), ticketAudiences });
|
|
72
92
|
}
|
|
73
93
|
function createGateRuntime(options, scoreAuthority, awardEndpoint) {
|
|
74
94
|
const { pool, game, sessions, claims, discovery, settlement } = options;
|
|
@@ -170,6 +190,8 @@ function createGateRuntime(options, scoreAuthority, awardEndpoint) {
|
|
|
170
190
|
seed: Number(BigInt(launch.poolId) % 2147483647n),
|
|
171
191
|
window: { opensAt: launch.opensAt, closesAt: launch.closesAt },
|
|
172
192
|
weiPerPoint: economy.economy.weiPerPoint,
|
|
193
|
+
pointsPerDollar: economy.economy.pointsPerDollar,
|
|
194
|
+
usdPerEth: economy.economy.usdPerEth,
|
|
173
195
|
walletCapWei: launch.walletCapWei,
|
|
174
196
|
maxPointsPerPlayer,
|
|
175
197
|
scoreAuthority,
|
|
@@ -289,11 +311,39 @@ function createGateRuntime(options, scoreAuthority, awardEndpoint) {
|
|
|
289
311
|
const adopted = await flight;
|
|
290
312
|
if (!adopted.ok)
|
|
291
313
|
return reply.code(adopted.status).send({ message: adopted.message });
|
|
314
|
+
// Terms ride alongside the launch rather than replacing it, so a caller that already parses
|
|
315
|
+
// this body as a LaunchContext keeps working and one that wants the round's economy does not
|
|
316
|
+
// need a second request for a value that was fixed by this very call.
|
|
292
317
|
return reply
|
|
293
318
|
.code(createdByThisRequest && adopted.created ? 201 : 200)
|
|
294
|
-
.send(adopted.room.launch);
|
|
319
|
+
.send({ ...adopted.room.launch, terms: wireTerms(adopted.room.terms) });
|
|
295
320
|
});
|
|
296
321
|
if (awardEndpoint) {
|
|
322
|
+
app.post('/rounds/:id/join-ticket', async (request, reply) => {
|
|
323
|
+
const who = player(request);
|
|
324
|
+
const id = request.params.id;
|
|
325
|
+
const room = await roomFor(id);
|
|
326
|
+
if (!room)
|
|
327
|
+
return reply.code(404).send({ message: 'that game is not running' });
|
|
328
|
+
const now = Date.now();
|
|
329
|
+
if (now >= room.window.closesAt) {
|
|
330
|
+
return reply.code(409).send({ message: 'that game has ended' });
|
|
331
|
+
}
|
|
332
|
+
const requested = request.body?.audience;
|
|
333
|
+
const audience = requested === undefined ? sessions.origin : requested;
|
|
334
|
+
if (typeof audience !== 'string' || !awardEndpoint.ticketAudiences.has(audience)) {
|
|
335
|
+
return reply.code(400).send({ message: 'that game server is not registered' });
|
|
336
|
+
}
|
|
337
|
+
return issuePlayerJoinTicket({
|
|
338
|
+
awardToken: awardEndpoint.token,
|
|
339
|
+
player: who,
|
|
340
|
+
gameId: game.id,
|
|
341
|
+
roundId: id,
|
|
342
|
+
audience,
|
|
343
|
+
closesAt: room.window.closesAt,
|
|
344
|
+
now,
|
|
345
|
+
});
|
|
346
|
+
});
|
|
297
347
|
app.post('/internal/rounds/:id/awards', async (request, reply) => {
|
|
298
348
|
if (!hasBearerToken(request.headers.authorization, awardEndpoint.token)) {
|
|
299
349
|
return reply.code(401).send({ message: 'game server authentication failed' });
|
|
@@ -316,6 +366,35 @@ function createGateRuntime(options, scoreAuthority, awardEndpoint) {
|
|
|
316
366
|
announcePlayer(result.award.roundId, result.award.player);
|
|
317
367
|
return reply.code(result.created ? 201 : 200).send(result.award);
|
|
318
368
|
});
|
|
369
|
+
/**
|
|
370
|
+
* What one wallet has earned, so a game server can refuse a seat before the player sits in it.
|
|
371
|
+
*
|
|
372
|
+
* Advisory, and deliberately so. The award route still enforces the ceiling inside the
|
|
373
|
+
* transaction that moves the balance, so a caller that stops handling `award.limit_exceeded`
|
|
374
|
+
* because it checked here first has moved the check out of the only place it is atomic.
|
|
375
|
+
*
|
|
376
|
+
* Never routed through `roomFor`: that resurrects rooms, advances game state and returns
|
|
377
|
+
* nothing once the books close — none of which a read should do.
|
|
378
|
+
*/
|
|
379
|
+
app.get('/internal/rounds/:id/players/:player', async (request, reply) => {
|
|
380
|
+
if (!hasBearerToken(request.headers.authorization, awardEndpoint.token)) {
|
|
381
|
+
return reply.code(401).send({ message: 'game server authentication failed' });
|
|
382
|
+
}
|
|
383
|
+
const params = request.params;
|
|
384
|
+
const result = await awardEndpoint.awards.pointsFor({
|
|
385
|
+
roundId: params.id,
|
|
386
|
+
player: params.player,
|
|
387
|
+
});
|
|
388
|
+
if (!result.ok) {
|
|
389
|
+
return reply.code(result.refuse === 'award.invalid' ? 400 : 404).send({ refuse: result.refuse });
|
|
390
|
+
}
|
|
391
|
+
// `heldWei` moves on its own when an authorisation expires, so this answer is only true at the
|
|
392
|
+
// moment it is read. Points are monotone; the wei beside them are not.
|
|
393
|
+
const balance = await claims.economyBalance(result.standing.roundId, result.standing.player);
|
|
394
|
+
return reply
|
|
395
|
+
.header('cache-control', 'no-store')
|
|
396
|
+
.send({ ...result.standing, economy: wireEconomy(balance) });
|
|
397
|
+
});
|
|
319
398
|
}
|
|
320
399
|
app.get('/rounds/:id', async (request, reply) => {
|
|
321
400
|
const id = request.params.id;
|
|
@@ -326,7 +405,12 @@ function createGateRuntime(options, scoreAuthority, awardEndpoint) {
|
|
|
326
405
|
await room.tick(Date.now());
|
|
327
406
|
if (room.sequence() !== before)
|
|
328
407
|
announce(id);
|
|
329
|
-
return {
|
|
408
|
+
return {
|
|
409
|
+
sequence: room.sequence(),
|
|
410
|
+
view: room.publicView(),
|
|
411
|
+
launch: room.launch,
|
|
412
|
+
terms: wireTerms(room.terms),
|
|
413
|
+
};
|
|
330
414
|
});
|
|
331
415
|
app.post('/rounds/:id/join', async (request, reply) => {
|
|
332
416
|
const room = await roomFor(request.params.id);
|
|
@@ -498,21 +582,14 @@ function createGateRuntime(options, scoreAuthority, awardEndpoint) {
|
|
|
498
582
|
const balance = viewer
|
|
499
583
|
? await claims.economyBalance(id, viewer)
|
|
500
584
|
: {
|
|
501
|
-
weiPerPoint: room.weiPerPoint,
|
|
585
|
+
weiPerPoint: room.terms.weiPerPoint,
|
|
502
586
|
earnedWei: 0n,
|
|
503
587
|
heldWei: 0n,
|
|
504
588
|
spentWei: 0n,
|
|
505
589
|
availableWei: 0n,
|
|
506
590
|
holdExpiresAt: null,
|
|
507
591
|
};
|
|
508
|
-
const economy =
|
|
509
|
-
weiPerPoint: balance.weiPerPoint.toString(),
|
|
510
|
-
earnedWei: balance.earnedWei.toString(),
|
|
511
|
-
heldWei: balance.heldWei.toString(),
|
|
512
|
-
spentWei: balance.spentWei.toString(),
|
|
513
|
-
availableWei: balance.availableWei.toString(),
|
|
514
|
-
holdExpiresAt: balance.holdExpiresAt,
|
|
515
|
-
};
|
|
592
|
+
const economy = wireEconomy(balance);
|
|
516
593
|
return {
|
|
517
594
|
v: LIVE_PROTOCOL_VERSION,
|
|
518
595
|
type: 'snapshot',
|
|
@@ -521,6 +598,7 @@ function createGateRuntime(options, scoreAuthority, awardEndpoint) {
|
|
|
521
598
|
view: room.publicView(),
|
|
522
599
|
you: viewer ? room.playerView(viewer) : null,
|
|
523
600
|
economy,
|
|
601
|
+
terms: wireTerms(room.terms),
|
|
524
602
|
launch: room.launch,
|
|
525
603
|
presence: presence(id),
|
|
526
604
|
};
|