@flayerlabs/gamemode-gate 0.5.5 → 0.6.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/DEPLOY.md +37 -9
- package/README.md +7 -1
- package/dist/chain/chains.d.ts +14 -6
- package/dist/chain/chains.d.ts.map +1 -1
- package/dist/chain/chains.js +8 -4
- package/dist/chain/chains.js.map +1 -1
- package/dist/chain/discover.d.ts +61 -3
- package/dist/chain/discover.d.ts.map +1 -1
- package/dist/chain/discover.js +181 -21
- package/dist/chain/discover.js.map +1 -1
- package/dist/chain/registry-prices.d.ts +69 -0
- package/dist/chain/registry-prices.d.ts.map +1 -0
- package/dist/chain/registry-prices.js +157 -0
- package/dist/chain/registry-prices.js.map +1 -0
- package/dist/chain/secure.d.ts +28 -0
- package/dist/chain/secure.d.ts.map +1 -1
- package/dist/chain/secure.js +55 -20
- package/dist/chain/secure.js.map +1 -1
- package/dist/economy.d.ts.map +1 -1
- package/dist/economy.js +12 -3
- package/dist/economy.js.map +1 -1
- package/dist/index.d.ts +7 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts +14 -3
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +44 -11
- package/dist/main.js.map +1 -1
- package/dist/room.d.ts +7 -0
- package/dist/room.d.ts.map +1 -1
- package/dist/room.js +15 -6
- package/dist/room.js.map +1 -1
- package/dist/server.d.ts +26 -0
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +21 -0
- package/dist/server.js.map +1 -1
- package/dist/store.d.ts +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +6 -0
- package/dist/store.js.map +1 -1
- package/dist/version.js +2 -2
- package/package.json +2 -2
- package/src/chain/chains.ts +14 -6
- package/src/chain/discover.ts +212 -21
- package/src/chain/registry-prices.ts +194 -0
- package/src/chain/secure.ts +75 -31
- package/src/economy.ts +13 -3
- package/src/index.ts +7 -4
- package/src/main.ts +50 -11
- package/src/room.ts +14 -3
- package/src/server.ts +49 -0
- package/src/store.ts +6 -0
- package/src/version.ts +2 -2
package/DEPLOY.md
CHANGED
|
@@ -38,15 +38,16 @@ gate whose signatures a swap can actually verify.
|
|
|
38
38
|
| `GATE_ORIGIN` | yes | This gate's own public https origin (e.g. `https://gate.example.com`) — the audience its sessions are scoped to. Configured, never derived from a request header. |
|
|
39
39
|
| `ALLOWED_ORIGINS` | yes | Comma-separated origins allowed to call this gate: your game's Moongate origin(s) AND every page that embeds it — the coin page calls `/rounds/adopt` itself. Production is `https://flaunch.gg`; a staging or preview launch page has its own origin and needs listing while you test against it. A launch that fails with a CORS error names the missing origin in its `Referer`. |
|
|
40
40
|
| `PORT` | no | Default `8790`. |
|
|
41
|
-
| `POSITION_MANAGER`, `SPEND_GATED_CALCULATOR` | no | Which recorded stack this gate serves, or address-book overrides. Naming a recorded manager selects its whole stack (calculator and router with it): on Base Sepolia `0x8D346f24278C5CD786309161aAC0fC2bbe4c25dc` is the paired-token stack, the one that can host coins paired with MUSD and other non-ETH tokens. Unset means the legacy stack. Override both only with addresses read back from the chain in question — a wrong address fails silently (see `chain/chains.ts`). |
|
|
42
|
-
| `POOL_SWAP`, `FLETH` | no | Address-book overrides for the paired stack's approved swap router and the chain's flETH wrapper. A `v1_3` stack needs a router. |
|
|
43
|
-
| `FLAUNCH_VARIANT` | no | `v1_2`, `multichain` or `
|
|
41
|
+
| `POSITION_MANAGER`, `SPEND_GATED_CALCULATOR` | no | Which recorded stack this gate serves, or address-book overrides. Naming a recorded manager selects its whole stack (calculator and router with it): on Base Sepolia `0x8D346f24278C5CD786309161aAC0fC2bbe4c25dc` is the paired-token stack, the one that can host coins paired with MUSD and other non-ETH tokens. Unset means the legacy stack. Override both only with addresses read back from the chain in question — a wrong address fails silently (see `chain/chains.ts`). The manager named here is the gate's PRIMARY one — asserted at boot, announced in `/config`, used for the readiness proof. It is not the only one the gate serves: see "Any wired position manager" below. |
|
|
42
|
+
| `POOL_SWAP`, `FLETH` | no | Address-book overrides for the paired stack's approved swap router and the chain's flETH wrapper. A `v1_3` or `any_v1_3` stack needs a router. |
|
|
43
|
+
| `FLAUNCH_VARIANT` | no | `v1_2`, `multichain`, `v1_3` or `any_v1_3` — the PRIMARY manager's generation; recorded per stack, override only with the overrides above. Not a limit on which managers the gate adopts coins from. |
|
|
44
44
|
| `SETTLER` | no | The address that may lift the gate early or rotate the signer on-chain. Defaults to the signing key's address; the gate expires on chain by itself either way. |
|
|
45
45
|
| `WALLET_CAP_WEI` | no | Advertised per-wallet cap for ETH-paired launches through this gate, in wei. Default 0.025 ETH. |
|
|
46
46
|
| `ROUND_MS` | no | Advertised round length. Default 90000. |
|
|
47
47
|
| `MIN_LOBBY_LEAD_MS`, `GATE_ENDS_AT_GRACE_S` | no | Defaults 60000 and 10. |
|
|
48
48
|
| `POINTS_PER_DOLLAR`, `USD_PER_ETH` | no | Your game's economy. Defaults 100 and 3000; `USD_PER_ETH` may be fractional. Boot refuses an economy your `rewardBounds` cannot honour. |
|
|
49
|
-
| `SPEND_TOKENS` | no |
|
|
49
|
+
| `SPEND_TOKENS` | no | Pin a price for a non-ETH paired token: a JSON array of `{ "address", "usdPerToken", "walletCap" }`, the cap in that token's base units. Symbol and decimals are read from the chain at boot, and boot refuses an economy the cap cannot honour. Tokens not listed are priced from the manager's `PairedTokenRegistry` at adoption (below); only a token the registry does not approve is refused. Needs the paired stack (`POSITION_MANAGER` above). |
|
|
50
|
+
| `PAIRED_TOKEN_CAP_HEADROOM_PERCENT` | no | Default `25`. Headroom over the smallest cap a flawless round fits under when the gate sizes the cap for a registry-priced pairing in `GET /config/spend-tokens/:address`. |
|
|
50
51
|
|
|
51
52
|
## Paired-token rounds
|
|
52
53
|
|
|
@@ -59,8 +60,35 @@ that token's units. Two things make a gate able to host them:
|
|
|
59
60
|
Sepolia. That manager also hosts flETH and native-ETH pairings, so the same gate still runs ETH
|
|
60
61
|
rounds. Boot reads the stack's wiring back (dispatcher registration, the calculator's role grant,
|
|
61
62
|
the router approval) and refuses with the missing call named if any is absent.
|
|
62
|
-
2.
|
|
63
|
-
|
|
63
|
+
2. Nothing else. The gate reads the manager's `pairedTokenRegistry()` at boot and prices every token
|
|
64
|
+
the registry approves through the calculator that token was registered with, at adoption, so a
|
|
65
|
+
pairing approved after boot is adopted with no redeploy. `/config` names the registry as
|
|
66
|
+
`pairedTokenRegistry`, and `GET /config/spend-tokens/<token>` serves the entry the launch page
|
|
67
|
+
needs before a coin is paid for — symbol, decimals, price and the per-wallet cap to write. Pin a
|
|
68
|
+
price with `SPEND_TOKENS` only when you must; `/config` announces pinned tokens under
|
|
69
|
+
`spendTokens`.
|
|
70
|
+
|
|
71
|
+
## Any wired position manager (0.6.0)
|
|
72
|
+
|
|
73
|
+
One gate serves one spend-gated calculator, and any Flaunch PositionManager wired to it. There is
|
|
74
|
+
no list of managers to keep: a coin offered for adoption names its own manager (`Memecoin.flaunch()`
|
|
75
|
+
is the launch ERC721, whose `positionManager()` is the pool's hook), and the gate adopts the coin
|
|
76
|
+
when that manager's fee wiring routes to the gate's calculator — the same three reads boot makes of
|
|
77
|
+
`POSITION_MANAGER` (`feeCalculator()` is a dispatcher, the dispatcher has the calculator registered,
|
|
78
|
+
the calculator grants the dispatcher its role), made once per manager and remembered for the life of
|
|
79
|
+
the process. Wiring a new manager to the dispatcher on chain is what approves it; no gate release
|
|
80
|
+
and nothing in your environment changes. This is how a coin launched through AnyFlaunchZap on the
|
|
81
|
+
V1_3 AnyPositionManager (a vested launch, say) is played on the same gate as a coin on the paired
|
|
82
|
+
manager.
|
|
83
|
+
|
|
84
|
+
A coin on a manager wired to some other calculator is refused for good with
|
|
85
|
+
`launch.unapproved_position_manager`, because the EIP-712 domain binds every authorisation to the
|
|
86
|
+
calculator and a coin this gate cannot sign for must not be given a room by it. A wired manager of
|
|
87
|
+
a generation the gate has no round model for (no `flaunchesAt()`) is refused with
|
|
88
|
+
`launch.unsupported_position_manager`. `/config` announces `positionManagerPolicy:
|
|
89
|
+
'wired-to-calculator'` so launch tooling can tell this gate from an older one, and keeps announcing
|
|
90
|
+
`contracts.positionManager` and `flaunchVariant` for the primary manager. Cost: two extra reads per
|
|
91
|
+
adoption (`flaunch()`, `positionManager()`); the wiring reads happen once per manager.
|
|
64
92
|
|
|
65
93
|
Release 0.5.0 removed `usdPerEth` from the wire along with the rest of the ETH-flavoured naming.
|
|
66
94
|
Round terms now always carry `spendToken` (symbol, decimals, address) and `usdPerSpendToken`, the
|
|
@@ -92,9 +120,9 @@ flow reads it from here. If `/config` is missing, the process was built without
|
|
|
92
120
|
|
|
93
121
|
## Hand it to Flaunch
|
|
94
122
|
|
|
95
|
-
The public https origin you just smoke-tested is exactly the Gate URL you enter
|
|
96
|
-
|
|
97
|
-
|
|
123
|
+
The public https origin you just smoke-tested is exactly the Gate URL you enter for your game in
|
|
124
|
+
the developer dashboard at `https://flaunch.gg/game-mode/dashboard` — declare it as a network
|
|
125
|
+
there. A game submitted without one is hosted as a passive game: its security policy allows no gate connection at all, so a launch
|
|
98
126
|
through it can never open a room. The origin must be public https (no localhost, no IPs, no
|
|
99
127
|
wildcards), because the game's browser policy only permits the origin you submitted.
|
|
100
128
|
|
package/README.md
CHANGED
|
@@ -60,8 +60,14 @@ A `createGate` setup needs:
|
|
|
60
60
|
|
|
61
61
|
Add the chain services used by your deployment:
|
|
62
62
|
|
|
63
|
-
- `Discovery` verifies each launch before the gate adopts it
|
|
63
|
+
- `Discovery` verifies each launch before the gate adopts it. It resolves the coin's own
|
|
64
|
+
PositionManager and adopts the coin when that manager is wired to your calculator (checked once
|
|
65
|
+
per manager, from the chain), so one gate serves one calculator and every manager wired to it;
|
|
66
|
+
the configured manager is the primary one, not the only one
|
|
64
67
|
- `Settlement` updates recorded spending from the chain
|
|
68
|
+
- `RegistryPrices` prices any pairing the manager's PairedTokenRegistry approves, from the
|
|
69
|
+
calculator it was registered with; pass its `priceFor` and serve `announceSpendToken` so a new
|
|
70
|
+
approval needs no gate change (`startGate` does both)
|
|
65
71
|
|
|
66
72
|
In 0.5.4, pass a full viem public client (including `getBlock`) to `Settlement`. It retires consumed
|
|
67
73
|
claims and records spend atomically after two block confirmations and the next reconciliation pass.
|
package/dist/chain/chains.d.ts
CHANGED
|
@@ -14,10 +14,14 @@
|
|
|
14
14
|
* that chain is served by the legacy gate, and this library refusing it keeps the two stacks from
|
|
15
15
|
* being pointed at each other by a copied env file.
|
|
16
16
|
*
|
|
17
|
-
* One gate serves
|
|
18
|
-
* every authorisation binds it to the calculator address, so a signature minted for one
|
|
19
|
-
* meaningless to
|
|
20
|
-
* as its own entry rather than pretending a chain has one.
|
|
17
|
+
* One gate serves ONE spendGatedCalculator, and any PositionManager wired to it. The EIP-712
|
|
18
|
+
* domain of every authorisation binds it to the calculator address, so a signature minted for one
|
|
19
|
+
* calculator is meaningless to another — a gate cannot straddle two calculators, and this book
|
|
20
|
+
* records each as its own entry rather than pretending a chain has one. The manager is looser: a
|
|
21
|
+
* coin offered for adoption names its own manager, and the gate adopts it when that manager's fee
|
|
22
|
+
* wiring routes to the gate's calculator (`chain/secure.ts`). The `positionManager` recorded here
|
|
23
|
+
* is the PRIMARY one — what boot asserts, what `/config` announces and what the readiness proof
|
|
24
|
+
* launches on — not the only one the gate will serve.
|
|
21
25
|
*/
|
|
22
26
|
/**
|
|
23
27
|
* Which launch generation the stack's PositionManager belongs to.
|
|
@@ -32,8 +36,12 @@
|
|
|
32
36
|
* v1_3 — the current generation, launched through the V1_3 FlaunchZap. The only one that
|
|
33
37
|
* can pair a coin with a token other than ETH, and therefore the only one that can
|
|
34
38
|
* run a paired-token round.
|
|
39
|
+
* any_v1_3 — the V1_3 AnyPositionManager, launched through AnyFlaunchZap: the same fee wiring
|
|
40
|
+
* and paired-token rounds as `v1_3`, plus vesting. Named here so an operator may
|
|
41
|
+
* make it the primary manager via `FLAUNCH_VARIANT`; a gate whose primary is `v1_3`
|
|
42
|
+
* adopts coins on it anyway, because adoption asks the chain, not this list.
|
|
35
43
|
*/
|
|
36
|
-
export type FlaunchVariant = 'v1_2' | 'multichain' | 'v1_3';
|
|
44
|
+
export type FlaunchVariant = 'v1_2' | 'multichain' | 'v1_3' | 'any_v1_3';
|
|
37
45
|
export interface GateDeployment {
|
|
38
46
|
positionManager: `0x${string}`;
|
|
39
47
|
spendGatedCalculator: `0x${string}`;
|
|
@@ -42,7 +50,7 @@ export interface GateDeployment {
|
|
|
42
50
|
* The single-pool swap router the calculator has approved, when the stack has one. A paired-token
|
|
43
51
|
* buy goes through it (ERC20 in, `hookData` carrying the authorisation), and the calculator binds
|
|
44
52
|
* the buyer to its `msgSender()` — so an unapproved router means every smart-wallet buy reverts.
|
|
45
|
-
* Required for `v1_3`; boot refuses a paired stack without it.
|
|
53
|
+
* Required for `v1_3` and `any_v1_3`; boot refuses a paired stack without it.
|
|
46
54
|
*/
|
|
47
55
|
poolSwap?: `0x${string}`;
|
|
48
56
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../src/chain/chains.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"chains.d.ts","sourceRoot":"","sources":["../../src/chain/chains.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,YAAY,GAAG,MAAM,GAAG,UAAU,CAAC;AAEzE,MAAM,WAAW,cAAc;IAC7B,eAAe,EAAE,KAAK,MAAM,EAAE,CAAC;IAC/B,oBAAoB,EAAE,KAAK,MAAM,EAAE,CAAC;IACpC,cAAc,EAAE,cAAc,CAAC;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;IACzB;;;OAGG;IACH,KAAK,CAAC,EAAE,KAAK,MAAM,EAAE,CAAC;CACvB;AAED,gGAAgG;AAChG,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAYtD,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CA0B7D,CAAC;AAEF;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,eAAe,CAAC,EAAE,KAAK,MAAM,EAAE,GAAG,IAAI,GAAG,cAAc,GAAG,SAAS,CAOjH"}
|
package/dist/chain/chains.js
CHANGED
|
@@ -14,10 +14,14 @@
|
|
|
14
14
|
* that chain is served by the legacy gate, and this library refusing it keeps the two stacks from
|
|
15
15
|
* being pointed at each other by a copied env file.
|
|
16
16
|
*
|
|
17
|
-
* One gate serves
|
|
18
|
-
* every authorisation binds it to the calculator address, so a signature minted for one
|
|
19
|
-
* meaningless to
|
|
20
|
-
* as its own entry rather than pretending a chain has one.
|
|
17
|
+
* One gate serves ONE spendGatedCalculator, and any PositionManager wired to it. The EIP-712
|
|
18
|
+
* domain of every authorisation binds it to the calculator address, so a signature minted for one
|
|
19
|
+
* calculator is meaningless to another — a gate cannot straddle two calculators, and this book
|
|
20
|
+
* records each as its own entry rather than pretending a chain has one. The manager is looser: a
|
|
21
|
+
* coin offered for adoption names its own manager, and the gate adopts it when that manager's fee
|
|
22
|
+
* wiring routes to the gate's calculator (`chain/secure.ts`). The `positionManager` recorded here
|
|
23
|
+
* is the PRIMARY one — what boot asserts, what `/config` announces and what the readiness proof
|
|
24
|
+
* launches on — not the only one the gate will serve.
|
|
21
25
|
*/
|
|
22
26
|
/** The legacy stack per chain — what `deploymentFor(chainId)` answers with no manager named. */
|
|
23
27
|
export const DEPLOYMENTS = {
|
package/dist/chain/chains.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"chains.js","sourceRoot":"","sources":["../../src/chain/chains.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"chains.js","sourceRoot":"","sources":["../../src/chain/chains.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAwCH,gGAAgG;AAChG,MAAM,CAAC,MAAM,WAAW,GAAmC;IACzD;;;;OAIG;IACH,KAAK,EAAE;QACL,eAAe,EAAE,4CAA4C;QAC7D,oBAAoB,EAAE,4CAA4C;QAClE,cAAc,EAAE,MAAM;QACtB,KAAK,EAAE,4CAA4C;KACpD;CACF,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAmC;IAChE;;;;;;;;;;;;;;;;;OAiBG;IACH,KAAK,EAAE;QACL,eAAe,EAAE,4CAA4C;QAC7D,oBAAoB,EAAE,4CAA4C;QAClE,cAAc,EAAE,MAAM;QACtB,QAAQ,EAAE,4CAA4C;QACtD,KAAK,EAAE,4CAA4C;KACpD;CACF,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,OAAe,EAAE,eAAsC;IACnF,IAAI,CAAC,eAAe;QAAE,OAAO,WAAW,CAAC,OAAO,CAAC,CAAC;IAClD,MAAM,MAAM,GAAG,eAAe,CAAC,WAAW,EAAE,CAAC;IAC7C,KAAK,MAAM,SAAS,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,kBAAkB,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAC5E,IAAI,SAAS,IAAI,SAAS,CAAC,eAAe,CAAC,WAAW,EAAE,KAAK,MAAM;YAAE,OAAO,SAAS,CAAC;IACxF,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC"}
|
package/dist/chain/discover.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type PublicClient } from 'viem';
|
|
2
2
|
import { type SpendToken } from '@flayerlabs/gamemode-spec/live';
|
|
3
|
+
import { type PositionManagerWiring } from './secure.js';
|
|
3
4
|
/**
|
|
4
5
|
* All this needs of a client: the ability to read a contract.
|
|
5
6
|
*
|
|
@@ -117,6 +118,11 @@ export interface Launch {
|
|
|
117
118
|
name: string;
|
|
118
119
|
symbol: string;
|
|
119
120
|
imageUrl?: string | null;
|
|
121
|
+
/**
|
|
122
|
+
* The PositionManager the coin was launched on — the pool's hook — resolved from the coin
|
|
123
|
+
* itself. Absent only from hand-built launches (demos, tests), where it means the primary one.
|
|
124
|
+
*/
|
|
125
|
+
positionManager?: `0x${string}`;
|
|
120
126
|
/**
|
|
121
127
|
* The token spend is measured in: the coin's paired token, read from the manager. Absent only
|
|
122
128
|
* from hand-built launches (demos, tests), where it means ETH.
|
|
@@ -140,11 +146,57 @@ export type LaunchCheck = ({
|
|
|
140
146
|
ok: true;
|
|
141
147
|
} & Launch) | Refused;
|
|
142
148
|
export interface Deployment {
|
|
149
|
+
/**
|
|
150
|
+
* The primary manager: what boot asserted and `/config` announces. Adoption does not require a
|
|
151
|
+
* coin to be on it — see {@link verifyLaunch} — but it is the one manager known wired before any
|
|
152
|
+
* coin arrives, so its wiring is never asked of the chain again.
|
|
153
|
+
*/
|
|
143
154
|
positionManager: `0x${string}`;
|
|
144
155
|
spendGatedCalculator: `0x${string}`;
|
|
145
156
|
/** The signer this gate holds. A launch naming anyone else is not ours to run. */
|
|
146
157
|
signer: `0x${string}`;
|
|
147
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Whether a manager's fee wiring routes to a calculator. {@link checkPositionManagerWiring} is the
|
|
161
|
+
* one implementation; this is its shape, so a test can stand in for the chain.
|
|
162
|
+
*/
|
|
163
|
+
export type WiringCheck = (client: ChainReader, wiring: {
|
|
164
|
+
positionManager: `0x${string}`;
|
|
165
|
+
spendGatedCalculator: `0x${string}`;
|
|
166
|
+
}) => Promise<PositionManagerWiring>;
|
|
167
|
+
/**
|
|
168
|
+
* Remembers which managers are wired to this gate's calculator, so the three wiring reads happen
|
|
169
|
+
* once per manager rather than once per coin.
|
|
170
|
+
*
|
|
171
|
+
* A yes is kept for the life of the process: wiring is a one-time owner action, and un-wiring a
|
|
172
|
+
* manager with live pools would also strand every coin already adopted on it, so nothing is lost
|
|
173
|
+
* by not re-asking. A no is kept a minute — long enough that a coin page polling an unwired
|
|
174
|
+
* manager is not a lever on the RPC, short enough that the owner wiring it up sees the gate follow.
|
|
175
|
+
*/
|
|
176
|
+
export declare class WiringCache {
|
|
177
|
+
private readonly check;
|
|
178
|
+
private readonly now;
|
|
179
|
+
private readonly negativeHoldMs;
|
|
180
|
+
private readonly verdicts;
|
|
181
|
+
private readonly inFlight;
|
|
182
|
+
constructor(check?: WiringCheck, now?: () => number, negativeHoldMs?: number);
|
|
183
|
+
isWired(client: ChainReader, positionManager: `0x${string}`, spendGatedCalculator: `0x${string}`): Promise<PositionManagerWiring>;
|
|
184
|
+
/** A fresh cache that already trusts the primary manager, which boot asserted before any coin arrived. */
|
|
185
|
+
static trusting(positionManager: `0x${string}`): WiringCache;
|
|
186
|
+
/** Record a manager known wired without asking — the primary one, which boot already asserted. */
|
|
187
|
+
trust(positionManager: `0x${string}`, dispatcher?: `0x${string}`): void;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Which PositionManager a coin was launched on, from the coin itself.
|
|
191
|
+
*
|
|
192
|
+
* Two reads: `Memecoin.flaunch()` names the launch ERC721 that minted the coin, and that contract's
|
|
193
|
+
* `positionManager()` names the hook. Both are public state written at launch, so the answer is the
|
|
194
|
+
* coin's and cannot be steered by whoever offers it for adoption. Null when the CONTRACT says no —
|
|
195
|
+
* an address with no code, or one that is not a Flaunch coin, answers `flaunch()` with no data.
|
|
196
|
+
* An RPC that did not answer is not a statement about the coin, so that is thrown to the caller
|
|
197
|
+
* rather than folded into null.
|
|
198
|
+
*/
|
|
199
|
+
export declare function resolvePositionManager(client: ChainReader, memecoin: `0x${string}`): Promise<`0x${string}` | null>;
|
|
148
200
|
export declare function poolIdOf(key: PoolKey): `0x${string}`;
|
|
149
201
|
/**
|
|
150
202
|
* Verify a coin, from the chain.
|
|
@@ -152,11 +204,11 @@ export declare function poolIdOf(key: PoolKey): `0x${string}`;
|
|
|
152
204
|
* Every read is wrapped, because an RPC failure is not a statement about the token. Treating one as
|
|
153
205
|
* "not a game launch" is exactly the mistake described on {@link Refused}.
|
|
154
206
|
*/
|
|
155
|
-
export declare function verifyLaunch(client: ChainReader, deployment: Deployment, memecoin: `0x${string}
|
|
207
|
+
export declare function verifyLaunch(client: ChainReader, deployment: Deployment, memecoin: `0x${string}`, wiring?: WiringCache): Promise<LaunchCheck>;
|
|
156
208
|
/**
|
|
157
209
|
* Verification with a memory, because every coin-page view asks.
|
|
158
210
|
*
|
|
159
|
-
* Unmemoised, each call costs
|
|
211
|
+
* Unmemoised, each call costs seven chain reads against one endpoint from one address — which is a
|
|
160
212
|
* free denial-of-service lever, and public endpoints rate-limit long before a launch does.
|
|
161
213
|
*
|
|
162
214
|
* A positive verdict is cached until the window closes, because a launch that qualifies cannot
|
|
@@ -169,7 +221,13 @@ export declare class Discovery {
|
|
|
169
221
|
private readonly now;
|
|
170
222
|
private readonly verdicts;
|
|
171
223
|
private readonly inFlight;
|
|
172
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Which managers are wired to this gate's calculator, remembered per manager. The primary one is
|
|
226
|
+
* trusted from the start: boot asserted it, and asking again would be the only three reads that
|
|
227
|
+
* could never answer differently.
|
|
228
|
+
*/
|
|
229
|
+
readonly wiring: WiringCache;
|
|
230
|
+
constructor(client: ChainReader, deployment: Deployment, now?: () => number, wiring?: WiringCache);
|
|
173
231
|
verify(memecoin: `0x${string}`): Promise<LaunchCheck>;
|
|
174
232
|
private holdFor;
|
|
175
233
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/chain/discover.ts"],"names":[],"mappings":"AAAA,OAAO,EAA4C,KAAK,YAAY,EAAE,MAAM,MAAM,CAAC;AACnF,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,gCAAgC,CAAC;
|
|
1
|
+
{"version":3,"file":"discover.d.ts","sourceRoot":"","sources":["../../src/chain/discover.ts"],"names":[],"mappings":"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"}
|
package/dist/chain/discover.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { encodeAbiParameters, keccak256, parseAbi } from 'viem';
|
|
2
2
|
import { ETH_SPEND_TOKEN } from '@flayerlabs/gamemode-spec/live';
|
|
3
|
+
import { checkPositionManagerWiring } from './secure.js';
|
|
3
4
|
/**
|
|
4
5
|
* Asking the chain whether a coin is really a game launch, and on what terms.
|
|
5
6
|
*
|
|
@@ -12,11 +13,15 @@ import { ETH_SPEND_TOKEN } from '@flayerlabs/gamemode-spec/live';
|
|
|
12
13
|
* can forge. So adoption needs no API key and no allowlist — anyone may ask, and the chain decides.
|
|
13
14
|
* That single property is what makes third-party games permissionless.
|
|
14
15
|
*
|
|
15
|
-
* A gate serves
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
16
|
+
* A gate serves one calculator and adopts a coin on ANY PositionManager wired to it. The coin
|
|
17
|
+
* names its own manager (`Memecoin.flaunch()` is the launch ERC721, whose `positionManager()` is
|
|
18
|
+
* the hook), and that manager is accepted when its fee wiring routes to the gate's calculator —
|
|
19
|
+
* the same three reads boot makes of the primary manager, made here per manager and cached. There
|
|
20
|
+
* is no list: wiring a new manager to the dispatcher on chain is what approves it. A coin on a
|
|
21
|
+
* manager wired to some OTHER calculator is refused for good — the EIP-712 domain binds every
|
|
22
|
+
* authorisation to the calculator, so a coin this gate cannot sign for must not be given a room
|
|
23
|
+
* by it — and every later read (`poolKey`, `flaunchesAt`, `pairedToken`) is asked of the coin's
|
|
24
|
+
* own manager, never the configured one.
|
|
20
25
|
*/
|
|
21
26
|
const poolKeyComponents = [
|
|
22
27
|
{ name: 'currency0', type: 'address' },
|
|
@@ -25,6 +30,10 @@ const poolKeyComponents = [
|
|
|
25
30
|
{ name: 'tickSpacing', type: 'int24' },
|
|
26
31
|
{ name: 'hooks', type: 'address' },
|
|
27
32
|
];
|
|
33
|
+
/** What a coin knows about its own launch: `flaunch()` is the ERC721 that minted it. */
|
|
34
|
+
const memecoinAbi = parseAbi(['function flaunch() view returns (address)']);
|
|
35
|
+
/** The launch ERC721 (`Flaunch`, `AnyFlaunch`) names the PositionManager that hooks its pools. */
|
|
36
|
+
const flaunchAbi = parseAbi(['function positionManager() view returns (address)']);
|
|
28
37
|
export const positionManagerAbi = [
|
|
29
38
|
{
|
|
30
39
|
type: 'function',
|
|
@@ -53,6 +62,97 @@ const erc20 = parseAbi([
|
|
|
53
62
|
'function decimals() view returns (uint8)',
|
|
54
63
|
]);
|
|
55
64
|
const ZERO_ADDRESS = '0x0000000000000000000000000000000000000000';
|
|
65
|
+
/**
|
|
66
|
+
* Remembers which managers are wired to this gate's calculator, so the three wiring reads happen
|
|
67
|
+
* once per manager rather than once per coin.
|
|
68
|
+
*
|
|
69
|
+
* A yes is kept for the life of the process: wiring is a one-time owner action, and un-wiring a
|
|
70
|
+
* manager with live pools would also strand every coin already adopted on it, so nothing is lost
|
|
71
|
+
* by not re-asking. A no is kept a minute — long enough that a coin page polling an unwired
|
|
72
|
+
* manager is not a lever on the RPC, short enough that the owner wiring it up sees the gate follow.
|
|
73
|
+
*/
|
|
74
|
+
export class WiringCache {
|
|
75
|
+
check;
|
|
76
|
+
now;
|
|
77
|
+
negativeHoldMs;
|
|
78
|
+
verdicts = new Map();
|
|
79
|
+
inFlight = new Map();
|
|
80
|
+
constructor(check = checkPositionManagerWiring, now = Date.now, negativeHoldMs = 60_000) {
|
|
81
|
+
this.check = check;
|
|
82
|
+
this.now = now;
|
|
83
|
+
this.negativeHoldMs = negativeHoldMs;
|
|
84
|
+
}
|
|
85
|
+
async isWired(client, positionManager, spendGatedCalculator) {
|
|
86
|
+
const key = positionManager.toLowerCase();
|
|
87
|
+
const cached = this.verdicts.get(key);
|
|
88
|
+
if (cached && cached.until > this.now())
|
|
89
|
+
return cached.verdict;
|
|
90
|
+
const existing = this.inFlight.get(key);
|
|
91
|
+
if (existing)
|
|
92
|
+
return existing;
|
|
93
|
+
const flight = this.check(client, { positionManager, spendGatedCalculator })
|
|
94
|
+
.then((verdict) => {
|
|
95
|
+
const until = verdict.ok ? Number.POSITIVE_INFINITY : this.now() + this.negativeHoldMs;
|
|
96
|
+
this.verdicts.set(key, { verdict, until });
|
|
97
|
+
return verdict;
|
|
98
|
+
})
|
|
99
|
+
.finally(() => this.inFlight.delete(key));
|
|
100
|
+
this.inFlight.set(key, flight);
|
|
101
|
+
return flight;
|
|
102
|
+
}
|
|
103
|
+
/** A fresh cache that already trusts the primary manager, which boot asserted before any coin arrived. */
|
|
104
|
+
static trusting(positionManager) {
|
|
105
|
+
const cache = new WiringCache();
|
|
106
|
+
cache.trust(positionManager);
|
|
107
|
+
return cache;
|
|
108
|
+
}
|
|
109
|
+
/** Record a manager known wired without asking — the primary one, which boot already asserted. */
|
|
110
|
+
trust(positionManager, dispatcher = ZERO_ADDRESS) {
|
|
111
|
+
this.verdicts.set(positionManager.toLowerCase(), {
|
|
112
|
+
verdict: { ok: true, dispatcher },
|
|
113
|
+
until: Number.POSITIVE_INFINITY,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Which PositionManager a coin was launched on, from the coin itself.
|
|
119
|
+
*
|
|
120
|
+
* Two reads: `Memecoin.flaunch()` names the launch ERC721 that minted the coin, and that contract's
|
|
121
|
+
* `positionManager()` names the hook. Both are public state written at launch, so the answer is the
|
|
122
|
+
* coin's and cannot be steered by whoever offers it for adoption. Null when the CONTRACT says no —
|
|
123
|
+
* an address with no code, or one that is not a Flaunch coin, answers `flaunch()` with no data.
|
|
124
|
+
* An RPC that did not answer is not a statement about the coin, so that is thrown to the caller
|
|
125
|
+
* rather than folded into null.
|
|
126
|
+
*/
|
|
127
|
+
export async function resolvePositionManager(client, memecoin) {
|
|
128
|
+
let flaunch;
|
|
129
|
+
try {
|
|
130
|
+
flaunch = (await client.readContract({ address: memecoin, abi: memecoinAbi, functionName: 'flaunch' }));
|
|
131
|
+
}
|
|
132
|
+
catch (error) {
|
|
133
|
+
if (isMissingFunction(error))
|
|
134
|
+
return null;
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
137
|
+
if (!flaunch || flaunch.toLowerCase() === ZERO_ADDRESS)
|
|
138
|
+
return null;
|
|
139
|
+
let manager;
|
|
140
|
+
try {
|
|
141
|
+
manager = (await client.readContract({
|
|
142
|
+
address: flaunch,
|
|
143
|
+
abi: flaunchAbi,
|
|
144
|
+
functionName: 'positionManager',
|
|
145
|
+
}));
|
|
146
|
+
}
|
|
147
|
+
catch (error) {
|
|
148
|
+
if (isMissingFunction(error))
|
|
149
|
+
return null;
|
|
150
|
+
throw error;
|
|
151
|
+
}
|
|
152
|
+
if (!manager || manager.toLowerCase() === ZERO_ADDRESS)
|
|
153
|
+
return null;
|
|
154
|
+
return manager;
|
|
155
|
+
}
|
|
56
156
|
export function poolIdOf(key) {
|
|
57
157
|
return keccak256(encodeAbiParameters([{ type: 'address' }, { type: 'address' }, { type: 'uint24' }, { type: 'int24' }, { type: 'address' }], [key.currency0, key.currency1, key.fee, key.tickSpacing, key.hooks]));
|
|
58
158
|
}
|
|
@@ -63,11 +163,28 @@ const refuse = (code, retryable) => ({ ok: false, code, retryable });
|
|
|
63
163
|
* Every read is wrapped, because an RPC failure is not a statement about the token. Treating one as
|
|
64
164
|
* "not a game launch" is exactly the mistake described on {@link Refused}.
|
|
65
165
|
*/
|
|
66
|
-
export async function verifyLaunch(client, deployment, memecoin) {
|
|
166
|
+
export async function verifyLaunch(client, deployment, memecoin, wiring = WiringCache.trusting(deployment.positionManager)) {
|
|
167
|
+
// The coin's own manager first. A coin the protocol has never heard of has no `flaunch()`, which
|
|
168
|
+
// is still "not yet": the coin page loads the instant a launch is submitted, before the chain has
|
|
169
|
+
// caught up, and that must not be remembered as "no".
|
|
170
|
+
let positionManager;
|
|
171
|
+
try {
|
|
172
|
+
positionManager = await resolvePositionManager(client, memecoin);
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
return refuse('launch.unreadable', true);
|
|
176
|
+
}
|
|
177
|
+
if (!positionManager)
|
|
178
|
+
return refuse('launch.not_flaunched', true);
|
|
179
|
+
// Approval is a fact about the chain: is this manager's fee wiring routed to OUR calculator? A
|
|
180
|
+
// manager wired elsewhere is another gate's, permanently — no amount of waiting rewires it.
|
|
181
|
+
const wired = await wiring.isWired(client, positionManager, deployment.spendGatedCalculator);
|
|
182
|
+
if (!wired.ok)
|
|
183
|
+
return refuse('launch.unapproved_position_manager', false);
|
|
67
184
|
let poolKey;
|
|
68
185
|
try {
|
|
69
186
|
poolKey = (await client.readContract({
|
|
70
|
-
address:
|
|
187
|
+
address: positionManager,
|
|
71
188
|
abi: positionManagerAbi,
|
|
72
189
|
functionName: 'poolKey',
|
|
73
190
|
args: [memecoin],
|
|
@@ -83,9 +200,8 @@ export async function verifyLaunch(client, deployment, memecoin) {
|
|
|
83
200
|
const poolId = poolIdOf(poolKey);
|
|
84
201
|
let settings;
|
|
85
202
|
let trusted;
|
|
86
|
-
let flaunchesAt;
|
|
87
203
|
try {
|
|
88
|
-
[settings, trusted
|
|
204
|
+
[settings, trusted] = (await Promise.all([
|
|
89
205
|
client.readContract({
|
|
90
206
|
address: deployment.spendGatedCalculator,
|
|
91
207
|
abi: spendGatedAbi,
|
|
@@ -98,17 +214,27 @@ export async function verifyLaunch(client, deployment, memecoin) {
|
|
|
98
214
|
functionName: 'trustedPoolKeySigner',
|
|
99
215
|
args: [poolId],
|
|
100
216
|
}),
|
|
101
|
-
client.readContract({
|
|
102
|
-
address: deployment.positionManager,
|
|
103
|
-
abi: positionManagerAbi,
|
|
104
|
-
functionName: 'flaunchesAt',
|
|
105
|
-
args: [poolId],
|
|
106
|
-
}),
|
|
107
217
|
]));
|
|
108
218
|
}
|
|
109
219
|
catch {
|
|
110
220
|
return refuse('launch.unreadable', true);
|
|
111
221
|
}
|
|
222
|
+
// The window's open is the manager's to report. A manager that is wired but has no
|
|
223
|
+
// `flaunchesAt` is a generation this gate has no round model for — a permanent fact about the
|
|
224
|
+
// contract, not an outage, so it is refused as unsupported rather than as unreadable and retried
|
|
225
|
+
// forever.
|
|
226
|
+
let flaunchesAt;
|
|
227
|
+
try {
|
|
228
|
+
flaunchesAt = (await client.readContract({
|
|
229
|
+
address: positionManager,
|
|
230
|
+
abi: positionManagerAbi,
|
|
231
|
+
functionName: 'flaunchesAt',
|
|
232
|
+
args: [poolId],
|
|
233
|
+
}));
|
|
234
|
+
}
|
|
235
|
+
catch (error) {
|
|
236
|
+
return refuse(isMissingFunction(error) ? 'launch.unsupported_position_manager' : 'launch.unreadable', !isMissingFunction(error));
|
|
237
|
+
}
|
|
112
238
|
const [enabled, walletCap, , endsAt] = settings;
|
|
113
239
|
const [signer, signerEnabled] = trusted;
|
|
114
240
|
if (!enabled)
|
|
@@ -123,7 +249,7 @@ export async function verifyLaunch(client, deployment, memecoin) {
|
|
|
123
249
|
const closesAt = Number(endsAt) * 1000;
|
|
124
250
|
if (closesAt <= Date.now())
|
|
125
251
|
return refuse('launch.already_over', false);
|
|
126
|
-
const spendToken = await resolveSpendToken(client,
|
|
252
|
+
const spendToken = await resolveSpendToken(client, positionManager, memecoin, poolKey, poolId);
|
|
127
253
|
if (!spendToken)
|
|
128
254
|
return refuse('launch.paired_unreadable', true);
|
|
129
255
|
let name = '';
|
|
@@ -150,8 +276,34 @@ export async function verifyLaunch(client, deployment, memecoin) {
|
|
|
150
276
|
name,
|
|
151
277
|
symbol,
|
|
152
278
|
spendToken,
|
|
279
|
+
positionManager,
|
|
153
280
|
};
|
|
154
281
|
}
|
|
282
|
+
/**
|
|
283
|
+
* Did a read fail because the contract has no such function, rather than because the chain did
|
|
284
|
+
* not answer? viem reports the former as a call that returned no data or reverted at the
|
|
285
|
+
* contract (`ContractFunctionZeroDataError`, `ContractFunctionRevertedError`); a transport
|
|
286
|
+
* failure looks nothing like it, and a `view` that exists does not revert on a pool id.
|
|
287
|
+
*/
|
|
288
|
+
function isMissingFunction(error) {
|
|
289
|
+
const seen = new Set();
|
|
290
|
+
let current = error;
|
|
291
|
+
while (current && typeof current === 'object' && !seen.has(current)) {
|
|
292
|
+
seen.add(current);
|
|
293
|
+
const name = current.name;
|
|
294
|
+
if (name === 'ContractFunctionZeroDataError' ||
|
|
295
|
+
name === 'AbiDecodingZeroDataError' ||
|
|
296
|
+
name === 'ContractFunctionRevertedError') {
|
|
297
|
+
return true;
|
|
298
|
+
}
|
|
299
|
+
const message = current.message;
|
|
300
|
+
if (typeof message === 'string' && /returned no data|zero data|function (selector )?was not (recognized|found)/i.test(message)) {
|
|
301
|
+
return true;
|
|
302
|
+
}
|
|
303
|
+
current = current.cause;
|
|
304
|
+
}
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
155
307
|
/**
|
|
156
308
|
* Which token this pool's spend is measured in.
|
|
157
309
|
*
|
|
@@ -162,11 +314,11 @@ export async function verifyLaunch(client, deployment, memecoin) {
|
|
|
162
314
|
* is the coin. Decimals are load-bearing, so unlike the coin's cosmetic name an unreadable token
|
|
163
315
|
* is a refusal — retryable, because an RPC blip is not a statement about the token.
|
|
164
316
|
*/
|
|
165
|
-
async function resolveSpendToken(client,
|
|
317
|
+
async function resolveSpendToken(client, positionManager, memecoin, poolKey, poolId) {
|
|
166
318
|
let paired;
|
|
167
319
|
try {
|
|
168
320
|
paired = (await client.readContract({
|
|
169
|
-
address:
|
|
321
|
+
address: positionManager,
|
|
170
322
|
abi: positionManagerAbi,
|
|
171
323
|
functionName: 'pairedToken',
|
|
172
324
|
args: [poolId],
|
|
@@ -191,7 +343,7 @@ async function resolveSpendToken(client, deployment, memecoin, poolKey, poolId)
|
|
|
191
343
|
/**
|
|
192
344
|
* Verification with a memory, because every coin-page view asks.
|
|
193
345
|
*
|
|
194
|
-
* Unmemoised, each call costs
|
|
346
|
+
* Unmemoised, each call costs seven chain reads against one endpoint from one address — which is a
|
|
195
347
|
* free denial-of-service lever, and public endpoints rate-limit long before a launch does.
|
|
196
348
|
*
|
|
197
349
|
* A positive verdict is cached until the window closes, because a launch that qualifies cannot
|
|
@@ -204,10 +356,18 @@ export class Discovery {
|
|
|
204
356
|
now;
|
|
205
357
|
verdicts = new Map();
|
|
206
358
|
inFlight = new Map();
|
|
207
|
-
|
|
359
|
+
/**
|
|
360
|
+
* Which managers are wired to this gate's calculator, remembered per manager. The primary one is
|
|
361
|
+
* trusted from the start: boot asserted it, and asking again would be the only three reads that
|
|
362
|
+
* could never answer differently.
|
|
363
|
+
*/
|
|
364
|
+
wiring;
|
|
365
|
+
constructor(client, deployment, now = Date.now, wiring = new WiringCache(checkPositionManagerWiring, now)) {
|
|
208
366
|
this.client = client;
|
|
209
367
|
this.deployment = deployment;
|
|
210
368
|
this.now = now;
|
|
369
|
+
this.wiring = wiring;
|
|
370
|
+
this.wiring.trust(deployment.positionManager);
|
|
211
371
|
}
|
|
212
372
|
async verify(memecoin) {
|
|
213
373
|
const key = memecoin.toLowerCase();
|
|
@@ -219,7 +379,7 @@ export class Discovery {
|
|
|
219
379
|
const existing = this.inFlight.get(key);
|
|
220
380
|
if (existing)
|
|
221
381
|
return existing;
|
|
222
|
-
const flight = verifyLaunch(this.client, this.deployment, memecoin)
|
|
382
|
+
const flight = verifyLaunch(this.client, this.deployment, memecoin, this.wiring)
|
|
223
383
|
.then((verdict) => {
|
|
224
384
|
this.verdicts.set(key, { verdict, until: this.now() + this.holdFor(verdict) });
|
|
225
385
|
return verdict;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/chain/discover.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"discover.js","sourceRoot":"","sources":["../../src/chain/discover.ts"],"names":[],"mappings":"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"}
|