@crowdedkingdoms/crowdyjs 17.13.0-dev.1 → 18.0.0-dev.1
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/MIGRATION.md +163 -1
- package/README.md +142 -146
- package/dist/crowdy-client.d.ts +12 -31
- package/dist/crowdy-client.d.ts.map +1 -1
- package/dist/crowdy-client.js +15 -37
- package/dist/crowdy-dsh/bridge.d.ts.map +1 -1
- package/dist/crowdy-dsh/bridge.js +3 -6
- package/dist/crowdy-studio/controller.d.ts +59 -57
- package/dist/crowdy-studio/controller.d.ts.map +1 -1
- package/dist/crowdy-studio/controller.js +268 -206
- package/dist/crowdy-studio/diagnostics.d.ts +3 -12
- package/dist/crowdy-studio/diagnostics.d.ts.map +1 -1
- package/dist/crowdy-studio/dom-shell.d.ts +2 -4
- package/dist/crowdy-studio/dom-shell.d.ts.map +1 -1
- package/dist/crowdy-studio/dom-shell.js +16 -47
- package/dist/crowdy-studio/embed/hud-layer.d.ts +1 -1
- package/dist/crowdy-studio/embed/panel.d.ts +3 -12
- package/dist/crowdy-studio/embed/panel.d.ts.map +1 -1
- package/dist/crowdy-studio/embed/panel.js +3 -6
- package/dist/crowdy-studio/index.d.ts +1 -3
- package/dist/crowdy-studio/index.d.ts.map +1 -1
- package/dist/crowdy-studio/index.js +0 -2
- package/dist/crowdy-studio/models.d.ts +3 -4
- package/dist/crowdy-studio/models.d.ts.map +1 -1
- package/dist/crowdy-studio/starter-projects.d.ts +8 -4
- package/dist/crowdy-studio/starter-projects.d.ts.map +1 -1
- package/dist/crowdy-studio/starter-projects.js +83 -100
- package/dist/domains/appAccess.d.ts +14 -1
- package/dist/domains/appAccess.d.ts.map +1 -1
- package/dist/domains/appAccess.js +37 -1
- package/dist/domains/exec.d.ts +162 -15
- package/dist/domains/exec.d.ts.map +1 -1
- package/dist/domains/exec.js +180 -18
- package/dist/domains/host.d.ts +3 -3
- package/dist/domains/host.js +3 -3
- package/dist/domains/marketplace.d.ts +9 -58
- package/dist/domains/marketplace.d.ts.map +1 -1
- package/dist/domains/marketplace.js +9 -106
- package/dist/domains/playerWallet.d.ts +6 -12
- package/dist/domains/playerWallet.d.ts.map +1 -1
- package/dist/domains/playerWallet.js +6 -21
- package/dist/errors.d.ts +7 -13
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +6 -10
- package/dist/generated/graphql.d.ts +1384 -7977
- package/dist/generated/graphql.d.ts.map +1 -1
- package/dist/generated/graphql.js +22 -321
- package/dist/grid-mods/exec-client-halves.d.ts +156 -0
- package/dist/grid-mods/exec-client-halves.d.ts.map +1 -0
- package/dist/grid-mods/exec-client-halves.js +356 -0
- package/dist/grid-mods/grid-host-calls.d.ts +29 -15
- package/dist/grid-mods/grid-host-calls.d.ts.map +1 -1
- package/dist/grid-mods/grid-host-calls.js +40 -44
- package/dist/grid-mods/index.d.ts +1 -0
- package/dist/grid-mods/index.d.ts.map +1 -1
- package/dist/grid-mods/index.js +1 -0
- package/dist/grid-mods/mod-runtime.d.ts +21 -6
- package/dist/grid-mods/mod-runtime.d.ts.map +1 -1
- package/dist/grid-mods/mod-runtime.js +6 -2
- package/dist/grid-scope.d.ts +0 -188
- package/dist/grid-scope.d.ts.map +1 -1
- package/dist/grid-scope.js +0 -69
- package/dist/index.d.ts +12 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -16
- package/dist/kit/actions.d.ts +5 -9
- package/dist/kit/actions.d.ts.map +1 -1
- package/dist/kit/actions.js +5 -9
- package/dist/kit/index.d.ts +2 -33
- package/dist/kit/index.d.ts.map +1 -1
- package/dist/kit/index.js +1 -32
- package/dist/kit/kit.d.ts +8 -208
- package/dist/kit/kit.d.ts.map +1 -1
- package/dist/kit/kit.js +5 -163
- package/dist/kit/social.d.ts +1 -3
- package/dist/kit/social.d.ts.map +1 -1
- package/dist/kit/social.js +1 -3
- package/dist/kit/wire.d.ts +16 -5
- package/dist/kit/wire.d.ts.map +1 -1
- package/dist/kit/wire.js +19 -5
- package/dist/live-coding/assets/browser-authoring-index.json +1 -1
- package/dist/live-coding/assets/manifest.json +1 -1
- package/dist/live-coding/browser-authoring-index.generated.d.ts.map +1 -1
- package/dist/live-coding/browser-authoring-index.generated.js +1496 -4386
- package/dist/live-coding/rust-analysis.d.ts.map +1 -1
- package/dist/live-coding/rust-analysis.js +31 -23
- package/dist/player-runtime/client-host-calls.d.ts +8 -0
- package/dist/player-runtime/client-host-calls.d.ts.map +1 -0
- package/dist/player-runtime/client-host-calls.js +28 -0
- package/dist/player-runtime/glue-runtime.d.ts +27 -10
- package/dist/player-runtime/glue-runtime.d.ts.map +1 -1
- package/dist/player-runtime/glue-runtime.js +40 -45
- package/dist/player-runtime/glue-sab.d.ts +2 -2
- package/dist/player-runtime/glue-sab.js +2 -2
- package/dist/player-runtime/player-code-broker.d.ts +80 -24
- package/dist/player-runtime/player-code-broker.d.ts.map +1 -1
- package/dist/player-runtime/player-code-broker.js +169 -41
- package/dist/player-runtime/player-glue-worker.d.ts +8 -8
- package/dist/player-runtime/player-glue-worker.d.ts.map +1 -1
- package/dist/player-runtime/player-glue-worker.js +26 -9
- package/dist/stores/actors.d.ts +12 -2
- package/dist/stores/actors.d.ts.map +1 -1
- package/dist/stores/actors.js +43 -18
- package/dist/stores/chunks.d.ts +12 -0
- package/dist/stores/chunks.d.ts.map +1 -1
- package/dist/stores/chunks.js +112 -39
- package/dist/stores/durable.d.ts.map +1 -1
- package/dist/stores/durable.js +2 -1
- package/dist/stores/inbox.d.ts +1 -1
- package/dist/stores/inbox.d.ts.map +1 -1
- package/dist/stores/index.d.ts +0 -11
- package/dist/stores/index.d.ts.map +1 -1
- package/dist/stores/index.js +0 -4
- package/dist/stores/session.d.ts +0 -2
- package/dist/stores/session.d.ts.map +1 -1
- package/package.json +1 -1
- package/dist/crowdy-studio/model-lint-log.d.ts +0 -76
- package/dist/crowdy-studio/model-lint-log.d.ts.map +0 -1
- package/dist/crowdy-studio/model-lint-log.js +0 -93
- package/dist/crowdy-studio/model-lint.d.ts +0 -61
- package/dist/crowdy-studio/model-lint.d.ts.map +0 -1
- package/dist/crowdy-studio/model-lint.js +0 -45
- package/dist/domains/compute.d.ts +0 -208
- package/dist/domains/compute.d.ts.map +0 -1
- package/dist/domains/compute.js +0 -274
- package/dist/domains/controlPlane.d.ts +0 -38
- package/dist/domains/controlPlane.d.ts.map +0 -1
- package/dist/domains/controlPlane.js +0 -43
- package/dist/domains/gameModel.d.ts +0 -1174
- package/dist/domains/gameModel.d.ts.map +0 -1
- package/dist/domains/gameModel.js +0 -1333
- package/dist/domains/playerCompute.d.ts +0 -91
- package/dist/domains/playerCompute.d.ts.map +0 -1
- package/dist/domains/playerCompute.js +0 -136
- package/dist/domains/playerModel.d.ts +0 -20
- package/dist/domains/playerModel.d.ts.map +0 -1
- package/dist/domains/playerModel.js +0 -54
- package/dist/kit/abilities.d.ts +0 -66
- package/dist/kit/abilities.d.ts.map +0 -1
- package/dist/kit/abilities.js +0 -71
- package/dist/kit/blueprints/combat.d.ts +0 -81
- package/dist/kit/blueprints/combat.d.ts.map +0 -1
- package/dist/kit/blueprints/combat.js +0 -357
- package/dist/kit/blueprints/core.d.ts +0 -222
- package/dist/kit/blueprints/core.d.ts.map +0 -1
- package/dist/kit/blueprints/core.js +0 -185
- package/dist/kit/blueprints/decks.d.ts +0 -50
- package/dist/kit/blueprints/decks.d.ts.map +0 -1
- package/dist/kit/blueprints/decks.js +0 -163
- package/dist/kit/blueprints/economy.d.ts +0 -88
- package/dist/kit/blueprints/economy.d.ts.map +0 -1
- package/dist/kit/blueprints/economy.js +0 -533
- package/dist/kit/blueprints/guild.d.ts +0 -51
- package/dist/kit/blueprints/guild.d.ts.map +0 -1
- package/dist/kit/blueprints/guild.js +0 -50
- package/dist/kit/blueprints/index.d.ts +0 -23
- package/dist/kit/blueprints/index.d.ts.map +0 -1
- package/dist/kit/blueprints/index.js +0 -22
- package/dist/kit/blueprints/inventory.d.ts +0 -84
- package/dist/kit/blueprints/inventory.d.ts.map +0 -1
- package/dist/kit/blueprints/inventory.js +0 -257
- package/dist/kit/blueprints/leaderboards.d.ts +0 -49
- package/dist/kit/blueprints/leaderboards.d.ts.map +0 -1
- package/dist/kit/blueprints/leaderboards.js +0 -126
- package/dist/kit/blueprints/liveops.d.ts +0 -42
- package/dist/kit/blueprints/liveops.d.ts.map +0 -1
- package/dist/kit/blueprints/liveops.js +0 -170
- package/dist/kit/blueprints/locks.d.ts +0 -82
- package/dist/kit/blueprints/locks.d.ts.map +0 -1
- package/dist/kit/blueprints/locks.js +0 -155
- package/dist/kit/blueprints/loot.d.ts +0 -90
- package/dist/kit/blueprints/loot.d.ts.map +0 -1
- package/dist/kit/blueprints/loot.js +0 -229
- package/dist/kit/blueprints/matches.d.ts +0 -84
- package/dist/kit/blueprints/matches.d.ts.map +0 -1
- package/dist/kit/blueprints/matches.js +0 -349
- package/dist/kit/blueprints/moderation.d.ts +0 -32
- package/dist/kit/blueprints/moderation.d.ts.map +0 -1
- package/dist/kit/blueprints/moderation.js +0 -140
- package/dist/kit/blueprints/npcs.d.ts +0 -78
- package/dist/kit/blueprints/npcs.d.ts.map +0 -1
- package/dist/kit/blueprints/npcs.js +0 -125
- package/dist/kit/blueprints/plots.d.ts +0 -63
- package/dist/kit/blueprints/plots.d.ts.map +0 -1
- package/dist/kit/blueprints/plots.js +0 -151
- package/dist/kit/blueprints/progression.d.ts +0 -68
- package/dist/kit/blueprints/progression.d.ts.map +0 -1
- package/dist/kit/blueprints/progression.js +0 -324
- package/dist/kit/blueprints/quests.d.ts +0 -72
- package/dist/kit/blueprints/quests.d.ts.map +0 -1
- package/dist/kit/blueprints/quests.js +0 -285
- package/dist/kit/blueprints/worldsim.d.ts +0 -91
- package/dist/kit/blueprints/worldsim.d.ts.map +0 -1
- package/dist/kit/blueprints/worldsim.js +0 -468
- package/dist/kit/combat.d.ts +0 -141
- package/dist/kit/combat.d.ts.map +0 -1
- package/dist/kit/combat.js +0 -196
- package/dist/kit/decks.d.ts +0 -157
- package/dist/kit/decks.d.ts.map +0 -1
- package/dist/kit/decks.js +0 -186
- package/dist/kit/director.d.ts +0 -88
- package/dist/kit/director.d.ts.map +0 -1
- package/dist/kit/director.js +0 -86
- package/dist/kit/economy.d.ts +0 -289
- package/dist/kit/economy.d.ts.map +0 -1
- package/dist/kit/economy.js +0 -427
- package/dist/kit/engine.d.ts +0 -48
- package/dist/kit/engine.d.ts.map +0 -1
- package/dist/kit/engine.js +0 -113
- package/dist/kit/features.d.ts +0 -60
- package/dist/kit/features.d.ts.map +0 -1
- package/dist/kit/features.js +0 -65
- package/dist/kit/instances.d.ts +0 -52
- package/dist/kit/instances.d.ts.map +0 -1
- package/dist/kit/instances.js +0 -60
- package/dist/kit/inventory.d.ts +0 -129
- package/dist/kit/inventory.d.ts.map +0 -1
- package/dist/kit/inventory.js +0 -200
- package/dist/kit/leaderboards.d.ts +0 -86
- package/dist/kit/leaderboards.d.ts.map +0 -1
- package/dist/kit/leaderboards.js +0 -133
- package/dist/kit/liveops.d.ts +0 -112
- package/dist/kit/liveops.d.ts.map +0 -1
- package/dist/kit/liveops.js +0 -183
- package/dist/kit/loot.d.ts +0 -128
- package/dist/kit/loot.d.ts.map +0 -1
- package/dist/kit/loot.js +0 -160
- package/dist/kit/matches.d.ts +0 -301
- package/dist/kit/matches.d.ts.map +0 -1
- package/dist/kit/matches.js +0 -458
- package/dist/kit/matchmaking.d.ts +0 -57
- package/dist/kit/matchmaking.d.ts.map +0 -1
- package/dist/kit/matchmaking.js +0 -59
- package/dist/kit/minigames.d.ts +0 -30
- package/dist/kit/minigames.d.ts.map +0 -1
- package/dist/kit/minigames.js +0 -38
- package/dist/kit/mobs.d.ts +0 -90
- package/dist/kit/mobs.d.ts.map +0 -1
- package/dist/kit/mobs.js +0 -98
- package/dist/kit/moderation.d.ts +0 -73
- package/dist/kit/moderation.d.ts.map +0 -1
- package/dist/kit/moderation.js +0 -103
- package/dist/kit/movement.d.ts +0 -78
- package/dist/kit/movement.d.ts.map +0 -1
- package/dist/kit/movement.js +0 -103
- package/dist/kit/notifications.d.ts +0 -45
- package/dist/kit/notifications.d.ts.map +0 -1
- package/dist/kit/notifications.js +0 -67
- package/dist/kit/npcs.d.ts +0 -226
- package/dist/kit/npcs.d.ts.map +0 -1
- package/dist/kit/npcs.js +0 -141
- package/dist/kit/objects.d.ts +0 -116
- package/dist/kit/objects.d.ts.map +0 -1
- package/dist/kit/objects.js +0 -119
- package/dist/kit/pets.d.ts +0 -85
- package/dist/kit/pets.d.ts.map +0 -1
- package/dist/kit/pets.js +0 -96
- package/dist/kit/plots.d.ts +0 -85
- package/dist/kit/plots.d.ts.map +0 -1
- package/dist/kit/plots.js +0 -113
- package/dist/kit/progression.d.ts +0 -181
- package/dist/kit/progression.d.ts.map +0 -1
- package/dist/kit/progression.js +0 -265
- package/dist/kit/quests.d.ts +0 -171
- package/dist/kit/quests.d.ts.map +0 -1
- package/dist/kit/quests.js +0 -237
- package/dist/kit/racing.d.ts +0 -85
- package/dist/kit/racing.d.ts.map +0 -1
- package/dist/kit/racing.js +0 -99
- package/dist/kit/shared.d.ts +0 -73
- package/dist/kit/shared.d.ts.map +0 -1
- package/dist/kit/shared.js +0 -101
- package/dist/kit/telemetry.d.ts +0 -66
- package/dist/kit/telemetry.d.ts.map +0 -1
- package/dist/kit/telemetry.js +0 -133
- package/dist/kit/territory.d.ts +0 -97
- package/dist/kit/territory.d.ts.map +0 -1
- package/dist/kit/territory.js +0 -114
- package/dist/kit/worldsim.d.ts +0 -263
- package/dist/kit/worldsim.d.ts.map +0 -1
- package/dist/kit/worldsim.js +0 -268
- package/dist/stores/model.d.ts +0 -81
- package/dist/stores/model.d.ts.map +0 -1
- package/dist/stores/model.js +0 -163
package/dist/kit/economy.js
DELETED
|
@@ -1,427 +0,0 @@
|
|
|
1
|
-
import { economyCurrencyFn, economyNames, } from './blueprints/index.js';
|
|
2
|
-
import { kitContainerProperties, kitInvoke, } from './shared.js';
|
|
3
|
-
/**
|
|
4
|
-
* Runtime helpers for the {@link economyBlueprint} conventions: wallets with
|
|
5
|
-
* per-currency balances, shop purchases, escrow trades, and player market
|
|
6
|
-
* listings. Every movement of currency or items is a single gated invoke —
|
|
7
|
-
* balances, stock, item identity, and ownership are all verified
|
|
8
|
-
* server-side, and a denial resolves with `success: false` (never an
|
|
9
|
-
* exception).
|
|
10
|
-
*
|
|
11
|
-
* `earn` is a trusted grant: with the default blueprint authority
|
|
12
|
-
* (`'server'`) it succeeds only for app admins — call it from studio/backend
|
|
13
|
-
* code, or drive grants through automations instead.
|
|
14
|
-
*
|
|
15
|
-
* Obtained via `client.kit(appId).economy`.
|
|
16
|
-
*/
|
|
17
|
-
export class EconomyKit {
|
|
18
|
-
constructor(appId, gameModel, options = {}, engines) {
|
|
19
|
-
this.appId = appId;
|
|
20
|
-
this.gameModel = gameModel;
|
|
21
|
-
/** Shop (admin-priced listings; atomic buys). */
|
|
22
|
-
this.shop = {
|
|
23
|
-
/**
|
|
24
|
-
* Create a shop listing (admin — the type is admin-instantiable).
|
|
25
|
-
* `maxStock` feeds the optional restock automation.
|
|
26
|
-
*/
|
|
27
|
-
create: async (input) => {
|
|
28
|
-
return this.gameModel.createContainer({
|
|
29
|
-
appId: this.appId,
|
|
30
|
-
typeName: this.names.listingType,
|
|
31
|
-
displayName: input.displayName,
|
|
32
|
-
properties: [
|
|
33
|
-
{ key: 'item_id', valueType: 'string', valueJson: JSON.stringify(input.itemId) },
|
|
34
|
-
{ key: 'price', valueType: 'int', valueJson: String(input.price) },
|
|
35
|
-
{ key: 'stock', valueType: 'int', valueJson: String(input.stock ?? 0) },
|
|
36
|
-
{
|
|
37
|
-
key: 'max_stock',
|
|
38
|
-
valueType: 'int',
|
|
39
|
-
valueJson: String(input.maxStock ?? input.stock ?? 0),
|
|
40
|
-
},
|
|
41
|
-
...(input.properties ?? []),
|
|
42
|
-
],
|
|
43
|
-
});
|
|
44
|
-
},
|
|
45
|
-
/** List shop listings with parsed state. */
|
|
46
|
-
list: async () => {
|
|
47
|
-
const containers = await this.gameModel.containers({
|
|
48
|
-
appId: this.appId,
|
|
49
|
-
typeName: this.names.listingType,
|
|
50
|
-
});
|
|
51
|
-
return Promise.all(containers.map(async (c) => {
|
|
52
|
-
const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
|
|
53
|
-
return {
|
|
54
|
-
containerId: c.containerId,
|
|
55
|
-
displayName: c.displayName,
|
|
56
|
-
itemId: String(props.item_id ?? ''),
|
|
57
|
-
price: Number(props.price ?? 0),
|
|
58
|
-
stock: Number(props.stock ?? 0),
|
|
59
|
-
maxStock: Number(props.max_stock ?? 0),
|
|
60
|
-
};
|
|
61
|
-
}));
|
|
62
|
-
},
|
|
63
|
-
/**
|
|
64
|
-
* Buy one unit: wallet debit + stock decrement + item grant into
|
|
65
|
-
* `toStackId` (a stack of the listed item), all in one transaction.
|
|
66
|
-
* Resolves with the wallet's remaining balance.
|
|
67
|
-
*/
|
|
68
|
-
buy: async (input) => {
|
|
69
|
-
return kitInvoke(this.gameModel, {
|
|
70
|
-
appId: String(this.appId),
|
|
71
|
-
functionName: this.names.buyListingFn,
|
|
72
|
-
selfContainerId: input.listingId,
|
|
73
|
-
params: { wallet_id: input.walletId, to_stack_id: input.toStackId },
|
|
74
|
-
});
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
/** Escrow trades (player↔player item swaps, atomic on accept). */
|
|
78
|
-
this.trades = {
|
|
79
|
-
/**
|
|
80
|
-
* Create a trade offer to another player. The stacks named here are the
|
|
81
|
-
* OFFERER's: `giveStackId` is the escrowed source, `receiveStackId`
|
|
82
|
-
* receives the wanted items when the trade is accepted. The offer's
|
|
83
|
-
* container ownership (server-assigned to the caller) is what the accept
|
|
84
|
-
* guards trust — a forged offer over someone else's stacks can never be
|
|
85
|
-
* accepted.
|
|
86
|
-
*/
|
|
87
|
-
offer: async (input) => {
|
|
88
|
-
return this.gameModel.createContainer({
|
|
89
|
-
appId: this.appId,
|
|
90
|
-
typeName: this.names.tradeType,
|
|
91
|
-
displayName: input.displayName ??
|
|
92
|
-
`Trade ${input.giveQty}x ${input.giveItemId} for ${input.wantQty}x ${input.wantItemId}`,
|
|
93
|
-
...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),
|
|
94
|
-
properties: [
|
|
95
|
-
{ key: 'to_user_id', valueType: 'int', valueJson: String(input.toUserId) },
|
|
96
|
-
{
|
|
97
|
-
key: 'give_stack_id',
|
|
98
|
-
valueType: 'string',
|
|
99
|
-
valueJson: JSON.stringify(input.giveStackId),
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
key: 'receive_stack_id',
|
|
103
|
-
valueType: 'string',
|
|
104
|
-
valueJson: JSON.stringify(input.receiveStackId),
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
key: 'give_item_id',
|
|
108
|
-
valueType: 'string',
|
|
109
|
-
valueJson: JSON.stringify(input.giveItemId),
|
|
110
|
-
},
|
|
111
|
-
{ key: 'give_qty', valueType: 'int', valueJson: String(input.giveQty) },
|
|
112
|
-
{
|
|
113
|
-
key: 'want_item_id',
|
|
114
|
-
valueType: 'string',
|
|
115
|
-
valueJson: JSON.stringify(input.wantItemId),
|
|
116
|
-
},
|
|
117
|
-
{ key: 'want_qty', valueType: 'int', valueJson: String(input.wantQty) },
|
|
118
|
-
],
|
|
119
|
-
});
|
|
120
|
-
},
|
|
121
|
-
/**
|
|
122
|
-
* Accept a trade as the invited player, supplying YOUR two stacks: the
|
|
123
|
-
* one paying the wanted items and the one receiving the given items. The
|
|
124
|
-
* offerer's stacks come from the offer record. All four quantity writes
|
|
125
|
-
* commit atomically or not at all.
|
|
126
|
-
*/
|
|
127
|
-
accept: async (input) => {
|
|
128
|
-
const offer = await this.trades.get(input.offerId);
|
|
129
|
-
return kitInvoke(this.gameModel, {
|
|
130
|
-
appId: String(this.appId),
|
|
131
|
-
functionName: this.names.acceptTradeFn,
|
|
132
|
-
selfContainerId: input.offerId,
|
|
133
|
-
params: {
|
|
134
|
-
give_stack_id: offer.giveStackId,
|
|
135
|
-
to_give_stack_id: input.toGiveStackId,
|
|
136
|
-
want_stack_id: input.wantStackId,
|
|
137
|
-
to_want_stack_id: offer.receiveStackId,
|
|
138
|
-
},
|
|
139
|
-
});
|
|
140
|
-
},
|
|
141
|
-
/** Cancel an open trade (either party may). */
|
|
142
|
-
cancel: async (offerId) => {
|
|
143
|
-
return kitInvoke(this.gameModel, {
|
|
144
|
-
appId: String(this.appId),
|
|
145
|
-
functionName: this.names.cancelTradeFn,
|
|
146
|
-
selfContainerId: offerId,
|
|
147
|
-
params: {},
|
|
148
|
-
});
|
|
149
|
-
},
|
|
150
|
-
/** Read one trade offer with parsed state. */
|
|
151
|
-
get: async (offerId) => {
|
|
152
|
-
const container = await this.gameModel.container({
|
|
153
|
-
appId: this.appId,
|
|
154
|
-
containerId: offerId,
|
|
155
|
-
});
|
|
156
|
-
return this.toTrade(container.containerId, container.displayName, container.ownerUserId != null ? String(container.ownerUserId) : null);
|
|
157
|
-
},
|
|
158
|
-
/** List trades the user created or was invited to (open ones first). */
|
|
159
|
-
listMine: async (userId) => {
|
|
160
|
-
const containers = await this.gameModel.containers({
|
|
161
|
-
appId: this.appId,
|
|
162
|
-
typeName: this.names.tradeType,
|
|
163
|
-
});
|
|
164
|
-
const all = await Promise.all(containers.map((c) => this.toTrade(c.containerId, c.displayName, c.ownerUserId != null ? String(c.ownerUserId) : null)));
|
|
165
|
-
const uid = String(userId);
|
|
166
|
-
return all
|
|
167
|
-
.filter((t) => t.fromUserId === uid || String(t.toUserId) === uid)
|
|
168
|
-
.sort((a, b) => Number(b.status === 'open') - Number(a.status === 'open'));
|
|
169
|
-
},
|
|
170
|
-
};
|
|
171
|
-
/** Player market (list a stack for currency; atomic purchases). */
|
|
172
|
-
this.market = {
|
|
173
|
-
/**
|
|
174
|
-
* List items for sale: names YOUR escrowed source stack and the ask
|
|
175
|
-
* price. Payment lands straight in your wallet when someone buys.
|
|
176
|
-
*/
|
|
177
|
-
list: async (input) => {
|
|
178
|
-
return this.gameModel.createContainer({
|
|
179
|
-
appId: this.appId,
|
|
180
|
-
typeName: this.names.marketType,
|
|
181
|
-
displayName: input.displayName ?? `${input.quantity}x ${input.itemId} for ${input.price}`,
|
|
182
|
-
...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),
|
|
183
|
-
properties: [
|
|
184
|
-
{
|
|
185
|
-
key: 'stack_id',
|
|
186
|
-
valueType: 'string',
|
|
187
|
-
valueJson: JSON.stringify(input.stackId),
|
|
188
|
-
},
|
|
189
|
-
{
|
|
190
|
-
key: 'item_id',
|
|
191
|
-
valueType: 'string',
|
|
192
|
-
valueJson: JSON.stringify(input.itemId),
|
|
193
|
-
},
|
|
194
|
-
{ key: 'quantity', valueType: 'int', valueJson: String(input.quantity) },
|
|
195
|
-
{ key: 'price', valueType: 'int', valueJson: String(input.price) },
|
|
196
|
-
],
|
|
197
|
-
});
|
|
198
|
-
},
|
|
199
|
-
/** Browse market listings (active ones only by default). */
|
|
200
|
-
browse: async (options = {}) => {
|
|
201
|
-
const containers = await this.gameModel.containers({
|
|
202
|
-
appId: this.appId,
|
|
203
|
-
typeName: this.names.marketType,
|
|
204
|
-
});
|
|
205
|
-
const all = await Promise.all(containers.map(async (c) => {
|
|
206
|
-
const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
|
|
207
|
-
return {
|
|
208
|
-
containerId: c.containerId,
|
|
209
|
-
displayName: c.displayName,
|
|
210
|
-
sellerUserId: c.ownerUserId != null ? String(c.ownerUserId) : null,
|
|
211
|
-
stackId: String(props.stack_id ?? ''),
|
|
212
|
-
itemId: String(props.item_id ?? ''),
|
|
213
|
-
quantity: Number(props.quantity ?? 0),
|
|
214
|
-
price: Number(props.price ?? 0),
|
|
215
|
-
active: props.active === true,
|
|
216
|
-
};
|
|
217
|
-
}));
|
|
218
|
-
return options.includeInactive ? all : all.filter((l) => l.active);
|
|
219
|
-
},
|
|
220
|
-
/**
|
|
221
|
-
* Buy a market listing: pays the seller's wallet and transfers the items
|
|
222
|
-
* into `toStackId` in one transaction. The seller's wallet and source
|
|
223
|
-
* stack are resolved from the listing. Resolves with the buyer wallet's
|
|
224
|
-
* remaining balance.
|
|
225
|
-
*/
|
|
226
|
-
buy: async (input) => {
|
|
227
|
-
const container = await this.gameModel.container({
|
|
228
|
-
appId: this.appId,
|
|
229
|
-
containerId: input.listingId,
|
|
230
|
-
});
|
|
231
|
-
const props = await kitContainerProperties(this.gameModel, String(this.appId), input.listingId);
|
|
232
|
-
if (container.ownerUserId == null) {
|
|
233
|
-
throw new Error('Market listing has no seller (unowned container)');
|
|
234
|
-
}
|
|
235
|
-
const sellerWallet = await this.ensureSellerWallet(String(container.ownerUserId));
|
|
236
|
-
return kitInvoke(this.gameModel, {
|
|
237
|
-
appId: String(this.appId),
|
|
238
|
-
functionName: this.names.buyMarketFn,
|
|
239
|
-
selfContainerId: input.listingId,
|
|
240
|
-
params: {
|
|
241
|
-
wallet_id: input.walletId,
|
|
242
|
-
seller_wallet_id: sellerWallet,
|
|
243
|
-
from_stack_id: String(props.stack_id ?? ''),
|
|
244
|
-
to_stack_id: input.toStackId,
|
|
245
|
-
},
|
|
246
|
-
});
|
|
247
|
-
},
|
|
248
|
-
/** Take a listing down (seller only). */
|
|
249
|
-
cancel: async (listingId) => {
|
|
250
|
-
return kitInvoke(this.gameModel, {
|
|
251
|
-
appId: String(this.appId),
|
|
252
|
-
functionName: this.names.cancelMarketFn,
|
|
253
|
-
selfContainerId: listingId,
|
|
254
|
-
params: {},
|
|
255
|
-
});
|
|
256
|
-
},
|
|
257
|
-
};
|
|
258
|
-
this.typePrefix = options.typePrefix ?? '';
|
|
259
|
-
this.names = economyNames(this.typePrefix);
|
|
260
|
-
this.currencies = options.currencies ?? ['gold'];
|
|
261
|
-
this.orderBook = new MarketKit(engines, options.marketModuleName ?? 'market-engine');
|
|
262
|
-
}
|
|
263
|
-
get defaultCurrency() {
|
|
264
|
-
return this.currencies[0];
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Find the player's wallet, creating it when absent (member-instantiable;
|
|
268
|
-
* the server assigns ownership to the caller). Sets the `owner_user_id`
|
|
269
|
-
* mirror property the blueprint's guards read.
|
|
270
|
-
*
|
|
271
|
-
* @param ownerUserId - The calling player's user id (decimal string).
|
|
272
|
-
*/
|
|
273
|
-
async ensureWallet(ownerUserId, options = {}) {
|
|
274
|
-
const existing = await this.gameModel.containers({
|
|
275
|
-
appId: this.appId,
|
|
276
|
-
typeName: this.names.walletType,
|
|
277
|
-
...(options.sessionId !== undefined ? { sessionId: options.sessionId } : {}),
|
|
278
|
-
});
|
|
279
|
-
const mine = existing.find((c) => c.ownerUserId != null && String(c.ownerUserId) === String(ownerUserId));
|
|
280
|
-
if (mine)
|
|
281
|
-
return mine;
|
|
282
|
-
return this.gameModel.createContainer({
|
|
283
|
-
appId: this.appId,
|
|
284
|
-
typeName: this.names.walletType,
|
|
285
|
-
displayName: options.displayName ?? `Wallet ${ownerUserId}`,
|
|
286
|
-
...(options.sessionId !== undefined ? { sessionId: options.sessionId } : {}),
|
|
287
|
-
properties: [
|
|
288
|
-
{ key: 'owner_user_id', valueType: 'int', valueJson: String(ownerUserId) },
|
|
289
|
-
],
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
/** Read one currency balance (default: the blueprint's first currency). */
|
|
293
|
-
async balance(walletId, currency) {
|
|
294
|
-
const props = await kitContainerProperties(this.gameModel, String(this.appId), walletId);
|
|
295
|
-
return Number(props[currency ?? this.defaultCurrency] ?? 0);
|
|
296
|
-
}
|
|
297
|
-
/** Read a wallet with every configured currency balance parsed. */
|
|
298
|
-
async wallet(walletId) {
|
|
299
|
-
const container = await this.gameModel.container({
|
|
300
|
-
appId: this.appId,
|
|
301
|
-
containerId: walletId,
|
|
302
|
-
});
|
|
303
|
-
const props = await kitContainerProperties(this.gameModel, String(this.appId), walletId);
|
|
304
|
-
const balances = {};
|
|
305
|
-
for (const c of this.currencies)
|
|
306
|
-
balances[c] = Number(props[c] ?? 0);
|
|
307
|
-
return {
|
|
308
|
-
containerId: container.containerId,
|
|
309
|
-
displayName: container.displayName,
|
|
310
|
-
ownerUserId: container.ownerUserId != null ? String(container.ownerUserId) : null,
|
|
311
|
-
balances,
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
/**
|
|
315
|
-
* Mint currency into a wallet — a **trusted** grant (default blueprint
|
|
316
|
-
* authority: app admins only). Resolves with the new balance.
|
|
317
|
-
*/
|
|
318
|
-
async earn(walletId, amount, currency) {
|
|
319
|
-
return kitInvoke(this.gameModel, {
|
|
320
|
-
appId: String(this.appId),
|
|
321
|
-
functionName: economyCurrencyFn('earn', currency ?? this.defaultCurrency, this.typePrefix),
|
|
322
|
-
selfContainerId: walletId,
|
|
323
|
-
params: { amount },
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
/**
|
|
327
|
-
* Spend currency from the caller's own wallet. The server refuses to
|
|
328
|
-
* overdraw. Resolves with the new balance.
|
|
329
|
-
*/
|
|
330
|
-
async spend(walletId, amount, currency) {
|
|
331
|
-
return kitInvoke(this.gameModel, {
|
|
332
|
-
appId: String(this.appId),
|
|
333
|
-
functionName: economyCurrencyFn('spend', currency ?? this.defaultCurrency, this.typePrefix),
|
|
334
|
-
selfContainerId: walletId,
|
|
335
|
-
params: { amount },
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
/** Find an existing wallet container id for a user (no creation). */
|
|
339
|
-
async ensureSellerWallet(sellerUserId) {
|
|
340
|
-
const wallets = await this.gameModel.containers({
|
|
341
|
-
appId: this.appId,
|
|
342
|
-
typeName: this.names.walletType,
|
|
343
|
-
});
|
|
344
|
-
const wallet = wallets.find((c) => c.ownerUserId != null && String(c.ownerUserId) === sellerUserId);
|
|
345
|
-
if (!wallet) {
|
|
346
|
-
throw new Error(`Seller ${sellerUserId} has no ${this.names.walletType}; they must ensureWallet() before selling`);
|
|
347
|
-
}
|
|
348
|
-
return wallet.containerId;
|
|
349
|
-
}
|
|
350
|
-
async toTrade(containerId, displayName, ownerUserId) {
|
|
351
|
-
const props = await kitContainerProperties(this.gameModel, String(this.appId), containerId);
|
|
352
|
-
return {
|
|
353
|
-
containerId,
|
|
354
|
-
displayName,
|
|
355
|
-
fromUserId: ownerUserId,
|
|
356
|
-
toUserId: Number(props.to_user_id ?? 0),
|
|
357
|
-
giveStackId: String(props.give_stack_id ?? ''),
|
|
358
|
-
receiveStackId: String(props.receive_stack_id ?? ''),
|
|
359
|
-
giveItemId: String(props.give_item_id ?? ''),
|
|
360
|
-
giveQty: Number(props.give_qty ?? 0),
|
|
361
|
-
wantItemId: String(props.want_item_id ?? ''),
|
|
362
|
-
wantQty: Number(props.want_qty ?? 0),
|
|
363
|
-
status: String(props.status ?? ''),
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
}
|
|
367
|
-
/**
|
|
368
|
-
* Order-book market methods over the market-engine (Wave 2): price-time
|
|
369
|
-
* priority matching with escrowed settlement. Deposits/withdrawals bridge
|
|
370
|
-
* to the game's wallets via compute events the game layer consumes.
|
|
371
|
-
*
|
|
372
|
-
* Obtained via `client.kit(appId).economy.market`.
|
|
373
|
-
*/
|
|
374
|
-
export class MarketKit {
|
|
375
|
-
constructor(engines, moduleName) {
|
|
376
|
-
this.engines = engines;
|
|
377
|
-
this.moduleName = moduleName;
|
|
378
|
-
}
|
|
379
|
-
/** Is the market engine deployed + enabled (cached per session)? */
|
|
380
|
-
engineAvailable() {
|
|
381
|
-
if (!this.engines)
|
|
382
|
-
return Promise.resolve(false);
|
|
383
|
-
return this.engines.has(this.moduleName);
|
|
384
|
-
}
|
|
385
|
-
/** Move coins into your market account (escrow source for bids). */
|
|
386
|
-
async depositCoins(amount) {
|
|
387
|
-
return this.invoke('deposit_coins', { amount });
|
|
388
|
-
}
|
|
389
|
-
/** Move items into your market account (escrow source for asks). */
|
|
390
|
-
async depositItems(item, quantity) {
|
|
391
|
-
return this.invoke('deposit_items', { item, quantity });
|
|
392
|
-
}
|
|
393
|
-
/** Place a limit bid: locks coins at your limit; fills at maker price. */
|
|
394
|
-
async bid(item, price, quantity) {
|
|
395
|
-
return this.invoke('place', { item, side: 'buy', price, quantity });
|
|
396
|
-
}
|
|
397
|
-
/** Place a limit ask: locks items until filled or cancelled. */
|
|
398
|
-
async ask(item, price, quantity) {
|
|
399
|
-
return this.invoke('place', { item, side: 'sell', price, quantity });
|
|
400
|
-
}
|
|
401
|
-
/** Cancel a resting order (owner only); escrow refunds instantly. */
|
|
402
|
-
async cancel(item, orderId) {
|
|
403
|
-
return this.invoke('cancel', { item, orderId });
|
|
404
|
-
}
|
|
405
|
-
/** Book depth: best bids/asks as [price, quantity] levels. */
|
|
406
|
-
async book(item) {
|
|
407
|
-
return this.invoke('book', { item });
|
|
408
|
-
}
|
|
409
|
-
/** Your market account (settled + locked balances). */
|
|
410
|
-
async account() {
|
|
411
|
-
return this.invoke('account', {});
|
|
412
|
-
}
|
|
413
|
-
/** Withdraw settled balances back to the game layer. */
|
|
414
|
-
async withdraw(input) {
|
|
415
|
-
return this.invoke('withdraw', input);
|
|
416
|
-
}
|
|
417
|
-
async invoke(exportName, params) {
|
|
418
|
-
if (!this.engines) {
|
|
419
|
-
throw new Error('market engine unavailable: compute domain not wired');
|
|
420
|
-
}
|
|
421
|
-
const result = await this.engines.invoke(this.moduleName, exportName, params);
|
|
422
|
-
if (!result.success) {
|
|
423
|
-
throw new Error(`market.${exportName} failed: ${result.reason ?? 'unknown'}`);
|
|
424
|
-
}
|
|
425
|
-
return result.body;
|
|
426
|
-
}
|
|
427
|
-
}
|
package/dist/kit/engine.d.ts
DELETED
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compute-engine capability detection + invoke envelope for the kit helpers.
|
|
3
|
-
* Games deploy engines (mob-engine, world-engine, bwf-mobs, ...) as compute
|
|
4
|
-
* modules; kit helpers probe once per module per session and route through
|
|
5
|
-
* the engine when it is present, falling back to the model/automation path
|
|
6
|
-
* when it is not — so the same client code works on model-only deployments.
|
|
7
|
-
*/
|
|
8
|
-
import type { ComputeAPI } from '../domains/compute.js';
|
|
9
|
-
/** The `{success, ...}` envelope engine invoke exports resolve with. */
|
|
10
|
-
export interface EngineInvokeResult<T = Record<string, unknown>> {
|
|
11
|
-
success: boolean;
|
|
12
|
-
/** The engine's denial reason when `success` is false. */
|
|
13
|
-
reason?: string;
|
|
14
|
-
/** The parsed result body (includes any extra fields the export returns). */
|
|
15
|
-
body: T & Record<string, unknown>;
|
|
16
|
-
fuelUsed?: string;
|
|
17
|
-
durationUs?: number;
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Per-session cached probe of which compute modules an app has enabled.
|
|
21
|
-
* Obtained internally by kit helpers; share one via `kit.engines`.
|
|
22
|
-
*/
|
|
23
|
-
export declare class EngineDetector {
|
|
24
|
-
private readonly appId;
|
|
25
|
-
private readonly compute;
|
|
26
|
-
private readonly cache;
|
|
27
|
-
constructor(appId: string, compute: ComputeAPI | undefined);
|
|
28
|
-
/**
|
|
29
|
-
* Is `moduleName` deployed + enabled? Cached per module for the client's
|
|
30
|
-
* lifetime ({@link reset} to re-probe after deploys). Resolves false when
|
|
31
|
-
* the client has no compute domain wired.
|
|
32
|
-
*/
|
|
33
|
-
has(moduleName: string): Promise<boolean>;
|
|
34
|
-
/** Drop cached probes (call after deploying/enabling modules). */
|
|
35
|
-
reset(): void;
|
|
36
|
-
/**
|
|
37
|
-
* Invoke an engine export and parse the `{success, ...}` envelope.
|
|
38
|
-
* Envelope failures (denials) resolve; every GraphQL-level error
|
|
39
|
-
* (invoke-policy FORBIDDEN, the typed invoke-contract violation —
|
|
40
|
-
* `BAD_REQUEST` "Invoke params violate ..." — a disabled module, ...) also
|
|
41
|
-
* resolves as `{ success: false, reason }` so kit callers always get
|
|
42
|
-
* gameplay-verdict semantics from compute invokes. Only non-GraphQL
|
|
43
|
-
* (transport) errors throw.
|
|
44
|
-
*/
|
|
45
|
-
invoke<T = Record<string, unknown>>(moduleName: string, exportName: string, params?: Record<string, unknown>): Promise<EngineInvokeResult<T>>;
|
|
46
|
-
private probe;
|
|
47
|
-
}
|
|
48
|
-
//# sourceMappingURL=engine.d.ts.map
|
package/dist/kit/engine.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/kit/engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,wEAAwE;AACxE,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,cAAc;IAIvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;gBAG1C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,UAAU,GAAG,SAAS;IAGlD;;;;OAIG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUzC,kEAAkE;IAClE,KAAK,IAAI,IAAI;IAIb;;;;;;;;OAQG;IACG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;YAwCnB,KAAK;CAmBpB"}
|
package/dist/kit/engine.js
DELETED
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Compute-engine capability detection + invoke envelope for the kit helpers.
|
|
3
|
-
* Games deploy engines (mob-engine, world-engine, bwf-mobs, ...) as compute
|
|
4
|
-
* modules; kit helpers probe once per module per session and route through
|
|
5
|
-
* the engine when it is present, falling back to the model/automation path
|
|
6
|
-
* when it is not — so the same client code works on model-only deployments.
|
|
7
|
-
*/
|
|
8
|
-
import { CrowdyGraphQLError } from '../errors.js';
|
|
9
|
-
/**
|
|
10
|
-
* Per-session cached probe of which compute modules an app has enabled.
|
|
11
|
-
* Obtained internally by kit helpers; share one via `kit.engines`.
|
|
12
|
-
*/
|
|
13
|
-
export class EngineDetector {
|
|
14
|
-
constructor(appId, compute) {
|
|
15
|
-
this.appId = appId;
|
|
16
|
-
this.compute = compute;
|
|
17
|
-
this.cache = new Map();
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* Is `moduleName` deployed + enabled? Cached per module for the client's
|
|
21
|
-
* lifetime ({@link reset} to re-probe after deploys). Resolves false when
|
|
22
|
-
* the client has no compute domain wired.
|
|
23
|
-
*/
|
|
24
|
-
has(moduleName) {
|
|
25
|
-
if (!this.compute)
|
|
26
|
-
return Promise.resolve(false);
|
|
27
|
-
let probe = this.cache.get(moduleName);
|
|
28
|
-
if (!probe) {
|
|
29
|
-
probe = this.probe(moduleName);
|
|
30
|
-
this.cache.set(moduleName, probe);
|
|
31
|
-
}
|
|
32
|
-
return probe;
|
|
33
|
-
}
|
|
34
|
-
/** Drop cached probes (call after deploying/enabling modules). */
|
|
35
|
-
reset() {
|
|
36
|
-
this.cache.clear();
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Invoke an engine export and parse the `{success, ...}` envelope.
|
|
40
|
-
* Envelope failures (denials) resolve; every GraphQL-level error
|
|
41
|
-
* (invoke-policy FORBIDDEN, the typed invoke-contract violation —
|
|
42
|
-
* `BAD_REQUEST` "Invoke params violate ..." — a disabled module, ...) also
|
|
43
|
-
* resolves as `{ success: false, reason }` so kit callers always get
|
|
44
|
-
* gameplay-verdict semantics from compute invokes. Only non-GraphQL
|
|
45
|
-
* (transport) errors throw.
|
|
46
|
-
*/
|
|
47
|
-
async invoke(moduleName, exportName, params) {
|
|
48
|
-
if (!this.compute) {
|
|
49
|
-
return {
|
|
50
|
-
success: false,
|
|
51
|
-
reason: 'compute domain unavailable',
|
|
52
|
-
body: {},
|
|
53
|
-
};
|
|
54
|
-
}
|
|
55
|
-
try {
|
|
56
|
-
const result = await this.compute.invoke({
|
|
57
|
-
appId: this.appId,
|
|
58
|
-
moduleName,
|
|
59
|
-
exportName,
|
|
60
|
-
...(params !== undefined ? { paramsJson: JSON.stringify(params) } : {}),
|
|
61
|
-
});
|
|
62
|
-
let body = {};
|
|
63
|
-
try {
|
|
64
|
-
body = JSON.parse(result.resultJson ?? '{}');
|
|
65
|
-
}
|
|
66
|
-
catch {
|
|
67
|
-
body = {};
|
|
68
|
-
}
|
|
69
|
-
return {
|
|
70
|
-
success: body.success !== false,
|
|
71
|
-
reason: typeof body.reason === 'string' ? body.reason : undefined,
|
|
72
|
-
body: body,
|
|
73
|
-
fuelUsed: result.fuelUsed != null ? String(result.fuelUsed) : undefined,
|
|
74
|
-
durationUs: result.durationUs != null ? Number(result.durationUs) : undefined,
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
catch (error) {
|
|
78
|
-
if (error instanceof CrowdyGraphQLError) {
|
|
79
|
-
return {
|
|
80
|
-
success: false,
|
|
81
|
-
reason: error.message,
|
|
82
|
-
body: {},
|
|
83
|
-
};
|
|
84
|
-
}
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
async probe(moduleName) {
|
|
89
|
-
if (!this.compute)
|
|
90
|
-
return false;
|
|
91
|
-
try {
|
|
92
|
-
const module = await this.compute.module({ appId: this.appId, name: moduleName });
|
|
93
|
-
return module != null && module.enabled === true;
|
|
94
|
-
}
|
|
95
|
-
catch (error) {
|
|
96
|
-
if (!(error instanceof CrowdyGraphQLError))
|
|
97
|
-
throw error;
|
|
98
|
-
if (error.code !== 'FORBIDDEN')
|
|
99
|
-
return false;
|
|
100
|
-
}
|
|
101
|
-
// Player tokens lack view_compute_diagnostics: probe via a status invoke
|
|
102
|
-
// (engines all export one). Missing modules reject; denials mean present.
|
|
103
|
-
try {
|
|
104
|
-
const result = await this.invoke(moduleName, 'status');
|
|
105
|
-
if (result.success)
|
|
106
|
-
return true;
|
|
107
|
-
return !/not found|no such module|not enabled/i.test(result.reason ?? '');
|
|
108
|
-
}
|
|
109
|
-
catch {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
package/dist/kit/features.d.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import type { GameModelAPI } from '../domains/gameModel.js';
|
|
2
|
-
import type { Scalars } from '../generated/graphql.js';
|
|
3
|
-
import type { KitInvokePolicy } from './blueprints/index.js';
|
|
4
|
-
/**
|
|
5
|
-
* Runtime **monetization** helpers — the app feature/tier surface in shop
|
|
6
|
-
* terms. Features are string keys (`'vip'`, `'land_owner'`, `'battle_pass'`)
|
|
7
|
-
* defined per app and granted to **access tiers** (the management-side
|
|
8
|
-
* `appAccess` tiers players buy/hold); any model function whose policy
|
|
9
|
-
* carries a `tier_feature` leaf then admits only players on a granted tier.
|
|
10
|
-
*
|
|
11
|
-
* Gate blueprint functions by composing {@link gate} (=`featureGate`) into a
|
|
12
|
-
* builder's `*policyExtra` option, e.g.
|
|
13
|
-
* `plotBlueprint({ buyPolicyExtra: kit.features.gate('land_owner') })`.
|
|
14
|
-
*
|
|
15
|
-
* All methods require the app-admin `manage_apps` permission.
|
|
16
|
-
*
|
|
17
|
-
* Obtained via `client.kit(appId).features`.
|
|
18
|
-
*/
|
|
19
|
-
export declare class FeaturesKit {
|
|
20
|
-
private readonly appId;
|
|
21
|
-
private readonly gameModel;
|
|
22
|
-
constructor(appId: Scalars['BigInt']['input'], gameModel: GameModelAPI);
|
|
23
|
-
/** Define (or re-describe) a feature key for the app. */
|
|
24
|
-
define(featureKey: string, description?: string): Promise<{
|
|
25
|
-
__typename?: "GmAppFeature";
|
|
26
|
-
appId: string;
|
|
27
|
-
featureKey: string;
|
|
28
|
-
description: string | null;
|
|
29
|
-
}>;
|
|
30
|
-
/** List the app's defined feature keys. */
|
|
31
|
-
list(): Promise<{
|
|
32
|
-
__typename?: "GmAppFeature";
|
|
33
|
-
appId: string;
|
|
34
|
-
featureKey: string;
|
|
35
|
-
description: string | null;
|
|
36
|
-
}[]>;
|
|
37
|
-
/** Grant a feature to an access tier (its holders pass `tier_feature` checks). */
|
|
38
|
-
grantToTier(tierId: Scalars['BigInt']['input'], featureKey: string): Promise<{
|
|
39
|
-
__typename?: "GmTierFeature";
|
|
40
|
-
appId: string;
|
|
41
|
-
tierId: string;
|
|
42
|
-
featureKey: string;
|
|
43
|
-
}>;
|
|
44
|
-
/** Revoke a feature from an access tier. */
|
|
45
|
-
revokeFromTier(tierId: Scalars['BigInt']['input'], featureKey: string): Promise<boolean>;
|
|
46
|
-
/** List tier→feature grants (optionally for one tier). */
|
|
47
|
-
tierFeatures(tierId?: Scalars['BigInt']['input']): Promise<{
|
|
48
|
-
__typename?: "GmTierFeature";
|
|
49
|
-
appId: string;
|
|
50
|
-
tierId: string;
|
|
51
|
-
featureKey: string;
|
|
52
|
-
}[]>;
|
|
53
|
-
/**
|
|
54
|
-
* A `tier_feature` policy leaf for `feature` — pass it to any blueprint
|
|
55
|
-
* builder's `*policyExtra` option to monetization-gate that function.
|
|
56
|
-
* (Also exported standalone as `featureGate`.)
|
|
57
|
-
*/
|
|
58
|
-
gate(feature: string): KitInvokePolicy;
|
|
59
|
-
}
|
|
60
|
-
//# sourceMappingURL=features.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/kit/features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY;IAG1C,yDAAyD;IACnD,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;;;;;;IAQrD,2CAA2C;IACrC,IAAI;;;;;;IAIV,kFAAkF;IAC5E,WAAW,CACf,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAClC,UAAU,EAAE,MAAM;;;;;;IASpB,4CAA4C;IACtC,cAAc,CAClB,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAClC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC;IAQnB,0DAA0D;IACpD,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;;;;;;IAOtD;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe;CAGvC"}
|