@shipload/sdk 1.0.0-next.7 → 1.0.0-next.71

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 (203) hide show
  1. package/lib/scan.d.ts +52 -0
  2. package/lib/scan.js +162 -0
  3. package/lib/scan.js.map +1 -0
  4. package/lib/scan.m.js +152 -0
  5. package/lib/scan.m.js.map +1 -0
  6. package/lib/shipload.d.ts +5822 -1484
  7. package/lib/shipload.js +20838 -5419
  8. package/lib/shipload.js.map +1 -1
  9. package/lib/shipload.m.js +20674 -5669
  10. package/lib/shipload.m.js.map +1 -1
  11. package/lib/testing.d.ts +1691 -0
  12. package/lib/testing.js +7109 -0
  13. package/lib/testing.js.map +1 -0
  14. package/lib/testing.m.js +7103 -0
  15. package/lib/testing.m.js.map +1 -0
  16. package/package.json +20 -2
  17. package/src/capabilities/craftable.test.ts +82 -0
  18. package/src/capabilities/craftable.ts +82 -0
  19. package/src/capabilities/crafting.test.ts +80 -0
  20. package/src/capabilities/crafting.ts +50 -8
  21. package/src/capabilities/gathering.test.ts +29 -0
  22. package/src/capabilities/gathering.ts +38 -20
  23. package/src/capabilities/hauling.ts +0 -5
  24. package/src/capabilities/index.ts +0 -1
  25. package/src/capabilities/modules.ts +27 -30
  26. package/src/capabilities/movement.ts +1 -1
  27. package/src/capabilities/storage.test.ts +26 -0
  28. package/src/capabilities/storage.ts +22 -7
  29. package/src/contracts/fund.ts +306 -0
  30. package/src/contracts/platform.ts +312 -3
  31. package/src/contracts/server.ts +2793 -478
  32. package/src/contracts/token.ts +170 -0
  33. package/src/contracts.ts +2 -0
  34. package/src/coordinates/address.ts +88 -0
  35. package/src/coordinates/constants.test.ts +15 -0
  36. package/src/coordinates/constants.ts +23 -0
  37. package/src/coordinates/index.ts +15 -0
  38. package/src/coordinates/memo.test.ts +47 -0
  39. package/src/coordinates/memo.ts +20 -0
  40. package/src/coordinates/permutation.ts +77 -0
  41. package/src/coordinates/regions.ts +48 -0
  42. package/src/coordinates/sectors.ts +115 -0
  43. package/src/data/capabilities.ts +49 -18
  44. package/src/data/capability-formulas.ts +26 -14
  45. package/src/data/catalog.test.ts +19 -0
  46. package/src/data/catalog.ts +13 -3
  47. package/src/data/charters.json +396 -0
  48. package/src/data/citizenry-adjectives.json +42 -0
  49. package/src/data/citizenry-nouns.json +50 -0
  50. package/src/data/colors.ts +14 -32
  51. package/src/data/entities.json +421 -15
  52. package/src/data/item-ids.ts +53 -13
  53. package/src/data/items.json +330 -77
  54. package/src/data/kind-registry.json +212 -0
  55. package/src/data/kind-registry.ts +192 -0
  56. package/src/data/metadata.ts +312 -51
  57. package/src/data/recipes-runtime.ts +6 -23
  58. package/src/data/recipes.json +2173 -173
  59. package/src/data/tiers.ts +9 -6
  60. package/src/derivation/build-methods.test.ts +71 -0
  61. package/src/derivation/build-methods.ts +50 -0
  62. package/src/derivation/capabilities.test.ts +348 -0
  63. package/src/derivation/capabilities.ts +707 -0
  64. package/src/derivation/capability-mappings.ts +60 -16
  65. package/src/derivation/crafting.test.ts +17 -0
  66. package/src/derivation/crafting.ts +57 -34
  67. package/src/derivation/index.ts +27 -2
  68. package/src/derivation/recipe-usage.test.ts +88 -0
  69. package/src/derivation/recipe-usage.ts +141 -0
  70. package/src/derivation/reserve-regen.ts +34 -0
  71. package/src/derivation/resources.ts +9 -1
  72. package/src/derivation/rollups.test.ts +55 -0
  73. package/src/derivation/rollups.ts +72 -0
  74. package/src/derivation/stars.test.ts +67 -0
  75. package/src/derivation/stars.ts +25 -0
  76. package/src/derivation/stat-scaling.ts +12 -0
  77. package/src/derivation/stats.ts +6 -6
  78. package/src/derivation/strata.ts +5 -3
  79. package/src/derivation/stratum.ts +26 -22
  80. package/src/derivation/tiers.ts +40 -7
  81. package/src/derivation/upgrades.ts +14 -0
  82. package/src/derivation/wormhole.ts +154 -0
  83. package/src/entities/entity.ts +102 -0
  84. package/src/entities/gamestate.ts +3 -28
  85. package/src/entities/makers.ts +144 -136
  86. package/src/entities/slot-multiplier.ts +43 -0
  87. package/src/entity/hydrate.test.ts +156 -0
  88. package/src/entity/hydrate.ts +86 -0
  89. package/src/errors.ts +21 -16
  90. package/src/format.ts +42 -9
  91. package/src/index-module.ts +425 -32
  92. package/src/influence/ballot.test.ts +103 -0
  93. package/src/influence/ballot.ts +98 -0
  94. package/src/influence/categories.ts +32 -0
  95. package/src/influence/charter-metadata.test.ts +136 -0
  96. package/src/influence/charter-metadata.ts +236 -0
  97. package/src/influence/charters.test.ts +112 -0
  98. package/src/influence/charters.ts +150 -0
  99. package/src/influence/citizenry.ts +38 -0
  100. package/src/influence/civic-shuttle.test.ts +202 -0
  101. package/src/influence/civic-shuttle.ts +142 -0
  102. package/src/influence/civic.test.ts +287 -0
  103. package/src/influence/civic.ts +269 -0
  104. package/src/influence/constants.ts +84 -0
  105. package/src/influence/decay.ts +20 -0
  106. package/src/influence/decomp.ts +95 -0
  107. package/src/influence/demand.ts +106 -0
  108. package/src/influence/duration.ts +101 -0
  109. package/src/influence/index.ts +118 -0
  110. package/src/influence/influence.test.ts +450 -0
  111. package/src/influence/quality.ts +25 -0
  112. package/src/influence/valuation.ts +154 -0
  113. package/src/managers/actions.ts +950 -93
  114. package/src/managers/balances.test.ts +161 -0
  115. package/src/managers/balances.ts +93 -0
  116. package/src/managers/base.ts +10 -2
  117. package/src/managers/cluster.test.ts +39 -0
  118. package/src/managers/cluster.ts +53 -0
  119. package/src/managers/construction-types.ts +80 -0
  120. package/src/managers/construction.ts +453 -0
  121. package/src/managers/context.ts +58 -1
  122. package/src/managers/coordinates.ts +14 -0
  123. package/src/managers/entities.ts +35 -63
  124. package/src/managers/epochs.ts +72 -1
  125. package/src/managers/index.ts +38 -1
  126. package/src/managers/influence.test.ts +56 -0
  127. package/src/managers/influence.ts +425 -0
  128. package/src/managers/jobs.test.ts +96 -0
  129. package/src/managers/jobs.ts +58 -0
  130. package/src/managers/locations.ts +25 -29
  131. package/src/managers/nft.test.ts +21 -0
  132. package/src/managers/nft.ts +110 -0
  133. package/src/managers/players.ts +25 -0
  134. package/src/managers/plot.ts +122 -0
  135. package/src/nft/atomicassets.abi.json +1342 -0
  136. package/src/nft/atomicassets.ts +237 -0
  137. package/src/nft/atomicdata.ts +130 -0
  138. package/src/nft/buildImmutableData.ts +388 -0
  139. package/src/nft/description.ts +222 -100
  140. package/src/nft/index.ts +3 -0
  141. package/src/planner/index.ts +296 -0
  142. package/src/planner/planner.test.ts +459 -0
  143. package/src/receipts.ts +22 -0
  144. package/src/resolution/describe-module.ts +43 -25
  145. package/src/resolution/display-name.ts +39 -11
  146. package/src/resolution/resolve-item.test.ts +48 -0
  147. package/src/resolution/resolve-item.ts +112 -58
  148. package/src/scan/index.ts +244 -0
  149. package/src/scan/scan-wasm.base64.ts +2 -0
  150. package/src/scheduling/accessor.ts +65 -23
  151. package/src/scheduling/availability.test.ts +320 -0
  152. package/src/scheduling/availability.ts +251 -0
  153. package/src/scheduling/cancel.test.ts +550 -0
  154. package/src/scheduling/cancel.ts +254 -0
  155. package/src/scheduling/cluster-stock.test.ts +31 -0
  156. package/src/scheduling/cluster-stock.ts +15 -0
  157. package/src/scheduling/energy.ts +47 -0
  158. package/src/scheduling/epoch.ts +1 -0
  159. package/src/scheduling/idle-resolve.ts +45 -0
  160. package/src/scheduling/jobs.test.ts +448 -0
  161. package/src/scheduling/jobs.ts +343 -0
  162. package/src/scheduling/lane-core.ts +128 -0
  163. package/src/scheduling/lanes.test.ts +250 -0
  164. package/src/scheduling/lanes.ts +279 -0
  165. package/src/scheduling/projection.ts +265 -149
  166. package/src/scheduling/schedule.test.ts +163 -0
  167. package/src/scheduling/schedule.ts +282 -116
  168. package/src/scheduling/task-cargo.test.ts +110 -0
  169. package/src/scheduling/task-cargo.ts +62 -0
  170. package/src/scheduling/task-effects.test.ts +35 -0
  171. package/src/scheduling/task-effects.ts +34 -0
  172. package/src/scheduling/unwrap.test.ts +86 -0
  173. package/src/scheduling/unwrap.ts +190 -0
  174. package/src/shipload.ts +63 -4
  175. package/src/subscriptions/manager.cluster.test.ts +51 -0
  176. package/src/subscriptions/manager.ts +245 -172
  177. package/src/subscriptions/mappers.ts +5 -8
  178. package/src/subscriptions/types.ts +28 -3
  179. package/src/testing/catalog-hash.ts +19 -0
  180. package/src/testing/index.ts +2 -0
  181. package/src/testing/projection-parity.ts +167 -0
  182. package/src/travel/reach.test.ts +86 -0
  183. package/src/travel/reach.ts +34 -0
  184. package/src/travel/route-build.test.ts +63 -0
  185. package/src/travel/route-build.ts +60 -0
  186. package/src/travel/route-planner.ts +288 -0
  187. package/src/travel/route-simulator.ts +170 -0
  188. package/src/travel/travel.ts +190 -123
  189. package/src/types/capabilities.ts +37 -8
  190. package/src/types/entity.ts +3 -3
  191. package/src/types/index.ts +0 -1
  192. package/src/types.ts +81 -23
  193. package/src/utils/cargo.test.ts +14 -0
  194. package/src/utils/cargo.ts +2 -0
  195. package/src/utils/display-name.ts +70 -0
  196. package/src/utils/hash.ts +22 -2
  197. package/src/utils/system.ts +24 -5
  198. package/src/capabilities/loading.ts +0 -8
  199. package/src/entities/container.ts +0 -123
  200. package/src/entities/ship-deploy.ts +0 -295
  201. package/src/entities/ship.ts +0 -221
  202. package/src/entities/warehouse.ts +0 -127
  203. package/src/types/entity-traits.ts +0 -69
