@flayerlabs/gamemode-client 0.5.6 → 0.7.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/mock.d.ts CHANGED
@@ -12,9 +12,6 @@ export declare class MockRoom<Config, State, Event, Action, PublicView, PlayerVi
12
12
  private readonly reactionListeners;
13
13
  private readonly timer;
14
14
  private spent;
15
- private held;
16
- /** Mirrors the gate's five-minute hold, so a game can build the countdown against the mock. */
17
- private holdExpiresAt;
18
15
  private buyProgress;
19
16
  private disposed;
20
17
  private readonly connectionSignal;
@@ -1 +1 @@
1
- {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,UAAU,EAAiB,MAAM,2BAA2B,CAAC;AACtF,OAAO,KAAK,EAA0B,OAAO,EAAgB,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACjI,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAElB,KAAK,UAAU,EAChB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAWvD,qBAAa,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CACxE,YAAW,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC;IAuB7C,OAAO,CAAC,QAAQ,CAAC,IAAI;IArBvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8D;IACpF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsB;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4D;IACtF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAoC;IACtE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,IAAI,CAAM;IAClB,+FAA+F;IAC/F,OAAO,CAAC,aAAa,CAAuB;IAC5C,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4C;IAC7E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwB;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoD;IACnF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;gBAGrB,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,EACvF,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC;IAiF9B,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,IAAI;IASZ,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAQ/E,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAW/C,GAAG,IAAI,MAAM;IAMb,QAAQ,CAAC,MAAM;;8BAES,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI;MACpD;IAEF,QAAQ,CAAC,KAAK;;8BAEU,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;MACjD;IAEF,QAAQ,CAAC,UAAU;;8BAEK,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI;MACtD;IAEF,QAAQ,CAAC,MAAM;;8BAES,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI;MAClD;IAEF,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAE1C,QAAQ,CAAC,QAAQ;;8BAEO,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI;MACpD;IAEF,OAAO,CAAC,YAAY;IAcpB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAQ3B;IAEH,OAAO,CAAC,cAAc;IAItB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAkDvB;IAEF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAUrB;IAEF,OAAO,IAAI,IAAI;CAchB"}
1
+ {"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AACA,OAAO,EAAa,KAAK,UAAU,EAAiB,MAAM,2BAA2B,CAAC;AACtF,OAAO,KAAK,EAA0B,OAAO,EAAgB,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACjI,OAAO,EAGL,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,WAAW,EAChB,KAAK,aAAa,EAElB,KAAK,UAAU,EAChB,MAAM,gCAAgC,CAAC;AAExC,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AASvD,qBAAa,QAAQ,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CACxE,YAAW,IAAI,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,CAAC;IAoB7C,OAAO,CAAC,QAAQ,CAAC,IAAI;IAlBvB,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8D;IACpF,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAW;IAClC,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAS;IACvC,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAsB;IACvD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAA4D;IACtF,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAoC;IACtE,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAiC;IACvD,OAAO,CAAC,KAAK,CAAM;IACnB,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAA4C;IAC7E,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAwB;IACrD,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IACjD,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAoD;IACnF,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAsB;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;gBAGrB,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,CAAC,EACvF,OAAO,EAAE,WAAW,CAAC,MAAM,CAAC;IAiF9B,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,IAAI;IASZ,SAAS,CAAC,QAAQ,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAC,KAAK,IAAI,GAAG,MAAM,IAAI;IAQ/E,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAW/C,GAAG,IAAI,MAAM;IAMb,QAAQ,CAAC,MAAM;;8BAES,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI;MACpD;IAEF,QAAQ,CAAC,KAAK;;8BAEU,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI;MACjD;IAEF,QAAQ,CAAC,UAAU;;8BAEK,CAAC,KAAK,EAAE,eAAe,KAAK,IAAI;MACtD;IAEF,QAAQ,CAAC,MAAM;;8BAES,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI;MAClD;IAEF,QAAQ,CAAC,QAAQ,EAAE,sBAAsB,CAAC;IAE1C,QAAQ,CAAC,QAAQ;;8BAEO,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI;MACpD;IAEF,OAAO,CAAC,YAAY;IAkBpB,OAAO,CAAC,QAAQ,CAAC,aAAa,CAM3B;IAEH,OAAO,CAAC,cAAc;IAItB,QAAQ,CAAC,OAAO,EAAE,OAAO,CA+CvB;IAEF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAUrB;IAEF,OAAO,IAAI,IAAI;CAchB"}
package/dist/mock.js CHANGED
@@ -8,8 +8,6 @@ const TICK_MS = 100;
8
8
  /** Long enough to see a spinner, short enough not to be annoying while building. */
9
9
  const FAKE_SIGN_MS = 150;
10
10
  const FAKE_PENDING_MS = 250;
11
- /** The gate's real hold window, so a countdown built against the mock is the one players see. */
12
- const MOCK_HOLD_MS = 5 * 60_000;
13
11
  export class MockRoom {
14
12
  game;
15
13
  round;
@@ -20,9 +18,6 @@ export class MockRoom {
20
18
  reactionListeners = new Set();
21
19
  timer;
22
20
  spent = 0n;
23
- held = 0n;
24
- /** Mirrors the gate's five-minute hold, so a game can build the countdown against the mock. */
25
- holdExpiresAt = null;
26
21
  buyProgress = null;
27
22
  disposed = false;
28
23
  connectionSignal = new Signal('connected');
@@ -163,24 +158,26 @@ export class MockRoom {
163
158
  };
164
159
  economyState() {
165
160
  const earned = BigInt(this.round.pointsFor(this.player)) * this.unitsPerPoint;
166
- const available = earned - this.spent - this.held;
161
+ // The gate's rule exactly: the smaller of what was earned and what the pool lets one wallet
162
+ // spend, less what the chain says was spent. Nothing is held while a buy is in flight. The
163
+ // constructor refuses a cap below a flawless round, so the clamp is fidelity rather than a
164
+ // live branch here — but a game built against the mock should see the same arithmetic.
165
+ const cap = this.termsSignal.current().walletCap;
166
+ const ceiling = earned < cap ? earned : cap;
167
+ const available = ceiling - this.spent;
167
168
  return {
168
169
  unitsPerPoint: this.unitsPerPoint,
169
170
  earned,
170
- held: this.held,
171
171
  spent: this.spent,
172
172
  available: available > 0n ? available : 0n,
173
- holdExpiresAt: this.held > 0n ? this.holdExpiresAt : null,
174
173
  buy: this.buyProgress,
175
174
  };
176
175
  }
177
176
  economySignal = new Signal({
178
177
  unitsPerPoint: 0n,
179
178
  earned: 0n,
180
- held: 0n,
181
179
  spent: 0n,
182
180
  available: 0n,
183
- holdExpiresAt: null,
184
181
  buy: null,
185
182
  });
186
183
  publishEconomy() {
@@ -205,14 +202,13 @@ export class MockRoom {
205
202
  if (this.buyProgress?.state === 'signing' || this.buyProgress?.state === 'pending') {
206
203
  return { bought: false, reason: 'try-again' };
207
204
  }
205
+ // As on the live gate: a buy in flight moves nothing. A player who backs out of the wallet
206
+ // dialog has spent nothing, so `available` is exactly what it was.
208
207
  const spend = maxSpendWei < available ? maxSpendWei : available;
209
- this.held += spend;
210
- this.holdExpiresAt = Date.now() + MOCK_HOLD_MS;
211
208
  this.buyProgress = { state: 'signing', spend: spend };
212
209
  this.publishEconomy();
213
210
  await new Promise((resolve) => setTimeout(resolve, FAKE_SIGN_MS));
214
211
  if (this.disposed) {
215
- this.held -= spend;
216
212
  this.buyProgress = { state: 'failed', reason: 'try-again' };
217
213
  this.publishEconomy();
218
214
  return { bought: false, reason: 'try-again' };
@@ -221,12 +217,10 @@ export class MockRoom {
221
217
  this.publishEconomy();
222
218
  await new Promise((resolve) => setTimeout(resolve, FAKE_PENDING_MS));
223
219
  if (this.disposed) {
224
- this.held -= spend;
225
220
  this.buyProgress = { state: 'failed', reason: 'try-again' };
226
221
  this.publishEconomy();
227
222
  return { bought: false, reason: 'try-again' };
228
223
  }
229
- this.held -= spend;
230
224
  this.spent += spend;
231
225
  this.buyProgress = { state: 'confirmed', spent: spend };
232
226
  this.emit();
package/dist/mock.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAC;AACxD,OAAO,EAAE,SAAS,EAAkC,MAAM,2BAA2B,CAAC;AAEtF,OAAO,EACL,eAAe,EACf,YAAY,GAOb,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAEvD,mEAAmE;AACnE,MAAM,OAAO,GAAG,GAAG,CAAC;AAEpB,oFAAoF;AACpF,MAAM,YAAY,GAAG,GAAG,CAAC;AACzB,MAAM,eAAe,GAAG,GAAG,CAAC;AAC5B,iGAAiG;AACjG,MAAM,YAAY,GAAG,CAAC,GAAG,MAAM,CAAC;AAEhC,MAAM,OAAO,QAAQ;IAwBA;IArBF,KAAK,CAA8D;IACnE,MAAM,CAAW;IACjB,aAAa,CAAS;IACtB,gBAAgB,CAAsB;IACtC,SAAS,GAAG,IAAI,GAAG,EAAiD,CAAC;IACrE,iBAAiB,GAAG,IAAI,GAAG,EAAyB,CAAC;IACrD,KAAK,CAAiC;IAC/C,KAAK,GAAG,EAAE,CAAC;IACX,IAAI,GAAG,EAAE,CAAC;IAClB,+FAA+F;IACvF,aAAa,GAAkB,IAAI,CAAC;IACpC,WAAW,GAAuB,IAAI,CAAC;IACvC,QAAQ,GAAG,KAAK,CAAC;IACR,gBAAgB,GAAG,IAAI,MAAM,CAAkB,WAAW,CAAC,CAAC;IAC5D,YAAY,CAAwB;IACpC,WAAW,CAAqB;IAChC,cAAc,GAAG,IAAI,MAAM,CAAgB,EAAE,cAAc,EAAE,CAAC,EAAE,CAAC,CAAC;IAClE,YAAY,CAAsB;IAClC,UAAU,CAAa;IAExC,YACmB,IAAsE,EACvF,OAA4B;QADX,SAAI,GAAJ,IAAI,CAAkE;QAGvF,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,KAAK,CAAC,CAAC;QACxD,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC;QACxC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,IAAI,eAAmB,CAAC;QAClE,IAAI,CAAC,gBAAgB,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QAC3D,IAAI,CAAC,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;YAC/D,MAAM,IAAI,UAAU,CAAC,0DAA0D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE;YAChE,OAAO;YACP,QAAQ,EAAE,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC;SACjD,CAAC,CAAC;QACH,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI;YAC/B,OAAO,EAAE,MAAM;YACf,MAAM,EAAE,MAAM;YACd,WAAW,EAAE,IAAI;YACjB,IAAI,EAAE,WAAW;YACjB,MAAM,EAAE,MAAM;YACd,QAAQ,EAAE,IAAI;YACd,OAAO;YACP,QAAQ,EAAE,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC;YAChD,YAAY,EAAE,OAAO,GAAG,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,CAAC;SACrD,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,IAAI,MAAM,CAAgB,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC,CAAC;QAE5E,+FAA+F;QAC/F,8FAA8F;QAC9F,8EAA8E;QAC9E,MAAM,kBAAkB,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC;QAChF,MAAM,gBAAgB,GAAG,MAAM,CAAC,kBAAkB,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC;QACzE,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,gBAAgB,CAAC;QACxD,IAAI,SAAS,GAAG,gBAAgB,EAAE,CAAC;YACjC,MAAM,IAAI,UAAU,CAAC,6EAA6E,CAAC,CAAC;QACtG,CAAC;QACD,yFAAyF;QACzF,+FAA+F;QAC/F,8DAA8D;QAC9D,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,GAAG,CAAC;QACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,eAAe,IAAI,CAAC,EAAE,CAAC;YAC9D,MAAM,IAAI,UAAU,CAAC,kDAAkD,CAAC,CAAC;QAC3E,CAAC;QACD,6FAA6F;QAC7F,2FAA2F;QAC3F,+EAA+E;QAC/E,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,eAAe,CAAC;QACzD,MAAM,QAAQ,GAAG,UAAU,CAAC,QAAQ,CAAC;QACrC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,QAAQ,CAAC,IAAI,QAAQ,GAAG,CAAC,IAAI,QAAQ,GAAG,EAAE,EAAE,CAAC;YACrE,MAAM,IAAI,UAAU,CAAC,yDAAyD,CAAC,CAAC;QAClF,CAAC;QACD,MAAM,KAAK,GAAG,GAAG,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,cAAc,GAAG,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC;QAClD,IAAI,cAAc,IAAI,EAAE,IAAI,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAC7E,MAAM,IAAI,UAAU,CAAC,0DAA0D,CAAC,CAAC;QACnF,CAAC;QACD,MAAM,gBAAgB,GAAG,MAAM,CAAC,cAAc,CAAC,GAAG,eAAe,CAAC;QAClE,MAAM,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,gBAAgB,GAAG,eAAe,CAAC,CAAC,CAAC;QACjF,IAAI,SAAS,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;YACrC,MAAM,IAAI,UAAU,CAAC,0DAA0D,CAAC,CAAC;QACnF,CAAC;QACD,IAAI,CAAC,WAAW,GAAG,IAAI,MAAM,CAC3B,MAAM,CAAC,MAAM,CAAC;YACZ,kBAAkB;YAClB,SAAS;YACT,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,eAAe;YACf,gBAAgB;YAChB,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,EAAE,GAAG,UAAU,EAAE,CAAC;SAC7C,CAAC,CACH,CAAC;QACF,IAAI,CAAC,YAAY,GAAG,IAAI,MAAM,CAC5B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAC7G,CAAC;QACF,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC7G,IAAI,CAAC,QAAQ,GAAG,IAAI,sBAAsB,CAAC,OAAO,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;QAEvE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QAChG,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,OAAO,CAAC,CAAC;IACvD,CAAC;IAEO,IAAI;QACV,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC;YAAE,IAAI,CAAC,IAAI,EAAE,CAAC;IACxD,CAAC;IAEO,IAAI;QACV,IAAI,CAAC,cAAc,EAAE,CAAC;QACtB,MAAM,QAAQ,GAAqC;YACjD,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE;YACnC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC;SAC/C,CAAC;QACF,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,SAAS;YAAE,QAAQ,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAED,SAAS,CAAC,QAA8D;QACtE,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,0FAA0F;QAC1F,sEAAsE;QACtE,QAAQ,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QAClG,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAc;QACvB,0FAA0F;QAC1F,yDAAyD;QACzD,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;QAE5E,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACxG,IAAI,CAAC,IAAI,EAAE,CAAC;QACZ,OAAO,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;IAC7F,CAAC;IAED,GAAG;QACD,8FAA8F;QAC9F,yBAAyB;QACzB,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC;IACpB,CAAC;IAEQ,MAAM,GAAG;QAChB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;QAC1C,SAAS,EAAE,CAAC,QAAwC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC;KAC/F,CAAC;IAEO,KAAK,GAAG;QACf,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE;QACzC,SAAS,EAAE,CAAC,QAAqC,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,SAAS,CAAC,QAAQ,CAAC;KAC3F,CAAC;IAEO,UAAU,GAAG;QACpB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE;QAC9C,SAAS,EAAE,CAAC,QAA0C,EAAE,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,SAAS,CAAC,QAAQ,CAAC;KACrG,CAAC;IAEO,MAAM,GAAG;QAChB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;QAC1C,SAAS,EAAE,CAAC,QAAsC,EAAE,EAAE,CAAC,IAAI,CAAC,YAAY,CAAC,SAAS,CAAC,QAAQ,CAAC;KAC7F,CAAC;IAEO,QAAQ,CAAyB;IAEjC,QAAQ,GAAG;QAClB,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE;QAC5C,SAAS,EAAE,CAAC,QAAwC,EAAE,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,QAAQ,CAAC;KACjG,CAAC;IAEM,YAAY;QAClB,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,aAAa,CAAC;QAC9E,MAAM,SAAS,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC;QAClD,OAAO;YACL,aAAa,EAAE,IAAI,CAAC,aAAa;YACjC,MAAM;YACN,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,SAAS,EAAE,SAAS,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;YAC1C,aAAa,EAAE,IAAI,CAAC,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI;YACzD,GAAG,EAAE,IAAI,CAAC,WAAW;SACtB,CAAC;IACJ,CAAC;IAEgB,aAAa,GAAG,IAAI,MAAM,CAAe;QACxD,aAAa,EAAE,EAAE;QACjB,MAAM,EAAE,EAAE;QACV,IAAI,EAAE,EAAE;QACR,KAAK,EAAE,EAAE;QACT,SAAS,EAAE,EAAE;QACb,aAAa,EAAE,IAAI;QACnB,GAAG,EAAE,IAAI;KACV,CAAC,CAAC;IAEK,cAAc;QACpB,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,CAAC;IAC9C,CAAC;IAEQ,OAAO,GAAY;QAC1B,OAAO,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE;QAClC,SAAS,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,IAAI,CAAC,aAAa,CAAC,SAAS,CAAC,QAAQ,CAAC;QAC/D,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC,SAAS;QAC9C,GAAG,EAAE,KAAK,EAAE,WAAmB,EAAsB,EAAE;YACrD,IAAI,WAAW,IAAI,EAAE,EAAE,CAAC;gBACtB,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;gBACnE,IAAI,CAAC,cAAc,EAAE,CAAC;gBACtB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;YACvD,CAAC;YACD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;YAC3C,IAAI,SAAS,IAAI,EAAE,EAAE,CAAC;gBACpB,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;gBACnE,IAAI,CAAC,cAAc,EAAE,CAAC;gBACtB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,kBAAkB,EAAE,CAAC;YACvD,CAAC;YACD,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK,SAAS,IAAI,IAAI,CAAC,WAAW,EAAE,KAAK,KAAK,SAAS,EAAE,CAAC;gBACnF,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YAChD,CAAC;YAED,MAAM,KAAK,GAAG,WAAW,GAAG,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAC;YAChE,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;YACnB,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC;YAC/C,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YACtD,IAAI,CAAC,cAAc,EAAE,CAAC;YAEtB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,YAAY,CAAC,CAAC,CAAC;YAClE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;gBACnB,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;gBAC5D,IAAI,CAAC,cAAc,EAAE,CAAC;gBACtB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YAChD,CAAC;YACD,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YACtD,IAAI,CAAC,cAAc,EAAE,CAAC;YAEtB,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,eAAe,CAAC,CAAC,CAAC;YACrE,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;gBAClB,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;gBACnB,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;gBAC5D,IAAI,CAAC,cAAc,EAAE,CAAC;gBACtB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,WAAW,EAAE,CAAC;YAChD,CAAC;YAED,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC;YACnB,IAAI,CAAC,KAAK,IAAI,KAAK,CAAC;YACpB,IAAI,CAAC,WAAW,GAAG,EAAE,KAAK,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;YACxD,IAAI,CAAC,IAAI,EAAE,CAAC;YACZ,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;QACxC,CAAC;KACF,CAAC;IAEO,MAAM,GAAW;QACxB,8FAA8F;QAC9F,KAAK,EAAE,CAAC,EAAU,EAAE,EAAE;YACpB,IAAI,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC;gBAAE,OAAO;YAChE,KAAK,MAAM,QAAQ,IAAI,IAAI,CAAC,iBAAiB;gBAAE,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC;QACvF,CAAC;QACD,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE;YACvB,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;YACrC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACvD,CAAC;KACF,CAAC;IAEF,OAAO;QACL,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QACrB,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC;QACvB,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC;QAC9B,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,CAAC;QAC5B,IAAI,CAAC,UAAU,EAAE,CAAC;QAClB,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC;QAC1B,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;CACF"}
1
+ {"version":3,"file":"mock.js","sourceRoot":"","sources":["../src/mock.ts"],"names":[],"mappings":"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"}
package/dist/version.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // Generated by scripts/write-version.mjs from package.json at build time. Do not edit.
2
2
  /** The published version of @flayerlabs/gamemode-client, as a literal so it survives any bundler. */
3
- export const CLIENT_VERSION = "0.5.6";
3
+ export const CLIENT_VERSION = "0.7.0";
4
4
  /** `@flayerlabs/gamemode-client@<version>`: the text a build of this package can be searched for. */
5
- export const CLIENT_MARKER = "@flayerlabs/gamemode-client@0.5.6";
5
+ export const CLIENT_MARKER = "@flayerlabs/gamemode-client@0.7.0";
6
6
  //# sourceMappingURL=version.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flayerlabs/gamemode-client",
3
- "version": "0.5.6",
3
+ "version": "0.7.0",
4
4
  "description": "Browser and mock-room client for Flaunch Game Modes",
5
5
  "license": "MIT",
6
6
  "author": "Flayer Labs",
@@ -33,7 +33,7 @@
33
33
  "ws": "^8.21.3"
34
34
  },
35
35
  "dependencies": {
36
- "@flayerlabs/gamemode-spec": "^0.5.6"
36
+ "@flayerlabs/gamemode-spec": "^0.7.0"
37
37
  },
38
38
  "types": "./dist/index.d.ts",
39
39
  "exports": {
@@ -0,0 +1,73 @@
1
+ /**
2
+ * What a gate says about itself at `GET /config`, as a page that builds launches reads it.
3
+ *
4
+ * This mirrors `ServedGateAnnouncement` in `@flayerlabs/gamemode-gate` without depending on that
5
+ * package: the client runs in the browser, the gate on a server, and the wire shape between them
6
+ * is what this type names. Fields a gate may not send are optional here, so a page can read the
7
+ * `/config` of a gate older than its own client.
8
+ */
9
+ export interface GateConfig {
10
+ chainId: number;
11
+ contracts: {
12
+ /** The gate's PRIMARY manager — the one it announces and proves readiness on. */
13
+ positionManager: `0x${string}`;
14
+ spendGatedCalculator: `0x${string}`;
15
+ poolSwap?: `0x${string}`;
16
+ };
17
+ signer: `0x${string}`;
18
+ settler: `0x${string}`;
19
+ walletCap: string;
20
+ roundDurationMs: number;
21
+ minLobbyLeadMs: number;
22
+ gateEndsAtGraceS: number;
23
+ /** The primary manager's generation. */
24
+ flaunchVariant: 'v1_2' | 'multichain' | 'v1_3' | 'any_v1_3';
25
+ /**
26
+ * How the gate decides which PositionManagers it adopts coins from. `'wired-to-calculator'`
27
+ * means any manager whose fee wiring routes to `contracts.spendGatedCalculator`, so a launch may
28
+ * target a manager other than `contracts.positionManager`. Absent from gates below 0.6.0, which
29
+ * adopt coins on the primary manager only.
30
+ */
31
+ positionManagerPolicy?: 'wired-to-calculator';
32
+ spendTokens?: { address: `0x${string}`; symbol: string; decimals: number; usdPerToken: number; walletCap: string }[];
33
+ pairedTokenRegistry?: `0x${string}`;
34
+ requiresEoa: boolean;
35
+ accepting: boolean;
36
+ publicLaunchesOpen: boolean;
37
+ privateLaunches: boolean;
38
+ /** The `@flayerlabs/gamemode-gate` version serving the route. Absent below 0.5.5. */
39
+ gateVersion?: string;
40
+ }
41
+
42
+ /** The first gate release that adopts a coin on any manager wired to its calculator. */
43
+ const ANY_WIRED_POSITION_MANAGER_SINCE = [0, 6, 0] as const;
44
+
45
+ /**
46
+ * Will this gate adopt a coin launched on a PositionManager other than its primary one?
47
+ *
48
+ * True when the gate announces the policy, or — for a build that predates the field but not the
49
+ * behaviour — when its `gateVersion` is 0.6.0 or later. A page that wants to launch on a manager
50
+ * other than `contracts.positionManager` (a vested launch on the AnyPositionManager, say) must ask
51
+ * this first: an older gate refuses such a coin at adoption, after the creator has paid for it.
52
+ * The gate also requires the chosen manager to be wired to `contracts.spendGatedCalculator` on
53
+ * chain; this answers only whether the gate will look.
54
+ */
55
+ export function acceptsAnyWiredPositionManager(
56
+ config: Pick<GateConfig, 'positionManagerPolicy' | 'gateVersion'>,
57
+ ): boolean {
58
+ if (config.positionManagerPolicy === 'wired-to-calculator') return true;
59
+ const version = parseVersion(config.gateVersion);
60
+ if (!version) return false;
61
+ const [major, minor, patch] = version;
62
+ const [sinceMajor, sinceMinor, sincePatch] = ANY_WIRED_POSITION_MANAGER_SINCE;
63
+ if (major !== sinceMajor) return major > sinceMajor;
64
+ if (minor !== sinceMinor) return minor > sinceMinor;
65
+ return patch >= sincePatch;
66
+ }
67
+
68
+ function parseVersion(input: string | undefined): [number, number, number] | null {
69
+ if (typeof input !== 'string') return null;
70
+ const match = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/.exec(input.trim());
71
+ if (!match) return null;
72
+ return [Number(match[1]), Number(match[2]), Number(match[3])];
73
+ }
package/src/host.ts CHANGED
@@ -137,7 +137,16 @@ export function attachGameHost(options: AttachGameHostOptions): () => void {
137
137
  // This listener shares the page's window with every other frame the page hosts.
138
138
  if (detached || origin !== gameOrigin || source !== frame.contentWindow) return;
139
139
  const parsed = gameFrameFrom(data);
140
- if (!parsed) return;
140
+ if (!parsed) {
141
+ // A game built on the 0.5.x SDK says hello on frame protocol 1. It gets no context — its buy
142
+ // would carry a per-claim authorisation this page cannot execute — but the page is told which
143
+ // SDK it runs, so it can say "rebuild this game" rather than leave the frame blank.
144
+ if (!sdkReported && isLegacyHello(data)) {
145
+ sdkReported = true;
146
+ options.onGameSdkVersion?.(sdkOf(data));
147
+ }
148
+ return;
149
+ }
141
150
 
142
151
  if (parsed.type === 'gm:hello') {
143
152
  if (!sdkReported) {
@@ -166,14 +175,6 @@ export function attachGameHost(options: AttachGameHostOptions): () => void {
166
175
  send({ v: FRAME_PROTOCOL_VERSION, type: 'gm:res', id, ok: true, result: { method: 'signIn', signature } });
167
176
  return;
168
177
  }
169
- // The wire allows hookData to be absent (older frames), but a buy cannot be executed
170
- // without its opaque proof — refuse here, at the execution boundary, in the protocol's
171
- // own vocabulary rather than letting a type hole reach the wallet call.
172
- const { hookData } = call.authorisation;
173
- if (hookData === undefined) {
174
- send({ v: FRAME_PROTOCOL_VERSION, type: 'gm:res', id, ok: false, error: { code: 'failed', message: 'that authorisation carries no hookData' } });
175
- return;
176
- }
177
178
  const outcome = await runBuy(async (authorisation, progress, signal) => {
178
179
  try {
179
180
  return await host.buy(authorisation, progress, signal);
@@ -183,7 +184,7 @@ export function attachGameHost(options: AttachGameHostOptions): () => void {
183
184
  }
184
185
  throw error;
185
186
  }
186
- }, { ...call.authorisation, hookData }, (progress) => {
187
+ }, call.authorisation, (progress) => {
187
188
  send({
188
189
  v: FRAME_PROTOCOL_VERSION,
189
190
  type: 'gm:progress',
@@ -240,3 +241,14 @@ export function attachGameHost(options: AttachGameHostOptions): () => void {
240
241
  unlisten();
241
242
  };
242
243
  }
244
+
245
+ function isLegacyHello(data: unknown): data is { v: 1; type: 'gm:hello'; sdk?: unknown } {
246
+ return typeof data === 'object' && data !== null
247
+ && (data as { v?: unknown }).v === 1 && (data as { type?: unknown }).type === 'gm:hello';
248
+ }
249
+
250
+ function sdkOf(hello: { sdk?: unknown }): string | null {
251
+ return typeof hello.sdk === 'string' && /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?(?:\+[0-9A-Za-z.-]+)?$/.test(hello.sdk)
252
+ ? hello.sdk
253
+ : null;
254
+ }
package/src/index.ts CHANGED
@@ -37,6 +37,8 @@ export type { MarketFixture, ReplayMarket } from './replay-market.js';
37
37
  export type { Authorisation, Host, HostBuyProgress, LiveOptions } from './live.js';
38
38
  export { connectHost } from './embed.js';
39
39
  export { CLIENT_MARKER, CLIENT_VERSION } from './version.js';
40
+ export { acceptsAnyWiredPositionManager } from './gate-config.js';
41
+ export type { GateConfig } from './gate-config.js';
40
42
  export type { ConnectHostOptions, EmbeddedHost, FrameEndpoint } from './embed.js';
41
43
  export { attachGameHost, HostRefusal } from './host.js';
42
44
  export type { AttachGameHostOptions, HostListenSource, PostTarget } from './host.js';
@@ -114,13 +116,19 @@ export interface Snapshot<PublicView, PlayerView> {
114
116
  export type SendResult = { accepted: true } | { accepted: false; refuse: string };
115
117
 
116
118
  export interface Economy extends Readable<EconomyState> {
117
- /** What this player could spend right now, in wei. */
119
+ /**
120
+ * What this player could spend right now, in base units of the round's spend token.
121
+ *
122
+ * The smaller of what they earned and the pool's wallet cap, less what the chain says they have
123
+ * spent. A buy that is declined or fails leaves it exactly where it was.
124
+ */
118
125
  available(): bigint;
119
126
  /**
120
127
  * Spend up to `maxSpendWei` on the coin.
121
128
  *
122
129
  * The game does not build this transaction and cannot: the page it is embedded in constructs it
123
- * from the server's authorisation and asks the player to approve it.
130
+ * from the server's authorisation and asks the player to approve it. The page spends exactly
131
+ * the amount the gate clamps this to, never more.
124
132
  */
125
133
  buy(maxSpendWei: bigint): Promise<BuyResult>;
126
134
  }
@@ -201,7 +209,10 @@ export interface MockOptions<Config> {
201
209
  player?: PlayerId;
202
210
  /** Points-to-wei, only so the buy button has something to show. */
203
211
  unitsPerPoint?: bigint;
204
- /** The launch's per-wallet ceiling. Defaults to exactly what a flawless round would earn. */
212
+ /**
213
+ * The launch's per-wallet ceiling. Defaults to exactly what a flawless round would earn. Also
214
+ * the ceiling the mock's `available` is clamped to, as the gate's is.
215
+ */
205
216
  walletCap?: bigint;
206
217
  /** The creator's one economic knob. The mock derives a matching token price from `unitsPerPoint`. */
207
218
  pointsPerDollar?: number;
package/src/live.ts CHANGED
@@ -13,7 +13,7 @@ import type {
13
13
  Social,
14
14
  } from './index.js';
15
15
  import type { PlayerId } from '@flayerlabs/gamemode-spec';
16
- import type { SpendAuthorisation } from '@flayerlabs/gamemode-spec/embed';
16
+ import { isSpendAuthorisation, type SpendAuthorisation } from '@flayerlabs/gamemode-spec/embed';
17
17
  import {
18
18
  LIVE_PROTOCOL_VERSION,
19
19
  isPlayerJoinTicket,
@@ -61,7 +61,13 @@ export interface Host {
61
61
  signIn(message: string, signal?: AbortSignal): Promise<`0x${string}`>;
62
62
  /** Fresh, single-use admission evidence. Honour abort when the trusted embed closes. */
63
63
  sessionEvidence?(signal?: AbortSignal): Promise<unknown>;
64
- /** Spend an authorisation the gate issued. The page builds and submits the transaction. */
64
+ /**
65
+ * Spend an authorisation the gate issued. The page builds and submits the transaction.
66
+ *
67
+ * Spend exactly `authorisation.spend`, never more. The signature carries a cumulative ceiling
68
+ * the calculator enforces against its own accumulator, so the page keeps no replay state: a
69
+ * resubmitted signature cannot spend past what the player earned.
70
+ */
65
71
  buy(
66
72
  authorisation: Authorisation,
67
73
  progress?: (event: HostBuyProgress) => void,
@@ -72,7 +78,7 @@ export interface Host {
72
78
  /** The host reports only what it uniquely knows; LiveRoom owns the terminal result. */
73
79
  export type HostBuyProgress = { state: 'pending'; transactionHash?: string };
74
80
 
75
- /** Exactly what the gate signed. Everything is a string because bigints do not survive JSON. */
81
+ /** What the gate signed plus the unsigned `spend`. All strings because bigints do not survive JSON. */
76
82
  export type Authorisation = SpendAuthorisation;
77
83
 
78
84
  export interface LiveOptions {
@@ -137,8 +143,9 @@ class LiveRoom<PublicView, PlayerView, Action> implements Room<PublicView, Playe
137
143
  private skew = 0;
138
144
  private closed = false;
139
145
  private claimSequence = 0;
140
- private balanceRevision = 0;
141
146
  private activeBuy: symbol | null = null;
147
+ /** The last live protocol version a frame carried that this client does not speak. */
148
+ private foreignProtocol: unknown = undefined;
142
149
  private readonly initialSnapshot: Promise<void>;
143
150
  private resolveInitialSnapshot!: () => void;
144
151
  private rejectInitialSnapshot!: (error: Error) => void;
@@ -198,7 +205,9 @@ class LiveRoom<PublicView, PlayerView, Action> implements Room<PublicView, Playe
198
205
  this.initialSnapshot,
199
206
  new Promise<never>((_, reject) => {
200
207
  timeout = setTimeout(
201
- () => reject(new Error('the room did not send its first snapshot in time')),
208
+ () => reject(new Error(this.foreignProtocol === undefined
209
+ ? 'the room did not send its first snapshot in time'
210
+ : `the gate speaks live protocol v${String(this.foreignProtocol)}; this client speaks v${LIVE_PROTOCOL_VERSION}`)),
202
211
  FIRST_SNAPSHOT_TIMEOUT_MS,
203
212
  );
204
213
  }),
@@ -267,6 +276,13 @@ class LiveRoom<PublicView, PlayerView, Action> implements Room<PublicView, Playe
267
276
  return;
268
277
  }
269
278
 
279
+ // Another version is another wire. Guessing at it would mean rendering a balance whose fields
280
+ // mean something else, so every frame is dropped and the join names the mismatch instead.
281
+ if (frame.v !== LIVE_PROTOCOL_VERSION) {
282
+ this.foreignProtocol = frame.v;
283
+ return;
284
+ }
285
+
270
286
  if (frame.type === 'reaction') {
271
287
  const reaction = reactionFrom(frame.reaction);
272
288
  if (reaction) for (const listener of this.reactionListeners) listener(reaction);
@@ -403,12 +419,11 @@ class LiveRoom<PublicView, PlayerView, Action> implements Room<PublicView, Playe
403
419
 
404
420
  private async performBuy(maxSpendWei: bigint, attempt: symbol): Promise<BuyResult> {
405
421
  if (maxSpendWei <= 0n) return this.failBuy(attempt, 'nothing-to-spend');
406
- const balanceRevision = this.balanceRevision;
407
422
  const requestId = this.nextRequestId();
408
423
  let authorisation: Authorisation;
409
424
  try {
410
425
  authorisation = await this.postClaim<Authorisation>(`/rounds/${this.options.roundId}/claim`, {
411
- maxSpendWei: maxSpendWei.toString(),
426
+ spend: maxSpendWei.toString(),
412
427
  requestId,
413
428
  });
414
429
  } catch (error) {
@@ -418,25 +433,17 @@ class LiveRoom<PublicView, PlayerView, Action> implements Room<PublicView, Playe
418
433
  return this.failBuy(attempt, 'try-again');
419
434
  }
420
435
 
421
- let spend: bigint;
422
- try {
423
- spend = BigInt(authorisation.maxSpendWei);
424
- } catch {
425
- return this.failBuy(attempt, 'try-again');
426
- }
436
+ // The page will pass this straight to the wallet, so it is checked here in the protocol's own
437
+ // terms first. A gate on another version answers with fields this client does not know.
438
+ if (!isSpendAuthorisation(authorisation)) return this.failBuy(attempt, 'try-again', { detail: 'claim-malformed' });
439
+ const spend = BigInt(authorisation.spend);
440
+ if (spend > maxSpendWei) return this.failBuy(attempt, 'try-again', { detail: 'claim-overspend' });
427
441
  if (this.activeBuy !== attempt) return { bought: false, reason: 'try-again' };
428
442
 
429
- const before = this.economySignal.current();
430
- this.economySignal.set({
431
- ...before,
432
- ...(this.balanceRevision === balanceRevision
433
- ? {
434
- held: before.held + spend,
435
- available: before.available > spend ? before.available - spend : 0n,
436
- }
437
- : {}),
438
- buy: { state: 'signing', spend },
439
- });
443
+ // Nothing moves yet. The authorisation is a ceiling, not a reservation: until the chain shows a
444
+ // purchase, the player still has everything they had, and a declined dialog leaves it so.
445
+ const spentBefore = this.economySignal.current().spent;
446
+ this.economySignal.set({ ...this.economySignal.current(), buy: { state: 'signing', spend } });
440
447
 
441
448
  let transactionHash: string | undefined;
442
449
  let hostSettled = false;
@@ -475,8 +482,15 @@ class LiveRoom<PublicView, PlayerView, Action> implements Room<PublicView, Playe
475
482
  const confirmed: BuyProgress = transactionHash === undefined
476
483
  ? { state: 'confirmed', spent: result.spent }
477
484
  : { state: 'confirmed', spent: result.spent, transactionHash };
478
- // The signed allowance remains held until the gate observes chain settlement or it expires.
479
- this.economySignal.set({ ...current, buy: confirmed });
485
+ // Optimistic in the safe direction only. The gate learns of this purchase a reconciliation
486
+ // pass and two confirmations later; until then its snapshot still offers the money just spent,
487
+ // and a second buy against it would be a swap the calculator reverts. So the confirmed spend
488
+ // is applied locally now and the next snapshot replaces it — unless the gate has already
489
+ // moved `spent` since this buy began, in which case its figure is the newer one and stays.
490
+ const optimistic = current.spent === spentBefore
491
+ ? { spent: current.spent + result.spent, available: current.available > result.spent ? current.available - result.spent : 0n }
492
+ : {};
493
+ this.economySignal.set({ ...current, ...optimistic, buy: confirmed });
480
494
  return { bought: true, spent: result.spent };
481
495
  }
482
496
 
@@ -509,7 +523,6 @@ class LiveRoom<PublicView, PlayerView, Action> implements Room<PublicView, Playe
509
523
  }
510
524
 
511
525
  private setBalance(balance: Omit<EconomyState, 'buy'>): void {
512
- this.balanceRevision += 1;
513
526
  this.economySignal.set({ ...balance, buy: this.economySignal.current().buy });
514
527
  }
515
528
 
@@ -574,15 +587,7 @@ class LiveRoom<PublicView, PlayerView, Action> implements Room<PublicView, Playe
574
587
  }
575
588
 
576
589
  function emptyEconomy(): EconomyState {
577
- return {
578
- unitsPerPoint: 0n,
579
- earned: 0n,
580
- held: 0n,
581
- spent: 0n,
582
- available: 0n,
583
- holdExpiresAt: null,
584
- buy: null,
585
- };
590
+ return { unitsPerPoint: 0n, earned: 0n, spent: 0n, available: 0n, buy: null };
586
591
  }
587
592
 
588
593
  function economyFrom(input: unknown): Omit<EconomyState, 'buy'> | null {
@@ -592,20 +597,11 @@ function economyFrom(input: unknown): Omit<EconomyState, 'buy'> | null {
592
597
  const amounts = {
593
598
  unitsPerPoint: BigInt(value.unitsPerPoint ?? '0'),
594
599
  earned: BigInt(value.earned ?? '-1'),
595
- held: BigInt(value.held ?? '-1'),
596
600
  spent: BigInt(value.spent ?? '-1'),
597
601
  available: BigInt(value.available ?? '-1'),
598
602
  };
599
603
  if (amounts.unitsPerPoint <= 0n || Object.values(amounts).some((amount) => amount < 0n)) return null;
600
-
601
- // A deadline is either a whole millisecond timestamp or absent. Anything else — a string, a
602
- // fraction, Infinity — is a malformed frame, and a countdown drawn from one would run to a
603
- // moment that never arrives.
604
- const holdExpiresAt = value.holdExpiresAt;
605
- if (holdExpiresAt !== null && holdExpiresAt !== undefined && !Number.isSafeInteger(holdExpiresAt)) {
606
- return null;
607
- }
608
- return { ...amounts, holdExpiresAt: holdExpiresAt ?? null };
604
+ return amounts;
609
605
  } catch {
610
606
  return null;
611
607
  }
package/src/mock.ts CHANGED
@@ -20,8 +20,6 @@ const TICK_MS = 100;
20
20
  /** Long enough to see a spinner, short enough not to be annoying while building. */
21
21
  const FAKE_SIGN_MS = 150;
22
22
  const FAKE_PENDING_MS = 250;
23
- /** The gate's real hold window, so a countdown built against the mock is the one players see. */
24
- const MOCK_HOLD_MS = 5 * 60_000;
25
23
 
26
24
  export class MockRoom<Config, State, Event, Action, PublicView, PlayerView>
27
25
  implements Room<PublicView, PlayerView, Action>
@@ -34,9 +32,6 @@ export class MockRoom<Config, State, Event, Action, PublicView, PlayerView>
34
32
  private readonly reactionListeners = new Set<(r: Reaction) => void>();
35
33
  private readonly timer: ReturnType<typeof setInterval>;
36
34
  private spent = 0n;
37
- private held = 0n;
38
- /** Mirrors the gate's five-minute hold, so a game can build the countdown against the mock. */
39
- private holdExpiresAt: number | null = null;
40
35
  private buyProgress: BuyProgress | null = null;
41
36
  private disposed = false;
42
37
  private readonly connectionSignal = new Signal<ConnectionState>('connected');
@@ -196,14 +191,18 @@ export class MockRoom<Config, State, Event, Action, PublicView, PlayerView>
196
191
 
197
192
  private economyState(): EconomyState {
198
193
  const earned = BigInt(this.round.pointsFor(this.player)) * this.unitsPerPoint;
199
- const available = earned - this.spent - this.held;
194
+ // The gate's rule exactly: the smaller of what was earned and what the pool lets one wallet
195
+ // spend, less what the chain says was spent. Nothing is held while a buy is in flight. The
196
+ // constructor refuses a cap below a flawless round, so the clamp is fidelity rather than a
197
+ // live branch here — but a game built against the mock should see the same arithmetic.
198
+ const cap = this.termsSignal.current().walletCap;
199
+ const ceiling = earned < cap ? earned : cap;
200
+ const available = ceiling - this.spent;
200
201
  return {
201
202
  unitsPerPoint: this.unitsPerPoint,
202
203
  earned,
203
- held: this.held,
204
204
  spent: this.spent,
205
205
  available: available > 0n ? available : 0n,
206
- holdExpiresAt: this.held > 0n ? this.holdExpiresAt : null,
207
206
  buy: this.buyProgress,
208
207
  };
209
208
  }
@@ -211,10 +210,8 @@ export class MockRoom<Config, State, Event, Action, PublicView, PlayerView>
211
210
  private readonly economySignal = new Signal<EconomyState>({
212
211
  unitsPerPoint: 0n,
213
212
  earned: 0n,
214
- held: 0n,
215
213
  spent: 0n,
216
214
  available: 0n,
217
- holdExpiresAt: null,
218
215
  buy: null,
219
216
  });
220
217
 
@@ -242,15 +239,14 @@ export class MockRoom<Config, State, Event, Action, PublicView, PlayerView>
242
239
  return { bought: false, reason: 'try-again' };
243
240
  }
244
241
 
242
+ // As on the live gate: a buy in flight moves nothing. A player who backs out of the wallet
243
+ // dialog has spent nothing, so `available` is exactly what it was.
245
244
  const spend = maxSpendWei < available ? maxSpendWei : available;
246
- this.held += spend;
247
- this.holdExpiresAt = Date.now() + MOCK_HOLD_MS;
248
245
  this.buyProgress = { state: 'signing', spend: spend };
249
246
  this.publishEconomy();
250
247
 
251
248
  await new Promise((resolve) => setTimeout(resolve, FAKE_SIGN_MS));
252
249
  if (this.disposed) {
253
- this.held -= spend;
254
250
  this.buyProgress = { state: 'failed', reason: 'try-again' };
255
251
  this.publishEconomy();
256
252
  return { bought: false, reason: 'try-again' };
@@ -260,13 +256,11 @@ export class MockRoom<Config, State, Event, Action, PublicView, PlayerView>
260
256
 
261
257
  await new Promise((resolve) => setTimeout(resolve, FAKE_PENDING_MS));
262
258
  if (this.disposed) {
263
- this.held -= spend;
264
259
  this.buyProgress = { state: 'failed', reason: 'try-again' };
265
260
  this.publishEconomy();
266
261
  return { bought: false, reason: 'try-again' };
267
262
  }
268
263
 
269
- this.held -= spend;
270
264
  this.spent += spend;
271
265
  this.buyProgress = { state: 'confirmed', spent: spend };
272
266
  this.emit();
package/src/version.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  // Generated by scripts/write-version.mjs from package.json at build time. Do not edit.
2
2
  /** The published version of @flayerlabs/gamemode-client, as a literal so it survives any bundler. */
3
- export const CLIENT_VERSION: string = "0.5.6";
3
+ export const CLIENT_VERSION: string = "0.7.0";
4
4
  /** `@flayerlabs/gamemode-client@<version>`: the text a build of this package can be searched for. */
5
- export const CLIENT_MARKER: string = "@flayerlabs/gamemode-client@0.5.6";
5
+ export const CLIENT_MARKER: string = "@flayerlabs/gamemode-client@0.7.0";