@flayerlabs/gamemode-spec 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,9 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Flayer Labs
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
6
+
7
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
8
+
9
+ THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,78 @@
1
+ # @flayerlabs/gamemode-spec
2
+
3
+ Define deterministic game rules and share the contracts used by Game Mode servers and browsers.
4
+
5
+ ## Requirements
6
+
7
+ Install the package with Node.js 20 or later:
8
+
9
+ ```bash
10
+ pnpm add @flayerlabs/gamemode-spec
11
+ ```
12
+
13
+ ## Choose an entry point
14
+
15
+ The package exports these public entry points:
16
+
17
+ | Entry point | Use it to |
18
+ |---|---|
19
+ | `@flayerlabs/gamemode-spec` | define a game module, commands, decisions, awards and views |
20
+ | `@flayerlabs/gamemode-spec/round` | run or resume a game round with the shared round driver |
21
+ | `@flayerlabs/gamemode-spec/schedule` | turn phase durations into fixed timestamps inside a round window |
22
+ | `@flayerlabs/gamemode-spec/live` | share launch, economy, market, identity and live-room message types |
23
+ | `@flayerlabs/gamemode-spec/embed` | parse registry and iframe data, then build canonical spend typed data |
24
+
25
+ Import only the entry points you need:
26
+
27
+ ```ts
28
+ import { defineGame } from '@flayerlabs/gamemode-spec'
29
+ import { Round } from '@flayerlabs/gamemode-spec/round'
30
+ import { scheduleWithin } from '@flayerlabs/gamemode-spec/schedule'
31
+ ```
32
+
33
+ ## Validate trusted-platform responses
34
+
35
+ The trusted parent should parse HTTP data before it chooses a gate, deploy or room:
36
+
37
+ ```ts
38
+ import { parseGameRegistration } from '@flayerlabs/gamemode-spec/embed'
39
+ import { isLaunchContext } from '@flayerlabs/gamemode-spec/live'
40
+
41
+ const registration = parseGameRegistration(await registryResponse.json())
42
+ if (!registration) throw new Error('invalid game registration')
43
+
44
+ const launch: unknown = await adoptionResponse.json()
45
+ if (!isLaunchContext(launch)) throw new Error('invalid launch context')
46
+ ```
47
+
48
+ Compare the parsed chain, coin and round with the trusted page selection as well. A valid shape does
49
+ not prove that the response belongs to the coin the player opened.
50
+
51
+ ## Define game rules
52
+
53
+ A `GameModule` owns action parsing, initial state, decisions, state changes, public views,
54
+ player-specific views, wake times and reward limits.
55
+
56
+ Your rules must:
57
+
58
+ - return the same output for the same state and command
59
+ - read time from `command.at`
60
+ - derive any random values from the supplied seed
61
+ - award points only from `decide`
62
+ - keep secrets out of the `publicView` return type
63
+ - reject malformed and oversized actions in `parseAction`
64
+ - declare the maximum points one player can earn in `rewardBounds`
65
+
66
+ Use `Round` in tests and offline tools. The production gate uses the same driver, so ordering and
67
+ wake behaviour remain the same.
68
+
69
+ ## Follow the authoring contract
70
+
71
+ Read the [game-building guide](https://github.com/flayerlabs/gamemode-sdk/blob/main/docs/guides/build-a-game.md)
72
+ before writing a rules module.
73
+
74
+ Use the reference implementations for different game shapes:
75
+
76
+ - [quiz rules with delayed awards](https://github.com/flayerlabs/gamemode-sdk/blob/main/examples/quiz/src/rules.ts)
77
+ - [arrow rules with immediate scoring](https://github.com/flayerlabs/gamemode-sdk/blob/main/examples/arrow/src/rules.ts)
78
+ - [example tests](https://github.com/flayerlabs/gamemode-sdk/blob/main/examples/README.md)
@@ -0,0 +1,145 @@
1
+ import type { PlayerId } from './index.js';
2
+ import { type BuyFailure, type LaunchContext, type PlayerIdentity, type WireMarketState } from './live.js';
3
+ export declare const EMBED_CHANNEL: "flaunch.game-mode";
4
+ export declare const EMBED_PROTOCOL_VERSION: 1;
5
+ export interface GameRegistration {
6
+ chainId: number;
7
+ coin: string;
8
+ gameId: string;
9
+ gateOrigin: string;
10
+ deployId: string;
11
+ }
12
+ /** Parse the central registry response into the exact browser-safe shape the parent may trust. */
13
+ export declare function parseGameRegistration(input: unknown): GameRegistration | null;
14
+ export interface SpendAuthorisation {
15
+ buyer: string;
16
+ poolId: string;
17
+ deadline: string;
18
+ maxSpendWei: string;
19
+ nonce: string;
20
+ signature: string;
21
+ signer: string;
22
+ /** Opaque proof from the gate. The parent passes it to the Flaunch SDK unchanged. */
23
+ hookData: `0x${string}`;
24
+ }
25
+ export interface SpendAuthorisationFields {
26
+ buyer: string;
27
+ poolId: string;
28
+ deadline: string | bigint;
29
+ maxSpendWei: string | bigint;
30
+ nonce: string | bigint;
31
+ }
32
+ /** Build the one typed-data shape shared by the gate signer and trusted parent verifier. */
33
+ export declare function spendAuthorisationTypedData(fields: SpendAuthorisationFields, chainId: number, verifyingContract: string): {
34
+ domain: {
35
+ name: string;
36
+ version: string;
37
+ chainId: number;
38
+ verifyingContract: `0x${string}`;
39
+ };
40
+ types: {
41
+ readonly SpendAuthorization: readonly [{
42
+ readonly name: "buyer";
43
+ readonly type: "address";
44
+ }, {
45
+ readonly name: "poolId";
46
+ readonly type: "bytes32";
47
+ }, {
48
+ readonly name: "deadline";
49
+ readonly type: "uint256";
50
+ }, {
51
+ readonly name: "maxSpendWei";
52
+ readonly type: "uint256";
53
+ }, {
54
+ readonly name: "nonce";
55
+ readonly type: "uint256";
56
+ }];
57
+ };
58
+ primaryType: "SpendAuthorization";
59
+ message: {
60
+ buyer: `0x${string}`;
61
+ poolId: `0x${string}`;
62
+ deadline: bigint;
63
+ maxSpendWei: bigint;
64
+ nonce: bigint;
65
+ };
66
+ };
67
+ export interface EmbeddedContext {
68
+ gateUrl: string;
69
+ roundId: string;
70
+ launch: LaunchContext;
71
+ }
72
+ export type EmbedRequest = {
73
+ method: 'address';
74
+ } | {
75
+ method: 'sign-in';
76
+ message: string;
77
+ } | {
78
+ method: 'session-evidence';
79
+ } | {
80
+ method: 'buy';
81
+ authorisation: SpendAuthorisation;
82
+ } | {
83
+ method: 'identity';
84
+ players: readonly PlayerId[];
85
+ };
86
+ export type GameToHostMessage = {
87
+ channel: typeof EMBED_CHANNEL;
88
+ v: typeof EMBED_PROTOCOL_VERSION;
89
+ type: 'ready';
90
+ } | {
91
+ channel: typeof EMBED_CHANNEL;
92
+ v: typeof EMBED_PROTOCOL_VERSION;
93
+ type: 'request';
94
+ id: string;
95
+ request: EmbedRequest;
96
+ };
97
+ export type EmbedFailure = BuyFailure | 'no-wallet';
98
+ export type HostToGameMessage = {
99
+ channel: typeof EMBED_CHANNEL;
100
+ v: typeof EMBED_PROTOCOL_VERSION;
101
+ type: 'context';
102
+ context: EmbeddedContext;
103
+ } | {
104
+ channel: typeof EMBED_CHANNEL;
105
+ v: typeof EMBED_PROTOCOL_VERSION;
106
+ type: 'response';
107
+ id: string;
108
+ ok: true;
109
+ value: unknown;
110
+ } | {
111
+ channel: typeof EMBED_CHANNEL;
112
+ v: typeof EMBED_PROTOCOL_VERSION;
113
+ type: 'response';
114
+ id: string;
115
+ ok: false;
116
+ error: EmbedFailure;
117
+ } | {
118
+ channel: typeof EMBED_CHANNEL;
119
+ v: typeof EMBED_PROTOCOL_VERSION;
120
+ type: 'buy-progress';
121
+ id: string;
122
+ transactionHash?: string;
123
+ } | {
124
+ channel: typeof EMBED_CHANNEL;
125
+ v: typeof EMBED_PROTOCOL_VERSION;
126
+ type: 'market';
127
+ market: WireMarketState;
128
+ };
129
+ export declare function isSpendAuthorisation(input: unknown): input is SpendAuthorisation;
130
+ /**
131
+ * Require the exact ABI payload the gate emits, including its zero referrer.
132
+ *
133
+ * The calculator signature covers the spend fields but not the outer referrer. A creator iframe
134
+ * can therefore redirect attribution while preserving a valid signature unless the trusted
135
+ * bridge checks the complete canonical encoding before opening wallet UI.
136
+ */
137
+ export declare function isCanonicalSpendHookData(input: unknown): input is SpendAuthorisation;
138
+ export declare function parseGameToHostMessage(input: unknown): GameToHostMessage | null;
139
+ export declare function parseHostToGameMessage(input: unknown): HostToGameMessage | null;
140
+ /** Reject an iframe trying to turn the trusted parent into a generic signing oracle. */
141
+ export declare function isSessionChallenge(message: string, address: string, gateOrigin: string, domain?: string): boolean;
142
+ /** Canonical wallet challenge shared by the gate and the trusted embedding parent. */
143
+ export declare function formatSessionChallenge(domain: string, address: string, gateOrigin: string, code: string): string;
144
+ export declare function isPlayerIdentities(input: unknown): input is readonly PlayerIdentity[];
145
+ //# sourceMappingURL=embed.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed.d.ts","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAmB,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5H,eAAO,MAAM,aAAa,EAAG,mBAA4B,CAAC;AAC1D,eAAO,MAAM,sBAAsB,EAAG,CAAU,CAAC;AAUjD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,kGAAkG;AAClG,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,GAAG,IAAI,CA0C7E;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,qFAAqF;IACrF,QAAQ,EAAE,KAAK,MAAM,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,wBAAwB;IACvC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,MAAM,CAAC;IAC7B,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;CACxB;AAqBD,4FAA4F;AAC5F,wBAAgB,2BAA2B,CACzC,MAAM,EAAE,wBAAwB,EAChC,OAAO,EAAE,MAAM,EACf,iBAAiB,EAAE,MAAM;;;;;2BAYmB,KAAK,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;eAK9B,KAAK,MAAM,EAAE;gBACX,KAAK,MAAM,EAAE;;;;;EAM3C;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,aAAa,CAAC;CACvB;AAED,MAAM,MAAM,YAAY,GACpB;IAAE,MAAM,EAAE,SAAS,CAAA;CAAE,GACrB;IAAE,MAAM,EAAE,SAAS,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACtC;IAAE,MAAM,EAAE,kBAAkB,CAAA;CAAE,GAC9B;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,aAAa,EAAE,kBAAkB,CAAA;CAAE,GACpD;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAA;CAAE,CAAC;AAEzD,MAAM,MAAM,iBAAiB,GACzB;IAAE,OAAO,EAAE,OAAO,aAAa,CAAC;IAAC,CAAC,EAAE,OAAO,sBAAsB,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,GAClF;IACE,OAAO,EAAE,OAAO,aAAa,CAAC;IAC9B,CAAC,EAAE,OAAO,sBAAsB,CAAC;IACjC,IAAI,EAAE,SAAS,CAAC;IAChB,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,YAAY,CAAC;CACvB,CAAC;AAEN,MAAM,MAAM,YAAY,GAAG,UAAU,GAAG,WAAW,CAAC;AAEpD,MAAM,MAAM,iBAAiB,GACzB;IACE,OAAO,EAAE,OAAO,aAAa,CAAC;IAC9B,CAAC,EAAE,OAAO,sBAAsB,CAAC;IACjC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,eAAe,CAAC;CAC1B,GACD;IACE,OAAO,EAAE,OAAO,aAAa,CAAC;IAC9B,CAAC,EAAE,OAAO,sBAAsB,CAAC;IACjC,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,IAAI,CAAC;IACT,KAAK,EAAE,OAAO,CAAC;CAChB,GACD;IACE,OAAO,EAAE,OAAO,aAAa,CAAC;IAC9B,CAAC,EAAE,OAAO,sBAAsB,CAAC;IACjC,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,YAAY,CAAC;CACrB,GACD;IACE,OAAO,EAAE,OAAO,aAAa,CAAC;IAC9B,CAAC,EAAE,OAAO,sBAAsB,CAAC;IACjC,IAAI,EAAE,cAAc,CAAC;IACrB,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,GACD;IACE,OAAO,EAAE,OAAO,aAAa,CAAC;IAC9B,CAAC,EAAE,OAAO,sBAAsB,CAAC;IACjC,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,eAAe,CAAC;CACzB,CAAC;AAoEN,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAuBhF;AAWD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,kBAAkB,CAwBpF;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,GAAG,IAAI,CAuC/E;AAED,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,OAAO,GAAG,iBAAiB,GAAG,IAAI,CAqB/E;AAED,wFAAwF;AACxF,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,UAAU,EAAE,MAAM,EAClB,MAAM,SAAe,GACpB,OAAO,CAkBT;AAED,sFAAsF;AACtF,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAUhH;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,cAAc,EAAE,CAerF"}
package/dist/embed.js ADDED
@@ -0,0 +1,332 @@
1
+ import { isLaunchContext } from './live.js';
2
+ export const EMBED_CHANNEL = 'flaunch.game-mode';
3
+ export const EMBED_PROTOCOL_VERSION = 1;
4
+ const ADDRESS = /^0x[0-9a-fA-F]{40}$/;
5
+ const BYTES32 = /^0x[0-9a-fA-F]{64}$/;
6
+ const HEX = /^0x(?:[0-9a-fA-F]{2})*$/;
7
+ const DECIMAL = /^(?:0|[1-9][0-9]{0,77})$/;
8
+ const REQUEST_ID = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
9
+ const DEPLOY_ID = /^[0-9a-f]{32}$/;
10
+ const PUBLIC_HOSTNAME = /^(?=.{1,253}$)([a-z0-9]([a-z0-9-]{0,61}[a-z0-9])?\.)+[a-z]{2,63}$/;
11
+ /** Parse the central registry response into the exact browser-safe shape the parent may trust. */
12
+ export function parseGameRegistration(input) {
13
+ const value = record(input);
14
+ if (!value ||
15
+ !Number.isSafeInteger(value.chainId) ||
16
+ value.chainId <= 0 ||
17
+ typeof value.coin !== 'string' ||
18
+ !ADDRESS.test(value.coin) ||
19
+ value.coin !== value.coin.toLowerCase() ||
20
+ typeof value.gameId !== 'string' ||
21
+ value.gameId.length === 0 ||
22
+ value.gameId.length > 128 ||
23
+ value.gameId !== value.gameId.trim() ||
24
+ typeof value.deployId !== 'string' ||
25
+ !DEPLOY_ID.test(value.deployId) ||
26
+ typeof value.gateOrigin !== 'string' ||
27
+ value.gateOrigin.length > 253 ||
28
+ /[^\x20-\x7e]/.test(value.gateOrigin)) {
29
+ return null;
30
+ }
31
+ try {
32
+ const gate = new URL(value.gateOrigin);
33
+ if (gate.protocol !== 'https:' ||
34
+ gate.origin !== value.gateOrigin ||
35
+ !PUBLIC_HOSTNAME.test(gate.hostname)) {
36
+ return null;
37
+ }
38
+ }
39
+ catch {
40
+ return null;
41
+ }
42
+ return {
43
+ chainId: value.chainId,
44
+ coin: value.coin,
45
+ gameId: value.gameId,
46
+ gateOrigin: value.gateOrigin,
47
+ deployId: value.deployId,
48
+ };
49
+ }
50
+ const SPEND_AUTHORIZATION_TYPES = {
51
+ SpendAuthorization: [
52
+ { name: 'buyer', type: 'address' },
53
+ { name: 'poolId', type: 'bytes32' },
54
+ { name: 'deadline', type: 'uint256' },
55
+ { name: 'maxSpendWei', type: 'uint256' },
56
+ { name: 'nonce', type: 'uint256' },
57
+ ],
58
+ };
59
+ function uint256(value, field) {
60
+ if (typeof value === 'string' && !DECIMAL.test(value)) {
61
+ throw new RangeError(`${field} must be an unsigned decimal integer`);
62
+ }
63
+ const parsed = BigInt(value);
64
+ if (parsed < 0n || parsed >= 1n << 256n)
65
+ throw new RangeError(`${field} must fit uint256`);
66
+ return parsed;
67
+ }
68
+ /** Build the one typed-data shape shared by the gate signer and trusted parent verifier. */
69
+ export function spendAuthorisationTypedData(fields, chainId, verifyingContract) {
70
+ if (!ADDRESS.test(fields.buyer))
71
+ throw new TypeError('buyer must be an EVM address');
72
+ if (!BYTES32.test(fields.poolId))
73
+ throw new TypeError('poolId must be 32 bytes');
74
+ if (!Number.isSafeInteger(chainId) || chainId <= 0)
75
+ throw new RangeError('chainId must be a positive safe integer');
76
+ if (!ADDRESS.test(verifyingContract))
77
+ throw new TypeError('verifyingContract must be an EVM address');
78
+ return {
79
+ domain: {
80
+ name: 'FlaunchSpendGate',
81
+ version: '1',
82
+ chainId,
83
+ verifyingContract: verifyingContract,
84
+ },
85
+ types: SPEND_AUTHORIZATION_TYPES,
86
+ primaryType: 'SpendAuthorization',
87
+ message: {
88
+ buyer: fields.buyer,
89
+ poolId: fields.poolId,
90
+ deadline: uint256(fields.deadline, 'deadline'),
91
+ maxSpendWei: uint256(fields.maxSpendWei, 'maxSpendWei'),
92
+ nonce: uint256(fields.nonce, 'nonce'),
93
+ },
94
+ };
95
+ }
96
+ function record(input) {
97
+ return typeof input === 'object' && input !== null ? input : null;
98
+ }
99
+ function bounded(value, max) {
100
+ return typeof value === 'string' && value.length > 0 && value.length <= max;
101
+ }
102
+ function finite(value) {
103
+ return typeof value === 'number' && Number.isFinite(value);
104
+ }
105
+ function isWireMarketState(input) {
106
+ const value = record(input);
107
+ if (!value ||
108
+ typeof value.status !== 'string' ||
109
+ !['unavailable', 'loading', 'live', 'stale'].includes(value.status) ||
110
+ !Array.isArray(value.prices) ||
111
+ value.prices.length > 1_000 ||
112
+ !Array.isArray(value.trades) ||
113
+ value.trades.length > 500 ||
114
+ (value.marketCapUsd !== null && !finite(value.marketCapUsd))) {
115
+ return false;
116
+ }
117
+ for (const inputPrice of value.prices) {
118
+ const price = record(inputPrice);
119
+ if (!price || !finite(price.at) || !finite(price.priceEth) || price.priceEth <= 0)
120
+ return false;
121
+ }
122
+ for (const inputTrade of value.trades) {
123
+ const trade = record(inputTrade);
124
+ if (!trade ||
125
+ !bounded(trade.id, 128) ||
126
+ !finite(trade.at) ||
127
+ (trade.player !== null && !bounded(trade.player, 128)) ||
128
+ (trade.side !== 'buy' && trade.side !== 'sell') ||
129
+ typeof trade.spendWei !== 'string' ||
130
+ !DECIMAL.test(trade.spendWei) ||
131
+ (trade.priceEth !== null && !finite(trade.priceEth)) ||
132
+ (trade.transactionHash !== undefined && !bounded(trade.transactionHash, 128))) {
133
+ return false;
134
+ }
135
+ }
136
+ return true;
137
+ }
138
+ function embeddedContext(input) {
139
+ const value = record(input);
140
+ if (!value || !bounded(value.gateUrl, 2_048) || !bounded(value.roundId, 128) || !isLaunchContext(value.launch)) {
141
+ return false;
142
+ }
143
+ if (value.roundId !== value.launch.roundId)
144
+ return false;
145
+ try {
146
+ const gate = new URL(value.gateUrl);
147
+ return (gate.protocol === 'https:' || gate.protocol === 'http:') && gate.origin === value.gateUrl;
148
+ }
149
+ catch {
150
+ return false;
151
+ }
152
+ }
153
+ export function isSpendAuthorisation(input) {
154
+ const value = record(input);
155
+ return Boolean(value &&
156
+ typeof value.buyer === 'string' &&
157
+ ADDRESS.test(value.buyer) &&
158
+ typeof value.poolId === 'string' &&
159
+ BYTES32.test(value.poolId) &&
160
+ typeof value.deadline === 'string' &&
161
+ DECIMAL.test(value.deadline) &&
162
+ typeof value.maxSpendWei === 'string' &&
163
+ DECIMAL.test(value.maxSpendWei) &&
164
+ typeof value.nonce === 'string' &&
165
+ DECIMAL.test(value.nonce) &&
166
+ typeof value.signature === 'string' &&
167
+ HEX.test(value.signature) &&
168
+ value.signature.length <= 512 &&
169
+ typeof value.signer === 'string' &&
170
+ ADDRESS.test(value.signer) &&
171
+ typeof value.hookData === 'string' &&
172
+ HEX.test(value.hookData) &&
173
+ value.hookData.length <= 8_194);
174
+ }
175
+ const uint256Word = (value) => {
176
+ try {
177
+ const parsed = BigInt(value);
178
+ return parsed < 1n << 256n ? parsed.toString(16).padStart(64, '0') : null;
179
+ }
180
+ catch {
181
+ return null;
182
+ }
183
+ };
184
+ /**
185
+ * Require the exact ABI payload the gate emits, including its zero referrer.
186
+ *
187
+ * The calculator signature covers the spend fields but not the outer referrer. A creator iframe
188
+ * can therefore redirect attribution while preserving a valid signature unless the trusted
189
+ * bridge checks the complete canonical encoding before opening wallet UI.
190
+ */
191
+ export function isCanonicalSpendHookData(input) {
192
+ if (!isSpendAuthorisation(input))
193
+ return false;
194
+ const deadline = uint256Word(input.deadline);
195
+ const maxSpendWei = uint256Word(input.maxSpendWei);
196
+ const nonce = uint256Word(input.nonce);
197
+ if (!deadline || !maxSpendWei || !nonce)
198
+ return false;
199
+ const signature = input.signature.slice(2).toLowerCase();
200
+ const signatureLength = uint256Word(String(signature.length / 2));
201
+ if (!signatureLength)
202
+ return false;
203
+ const paddedSignature = signature.padEnd(Math.ceil(signature.length / 64) * 64, '0');
204
+ const expected = `0x${[
205
+ '0'.repeat(64),
206
+ uint256Word('64'),
207
+ input.buyer.slice(2).toLowerCase().padStart(64, '0'),
208
+ input.poolId.slice(2).toLowerCase(),
209
+ deadline,
210
+ maxSpendWei,
211
+ nonce,
212
+ uint256Word('192'),
213
+ signatureLength,
214
+ paddedSignature,
215
+ ].join('')}`;
216
+ return input.hookData.toLowerCase() === expected;
217
+ }
218
+ export function parseGameToHostMessage(input) {
219
+ const value = record(input);
220
+ if (value?.channel !== EMBED_CHANNEL || value.v !== EMBED_PROTOCOL_VERSION)
221
+ return null;
222
+ if (value.type === 'ready')
223
+ return { channel: EMBED_CHANNEL, v: EMBED_PROTOCOL_VERSION, type: 'ready' };
224
+ if (value.type !== 'request' || typeof value.id !== 'string' || !REQUEST_ID.test(value.id))
225
+ return null;
226
+ const request = record(value.request);
227
+ if (!request)
228
+ return null;
229
+ let parsed = null;
230
+ if (request.method === 'address')
231
+ parsed = { method: 'address' };
232
+ if (request.method === 'session-evidence')
233
+ parsed = { method: 'session-evidence' };
234
+ if (request.method === 'sign-in' && bounded(request.message, 4_096)) {
235
+ parsed = { method: 'sign-in', message: request.message };
236
+ }
237
+ if (request.method === 'buy' && isSpendAuthorisation(request.authorisation)) {
238
+ const authorisation = request.authorisation;
239
+ parsed = {
240
+ method: 'buy',
241
+ authorisation: {
242
+ buyer: authorisation.buyer,
243
+ poolId: authorisation.poolId,
244
+ deadline: authorisation.deadline,
245
+ maxSpendWei: authorisation.maxSpendWei,
246
+ nonce: authorisation.nonce,
247
+ signature: authorisation.signature,
248
+ signer: authorisation.signer,
249
+ hookData: authorisation.hookData,
250
+ },
251
+ };
252
+ }
253
+ if (request.method === 'identity' &&
254
+ Array.isArray(request.players) &&
255
+ request.players.length <= 100 &&
256
+ request.players.every((player) => typeof player === 'string' && ADDRESS.test(player))) {
257
+ parsed = { method: 'identity', players: [...new Set(request.players)] };
258
+ }
259
+ return parsed ? { channel: EMBED_CHANNEL, v: EMBED_PROTOCOL_VERSION, type: 'request', id: value.id, request: parsed } : null;
260
+ }
261
+ export function parseHostToGameMessage(input) {
262
+ const value = record(input);
263
+ if (value?.channel !== EMBED_CHANNEL || value.v !== EMBED_PROTOCOL_VERSION)
264
+ return null;
265
+ if (value.type === 'context' && embeddedContext(value.context)) {
266
+ return { channel: EMBED_CHANNEL, v: EMBED_PROTOCOL_VERSION, type: 'context', context: value.context };
267
+ }
268
+ if (value.type === 'market' && isWireMarketState(value.market))
269
+ return value;
270
+ if (typeof value.id !== 'string' || !REQUEST_ID.test(value.id))
271
+ return null;
272
+ if (value.type === 'buy-progress') {
273
+ if (value.transactionHash !== undefined && (typeof value.transactionHash !== 'string' || !BYTES32.test(value.transactionHash))) {
274
+ return null;
275
+ }
276
+ return value;
277
+ }
278
+ if (value.type !== 'response' || typeof value.ok !== 'boolean')
279
+ return null;
280
+ if (value.ok)
281
+ return value;
282
+ return ['nothing-to-spend', 'declined', 'not-enough-for-fees', 'window-closed', 'no-wallet', 'try-again'].includes(String(value.error))
283
+ ? value
284
+ : null;
285
+ }
286
+ /** Reject an iframe trying to turn the trusted parent into a generic signing oracle. */
287
+ export function isSessionChallenge(message, address, gateOrigin, domain = 'flaunch.gg') {
288
+ if (!ADDRESS.test(address) || message.length > 4_096)
289
+ return false;
290
+ try {
291
+ const gate = new URL(gateOrigin);
292
+ if ((gate.protocol !== 'https:' && gate.protocol !== 'http:') || gate.origin !== gateOrigin)
293
+ return false;
294
+ }
295
+ catch {
296
+ return false;
297
+ }
298
+ const lines = message.split('\n');
299
+ if (lines.length !== 7 || !lines[4]?.startsWith('Wallet: ') || !lines[6]?.startsWith('Code: '))
300
+ return false;
301
+ const wallet = lines[4].slice('Wallet: '.length);
302
+ const code = lines[6].slice('Code: '.length);
303
+ return (wallet.toLowerCase() === address.toLowerCase() &&
304
+ code.length > 0 &&
305
+ code.length <= 2_048 &&
306
+ message === formatSessionChallenge(domain, wallet, gateOrigin, code));
307
+ }
308
+ /** Canonical wallet challenge shared by the gate and the trusted embedding parent. */
309
+ export function formatSessionChallenge(domain, address, gateOrigin, code) {
310
+ return [
311
+ `${domain} wants you to sign in with your wallet.`,
312
+ '',
313
+ 'Signing proves this wallet is yours. It costs nothing and moves nothing.',
314
+ '',
315
+ `Wallet: ${address}`,
316
+ `Gate: ${gateOrigin}`,
317
+ `Code: ${code}`,
318
+ ].join('\n');
319
+ }
320
+ export function isPlayerIdentities(input) {
321
+ return (Array.isArray(input) &&
322
+ input.length <= 100 &&
323
+ input.every((identity) => {
324
+ const value = record(identity);
325
+ return Boolean(value &&
326
+ typeof value.player === 'string' &&
327
+ ADDRESS.test(value.player) &&
328
+ (value.displayName === null || (typeof value.displayName === 'string' && value.displayName.length <= 256)) &&
329
+ (value.avatarUrl === null || (typeof value.avatarUrl === 'string' && value.avatarUrl.length <= 2_048)));
330
+ }));
331
+ }
332
+ //# sourceMappingURL=embed.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"embed.js","sourceRoot":"","sources":["../src/embed.ts"],"names":[],"mappings":"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"}