@@ -0,0 +1,170 @@
1
+ import type {Action, AssetType, NameType} from '@wharfkit/antelope'
2
+ import {ABI, Asset, Blob, Name, Struct} from '@wharfkit/antelope'
3
+ import type {ActionOptions, ContractArgs, PartialBy, Table} from '@wharfkit/contract'
4
+ import {Contract as BaseContract} from '@wharfkit/contract'
5
+ export const abiBlob = Blob.from(
6
+ 'DmVvc2lvOjphYmkvMS4yAAoHYWNjb3VudAABB2JhbGFuY2UFYXNzZXQFY2xvc2UAAgVvd25lcgRuYW1lBnN5bWJvbAZzeW1ib2wGY3JlYXRlAAIGaXNzdWVyBG5hbWUObWF4aW11bV9zdXBwbHkFYXNzZXQOY3VycmVuY3lfc3RhdHMAAwZzdXBwbHkFYXNzZXQKbWF4X3N1cHBseQVhc3NldAZpc3N1ZXIEbmFtZQVpc3N1ZQADAnRvBG5hbWUIcXVhbnRpdHkFYXNzZXQEbWVtbwZzdHJpbmcKaXNzdWVmaXhlZAADAnRvBG5hbWUGc3VwcGx5BWFzc2V0BG1lbW8Gc3RyaW5nBG9wZW4AAwVvd25lcgRuYW1lBnN5bWJvbAZzeW1ib2wJcmFtX3BheWVyBG5hbWUGcmV0aXJlAAIIcXVhbnRpdHkFYXNzZXQEbWVtbwZzdHJpbmcMc2V0bWF4c3VwcGx5AAIGaXNzdWVyBG5hbWUObWF4aW11bV9zdXBwbHkFYXNzZXQIdHJhbnNmZXIABARmcm9tBG5hbWUCdG8EbmFtZQhxdWFudGl0eQVhc3NldARtZW1vBnN0cmluZwgAAAAAAIVpRAVjbG9zZfkDLS0tCnNwZWNfdmVyc2lvbjogIjAuMi4wIgp0aXRsZTogQ2xvc2UgVG9rZW4gQmFsYW5jZQpzdW1tYXJ5OiAnQ2xvc2Uge3tub3dyYXAgb3duZXJ9feKAmXMgemVybyBxdWFudGl0eSBiYWxhbmNlJwppY29uOiBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZW9zbmV0d29ya2ZvdW5kYXRpb24vZW9zLXN5c3RlbS1jb250cmFjdHMvbWFpbi9jb250cmFjdHMvaWNvbnMvdG9rZW4ucG5nIzIwN2ZmNjhiMDQwNmVhYTU2NjE4YjA4YmRhODFkNmEwOTU0NTQzZjM2YWRjMzI4YWIzMDY1ZjMxYTVjNWQ2NTQKLS0tCgp7e293bmVyfX0gYWdyZWVzIHRvIGNsb3NlIHRoZWlyIHplcm8gcXVhbnRpdHkgYmFsYW5jZSBmb3IgdGhlIHt7c3ltYm9sX3RvX3N5bWJvbF9jb2RlIHN5bWJvbH19IHRva2VuLgoKUkFNIHdpbGwgYmUgcmVmdW5kZWQgdG8gdGhlIFJBTSBwYXllciBvZiB0aGUge3tzeW1ib2xfdG9fc3ltYm9sX2NvZGUgc3ltYm9sfX0gdG9rZW4gYmFsYW5jZSBmb3Ige3tvd25lcn19LgAAAACobNRFBmNyZWF0ZZoFLS0tCnNwZWNfdmVyc2lvbjogIjAuMi4wIgp0aXRsZTogQ3JlYXRlIE5ldyBUb2tlbgpzdW1tYXJ5OiAnQ3JlYXRlIGEgbmV3IHRva2VuJwppY29uOiBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZW9zbmV0d29ya2ZvdW5kYXRpb24vZW9zLXN5c3RlbS1jb250cmFjdHMvbWFpbi9jb250cmFjdHMvaWNvbnMvdG9rZW4ucG5nIzIwN2ZmNjhiMDQwNmVhYTU2NjE4YjA4YmRhODFkNmEwOTU0NTQzZjM2YWRjMzI4YWIzMDY1ZjMxYTVjNWQ2NTQKLS0tCgp7eyRhY3Rpb24uYWNjb3VudH19IGFncmVlcyB0byBjcmVhdGUgYSBuZXcgdG9rZW4gd2l0aCBzeW1ib2wge3thc3NldF90b19zeW1ib2xfY29kZSBtYXhpbXVtX3N1cHBseX19IHRvIGJlIG1hbmFnZWQgYnkge3tpc3N1ZXJ9fS4KClRoaXMgYWN0aW9uIHdpbGwgbm90IHJlc3VsdCBhbnkgYW55IHRva2VucyBiZWluZyBpc3N1ZWQgaW50byBjaXJjdWxhdGlvbi4KCnt7aXNzdWVyfX0gd2lsbCBiZSBhbGxvd2VkIHRvIGlzc3VlIHRva2VucyBpbnRvIGNpcmN1bGF0aW9uLCB1cCB0byBhIG1heGltdW0gc3VwcGx5IG9mIHt7bWF4aW11bV9zdXBwbHl9fS4KClJBTSB3aWxsIGRlZHVjdGVkIGZyb20ge3skYWN0aW9uLmFjY291bnR9feKAmXMgcmVzb3VyY2VzIHRvIGNyZWF0ZSB0aGUgbmVjZXNzYXJ5IHJlY29yZHMuAAAAAAClMXYFaXNzdWXuBy0tLQpzcGVjX3ZlcnNpb246ICIwLjIuMCIKdGl0bGU6IElzc3VlIFRva2VucyBpbnRvIENpcmN1bGF0aW9uCnN1bW1hcnk6ICdJc3N1ZSB7e25vd3JhcCBxdWFudGl0eX19IGludG8gY2lyY3VsYXRpb24gYW5kIHRyYW5zZmVyIGludG8ge3tub3dyYXAgdG99feKAmXMgYWNjb3VudCcKaWNvbjogaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2Vvc25ldHdvcmtmb3VuZGF0aW9uL2Vvcy1zeXN0ZW0tY29udHJhY3RzL21haW4vY29udHJhY3RzL2ljb25zL3Rva2VuLnBuZyMyMDdmZjY4YjA0MDZlYWE1NjYxOGIwOGJkYTgxZDZhMDk1NDU0M2YzNmFkYzMyOGFiMzA2NWYzMWE1YzVkNjU0Ci0tLQoKVGhlIHRva2VuIG1hbmFnZXIgYWdyZWVzIHRvIGlzc3VlIHt7cXVhbnRpdHl9fSBpbnRvIGNpcmN1bGF0aW9uLCBhbmQgdHJhbnNmZXIgaXQgaW50byB7e3RvfX3igJlzIGFjY291bnQuCgp7eyNpZiBtZW1vfX1UaGVyZSBpcyBhIG1lbW8gYXR0YWNoZWQgdG8gdGhlIHRyYW5zZmVyIHN0YXRpbmc6Cnt7bWVtb319Cnt7L2lmfX0KCklmIHt7dG99fSBkb2VzIG5vdCBoYXZlIGEgYmFsYW5jZSBmb3Ige3thc3NldF90b19zeW1ib2xfY29kZSBxdWFudGl0eX19LCBvciB0aGUgdG9rZW4gbWFuYWdlciBkb2VzIG5vdCBoYXZlIGEgYmFsYW5jZSBmb3Ige3thc3NldF90b19zeW1ib2xfY29kZSBxdWFudGl0eX19LCB0aGUgdG9rZW4gbWFuYWdlciB3aWxsIGJlIGRlc2lnbmF0ZWQgYXMgdGhlIFJBTSBwYXllciBvZiB0aGUge3thc3NldF90b19zeW1ib2xfY29kZSBxdWFudGl0eX19IHRva2VuIGJhbGFuY2UgZm9yIHt7dG99fS4gQXMgYSByZXN1bHQsIFJBTSB3aWxsIGJlIGRlZHVjdGVkIGZyb20gdGhlIHRva2VuIG1hbmFnZXLigJlzIHJlc291cmNlcyB0byBjcmVhdGUgdGhlIG5lY2Vzc2FyeSByZWNvcmRzLgoKVGhpcyBhY3Rpb24gZG9lcyBub3QgYWxsb3cgdGhlIHRvdGFsIHF1YW50aXR5IHRvIGV4Y2VlZCB0aGUgbWF4IGFsbG93ZWQgc3VwcGx5IG9mIHRoZSB0b2tlbi4AQFLdLaUxdgppc3N1ZWZpeGVkoQgtLS0Kc3BlY192ZXJzaW9uOiAiMC4yLjAiCnRpdGxlOiBJc3N1ZSBGaXhlZCBTdXBwbHkgb2YgVG9rZW5zIGludG8gQ2lyY3VsYXRpb24Kc3VtbWFyeTogJ0lzc3VlIHVwIHRvIHt7bm93cmFwIHN1cHBseX19IHN1cHBseSBpbnRvIGNpcmN1bGF0aW9uIGFuZCB0cmFuc2ZlciBpbnRvIHt7bm93cmFwIHRvfX3igJlzIGFjY291bnQnCmljb246IGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9lb3NuZXR3b3JrZm91bmRhdGlvbi9lb3Mtc3lzdGVtLWNvbnRyYWN0cy9tYWluL2NvbnRyYWN0cy9pY29ucy90b2tlbi5wbmcjMjA3ZmY2OGIwNDA2ZWFhNTY2MThiMDhiZGE4MWQ2YTA5NTQ1NDNmMzZhZGMzMjhhYjMwNjVmMzFhNWM1ZDY1NAotLS0KClRoZSB0b2tlbiBtYW5hZ2VyIGFncmVlcyB0byBpc3N1ZSB0b2tlbnMgdXAgdG8ge3tzdXBwbHl9fSBmaXhlZCBzdXBwbHkgaW50byBjaXJjdWxhdGlvbiwgYW5kIHRyYW5zZmVyIGl0IGludG8ge3t0b3194oCZcyBhY2NvdW50LgoKe3sjaWYgbWVtb319VGhlcmUgaXMgYSBtZW1vIGF0dGFjaGVkIHRvIHRoZSB0cmFuc2ZlciBzdGF0aW5nOgp7e21lbW99fQp7ey9pZn19CgpJZiB7e3RvfX0gZG9lcyBub3QgaGF2ZSBhIGJhbGFuY2UgZm9yIHt7YXNzZXRfdG9fc3ltYm9sX2NvZGUgcXVhbnRpdHl9fSwgb3IgdGhlIHRva2VuIG1hbmFnZXIgZG9lcyBub3QgaGF2ZSBhIGJhbGFuY2UgZm9yIHt7YXNzZXRfdG9fc3ltYm9sX2NvZGUgcXVhbnRpdHl9fSwgdGhlIHRva2VuIG1hbmFnZXIgd2lsbCBiZSBkZXNpZ25hdGVkIGFzIHRoZSBSQU0gcGF5ZXIgb2YgdGhlIHt7YXNzZXRfdG9fc3ltYm9sX2NvZGUgcXVhbnRpdHl9fSB0b2tlbiBiYWxhbmNlIGZvciB7e3RvfX0uIEFzIGEgcmVzdWx0LCBSQU0gd2lsbCBiZSBkZWR1Y3RlZCBmcm9tIHRoZSB0b2tlbiBtYW5hZ2Vy4oCZcyByZXNvdXJjZXMgdG8gY3JlYXRlIHRoZSBuZWNlc3NhcnkgcmVjb3Jkcy4KClRoaXMgYWN0aW9uIGRvZXMgbm90IGFsbG93IHRoZSB0b3RhbCBxdWFudGl0eSB0byBleGNlZWQgdGhlIG1heCBhbGxvd2VkIHN1cHBseSBvZiB0aGUgdG9rZW4uAAAAAAAwVaUEb3BlbsYFLS0tCnNwZWNfdmVyc2lvbjogIjAuMi4wIgp0aXRsZTogT3BlbiBUb2tlbiBCYWxhbmNlCnN1bW1hcnk6ICdPcGVuIGEgemVybyBxdWFudGl0eSBiYWxhbmNlIGZvciB7e25vd3JhcCBvd25lcn19JwppY29uOiBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZW9zbmV0d29ya2ZvdW5kYXRpb24vZW9zLXN5c3RlbS1jb250cmFjdHMvbWFpbi9jb250cmFjdHMvaWNvbnMvdG9rZW4ucG5nIzIwN2ZmNjhiMDQwNmVhYTU2NjE4YjA4YmRhODFkNmEwOTU0NTQzZjM2YWRjMzI4YWIzMDY1ZjMxYTVjNWQ2NTQKLS0tCgp7e3JhbV9wYXllcn19IGFncmVlcyB0byBlc3RhYmxpc2ggYSB6ZXJvIHF1YW50aXR5IGJhbGFuY2UgZm9yIHt7b3duZXJ9fSBmb3IgdGhlIHt7c3ltYm9sX3RvX3N5bWJvbF9jb2RlIHN5bWJvbH19IHRva2VuLgoKSWYge3tvd25lcn19IGRvZXMgbm90IGhhdmUgYSBiYWxhbmNlIGZvciB7e3N5bWJvbF90b19zeW1ib2xfY29kZSBzeW1ib2x9fSwge3tyYW1fcGF5ZXJ9fSB3aWxsIGJlIGRlc2lnbmF0ZWQgYXMgdGhlIFJBTSBwYXllciBvZiB0aGUge3tzeW1ib2xfdG9fc3ltYm9sX2NvZGUgc3ltYm9sfX0gdG9rZW4gYmFsYW5jZSBmb3Ige3tvd25lcn19LiBBcyBhIHJlc3VsdCwgUkFNIHdpbGwgYmUgZGVkdWN0ZWQgZnJvbSB7e3JhbV9wYXllcn194oCZcyByZXNvdXJjZXMgdG8gY3JlYXRlIHRoZSBuZWNlc3NhcnkgcmVjb3Jkcy4AAAAAqOuyugZyZXRpcmXcAy0tLQpzcGVjX3ZlcnNpb246ICIwLjIuMCIKdGl0bGU6IFJlbW92ZSBUb2tlbnMgZnJvbSBDaXJjdWxhdGlvbgpzdW1tYXJ5OiAnUmVtb3ZlIHt7bm93cmFwIHF1YW50aXR5fX0gZnJvbSBjaXJjdWxhdGlvbicKaWNvbjogaHR0cHM6Ly9yYXcuZ2l0aHVidXNlcmNvbnRlbnQuY29tL2Vvc25ldHdvcmtmb3VuZGF0aW9uL2Vvcy1zeXN0ZW0tY29udHJhY3RzL21haW4vY29udHJhY3RzL2ljb25zL3Rva2VuLnBuZyMyMDdmZjY4YjA0MDZlYWE1NjYxOGIwOGJkYTgxZDZhMDk1NDU0M2YzNmFkYzMyOGFiMzA2NWYzMWE1YzVkNjU0Ci0tLQoKVGhlIHRva2VuIG1hbmFnZXIgYWdyZWVzIHRvIHJlbW92ZSB7e3F1YW50aXR5fX0gZnJvbSBjaXJjdWxhdGlvbiwgdGFrZW4gZnJvbSB0aGVpciBvd24gYWNjb3VudC4KCnt7I2lmIG1lbW99fSBUaGVyZSBpcyBhIG1lbW8gYXR0YWNoZWQgdG8gdGhlIGFjdGlvbiBzdGF0aW5nOgp7e21lbW99fQp7ey9pZn194GOtGncjs8IMc2V0bWF4c3VwcGx5wAMtLS0Kc3BlY192ZXJzaW9uOiAiMC4yLjAiCnRpdGxlOiBTZXQgTWF4IFN1cHBseQpzdW1tYXJ5OiAnU2V0IG1heCBzdXBwbHkgZm9yIHRva2VuJwppY29uOiBodHRwczovL3Jhdy5naXRodWJ1c2VyY29udGVudC5jb20vZW9zbmV0d29ya2ZvdW5kYXRpb24vZW9zLXN5c3RlbS1jb250cmFjdHMvbWFpbi9jb250cmFjdHMvaWNvbnMvdG9rZW4ucG5nIzIwN2ZmNjhiMDQwNmVhYTU2NjE4YjA4YmRhODFkNmEwOTU0NTQzZjM2YWRjMzI4YWIzMDY1ZjMxYTVjNWQ2NTQKLS0tCgp7e2lzc3Vlcn19IHdpbGwgYmUgYWxsb3dlZCB0byBpc3N1ZSB0b2tlbnMgaW50byBjaXJjdWxhdGlvbiwgdXAgdG8gYSBtYXhpbXVtIHN1cHBseSBvZiB7e21heGltdW1fc3VwcGx5fX0uCgpUaGlzIGFjdGlvbiB3aWxsIG5vdCByZXN1bHQgYW55IGFueSB0b2tlbnMgYmVpbmcgaXNzdWVkIGludG8gY2lyY3VsYXRpb24uAAAAVy08zc0IdHJhbnNmZXK2By0tLQpzcGVjX3ZlcnNpb246ICIwLjIuMCIKdGl0bGU6IFRyYW5zZmVyIFRva2VucwpzdW1tYXJ5OiAnU2VuZCB7e25vd3JhcCBxdWFudGl0eX19IGZyb20ge3tub3dyYXAgZnJvbX19IHRvIHt7bm93cmFwIHRvfX0nCmljb246IGh0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9lb3NuZXR3b3JrZm91bmRhdGlvbi9lb3Mtc3lzdGVtLWNvbnRyYWN0cy9tYWluL2NvbnRyYWN0cy9pY29ucy90cmFuc2Zlci5wbmcjNWRmYWQwZGY3Mjc3MmVlMWNjYzE1NWU2NzBjMWQxMjRmNWM1MTIyZjFkNTAyNzU2NWRmMzhiNDE4MDQyZDFkZAotLS0KCnt7ZnJvbX19IGFncmVlcyB0byBzZW5kIHt7cXVhbnRpdHl9fSB0byB7e3RvfX0uCgp7eyNpZiBtZW1vfX1UaGVyZSBpcyBhIG1lbW8gYXR0YWNoZWQgdG8gdGhlIHRyYW5zZmVyIHN0YXRpbmc6Cnt7bWVtb319Cnt7L2lmfX0KCklmIHt7ZnJvbX19IGlzIG5vdCBhbHJlYWR5IHRoZSBSQU0gcGF5ZXIgb2YgdGhlaXIge3thc3NldF90b19zeW1ib2xfY29kZSBxdWFudGl0eX19IHRva2VuIGJhbGFuY2UsIHt7ZnJvbX19IHdpbGwgYmUgZGVzaWduYXRlZCBhcyBzdWNoLiBBcyBhIHJlc3VsdCwgUkFNIHdpbGwgYmUgZGVkdWN0ZWQgZnJvbSB7e2Zyb219feKAmXMgcmVzb3VyY2VzIHRvIHJlZnVuZCB0aGUgb3JpZ2luYWwgUkFNIHBheWVyLgoKSWYge3t0b319IGRvZXMgbm90IGhhdmUgYSBiYWxhbmNlIGZvciB7e2Fzc2V0X3RvX3N5bWJvbF9jb2RlIHF1YW50aXR5fX0sIHt7ZnJvbX19IHdpbGwgYmUgZGVzaWduYXRlZCBhcyB0aGUgUkFNIHBheWVyIG9mIHRoZSB7e2Fzc2V0X3RvX3N5bWJvbF9jb2RlIHF1YW50aXR5fX0gdG9rZW4gYmFsYW5jZSBmb3Ige3t0b319LiBBcyBhIHJlc3VsdCwgUkFNIHdpbGwgYmUgZGVkdWN0ZWQgZnJvbSB7e2Zyb219feKAmXMgcmVzb3VyY2VzIHRvIGNyZWF0ZSB0aGUgbmVjZXNzYXJ5IHJlY29yZHMuAgAAADhPTREyA2k2NAAAB2FjY291bnQAAAAAAJBNxgNpNjQAAA5jdXJyZW5jeV9zdGF0cwAAAAAA'
7
+ )
8
+ export const abi = ABI.from(abiBlob)
9
+ export namespace Types {
10
+ @Struct.type('account')
11
+ export class account extends Struct {
12
+ @Struct.field(Asset)
13
+ declare balance: Asset
14
+ }
15
+ @Struct.type('close')
16
+ export class close extends Struct {
17
+ @Struct.field(Name)
18
+ declare owner: Name
19
+ @Struct.field(Asset.Symbol)
20
+ declare symbol: Asset.Symbol
21
+ }
22
+ @Struct.type('create')
23
+ export class create extends Struct {
24
+ @Struct.field(Name)
25
+ declare issuer: Name
26
+ @Struct.field(Asset)
27
+ declare maximum_supply: Asset
28
+ }
29
+ @Struct.type('currency_stats')
30
+ export class currency_stats extends Struct {
31
+ @Struct.field(Asset)
32
+ declare supply: Asset
33
+ @Struct.field(Asset)
34
+ declare max_supply: Asset
35
+ @Struct.field(Name)
36
+ declare issuer: Name
37
+ }
38
+ @Struct.type('issue')
39
+ export class issue extends Struct {
40
+ @Struct.field(Name)
41
+ declare to: Name
42
+ @Struct.field(Asset)
43
+ declare quantity: Asset
44
+ @Struct.field('string')
45
+ declare memo: string
46
+ }
47
+ @Struct.type('issuefixed')
48
+ export class issuefixed extends Struct {
49
+ @Struct.field(Name)
50
+ declare to: Name
51
+ @Struct.field(Asset)
52
+ declare supply: Asset
53
+ @Struct.field('string')
54
+ declare memo: string
55
+ }
56
+ @Struct.type('open')
57
+ export class open extends Struct {
58
+ @Struct.field(Name)
59
+ declare owner: Name
60
+ @Struct.field(Asset.Symbol)
61
+ declare symbol: Asset.Symbol
62
+ @Struct.field(Name)
63
+ declare ram_payer: Name
64
+ }
65
+ @Struct.type('retire')
66
+ export class retire extends Struct {
67
+ @Struct.field(Asset)
68
+ declare quantity: Asset
69
+ @Struct.field('string')
70
+ declare memo: string
71
+ }
72
+ @Struct.type('setmaxsupply')
73
+ export class setmaxsupply extends Struct {
74
+ @Struct.field(Name)
75
+ declare issuer: Name
76
+ @Struct.field(Asset)
77
+ declare maximum_supply: Asset
78
+ }
79
+ @Struct.type('transfer')
80
+ export class transfer extends Struct {
81
+ @Struct.field(Name)
82
+ declare from: Name
83
+ @Struct.field(Name)
84
+ declare to: Name
85
+ @Struct.field(Asset)
86
+ declare quantity: Asset
87
+ @Struct.field('string')
88
+ declare memo: string
89
+ }
90
+ }
91
+ export const TableMap = {
92
+ accounts: Types.account,
93
+ stat: Types.currency_stats,
94
+ }
95
+ export interface TableTypes {
96
+ accounts: Types.account
97
+ stat: Types.currency_stats
98
+ }
99
+ export type RowType<T> = T extends keyof TableTypes ? TableTypes[T] : any
100
+ export type TableNames = keyof TableTypes
101
+ export namespace ActionParams {
102
+ export namespace Type {}
103
+ export interface close {
104
+ owner: NameType
105
+ symbol: Asset.SymbolType
106
+ }
107
+ export interface create {
108
+ issuer: NameType
109
+ maximum_supply: AssetType
110
+ }
111
+ export interface issue {
112
+ to: NameType
113
+ quantity: AssetType
114
+ memo: string
115
+ }
116
+ export interface issuefixed {
117
+ to: NameType
118
+ supply: AssetType
119
+ memo: string
120
+ }
121
+ export interface open {
122
+ owner: NameType
123
+ symbol: Asset.SymbolType
124
+ ram_payer: NameType
125
+ }
126
+ export interface retire {
127
+ quantity: AssetType
128
+ memo: string
129
+ }
130
+ export interface setmaxsupply {
131
+ issuer: NameType
132
+ maximum_supply: AssetType
133
+ }
134
+ export interface transfer {
135
+ from: NameType
136
+ to: NameType
137
+ quantity: AssetType
138
+ memo: string
139
+ }
140
+ }
141
+ export interface ActionNameParams {
142
+ close: ActionParams.close
143
+ create: ActionParams.create
144
+ issue: ActionParams.issue
145
+ issuefixed: ActionParams.issuefixed
146
+ open: ActionParams.open
147
+ retire: ActionParams.retire
148
+ setmaxsupply: ActionParams.setmaxsupply
149
+ transfer: ActionParams.transfer
150
+ }
151
+ export type ActionNames = keyof ActionNameParams
152
+ export class Contract extends BaseContract {
153
+ constructor(args: PartialBy<ContractArgs, 'abi' | 'account'>) {
154
+ super({
155
+ client: args.client,
156
+ abi: abi,
157
+ account: args.account || Name.from('eosio.token'),
158
+ })
159
+ }
160
+ action<T extends ActionNames>(
161
+ name: T,
162
+ data: ActionNameParams[T],
163
+ options?: ActionOptions
164
+ ): Action {
165
+ return super.action(name, data, options)
166
+ }
167
+ table<T extends TableNames>(name: T, scope?: NameType): Table<RowType<T>> {
168
+ return super.table(name, scope, TableMap[name])
169
+ }
170
+ }
package/src/contracts.ts CHANGED
@@ -1,2 +1,4 @@
1
+ export * as FundContract from './contracts/fund'
1
2
  export * as PlatformContract from './contracts/platform'
