@xgamesfun/solana 0.24.0 → 0.25.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.
Files changed (92) hide show
  1. package/README.md +94 -51
  2. package/bin/xsolana.mjs +23 -8
  3. package/examples/blind-forge.json +2 -4
  4. package/examples/coin-flip-arena.json +2 -5
  5. package/examples/duel-arena.json +1 -4
  6. package/examples/fair-presale.json +1 -3
  7. package/examples/hero-trials.json +14 -2
  8. package/examples/holder-den.json +38 -0
  9. package/examples/holders-drop.json +105 -0
  10. package/examples/ideas.json +788 -788
  11. package/examples/match-predictions.json +24 -0
  12. package/examples/nft-raffle.json +1 -0
  13. package/examples/pack-league.json +108 -0
  14. package/examples/partner-vault.json +19 -3
  15. package/examples/sacrifice-raffle.json +2 -10
  16. package/examples/shelter-fair.json +1 -0
  17. package/examples/stakers-draw.json +3 -7
  18. package/examples/stride-sneakers.json +164 -0
  19. package/examples/trade-in-shop.json +2 -3
  20. package/js/approve/details.mjs +117 -48
  21. package/js/approve/ed25519.mjs +5 -1
  22. package/js/approve/live-check.mjs +83 -26
  23. package/js/approve/page.html +217 -78
  24. package/js/approve/page.js +43 -15
  25. package/js/approve/server.mjs +276 -74
  26. package/js/chain/base58.js +7 -1
  27. package/js/chain/borsh.js +15 -11
  28. package/js/chain/bytes.js +11 -8
  29. package/js/chain/core.js +21 -5
  30. package/js/chain/curve.js +1 -1
  31. package/js/chain/lookup.js +118 -36
  32. package/js/chain/mint.js +6 -2
  33. package/js/chain/pda.js +2 -2
  34. package/js/chain/programs.js +6 -6
  35. package/js/chain/rpc.js +40 -14
  36. package/js/chain/token.js +13 -2
  37. package/js/chain/token2022.js +55 -16
  38. package/js/chain/tx.js +32 -22
  39. package/js/client/accounts.js +270 -80
  40. package/js/client/compressed.js +4 -3
  41. package/js/client/grant.js +165 -40
  42. package/js/client/idl/loot.js +1 -1
  43. package/js/client/idl/loot.json +104 -16
  44. package/js/client/ix.js +2121 -457
  45. package/js/client/pda.js +20 -18
  46. package/js/client/policy.js +12 -5
  47. package/js/client/random.js +1 -1
  48. package/js/client/sizes.js +220 -65
  49. package/js/client/traits.js +14 -5
  50. package/js/connect/connect.mjs +59 -17
  51. package/js/economy/check.mjs +3873 -690
  52. package/js/economy/cost.mjs +380 -56
  53. package/js/economy/examples.mjs +176 -35
  54. package/js/economy/explain.mjs +461 -110
  55. package/js/economy/guide.mjs +282 -59
  56. package/js/economy/legal.mjs +12 -6
  57. package/js/economy/live.mjs +60 -19
  58. package/js/economy/model.mjs +320 -97
  59. package/js/economy/plan.mjs +1022 -203
  60. package/js/economy/schema.json +127 -369
  61. package/js/economy/secrets.mjs +17 -7
  62. package/js/economy/simulate.mjs +771 -178
  63. package/js/economy/txsize.mjs +15 -3
  64. package/js/economy/validate.mjs +61 -24
  65. package/js/mcp/server.mjs +42 -14
  66. package/js/mcp/tools.mjs +293 -80
  67. package/js/play/index.js +1960 -461
  68. package/js/play/keys.js +35 -9
  69. package/js/results/index.js +223 -30
  70. package/js/results/server.js +230 -0
  71. package/js/results/wire.js +64 -16
  72. package/package.json +6 -4
  73. package/release.json +5 -5
  74. package/skills/xsolana-economy/SKILL.md +30 -16
  75. package/skills/xsolana-economy/references/after-launch.md +30 -20
  76. package/skills/xsolana-economy/references/apps.md +47 -36
  77. package/skills/xsolana-economy/references/sentence-to-spec.md +148 -129
  78. package/skills/xsolana-economy/references/telling-the-person.md +9 -6
  79. package/types/chain/core.d.ts +1 -1
  80. package/types/chain/lookup.d.ts +1 -1
  81. package/types/client/accounts.d.ts +24 -3
  82. package/types/client/grant.d.ts +2 -2
  83. package/types/client/idl/loot.d.ts +22 -0
  84. package/types/client/ix.d.ts +54 -45
  85. package/types/client/pda.d.ts +3 -1
  86. package/types/economy/guide.d.mts +5 -0
  87. package/types/economy/model.d.mts +48 -3
  88. package/types/economy/plan.d.mts +44 -2
  89. package/types/play/index.d.ts +8 -19
  90. package/types/results/index.d.ts +7 -6
  91. package/types/results/server.d.ts +126 -0
  92. package/types/results/wire.d.ts +1 -1
@@ -4,9 +4,7 @@
4
4
  "title": "A loot economy (spec version 2)",
5
5
  "description": "One project's economy on the shared loot program: its currencies, collectibles, pools and the mechanics that move them. Kept as xsolana.json in a project (or as the `economy` section of a games.fun game). Amounts are in whole units of their token, percents are percents, durations are like \"7d\".",
6
6
  "type": "object",
7
- "required": [
8
- "version"
9
- ],
7
+ "required": ["version"],
10
8
  "additionalProperties": false,
