create-dubhe 1.2.0-pre.98 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (361) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +16 -16
  4. package/templates/101/sui-template/docker-compose.testnet.yml +73 -0
  5. package/templates/101/sui-template/packages/client/src/app/page.tsx +545 -41
  6. package/templates/101/sui-template/packages/client/src/app/providers.tsx +12 -4
  7. package/templates/101/sui-template/packages/contracts/Pub.localnet.toml +4 -4
  8. package/templates/101/sui-template/packages/contracts/counter.lock.json +20 -0
  9. package/templates/101/sui-template/packages/contracts/deployment.ts +8 -3
  10. package/templates/101/sui-template/packages/contracts/dubhe.config.json +59 -13
  11. package/templates/101/sui-template/packages/contracts/dubhe.config.ts +1 -4
  12. package/templates/101/sui-template/packages/contracts/metadata.json +1015 -68
  13. package/templates/101/sui-template/packages/contracts/package.json +7 -4
  14. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/dapp_key.move +45 -31
  15. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/error.move +8 -0
  16. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/genesis.move +30 -13
  17. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/init_test.move +19 -14
  18. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter2.move +198 -0
  19. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter2withkey.move +90 -0
  20. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/resources/value.move +30 -20
  21. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/user_storage_init.move +26 -0
  22. package/templates/101/sui-template/packages/contracts/src/counter/sources/scripts/deploy_hook.move +6 -11
  23. package/templates/101/sui-template/packages/contracts/src/counter/sources/systems/counter.move +23 -11
  24. package/templates/101/sui-template/packages/contracts/src/counter/sources/tests/counter.move +15 -14
  25. package/templates/101/sui-template/packages/contracts/src/dubhe/Move.lock +33 -30
  26. package/templates/101/sui-template/packages/contracts/src/dubhe/Move.toml +8 -3
  27. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/dapp_key.move +45 -31
  28. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/error.move +170 -0
  29. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/genesis.move +16 -13
  30. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/init_test.move +8 -14
  31. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/account_key.move +1 -3
  32. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/dapp_service.move +1776 -137
  33. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/data_key.move +1 -20
  34. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/events.move +864 -25
  35. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/scripts/deploy_hook.move +15 -16
  36. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/scripts/migrate.move +0 -3
  37. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/address_system.move +25 -17
  38. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/dapp_system.move +2802 -343
  39. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/utils.move +1 -1
  40. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/address.move +173 -55
  41. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/dapp_test.move +769 -0
  42. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/fee_test.move +2965 -0
  43. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/integration_test.move +303 -0
  44. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/listing_test.move +1422 -0
  45. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/scene_session_test.move +269 -0
  46. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/session_test.move +624 -0
  47. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/storage_test.move +700 -0
  48. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/typed_object_test.move +177 -0
  49. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/typed_scene_test.move +452 -0
  50. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/user_storage_test.move +160 -0
  51. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/utils/math.move +4 -3
  52. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/utils/type_info.move +2 -2
  53. package/templates/contract/sui-template/dubhe.config.ts +0 -1
  54. package/templates/contract/sui-template/package.json +3 -3
  55. package/templates/contract/sui-template/src/dubhe/Move.lock +33 -30
  56. package/templates/contract/sui-template/src/dubhe/Move.toml +8 -3
  57. package/templates/contract/sui-template/src/dubhe/sources/codegen/dapp_key.move +45 -31
  58. package/templates/contract/sui-template/src/dubhe/sources/codegen/error.move +170 -0
  59. package/templates/contract/sui-template/src/dubhe/sources/codegen/genesis.move +16 -13
  60. package/templates/contract/sui-template/src/dubhe/sources/codegen/init_test.move +8 -14
  61. package/templates/contract/sui-template/src/dubhe/sources/core/account_key.move +1 -3
  62. package/templates/contract/sui-template/src/dubhe/sources/core/dapp_service.move +1776 -137
  63. package/templates/contract/sui-template/src/dubhe/sources/core/data_key.move +1 -20
  64. package/templates/contract/sui-template/src/dubhe/sources/core/events.move +864 -25
  65. package/templates/contract/sui-template/src/dubhe/sources/scripts/deploy_hook.move +15 -16
  66. package/templates/contract/sui-template/src/dubhe/sources/scripts/migrate.move +0 -3
  67. package/templates/contract/sui-template/src/dubhe/sources/systems/address_system.move +25 -17
  68. package/templates/contract/sui-template/src/dubhe/sources/systems/dapp_system.move +2802 -343
  69. package/templates/contract/sui-template/src/dubhe/sources/systems/utils.move +1 -1
  70. package/templates/contract/sui-template/src/dubhe/sources/tests/address.move +173 -55
  71. package/templates/contract/sui-template/src/dubhe/sources/tests/dapp_test.move +769 -0
  72. package/templates/contract/sui-template/src/dubhe/sources/tests/fee_test.move +2965 -0
  73. package/templates/contract/sui-template/src/dubhe/sources/tests/integration_test.move +303 -0
  74. package/templates/contract/sui-template/src/dubhe/sources/tests/listing_test.move +1422 -0
  75. package/templates/contract/sui-template/src/dubhe/sources/tests/scene_session_test.move +269 -0
  76. package/templates/contract/sui-template/src/dubhe/sources/tests/session_test.move +624 -0
  77. package/templates/contract/sui-template/src/dubhe/sources/tests/storage_test.move +700 -0
  78. package/templates/contract/sui-template/src/dubhe/sources/tests/typed_object_test.move +177 -0
  79. package/templates/contract/sui-template/src/dubhe/sources/tests/typed_scene_test.move +452 -0
  80. package/templates/contract/sui-template/src/dubhe/sources/tests/user_storage_test.move +160 -0
  81. package/templates/contract/sui-template/src/dubhe/sources/utils/math.move +4 -3
  82. package/templates/contract/sui-template/src/dubhe/sources/utils/type_info.move +2 -2
  83. package/templates/contract/sui-template/src/template/Move.toml +12 -0
  84. package/templates/contract/sui-template/src/template/sources/codegen/dapp_key.move +47 -0
  85. package/templates/contract/sui-template/src/template/sources/codegen/genesis.move +34 -0
  86. package/templates/contract/sui-template/src/template/sources/codegen/init_test.move +23 -0
  87. package/templates/contract/sui-template/src/template/sources/codegen/user_storage_init.move +27 -0
  88. package/templates/contract/sui-template/src/template/sources/scripts/deploy_hook.move +13 -0
  89. package/templates/contract/sui-template/src/template/sources/scripts/migrate.move +7 -0
  90. package/templates/nextjs/sui-card-duel/.gitignore_ +51 -0
  91. package/templates/nextjs/sui-card-duel/README.md +213 -0
  92. package/templates/nextjs/sui-card-duel/docker-compose.yml +34 -0
  93. package/templates/nextjs/sui-card-duel/mprocs.yaml +17 -0
  94. package/templates/nextjs/sui-card-duel/package.json +43 -0
  95. package/templates/nextjs/sui-card-duel/packages/client/.gitignore_ +48 -0
  96. package/templates/nextjs/sui-card-duel/packages/client/.prettierignore +1 -0
  97. package/templates/nextjs/sui-card-duel/packages/client/.prettierrc.json +8 -0
  98. package/templates/nextjs/sui-card-duel/packages/client/eslint.config.mjs +22 -0
  99. package/templates/nextjs/sui-card-duel/packages/client/next.config.mjs +8 -0
  100. package/templates/nextjs/sui-card-duel/packages/client/package.json +47 -0
  101. package/templates/nextjs/sui-card-duel/packages/client/postcss.config.mjs +8 -0
  102. package/templates/nextjs/sui-card-duel/packages/client/src/app/admin/ArenaPanel.tsx +307 -0
  103. package/templates/nextjs/sui-card-duel/packages/client/src/app/admin/page.tsx +622 -0
  104. package/templates/nextjs/sui-card-duel/packages/client/src/app/brawl/[id]/page.tsx +559 -0
  105. package/templates/nextjs/sui-card-duel/packages/client/src/app/collection/page.tsx +202 -0
  106. package/templates/nextjs/sui-card-duel/packages/client/src/app/components/CardView.tsx +66 -0
  107. package/templates/nextjs/sui-card-duel/packages/client/src/app/components/GameShell.tsx +294 -0
  108. package/templates/nextjs/sui-card-duel/packages/client/src/app/components/icons.tsx +101 -0
  109. package/templates/nextjs/sui-card-duel/packages/client/src/app/duel/[id]/page.tsx +477 -0
  110. package/templates/nextjs/sui-card-duel/packages/client/src/app/favicon.ico +0 -0
  111. package/templates/nextjs/sui-card-duel/packages/client/src/app/globals.css +85 -0
  112. package/templates/nextjs/sui-card-duel/packages/client/src/app/hooks/useGame.ts +313 -0
  113. package/templates/nextjs/sui-card-duel/packages/client/src/app/layout.tsx +24 -0
  114. package/templates/nextjs/sui-card-duel/packages/client/src/app/leaderboard/page.tsx +123 -0
  115. package/templates/nextjs/sui-card-duel/packages/client/src/app/lib/game.ts +77 -0
  116. package/templates/nextjs/sui-card-duel/packages/client/src/app/lib/scenes.ts +226 -0
  117. package/templates/nextjs/sui-card-duel/packages/client/src/app/market/page.tsx +418 -0
  118. package/templates/nextjs/sui-card-duel/packages/client/src/app/page.tsx +427 -0
  119. package/templates/nextjs/sui-card-duel/packages/client/src/app/providers.tsx +69 -0
  120. package/templates/nextjs/sui-card-duel/packages/client/tailwind.config.ts +21 -0
  121. package/templates/nextjs/sui-card-duel/packages/client/tsconfig.json +30 -0
  122. package/templates/nextjs/sui-card-duel/packages/contracts/.gitignore_ +51 -0
  123. package/templates/nextjs/sui-card-duel/packages/contracts/.prettierignore +1 -0
  124. package/templates/nextjs/sui-card-duel/packages/contracts/.prettierrc.json +8 -0
  125. package/templates/nextjs/sui-card-duel/packages/contracts/Dockerfile +5 -0
  126. package/templates/nextjs/sui-card-duel/packages/contracts/Pub.localnet.toml +13 -0
  127. package/templates/nextjs/sui-card-duel/packages/contracts/card_duel.lock.json +66 -0
  128. package/templates/nextjs/sui-card-duel/packages/contracts/docker-compose.yml +34 -0
  129. package/templates/nextjs/sui-card-duel/packages/contracts/dubhe.config.ts +150 -0
  130. package/templates/nextjs/sui-card-duel/packages/contracts/logs/combined.log +31383 -0
  131. package/templates/nextjs/sui-card-duel/packages/contracts/package.json +49 -0
  132. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/config.ts +17 -0
  133. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-brawl.ts +270 -0
  134. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-duel.ts +272 -0
  135. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-lobby.ts +177 -0
  136. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-market.ts +219 -0
  137. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-session.ts +342 -0
  138. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/query-dapp-revenue.ts +95 -0
  139. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/seed.ts +92 -0
  140. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/withdraw-dapp-revenue.ts +56 -0
  141. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/Move.toml +15 -0
  142. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/dapp_key.move +46 -0
  143. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/enums/card_kind.move +47 -0
  144. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/enums/match_state.move +37 -0
  145. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/enums/rarity.move +37 -0
  146. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/error.move +126 -0
  147. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/genesis.move +33 -0
  148. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/init_test.move +23 -0
  149. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/objects/arena.move +137 -0
  150. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/permits/brawl_permit.move +125 -0
  151. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/permits/duel_permit.move +125 -0
  152. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/battle_state.move +255 -0
  153. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/card.move +282 -0
  154. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/deck.move +64 -0
  155. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/game_config.move +267 -0
  156. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/gold.move +205 -0
  157. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/profile.move +255 -0
  158. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/scenes/brawl.move +313 -0
  159. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/scenes/duel.move +313 -0
  160. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/user_storage_init.move +26 -0
  161. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/scripts/deploy_hook.move +32 -0
  162. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/scripts/migrate.move +7 -0
  163. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/arena_system.move +57 -0
  164. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/brawl_system.move +559 -0
  165. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/card_system.move +146 -0
  166. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/duel_system.move +515 -0
  167. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/market_system.move +115 -0
  168. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/player_system.move +37 -0
  169. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/tests/brawl_tests.move +385 -0
  170. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/tests/duel_tests.move +656 -0
  171. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/tests/test_helpers.move +31 -0
  172. package/templates/nextjs/sui-card-duel/packages/contracts/sui-indexer-schema.graphql +5973 -0
  173. package/templates/nextjs/sui-card-duel/pnpm-workspace.yaml +2 -0
  174. package/templates/nextjs/sui-farm/.gitignore_ +51 -0
  175. package/templates/nextjs/sui-farm/README.md +15 -0
  176. package/templates/nextjs/sui-farm/UPGRADE_NOTES.md +97 -0
  177. package/templates/nextjs/sui-farm/docker-compose.yml +34 -0
  178. package/templates/nextjs/sui-farm/mprocs.yaml +17 -0
  179. package/templates/nextjs/sui-farm/package.json +43 -0
  180. package/templates/nextjs/sui-farm/packages/client/.gitignore_ +48 -0
  181. package/templates/nextjs/sui-farm/packages/client/.prettierignore +1 -0
  182. package/templates/nextjs/sui-farm/packages/client/.prettierrc.json +8 -0
  183. package/templates/nextjs/sui-farm/packages/client/eslint.config.mjs +22 -0
  184. package/templates/nextjs/sui-farm/packages/client/next.config.mjs +8 -0
  185. package/templates/nextjs/sui-farm/packages/client/package.json +47 -0
  186. package/templates/nextjs/sui-farm/packages/client/postcss.config.mjs +8 -0
  187. package/templates/nextjs/sui-farm/packages/client/src/app/admin/page.tsx +618 -0
  188. package/templates/nextjs/sui-farm/packages/client/src/app/components/FarmLand.tsx +526 -0
  189. package/templates/nextjs/sui-farm/packages/client/src/app/components/FarmPlotCard.tsx +215 -0
  190. package/templates/nextjs/sui-farm/packages/client/src/app/components/PetAvatar.tsx +868 -0
  191. package/templates/nextjs/sui-farm/packages/client/src/app/components/PetPanel.tsx +1360 -0
  192. package/templates/nextjs/sui-farm/packages/client/src/app/components/PlantModal.tsx +147 -0
  193. package/templates/nextjs/sui-farm/packages/client/src/app/components/ProxyCard.tsx +684 -0
  194. package/templates/nextjs/sui-farm/packages/client/src/app/components/RanchLand.tsx +822 -0
  195. package/templates/nextjs/sui-farm/packages/client/src/app/components/ResourceHUD.tsx +125 -0
  196. package/templates/nextjs/sui-farm/packages/client/src/app/components/ShopPanel.tsx +232 -0
  197. package/templates/nextjs/sui-farm/packages/client/src/app/components/icons/GameIcons.tsx +574 -0
  198. package/templates/nextjs/sui-farm/packages/client/src/app/favicon.ico +0 -0
  199. package/templates/nextjs/sui-farm/packages/client/src/app/globals.css +423 -0
  200. package/templates/nextjs/sui-farm/packages/client/src/app/hooks/useWorldPermitId.ts +66 -0
  201. package/templates/nextjs/sui-farm/packages/client/src/app/layout.tsx +23 -0
  202. package/templates/nextjs/sui-farm/packages/client/src/app/leaderboard/page.tsx +185 -0
  203. package/templates/nextjs/sui-farm/packages/client/src/app/lib/crops.ts +97 -0
  204. package/templates/nextjs/sui-farm/packages/client/src/app/market/page.tsx +763 -0
  205. package/templates/nextjs/sui-farm/packages/client/src/app/page.tsx +1173 -0
  206. package/templates/nextjs/sui-farm/packages/client/src/app/providers.tsx +69 -0
  207. package/templates/nextjs/sui-farm/packages/client/src/app/state/index.tsx +5 -0
  208. package/templates/nextjs/sui-farm/packages/client/tailwind.config.ts +25 -0
  209. package/templates/nextjs/sui-farm/packages/client/tsconfig.json +30 -0
  210. package/templates/nextjs/sui-farm/packages/contracts/.gitignore_ +51 -0
  211. package/templates/nextjs/sui-farm/packages/contracts/.prettierignore +1 -0
  212. package/templates/nextjs/sui-farm/packages/contracts/.prettierrc.json +8 -0
  213. package/templates/nextjs/sui-farm/packages/contracts/Dockerfile +5 -0
  214. package/templates/nextjs/sui-farm/packages/contracts/Pub.localnet.toml +13 -0
  215. package/templates/nextjs/sui-farm/packages/contracts/counter.lock.json +14 -0
  216. package/templates/nextjs/sui-farm/packages/contracts/docker-compose.yml +34 -0
  217. package/templates/nextjs/sui-farm/packages/contracts/dubhe.config.ts +178 -0
  218. package/templates/nextjs/sui-farm/packages/contracts/harvest.lock.json +120 -0
  219. package/templates/nextjs/sui-farm/packages/contracts/package.json +48 -0
  220. package/templates/nextjs/sui-farm/packages/contracts/scripts/config.ts +17 -0
  221. package/templates/nextjs/sui-farm/packages/contracts/scripts/query-dapp-revenue.ts +95 -0
  222. package/templates/nextjs/sui-farm/packages/contracts/scripts/read-permit.ts +72 -0
  223. package/templates/nextjs/sui-farm/packages/contracts/scripts/seed.ts +85 -0
  224. package/templates/nextjs/sui-farm/packages/contracts/scripts/withdraw-dapp-revenue.ts +56 -0
  225. package/templates/nextjs/sui-farm/packages/contracts/src/counter/Move.toml +14 -0
  226. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/dapp_key.move +31 -0
  227. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/error.move +10 -0
  228. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/genesis.move +33 -0
  229. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/init_test.move +23 -0
  230. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/resources/counter1.move +64 -0
  231. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/resources/counter2.move +70 -0
  232. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/user_storage_init.move +26 -0
  233. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/scripts/deploy_hook.move +8 -0
  234. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/scripts/migrate.move +8 -0
  235. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/systems/counter.move +13 -0
  236. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/tests/counter.move +28 -0
  237. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/Move.toml +14 -0
  238. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/dapp_key.move +46 -0
  239. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/enums/crop_type.move +47 -0
  240. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/enums/egg_type.move +42 -0
  241. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/enums/pet_rarity.move +37 -0
  242. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/enums/pet_species.move +52 -0
  243. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/error.move +110 -0
  244. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/genesis.move +33 -0
  245. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/init_test.move +23 -0
  246. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/permits/world.move +125 -0
  247. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/carrot.move +136 -0
  248. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/carrot_seed.move +80 -0
  249. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/common_egg.move +136 -0
  250. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/corn.move +136 -0
  251. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/corn_seed.move +80 -0
  252. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/crow_charges.move +162 -0
  253. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/crow_damage.move +207 -0
  254. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/farm_plot.move +261 -0
  255. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/gold.move +80 -0
  256. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet.move +467 -0
  257. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet_config.move +372 -0
  258. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet_hatch.move +162 -0
  259. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet_slot_index.move +83 -0
  260. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pet_slots.move +64 -0
  261. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/profile.move +162 -0
  262. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pumpkin.move +136 -0
  263. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/pumpkin_seed.move +80 -0
  264. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/rare_egg.move +136 -0
  265. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/scarecrow.move +64 -0
  266. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/season_config.move +197 -0
  267. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/season_stats.move +64 -0
  268. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/seasonal_egg.move +136 -0
  269. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/shop_config.move +267 -0
  270. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/trophy.move +245 -0
  271. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/wheat.move +136 -0
  272. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/wheat_seed.move +80 -0
  273. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/resources/world_permit_id.move +64 -0
  274. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/user_storage_init.move +26 -0
  275. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/scripts/deploy_hook.move +45 -0
  276. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/scripts/migrate.move +7 -0
  277. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/crow_system.move +96 -0
  278. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/farm_system.move +182 -0
  279. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/market_system.move +172 -0
  280. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/pet_system.move +495 -0
  281. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/season_system.move +70 -0
  282. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/shop_system.move +112 -0
  283. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/world_system.move +34 -0
  284. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/tests/farm_tests.move +1192 -0
  285. package/templates/nextjs/sui-farm/pnpm-workspace.yaml +2 -0
  286. package/templates/nextjs/sui-template/packages/client/src/app/components/ProxyCard.tsx +683 -0
  287. package/templates/nextjs/sui-template/packages/client/src/app/page.tsx +510 -5
  288. package/templates/nextjs/sui-template/packages/client/src/app/providers.tsx +13 -5
  289. package/templates/nextjs/sui-template/packages/contracts/Pub.localnet.toml +4 -4
  290. package/templates/nextjs/sui-template/packages/contracts/counter.lock.json +14 -0
  291. package/templates/nextjs/sui-template/packages/contracts/deployment.ts +8 -3
  292. package/templates/nextjs/sui-template/packages/contracts/dubhe.config.json +9 -9
  293. package/templates/nextjs/sui-template/packages/contracts/dubhe.config.ts +0 -4
  294. package/templates/nextjs/sui-template/packages/contracts/metadata.json +180 -124
  295. package/templates/nextjs/sui-template/packages/contracts/package.json +8 -4
  296. package/templates/nextjs/sui-template/packages/contracts/src/counter/Move.toml +4 -0
  297. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/dapp_key.move +45 -31
  298. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/error.move +10 -0
  299. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/genesis.move +30 -13
  300. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/init_test.move +19 -14
  301. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter1.move +30 -20
  302. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter2.move +35 -24
  303. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/user_storage_init.move +26 -0
  304. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/scripts/deploy_hook.move +6 -10
  305. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/systems/counter.move +7 -20
  306. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/tests/counter.move +14 -27
  307. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/Move.lock +33 -30
  308. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/Move.toml +8 -3
  309. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/dapp_key.move +45 -31
  310. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/error.move +170 -0
  311. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/genesis.move +16 -13
  312. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/init_test.move +8 -14
  313. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/account_key.move +1 -3
  314. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/dapp_service.move +1776 -137
  315. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/data_key.move +1 -20
  316. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/events.move +864 -25
  317. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/scripts/deploy_hook.move +15 -16
  318. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/scripts/migrate.move +0 -3
  319. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/address_system.move +25 -17
  320. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/dapp_system.move +2802 -343
  321. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/utils.move +1 -1
  322. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/address.move +173 -55
  323. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/dapp_test.move +769 -0
  324. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/fee_test.move +2965 -0
  325. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/integration_test.move +303 -0
  326. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/listing_test.move +1422 -0
  327. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/scene_session_test.move +269 -0
  328. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/session_test.move +624 -0
  329. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/storage_test.move +700 -0
  330. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/typed_object_test.move +177 -0
  331. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/typed_scene_test.move +452 -0
  332. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/user_storage_test.move +160 -0
  333. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/utils/math.move +4 -3
  334. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/utils/type_info.move +2 -2
  335. package/templates/101/sui-template/packages/contracts/src/counter/Move.lock +0 -41
  336. package/templates/101/sui-template/packages/contracts/src/counter/Published.toml +0 -9
  337. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/errors.move +0 -12
  338. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/errors.move +0 -140
  339. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_config.move +0 -186
  340. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_state.move +0 -306
  341. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_metadata.move +0 -396
  342. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dubhe_config.move +0 -246
  343. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/dapp_store.move +0 -29
  344. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/session_system.move +0 -44
  345. package/templates/contract/sui-template/src/dubhe/sources/codegen/errors.move +0 -140
  346. package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dapp_fee_config.move +0 -186
  347. package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dapp_fee_state.move +0 -306
  348. package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dapp_metadata.move +0 -396
  349. package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dubhe_config.move +0 -246
  350. package/templates/contract/sui-template/src/dubhe/sources/core/dapp_store.move +0 -29
  351. package/templates/contract/sui-template/src/dubhe/sources/systems/session_system.move +0 -44
  352. package/templates/nextjs/sui-template/packages/contracts/src/counter/Move.lock +0 -47
  353. package/templates/nextjs/sui-template/packages/contracts/src/counter/Published.toml +0 -9
  354. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/errors.move +0 -12
  355. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/errors.move +0 -140
  356. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_config.move +0 -186
  357. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_state.move +0 -306
  358. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_metadata.move +0 -396
  359. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dubhe_config.move +0 -246
  360. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/dapp_store.move +0 -29
  361. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/session_system.move +0 -44
