@indiegems/gem-web-sdk 23.1.3 → 23.2.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.
@@ -2,7 +2,7 @@
2
2
  "schema_version": 2,
3
3
  "source": {
4
4
  "repo": "IndieGems/gem-web-sdk",
5
- "version": "23.1.3"
5
+ "version": "23.2.0"
6
6
  },
7
7
  "entries": [
8
8
  {
@@ -397,7 +397,7 @@
397
397
  "group": "config",
398
398
  "signature": "rewarded_placements?: SnapshotRewardedPlacement[]",
399
399
  "documented": true,
400
- "summary": "Your rewarded placements — what pressing a rewarded button grants. An\narray, one row per placement, each naming itself in `placement`, with its\n`grants`, the caps the platform enforces on it (`max_per_day`,\n`cooldown_seconds`, `max_held`) and what happens where no ad serves\n(`without_ads`, which is `nothing` when the config leaves it out).\n\nRead it to LABEL your button — \"+1 Revive\" — never to decide a reward. A\ngrant is an `item_grant`, with a `quantity` of the item its\n`item_definition_id` names, or a `currency_grant`, with an `amount` of the\ncurrency its `currency_id` names; the word on the button is that\ndefinition's `display_name`, from [GameConfig.item](api-reference-game.md#gameconfig-item) or\n[GameConfig.currency](api-reference-game.md#gameconfig-currency):\n\n```js\nconst row = config?.rewarded_placements?.find((p) => p.placement === 'classic_revive');\nconst grant = row?.grants[0];\nconst label =\n grant?.type === 'item_grant'\n ? `+${grant.quantity} ${config.item(grant.item_definition_id)?.display_name ?? ''}`\n : grant?.type === 'currency_grant'\n ? `+${grant.amount} ${config.currency(grant.currency_id)?.display_name ?? ''}`\n : undefined;\n```\n\nWhether an ask grants anything is the platform's decision, made against\nthis config server-side; the grant lands on your game's inventory, and\nre-reading `gem.me.inventory` is the only way to learn that it did. Whether\nthe button could pay right now is [AdsApi.rewardedStatus](api-reference-game.md#adsapi-rewardedstatus).\n\nAbsent when your game declares none.",
400
+ "summary": "Your rewarded placements — what pressing a rewarded button grants. An\narray, one row per placement, each naming itself in `placement`, with its\n`grants`, the caps the platform enforces on it (`max_per_day`,\n`cooldown_seconds`, `max_held`) and what happens where no ad serves\n(`without_ads`, which is `nothing` when the config leaves it out).\n\nRead it to LABEL your button — \"+1 Revive\" — never to decide a reward. A\ngrant is an `item_grant`, with a `quantity` of the item its\n`item_definition_id` names, or a `currency_grant`, with an `amount` of the\ncurrency its `currency_id` names; the word on the button is that\ndefinition's `display_name`, from [GameConfig.item](api-reference-game.md#gameconfig-item) or\n[GameConfig.currency](api-reference-game.md#gameconfig-currency):\n\n```js\nconst row = config?.rewarded_placements?.find((p) => p.placement === 'classic_revive');\nconst grant = row?.grants[0];\nconst label =\n grant?.type === 'item_grant'\n ? `+${grant.quantity} ${config.item(grant.item_definition_id)?.display_name ?? ''}`\n : grant?.type === 'currency_grant'\n ? `+${grant.amount} ${config.currency(grant.currency_id)?.display_name ?? ''}`\n : undefined;\n```\n\nWhether an ask grants anything is the platform's decision, made against\nthis config server-side; the grant lands on your game's inventory, and\nre-reading `gem.me.inventory` is the only way to learn that it did. Whether\nthe button could pay right now is [AdsApi.rewardedStatus](api-reference-game.md#adsapi-rewardedstatus).\n\nA row may also carry `platform_prices`, the Coin and Gem prices that unlock\nit beside the ad, and `ad: false` when only a price does (`ad` is absent\notherwise, which means the ad unlocks it). Both are what you declared, not\nwhat is offered now: label the button from `rewardedStatus`'s\n`adGrantable` and `options`, which say what this platform serves.\n\nAbsent when your game declares none.",
401
401
  "deprecated": null,
402
402
  "params": [],
403
403
  "returns": null,
@@ -4170,7 +4170,7 @@
4170
4170
  "group": "ads",
4171
4171
  "signature": "rewardedStatus(placement: string): Promise<RewardedStatus>",
4172
4172
  "documented": true,
4173
- "summary": "Whether a rewarded placement could pay right now, so you can decide whether\nto draw its button. **It never says whether an ad will play.**\n\nThe answer comes from your own `rewarded_placements` config — its daily\ncap, cooldown and `max_held` — applied to this player's use of it, as the\nplatform holds them. Nothing in it describes the player. `grantable: true`\nmeans the platform would grant if an ad is watched or, where no ad serves,\nunder the placement's `without_ads: grant`; a player can still press the\nbutton and get `no_ad`, for reasons your game is not told.\n\nNOTHING REJECTS, like everything else on `gem.ads`. Without a play token,\nwhen the read fails or takes longer than ten seconds, or for a `placement`\noutside the grammar [AdRequest.placement](api-reference-game.md#adrequest-placement) documents, it resolves not\ndeclared and not grantable, with no `resetsAt`, and the reason goes to your\n`onError` handler.\n\nIt is a read of the platform, so call it when you draw the button — on a\nresults or death screen — not every frame. Calls for one placement that\noverlap share one request. Draw the rest of the screen first rather than\nholding it on this answer.\n\n⚠️ It grants nothing and reserves nothing. The reward is granted by the\nplatform when the player asks with `requestAd`; re-read `gem.me.inventory`\nafter that ask settles, whatever it settled as.",
4173
+ "summary": "Whether a rewarded placement could pay right now, so you can decide whether\nto draw its button. **It never says whether an ad will play.**\n\nThe answer comes from your own `rewarded_placements` config — its daily\ncap, cooldown and `max_held` — applied to this player's use of it, as the\nplatform holds them. Nothing in it describes the player. `grantable: true`\nmeans the platform would grant if an ad is watched or, where no ad serves,\nunder the placement's `without_ads: grant`; a player can still press the\nbutton and get `no_ad`, for reasons your game is not told.\n\nA placement your config also prices in Coins or Gems (`platform_prices`)\ncarries those prices in `options`, where the platform lets players pay for\none, and `adGrantable` says whether the ad itself could pay. Label your\nbutton from both: name the ad only when `adGrantable` is `true`, and each\nprice in `options`. The Arcade then shows the player those choices when\nthey press, and the press answers and is re-read exactly as an ad's is.\n\nNOTHING REJECTS, like everything else on `gem.ads`. Without a play token,\nwhen the read fails or takes longer than ten seconds, or for a `placement`\noutside the grammar [AdRequest.placement](api-reference-game.md#adrequest-placement) documents, it resolves not\ndeclared and not grantable, with no `resetsAt`, and the reason goes to your\n`onError` handler.\n\nIt is a read of the platform, so call it when you draw the button — on a\nresults or death screen — not every frame. Calls for one placement that\noverlap share one request. Draw the rest of the screen first rather than\nholding it on this answer.\n\n⚠️ It grants nothing and reserves nothing. The reward is granted by the\nplatform when the player asks with `requestAd`; re-read `gem.me.inventory`\nafter that ask settles, whatever it settled as.",
4174
4174
  "deprecated": null,
4175
4175
  "params": [
4176
4176
  {
@@ -4191,6 +4191,70 @@
4191
4191
  }
4192
4192
  ]
4193
4193
  },
4194
+ {
4195
+ "id": "RewardedOption",
4196
+ "name": "RewardedOption",
4197
+ "anchor": "rewardedoption",
4198
+ "group": "ads",
4199
+ "signature": "interface RewardedOption",
4200
+ "documented": true,
4201
+ "summary": "One price that also unlocks a rewarded placement, in\n[RewardedStatus.options](api-reference-game.md#rewardedstatus-options): what your config's `platform_prices` set for\nit, as the platform serves it. Label your button from it (\"5 Gems\").\n\nIt says nothing about the player: not their balance, and not whether they\ncan afford it. The Arcade shows them that when they press.",
4202
+ "deprecated": null,
4203
+ "params": [],
4204
+ "returns": null,
4205
+ "throws": null,
4206
+ "example": null,
4207
+ "defaultValue": null,
4208
+ "guides": []
4209
+ },
4210
+ {
4211
+ "id": "RewardedOption.kind",
4212
+ "name": "kind",
4213
+ "anchor": "rewardedoption-kind",
4214
+ "group": "ads",
4215
+ "signature": "readonly kind: \"coins\" | \"gems\"",
4216
+ "documented": true,
4217
+ "summary": "Which platform currency: `coins` (Coins, `ARCADE_TICKETS`) or `gems`\n(Gems, `GEMS`).",
4218
+ "deprecated": null,
4219
+ "params": [],
4220
+ "returns": null,
4221
+ "throws": null,
4222
+ "example": null,
4223
+ "defaultValue": null,
4224
+ "guides": []
4225
+ },
4226
+ {
4227
+ "id": "RewardedOption.currencyId",
4228
+ "name": "currencyId",
4229
+ "anchor": "rewardedoption-currencyid",
4230
+ "group": "ads",
4231
+ "signature": "readonly currencyId: string",
4232
+ "documented": true,
4233
+ "summary": "The platform currency's id, as your config's `platform_prices` resolved it.",
4234
+ "deprecated": null,
4235
+ "params": [],
4236
+ "returns": null,
4237
+ "throws": null,
4238
+ "example": null,
4239
+ "defaultValue": null,
4240
+ "guides": []
4241
+ },
4242
+ {
4243
+ "id": "RewardedOption.price",
4244
+ "name": "price",
4245
+ "anchor": "rewardedoption-price",
4246
+ "group": "ads",
4247
+ "signature": "readonly price: number",
4248
+ "documented": true,
4249
+ "summary": "The price, a positive whole number of the currency.",
4250
+ "deprecated": null,
4251
+ "params": [],
4252
+ "returns": null,
4253
+ "throws": null,
4254
+ "example": null,
4255
+ "defaultValue": null,
4256
+ "guides": []
4257
+ },
4194
4258
  {
4195
4259
  "id": "RewardedStatus",
4196
4260
  "name": "RewardedStatus",
@@ -4230,7 +4294,39 @@
4230
4294
  "group": "ads",
4231
4295
  "signature": "readonly grantable: boolean",
4232
4296
  "documented": true,
4233
- "summary": "Whether pressing your button could pay right now: the platform would grant\nthe reward if an ad is watched or, where no ad serves, under the\nplacement's `without_ads: grant`.\n\n**Not a promise that an ad will play, and not a promise of a reward.** It\nis `false` whenever a cap is spent, a cooldown is running, the player holds\n`max_held`, rewarded is off on this channel, or the arcade running your\ngame does not take ad requests at all.",
4297
+ "summary": "Whether pressing your button could pay right now: the platform would grant\nthe reward if an ad is watched or, where no ad serves, under the\nplacement's `without_ads: grant` — or, where [RewardedStatus.options](api-reference-game.md#rewardedstatus-options)\nis present, if the player pays one of its prices.\n\n**Not a promise that an ad will play, and not a promise of a reward.** For\nthe ad, it is `false` whenever a cap is spent, a cooldown is running, the\nplayer holds `max_held`, rewarded is off on this channel, or the arcade\nrunning your game does not take ad requests at all. The cap, the cooldown\nand `max_held` limit the ad only: a placement with `options` stays\ngrantable through them, because the player can still pay. It never says\nwhether the player can afford a price.",
4298
+ "deprecated": null,
4299
+ "params": [],
4300
+ "returns": null,
4301
+ "throws": null,
4302
+ "example": null,
4303
+ "defaultValue": null,
4304
+ "guides": []
4305
+ },
4306
+ {
4307
+ "id": "RewardedStatus.adGrantable",
4308
+ "name": "adGrantable",
4309
+ "anchor": "rewardedstatus-adgrantable",
4310
+ "group": "ads",
4311
+ "signature": "readonly adGrantable: boolean",
4312
+ "documented": true,
4313
+ "summary": "Whether the AD could pay right now: [RewardedStatus.grantable](api-reference-game.md#rewardedstatus-grantable) for\nthe ad alone, leaving out the prices. Name the ad on your button only when\nthis is `true`.\n\nThe same as `grantable` for a placement with no `options`. `false` for a\nplacement whose config switches the ad off (`ad: false`) where the\nplatform lets players pay for it, and on every answer where `grantable` is.",
4314
+ "deprecated": null,
4315
+ "params": [],
4316
+ "returns": null,
4317
+ "throws": null,
4318
+ "example": null,
4319
+ "defaultValue": null,
4320
+ "guides": []
4321
+ },
4322
+ {
4323
+ "id": "RewardedStatus.options",
4324
+ "name": "options",
4325
+ "anchor": "rewardedstatus-options",
4326
+ "group": "ads",
4327
+ "signature": "readonly options?: readonly RewardedOption[]",
4328
+ "documented": true,
4329
+ "summary": "The Coin and Gem prices that also unlock the placement, from your config's\n`platform_prices`, at most one per currency.\n\nABSENT — no key — for a placement with no prices, on any answer where\n`declared` is `false`, and wherever the platform does not yet let players\npay for a placement: there your prices are not offered and the placement\nunlocks by its ad alone. Nothing here says what the player holds.",
4234
4330
  "deprecated": null,
4235
4331
  "params": [],
4236
4332
  "returns": null,
package/docs/changelog.md CHANGED
@@ -16,6 +16,18 @@ Its entries are grouped under up to five headings:
16
16
  - **Rebuild**: a type changed. Recompile against the new version; code that compiles today keeps compiling unless the entry says otherwise.
17
17
  - **New capability**: something a game can now do. Nothing changes unless you use it.
18
18
 
19
+ ## 23.2.0
20
+
21
+ *Written from the API facts alone; no summary was generated for this release.*
22
+
23
+ Upgrading from 23.1.3. Impact: none.
24
+
25
+ ### New capability
26
+
27
+ - RewardedOption was added.
28
+ - RewardedStatus.adGrantable was added.
29
+ - RewardedStatus.options was added.
30
+
19
31
  ## 23.1.3
20
32
 
21
33
  Upgrading from 23.1.2. Impact: none.
@@ -50,7 +50,7 @@ either way.
50
50
  ```jsonc
51
51
  // package.json
52
52
  "dependencies": {
53
- "@indiegems/gem-web-sdk": "23.1.3"
53
+ "@indiegems/gem-web-sdk": "23.2.0"
54
54
  }
55
55
  ```
56
56
 
@@ -48,8 +48,8 @@
48
48
  },
49
49
  {
50
50
  "file": "changelog.md",
51
- "sha256": "e6195c6d12e52535a21a4a3291268a82a445b85e6a76f0049b981ff9ab374232",
52
- "updated": "2026-11-09T03:45:00Z"
51
+ "sha256": "819160e36c0258c34aa3e8b06ea0f1e26a50bcc83c5919780de2b33f4fac1cd9",
52
+ "updated": "2026-11-09T16:19:51Z"
53
53
  },
54
54
  {
55
55
  "file": "daily-challenges.md",
@@ -78,8 +78,8 @@
78
78
  },
79
79
  {
80
80
  "file": "getting-started.md",
81
- "sha256": "aaed9165f80ea79b32eae8509dc2ef0af436b3e3df1d23cac30941c8268ee022",
82
- "updated": "2026-11-09T03:45:00Z"
81
+ "sha256": "763113c6da4ae1d154ba655e44e87f32912a66ea7db40a61dca9c17f51fcc234",
82
+ "updated": "2026-11-09T16:19:51Z"
83
83
  },
84
84
  {
85
85
  "file": "graphics-route.md",
@@ -123,8 +123,8 @@
123
123
  },
124
124
  {
125
125
  "file": "rewarded-ads.md",
126
- "sha256": "81b421d4bde3f71b40c7a5a173e6a2c114a315215a11491e488872ff9e1909dc",
127
- "updated": "2026-11-07T16:40:01Z"
126
+ "sha256": "f632d54aa605b34dc071b59d49e7ecfd35ab95eb6f601885ceb0d3d6fc41a949",
127
+ "updated": "2026-11-09T15:28:20Z"
128
128
  },
129
129
  {
130
130
  "file": "room-shapes.md",
@@ -143,8 +143,8 @@
143
143
  },
144
144
  {
145
145
  "file": "server-bundles.md",
146
- "sha256": "3274318b99daed546ee192381e40962c9e1e62436cbf4edfb61340548d6dc493",
147
- "updated": "2026-11-09T03:45:00Z"
146
+ "sha256": "b712e407e79482f1edc596ebcaab00852429fbaacebb05d04a2a2f9cbe1f5b9c",
147
+ "updated": "2026-11-09T16:19:51Z"
148
148
  },
149
149
  {
150
150
  "file": "serverless-functions-js.md",
@@ -111,6 +111,8 @@ rewarded_placements:
111
111
  | `max_held` | No grant while the player already holds at least this many of the granted item. 1 to 100, and only on a placement whose grants are all items. |
112
112
  | `without_ads` | **Optional:** `grant` or `nothing`, and `nothing` when you leave it out. What a press gets when no ad plays: where no ad serves your channel at all, and where one does but no ad was available for this press or it failed to play (§8). `grant` pays the reward with no ad, within your caps, so write it out only for a reward that is fine to give free. |
113
113
  | `allowance_currency_slug` | Optional: one of your own currencies that each grant also spends 1 of. Use it when another path in your game must share the same daily cap. It must not be `client_writable` and must have `transfer_policy: none`. A grant is refused while it is empty (§3). ⚠️ For an allowance your game grants per use, put it in a bucket that never resets (`reset_interval: never`) for now, even though the upload warns `rewarded_placement_allowance_no_reset` (below). |
114
+ | `ad` | **Optional:** `true` or `false`, and `true` when you leave it out. Whether watching an ad unlocks the placement. Write `false` only beside `platform_prices`, for a placement a price alone unlocks. |
115
+ | `platform_prices` | **Optional:** Coin and Gem prices that also unlock the placement, beside the ad or instead of it, written as an item's prices are. Leave it out for none. See [Coins and Gems beside the ad](#coins-and-gems-beside-the-ad), below. |
114
116
 
115
117
  ⚠️ **Until a gem-api fix ships, an allowance in a resetting bucket refuses a player's first
116
118
  press.** A grant that creates the player's balance of the allowance currency is not stamped with
@@ -170,6 +172,60 @@ pays without one. If both said `grant`, the bigger reward would cost the player
170
172
  everyone would press that button. Leaving it out of the bigger one, which is `nothing`, keeps it a
171
173
  reward for watching.
172
174
 
175
+ ### Coins and Gems beside the ad
176
+
177
+ A placement can also be unlocked for the player's **Coins** (`ARCADE_TICKETS`) or **Gems** (`GEMS`),
178
+ beside its ad or instead of it. Give it `platform_prices`, the same shape an item's prices take,
179
+ at most one per currency, each a positive whole number:
180
+
181
+ ```yaml
182
+ rewarded_placements:
183
+ - placement: classic_revive
184
+ grants:
185
+ - { type: item_grant, item_definition_slug: revive_token, quantity: 1 }
186
+ max_per_day: 5 # limits the ad only
187
+ platform_prices:
188
+ - { currency: ARCADE_TICKETS, price: 50 } # 50 Coins
189
+ - { currency: GEMS, price: 5 } # 5 Gems
190
+ - placement: skip_level
191
+ grants:
192
+ - { type: item_grant, item_definition_slug: level_skip, quantity: 1 }
193
+ ad: false # a price alone unlocks this one
194
+ platform_prices:
195
+ - { currency: GEMS, price: 10 }
196
+ ```
197
+
198
+ Your game asks exactly as it does for an ad: `requestAd` from the press (§3), then re-read your
199
+ inventory. The Arcade, not your game, shows the player the choices that press has: a chooser when
200
+ there are several, such as **Watch an ad**, **50 Coins** and **5 Gems**, or a confirmation when a
201
+ price is the only one. A price the player cannot afford is shown but cannot be picked. Paying takes
202
+ the price from the player's wallet and grants the reward in one step: never the reward without the
203
+ payment, never charged twice, and the payment given back if the reward cannot be granted. Nothing
204
+ is bought with real money here. The answer is `shown` whenever the Arcade put a choice up, whatever
205
+ the player then did, so **branch on your inventory, never on the outcome**, as for an ad.
206
+
207
+ - **Your caps limit the ad only.** `max_per_day`, `cooldown_seconds`, `max_held` and
208
+ `allowance_currency_slug` decide when the ad can pay. The prices stay on offer when the ad
209
+ cannot, and a paid unlock does not count toward them. Only the player's balance limits how often
210
+ they pay, so price the reward for that. The grant still refuses a reward that would not fit
211
+ (a full stack, say), and the payment is then given back.
212
+ - **Not with `without_ads: grant`,** which would give the reward free and make the price pointless.
213
+ The upload refuses it, and `ad: false` with no `platform_prices` too, since then nothing unlocks
214
+ the placement.
215
+ - **Each currency's spend scope applies,** as it does to an item's price
216
+ ([`inventory-and-catalogs.md`](inventory-and-catalogs.md#what-coins-and-gems-may-buy-the-spend-scope)):
217
+ where Coins may price cosmetics only, a Coin price on a placement that grants anything else is
218
+ refused. Gems may price any placement. `gemctl platform config` lists which currencies your
219
+ game may price in, and each one's spend scope: author against it, never against a list you
220
+ remember.
221
+ - **A placement's own prices do not make its reward "sold for a platform currency"** in §1's sense,
222
+ so the ad keeps serving beside them as it did before.
223
+
224
+ ⚠️ **The upload warns `rewarded_paid_unlocks_not_live` while the platform does not let players pay
225
+ for a placement yet.** Until then your prices are not offered, the placement unlocks by its ad
226
+ alone, `ad: false` included, and `rewardedStatus` carries no `options` (§5). Nothing in your game
227
+ needs to change when it goes live: draw the button from `rewardedStatus` and it follows.
228
+
173
229
  ## 3. Ask from the press, then re-read
174
230
 
175
231
  ```js
@@ -342,14 +398,32 @@ const status = await gem.ads.rewardedStatus('classic_revive');
342
398
  watchAdButton.hidden = !status.grantable;
343
399
  ```
344
400
 
345
- | field | what it says |
346
- | ------------------ | -------------------------------------------------------------------------- |
347
- | `declared` | the config promoted to the channel being played names this placement |
348
- | `grantable` | pressing the button could pay right now — **not** that an ad will play |
349
- | `remainingToday` | grants left today under the daily cap; absent when the placement has none |
350
- | `nextEligibleAt` | when a running cooldown ends, in epoch milliseconds; absent when none runs |
351
- | `heldLimitReached` | the player already holds the placement's `max_held` — spend one first |
352
- | `resetsAt` | when today's count resets, the next 00:00 UTC, in epoch milliseconds |
401
+ **For a placement with prices** (§2), `grantable` is `true` when the ad could pay **or** a price
402
+ could, so the button stays up through the ad's caps. Label it from the answer: name the ad only
403
+ when `adGrantable` is `true`, and each price in `options`, whose `kind` is `coins` or `gems`.
404
+ Neither says what the player holds; the Arcade shows that when they press. Both are in SDK
405
+ releases after 23.1.3.
406
+
407
+ ```js
408
+ const status = await gem.ads.rewardedStatus('classic_revive');
409
+ const ways = [
410
+ ...(status.adGrantable ? ['watch an ad'] : []),
411
+ ...(status.options ?? []).map((o) => `${o.price} ${o.kind === 'coins' ? 'Coins' : 'Gems'}`),
412
+ ];
413
+ reviveButton.textContent = `Revive: ${ways.join(' or ')}`; // "Revive: watch an ad or 5 Gems"
414
+ reviveButton.hidden = !status.grantable;
415
+ ```
416
+
417
+ | field | what it says |
418
+ | ------------------ | ------------------------------------------------------------------------------------------ |
419
+ | `declared` | the config promoted to the channel being played names this placement |
420
+ | `grantable` | pressing the button could pay right now — **not** that an ad will play |
421
+ | `adGrantable` | the ad itself could pay right now: `grantable` without the prices |
422
+ | `options` | the Coin and Gem prices on offer, each `{ kind, currencyId, price }`; absent when none are |
423
+ | `remainingToday` | grants left today under the daily cap; absent when the placement has none |
424
+ | `nextEligibleAt` | when a running cooldown ends, in epoch milliseconds; absent when none runs |
425
+ | `heldLimitReached` | the player already holds the placement's `max_held` — spend one first |
426
+ | `resetsAt` | when today's count resets, the next 00:00 UTC, in epoch milliseconds |
353
427
 
354
428
  Without a play token, when the read fails or takes longer than ten seconds, or for a placement
355
429
  outside the grammar, it answers not declared and not grantable with no `resetsAt`, and the reason
@@ -80,8 +80,8 @@ To check the download yourself: the package npm serves is, byte for byte, the fi
80
80
  also publishes on its download host, with the hash beside it:
81
81
 
82
82
  ```bash
83
- curl -fsSL -O https://downloads.gemarcade.com/sdk/v23.1.3/gem-web-sdk.tgz
84
- curl -fsSL https://downloads.gemarcade.com/sdk/v23.1.3/gem-web-sdk.tgz.sri
83
+ curl -fsSL -O https://downloads.gemarcade.com/sdk/v23.2.0/gem-web-sdk.tgz
84
+ curl -fsSL https://downloads.gemarcade.com/sdk/v23.2.0/gem-web-sdk.tgz.sri
85
85
  openssl dgst -sha384 -binary gem-web-sdk.tgz | openssl base64 -A
86
86
  ```
87
87
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@indiegems/gem-web-sdk",
3
- "version": "23.1.3",
3
+ "version": "23.2.0",
4
4
  "description": "postMessage bridge contract between gem-web and browser-playable games",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",