11
9
  "properties": {
12
10
  "version": {
@@ -164,10 +162,7 @@
164
162
  "items": {
165
163
  "type": "object",
166
164
  "additionalProperties": false,
167
- "required": [
168
- "collection",
169
- "root"
170
- ],
165
+ "required": ["collection", "root"],
171
166
  "properties": {
172
167
  "collection": {
173
168
  "$ref": "#/$defs/address",
@@ -288,10 +283,7 @@
288
283
  },
289
284
  "share": {
290
285
  "type": "object",
291
- "required": [
292
- "to",
293
- "percent"
294
- ],
286
+ "required": ["to", "percent"],
295
287
  "additionalProperties": false,
296
288
  "properties": {
297
289
  "to": {
@@ -324,10 +316,7 @@
324
316
  },
325
317
  "fall": {
326
318
  "type": "object",
327
- "required": [
328
- "step",
329
- "every"
330
- ],
319
+ "required": ["step", "every"],
331
320
  "additionalProperties": false,
332
321
  "description": "The price falls by `step` every `every`, from `start`, never below `floor`. A sale does not put the price back up: it stays at what was paid. By default (\"clock\": \"sale\") the next step comes `every` after that sale, so steady sales hold the price where it is. With \"clock\": \"shared\" the steps keep their own clock, sales or not: a Dutch drop that keeps falling however often it sells.",
333
322
  "properties": {
@@ -344,10 +333,7 @@
344
333
  "$ref": "#/$defs/time"
345
334
  },
346
335
  "clock": {
347
- "enum": [
348
- "sale",
349
- "shared"
350
- ],
336
+ "enum": ["sale", "shared"],
351
337
  "default": "sale"
352
338
  }
353
339
  }
@@ -375,10 +361,7 @@
375
361
  },
376
362
  "token": {
377
363
  "type": "object",
378
- "required": [
379
- "key",
380
- "source"
381
- ],
364
+ "required": ["key", "source"],
382
365
  "additionalProperties": false,
383
366
  "description": "A currency. `sol`: SOL (players pay in wrapped SOL). `existing`: any mint by address, launched anywhere, classic or Token-2022, pump.fun included (games.fun takes no share of its fees). `project` (`game` is its older spelling): a token made when the economy goes live: the project mints it as its rules say (points, tickets, shards), or, with `supply`, a fixed supply minted once to the owner (a community token you keep).",
384
367
  "properties": {
@@ -386,12 +369,7 @@
386
369
  "$ref": "#/$defs/key"
387
370
  },
388
371
  "source": {
389
- "enum": [
390
- "sol",
391
- "existing",
392
- "project",
393
- "game"
394
- ],
372
+ "enum": ["sol", "existing", "project", "game"],
395
373
  "description": "`project` (`game` is its older spelling): a token made when the economy goes live, which the project mints. Such a token names no `mint`: the setup makes it."
396
374
  },
397
375
  "name": {
@@ -412,22 +390,14 @@
412
390
  "description": "`project` only: a fixed supply. Going live makes the token, mints all of it to the owner's wallet and turns minting off for good, so nobody (the project included) can ever make more. Pools are seeded from it. Leave it out for a token the project mints as its rules say (points, rewards, an emission)."
413
391
  },
414
392
  "program": {
415
- "enum": [
416
- "spl-token",
417
- "token-2022"
418
- ],
393
+ "enum": ["spl-token", "token-2022"],
419
394
  "default": "spl-token"
420
395
  },
421
396
  "mint": {
422
397
  "$ref": "#/$defs/address"
423
398
  },
424
399
  "venue": {
425
- "enum": [
426
- "games.fun",
427
- "pump.fun",
428
- "meteora",
429
- "other"
430
- ],
400
+ "enum": ["games.fun", "pump.fun", "meteora", "other"],
431
401
  "description": "Where the token trades, recorded for the app and not read or enforced by the tools: loot doesn't launch or trade tokens. A token launched elsewhere is `existing`, by its mint."
432
402
  },
433
403
  "uri": {
@@ -443,12 +413,7 @@
443
413
  "description": "What the mint's own keys can do, as far as the creator knows. The checker warns about each one.",
444
414
  "properties": {
445
415
  "mintAuthority": {
446
- "enum": [
447
- "game",
448
- "someone else",
449
- "none",
450
- "project"
451
- ]
416
+ "enum": ["game", "someone else", "none", "project"]
452
417
  },
453
418
  "freeze": {
454
419
  "type": "boolean"
@@ -485,9 +450,7 @@
485
450
  },
486
451
  "collection": {
487
452
  "type": "object",
488
- "required": [
489
- "name"
490
- ],
453
+ "required": ["name"],
491
454
  "additionalProperties": false,
492
455
  "description": "The Metaplex Core collection the game's collectibles are minted into.",
493
456
  "properties": {
@@ -515,10 +478,7 @@
515
478
  },
516
479
  "item": {
517
480
  "type": "object",
518
- "required": [
519
- "key",
520
- "name"
521
- ],
481
+ "required": ["key", "name"],
522
482
  "additionalProperties": false,
523
483
  "properties": {
524
484
  "key": {
@@ -537,24 +497,14 @@
537
497
  "$ref": "#/$defs/words"
538
498
  },
539
499
  "kind": {
540
- "enum": [
541
- "collectible",
542
- "normal"
543
- ],
500
+ "enum": ["collectible", "normal"],
544
501
  "default": "collectible",
545
502
  "description": "A collectible is minted to the player's wallet; a normal item lives in the project's own backend and the chain records the sale."
546
503
  },
547
504
  "rarity": {
548
505
  "anyOf": [
549
506
  {
550
- "enum": [
551
- "Common",
552
- "Uncommon",
553
- "Rare",
554
- "Epic",
555
- "Legendary",
556
- "Mythic"
557
- ]
507
+ "enum": ["Common", "Uncommon", "Rare", "Epic", "Legendary", "Mythic"]
558
508
  },
559
509
  {
560
510
  "type": "integer",
@@ -653,13 +603,11 @@
653
603
  },
654
604
  "drawn": {
655
605
  "type": "array",
656
- "description": "A fresh collectible: at most 64 traits drawn for each unit, in order, written on it, each attribute's name at most 64 bytes. Each from a table (`\"table\": key`, a row by weight among those in stock, drawn atomically with the box's roll) or a range (`\"min\"`/`\"max\"`, every whole number as likely, drawn at the mint from the same answer). Its name and link may contain `{attribute}` for each, beside `{serial}`. A fresh item is given only by a box's roll.",
606
+ "description": "A fresh collectible: at most 64 traits drawn for each unit, in order, written on it, each attribute's name at most 64 bytes. Each from a table (`\"table\": key`, a row by weight among those in stock, drawn atomically with the box's roll) or a range (`\"min\"`/`\"max\"`, every whole number as likely, drawn at the mint from the same answer). Its name and link may contain `{attribute}` for each, and its link `{serial}` (the name always ends with “ #<serial>”). A fresh item is given only by a box's roll.",
657
607
  "items": {
658
608
  "type": "object",
659
609
  "additionalProperties": false,
660
- "required": [
661
- "attribute"
662
- ],
610
+ "required": ["attribute"],
663
611
  "properties": {
664
612
  "attribute": {
665
613
  "type": "string",
@@ -683,10 +631,7 @@
683
631
  },
684
632
  "pool": {
685
633
  "type": "object",
686
- "required": [
687
- "key",
688
- "currency"
689
- ],
634
+ "required": ["key", "currency"],
690
635
  "additionalProperties": false,
691
636
  "description": "A vault only the game can spend from: a prize pool, a lottery's pot, stakers' rewards.",
692
637
  "properties": {
@@ -713,23 +658,12 @@
713
658
  },
714
659
  "outcome": {
715
660
  "type": "object",
716
- "required": [
717
- "gives"
718
- ],
661
+ "required": ["gives"],
719
662
  "additionalProperties": false,
720
663
  "description": "One way a box can land: an item, a fixed amount of tokens from a pool (`pay`) or minted (`tokens`), all of it or none, an NFT of a stash at random (`stash`) or a named one (`nft`), a roll of another box (`roll`), any number of them together (`bundle`), or nothing. Give every outcome a `chance` (percents that add up to 100) or every one a `weight`. In a box that rolls on an NFT (`rollsOn`), an outcome can also move numbers on it (`shifts`) and say where it goes (`then`). A box of one outcome that needs no chance sells in one step (`buy`): no order, no settle. A box burns its price with a \"burn\" share in its `split`, whatever the roll gives.",
721
664
  "properties": {
722
665
  "gives": {
723
- "enum": [
724
- "item",
725
- "pay",
726
- "stash",
727
- "tokens",
728
- "nft",
729
- "roll",
730
- "bundle",
731
- "nothing"
732
- ]
666
+ "enum": ["item", "pay", "stash", "tokens", "nft", "roll", "bundle", "nothing"]
733
667
  },
734
668
  "chance": {
735
669
  "type": "number",
@@ -756,10 +690,7 @@
756
690
  "items": {
757
691
  "type": "object",
758
692
  "additionalProperties": false,
759
- "required": [
760
- "attribute",
761
- "by"
762
- ],
693
+ "required": ["attribute", "by"],
763
694
  "properties": {
764
695
  "attribute": {
765
696
  "type": "string",
@@ -807,18 +738,12 @@
807
738
  "description": "For a box that rolls on an NFT: where the NFT goes after this outcome. \"back\" (the default) to whoever brought it; \"burn\" (a Core asset burned; any other kind sent to the incinerator's address, where nobody can move it); \"treasury\" to the game's treasury wallet; { \"giveTo\": \"<wallet>\" } to that wallet. A box with any outcome that burns or gives the NFT away takes it into the game's hands when it is rolled, until the roll is settled (a custodial route). { \"stash\": \"<key>\" }: into one of the spec's stashes, a trade-in that becomes another player's prize.",
808
739
  "anyOf": [
809
740
  {
810
- "enum": [
811
- "back",
812
- "burn",
813
- "treasury"
814
- ]
741
+ "enum": ["back", "burn", "treasury"]
815
742
  },
816
743
  {
817
744
  "type": "object",
818
745
  "additionalProperties": false,
819
- "required": [
820
- "giveTo"
821
- ],
746
+ "required": ["giveTo"],
822
747
  "properties": {
823
748
  "giveTo": {
824
749
  "$ref": "#/$defs/address"
@@ -828,9 +753,7 @@
828
753
  {
829
754
  "type": "object",
830
755
  "additionalProperties": false,
831
- "required": [
832
- "stash"
833
- ],
756
+ "required": ["stash"],
834
757
  "properties": {
835
758
  "stash": {
836
759
  "$ref": "#/$defs/key"
@@ -866,9 +789,7 @@
866
789
  "description": "For bundle: what it gives together, any number: each { gives: item | pay | share | stash | tokens | nft | roll, … } as an outcome of one says.",
867
790
  "items": {
868
791
  "type": "object",
869
- "required": [
870
- "gives"
871
- ],
792
+ "required": ["gives"],
872
793
  "additionalProperties": false,
873
794
  "properties": {
874
795
  "item": {
@@ -902,14 +823,7 @@
902
823
  "description": "For roll: the box rolled for the player when the order settles."
903
824
  },
904
825
  "gives": {
905
- "enum": [
906
- "item",
907
- "pay",
908
- "stash",
909
- "tokens",
910
- "nft",
911
- "roll"
912
- ]
826
+ "enum": ["item", "pay", "stash", "tokens", "nft", "roll"]
913
827
  },
914
828
  "compressed": {
915
829
  "type": "boolean",
@@ -926,12 +840,7 @@
926
840
  },
927
841
  "box": {
928
842
  "type": "object",
929
- "required": [
930
- "key",
931
- "name",
932
- "price",
933
- "outcomes"
934
- ],
843
+ "required": ["key", "name", "price", "outcomes"],
935
844
  "additionalProperties": false,
936
845
  "properties": {
937
846
  "key": {
@@ -966,10 +875,7 @@
966
875
  "description": "Each item's chance shrinks with what is left of its supply."
967
876
  },
968
877
  "whenOut": {
969
- "enum": [
970
- "stopSales",
971
- "drawLeft"
972
- ],
878
+ "enum": ["stopSales", "drawLeft"],
973
879
  "default": "stopSales",
974
880
  "description": "What a box that rolls does once an outcome can't be given (an item sold out, a pool short of its prize, a stash empty). \"stopSales\" (the default): it isn't sold while any outcome couldn't cover this purchase's draws and those of purchases still waiting for their answer, so every roll is on the odds written, and the project restocks or edits the box to sell again. \"drawLeft\": it keeps selling, and a roll draws among the outcomes still there by their written weights, so the others' chances rise as one runs out: a player can empty a common outcome to make a rare one likelier. A box selling a rare prize keeps \"stopSales\"."
975
881
  },
@@ -1023,18 +929,12 @@
1023
929
  "description": "Where the NFT it rolls on goes after an outcome that names no `then` of its own: a box that takes an NFT as its price (`rollsOn` its rule, `then` \"burn\", \"treasury\", { giveTo } or { stash }).",
1024
930
  "anyOf": [
1025
931
  {
1026
- "enum": [
1027
- "back",
1028
- "burn",
1029
- "treasury"
1030
- ]
932
+ "enum": ["back", "burn", "treasury"]
1031
933
  },
1032
934
  {
1033
935
  "type": "object",
1034
936
  "additionalProperties": false,
1035
- "required": [
1036
- "giveTo"
1037
- ],
937
+ "required": ["giveTo"],
1038
938
  "properties": {
1039
939
  "giveTo": {
1040
940
  "$ref": "#/$defs/address"
@@ -1044,9 +944,7 @@
1044
944
  {
1045
945
  "type": "object",
1046
946
  "additionalProperties": false,
1047
- "required": [
1048
- "stash"
1049
- ],
947
+ "required": ["stash"],
1050
948
  "properties": {
1051
949
  "stash": {
1052
950
  "$ref": "#/$defs/key"
@@ -1061,9 +959,7 @@
1061
959
  "items": {
1062
960
  "type": "object",
1063
961
  "additionalProperties": false,
1064
- "required": [
1065
- "count"
1066
- ],
962
+ "required": ["count"],
1067
963
  "properties": {
1068
964
  "count": {
1069
965
  "type": "integer",
@@ -1093,11 +989,7 @@
1093
989
  },
1094
990
  "payment": {
1095
991
  "type": "object",
1096
- "required": [
1097
- "key",
1098
- "name",
1099
- "amount"
1100
- ],
992
+ "required": ["key", "name", "amount"],
1101
993
  "additionalProperties": false,
1102
994
  "description": "A payment a player signs for something the game gives off chain: an entry fee, an attempt at a level, a tip.",
1103
995
  "properties": {
@@ -1126,22 +1018,12 @@
1126
1018
  },
1127
1019
  "input": {
1128
1020
  "type": "object",
1129
- "required": [
1130
- "takes"
1131
- ],
1021
+ "required": ["takes"],
1132
1022
  "additionalProperties": false,
1133
1023
  "description": "burn: `count` collectibles of `item`, burned. use: one collectible of `item`, kept (counts a use of its life). renew: one kept, its uses counted from zero again (its `used` count). staked: one collectible of `item`, kept as `use` keeps it, that must be staked in `farm`: on its own seat in that farm of this spec, which escrows or freezes it (a watched one could be sold). A set bound into a badge takes its pieces this way and moves that farm's `lockAttribute` far ahead, so they stay staked while the badge exists; a recipe that raises anything on a staked piece must raise its farm's `lockAttribute` (to raise a stat and leave the lock alone, use `use`). show: one NFT of `collection` the player holds, kept (any Core NFT, or a Token Metadata NFT verified in it; the game's own collection when left out), read with what the game wrote in its Sheet. pay: `amount` of `currency`, sent `to` a destination. trade: one NFT of `collection` the player holds, any kind, traded in: burned, given on, or put in a stash (`then`).",
1134
1024
  "properties": {
1135
1025
  "takes": {
1136
- "enum": [
1137
- "burn",
1138
- "use",
1139
- "renew",
1140
- "show",
1141
- "staked",
1142
- "pay",
1143
- "trade"
1144
- ]
1026
+ "enum": ["burn", "use", "renew", "show", "staked", "pay", "trade"]
1145
1027
  },
1146
1028
  "item": {
1147
1029
  "$ref": "#/$defs/key"
@@ -1176,19 +1058,12 @@
1176
1058
  },
1177
1059
  "output": {
1178
1060
  "type": "object",
1179
- "required": [
1180
- "gives"
1181
- ],
1061
+ "required": ["gives"],
1182
1062
  "additionalProperties": false,
1183
1063
  "description": "A prize (see `prize`), or a roll on a collectible the recipe keeps: { \"gives\": \"roll\", \"box\": key, \"on\": place } (a risky upgrade; the player or the project’s keys ask the oracle and settle it). A craft refuses a prize it can't give (a pool that holds less, an item sold out or switched off, an NFT gone).",
1184
1064
  "properties": {
1185
1065
  "gives": {
1186
- "enum": [
1187
- "item",
1188
- "tokens",
1189
- "nft",
1190
- "roll"
1191
- ]
1066
+ "enum": ["item", "tokens", "nft", "roll"]
1192
1067
  },
1193
1068
  "item": {
1194
1069
  "$ref": "#/$defs/key"
@@ -1230,11 +1105,7 @@
1230
1105
  },
1231
1106
  "recipe": {
1232
1107
  "type": "object",
1233
- "required": [
1234
- "key",
1235
- "name",
1236
- "in"
1237
- ],
1108
+ "required": ["key", "name", "in"],
1238
1109
  "additionalProperties": false,
1239
1110
  "properties": {
1240
1111
  "key": {
@@ -1269,11 +1140,7 @@
1269
1140
  "type": "array",
1270
1141
  "items": {
1271
1142
  "type": "object",
1272
- "required": [
1273
- "place",
1274
- "key",
1275
- "atLeast"
1276
- ],
1143
+ "required": ["place", "key", "atLeast"],
1277
1144
  "additionalProperties": false,
1278
1145
  "description": "The collectible handed in at `place` (the first is 0) must carry a number `key` the authority wrote of at least `atLeast`.",
1279
1146
  "properties": {
@@ -1298,11 +1165,7 @@
1298
1165
  "type": "array",
1299
1166
  "items": {
1300
1167
  "type": "object",
1301
- "required": [
1302
- "key",
1303
- "from",
1304
- "to"
1305
- ],
1168
+ "required": ["key", "from", "to"],
1306
1169
  "additionalProperties": false,
1307
1170
  "description": "The new collectible `to` (the first made is 0) takes attribute `key` from the one handed in at `from`.",
1308
1171
  "properties": {
@@ -1328,11 +1191,7 @@
1328
1191
  "description": "Numbers the recipe moves on collectibles handed in and kept (use, renew, show): a level or a stat bought with the recipe's own payment, or one it costs (a negative `by`: a merge that costs a level, never below 0). Written on the NFT when the game has authority over it, in its Sheet otherwise. One already at `upTo` is refused (MaxedOut) when raising. With `fromNow`, it moves a time: fuel for a day more (\"by\": \"1d\", \"upTo\": \"3d\"), a day off a lock (\"by\": \"-1d\").",
1329
1192
  "items": {
1330
1193
  "type": "object",
1331
- "required": [
1332
- "place",
1333
- "key",
1334
- "by"
1335
- ],
1194
+ "required": ["place", "key", "by"],
1336
1195
  "additionalProperties": false,
1337
1196
  "properties": {
1338
1197
  "place": {
@@ -1404,11 +1263,7 @@
1404
1263
  },
1405
1264
  "schedule": {
1406
1265
  "type": "object",
1407
- "required": [
1408
- "key",
1409
- "does",
1410
- "every"
1411
- ],
1266
+ "required": ["key", "does", "every"],
1412
1267
  "additionalProperties": false,
1413
1268
  "description": "issue: mint `amount` of a game token into `pool`, halving every `halveEvery` runs. burn: burn `percent` (or `amount`) of what `pool` holds. move: move `percent` (or `amount`) of what pool `from` holds into pool `to`. pay: pay `amount` (or `percent`) from pool `from` `to` a wallet (\"wallet:<address>\"), a token account (\"account:<token account>\") or a collectible's holder (\"holder:<asset>\") on each run: a payroll, a vesting drip, a landlord's rent. Anyone may run it when it is due.",
1414
1269
  "properties": {
@@ -1425,12 +1280,7 @@
1425
1280
  "maxLength": 40
1426
1281
  },
1427
1282
  "does": {
1428
- "enum": [
1429
- "issue",
1430
- "burn",
1431
- "move",
1432
- "pay"
1433
- ]
1283
+ "enum": ["issue", "burn", "move", "pay"]
1434
1284
  },
1435
1285
  "currency": {
1436
1286
  "$ref": "#/$defs/key"
@@ -1500,9 +1350,14 @@
1500
1350
  },
1501
1351
  "lottery": {
1502
1352
  "type": "object",
1503
- "required": [
1504
- "key",
1505
- "name"
1353
+ "required": ["key", "name"],
1354
+ "oneOf": [
1355
+ {
1356
+ "required": ["pot"]
1357
+ },
1358
+ {
1359
+ "required": ["rest"]
1360
+ }
1506
1361
  ],
1507
1362
  "additionalProperties": false,
1508
1363
  "properties": {
@@ -1520,15 +1375,25 @@
1520
1375
  },
1521
1376
  "price": {
1522
1377
  "$ref": "#/$defs/amount",
1523
- "description": "One ticket, in the pot's currency (or in `ticketCurrency`). Leave it out for a lottery whose tickets cost an NFT (`ticketNft`)."
1378
+ "description": "One ticket, in the lottery's currency (or in `ticketCurrency`). Leave it out for a lottery whose tickets cost an NFT (`ticketNft`)."
1524
1379
  },
1525
1380
  "ticketCurrency": {
1526
1381
  "$ref": "#/$defs/key",
1527
- "description": "Tickets paid in another token are burned, and the pot is filled from elsewhere."
1382
+ "description": "Tickets paid in another token are burned, and no ticket money reaches the places: they are paid from what reaches the pot from elsewhere (\"pot\")."
1528
1383
  },
1529
1384
  "cutPercent": {
1530
1385
  "$ref": "#/$defs/percent",
1531
- "description": "The share of ticket money that goes to the treasury instead of the pot (the same as a split share to \"treasury\")."
1386
+ "description": "The share of ticket money that goes to the treasury before the places (the same as a split share to \"treasury\")."
1387
+ },
1388
+ "pot": {
1389
+ "type": "integer",
1390
+ "minimum": 0,
1391
+ "maximum": 15,
1392
+ "description": "Pays its places from a pot it keeps from round to round, this one of its 16 (0 unless it moves to a fresh one): each place takes its percent of what the pot holds at the draw with the round's ticket money, so the seed, gifts and shares sent to it (\"lottery:<key>\"), yield, and what earlier rounds' places left all count, and the next round always starts with what the round before left. Write exactly one of \"pot\" or \"rest\". A no-loss lottery needs a pot. Changing the number between rounds starts a fresh pot; every pot it opened is emptied to the owner when it closes."
1393
+ },
1394
+ "rest": {
1395
+ "$ref": "#/$defs/destination",
1396
+ "description": "Pays each round's places from that round's own ticket money only, and sends what they leave here: \"treasury\", \"burn\", \"wallet:<address>\", \"account:<token account>\", \"holder:<collectible>\", a pool, a farm or another lottery (\"lottery:<key>\"), never \"chosen\" or itself; a pool, farm or lottery named here counts the leftover only once someone pulls it. Nothing from outside can change a round's prizes: no seed, no gifts, no carry-over. Write exactly one of \"pot\" or \"rest\"."
1532
1397
  },
1533
1398
  "places": {
1534
1399
  "type": "array",
@@ -1551,7 +1416,7 @@
1551
1416
  },
1552
1417
  "prize": {
1553
1418
  "$ref": "#/$defs/prize",
1554
- "description": "What its winner gets besides its share of the pot: a raffled NFT, a collectible, tokens, a roll of a box."
1419
+ "description": "What its winner gets besides its percent of the money: a raffled NFT, a collectible, tokens, a roll of a box."
1555
1420
  },
1556
1421
  "times": {
1557
1422
  "type": "integer",
@@ -1563,7 +1428,7 @@
1563
1428
  }
1564
1429
  ]
1565
1430
  },
1566
- "description": "What each place wins, first place first: a percent of the pot, or { \"percent\", \"prize\", \"times\" }: a share of the pot and a prize for its winner (either, or both), for `times` places in a row. Default: one winner takes all."
1431
+ "description": "What each place wins, first place first: a percent of what the round pays from (its pot with the round's ticket money, or with \"rest\" that round's ticket money alone), or { \"percent\", \"prize\", \"times\" }: a percent and a prize for its winner (either, or both), for `times` places in a row. Default: one winner takes all."
1567
1432
  },
1568
1433
  "every": {
1569
1434
  "$ref": "#/$defs/duration",
@@ -1577,11 +1442,11 @@
1577
1442
  },
1578
1443
  "currency": {
1579
1444
  "$ref": "#/$defs/key",
1580
- "description": "The pot's token. Default: the game's currency."
1445
+ "description": "The token tickets are paid in and the places are paid in (and the pot's, with \"pot\"). Default: the game's currency."
1581
1446
  },
1582
1447
  "seed": {
1583
1448
  "$ref": "#/$defs/amount",
1584
- "description": "What the owner puts in the pot at go-live."
1449
+ "description": "What the owner puts in the pot at go-live (a lottery with \"pot\" only)."
1585
1450
  },
1586
1451
  "roundRent": {
1587
1452
  "$ref": "#/$defs/amount",
@@ -1606,7 +1471,7 @@
1606
1471
  },
1607
1472
  "split": {
1608
1473
  "$ref": "#/$defs/split",
1609
- "description": "Where ticket money goes before the pot (the rest goes into the pot): a charity, a referrer the buyer names (\"chosen\"), the treasury."
1474
+ "description": "Where ticket money goes before the places (the rest is the round's money for its places): a charity, a referrer the buyer names (\"chosen\"), the treasury."
1610
1475
  },
1611
1476
  "perWallet": {
1612
1477
  "type": "integer",
@@ -1616,11 +1481,11 @@
1616
1481
  },
1617
1482
  "ticketNft": {
1618
1483
  "$ref": "#/$defs/nftPrice",
1619
- "description": "A ticket costs one NFT that passes the rule, in place of tokens: held until the draw, then burned, given on or stashed; back to its buyer if the draw is cancelled. Such a lottery has no price and no split; its pot is what the owner and its places' prizes put in."
1484
+ "description": "A ticket costs one NFT that passes the rule, in place of tokens: held until the draw, then burned, given on or stashed; back to its buyer if the draw is cancelled. Such a lottery has no price and no split; its places are paid from what the owner and others put in its pot (\"pot\"), and its places' prizes."
1620
1485
  },
1621
1486
  "noLoss": {
1622
1487
  "type": "boolean",
1623
- "description": "A no-loss lottery: every ticket goes back to its buyer once the round is drawn, and the winners take only the pot, what is paid into it (`seed`, a sponsor, a share of other sales: \"lottery:<key>\"). No split, no cut and no `ticketCurrency`; NFT tickets come back too."
1488
+ "description": "A no-loss lottery: every ticket goes back to its buyer once the round is drawn, and the winners take only the pot, what is paid into it (`seed`, a sponsor, a share of other sales: \"lottery:<key>\"). It needs \"pot\". No split, no cut and no `ticketCurrency`; NFT tickets come back too."
1624
1489
  },
1625
1490
  "minSold": {
1626
1491
  "type": "integer",
@@ -1636,9 +1501,7 @@
1636
1501
  {
1637
1502
  "type": "object",
1638
1503
  "additionalProperties": false,
1639
- "required": [
1640
- "nft"
1641
- ],
1504
+ "required": ["nft"],
1642
1505
  "properties": {
1643
1506
  "nft": {
1644
1507
  "$ref": "#/$defs/address"
@@ -1663,9 +1526,7 @@
1663
1526
  {
1664
1527
  "type": "object",
1665
1528
  "additionalProperties": false,
1666
- "required": [
1667
- "nft"
1668
- ],
1529
+ "required": ["nft"],
1669
1530
  "properties": {
1670
1531
  "nft": {
1671
1532
  "$ref": "#/$defs/address"
@@ -1680,15 +1541,11 @@
1680
1541
  "description": "NFTs the lottery's own stash holds for its places that give { \"gives\": \"raffled\" } (each draws one at random with the round's answer): a raffle of many NFTs. Your wallet puts them in at go-live, a group a transaction, before the lottery is written; at least as many as such places. The lottery draws once."
1681
1542
  }
1682
1543
  },
1683
- "description": "Tickets into a pot of the lottery's own, one random draw, the winners paid. Nothing but its winners' payouts takes from the pot: not the authority, a schedule, a farm or a recipe. Anything sold or paid can send it a share (\"lottery:<key>\" in a split); a schedule can't pay a lottery."
1544
+ "description": "Tickets sold in rounds, one random draw a round, the winners paid. It names where its places are paid from, exactly one of: \"pot\", a pot of its own kept from round to round that anything can add to (a seed, a share of a sale or payment, \"lottery:<key>\" in a split, a schedule that pays \"lottery:<key>\"); or \"rest\", each round's own ticket money alone, what the places leave going to that destination. Nothing but its winners' payouts takes from a pot: not the authority, a schedule, a farm or a recipe."
1684
1545
  },
1685
1546
  "contest": {
1686
1547
  "type": "object",
1687
- "required": [
1688
- "key",
1689
- "name",
1690
- "sides"
1691
- ],
1548
+ "required": ["key", "name", "sides"],
1692
1549
  "additionalProperties": false,
1693
1550
  "description": "Players put money on a side; the side that wins shares the pot. The authority opens each one while the game runs, and the authority or one of its `deciders` (a results server's key) names the side that won. One side and a `minPot` is an all-or-nothing crowdfund; a wallet gate and a `stake` is a duel.",
1694
1551
  "properties": {
@@ -1769,12 +1626,7 @@
1769
1626
  },
1770
1627
  "auction": {
1771
1628
  "type": "object",
1772
- "required": [
1773
- "key",
1774
- "name",
1775
- "lot",
1776
- "runs"
1777
- ],
1629
+ "required": ["key", "name", "lot", "runs"],
1778
1630
  "additionalProperties": false,
1779
1631
  "description": "An English auction, opened when the economy goes live: the highest bid when the time runs out wins the lot. Each bid must reach the reserve and top the last by the least raise; a bid that is topped goes back to its bidder at once. A late bid moves the end. With no bid the lot goes home.",
1780
1632
  "properties": {
@@ -1804,9 +1656,7 @@
1804
1656
  "oneOf": [
1805
1657
  {
1806
1658
  "type": "object",
1807
- "required": [
1808
- "item"
1809
- ],
1659
+ "required": ["item"],
1810
1660
  "additionalProperties": false,
1811
1661
  "properties": {
1812
1662
  "item": {
@@ -1816,9 +1666,7 @@
1816
1666
  },
1817
1667
  {
1818
1668
  "type": "object",
1819
- "required": [
1820
- "asset"
1821
- ],
1669
+ "required": ["asset"],
1822
1670
  "additionalProperties": false,
1823
1671
  "properties": {
1824
1672
  "asset": {
@@ -1832,9 +1680,7 @@
1832
1680
  },
1833
1681
  {
1834
1682
  "type": "object",
1835
- "required": [
1836
- "roll"
1837
- ],
1683
+ "required": ["roll"],
1838
1684
  "additionalProperties": false,
1839
1685
  "properties": {
1840
1686
  "roll": {
@@ -1880,11 +1726,7 @@
1880
1726
  },
1881
1727
  "hold": {
1882
1728
  "type": "object",
1883
- "required": [
1884
- "key",
1885
- "name",
1886
- "item"
1887
- ],
1729
+ "required": ["key", "name", "item"],
1888
1730
  "additionalProperties": false,
1889
1731
  "description": "A player hands a collectible to the game for a time they choose; until it is up the authority says where it goes, after it anyone can send it home.",
1890
1732
  "properties": {
@@ -1914,11 +1756,7 @@
1914
1756
  },
1915
1757
  "decision": {
1916
1758
  "type": "object",
1917
- "required": [
1918
- "key",
1919
- "when",
1920
- "does"
1921
- ],
1759
+ "required": ["key", "when", "does"],
1922
1760
  "additionalProperties": false,
1923
1761
  "description": "A rule only the game can carry out, signed by the authority while the game runs.",
1924
1762
  "properties": {
@@ -1929,18 +1767,7 @@
1929
1767
  "$ref": "#/$defs/words"
1930
1768
  },
1931
1769
  "does": {
1932
- "enum": [
1933
- "payout",
1934
- "burn",
1935
- "issue",
1936
- "make",
1937
- "unmake",
1938
- "set",
1939
- "award",
1940
- "decide",
1941
- "roll",
1942
- "open_contest"
1943
- ]
1770
+ "enum": ["payout", "burn", "issue", "make", "unmake", "set", "award", "decide", "roll", "open_contest"]
1944
1771
  },
1945
1772
  "pool": {
1946
1773
  "$ref": "#/$defs/key"
@@ -1973,19 +1800,14 @@
1973
1800
  "description": "How often it happens, for the simulation."
1974
1801
  },
1975
1802
  "signedBy": {
1976
- "enum": [
1977
- "page",
1978
- "server"
1979
- ],
1803
+ "enum": ["page", "server"],
1980
1804
  "default": "page",
1981
1805
  "description": "page: the authority approves each one in its own wallet. server: a server you run holds the authority key (keys.authority is its public address)."
1982
1806
  },
1983
1807
  "proof": {
1984
1808
  "type": "object",
1985
1809
  "additionalProperties": false,
1986
- "required": [
1987
- "payment"
1988
- ],
1810
+ "required": ["payment"],
1989
1811
  "description": "What a claim must show before the keeper or the page acts on it: a payment the receiver made on chain (an attempt), not claimed before, at least `after` and at most `within` before the claim. The game's word alone is never proof: it runs in the player's browser. The checker only checks that `payment` is one of the economy's payments; `after` and `within` are recorded for the server that acts on claims, and neither the tools nor the program enforce them.",
1990
1812
  "properties": {
1991
1813
  "payment": {
@@ -2159,10 +1981,7 @@
2159
1981
  "items": {
2160
1982
  "type": "object",
2161
1983
  "additionalProperties": false,
2162
- "required": [
2163
- "signature",
2164
- "steps"
2165
- ],
1984
+ "required": ["signature", "steps"],
2166
1985
  "properties": {
2167
1986
  "signature": {
2168
1987
  "type": "string",
@@ -2218,7 +2037,7 @@
2218
2037
  "type": "object",
2219
2038
  "additionalProperties": false,
2220
2039
  "required": [],
2221
- "description": "What an NFT the player shows must be: of an `item` the game mints, or of a `collection` (a Core collection, or a Token Metadata collection mint it is verified in; with neither, the game's own collection, the one it has authority over); and, when `attribute` is given, its attribute at least `atLeast`, equal to `equals`, a time still `ahead` or `passed` (`time`), or present. `{ \"item\": \"pass\" }` alone means \"holds a Member Pass\". An NFT's attributes are read as they are; for one the game has no authority over, what the game wrote about it in its Sheet counts over them.",
2040
+ "description": "What an NFT the player shows must be: of an `item` the game mints, or of a `collection` (a Core collection, or a Token Metadata collection mint it is verified in; with neither, the game's own collection, the one it has authority over); and, when `attribute` is given, its attribute at least `atLeast`, equal to `equals`, one of `oneOf`, a time still `ahead` or `passed` (`time`), or present. `{ \"item\": \"pass\" }` alone means \"holds a Member Pass\"; `{ \"items\": [\"oak\", \"pine\"] }` means any of them. An NFT's attributes are read as they are; for one the game has no authority over, what the game wrote about it in its Sheet counts over them.",
2222
2041
  "properties": {
2223
2042
  "item": {
2224
2043
  "$ref": "#/$defs/key",
@@ -2240,11 +2059,22 @@
2240
2059
  "equals": {
2241
2060
  "type": "string"
2242
2061
  },
2062
+ "oneOf": {
2063
+ "type": "array",
2064
+ "minItems": 1,
2065
+ "maxItems": 16,
2066
+ "items": { "type": "string" },
2067
+ "description": "The attribute is one of these texts (at most 16): a tier of two, one species of three."
2068
+ },
2069
+ "items": {
2070
+ "type": "array",
2071
+ "minItems": 1,
2072
+ "maxItems": 16,
2073
+ "items": { "$ref": "#/$defs/key" },
2074
+ "description": "Any of these items the game mints (at most 16), in its own collection: a farm for three tree species, a gate for holders of any of five plots. Read by the program as the collection's `item_id` being one of theirs; not with `item`, `collection` or `attribute`."
2075
+ },
2243
2076
  "time": {
2244
- "enum": [
2245
- "ahead",
2246
- "passed"
2247
- ],
2077
+ "enum": ["ahead", "passed"],
2248
2078
  "description": "The attribute is a time (Unix seconds) still to come (\"ahead\": fuel left, a pass still good) or past, or missing (\"passed\": out of jail, no cooldown). In a farm's gate it is read as an NFT comes in; after that, the farm's `upkeepAttribute` says how long it earns."
2249
2079
  }
2250
2080
  }
@@ -2276,11 +2106,7 @@
2276
2106
  "odds": {
2277
2107
  "type": "object",
2278
2108
  "additionalProperties": false,
2279
- "required": [
2280
- "outcome",
2281
- "when",
2282
- "add"
2283
- ],
2109
+ "required": ["outcome", "when", "add"],
2284
2110
  "description": "A box outcome that grows more likely for a player who shows a collectible.",
2285
2111
  "properties": {
2286
2112
  "outcome": {
@@ -2300,9 +2126,7 @@
2300
2126
  "tier": {
2301
2127
  "type": "object",
2302
2128
  "additionalProperties": false,
2303
- "required": [
2304
- "lock"
2305
- ],
2129
+ "required": ["lock"],
2306
2130
  "properties": {
2307
2131
  "lock": {
2308
2132
  "$ref": "#/$defs/duration",
@@ -2336,11 +2160,7 @@
2336
2160
  "farm": {
2337
2161
  "type": "object",
2338
2162
  "additionalProperties": false,
2339
- "required": [
2340
- "key",
2341
- "name",
2342
- "stakes"
2343
- ],
2163
+ "required": ["key", "name", "stakes"],
2344
2164
  "description": "Players stake a token or collectibles. Rewards are whatever lands in the farm's own rewards vault (\"farm:<key>\" in a split or a schedule, its `seed`), shared by weight (what they stake, times their lock tier, plus boosts from what a collectible says), or a fixed `rate`. A farm can also write points and levels on what is staked (`growth`), and pay a mission's `prize` to a collectible that stays its tier's lock. It cannot be edited once open. A farm of collectibles can keep two times on the NFT itself: its lock (`lockAttribute`) and an upkeep (`upkeepAttribute`), which recipes and rolls move like any number.",
2345
2165
  "properties": {
2346
2166
  "key": {
@@ -2381,9 +2201,7 @@
2381
2201
  "rate": {
2382
2202
  "type": "object",
2383
2203
  "additionalProperties": false,
2384
- "required": [
2385
- "perDay"
2386
- ],
2204
+ "required": ["perDay"],
2387
2205
  "description": "A fixed rate instead of sharing what lands: for each seat whoever else is in, times its tier and boosts (most Solana NFT staking paid this way), or with `shared` the whole farm's a day, shared by weight.",
2388
2206
  "properties": {
2389
2207
  "perDay": {
@@ -2407,11 +2225,7 @@
2407
2225
  }
2408
2226
  },
2409
2227
  "custody": {
2410
- "enum": [
2411
- "freeze",
2412
- "escrow",
2413
- "watch"
2414
- ],
2228
+ "enum": ["freeze", "escrow", "watch"],
2415
2229
  "default": "escrow",
2416
2230
  "description": "For staked NFTs and token-seat boosters. escrow (default): the game holds them (Core NFTs only; issuer-controlled transfer rules can block return). freeze: they stay in the wallet, frozen (Core) or locked by Token Metadata (legacy NFTs and pNFTs), the game their delegate; Core's unfreeze can fail if the issuer later enlarges metadata or plugins. Select freeze explicitly for soulbound collectibles, which need no extra freeze. watch (a farm of collectibles only): they stay in the wallet, free: an NFT can be sold while staked, and its seat earns only while its staker holds it (a staker who no longer does collects nothing, their due going back to the farm, and the next holder can take the seat over). A Token Metadata NFT is frozen or watched, never escrowed. Staked tokens always go to the farm's vault."
2417
2231
  },
@@ -2429,10 +2243,7 @@
2429
2243
  "items": {
2430
2244
  "type": "object",
2431
2245
  "additionalProperties": false,
2432
- "required": [
2433
- "when",
2434
- "add"
2435
- ],
2246
+ "required": ["when", "add"],
2436
2247
  "properties": {
2437
2248
  "when": {
2438
2249
  "$ref": "#/$defs/rule"
@@ -2501,10 +2312,7 @@
2501
2312
  "grant": {
2502
2313
  "type": "object",
2503
2314
  "additionalProperties": false,
2504
- "required": [
2505
- "key",
2506
- "name"
2507
- ],
2315
+ "required": ["key", "name"],
2508
2316
  "description": "A reward handed out to wallets that earned it: one collectible of an item, a fixed amount from a pool, or a roll of a box (any random prize). A voucher key signs who earned it (one of `vouchers`, or of `keys`), or the wallet is on an approved list. With none of them the grant is open: any wallet claims, within its limits (with a gate, a collectible shown claims once too). The program keeps every claim within the limits. Each wallet can receive at most 256 distinct voucher rounds per grant incarnation, retained permanently; open claims do not consume round slots, and a list written in xsolana.json pays each wallet once. Closing and recreating starts a new incarnation with separate vouchers and receipts.",
2509
2317
  "properties": {
2510
2318
  "key": {
@@ -2558,9 +2366,7 @@
2558
2366
  {
2559
2367
  "type": "object",
2560
2368
  "additionalProperties": false,
2561
- "required": [
2562
- "wallet"
2563
- ],
2369
+ "required": ["wallet"],
2564
2370
  "properties": {
2565
2371
  "wallet": {
2566
2372
  "$ref": "#/$defs/address"
@@ -2668,9 +2474,7 @@
2668
2474
  {
2669
2475
  "type": "object",
2670
2476
  "additionalProperties": false,
2671
- "required": [
2672
- "wallets"
2673
- ],
2477
+ "required": ["wallets"],
2674
2478
  "properties": {
2675
2479
  "wallets": {
2676
2480
  "type": "array",
@@ -2684,9 +2488,7 @@
2684
2488
  {
2685
2489
  "type": "object",
2686
2490
  "additionalProperties": false,
2687
- "required": [
2688
- "list"
2689
- ],
2491
+ "required": ["list"],
2690
2492
  "properties": {
2691
2493
  "list": {
2692
2494
  "type": "array",
@@ -2703,17 +2505,12 @@
2703
2505
  {
2704
2506
  "type": "object",
2705
2507
  "additionalProperties": false,
2706
- "required": [
2707
- "staked"
2708
- ],
2508
+ "required": ["staked"],
2709
2509
  "properties": {
2710
2510
  "staked": {
2711
2511
  "type": "object",
2712
2512
  "additionalProperties": false,
2713
- "required": [
2714
- "farm",
2715
- "atLeast"
2716
- ],
2513
+ "required": ["farm", "atLeast"],
2717
2514
  "description": "A stake to enter: the wallet’s seat in `farm` (a farm of a token in this spec) holds at least `atLeast` of its token, staked before this second (launchpad tiers, stake to play).",
2718
2515
  "properties": {
2719
2516
  "farm": {
@@ -2732,9 +2529,7 @@
2732
2529
  "perWalletEach": {
2733
2530
  "type": "object",
2734
2531
  "additionalProperties": false,
2735
- "required": [
2736
- "count"
2737
- ],
2532
+ "required": ["count"],
2738
2533
  "description": "How many one wallet may do in each window of time: `{ \"count\": 1, \"every\": \"1d\" }` is once a day (windows counted from the Unix epoch, a UTC day for \"1d\").",
2739
2534
  "properties": {
2740
2535
  "count": {
@@ -2751,9 +2546,7 @@
2751
2546
  "growth": {
2752
2547
  "type": "object",
2753
2548
  "additionalProperties": false,
2754
- "required": [
2755
- "perDay"
2756
- ],
2549
+ "required": ["perDay"],
2757
2550
  "description": "Points a collectible earns by staying in, written under `attribute`, with the level they reach under `level` when there are `levels`. Without `levels` the points themselves can be the level: { \"attribute\": \"level\", \"perDay\": 1 } is a level a day.",
2758
2551
  "properties": {
2759
2552
  "attribute": {
@@ -2793,11 +2586,7 @@
2793
2586
  "stash": {
2794
2587
  "type": "object",
2795
2588
  "additionalProperties": false,
2796
- "required": [
2797
- "key",
2798
- "name",
2799
- "nfts"
2800
- ],
2589
+ "required": ["key", "name", "nfts"],
2801
2590
  "description": "A stash: NFTs of any collection the game holds until a prize names one or a roll gives one away. Any kind: a Core asset (with or without the game's authority), a Token Metadata NFT, a compressed NFT. A roll takes the one it picks out of the stash at once, so two winners never get the same one, and an empty stash can't be won. The game's owner or authority can put more in, or take one out, at any time (`loot.stashIx`).",
2802
2591
  "properties": {
2803
2592
  "key": {
@@ -2827,9 +2616,7 @@
2827
2616
  {
2828
2617
  "type": "object",
2829
2618
  "additionalProperties": false,
2830
- "required": [
2831
- "asset"
2832
- ],
2619
+ "required": ["asset"],
2833
2620
  "properties": {
2834
2621
  "asset": {
2835
2622
  "$ref": "#/$defs/address"
@@ -2849,9 +2636,7 @@
2849
2636
  {
2850
2637
  "type": "object",
2851
2638
  "additionalProperties": false,
2852
- "required": [
2853
- "mint"
2854
- ],
2639
+ "required": ["mint"],
2855
2640
  "properties": {
2856
2641
  "mint": {
2857
2642
  "$ref": "#/$defs/address"
@@ -2876,9 +2661,7 @@
2876
2661
  {
2877
2662
  "type": "object",
2878
2663
  "additionalProperties": false,
2879
- "required": [
2880
- "compressed"
2881
- ],
2664
+ "required": ["compressed"],
2882
2665
  "properties": {
2883
2666
  "compressed": {
2884
2667
  "$ref": "#/$defs/address",
@@ -2904,20 +2687,12 @@
2904
2687
  },
2905
2688
  "prize": {
2906
2689
  "type": "object",
2907
- "required": [
2908
- "gives"
2909
- ],
2690
+ "required": ["gives"],
2910
2691
  "additionalProperties": false,
2911
2692
  "description": "A prize, given the same way on every route that gives one (a grant, a lottery's place, a contest's winners, a mission's tier, a recipe's line), in the transaction that wins it; only a roll is settled after, by the oracle. item: one of `item` (a collectible minted to the winner, or with `compressed` a compressed NFT of it; a normal item is the game's backend's to deliver). tokens: `amount`, minted (`from`: \"mint\", in `currency`, a token the game mints) or paid from a pool (\"pool:<key>\", in what it holds). share: `percent` of what `pool` holds then (a jackpot). nft: the NFT `nft`, which the stash `stash` lists (given once: the first winner takes it). roll: a roll of `box` for the winner: chance (a box can give a stash's NFT at random). raffled (a lottery's place only, of a lottery that draws once): one NFT drawn at random from the lottery's own stash (its `nfts`).",
2912
2693
  "properties": {
2913
2694
  "gives": {
2914
- "enum": [
2915
- "item",
2916
- "tokens",
2917
- "nft",
2918
- "roll",
2919
- "raffled"
2920
- ]
2695
+ "enum": ["item", "tokens", "nft", "roll", "raffled"]
2921
2696
  },
2922
2697
  "item": {
2923
2698
  "$ref": "#/$defs/key"
@@ -2967,17 +2742,12 @@
2967
2742
  "description": "Where an NFT paid goes: \"burn\" (a Core asset burned, any other kind sent to the incinerator's address), \"treasury\" (the treasury wallet), { \"giveTo\": \"<wallet>\" }, or { \"stash\": \"<key>\" } (into one of this spec's stashes, to be given away as a prize).",
2968
2743
  "anyOf": [
2969
2744
  {
2970
- "enum": [
2971
- "burn",
2972
- "treasury"
2973
- ]
2745
+ "enum": ["burn", "treasury"]
2974
2746
  },
2975
2747
  {
2976
2748
  "type": "object",
2977
2749
  "additionalProperties": false,
2978
- "required": [
2979
- "giveTo"
2980
- ],
2750
+ "required": ["giveTo"],
2981
2751
  "properties": {
2982
2752
  "giveTo": {
2983
2753
  "$ref": "#/$defs/address"
@@ -2987,9 +2757,7 @@
2987
2757
  {
2988
2758
  "type": "object",
2989
2759
  "additionalProperties": false,
2990
- "required": [
2991
- "stash"
2992
- ],
2760
+ "required": ["stash"],
2993
2761
  "properties": {
2994
2762
  "stash": {
2995
2763
  "$ref": "#/$defs/key"
@@ -3001,9 +2769,7 @@
3001
2769
  "nftPrice": {
3002
2770
  "type": "object",
3003
2771
  "additionalProperties": false,
3004
- "required": [
3005
- "rule"
3006
- ],
2772
+ "required": ["rule"],
3007
2773
  "description": "An NFT as the price: one the player holds that passes `rule`, sent where `then` says (default \"burn\").",
3008
2774
  "properties": {
3009
2775
  "rule": {
@@ -3017,10 +2783,7 @@
3017
2783
  "table": {
3018
2784
  "type": "object",
3019
2785
  "additionalProperties": false,
3020
- "required": [
3021
- "key",
3022
- "rows"
3023
- ],
2786
+ "required": ["key", "rows"],
3024
2787
  "description": "A table (`table.rs`): rows, each a weight and an optional stock, and a label (`\"labels\"`, up to 32 bytes each) or nothing (`\"numbers\"`: a row gives its own number, from 0). Sealed once written: its weights never change and its stock only goes down. A row with a stock leaves the draws once it is used up.",
3025
2788
  "properties": {
3026
2789
  "key": {
@@ -3032,10 +2795,7 @@
3032
2795
  "maximum": 4294967295
3033
2796
  },
3034
2797
  "kind": {
3035
- "enum": [
3036
- "labels",
3037
- "numbers"
3038
- ],
2798
+ "enum": ["labels", "numbers"],
3039
2799
  "default": "labels"
3040
2800
  },
3041
2801
  "rows": {
@@ -3044,9 +2804,7 @@
3044
2804
  "items": {
3045
2805
  "type": "object",
3046
2806
  "additionalProperties": false,
3047
- "required": [
3048
- "weight"
3049
- ],
2807
+ "required": ["weight"],
3050
2808
  "properties": {
3051
2809
  "label": {
3052
2810
  "type": "string"