@indiegems/gem-web-sdk 21.1.1 → 22.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sdk.d.ts CHANGED
@@ -1497,6 +1497,7 @@ declare class ProfilesApi {
1497
1497
  }
1498
1498
  interface FunctionInvokeOptions {
1499
1499
  readonly signal?: AbortSignal;
1500
+ readonly cueId?: string;
1500
1501
  }
1501
1502
  interface FunctionResult {
1502
1503
  readonly bytes: Uint8Array;
@@ -1520,6 +1521,7 @@ declare class FunctionsApi {
1520
1521
  #private;
1521
1522
  constructor(invoke: (body: Uint8Array, options?: {
1522
1523
  signal?: AbortSignal;
1524
+ cue_id?: string;
1523
1525
  }) => Promise<BytesResponse>);
1524
1526
  invoke(input: unknown, options?: FunctionInvokeOptions): Promise<FunctionResult>;
1525
1527
  }
@@ -4252,6 +4254,7 @@ declare function initiateInventoryTransfer(api: GameApi, body: InitiateTransferR
4252
4254
  signal?: AbortSignal;
4253
4255
  }): Promise<TransferResponse>;
4254
4256
  declare function invokeFunction(api: GameApi, body: Uint8Array, options?: {
4257
+ "cue_id"?: string;
4255
4258
  signal?: AbortSignal;
4256
4259
  }): Promise<BytesResponse>;
