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,656 @@
1
+ /// Boundary + full-flow tests for player registration, deck management and
2
+ /// the 1v1 duel lifecycle (invite → accept → reactive combat → settlement).
3
+ ///
4
+ /// Economy facts (deploy_hook defaults):
5
+ /// starting_gold=500 pack_price=100 rake_bps=300 (3%) max_hp=30
6
+ /// turn_timeout_ms=300_000 (5 min)
7
+ /// Starter deck (in order): Strike(12) Strike(12) Strike(12) Fireball(18) Shield(8)
8
+ #[test_only]
9
+ module card_duel::duel_tests {
10
+ use sui::clock;
11
+ use sui::test_scenario;
12
+ use dubhe::dapp_service::{ScenePermit, SceneStorage, ObjectStorage};
13
+ use card_duel::test_helpers;
14
+ use card_duel::init_test;
15
+ use card_duel::player_system;
16
+ use card_duel::card_system;
17
+ use card_duel::duel_system;
18
+ use card_duel::gold;
19
+ use card_duel::profile;
20
+ use card_duel::deck;
21
+ use card_duel::card;
22
+ use card_duel::battle_state;
23
+ use card_duel::duel::{Self, Duel};
24
+ use card_duel::duel_permit::DuelPermit;
25
+ use card_duel::arena::{Self, Arena};
26
+
27
+ const A: address = @0xA11CE;
28
+ const B: address = @0xB0B;
29
+ const C: address = @0xCA01;
30
+
31
+ const STAKE: u64 = 100;
32
+ const STARTING_GOLD: u64 = 500;
33
+ const MAX_HP: u64 = 30;
34
+ const TURN_TIMEOUT_MS: u64 = 5 * 60 * 1000;
35
+
36
+ // ─── Registration ───────────────────────────────────────────────────────
37
+
38
+ #[test]
39
+ fun test_register_grants_gold_deck_profile() {
40
+ let (mut sc, ds) = test_helpers::setup();
41
+ let us = test_helpers::new_player(&mut sc, &ds, A);
42
+
43
+ assert!(gold::get(&us) == STARTING_GOLD, 0);
44
+ let (wins, losses, rating) = profile::get(&us);
45
+ assert!(wins == 0 && losses == 0 && rating == 1200, 1);
46
+ assert!(battle_state::get_match_id(&us) == @0x0, 2);
47
+
48
+ let deck_ids = deck::get(&us);
49
+ assert!(deck_ids.length() == 5, 3);
50
+ // Every deck card must be owned.
51
+ let mut i = 0;
52
+ while (i < 5) {
53
+ assert!(card::has(&us, *deck_ids.borrow(i)), 4);
54
+ i = i + 1;
55
+ };
56
+ // Starter composition: Strike Strike Strike Fireball Shield
57
+ assert!(card::get_kind(&us, *deck_ids.borrow(0)) == 1, 5);
58
+ assert!(card::get_kind(&us, *deck_ids.borrow(3)) == 2, 6);
59
+ assert!(card::get_kind(&us, *deck_ids.borrow(4)) == 4, 7);
60
+ assert!(card::get_power(&us, *deck_ids.borrow(0)) == 12, 8);
61
+ assert!(card::get_power(&us, *deck_ids.borrow(3)) == 18, 9);
62
+
63
+ std::unit_test::destroy(ds);
64
+ std::unit_test::destroy(us);
65
+ sc.end();
66
+ }
67
+
68
+ #[test]
69
+ #[expected_failure]
70
+ fun test_register_twice_fails() {
71
+ let (mut sc, ds) = test_helpers::setup();
72
+ let mut us = test_helpers::new_player(&mut sc, &ds, A);
73
+
74
+ player_system::register(&ds, &mut us, sc.ctx());
75
+
76
+ std::unit_test::destroy(ds);
77
+ std::unit_test::destroy(us);
78
+ sc.end();
79
+ }
80
+
81
+ #[test]
82
+ #[expected_failure]
83
+ fun test_set_deck_fails_wrong_size() {
84
+ let (mut sc, ds) = test_helpers::setup();
85
+ let mut us = test_helpers::new_player(&mut sc, &ds, A);
86
+
87
+ let deck_ids = deck::get(&us);
88
+ let four = vector[
89
+ *deck_ids.borrow(0), *deck_ids.borrow(1), *deck_ids.borrow(2), *deck_ids.borrow(3),
90
+ ];
91
+ card_system::set_deck(&ds, &mut us, four, sc.ctx());
92
+
93
+ std::unit_test::destroy(ds);
94
+ std::unit_test::destroy(us);
95
+ sc.end();
96
+ }
97
+
98
+ #[test]
99
+ #[expected_failure]
100
+ fun test_set_deck_fails_duplicate_card() {
101
+ let (mut sc, ds) = test_helpers::setup();
102
+ let mut us = test_helpers::new_player(&mut sc, &ds, A);
103
+
104
+ let deck_ids = deck::get(&us);
105
+ let first = *deck_ids.borrow(0);
106
+ let dup = vector[
107
+ first, first, *deck_ids.borrow(2), *deck_ids.borrow(3), *deck_ids.borrow(4),
108
+ ];
109
+ card_system::set_deck(&ds, &mut us, dup, sc.ctx());
110
+
111
+ std::unit_test::destroy(ds);
112
+ std::unit_test::destroy(us);
113
+ sc.end();
114
+ }
115
+
116
+ // ─── Duel: full happy path ──────────────────────────────────────────────
117
+
118
+ /// invite → accept → 5 turns of combat → KO → settlement with arena rake.
119
+ #[test]
120
+ fun test_duel_full_flow_with_knockout_and_settlement() {
121
+ let (mut sc, ds) = test_helpers::setup();
122
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
123
+ let mut us_b = test_helpers::new_player(&mut sc, &ds, B);
124
+ let deck_a = deck::get(&us_a);
125
+ let deck_b = deck::get(&us_b);
126
+
127
+ // A invites B with a 100 gold stake.
128
+ sc.next_tx(A);
129
+ let mut clk = clock::create_for_testing(sc.ctx());
130
+ clk.set_for_testing(1_000);
131
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
132
+ assert!(gold::get(&us_a) == STARTING_GOLD - STAKE, 0);
133
+ assert!(battle_state::get_match_id(&us_a) != @0x0, 1);
134
+ assert!(battle_state::get_hp(&us_a) == MAX_HP, 2);
135
+
136
+ // B accepts and matches the stake. Pot is escrowed in the scene bag.
137
+ sc.next_tx(B);
138
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
139
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
140
+ duel_system::accept_duel(&ds, &mut us_b, &mut permit, &mut scene, &clk, sc.ctx());
141
+ assert!(gold::get(&us_b) == STARTING_GOLD - STAKE, 3);
142
+ assert!(duel::get_gold(&scene) == 2 * STAKE, 4);
143
+ assert!(duel::get_state(&scene) == 1, 5);
144
+ assert!(duel::get_turn_addr(&scene) == A, 6);
145
+
146
+ // Turn 1 — A strikes (12): B 30 → 18 (reactive cross-user write).
147
+ sc.next_tx(A);
148
+ duel_system::attack(&ds, &mut us_a, &mut us_b, &permit, &mut scene, *deck_a.borrow(0), &clk, sc.ctx());
149
+ assert!(battle_state::get_hp(&us_b) == 18, 7);
150
+ assert!(duel::get_turn_addr(&scene) == B, 8);
151
+
152
+ // Turn 2 — B shields (+8).
153
+ sc.next_tx(B);
154
+ duel_system::defend(&ds, &mut us_b, &permit, &mut scene, *deck_b.borrow(4), &clk, sc.ctx());
155
+ assert!(battle_state::get_shield(&us_b) == 8, 9);
156
+
157
+ // Turn 3 — A strikes (12): shield absorbs 8, pierce 4 → B 18 → 14.
158
+ sc.next_tx(A);
159
+ duel_system::attack(&ds, &mut us_a, &mut us_b, &permit, &mut scene, *deck_a.borrow(1), &clk, sc.ctx());
160
+ assert!(battle_state::get_hp(&us_b) == 14, 10);
161
+ assert!(battle_state::get_shield(&us_b) == 0, 11);
162
+
163
+ // Turn 4 — B strikes (12): A 30 → 18.
164
+ sc.next_tx(B);
165
+ duel_system::attack(&ds, &mut us_b, &mut us_a, &permit, &mut scene, *deck_b.borrow(0), &clk, sc.ctx());
166
+ assert!(battle_state::get_hp(&us_a) == 18, 12);
167
+
168
+ // Turn 5 — A fireballs (18 ≥ 14): knockout. Match decided on the spot.
169
+ sc.next_tx(A);
170
+ duel_system::attack(&ds, &mut us_a, &mut us_b, &permit, &mut scene, *deck_a.borrow(3), &clk, sc.ctx());
171
+ assert!(duel::get_state(&scene) == 2, 13);
172
+ assert!(duel::get_winner(&scene) == A, 14);
173
+ // Loser settled reactively: battle reset + loss recorded.
174
+ assert!(battle_state::get_match_id(&us_b) == @0x0, 15);
175
+ let (_, b_losses, b_rating) = profile::get(&us_b);
176
+ assert!(b_losses == 1 && b_rating == 1175, 16);
177
+
178
+ // Settlement: pot 200, rake 3% = 6 → arena; 194 → winner.
179
+ sc.next_tx(A);
180
+ let mut arena_obj = test_scenario::take_shared<ObjectStorage<Arena>>(&sc);
181
+ duel_system::finish_duel(&ds, &mut us_a, &mut permit, &mut scene, &mut arena_obj, sc.ctx());
182
+ assert!(arena::get_gold(&arena_obj) == 6, 17);
183
+ assert!(gold::get(&us_a) == STARTING_GOLD - STAKE + 194, 18);
184
+ let (a_wins, _, a_rating) = profile::get(&us_a);
185
+ assert!(a_wins == 1 && a_rating == 1225, 19);
186
+ assert!(battle_state::get_match_id(&us_a) == @0x0, 20);
187
+ assert!(duel::get_gold(&scene) == 0, 21);
188
+
189
+ // Loser exits the permit, then anyone can destroy the empty scene+permit.
190
+ sc.next_tx(B);
191
+ duel_system::leave_duel(&mut permit, &scene, &us_b, sc.ctx());
192
+ sc.next_tx(C);
193
+ duel_system::cleanup_duel(scene, permit, sc.ctx());
194
+
195
+ test_scenario::return_shared(arena_obj);
196
+ clk.destroy_for_testing();
197
+ std::unit_test::destroy(ds);
198
+ std::unit_test::destroy(us_a);
199
+ std::unit_test::destroy(us_b);
200
+ sc.end();
201
+ }
202
+
203
+ // ─── Duel: session key delegation ───────────────────────────────────────
204
+
205
+ /// A session key signs every action for player A; the on-chain identity
206
+ /// (challenger, turn order, winner, permit participant) must always
207
+ /// resolve to the canonical owner A, never to the session address.
208
+ #[test]
209
+ fun test_duel_session_key_plays_for_canonical_owner() {
210
+ let a_session: address = @0x5E55;
211
+ let (mut sc, ds) = test_helpers::setup();
212
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
213
+ let mut us_b = test_helpers::new_player(&mut sc, &ds, B);
214
+ let deck_a = deck::get(&us_a);
215
+ let deck_b = deck::get(&us_b);
216
+
217
+ // Bind an active session key to A's storage (test-only shortcut for
218
+ // player_system-level activate_session).
219
+ dubhe::dapp_service::set_session_key_for_testing(&mut us_a, a_session, 999_999_999_999);
220
+
221
+ // Session-signed duel creation: challenger must register as A.
222
+ sc.next_tx(a_session);
223
+ let mut clk = clock::create_for_testing(sc.ctx());
224
+ clk.set_for_testing(1_000);
225
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
226
+
227
+ sc.next_tx(B);
228
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
229
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
230
+ assert!(duel::get_challenger(&scene) == A, 0);
231
+ duel_system::accept_duel(&ds, &mut us_b, &mut permit, &mut scene, &clk, sc.ctx());
232
+ // The turn belongs to A (the canonical owner), not the session key.
233
+ assert!(duel::get_turn_addr(&scene) == A, 1);
234
+
235
+ // Session-signed fireball (18): B 30 → 12.
236
+ sc.next_tx(a_session);
237
+ duel_system::attack(&ds, &mut us_a, &mut us_b, &permit, &mut scene, *deck_a.borrow(3), &clk, sc.ctx());
238
+ assert!(battle_state::get_hp(&us_b) == 12, 2);
239
+ assert!(duel::get_turn_addr(&scene) == B, 3);
240
+
241
+ // B responds from the main wallet: A 30 → 18.
242
+ sc.next_tx(B);
243
+ duel_system::attack(&ds, &mut us_b, &mut us_a, &permit, &mut scene, *deck_b.borrow(0), &clk, sc.ctx());
244
+
245
+ // Session-signed strike (12 ≥ 12): knockout — winner is A.
246
+ sc.next_tx(a_session);
247
+ duel_system::attack(&ds, &mut us_a, &mut us_b, &permit, &mut scene, *deck_a.borrow(0), &clk, sc.ctx());
248
+ assert!(duel::get_state(&scene) == 2, 4);
249
+ assert!(duel::get_winner(&scene) == A, 5);
250
+
251
+ // Session-signed settlement: the win lands on A's profile.
252
+ sc.next_tx(a_session);
253
+ let mut arena_obj = test_scenario::take_shared<ObjectStorage<Arena>>(&sc);
254
+ duel_system::finish_duel(&ds, &mut us_a, &mut permit, &mut scene, &mut arena_obj, sc.ctx());
255
+ let (a_wins, _, _) = profile::get(&us_a);
256
+ assert!(a_wins == 1, 6);
257
+
258
+ sc.next_tx(B);
259
+ duel_system::leave_duel(&mut permit, &scene, &us_b, sc.ctx());
260
+ sc.next_tx(C);
261
+ duel_system::cleanup_duel(scene, permit, sc.ctx());
262
+
263
+ test_scenario::return_shared(arena_obj);
264
+ clk.destroy_for_testing();
265
+ std::unit_test::destroy(ds);
266
+ std::unit_test::destroy(us_a);
267
+ std::unit_test::destroy(us_b);
268
+ sc.end();
269
+ }
270
+
271
+ /// A stranger (neither the canonical owner nor the session key of us_a)
272
+ /// must not be able to open a duel on A's behalf.
273
+ #[test]
274
+ #[expected_failure]
275
+ fun test_create_duel_fails_for_unauthorized_signer() {
276
+ let (mut sc, ds) = test_helpers::setup();
277
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
278
+
279
+ sc.next_tx(C);
280
+ let clk = clock::create_for_testing(sc.ctx());
281
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
282
+
283
+ clk.destroy_for_testing();
284
+ std::unit_test::destroy(ds);
285
+ std::unit_test::destroy(us_a);
286
+ sc.end();
287
+ }
288
+
289
+ // ─── Duel: cancel / surrender / timeout ─────────────────────────────────
290
+
291
+ #[test]
292
+ fun test_cancel_duel_refunds_stake() {
293
+ let (mut sc, ds) = test_helpers::setup();
294
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
295
+
296
+ sc.next_tx(A);
297
+ let mut clk = clock::create_for_testing(sc.ctx());
298
+ clk.set_for_testing(1_000);
299
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
300
+
301
+ sc.next_tx(A);
302
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
303
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
304
+ duel_system::cancel_duel(&ds, &mut us_a, &mut permit, &mut scene, sc.ctx());
305
+
306
+ assert!(gold::get(&us_a) == STARTING_GOLD, 0);
307
+ assert!(battle_state::get_match_id(&us_a) == @0x0, 1);
308
+ assert!(duel::get_state(&scene) == 2, 2);
309
+
310
+ sc.next_tx(A);
311
+ duel_system::cleanup_duel(scene, permit, sc.ctx());
312
+
313
+ clk.destroy_for_testing();
314
+ std::unit_test::destroy(ds);
315
+ std::unit_test::destroy(us_a);
316
+ sc.end();
317
+ }
318
+
319
+ #[test]
320
+ fun test_surrender_lets_opponent_collect_pot() {
321
+ let (mut sc, ds) = test_helpers::setup();
322
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
323
+ let mut us_b = test_helpers::new_player(&mut sc, &ds, B);
324
+
325
+ sc.next_tx(A);
326
+ let mut clk = clock::create_for_testing(sc.ctx());
327
+ clk.set_for_testing(1_000);
328
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
329
+
330
+ sc.next_tx(B);
331
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
332
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
333
+ duel_system::accept_duel(&ds, &mut us_b, &mut permit, &mut scene, &clk, sc.ctx());
334
+
335
+ // B surrenders without playing a card.
336
+ sc.next_tx(B);
337
+ duel_system::surrender(&ds, &mut us_b, &mut permit, &mut scene, sc.ctx());
338
+ assert!(duel::get_state(&scene) == 2, 0);
339
+ assert!(duel::get_winner(&scene) == A, 1);
340
+ let (_, b_losses, _) = profile::get(&us_b);
341
+ assert!(b_losses == 1, 2);
342
+
343
+ sc.next_tx(A);
344
+ let mut arena_obj = test_scenario::take_shared<ObjectStorage<Arena>>(&sc);
345
+ duel_system::finish_duel(&ds, &mut us_a, &mut permit, &mut scene, &mut arena_obj, sc.ctx());
346
+ assert!(gold::get(&us_a) == STARTING_GOLD - STAKE + 194, 3);
347
+
348
+ test_scenario::return_shared(scene);
349
+ test_scenario::return_shared(permit);
350
+ test_scenario::return_shared(arena_obj);
351
+ clk.destroy_for_testing();
352
+ std::unit_test::destroy(ds);
353
+ std::unit_test::destroy(us_a);
354
+ std::unit_test::destroy(us_b);
355
+ sc.end();
356
+ }
357
+
358
+ #[test]
359
+ fun test_claim_timeout_win_after_stall() {
360
+ let (mut sc, ds) = test_helpers::setup();
361
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
362
+ let mut us_b = test_helpers::new_player(&mut sc, &ds, B);
363
+
364
+ sc.next_tx(A);
365
+ let mut clk = clock::create_for_testing(sc.ctx());
366
+ clk.set_for_testing(1_000);
367
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
368
+
369
+ sc.next_tx(B);
370
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
371
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
372
+ duel_system::accept_duel(&ds, &mut us_b, &mut permit, &mut scene, &clk, sc.ctx());
373
+
374
+ // It is A's turn; A stalls past the timeout, so B claims the win.
375
+ let accepted_at = duel::get_last_action_ms(&scene);
376
+ clk.set_for_testing(accepted_at + TURN_TIMEOUT_MS + 1);
377
+ sc.next_tx(B);
378
+ duel_system::claim_timeout_win(
379
+ &ds, &mut us_b, &mut us_a, &permit, &mut scene, &clk, sc.ctx(),
380
+ );
381
+ assert!(duel::get_state(&scene) == 2, 0);
382
+ assert!(duel::get_winner(&scene) == B, 1);
383
+ // The stalling player is settled reactively.
384
+ assert!(battle_state::get_match_id(&us_a) == @0x0, 2);
385
+ let (_, a_losses, _) = profile::get(&us_a);
386
+ assert!(a_losses == 1, 3);
387
+
388
+ test_scenario::return_shared(scene);
389
+ test_scenario::return_shared(permit);
390
+ clk.destroy_for_testing();
391
+ std::unit_test::destroy(ds);
392
+ std::unit_test::destroy(us_a);
393
+ std::unit_test::destroy(us_b);
394
+ sc.end();
395
+ }
396
+
397
+ #[test]
398
+ #[expected_failure]
399
+ fun test_claim_timeout_win_fails_before_timeout() {
400
+ let (mut sc, ds) = test_helpers::setup();
401
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
402
+ let mut us_b = test_helpers::new_player(&mut sc, &ds, B);
403
+
404
+ sc.next_tx(A);
405
+ let mut clk = clock::create_for_testing(sc.ctx());
406
+ clk.set_for_testing(1_000);
407
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
408
+
409
+ sc.next_tx(B);
410
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
411
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
412
+ duel_system::accept_duel(&ds, &mut us_b, &mut permit, &mut scene, &clk, sc.ctx());
413
+
414
+ // Only 1 ms has passed — claim must abort.
415
+ let accepted_at = duel::get_last_action_ms(&scene);
416
+ clk.set_for_testing(accepted_at + 1);
417
+ sc.next_tx(B);
418
+ duel_system::claim_timeout_win(
419
+ &ds, &mut us_b, &mut us_a, &permit, &mut scene, &clk, sc.ctx(),
420
+ );
421
+
422
+ test_scenario::return_shared(scene);
423
+ test_scenario::return_shared(permit);
424
+ clk.destroy_for_testing();
425
+ std::unit_test::destroy(ds);
426
+ std::unit_test::destroy(us_a);
427
+ std::unit_test::destroy(us_b);
428
+ sc.end();
429
+ }
430
+
431
+ // ─── Duel: failure boundaries ───────────────────────────────────────────
432
+
433
+ #[test]
434
+ #[expected_failure]
435
+ fun test_create_duel_fails_against_self() {
436
+ let (mut sc, ds) = test_helpers::setup();
437
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
438
+
439
+ sc.next_tx(A);
440
+ let clk = clock::create_for_testing(sc.ctx());
441
+ duel_system::create_duel(&ds, &mut us_a, A, STAKE, &clk, sc.ctx());
442
+
443
+ clk.destroy_for_testing();
444
+ std::unit_test::destroy(ds);
445
+ std::unit_test::destroy(us_a);
446
+ sc.end();
447
+ }
448
+
449
+ #[test]
450
+ #[expected_failure]
451
+ fun test_create_duel_fails_zero_stake() {
452
+ let (mut sc, ds) = test_helpers::setup();
453
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
454
+
455
+ sc.next_tx(A);
456
+ let clk = clock::create_for_testing(sc.ctx());
457
+ duel_system::create_duel(&ds, &mut us_a, B, 0, &clk, sc.ctx());
458
+
459
+ clk.destroy_for_testing();
460
+ std::unit_test::destroy(ds);
461
+ std::unit_test::destroy(us_a);
462
+ sc.end();
463
+ }
464
+
465
+ #[test]
466
+ #[expected_failure]
467
+ fun test_create_duel_fails_insufficient_gold() {
468
+ let (mut sc, ds) = test_helpers::setup();
469
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
470
+
471
+ sc.next_tx(A);
472
+ let clk = clock::create_for_testing(sc.ctx());
473
+ duel_system::create_duel(&ds, &mut us_a, B, STARTING_GOLD + 1, &clk, sc.ctx());
474
+
475
+ clk.destroy_for_testing();
476
+ std::unit_test::destroy(ds);
477
+ std::unit_test::destroy(us_a);
478
+ sc.end();
479
+ }
480
+
481
+ #[test]
482
+ #[expected_failure]
483
+ fun test_accept_duel_fails_for_uninvited_player() {
484
+ let (mut sc, ds) = test_helpers::setup();
485
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
486
+ let mut us_c = test_helpers::new_player(&mut sc, &ds, C);
487
+
488
+ sc.next_tx(A);
489
+ let clk = clock::create_for_testing(sc.ctx());
490
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
491
+
492
+ // C was not invited — accept must abort.
493
+ sc.next_tx(C);
494
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
495
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
496
+ duel_system::accept_duel(&ds, &mut us_c, &mut permit, &mut scene, &clk, sc.ctx());
497
+
498
+ test_scenario::return_shared(scene);
499
+ test_scenario::return_shared(permit);
500
+ clk.destroy_for_testing();
501
+ std::unit_test::destroy(ds);
502
+ std::unit_test::destroy(us_a);
503
+ std::unit_test::destroy(us_c);
504
+ sc.end();
505
+ }
506
+
507
+ #[test]
508
+ #[expected_failure]
509
+ fun test_attack_fails_out_of_turn() {
510
+ let (mut sc, ds) = test_helpers::setup();
511
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
512
+ let mut us_b = test_helpers::new_player(&mut sc, &ds, B);
513
+ let deck_b = deck::get(&us_b);
514
+
515
+ sc.next_tx(A);
516
+ let mut clk = clock::create_for_testing(sc.ctx());
517
+ clk.set_for_testing(1_000);
518
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
519
+
520
+ sc.next_tx(B);
521
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
522
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
523
+ duel_system::accept_duel(&ds, &mut us_b, &mut permit, &mut scene, &clk, sc.ctx());
524
+
525
+ // It is A's turn but B attacks — must abort.
526
+ sc.next_tx(B);
527
+ duel_system::attack(&ds, &mut us_b, &mut us_a, &permit, &mut scene, *deck_b.borrow(0), &clk, sc.ctx());
528
+
529
+ test_scenario::return_shared(scene);
530
+ test_scenario::return_shared(permit);
531
+ clk.destroy_for_testing();
532
+ std::unit_test::destroy(ds);
533
+ std::unit_test::destroy(us_a);
534
+ std::unit_test::destroy(us_b);
535
+ sc.end();
536
+ }
537
+
538
+ #[test]
539
+ #[expected_failure]
540
+ fun test_attack_fails_reusing_card_in_same_duel() {
541
+ let (mut sc, ds) = test_helpers::setup();
542
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
543
+ let mut us_b = test_helpers::new_player(&mut sc, &ds, B);
544
+ let deck_a = deck::get(&us_a);
545
+ let deck_b = deck::get(&us_b);
546
+
547
+ sc.next_tx(A);
548
+ let mut clk = clock::create_for_testing(sc.ctx());
549
+ clk.set_for_testing(1_000);
550
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
551
+
552
+ sc.next_tx(B);
553
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
554
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
555
+ duel_system::accept_duel(&ds, &mut us_b, &mut permit, &mut scene, &clk, sc.ctx());
556
+
557
+ let strike_a = *deck_a.borrow(0);
558
+ sc.next_tx(A);
559
+ duel_system::attack(&ds, &mut us_a, &mut us_b, &permit, &mut scene, strike_a, &clk, sc.ctx());
560
+ sc.next_tx(B);
561
+ duel_system::attack(&ds, &mut us_b, &mut us_a, &permit, &mut scene, *deck_b.borrow(0), &clk, sc.ctx());
562
+ // A replays the same Strike — must abort (one use per duel).
563
+ sc.next_tx(A);
564
+ duel_system::attack(&ds, &mut us_a, &mut us_b, &permit, &mut scene, strike_a, &clk, sc.ctx());
565
+
566
+ test_scenario::return_shared(scene);
567
+ test_scenario::return_shared(permit);
568
+ clk.destroy_for_testing();
569
+ std::unit_test::destroy(ds);
570
+ std::unit_test::destroy(us_a);
571
+ std::unit_test::destroy(us_b);
572
+ sc.end();
573
+ }
574
+
575
+ #[test]
576
+ #[expected_failure]
577
+ fun test_defend_fails_with_attack_card() {
578
+ let (mut sc, ds) = test_helpers::setup();
579
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
580
+ let mut us_b = test_helpers::new_player(&mut sc, &ds, B);
581
+ let deck_a = deck::get(&us_a);
582
+
583
+ sc.next_tx(A);
584
+ let mut clk = clock::create_for_testing(sc.ctx());
585
+ clk.set_for_testing(1_000);
586
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
587
+
588
+ sc.next_tx(B);
589
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
590
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
591
+ duel_system::accept_duel(&ds, &mut us_b, &mut permit, &mut scene, &clk, sc.ctx());
592
+
593
+ // Strike is not a defense card — must abort.
594
+ sc.next_tx(A);
595
+ duel_system::defend(&ds, &mut us_a, &permit, &mut scene, *deck_a.borrow(0), &clk, sc.ctx());
596
+
597
+ test_scenario::return_shared(scene);
598
+ test_scenario::return_shared(permit);
599
+ clk.destroy_for_testing();
600
+ std::unit_test::destroy(ds);
601
+ std::unit_test::destroy(us_a);
602
+ std::unit_test::destroy(us_b);
603
+ sc.end();
604
+ }
605
+
606
+ #[test]
607
+ #[expected_failure]
608
+ fun test_create_duel_fails_while_already_in_match() {
609
+ let (mut sc, ds) = test_helpers::setup();
610
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
611
+
612
+ sc.next_tx(A);
613
+ let clk = clock::create_for_testing(sc.ctx());
614
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
615
+ // Second concurrent duel — must abort (already bound to a match).
616
+ duel_system::create_duel(&ds, &mut us_a, C, STAKE, &clk, sc.ctx());
617
+
618
+ clk.destroy_for_testing();
619
+ std::unit_test::destroy(ds);
620
+ std::unit_test::destroy(us_a);
621
+ sc.end();
622
+ }
623
+
624
+ #[test]
625
+ #[expected_failure]
626
+ fun test_finish_duel_fails_for_loser() {
627
+ let (mut sc, ds) = test_helpers::setup();
628
+ let mut us_a = test_helpers::new_player(&mut sc, &ds, A);
629
+ let mut us_b = test_helpers::new_player(&mut sc, &ds, B);
630
+
631
+ sc.next_tx(A);
632
+ let mut clk = clock::create_for_testing(sc.ctx());
633
+ clk.set_for_testing(1_000);
634
+ duel_system::create_duel(&ds, &mut us_a, B, STAKE, &clk, sc.ctx());
635
+
636
+ sc.next_tx(B);
637
+ let mut scene = test_scenario::take_shared<SceneStorage<Duel>>(&sc);
638
+ let mut permit = test_scenario::take_shared<ScenePermit<DuelPermit>>(&sc);
639
+ duel_system::accept_duel(&ds, &mut us_b, &mut permit, &mut scene, &clk, sc.ctx());
640
+ duel_system::surrender(&ds, &mut us_b, &mut permit, &mut scene, sc.ctx());
641
+
642
+ // B lost — claiming the pot must abort.
643
+ sc.next_tx(B);
644
+ let mut arena_obj = test_scenario::take_shared<ObjectStorage<Arena>>(&sc);
645
+ duel_system::finish_duel(&ds, &mut us_b, &mut permit, &mut scene, &mut arena_obj, sc.ctx());
646
+
647
+ test_scenario::return_shared(scene);
648
+ test_scenario::return_shared(permit);
649
+ test_scenario::return_shared(arena_obj);
650
+ clk.destroy_for_testing();
651
+ std::unit_test::destroy(ds);
652
+ std::unit_test::destroy(us_a);
653
+ std::unit_test::destroy(us_b);
654
+ sc.end();
655
+ }
656
+ }
@@ -0,0 +1,31 @@
1
+ /// Shared scaffolding for card_duel unit tests.
2
+ #[test_only]
3
+ module card_duel::test_helpers {
4
+ use sui::test_scenario::{Self, Scenario};
5
+ use dubhe::dapp_service::{DappStorage, UserStorage};
6
+ use card_duel::init_test;
7
+ use card_duel::deploy_hook;
8
+ use card_duel::player_system;
9
+
10
+ const ADMIN: address = @0xAD;
11
+
12
+ public fun admin(): address { ADMIN }
13
+
14
+ /// Begin a scenario as ADMIN with a fully initialised DappStorage
15
+ /// (game_config set, arena object created and shared by deploy_hook).
16
+ public fun setup(): (Scenario, DappStorage) {
17
+ let mut sc = test_scenario::begin(ADMIN);
18
+ let mut ds = init_test::create_dapp_storage_for_testing(sc.ctx());
19
+ deploy_hook::run(&mut ds, sc.ctx());
20
+ (sc, ds)
21
+ }
22
+
23
+ /// Create and register a player owned by `addr`.
24
+ /// Leaves the scenario positioned on a tx sent by `addr`.
25
+ public fun new_player(sc: &mut Scenario, ds: &DappStorage, addr: address): UserStorage {
26
+ sc.next_tx(addr);
27
+ let mut us = init_test::create_user_storage_for_testing(addr, sc.ctx());
28
+ player_system::register(ds, &mut us, sc.ctx());
29
+ us
30
+ }
31
+ }