@@ -0,0 +1,624 @@
1
+ /// Unit tests — Session key management
2
+ ///
3
+ /// Covers activate_session, deactivate_session, is_write_authorized, and dapp_key_mismatch:
4
+ ///
5
+ /// activate_session:
6
+ /// happy path (sets key + expiry)
7
+ /// overwrites an active session (device switch / key loss without deactivate)
8
+ /// overwrites an expired session (direct renewal, no deactivate needed)
9
+ /// aborts: non-canonical-owner caller
10
+ /// aborts: session_wallet == @0x0
11
+ /// aborts: session_wallet == canonical_owner (self-proxy)
12
+ /// aborts: duration below MIN_SESSION_DURATION_MS
13
+ /// aborts: duration above MAX_SESSION_DURATION_MS
14
+ /// boundary: exactly MIN_SESSION_DURATION_MS succeeds
15
+ /// boundary: exactly MAX_SESSION_DURATION_MS succeeds
16
+ ///
17
+ /// deactivate_session:
18
+ /// canonical owner deactivates an active session
19
+ /// session key deactivates itself
20
+ /// anyone cleans up after natural expiry
21
+ /// aborts: no active session (key == @0x0)
22
+ /// aborts: stranger tries to deactivate a still-active session
23
+ /// clears both session_key and session_expires_at to zero
24
+ ///
25
+ /// is_write_authorized:
26
+ /// canonical owner is always authorized (no session, active session, expired session)
27
+ /// session key authorized when active (before expiry)
28
+ /// session key rejected at the exact expiry timestamp
29
+ /// session key rejected after expiry
30
+ /// stranger always rejected
31
+ /// @0x0 session key (no session) rejects non-canonical callers
32
+ #[test_only]
33
+ module dubhe::session_test;
34
+
35
+ use dubhe::dapp_service::{Self, UserStorage, DappHub};
36
+ use dubhe::dapp_system;
37
+ use sui::test_scenario;
38
+ use sui::clock;
39
+
40
+ public struct SessionTestKey has copy, drop {}
41
+ /// A distinct DApp key used only to trigger dapp_key_mismatch errors.
42
+ public struct SessionWrongKey has copy, drop {}
43
+
44
+ const OWNER: address = @0x1111;
45
+ const SESSION: address = @0x2222;
46
+ const OTHER: address = @0x3333;
47
+
48
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
49
+
50
+ fun new_us_for(owner: address, ctx: &mut TxContext): UserStorage {
51
+ dapp_service::create_user_storage_for_testing<SessionTestKey>(owner, ctx)
52
+ }
53
+
54
+ fun new_dh(ctx: &mut TxContext): DappHub {
55
+ dapp_system::create_dapp_hub_for_testing(ctx)
56
+ }
57
+
58
+ // ═══════════════════════════════════════════════════════════════════════════════
59
+ // activate_session — happy paths
60
+ // ═══════════════════════════════════════════════════════════════════════════════
61
+
62
+ #[test]
63
+ fun test_activate_sets_key_and_expiry() {
64
+ let mut scenario = test_scenario::begin(OWNER);
65
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
66
+ clock::set_for_testing(&mut clk, 1_000);
67
+ {
68
+ let ctx = test_scenario::ctx(&mut scenario);
69
+ let dh = new_dh(ctx);
70
+ let mut us = new_us_for(OWNER, ctx);
71
+
72
+ let duration = dapp_system::min_session_duration_ms();
73
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, duration, &clk, ctx);
74
+
75
+ assert!(dapp_service::session_key(&us) == SESSION);
76
+ assert!(dapp_service::session_expires_at(&us) == 1_000 + duration);
77
+
78
+ dapp_service::destroy_user_storage(us);
79
+ dapp_system::destroy_dapp_hub(dh);
80
+ };
81
+ clk.destroy_for_testing();
82
+ scenario.end();
83
+ }
84
+
85
+ #[test]
86
+ fun test_activate_overwrites_active_session() {
87
+ // Owner lost access to SESSION wallet and needs to replace it without deactivating.
88
+ let mut scenario = test_scenario::begin(OWNER);
89
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
90
+ clock::set_for_testing(&mut clk, 0);
91
+ {
92
+ let ctx = test_scenario::ctx(&mut scenario);
93
+ let dh = new_dh(ctx);
94
+ let mut us = new_us_for(OWNER, ctx);
95
+
96
+ // Activate first session.
97
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, dapp_system::min_session_duration_ms(), &clk, ctx);
98
+ assert!(dapp_service::session_key(&us) == SESSION);
99
+
100
+ // Overwrite with a new session key WITHOUT deactivating first.
101
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, OTHER, dapp_system::min_session_duration_ms(), &clk, ctx);
102
+ assert!(dapp_service::session_key(&us) == OTHER);
103
+
104
+ dapp_service::destroy_user_storage(us);
105
+ dapp_system::destroy_dapp_hub(dh);
106
+ };
107
+ clk.destroy_for_testing();
108
+ scenario.end();
109
+ }
110
+
111
+ #[test]
112
+ fun test_activate_overwrites_expired_session() {
113
+ let mut scenario = test_scenario::begin(OWNER);
114
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
115
+ let min = dapp_system::min_session_duration_ms();
116
+ clock::set_for_testing(&mut clk, 0);
117
+ {
118
+ let ctx = test_scenario::ctx(&mut scenario);
119
+ let dh = new_dh(ctx);
120
+ let mut us = new_us_for(OWNER, ctx);
121
+
122
+ // Activate and let it expire naturally.
123
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, min, &clk, ctx);
124
+ clock::set_for_testing(&mut clk, min + 1);
125
+
126
+ // Renewal: activate new session directly without deactivate.
127
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, OTHER, min, &clk, ctx);
128
+ assert!(dapp_service::session_key(&us) == OTHER);
129
+ // New expiry is relative to the new clock value.
130
+ assert!(dapp_service::session_expires_at(&us) == (min + 1) + min);
131
+
132
+ dapp_service::destroy_user_storage(us);
133
+ dapp_system::destroy_dapp_hub(dh);
134
+ };
135
+ clk.destroy_for_testing();
136
+ scenario.end();
137
+ }
138
+
139
+ // ═══════════════════════════════════════════════════════════════════════════════
140
+ // activate_session — abort cases
141
+ // ═══════════════════════════════════════════════════════════════════════════════
142
+
143
+ #[test]
144
+ #[expected_failure]
145
+ fun test_activate_aborts_for_non_canonical_owner() {
146
+ let mut scenario = test_scenario::begin(OWNER);
147
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
148
+ clock::set_for_testing(&mut clk, 0);
149
+
150
+ let mut us = {
151
+ let ctx = test_scenario::ctx(&mut scenario);
152
+ new_us_for(OWNER, ctx)
153
+ };
154
+ let dh = {
155
+ let ctx = test_scenario::ctx(&mut scenario);
156
+ new_dh(ctx)
157
+ };
158
+
159
+ // OTHER is not the canonical owner — must abort.
160
+ test_scenario::next_tx(&mut scenario, OTHER);
161
+ {
162
+ let ctx = test_scenario::ctx(&mut scenario);
163
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, dapp_system::min_session_duration_ms(), &clk, ctx);
164
+ };
165
+
166
+ clk.destroy_for_testing();
167
+ dapp_service::destroy_user_storage(us);
168
+ dapp_system::destroy_dapp_hub(dh);
169
+ scenario.end();
170
+ }
171
+
172
+ #[test]
173
+ #[expected_failure]
174
+ fun test_activate_aborts_for_zero_address() {
175
+ let mut scenario = test_scenario::begin(OWNER);
176
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
177
+ clock::set_for_testing(&mut clk, 0);
178
+ {
179
+ let ctx = test_scenario::ctx(&mut scenario);
180
+ let dh = new_dh(ctx);
181
+ let mut us = new_us_for(OWNER, ctx);
182
+ // @0x0 session key must abort with invalid_session_key.
183
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, @0x0, dapp_system::min_session_duration_ms(), &clk, ctx);
184
+ dapp_service::destroy_user_storage(us);
185
+ dapp_system::destroy_dapp_hub(dh);
186
+ };
187
+ clk.destroy_for_testing();
188
+ scenario.end();
189
+ }
190
+
191
+ #[test]
192
+ #[expected_failure]
193
+ fun test_activate_aborts_when_session_wallet_equals_owner() {
194
+ let mut scenario = test_scenario::begin(OWNER);
195
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
196
+ clock::set_for_testing(&mut clk, 0);
197
+ {
198
+ let ctx = test_scenario::ctx(&mut scenario);
199
+ let dh = new_dh(ctx);
200
+ let mut us = new_us_for(OWNER, ctx);
201
+ // canonical owner can't set themselves as the session key.
202
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, OWNER, dapp_system::min_session_duration_ms(), &clk, ctx);
203
+ dapp_service::destroy_user_storage(us);
204
+ dapp_system::destroy_dapp_hub(dh);
205
+ };
206
+ clk.destroy_for_testing();
207
+ scenario.end();
208
+ }
209
+
210
+ #[test]
211
+ #[expected_failure]
212
+ fun test_activate_aborts_duration_below_min() {
213
+ let mut scenario = test_scenario::begin(OWNER);
214
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
215
+ clock::set_for_testing(&mut clk, 0);
216
+ {
217
+ let ctx = test_scenario::ctx(&mut scenario);
218
+ let dh = new_dh(ctx);
219
+ let mut us = new_us_for(OWNER, ctx);
220
+ let too_short = dapp_system::min_session_duration_ms() - 1;
221
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, too_short, &clk, ctx);
222
+ dapp_service::destroy_user_storage(us);
223
+ dapp_system::destroy_dapp_hub(dh);
224
+ };
225
+ clk.destroy_for_testing();
226
+ scenario.end();
227
+ }
228
+
229
+ #[test]
230
+ #[expected_failure]
231
+ fun test_activate_aborts_duration_above_max() {
232
+ let mut scenario = test_scenario::begin(OWNER);
233
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
234
+ clock::set_for_testing(&mut clk, 0);
235
+ {
236
+ let ctx = test_scenario::ctx(&mut scenario);
237
+ let dh = new_dh(ctx);
238
+ let mut us = new_us_for(OWNER, ctx);
239
+ let too_long = dapp_system::max_session_duration_ms() + 1;
240
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, too_long, &clk, ctx);
241
+ dapp_service::destroy_user_storage(us);
242
+ dapp_system::destroy_dapp_hub(dh);
243
+ };
244
+ clk.destroy_for_testing();
245
+ scenario.end();
246
+ }
247
+
248
+ #[test]
249
+ fun test_activate_succeeds_at_exactly_min_duration() {
250
+ let mut scenario = test_scenario::begin(OWNER);
251
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
252
+ clock::set_for_testing(&mut clk, 0);
253
+ {
254
+ let ctx = test_scenario::ctx(&mut scenario);
255
+ let dh = new_dh(ctx);
256
+ let mut us = new_us_for(OWNER, ctx);
257
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, dapp_system::min_session_duration_ms(), &clk, ctx);
258
+ assert!(dapp_service::session_key(&us) == SESSION);
259
+ dapp_service::destroy_user_storage(us);
260
+ dapp_system::destroy_dapp_hub(dh);
261
+ };
262
+ clk.destroy_for_testing();
263
+ scenario.end();
264
+ }
265
+
266
+ #[test]
267
+ fun test_activate_succeeds_at_exactly_max_duration() {
268
+ let mut scenario = test_scenario::begin(OWNER);
269
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
270
+ clock::set_for_testing(&mut clk, 0);
271
+ {
272
+ let ctx = test_scenario::ctx(&mut scenario);
273
+ let dh = new_dh(ctx);
274
+ let mut us = new_us_for(OWNER, ctx);
275
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, dapp_system::max_session_duration_ms(), &clk, ctx);
276
+ assert!(dapp_service::session_key(&us) == SESSION);
277
+ dapp_service::destroy_user_storage(us);
278
+ dapp_system::destroy_dapp_hub(dh);
279
+ };
280
+ clk.destroy_for_testing();
281
+ scenario.end();
282
+ }
283
+
284
+ // ═══════════════════════════════════════════════════════════════════════════════
285
+ // deactivate_session — happy paths
286
+ // ═══════════════════════════════════════════════════════════════════════════════
287
+
288
+ #[test]
289
+ fun test_deactivate_by_canonical_owner_clears_session() {
290
+ let mut scenario = test_scenario::begin(OWNER);
291
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
292
+ clock::set_for_testing(&mut clk, 0);
293
+ {
294
+ let ctx = test_scenario::ctx(&mut scenario);
295
+ let dh = new_dh(ctx);
296
+ let mut us = new_us_for(OWNER, ctx);
297
+
298
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, dapp_system::min_session_duration_ms(), &clk, ctx);
299
+ assert!(dapp_service::session_key(&us) == SESSION);
300
+
301
+ dapp_system::deactivate_session<SessionTestKey>(&dh, &mut us, ctx);
302
+
303
+ assert!(dapp_service::session_key(&us) == @0x0);
304
+ assert!(dapp_service::session_expires_at(&us) == 0);
305
+
306
+ dapp_service::destroy_user_storage(us);
307
+ dapp_system::destroy_dapp_hub(dh);
308
+ };
309
+ clk.destroy_for_testing();
310
+ scenario.end();
311
+ }
312
+
313
+ #[test]
314
+ fun test_deactivate_by_session_key_itself() {
315
+ let mut scenario = test_scenario::begin(OWNER);
316
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
317
+ clock::set_for_testing(&mut clk, 0);
318
+
319
+ let mut us = {
320
+ let ctx = test_scenario::ctx(&mut scenario);
321
+ new_us_for(OWNER, ctx)
322
+ };
323
+ let dh = {
324
+ let ctx = test_scenario::ctx(&mut scenario);
325
+ new_dh(ctx)
326
+ };
327
+ {
328
+ let ctx = test_scenario::ctx(&mut scenario);
329
+ dapp_system::activate_session<SessionTestKey>(&dh, &mut us, SESSION, dapp_system::min_session_duration_ms(), &clk, ctx);
330
+ };
331
+
332
+ // SESSION key signs out itself.
333
+ test_scenario::next_tx(&mut scenario, SESSION);
334
+ {
335
+ let ctx = test_scenario::ctx(&mut scenario);
336
+ dapp_system::deactivate_session<SessionTestKey>(&dh, &mut us, ctx);
337
+ assert!(dapp_service::session_key(&us) == @0x0);
338
+ };
339
+
340
+ clk.destroy_for_testing();
341
+ dapp_service::destroy_user_storage(us);
342
+ dapp_system::destroy_dapp_hub(dh);
343
+ scenario.end();
344
+ }
345
+
346
+ // NOTE: deactivate_session() uses ctx.epoch_timestamp_ms() which stays at 0 in
347
+ // test_scenario and cannot be advanced without real epoch progression.
348
+ // The "expired session can be cleaned up by anyone" path is tested below via
349
+ // dapp_system::deactivate_session_with_now_ms_for_testing, which exercises the
350
+ // same permission logic with an explicit now_ms parameter.
351
+
352
+ #[test]
353
+ fun test_zero_session_key_means_no_active_session() {
354
+ // When session_key == @0x0, no session exists regardless of expires_at.
355
+ // is_write_authorized returns false for any non-owner sender.
356
+ let mut scenario = test_scenario::begin(OWNER);
357
+ {
358
+ let ctx = test_scenario::ctx(&mut scenario);
359
+ let us = new_us_for(OWNER, ctx);
360
+ // Default state: session_key = @0x0, expires_at = 0.
361
+ assert!(!dapp_service::is_write_authorized(&us, SESSION, 0));
362
+ assert!(!dapp_service::is_write_authorized(&us, SESSION, 999_999));
363
+ dapp_service::destroy_user_storage(us);
364
+ };
365
+ scenario.end();
366
+ }
367
+
368
+
369
+ // ─── deactivate_session: expired-session cleanup by any sender ────────────────
370
+
371
+ /// Any address may clean up a session after it has expired.
372
+ /// In production this is gated on ctx.epoch_timestamp_ms() >= session_expires_at;
373
+ /// here we use the test helper that accepts an explicit now_ms.
374
+ #[test]
375
+ fun test_deactivate_expired_session_by_stranger_succeeds() {
376
+ let mut scenario = test_scenario::begin(OWNER);
377
+ {
378
+ let ctx = test_scenario::ctx(&mut scenario);
379
+ let mut us = new_us_for(OWNER, ctx);
380
+ // Plant a session with expires_at = 1 ms.
381
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, 1);
382
+
383
+ // Stranger calls at now_ms = 1000 — session is expired → allowed.
384
+ dapp_system::deactivate_session_with_now_ms_for_testing<SessionTestKey>(&mut us, OTHER, 1000);
385
+
386
+ assert!(dapp_service::session_key(&us) == @0x0);
387
+ assert!(dapp_service::session_expires_at(&us) == 0);
388
+
389
+ dapp_service::destroy_user_storage(us);
390
+ };
391
+ scenario.end();
392
+ }
393
+
394
+ /// A stranger must NOT deactivate a session that is still active (not yet expired).
395
+ #[test]
396
+ #[expected_failure]
397
+ fun test_deactivate_non_expired_session_by_stranger_aborts() {
398
+ let mut scenario = test_scenario::begin(OWNER);
399
+ {
400
+ let ctx = test_scenario::ctx(&mut scenario);
401
+ let mut us = new_us_for(OWNER, ctx);
402
+ // Session that expires far in the future.
403
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, 9_999_999);
404
+
405
+ // now_ms = 0 < 9_999_999 → not expired → stranger must abort.
406
+ dapp_system::deactivate_session_with_now_ms_for_testing<SessionTestKey>(&mut us, OTHER, 0);
407
+
408
+ dapp_service::destroy_user_storage(us);
409
+ };
410
+ scenario.end();
411
+ }
412
+
413
+ // ═══════════════════════════════════════════════════════════════════════════════
414
+ // deactivate_session — abort cases
415
+ // ═══════════════════════════════════════════════════════════════════════════════
416
+
417
+ #[test]
418
+ #[expected_failure]
419
+ fun test_deactivate_aborts_when_no_active_session() {
420
+ let mut scenario = test_scenario::begin(OWNER);
421
+ {
422
+ let ctx = test_scenario::ctx(&mut scenario);
423
+ let dh = new_dh(ctx);
424
+ let mut us = new_us_for(OWNER, ctx);
425
+ // No session — must abort with no_active_session.
426
+ dapp_system::deactivate_session<SessionTestKey>(&dh, &mut us, ctx);
427
+ dapp_service::destroy_user_storage(us);
428
+ dapp_system::destroy_dapp_hub(dh);
429
+ };
430
+ scenario.end();
431
+ }
432
+
433
+ #[test]
434
+ #[expected_failure]
435
+ fun test_deactivate_aborts_for_stranger_with_active_session() {
436
+ let min = dapp_system::min_session_duration_ms();
437
+ let mut scenario = test_scenario::begin(OWNER);
438
+
439
+ let mut us = {
440
+ let ctx = test_scenario::ctx(&mut scenario);
441
+ new_us_for(OWNER, ctx)
442
+ };
443
+ let dh = {
444
+ let ctx = test_scenario::ctx(&mut scenario);
445
+ new_dh(ctx)
446
+ };
447
+ // Active session with far-future expiry (epoch_timestamp_ms stays near 0 in tests).
448
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, min * 1000);
449
+
450
+ // OTHER is not owner, not SESSION key, and session is not expired → must abort.
451
+ test_scenario::next_tx(&mut scenario, OTHER);
452
+ {
453
+ let ctx = test_scenario::ctx(&mut scenario);
454
+ dapp_system::deactivate_session<SessionTestKey>(&dh, &mut us, ctx);
455
+ };
456
+
457
+ dapp_service::destroy_user_storage(us);
458
+ dapp_system::destroy_dapp_hub(dh);
459
+ scenario.end();
460
+ }
461
+
462
+ // ═══════════════════════════════════════════════════════════════════════════════
463
+ // is_write_authorized
464
+ // ═══════════════════════════════════════════════════════════════════════════════
465
+
466
+ #[test]
467
+ fun test_canonical_owner_always_authorized_with_no_session() {
468
+ let mut scenario = test_scenario::begin(OWNER);
469
+ {
470
+ let ctx = test_scenario::ctx(&mut scenario);
471
+ let us = dapp_service::create_user_storage_for_testing<SessionTestKey>(OWNER, ctx);
472
+ assert!(dapp_service::is_write_authorized(&us, OWNER, 0));
473
+ assert!(dapp_service::is_write_authorized(&us, OWNER, 999_999_999));
474
+ dapp_service::destroy_user_storage(us);
475
+ };
476
+ scenario.end();
477
+ }
478
+
479
+ #[test]
480
+ fun test_canonical_owner_authorized_while_session_active() {
481
+ let min = dapp_system::min_session_duration_ms();
482
+ let mut scenario = test_scenario::begin(OWNER);
483
+ {
484
+ let ctx = test_scenario::ctx(&mut scenario);
485
+ let mut us = dapp_service::create_user_storage_for_testing<SessionTestKey>(OWNER, ctx);
486
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, min * 100);
487
+ assert!(dapp_service::is_write_authorized(&us, OWNER, 0));
488
+ dapp_service::destroy_user_storage(us);
489
+ };
490
+ scenario.end();
491
+ }
492
+
493
+ #[test]
494
+ fun test_canonical_owner_authorized_after_session_expires() {
495
+ let mut scenario = test_scenario::begin(OWNER);
496
+ {
497
+ let ctx = test_scenario::ctx(&mut scenario);
498
+ let mut us = dapp_service::create_user_storage_for_testing<SessionTestKey>(OWNER, ctx);
499
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, 100);
500
+ // At now_ms = 200, session is expired — but owner is still fine.
501
+ assert!(dapp_service::is_write_authorized(&us, OWNER, 200));
502
+ dapp_service::destroy_user_storage(us);
503
+ };
504
+ scenario.end();
505
+ }
506
+
507
+ #[test]
508
+ fun test_session_key_authorized_before_expiry() {
509
+ let min = dapp_system::min_session_duration_ms();
510
+ let mut scenario = test_scenario::begin(OWNER);
511
+ {
512
+ let ctx = test_scenario::ctx(&mut scenario);
513
+ let mut us = dapp_service::create_user_storage_for_testing<SessionTestKey>(OWNER, ctx);
514
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, min);
515
+ // At now_ms = 0, session is active.
516
+ assert!(dapp_service::is_write_authorized(&us, SESSION, 0));
517
+ // At now_ms = min - 1, session is still active.
518
+ assert!(dapp_service::is_write_authorized(&us, SESSION, min - 1));
519
+ dapp_service::destroy_user_storage(us);
520
+ };
521
+ scenario.end();
522
+ }
523
+
524
+ #[test]
525
+ fun test_session_key_rejected_at_exact_expiry_timestamp() {
526
+ let mut scenario = test_scenario::begin(OWNER);
527
+ {
528
+ let ctx = test_scenario::ctx(&mut scenario);
529
+ let mut us = dapp_service::create_user_storage_for_testing<SessionTestKey>(OWNER, ctx);
530
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, 100);
531
+ // At now_ms == expires_at → expired (>= check).
532
+ assert!(!dapp_service::is_write_authorized(&us, SESSION, 100));
533
+ dapp_service::destroy_user_storage(us);
534
+ };
535
+ scenario.end();
536
+ }
537
+
538
+ #[test]
539
+ fun test_session_key_rejected_after_expiry() {
540
+ let mut scenario = test_scenario::begin(OWNER);
541
+ {
542
+ let ctx = test_scenario::ctx(&mut scenario);
543
+ let mut us = dapp_service::create_user_storage_for_testing<SessionTestKey>(OWNER, ctx);
544
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, 100);
545
+ assert!(!dapp_service::is_write_authorized(&us, SESSION, 200));
546
+ dapp_service::destroy_user_storage(us);
547
+ };
548
+ scenario.end();
549
+ }
550
+
551
+ #[test]
552
+ fun test_stranger_always_rejected() {
553
+ let min = dapp_system::min_session_duration_ms();
554
+ let mut scenario = test_scenario::begin(OWNER);
555
+ {
556
+ let ctx = test_scenario::ctx(&mut scenario);
557
+ let mut us = dapp_service::create_user_storage_for_testing<SessionTestKey>(OWNER, ctx);
558
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, min * 100);
559
+ // Even with an active session key, OTHER is never authorized.
560
+ assert!(!dapp_service::is_write_authorized(&us, OTHER, 0));
561
+ dapp_service::destroy_user_storage(us);
562
+ };
563
+ scenario.end();
564
+ }
565
+
566
+ #[test]
567
+ fun test_no_session_key_rejects_non_owner() {
568
+ let mut scenario = test_scenario::begin(OWNER);
569
+ {
570
+ let ctx = test_scenario::ctx(&mut scenario);
571
+ let us = dapp_service::create_user_storage_for_testing<SessionTestKey>(OWNER, ctx);
572
+ // session_key == @0x0 → non-owner is never authorized.
573
+ assert!(!dapp_service::is_write_authorized(&us, SESSION, 0));
574
+ assert!(!dapp_service::is_write_authorized(&us, OTHER, 0));
575
+ dapp_service::destroy_user_storage(us);
576
+ };
577
+ scenario.end();
578
+ }
579
+
580
+ // ═══════════════════════════════════════════════════════════════════════════════
581
+ // dapp_key_mismatch — activate_session and deactivate_session
582
+ // ═══════════════════════════════════════════════════════════════════════════════
583
+
584
+ /// activate_session must abort when the UserStorage belongs to a different DApp.
585
+ #[test]
586
+ #[expected_failure]
587
+ fun test_activate_session_aborts_on_dapp_key_mismatch() {
588
+ let mut scenario = test_scenario::begin(OWNER);
589
+ let mut clk = clock::create_for_testing(test_scenario::ctx(&mut scenario));
590
+ clock::set_for_testing(&mut clk, 0);
591
+ {
592
+ let ctx = test_scenario::ctx(&mut scenario);
593
+ let dh = new_dh(ctx);
594
+ // UserStorage keyed to SessionWrongKey.
595
+ let mut us = dapp_service::create_user_storage_for_testing<SessionWrongKey>(OWNER, ctx);
596
+ // activate_session<SessionTestKey> on a SessionWrongKey storage — must abort.
597
+ dapp_system::activate_session<SessionTestKey>(
598
+ &dh, &mut us, SESSION, dapp_system::min_session_duration_ms(), &clk, ctx
599
+ );
600
+ dapp_service::destroy_user_storage(us);
601
+ dapp_system::destroy_dapp_hub(dh);
602
+ };
603
+ clk.destroy_for_testing();
604
+ scenario.end();
605
+ }
606
+
607
+ /// deactivate_session must abort when the UserStorage belongs to a different DApp.
608
+ #[test]
609
+ #[expected_failure]
610
+ fun test_deactivate_session_aborts_on_dapp_key_mismatch() {
611
+ let mut scenario = test_scenario::begin(OWNER);
612
+ {
613
+ let ctx = test_scenario::ctx(&mut scenario);
614
+ let dh = new_dh(ctx);
615
+ // UserStorage keyed to SessionWrongKey, with an active session set directly.
616
+ let mut us = dapp_service::create_user_storage_for_testing<SessionWrongKey>(OWNER, ctx);
617
+ dapp_service::set_session_key_for_testing(&mut us, SESSION, 999_999_999);
618
+ // deactivate_session<SessionTestKey> on a SessionWrongKey storage — must abort.
619
+ dapp_system::deactivate_session<SessionTestKey>(&dh, &mut us, ctx);
620
+ dapp_service::destroy_user_storage(us);
621
+ dapp_system::destroy_dapp_hub(dh);
622
+ };
623
+ scenario.end();
624
+ }