4257
4260
  declare function kickPlayer(api: GameApi, game_room_id: string, player_id: string, options?: {
@@ -4785,6 +4788,7 @@ interface PlayerBoost {
4785
4788
  }
4786
4789
  interface RewardCue {
4787
4790
  currencySlug: string;
4791
+ cueId?: string;
4788
4792
  expected?: number;
4789
4793
  origin?: {
4790
4794
  x: number;
@@ -4792,6 +4796,7 @@ interface RewardCue {
4792
4796
  };
4793
4797
  }
4794
4798
  type GemCorner = "top-left" | "top-right" | "bottom-left" | "bottom-right";
4799
+ type RewardPresentation = "arcade" | "game";
4795
4800
  interface MenuStyle {
4796
4801
  readonly ground: string;
4797
4802
  readonly accent: string;
@@ -4901,6 +4906,7 @@ declare class GemFrame {
4901
4906
  }>): boolean;
4902
4907
  declareSettings(settings: GemSettingsDeclare["settings"]): boolean;
4903
4908
  setGemCorner(corner: GemCorner): boolean;
4909
+ setRewardPresentation(mode: RewardPresentation): boolean;
4904
4910
  setMenuStyle(style: MenuStyle | null): boolean;
4905
4911
  requestShare(params: ReadonlyArray<{
4906
4912
  readonly key: string;
@@ -5355,6 +5361,7 @@ interface Gem {
5355
5361
  reportMuted(muted: boolean): void;
5356
5362
  showPortraitBorders(name: string | null): void;
5357
5363
  cueReward(cue: RewardCue): boolean;
5364
+ setRewardPresentation(mode: RewardPresentation): boolean;
5358
5365
  setWalletVisible(visible: boolean, options?: WalletVisibleOptions): boolean;
5359
5366
  setMenu(menu: GameMenu): boolean;
5360
5367
  setGemCorner(corner: GemCorner): boolean;
@@ -5385,4 +5392,4 @@ interface ExitAnalytics {
5385
5392
  }
5386
5393
  declare function leaveAndExit(rooms: ExitRooms, bridge: ExitBridge | null, reason?: string, analytics?: ExitAnalytics): Promise<void>;
5387
5394
  declare function createGem(options?: GemOptions): Gem;
5388
- export { ARCADE_EMBEDDERS, AVATAR_RIGS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection$1 as AnalyticsRejection, type AnalyticsValue, type AppLinksOutcome, type AppListing, type AppStore, type ArcadeApi, type ArcadeAvailability, type ArcadeOffer, type ArcadeOutcome, type ArcadeOutcomeKind, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Avatar3dOffer, type Avatar3dPrice, type Avatar3dPurchaseRequest, type AvatarRigNode, type AvatarRigs, type Avatars3dApi, type Base64String, type BootMark, type BootTimeline, type BrandingApi, type BrandingAsset, type BrandingAssetOptions, type BrandingCurrency, type BrandingImageOptions, type BrandingList, type BrandingLookup, type BrandingTheme, type BrandingVariant, type BroadcastOptions, type BytesResponse, CONDITIONAL_HEADERS, type Challenge, type ChallengeWindow, ChallengesApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType$1 as EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameApi, type GameCard, type GameConfig, type GameMenu, type GameMenuItem, type GamePass, type GameServerLink, type GameSettingsApi, type Gem, GemApiError, type GemAudioChannels, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemControlBox, type GemCorner, type GemDevTools, type GemErrorReason, GemFrame, GemFunctionError, type GemGameChoiceSetting, type GemGameSetting, type GemGameSettingBase, type GemGameSettingChange, type GemGameSettingIcon, type GemGameSettingOption, type GemGameSettingValue, type GemGameSliderSetting, type GemGameToggleSetting, type GemGraphicsQuality, type GemGraphicsRoute, type GemGraphicsRouteEntry, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServer, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPreferredRoute, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServer, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerIdentity, type GemServerLifecycle, type GemServerOptions, type GemServerProfile, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type GraphicsApi, type HostTokenSource, type HostTokenSourceOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchBackfillState, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchPlayerReport, type MatchPlayerReportResult, type MatchServeOptions, type MatchTransport, type MenuStyle, type MessageMeta, type MomentKind, type MomentResult, type MomentSignal, type MomentsApi, type MultiTransportSession, PLATFORM_EVENTS, type PassesApi, type PassesEvent, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge$1 as PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, type PlayerScope, PlayerText, type PreferredRouteOptions, type ProfileCallOptions, type ProfileShowcaseEntry$1 as ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PurchaseSettlement, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RequestOptions, type RewardCue, type RewardedStatus, type RoomArgValue, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerApi, type ServerBundleHost, type ServerTokenGrant, type SessionEndReason, type ShareApi, ShareRefusal, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SimilarGamesOutcome, type SnapshotCurrency, type SnapshotItem, type StoreApi, type StoreOffersOutcome, type StoreSettlement, type TokenGrant, type Transport, type TransportAdvert, type TransportKind, TransportRefusal, type TransportRequest, type TransportResponse, UNRELIABLE_CHANNEL_LABEL, type VersionedGetOptions, type VersionedResponse, type VibrationApi, type WalletVisibleOptions, type WornAvatar3d$1 as WornAvatar3d, asPlayerText, createBootTimeline, createGem, createGemServer, createHostTokenSource, createMatchServer, defineServer, experimentSelection, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, systemClock, text, toBase64, webTransportAvailable };
5395
+ export { ARCADE_EMBEDDERS, AVATAR_RIGS, type AccountApi, type AdFormat, type AdOutcome, type AdOutcomeKind, type AdRequest, type AdsApi, AnalyticsApi, type AnalyticsFlushOptions, type AnalyticsFlushResult, type AnalyticsOptions, type AnalyticsRejection$1 as AnalyticsRejection, type AnalyticsValue, type AppLinksOutcome, type AppListing, type AppStore, type ArcadeApi, type ArcadeAvailability, type ArcadeOffer, type ArcadeOutcome, type ArcadeOutcomeKind, AuthError, type AuthFailure, type AuthState, type Avatar3dFamily, type Avatar3dOffer, type Avatar3dPrice, type Avatar3dPurchaseRequest, type AvatarRigNode, type AvatarRigs, type Avatars3dApi, type Base64String, type BootMark, type BootTimeline, type BrandingApi, type BrandingAsset, type BrandingAssetOptions, type BrandingCurrency, type BrandingImageOptions, type BrandingList, type BrandingLookup, type BrandingTheme, type BrandingVariant, type BroadcastOptions, type BytesResponse, CONDITIONAL_HEADERS, type Challenge, type ChallengeWindow, ChallengesApi, type ClientOptions, type Clock, type ConditionalRequestHeaders, type ConfiguredPurchasePayment, type ConfiguredPurchaseRequest, type ConfiguredPurchaseResult, type ControlsApi, DEVICE_SETTINGS_MAX_BYTES, DedicatedServerError, type DedicatedServerFailure, type DedicatedServerSession, type DevToolsOpener, type DeviceSettings, type DeviceSettingsApi, type DeviceSettingsPutOutcome, type DirectPurchaseRequest, type DirectPurchaseResult, type EarnAllowance, type EarnAllowanceEvent, type EarnAllowancePeriod, type EarnAllowanceReadOptions, type EntityLeaderboard, type EntityLeaderboardEntry, type EntityLeaderboardOptions, type EntityType$1 as EntityType, type ExitAnalytics, type ExitBridge, type ExitRooms, type FrameState, type Friend, type FriendChallenge, FriendChallengeError, type FriendChallengeErrorCode, type FriendChallengeOutcome, type FriendChallengeOutcomeKind, type FriendChallengeRequest, type FriendChallengesPage, FriendsApi, type FriendsPage, type FunctionFailure, type FunctionInvokeOptions, type FunctionResult, FunctionsApi, type GameApi, type GameCard, type GameConfig, type GameMenu, type GameMenuItem, type GamePass, type GameServerLink, type GameSettingsApi, type Gem, GemApiError, type GemAudioChannels, GemClient, type GemCohort, type GemCohorts, GemConfigError, type GemControlBox, type GemCorner, type GemDevTools, type GemErrorReason, GemFrame, GemFunctionError, type GemGameChoiceSetting, type GemGameSetting, type GemGameSettingBase, type GemGameSettingChange, type GemGameSettingIcon, type GemGameSettingOption, type GemGameSettingValue, type GemGameSliderSetting, type GemGameToggleSetting, type GemGraphicsQuality, type GemGraphicsRoute, type GemGraphicsRouteEntry, type GemIdentity, type GemInsets, type GemLook, type GemLookBase, type GemLookDelta, type GemLookOptions, type GemLookSpeed, type GemMatchApi, type GemMatchServer, type GemMatchServerModule, type GemOptions, type GemPlayer, type GemPreferredRoute, type GemPrefs, type GemRecommendedSettings, type GemReservedArea, GemSaveError, type GemServer, type GemServerBundle, type GemServerFactory, type GemServerHost, type GemServerHostProfile, type GemServerIdentity, type GemServerLifecycle, type GemServerOptions, type GemServerProfile, type GemTerminationNotice, GemUnframedError, type GemViewport, type GetLeaderboardOptions, type GraphicsApi, type HostTokenSource, type HostTokenSourceOptions, type JoinWelcome, type Leaderboard, type LeaderboardEntry, type LeaderboardPeriod, LeaderboardsApi, type ListChallengesOptions, type ListFriendChallengesOptions, type ListFriendsOptions, MAX_PERIODS_BACK, type MatchBackfillState, type MatchConnectOptions, type MatchConnection, type MatchHosting, type MatchHostingMode, type MatchPlayerReport, type MatchPlayerReportResult, type MatchServeOptions, type MatchTransport, type MenuStyle, type MessageMeta, type MomentKind, type MomentResult, type MomentSignal, type MomentsApi, type MultiTransportSession, PLATFORM_EVENTS, type PassesApi, type PassesEvent, type PeriodOptions, PlatformApi, PlatformCurrenciesApi, type PlatformCurrency, type PlatformCurrencyAccess, type PlatformCurrencyPurchasePayment, type PlatformCurrencyPurchaseRequest, type PlatformCurrencyPurchaseResult, type PlatformCurrencyReadOptions, PlatformEarnAllowanceApi, type PlatformEventName, type PlayerBadge$1 as PlayerBadge, type PlayerBoost, type PlayerBoostMultiplier, type PlayerIdentity, type PlayerProfile, type PlayerScope, PlayerText, type PreferredRouteOptions, type ProfileCallOptions, type ProfileShowcaseEntry$1 as ProfileShowcaseEntry, ProfilesApi, type PurchaseApi, type PurchaseOptions, type PurchaseOutcome, PurchaseRefusal, type PurchaseRefusalCode, type PurchaseRequest, type PurchaseSettlement, type PutBytesOptions, type PutSaveOptions, type RankedRow, type RecipeAvailability, type RecipeLock, type RequestOptions, type RewardCue, type RewardPresentation, type RewardedStatus, type RoomArgValue, type SavePage, type SaveRecord, type SendOptions$1 as SendOptions, type ServerApi, type ServerBundleHost, type ServerTokenGrant, type SessionEndReason, type ShareApi, ShareRefusal, type ShareRequest, ShowcaseApi, type ShowcaseCallOptions, type ShowcaseFriendEntry, type ShowcaseFriends, type ShowcaseValue, type SignInOutcome, type SignInOutcomeKind, type SimilarGamesOutcome, type SnapshotCurrency, type SnapshotItem, type StoreApi, type StoreOffersOutcome, type StoreSettlement, type TokenGrant, type Transport, type TransportAdvert, type TransportKind, TransportRefusal, type TransportRequest, type TransportResponse, UNRELIABLE_CHANNEL_LABEL, type VersionedGetOptions, type VersionedResponse, type VibrationApi, type WalletVisibleOptions, type WornAvatar3d$1 as WornAvatar3d, asPlayerText, createBootTimeline, createGem, createGemServer, createHostTokenSource, createMatchServer, defineServer, experimentSelection, leaveAndExit, mapIdentity, markOnResolve, platformIconUrl, presentJoinCredential, readTemplateTransports, readTransportAdvert, reportOnResolve, systemClock, text, toBase64, webTransportAvailable };
@@ -1326,6 +1326,7 @@ declare function initiateInventoryTransfer(api: GameApi, body: InitiateTransferR
1326
1326
  signal?: AbortSignal;
1327
1327
  }): Promise<TransferResponse>;
1328
1328
  declare function invokeFunction(api: GameApi, body: Uint8Array, options?: {
1329
+ "cue_id"?: string;
1329
1330
  signal?: AbortSignal;
1330
1331
  }): Promise<BytesResponse>;
1331
1332
  declare function kickPlayer(api: GameApi, game_room_id: string, player_id: string, options?: {
package/dist/server.d.ts CHANGED
@@ -1404,6 +1404,7 @@ declare function initiateInventoryTransfer(api: GameApi, body: InitiateTransferR
1404
1404
  signal?: AbortSignal;
1405
1405
  }): Promise<TransferResponse>;
1406
1406
  declare function invokeFunction(api: GameApi, body: Uint8Array, options?: {
1407
+ "cue_id"?: string;
1407
1408
  signal?: AbortSignal;
1408
1409
  }): Promise<BytesResponse>;
1409
1410
  declare function kickPlayer(api: GameApi, game_room_id: string, player_id: string, options?: {
@@ -1723,6 +1724,7 @@ interface ServerAnalytics {
1723
1724
  }
1724
1725
  interface FunctionInvokeOptions {
1725
1726
  readonly signal?: AbortSignal;
1727
+ readonly cueId?: string;
1726
1728
  }
1727
1729
  interface FunctionResult {
1728
1730
  readonly bytes: Uint8Array;
@@ -1746,6 +1748,7 @@ declare class FunctionsApi {
1746
1748
  #private;
1747
1749
  constructor(invoke: (body: Uint8Array, options?: {
1748
1750
  signal?: AbortSignal;
1751
+ cue_id?: string;
1749
1752
  }) => Promise<BytesResponse>);
1750
1753
  invoke(input: unknown, options?: FunctionInvokeOptions): Promise<FunctionResult>;
1751
1754
  }
@@ -1,6 +1,6 @@
1
1
  # The function surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/function` v21.1.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/function` v22.0.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/function` exports exactly the symbols on this page and nothing else.
6
6
 
@@ -1,6 +1,6 @@
1
1
  # The browser surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v21.1.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v22.0.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/game` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6
 
@@ -7180,6 +7180,24 @@ The platform currency's slug, as `gem.platform.currencies.get()` lists it —
7180
7180
  `GEMS` or `ARCADE_TICKETS`. It decides what flies — gems or coins — and
7181
7181
  which of the player's totals the payout moves.
7182
7182
 
7183
+ <a id="rewardcue-cueid"></a>
7184
+
7185
+ ## RewardCue.cueId
7186
+
7187
+ ```ts
7188
+ cueId?: string
7189
+ ```
7190
+
7191
+ Your id for this award, so the arcade flies it once. Make one per award
7192
+ with `crypto.randomUUID()` and pass the same one as the `cueId` of the
7193
+ `gem.functions.invoke` that pays it; then the cue and the payout may reach
7194
+ the arcade in either order. 1 to 64 letters, digits, `_` or `-`; anything
7195
+ else is left out (with a console warning, from `gem.cueReward`), and the
7196
+ cue still goes.
7197
+
7198
+ For animation only: it moves no balance. Leave it out and the arcade pairs
7199
+ the cue with the payout by currency and timing.
7200
+
7183
7201
  <a id="rewardcue-expected"></a>
7184
7202
 
7185
7203
  ## RewardCue.expected
@@ -7238,6 +7256,18 @@ A corner of your frame, for `gem.setGemCorner`: where you would like the
7238
7256
  arcade's Gem button to sit. `'top-left'` is where it sits unless you ask.
7239
7257
  Physical corners: `'top-left'` is the top-left in every language.
7240
7258
 
7259
+ <a id="rewardpresentation"></a>
7260
+
7261
+ ## RewardPresentation
7262
+
7263
+ ```ts
7264
+ type RewardPresentation = "arcade" | "game"
7265
+ ```
7266
+
7267
+ Who decides when your platform-currency payouts are shown landing, for
7268
+ `gem.setRewardPresentation`: `'arcade'`, the default, or `'game'`, when each
7269
+ payout waits for your `gem.cueReward`.
7270
+
7241
7271
  <a id="menustyle"></a>
7242
7272
 
7243
7273
  ## MenuStyle
@@ -7646,6 +7676,29 @@ its control.
7646
7676
  up, for an arcade that cannot move its control, for a value that is not
7647
7677
  one of the four corners, and past this frame's own limit.
7648
7678
 
7679
+ <a id="gemframe-setrewardpresentation"></a>
7680
+
7681
+ ## GemFrame.setRewardPresentation
7682
+
7683
+ ```ts
7684
+ setRewardPresentation(mode: RewardPresentation): boolean
7685
+ ```
7686
+
7687
+ Tell the arcade who decides when your platform-currency payouts are shown
7688
+ landing: the whole answer each time, the latest one winning.
7689
+
7690
+ Prefer `gem.setRewardPresentation`, which holds the answer across a
7691
+ reconnect. This one sends only while connected, and only to an arcade
7692
+ that can hold a payout for your cue.
7693
+
7694
+ | Parameter | Type |
7695
+ | --- | --- |
7696
+ | `mode` | `RewardPresentation` |
7697
+
7698
+ **Returns.** whether the message left the frame: `false` before the bridge is
7699
+ up, for an arcade that cannot hold a payout, for a value that is neither
7700
+ `'arcade'` nor `'game'`, and past this frame's own limit.
7701
+
7649
7702
  <a id="gemframe-setmenustyle"></a>
7650
7703
 
7651
7704
  ## GemFrame.setMenuStyle
@@ -8726,6 +8779,24 @@ readonly signal?: AbortSignal
8726
8779
 
8727
8780
  Cancel the call. A call already cancelled sends nothing.
8728
8781
 
8782
+ <a id="functioninvokeoptions-cueid"></a>
8783
+
8784
+ ## FunctionInvokeOptions.cueId
8785
+
8786
+ ```ts
8787
+ readonly cueId?: string
8788
+ ```
8789
+
8790
+ The id of the reward this call pays, so the Gem Arcade flies it once:
8791
+ the same `cueId` you pass to `gem.cueReward` for it, one
8792
+ `crypto.randomUUID()` per award. The platform hands it back on the payout
8793
+ it shows the arcade, and nowhere else: your function never sees it, and
8794
+ neither the answer nor a receipt carries it.
8795
+
8796
+ 1 to 64 letters, digits, `_` or `-`. Anything else is left out with a
8797
+ console warning, and the call still goes: it decides an animation, never
8798
+ whether the call pays.
8799
+
8729
8800
  <a id="functionresult"></a>
8730
8801
 
8731
8802
  ## FunctionResult
@@ -9009,6 +9080,15 @@ const result = await gem.functions.invoke({ v: 2, runId, finishMs });
9009
9080
  const { accepted, why } = result.json();
9010
9081
  ```
9011
9082
 
9083
+ When the call pays a reward the player sees, pass the reward's `cueId`, the
9084
+ same one the page gives `gem.cueReward` for it, and the Gem Arcade flies it
9085
+ once:
9086
+
9087
+ ```js
9088
+ const cueId = crypto.randomUUID(); // one per award, also passed to the cue
9089
+ await gem.functions.invoke({ claim: 'daily' }, { cueId });
9090
+ ```
9091
+
9012
9092
  | Parameter | Type | Description |
9013
9093
  | --- | --- | --- |
9014
9094
  | `input` | `unknown` | Bytes, or a value to send as JSON. |
@@ -12231,6 +12311,30 @@ gem.cueReward({
12231
12311
  });
12232
12312
  ```
12233
12313
 
12314
+ **When your function pays it, give both calls one `cueId`.** Make one per
12315
+ award with `crypto.randomUUID()`, pass it here and to the
12316
+ `gem.functions.invoke` that pays, and the arcade flies that reward once,
12317
+ whichever reaches it first — so you may cue before the call or after it
12318
+ returns:
12319
+
12320
+ ```js
12321
+ const cueId = crypto.randomUUID();
12322
+ const result = await gem.functions.invoke({ claim: 'daily' }, { cueId });
12323
+ gem.cueReward({ currencySlug: 'GEMS', expected: 15, origin, cueId });
12324
+ ```
12325
+
12326
+ A payout that is not a function call (your own game server's) has no id
12327
+ to share: cue it with none, and the arcade pairs the two by currency and
12328
+ timing.
12329
+
12330
+ **When is up to the arcade unless you say otherwise.** By default the cue
12331
+ is paired with its payout only within about half a second either side of
12332
+ your server's write; a payout with no cue by then flies from the middle of
12333
+ your frame, and a cue that comes later adds nothing. To show the payout at
12334
+ a later moment of your own, such as a Claim tap on the win card or the
12335
+ screen the player returns to, call `gem.setRewardPresentation('game')` once
12336
+ at boot: each payout then waits for your cue.
12337
+
12234
12338
  **This is the platform-currency animation, and the only one.** The display
12235
12339
  of every platform currency — Gems and Coins alike — belongs to the
12236
12340
  arcade: a game draws no flight or celebration of its own for one and keeps
@@ -12252,6 +12356,53 @@ landed — which it does on every channel, dev and test included.
12252
12356
  before the bridge is up, or under an embedder with no wallet. On `false`
12253
12357
  the game does nothing: it draws no animation of its own in its place.
12254
12358
 
12359
+ <a id="gem-setrewardpresentation"></a>
12360
+
12361
+ ## Gem.setRewardPresentation
12362
+
12363
+ ```ts
12364
+ setRewardPresentation(mode: RewardPresentation): boolean
12365
+ ```
12366
+
12367
+ Say who decides when your platform-currency payouts are shown landing: the
12368
+ arcade (`'arcade'`, the default) or your game (`'game'`). Call it once at
12369
+ boot when your reward moment comes after your server pays, such as a Claim
12370
+ tap on the win card or the next screen the player sees.
12371
+
12372
+ ```js
12373
+ gem.setRewardPresentation('game'); // at boot
12374
+ // ...the server pays when the board is won; later, on Claim:
12375
+ gem.cueReward({ currencySlug: 'ARCADE_TICKETS', expected: 20, origin });
12376
+ ```
12377
+
12378
+ **With `'game'`, your cue supplies the moment and the payout supplies the
12379
+ number.** The arcade holds each payout's presentation for its currency
12380
+ rather than flying it from the middle of your frame. Each `cueReward`
12381
+ releases up to its `expected` of what is held (all of it when it names no
12382
+ amount) and flies it from its `origin`, and the arcade's wallet chip over
12383
+ your game counts up as the marks land. A cue that finds nothing held waits
12384
+ for the next payout of its currency, so cue before or after the write, in
12385
+ either order.
12386
+
12387
+ **It delays the show, never the money.** What is paid, when, and every
12388
+ ceiling are unchanged, and the arcade's menu and every purchase see the
12389
+ player's true total at once. A payout no cue releases within five minutes
12390
+ lands quietly, with no flight, so a game can never hide one.
12391
+
12392
+ **It is screen state, not a toggle**, held before the bridge is up and
12393
+ re-sent after every reconnect. Switching back to `'arcade'` lands whatever
12394
+ is held. A value that is neither is ignored, with a warning on the console,
12395
+ and changes nothing.
12396
+
12397
+ | Parameter | Type | Description |
12398
+ | --- | --- | --- |
12399
+ | `mode` | `RewardPresentation` | `'game'` to present each payout on your cue, `'arcade'` for the default. |
12400
+
12401
+ **Returns.** `true` when the arcade was told now; `false` before the bridge is
12402
+ up (the answer is held and sent when it connects), under an embedder
12403
+ that presents every payout its own way, and for a value that is neither.
12404
+ On `false` from an embedder, keep cueing as usual: nothing else changes.
12405
+
12255
12406
  <a id="gem-setwalletvisible"></a>
12256
12407
 
12257
12408
  ## Gem.setWalletVisible
@@ -1,6 +1,6 @@
1
1
  # The server surface — API reference
2
2
 
3
- Generated from `@indiegems/gem-web-sdk/sdk` v21.1.1, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
3
+ Generated from `@indiegems/gem-web-sdk/sdk` v22.0.0, the version of the package this file ships in. Every symbol below carries an explicit anchor, its `anchor` in `reference.json` beside this file.
4
4
 
5
5
  `@indiegems/gem-web-sdk/sdk` is the one import a game writes, wherever its code runs. `@indiegems/gem-web-sdk/server` exports exactly the symbols on this page and nothing else, for a build that wants only this half.
6
6
 
@@ -1489,6 +1489,24 @@ readonly signal?: AbortSignal
1489
1489
 
1490
1490
  Cancel the call. A call already cancelled sends nothing.
1491
1491
 
1492
+ <a id="functioninvokeoptions-cueid"></a>
1493
+
1494
+ ## FunctionInvokeOptions.cueId
1495
+
1496
+ ```ts
1497
+ readonly cueId?: string
1498
+ ```
1499
+
1500
+ The id of the reward this call pays, so the Gem Arcade flies it once:
1501
+ the same `cueId` you pass to `gem.cueReward` for it, one
1502
+ `crypto.randomUUID()` per award. The platform hands it back on the payout
1503
+ it shows the arcade, and nowhere else: your function never sees it, and
1504
+ neither the answer nor a receipt carries it.
1505
+
1506
+ 1 to 64 letters, digits, `_` or `-`. Anything else is left out with a
1507
+ console warning, and the call still goes: it decides an animation, never
1508
+ whether the call pays.
1509
+
1492
1510
  <a id="functionresult"></a>
1493
1511
 
1494
1512
  ## FunctionResult
@@ -1772,6 +1790,15 @@ const result = await gem.functions.invoke({ v: 2, runId, finishMs });
1772
1790
  const { accepted, why } = result.json();
1773
1791
  ```
1774
1792
 
1793
+ When the call pays a reward the player sees, pass the reward's `cueId`, the
1794
+ same one the page gives `gem.cueReward` for it, and the Gem Arcade flies it
1795
+ once:
1796
+
1797
+ ```js
1798
+ const cueId = crypto.randomUUID(); // one per award, also passed to the cue
1799
+ await gem.functions.invoke({ claim: 'daily' }, { cueId });
1800
+ ```
1801
+
1775
1802
  | Parameter | Type | Description |
1776
1803
  | --- | --- | --- |
1777
1804
  | `input` | `unknown` | Bytes, or a value to send as JSON. |
@@ -2,7 +2,7 @@
2
2
  "schema_version": 2,
3
3
  "source": {
4
4
  "repo": "IndieGems/gem-web-sdk",
5
- "version": "21.1.1"
5
+ "version": "22.0.0"
6
6
  },
7
7
  "entries": [
8
8
  {
@@ -8556,6 +8556,22 @@
8556
8556
  "defaultValue": null,
8557
8557
  "guides": []
8558
8558
  },
8559
+ {
8560
+ "id": "RewardCue.cueId",
8561
+ "name": "cueId",
8562
+ "anchor": "rewardcue-cueid",
8563
+ "group": "platform",
8564
+ "signature": "cueId?: string",
8565
+ "documented": true,
8566
+ "summary": "Your id for this award, so the arcade flies it once. Make one per award\nwith `crypto.randomUUID()` and pass the same one as the `cueId` of the\n`gem.functions.invoke` that pays it; then the cue and the payout may reach\nthe arcade in either order. 1 to 64 letters, digits, `_` or `-`; anything\nelse is left out (with a console warning, from `gem.cueReward`), and the\ncue still goes.\n\nFor animation only: it moves no balance. Leave it out and the arcade pairs\nthe cue with the payout by currency and timing.",
8567
+ "deprecated": null,
8568
+ "params": [],
8569
+ "returns": null,
8570
+ "throws": null,
8571
+ "example": null,
8572
+ "defaultValue": null,
8573
+ "guides": []
8574
+ },
8559
8575
  {
8560
8576
  "id": "RewardCue.expected",
8561
8577
  "name": "expected",
@@ -8636,6 +8652,22 @@
8636
8652
  "defaultValue": null,
8637
8653
  "guides": []
8638
8654
  },
8655
+ {
8656
+ "id": "RewardPresentation",
8657
+ "name": "RewardPresentation",
8658
+ "anchor": "rewardpresentation",
8659
+ "group": "platform",
8660
+ "signature": "type RewardPresentation = \"arcade\" | \"game\"",
8661
+ "documented": true,
8662
+ "summary": "Who decides when your platform-currency payouts are shown landing, for\n`gem.setRewardPresentation`: `'arcade'`, the default, or `'game'`, when each\npayout waits for your `gem.cueReward`.",
8663
+ "deprecated": null,
8664
+ "params": [],
8665
+ "returns": null,
8666
+ "throws": null,
8667
+ "example": null,
8668
+ "defaultValue": null,
8669
+ "guides": []
8670
+ },
8639
8671
  {
8640
8672
  "id": "MenuStyle",
8641
8673
  "name": "MenuStyle",
@@ -9064,6 +9096,29 @@
9064
9096
  "defaultValue": null,
9065
9097
  "guides": []
9066
9098
  },
9099
+ {
9100
+ "id": "GemFrame.setRewardPresentation",
9101
+ "name": "setRewardPresentation",
9102
+ "anchor": "gemframe-setrewardpresentation",
9103
+ "group": "frame",
9104
+ "signature": "setRewardPresentation(mode: RewardPresentation): boolean",
9105
+ "documented": true,
9106
+ "summary": "Tell the arcade who decides when your platform-currency payouts are shown\nlanding: the whole answer each time, the latest one winning.\n\nPrefer `gem.setRewardPresentation`, which holds the answer across a\nreconnect. This one sends only while connected, and only to an arcade\nthat can hold a payout for your cue.",
9107
+ "deprecated": null,
9108
+ "params": [
9109
+ {
9110
+ "name": "mode",
9111
+ "type": "RewardPresentation",
9112
+ "optional": false,
9113
+ "summary": null
9114
+ }
9115
+ ],
9116
+ "returns": "whether the message left the frame: `false` before the bridge is\n up, for an arcade that cannot hold a payout, for a value that is neither\n `'arcade'` nor `'game'`, and past this frame's own limit.",
9117
+ "throws": null,
9118
+ "example": null,
9119
+ "defaultValue": null,
9120
+ "guides": []
9121
+ },
9067
9122
  {
9068
9123
  "id": "GemFrame.setMenuStyle",
9069
9124
  "name": "setMenuStyle",
@@ -10203,6 +10258,22 @@
10203
10258
  "defaultValue": null,
10204
10259
  "guides": []
10205
10260
  },
10261
+ {
10262
+ "id": "FunctionInvokeOptions.cueId",
10263
+ "name": "cueId",
10264
+ "anchor": "functioninvokeoptions-cueid",
10265
+ "group": "functions",
10266
+ "signature": "readonly cueId?: string",
10267
+ "documented": true,
10268
+ "summary": "The id of the reward this call pays, so the Gem Arcade flies it once:\nthe same `cueId` you pass to `gem.cueReward` for it, one\n`crypto.randomUUID()` per award. The platform hands it back on the payout\nit shows the arcade, and nowhere else: your function never sees it, and\nneither the answer nor a receipt carries it.\n\n1 to 64 letters, digits, `_` or `-`. Anything else is left out with a\nconsole warning, and the call still goes: it decides an animation, never\nwhether the call pays.",
10269
+ "deprecated": null,
10270
+ "params": [],
10271
+ "returns": null,
10272
+ "throws": null,
10273
+ "example": null,
10274
+ "defaultValue": null,
10275
+ "guides": []
10276
+ },
10206
10277
  {
10207
10278
  "id": "FunctionResult",
10208
10279
  "name": "FunctionResult",
@@ -10482,7 +10553,7 @@
10482
10553
  "group": "functions",
10483
10554
  "signature": "invoke(input: unknown, options?: FunctionInvokeOptions): Promise<FunctionResult>",
10484
10555
  "documented": true,
10485
- "summary": "Call the function published on your channel, and get its answer.\n\nThe input is sent as your function's `input`, byte for byte. Pass a\n`Uint8Array`, an `ArrayBuffer` or another typed array to send bytes as they\nare. Pass anything else and it is sent as its JSON text — a string too, so\n`'ping'` arrives as `\"ping\"` with its quotes.\n\nThe call is made once. It is never repeated for you, because your function\nmay have granted or written something: see [GemFunctionError.retryable](api-reference-game.md#gemfunctionerror-retryable)\nfor whether repeating it could help.\n\n```js\nconst result = await gem.functions.invoke({ v: 2, runId, finishMs });\nconst { accepted, why } = result.json();\n```",
10556
+ "summary": "Call the function published on your channel, and get its answer.\n\nThe input is sent as your function's `input`, byte for byte. Pass a\n`Uint8Array`, an `ArrayBuffer` or another typed array to send bytes as they\nare. Pass anything else and it is sent as its JSON text — a string too, so\n`'ping'` arrives as `\"ping\"` with its quotes.\n\nThe call is made once. It is never repeated for you, because your function\nmay have granted or written something: see [GemFunctionError.retryable](api-reference-game.md#gemfunctionerror-retryable)\nfor whether repeating it could help.\n\n```js\nconst result = await gem.functions.invoke({ v: 2, runId, finishMs });\nconst { accepted, why } = result.json();\n```\n\nWhen the call pays a reward the player sees, pass the reward's `cueId`, the\nsame one the page gives `gem.cueReward` for it, and the Gem Arcade flies it\nonce:\n\n```js\nconst cueId = crypto.randomUUID(); // one per award, also passed to the cue\nawait gem.functions.invoke({ claim: 'daily' }, { cueId });\n```",
10486
10557
  "deprecated": null,
10487
10558
  "params": [
10488
10559
  {
@@ -13703,7 +13774,7 @@
13703
13774
  "group": "start",
13704
13775
  "signature": "cueReward(cue: RewardCue): boolean",
13705
13776
  "documented": true,
13706
- "summary": "Tell the arcade a platform-currency reward is on its way, so it **shows it\nlanding**: in the Gem Arcade the currency flies from `origin` into the Gem\nbutton, wherever on your frame it sits, which pops as each mark lands, and\nthe player's total moves once the platform confirms the grant. The Gem\nArcade draws no wallet over your game unless you ask (`setWalletVisible`):\nthe player sees their Gems and Coins in the Gem menu. A payout you do not\ncue still flies, from the middle of your frame, so cue the ones the player\nearns on screen.\n\nCall it the moment your game decides to award — when your server has moved\n(or is about to move) the progression mapped onto a platform currency —\nand pass the centre of that currency's icon (or hero) on your screen, so\nthe flight starts from the mark the player is looking at:\n\n```js\nconst { x, y, width, height } = rewardGem.getBoundingClientRect(); // the gem's own box\ngem.cueReward({\n currencySlug: 'GEMS', // or 'ARCADE_TICKETS', from the coin\n expected: 15,\n origin: { x: x + width / 2, y: y + height / 2 },\n});\n```\n\n**This is the platform-currency animation, and the only one.** The display\nof every platform currency — Gems and Coins alike — belongs to the\narcade: a game draws no flight or celebration of its own for one and keeps\nno counter of one. **If this returns `false`, do nothing** — there is no\nfallback celebration.\n\n**The arcade never takes your word for the amount.** What lands, and the\nplayer's new total, come from the platform itself; `expected` is drawn as\nprovisional, and a cue the platform never confirms fades on its own — a\ngrant clamped to zero, say, or one the receipt reports `suppressed`. So\nthe cue can only ever make the wallet move for a reward that really\nlanded — which it does on every channel, dev and test included.",
13777
+ "summary": "Tell the arcade a platform-currency reward is on its way, so it **shows it\nlanding**: in the Gem Arcade the currency flies from `origin` into the Gem\nbutton, wherever on your frame it sits, which pops as each mark lands, and\nthe player's total moves once the platform confirms the grant. The Gem\nArcade draws no wallet over your game unless you ask (`setWalletVisible`):\nthe player sees their Gems and Coins in the Gem menu. A payout you do not\ncue still flies, from the middle of your frame, so cue the ones the player\nearns on screen.\n\nCall it the moment your game decides to award — when your server has moved\n(or is about to move) the progression mapped onto a platform currency —\nand pass the centre of that currency's icon (or hero) on your screen, so\nthe flight starts from the mark the player is looking at:\n\n```js\nconst { x, y, width, height } = rewardGem.getBoundingClientRect(); // the gem's own box\ngem.cueReward({\n currencySlug: 'GEMS', // or 'ARCADE_TICKETS', from the coin\n expected: 15,\n origin: { x: x + width / 2, y: y + height / 2 },\n});\n```\n\n**When your function pays it, give both calls one `cueId`.** Make one per\naward with `crypto.randomUUID()`, pass it here and to the\n`gem.functions.invoke` that pays, and the arcade flies that reward once,\nwhichever reaches it first — so you may cue before the call or after it\nreturns:\n\n```js\nconst cueId = crypto.randomUUID();\nconst result = await gem.functions.invoke({ claim: 'daily' }, { cueId });\ngem.cueReward({ currencySlug: 'GEMS', expected: 15, origin, cueId });\n```\n\nA payout that is not a function call (your own game server's) has no id\nto share: cue it with none, and the arcade pairs the two by currency and\ntiming.\n\n**When is up to the arcade unless you say otherwise.** By default the cue\nis paired with its payout only within about half a second either side of\nyour server's write; a payout with no cue by then flies from the middle of\nyour frame, and a cue that comes later adds nothing. To show the payout at\na later moment of your own, such as a Claim tap on the win card or the\nscreen the player returns to, call `gem.setRewardPresentation('game')` once\nat boot: each payout then waits for your cue.\n\n**This is the platform-currency animation, and the only one.** The display\nof every platform currency — Gems and Coins alike — belongs to the\narcade: a game draws no flight or celebration of its own for one and keeps\nno counter of one. **If this returns `false`, do nothing** — there is no\nfallback celebration.\n\n**The arcade never takes your word for the amount.** What lands, and the\nplayer's new total, come from the platform itself; `expected` is drawn as\nprovisional, and a cue the platform never confirms fades on its own — a\ngrant clamped to zero, say, or one the receipt reports `suppressed`. So\nthe cue can only ever make the wallet move for a reward that really\nlanded — which it does on every channel, dev and test included.",
13707
13778
  "deprecated": null,
13708
13779
  "params": [
13709
13780
  {
@@ -13719,6 +13790,29 @@
13719
13790
  "defaultValue": null,
13720
13791
  "guides": []
13721
13792
  },
13793
+ {
13794
+ "id": "Gem.setRewardPresentation",
13795
+ "name": "setRewardPresentation",
13796
+ "anchor": "gem-setrewardpresentation",
13797
+ "group": "start",
13798
+ "signature": "setRewardPresentation(mode: RewardPresentation): boolean",
13799
+ "documented": true,
13800
+ "summary": "Say who decides when your platform-currency payouts are shown landing: the\narcade (`'arcade'`, the default) or your game (`'game'`). Call it once at\nboot when your reward moment comes after your server pays, such as a Claim\ntap on the win card or the next screen the player sees.\n\n```js\ngem.setRewardPresentation('game'); // at boot\n// ...the server pays when the board is won; later, on Claim:\ngem.cueReward({ currencySlug: 'ARCADE_TICKETS', expected: 20, origin });\n```\n\n**With `'game'`, your cue supplies the moment and the payout supplies the\nnumber.** The arcade holds each payout's presentation for its currency\nrather than flying it from the middle of your frame. Each `cueReward`\nreleases up to its `expected` of what is held (all of it when it names no\namount) and flies it from its `origin`, and the arcade's wallet chip over\nyour game counts up as the marks land. A cue that finds nothing held waits\nfor the next payout of its currency, so cue before or after the write, in\neither order.\n\n**It delays the show, never the money.** What is paid, when, and every\nceiling are unchanged, and the arcade's menu and every purchase see the\nplayer's true total at once. A payout no cue releases within five minutes\nlands quietly, with no flight, so a game can never hide one.\n\n**It is screen state, not a toggle**, held before the bridge is up and\nre-sent after every reconnect. Switching back to `'arcade'` lands whatever\nis held. A value that is neither is ignored, with a warning on the console,\nand changes nothing.",
13801
+ "deprecated": null,
13802
+ "params": [
13803
+ {
13804
+ "name": "mode",
13805
+ "type": "RewardPresentation",
13806
+ "optional": false,
13807
+ "summary": "`'game'` to present each payout on your cue, `'arcade'` for the default."
13808
+ }
13809
+ ],
13810
+ "returns": "`true` when the arcade was told now; `false` before the bridge is\n up (the answer is held and sent when it connects), under an embedder\n that presents every payout its own way, and for a value that is neither.\n On `false` from an embedder, keep cueing as usual: nothing else changes.",
13811
+ "throws": null,
13812
+ "example": null,
13813
+ "defaultValue": null,
13814
+ "guides": []
13815
+ },
13722
13816
  {
13723
13817
  "id": "Gem.setWalletVisible",
13724
13818
  "name": "setWalletVisible",
@@ -26721,6 +26815,22 @@
26721
26815
  "defaultValue": null,
26722
26816
  "guides": []
26723
26817
  },
26818
+ {
26819
+ "id": "FunctionInvokeOptions.cueId",
26820
+ "name": "cueId",
26821
+ "anchor": "functioninvokeoptions-cueid",
26822
+ "group": "functions",
26823
+ "signature": "readonly cueId?: string",
26824
+ "documented": true,
26825
+ "summary": "The id of the reward this call pays, so the Gem Arcade flies it once:\nthe same `cueId` you pass to `gem.cueReward` for it, one\n`crypto.randomUUID()` per award. The platform hands it back on the payout\nit shows the arcade, and nowhere else: your function never sees it, and\nneither the answer nor a receipt carries it.\n\n1 to 64 letters, digits, `_` or `-`. Anything else is left out with a\nconsole warning, and the call still goes: it decides an animation, never\nwhether the call pays.",
26826
+ "deprecated": null,
26827
+ "params": [],
26828
+ "returns": null,
26829
+ "throws": null,
26830
+ "example": null,
26831
+ "defaultValue": null,
26832
+ "guides": []
26833
+ },
26724
26834
  {
26725
26835
  "id": "FunctionResult",
26726
26836
  "name": "FunctionResult",
@@ -27000,7 +27110,7 @@
27000
27110
  "group": "functions",
27001
27111
  "signature": "invoke(input: unknown, options?: FunctionInvokeOptions): Promise<FunctionResult>",
27002
27112
  "documented": true,
27003
- "summary": "Call the function published on your channel, and get its answer.\n\nThe input is sent as your function's `input`, byte for byte. Pass a\n`Uint8Array`, an `ArrayBuffer` or another typed array to send bytes as they\nare. Pass anything else and it is sent as its JSON text — a string too, so\n`'ping'` arrives as `\"ping\"` with its quotes.\n\nThe call is made once. It is never repeated for you, because your function\nmay have granted or written something: see [GemFunctionError.retryable](api-reference-server.md#gemfunctionerror-retryable)\nfor whether repeating it could help.\n\n```js\nconst result = await gem.functions.invoke({ v: 2, runId, finishMs });\nconst { accepted, why } = result.json();\n```",
27113
+ "summary": "Call the function published on your channel, and get its answer.\n\nThe input is sent as your function's `input`, byte for byte. Pass a\n`Uint8Array`, an `ArrayBuffer` or another typed array to send bytes as they\nare. Pass anything else and it is sent as its JSON text — a string too, so\n`'ping'` arrives as `\"ping\"` with its quotes.\n\nThe call is made once. It is never repeated for you, because your function\nmay have granted or written something: see [GemFunctionError.retryable](api-reference-server.md#gemfunctionerror-retryable)\nfor whether repeating it could help.\n\n```js\nconst result = await gem.functions.invoke({ v: 2, runId, finishMs });\nconst { accepted, why } = result.json();\n```\n\nWhen the call pays a reward the player sees, pass the reward's `cueId`, the\nsame one the page gives `gem.cueReward` for it, and the Gem Arcade flies it\nonce:\n\n```js\nconst cueId = crypto.randomUUID(); // one per award, also passed to the cue\nawait gem.functions.invoke({ claim: 'daily' }, { cueId });\n```",
27004
27114
  "deprecated": null,
27005
27115
  "params": [
27006
27116
  {
@@ -237,7 +237,9 @@ animates every payout into the right total. Gems and Coins follow the same rules
237
237
  `onPause(false)` if you keep anything worked out from it, such as a greyed-out Buy button.
238
238
  - **No celebration of your own.** At a payout, cue the arcade's wallet with `gem.cueReward`, naming
239
239
  the currency that paid — `currencySlug: 'GEMS'` from the gem on your reward screen,
240
- `'ARCADE_TICKETS'` from the coin. If it returns `false`, do nothing
240
+ `'ARCADE_TICKETS'` from the coin. If it returns `false`, do nothing. When your serverless function
241
+ pays it, pass one `cueId` (a `crypto.randomUUID()`) to both the cue and the `gem.functions.invoke`
242
+ call, and the reward flies once
241
243
  ([inventory-and-catalogs.md](inventory-and-catalogs.md#showing-the-reward-land-in-the-arcades-wallet)).
242
244
  - **No "daily max" of your own making.** Your game cannot see what every other game paid the player,
243
245
  and must not compute a maximum. To show how much more your game can pay, read
package/docs/changelog.md CHANGED
@@ -16,6 +16,20 @@ 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
+ ## 22.0.0
20
+
21
+ Upgrading from 21.1.1. Impact: required.
22
+
23
+ ### Rebuild
24
+
25
+ - The function invoke options gained an optional cueId field, which changes the signatures of the functions API constructor, the server API invoke function member and the standalone invoke function. Nothing is required of existing calls; recompiling is enough.
26
+ - The frame message union, the list of frame-to-parent messages and the capability type each gained a reward presentation entry. Recompiling is enough, unless your code switches exhaustively over these types, in which case add a case for the new entry.
27
+
28
+ ### New capability
29
+
30
+ - A game can now make one id per award and pass it to both the reward cue call and the function invoke call, so the Arcade pairs the cue with its payout and the reward flies once. An id that is malformed is left out with a console warning and never throws. Passing an id is optional and existing calls behave as before.
31
+ - A server-paid game whose reward moment comes after the payout can now declare that its own reward cue decides when the payout is shown, instead of leaving the timing to the Arcade. Under the game choice the Arcade holds each payout's presentation until a cue releases it, and a payout that no cue releases within a limited time lands quietly. Only the presentation changes; what is paid, when it is paid, and every limit stay the same. The declaration is remembered until the Arcade connection is ready and sent again after each reconnect, and it takes effect only when the Arcade offers the matching capability.
32
+
19
33
  ## 21.1.1
20
34
 
21
35
  Upgrading from 21.1.0. Impact: none.
@@ -324,7 +324,9 @@ Four things to know before you ship one:
324
324
  player's Gems and Coins in its own chrome, and without a cue a payout flies from the middle of
325
325
  your frame, not from the payout the player is looking at. At the moment your game shows the challenge complete, call
326
326
  `gem.cueReward` with the currency that paid (`GEMS` or `ARCADE_TICKETS`) and the centre of its icon
327
- beside the payout on your completion screen, and the payout flies from there into the Gem button:
327
+ beside the payout on your completion screen, and the payout flies from there into the Gem button.
328
+ When a serverless function pays it, give the cue and the `gem.functions.invoke` call one `cueId`
329
+ so it flies once:
328
330
  [inventory-and-catalogs.md](inventory-and-catalogs.md#showing-the-reward-land-in-the-arcades-wallet).
329
331
  **If it returns `false`, do nothing** — no celebration of your own, no counter, no flight;
330
332
  platform-currency display belongs to the arcade, and a game not connected to it shows no
@@ -50,7 +50,7 @@ either way.
50
50
  ```jsonc
51
51
  // package.json
52
52
  "dependencies": {
53
- "@indiegems/gem-web-sdk": "21.1.1"
53
+ "@indiegems/gem-web-sdk": "22.0.0"
54
54
  }
55
55
  ```
56
56