2
3
  export * as ServerContract from './contracts/server'
4
+ export * as TokenContract from './contracts/token'
@@ -0,0 +1,88 @@
1
+ import type {Checksum256Type} from '@wharfkit/antelope'
2
+ import {
3
+ COORD_MAX,
4
+ COORD_MIN,
5
+ COORD_OFFSET,
6
+ LOCAL_HALF,
7
+ LOCAL_MAX,
8
+ LOCAL_MIN,
9
+ REGION_DIV,
10
+ REGION_PER_AXIS,
11
+ SECTOR_DIV,
12
+ } from './constants'
13
+ import {decodeRegion, encodeRegion} from './regions'
14
+ import {decodeSector, encodeSector} from './sectors'
15
+
16
+ export interface CoordinateAddress {
17
+ sector: string
18
+ region: string
19
+ localX: number
20
+ localY: number
21
+ }
22
+
23
+ interface AxisSlices {
24
+ sector: number
25
+ region: number
26
+ local: number
27
+ }
28
+
29
+ function sliceAxis(coord: number): AxisSlices {
30
+ if (!Number.isInteger(coord) || coord < COORD_MIN || coord > COORD_MAX) {
31
+ throw new RangeError(`coordinate out of range: ${coord}`)
32
+ }
33
+ const u = coord + COORD_OFFSET
34
+ return {
35
+ sector: Math.floor(u / SECTOR_DIV),
36
+ region: Math.floor(u / REGION_DIV) % REGION_PER_AXIS,
37
+ local: (u % REGION_DIV) - LOCAL_HALF,
38
+ }
39
+ }
40
+
41
+ export function encodeAddress(seed: Checksum256Type, x: number, y: number): CoordinateAddress {
42
+ const ax = sliceAxis(x)
43
+ const ay = sliceAxis(y)
44
+ return {
45
+ sector: encodeSector(seed, ax.sector, ay.sector),
46
+ region: encodeRegion(seed, ax.region, ay.region),
47
+ localX: ax.local,
48
+ localY: ay.local,
49
+ }
50
+ }
51
+
52
+ export function decodeAddress(
53
+ seed: Checksum256Type,
54
+ addr: CoordinateAddress
55
+ ): {x: number; y: number} {
56
+ if (
57
+ !Number.isInteger(addr.localX) ||
58
+ !Number.isInteger(addr.localY) ||
59
+ addr.localX < LOCAL_MIN ||
60
+ addr.localX > LOCAL_MAX ||
61
+ addr.localY < LOCAL_MIN ||
62
+ addr.localY > LOCAL_MAX
63
+ ) {
64
+ throw new RangeError(`local position out of range: ${addr.localX}, ${addr.localY}`)
65
+ }
66
+ const sector = decodeSector(seed, addr.sector)
67
+ const region = decodeRegion(seed, addr.region)
68
+ const x =
69
+ sector.sx * SECTOR_DIV + region.rx * REGION_DIV + (addr.localX + LOCAL_HALF) - COORD_OFFSET
70
+ const y =
71
+ sector.sy * SECTOR_DIV + region.ry * REGION_DIV + (addr.localY + LOCAL_HALF) - COORD_OFFSET
72
+ if (x < COORD_MIN || x > COORD_MAX || y < COORD_MIN || y > COORD_MAX) {
73
+ throw new RangeError(`address decodes outside the coordinate range: ${x}, ${y}`)
74
+ }
75
+ return {x, y}
76
+ }
77
+
78
+ export function addressFromCoordinates(
79
+ seed: Checksum256Type,
80
+ coords: {
81
+ x: number | {toNumber(): number}
82
+ y: number | {toNumber(): number}
83
+ }
84
+ ): CoordinateAddress {
85
+ const x = typeof coords.x === 'number' ? coords.x : coords.x.toNumber()
86
+ const y = typeof coords.y === 'number' ? coords.y : coords.y.toNumber()
87
+ return encodeAddress(seed, x, y)
88
+ }
@@ -0,0 +1,15 @@
1
+ import {describe, expect, test} from 'bun:test'
2
+ import * as sdk from '../index-module'
3
+
4
+ describe('coordinate constants re-export', () => {
5
+ test('frozen spatial constants are reachable from the package root', () => {
6
+ expect(sdk.REGION_DIV).toBe(10_000)
7
+ expect(sdk.SECTOR_DIV).toBe(100_000_000)
8
+ expect(sdk.COORD_OFFSET).toBe(2_147_485_000)
9
+ expect(sdk.SECTORS_PER_AXIS).toBe(43)
10
+ expect(sdk.REGION_PER_AXIS).toBe(10_000)
11
+ expect(sdk.LOCAL_HALF).toBe(5_000)
12
+ expect(sdk.COORD_MIN).toBe(-2_147_483_648)
13
+ expect(sdk.COORD_MAX).toBe(2_147_483_647)
14
+ })
15
+ })
@@ -0,0 +1,23 @@
1
+ import type {FeistelConfig} from './permutation'
2
+
3
+ // FROZEN INTERFACE — these values define the on-the-wire address format.
4
+ export const COORD_MIN = -2_147_483_648
5
+ export const COORD_MAX = 2_147_483_647
6
+ // Centers the region grid on the origin: raw (0,0) sits at a region center (local 0,0), not a corner; u stays >= 0 across int32.
7
+ export const COORD_OFFSET = 2_147_485_000
8
+ export const AXIS_SPAN = 4_294_967_296 // 2^32 distinct values per axis
9
+
10
+ export const SECTOR_DIV = 100_000_000 // 10^8 tiles per sector side
11
+ export const REGION_DIV = 10_000 // 10^4 tiles per region side
12
+ export const SECTORS_PER_AXIS = 43 // floor((2^32 - 1) / 10^8) + 1
13
+ export const REGION_PER_AXIS = 10_000
14
+ export const LOCAL_HALF = 5_000 // half a region; local is signed, measured from the region center
15
+ export const LOCAL_MIN = -5_000
16
+ export const LOCAL_MAX = 4_999
17
+
18
+ export const SECTOR_COUNT = SECTORS_PER_AXIS * SECTORS_PER_AXIS // 1849
19
+ export const REGION_COUNT = REGION_PER_AXIS * REGION_PER_AXIS // 100,000,000
20
+
21
+ // 2*halfBits must give a block domain >= the tier's count.
22
+ export const SECTOR_FEISTEL: FeistelConfig = {n: SECTOR_COUNT, halfBits: 6, label: 'sector'} // 2^12 = 4096
23
+ export const REGION_FEISTEL: FeistelConfig = {n: REGION_COUNT, halfBits: 14, label: 'region'} // 2^28 ≈ 2.68e8
@@ -0,0 +1,15 @@
1
+ export type {CoordinateAddress} from './address'
2
+ export {addressFromCoordinates, decodeAddress, encodeAddress} from './address'
3
+ export {encodeSector, decodeSector} from './sectors'
4
+ export {encodeRegion, decodeRegion} from './regions'
5
+ export {encodeAddressMemo} from './memo'
6
+ export {
7
+ COORD_MIN,
8
+ COORD_MAX,
9
+ COORD_OFFSET,
10
+ REGION_DIV,
11
+ SECTOR_DIV,
12
+ SECTORS_PER_AXIS,
13
+ REGION_PER_AXIS,
14
+ LOCAL_HALF,
15
+ } from './constants'
@@ -0,0 +1,47 @@
1
+ import {describe, expect, test} from 'bun:test'
2
+ import {Checksum256} from '@wharfkit/antelope'
3
+ import {encodeAddress, decodeAddress} from './address'
4
+ import {encodeAddressMemo} from './memo'
5
+
6
+ const SEED = Checksum256.from('73e4385a2708e6d704883c670c50b0aa502ba1098072ed100ae1920eee3597d9')
7
+
8
+ describe('encodeAddressMemo', () => {
9
+ test('matches encodeAddress', () => {
10
+ for (const [x, y] of [
11
+ [0, 0],
12
+ [12, -9],
13
+ [2_147_483_647, -2_147_483_648],
14
+ ] as const) {
15
+ expect(encodeAddressMemo(SEED, x, y)).toEqual(encodeAddress(SEED, x, y))
16
+ }
17
+ })
18
+
19
+ test('returns the same cached object reference for repeat calls', () => {
20
+ const a = encodeAddressMemo(SEED, 4827, 1190)
21
+ const b = encodeAddressMemo(SEED, 4827, 1190)
22
+ expect(a).toBe(b)
23
+ })
24
+
25
+ test('round-trips through decodeAddress', () => {
26
+ const addr = encodeAddressMemo(SEED, -5, 7)
27
+ expect(decodeAddress(SEED, addr)).toEqual({x: -5, y: 7})
28
+ })
29
+
30
+ test('origin is centered: raw (0,0) is local (0,0)', () => {
31
+ const addr = encodeAddressMemo(SEED, 0, 0)
32
+ expect([addr.localX, addr.localY]).toEqual([0, 0])
33
+ })
34
+
35
+ test('origin neighbors share the origin region', () => {
36
+ const origin = encodeAddressMemo(SEED, 0, 0)
37
+ for (const [x, y] of [
38
+ [-1, -1],
39
+ [4999, 4999],
40
+ [-5000, -5000],
41
+ ] as const) {
42
+ expect(encodeAddressMemo(SEED, x, y).region).toBe(origin.region)
43
+ }
44
+ // first tile outside the origin region on each axis falls into a different region
45
+ expect(encodeAddressMemo(SEED, 5000, 0).region).not.toBe(origin.region)
46
+ })
47
+ })
@@ -0,0 +1,20 @@
1
+ import type {Checksum256Type} from '@wharfkit/antelope'
2
+ import {Checksum256} from '@wharfkit/antelope'
3
+ import {type CoordinateAddress, encodeAddress} from './address'
4
+
5
+ const cache = new Map<string, CoordinateAddress>()
6
+ const CACHE_MAX = 4096
7
+
8
+ export function encodeAddressMemo(seed: Checksum256Type, x: number, y: number): CoordinateAddress {
9
+ const key = `${Checksum256.from(seed).toString()}:${x},${y}`
10
+ let hit = cache.get(key)
11
+ if (!hit) {
12
+ hit = encodeAddress(seed, x, y)
13
+ if (cache.size >= CACHE_MAX) {
14
+ const oldest = cache.keys().next().value
15
+ if (oldest !== undefined) cache.delete(oldest)
16
+ }
17
+ cache.set(key, hit)
18
+ }
19
+ return hit
20
+ }
@@ -0,0 +1,77 @@
1
+ import type {Checksum256Type} from '@wharfkit/antelope'
2
+ import {hash512} from '../utils/hash'
3
+
4
+ // FROZEN INTERFACE — round count, key-derivation strings, and mixing constants must never change; per-game variation comes from the seed.
5
+ const ROUNDS = 4
6
+
7
+ export interface FeistelConfig {
8
+ n: number
9
+ halfBits: number
10
+ label: string
11
+ }
12
+
13
+ const keyCache = new Map<string, number[]>()
14
+
15
+ function deriveRoundKeys(seed: Checksum256Type, label: string): number[] {
16
+ const cacheKey = `${seed}:${label}`
17
+ const cached = keyCache.get(cacheKey)
18
+ if (cached) return cached
19
+ const h = hash512(seed, `coord-keys-${label}`).array
20
+ const keys: number[] = []
21
+ for (let i = 0; i < ROUNDS; i++) {
22
+ const o = i * 4
23
+ keys.push(((h[o] << 24) | (h[o + 1] << 16) | (h[o + 2] << 8) | h[o + 3]) >>> 0)
24
+ }
25
+ keyCache.set(cacheKey, keys)
26
+ return keys
27
+ }
28
+
29
+ function roundFn(r: number, key: number, halfBits: number): number {
30
+ let x = (r ^ key) >>> 0
31
+ x = Math.imul(x ^ (x >>> 16), 0x9e3779b1) >>> 0
32
+ x = Math.imul(x ^ (x >>> 13), 0x7feb352d) >>> 0
33
+ x = (x ^ (x >>> 16)) >>> 0
34
+ return x & ((1 << halfBits) - 1)
35
+ }
36
+
37
+ function encryptBlock(x: number, halfBits: number, keys: number[]): number {
38
+ const mask = (1 << halfBits) - 1
39
+ let L = (x >>> halfBits) & mask
40
+ let R = x & mask
41
+ for (let i = 0; i < ROUNDS; i++) {
42
+ const F = roundFn(R, keys[i], halfBits)
43
+ const nL = R
44
+ const nR = (L ^ F) & mask
45
+ L = nL
46
+ R = nR
47
+ }
48
+ return ((L << halfBits) | R) >>> 0
49
+ }
50
+
51
+ function decryptBlock(y: number, halfBits: number, keys: number[]): number {
52
+ const mask = (1 << halfBits) - 1
53
+ let L = (y >>> halfBits) & mask
54
+ let R = y & mask
55
+ for (let i = ROUNDS - 1; i >= 0; i--) {
56
+ const F = roundFn(L, keys[i], halfBits)
57
+ const nR = L
58
+ const nL = (R ^ F) & mask
59
+ L = nL
60
+ R = nR
61
+ }
62
+ return ((L << halfBits) | R) >>> 0
63
+ }
64
+
65
+ export function permute(seed: Checksum256Type, x: number, cfg: FeistelConfig): number {
66
+ const keys = deriveRoundKeys(seed, cfg.label)
67
+ let v = encryptBlock(x, cfg.halfBits, keys)
68
+ while (v >= cfg.n) v = encryptBlock(v, cfg.halfBits, keys)
69
+ return v
70
+ }
71
+
72
+ export function unpermute(seed: Checksum256Type, y: number, cfg: FeistelConfig): number {
73
+ const keys = deriveRoundKeys(seed, cfg.label)
74
+ let v = decryptBlock(y, cfg.halfBits, keys)
75
+ while (v >= cfg.n) v = decryptBlock(v, cfg.halfBits, keys)
76
+ return v
77
+ }
@@ -0,0 +1,48 @@
1
+ import type {Checksum256Type} from '@wharfkit/antelope'
2
+ import {REGION_FEISTEL, REGION_PER_AXIS} from './constants'
3
+ import {permute, unpermute} from './permutation'
4
+
5
+ // FROZEN INTERFACE — phoneme tables; tune aesthetics before launch, then never reorder.
6
+ const ONSETS = ['b', 'd', 'f', 'g', 'k', 'l', 'm', 'n', 'p', 'r', 's', 't'] // 12
7
+ const VOWELS = ['a', 'e', 'i', 'o', 'u'] // 5
8
+ const CODAS = ['n', 'r', 'l', 's', 'k', 'm', 't', 'x'] // 8
9
+ const SYL_BASE = ONSETS.length * VOWELS.length * CODAS.length // 480
10
+
11
+ function syllable(digit: number): string {
12
+ const onset = Math.floor(digit / (VOWELS.length * CODAS.length))
13
+ const rem = digit % (VOWELS.length * CODAS.length)
14
+ const vowel = Math.floor(rem / CODAS.length)
15
+ const coda = rem % CODAS.length
16
+ return ONSETS[onset] + VOWELS[vowel] + CODAS[coda]
17
+ }
18
+
19
+ function unsyllable(chunk: string): number {
20
+ const onset = ONSETS.indexOf(chunk[0])
21
+ const vowel = VOWELS.indexOf(chunk[1])
22
+ const coda = CODAS.indexOf(chunk[2])
23
+ if (onset < 0 || vowel < 0 || coda < 0) throw new Error(`invalid region token chunk: ${chunk}`)
24
+ return onset * (VOWELS.length * CODAS.length) + vowel * CODAS.length + coda
25
+ }
26
+
27
+ export function encodeRegion(seed: Checksum256Type, rx: number, ry: number): string {
28
+ const index = rx * REGION_PER_AXIS + ry
29
+ let n = permute(seed, index, REGION_FEISTEL)
30
+ const d0 = n % SYL_BASE
31
+ n = Math.floor(n / SYL_BASE)
32
+ const d1 = n % SYL_BASE
33
+ const d2 = Math.floor(n / SYL_BASE)
34
+ const token = syllable(d2) + syllable(d1) + syllable(d0)
35
+ return token.charAt(0).toUpperCase() + token.slice(1)
36
+ }
37
+
38
+ export function decodeRegion(seed: Checksum256Type, token: string): {rx: number; ry: number} {
39
+ if (token.length !== 9) throw new Error(`invalid region token length: ${token}`)
40
+ const lower = token.toLowerCase()
41
+ const d2 = unsyllable(lower.slice(0, 3))
42
+ const d1 = unsyllable(lower.slice(3, 6))
43
+ const d0 = unsyllable(lower.slice(6, 9))
44
+ const scrambled = (d2 * SYL_BASE + d1) * SYL_BASE + d0
45
+ if (scrambled >= REGION_FEISTEL.n) throw new Error(`invalid region token: ${token}`)
46
+ const index = unpermute(seed, scrambled, REGION_FEISTEL)
47
+ return {rx: Math.floor(index / REGION_PER_AXIS), ry: index % REGION_PER_AXIS}
48
+ }
@@ -0,0 +1,115 @@
1
+ import type {Checksum256Type} from '@wharfkit/antelope'
2
+ import {SECTOR_FEISTEL, SECTORS_PER_AXIS} from './constants'
3
+ import {permute, unpermute} from './permutation'
4
+
5
+ // FROZEN INTERFACE — curation seed; review before launch, then never reorder.
6
+ export const SECTOR_ADJECTIVES: readonly string[] = [
7
+ 'Amber',
8
+ 'Azure',
9
+ 'Brass',
10
+ 'Cinder',
11
+ 'Cobalt',
12
+ 'Copper',
13
+ 'Coral',
14
+ 'Crimson',
15
+ 'Crystal',
16
+ 'Dusk',
17
+ 'Ember',
18
+ 'Emerald',
19
+ 'Frost',
20
+ 'Glimmer',
21
+ 'Golden',
22
+ 'Hazy',
23
+ 'Indigo',
24
+ 'Iron',
25
+ 'Ivory',
26
+ 'Jade',
27
+ 'Lunar',
28
+ 'Misty',
29
+ 'Neon',
30
+ 'Onyx',
31
+ 'Opal',
32
+ 'Pearl',
33
+ 'Plasma',
34
+ 'Quartz',
35
+ 'Rusty',
36
+ 'Saffron',
37
+ 'Scarlet',
38
+ 'Silver',
39
+ 'Solar',
40
+ 'Static',
41
+ 'Stormy',
42
+ 'Sunny',
43
+ 'Teal',
44
+ 'Umber',
45
+ 'Velvet',
46
+ 'Verdant',
47
+ 'Vermilion',
48
+ 'Violet',
49
+ 'Wispy',
50
+ ]
51
+
52
+ export const SECTOR_NOUNS: readonly string[] = [
53
+ 'Belt',
54
+ 'Bluff',
55
+ 'Cluster',
56
+ 'Coil',
57
+ 'Crest',
58
+ 'Drift',
59
+ 'Expanse',
60
+ 'Fathom',
61
+ 'Flare',
62
+ 'Gulf',
63
+ 'Halo',
64
+ 'Haven',
65
+ 'Hollow',
66
+ 'Maw',
67
+ 'Mesa',
68
+ 'Mire',
69
+ 'Notch',
70
+ 'Nook',
71
+ 'Oasis',
72
+ 'Lagoon',
73
+ 'Peak',
74
+ 'Pocket',
75
+ 'Reach',
76
+ 'Reef',
77
+ 'Ridge',
78
+ 'Rift',
79
+ 'Run',
80
+ 'Shoal',
81
+ 'Shroud',
82
+ 'Span',
83
+ 'Spire',
84
+ 'Spur',
85
+ 'Stretch',
86
+ 'Sprawl',
87
+ 'Tangle',
88
+ 'Trace',
89
+ 'Trench',
90
+ 'Vale',
91
+ 'Vault',
92
+ 'Verge',
93
+ 'Vortex',
94
+ 'Ward',
95
+ 'Wisp',
96
+ ]
97
+
98
+ export function encodeSector(seed: Checksum256Type, sx: number, sy: number): string {
99
+ const index = sx * SECTORS_PER_AXIS + sy
100
+ const scrambled = permute(seed, index, SECTOR_FEISTEL)
101
+ const adj = Math.floor(scrambled / SECTORS_PER_AXIS)
102
+ const noun = scrambled % SECTORS_PER_AXIS
103
+ return `${SECTOR_ADJECTIVES[adj]} ${SECTOR_NOUNS[noun]}`
104
+ }
105
+
106
+ export function decodeSector(seed: Checksum256Type, name: string): {sx: number; sy: number} {
107
+ const parts = name.trim().split(/\s+/)
108
+ if (parts.length !== 2) throw new Error(`invalid sector name: ${name}`)
109
+ const adj = SECTOR_ADJECTIVES.indexOf(parts[0])
110
+ const noun = SECTOR_NOUNS.indexOf(parts[1])
111
+ if (adj < 0 || noun < 0) throw new Error(`unknown sector name: ${name}`)
112
+ const scrambled = adj * SECTORS_PER_AXIS + noun
113
+ const index = unpermute(seed, scrambled, SECTOR_FEISTEL)
114
+ return {sx: Math.floor(index / SECTORS_PER_AXIS), sy: index % SECTORS_PER_AXIS}
115
+ }