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,769 @@
1
+ /// Unit tests — DApp lifecycle operations
2
+ ///
3
+ /// Covers all admin-level DApp management functions:
4
+ /// initial_metadata: default values verified after construction
5
+ /// upgrade_dapp: happy path, non-admin, duplicate package, version not increasing,
6
+ /// large version jump, upgrade while paused, new admin after ownership transfer
7
+ /// ensure_latest_version: pass, abort for stale version, abort for future version
8
+ /// set_paused: admin pauses, admin resumes, non-admin abort
9
+ /// ensure_not_paused: pass, abort when paused
10
+ /// set_metadata: admin updates all five fields, non-empty vectors, non-admin abort,
11
+ /// dapp_key mismatch abort, new admin can update after ownership transfer
12
+ /// propose_ownership: sets pending, update overwrites, @0x0 cancels, non-admin abort
13
+ /// accept_ownership: two-step transfer, abort when no pending, abort for wrong caller
14
+ /// ensure_dapp_admin: pass for current admin, abort for non-admin
15
+ ///
16
+ /// Design: single-sender tests use sui::tx_context::dummy() directly.
17
+ /// Multi-sender permission tests use test_scenario only where a second sender is needed.
18
+ #[test_only]
19
+ #[allow(implicit_const_copy)]
20
+ module dubhe::dapp_test;
21
+
22
+ use dubhe::dapp_service::{Self, DappStorage, DappHub};
23
+ use dubhe::dapp_system;
24
+ use sui::test_scenario;
25
+ use std::ascii::string;
26
+
27
+ public struct DappTestKey has copy, drop {}
28
+ public struct DappOtherKey has copy, drop {}
29
+
30
+ const ADMIN: address = @0xAD;
31
+ const NOMINEE: address = @0xBEEF;
32
+ const ATTACKER: address = @0xBAD;
33
+ const NEW_PKG: address = @0x9999;
34
+
35
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
36
+
37
+ // Create a DappHub for version-gating (version = 1 matches FRAMEWORK_VERSION).
38
+ fun new_dh(ctx: &mut TxContext): DappHub {
39
+ dapp_system::create_dapp_hub_for_testing(ctx)
40
+ }
41
+
42
+ // Create a DappStorage with ctx.sender() as admin (for single-sender tests).
43
+ fun new_ds(ctx: &mut TxContext): DappStorage {
44
+ dapp_system::create_dapp_storage_for_testing<DappTestKey>(ctx)
45
+ }
46
+
47
+ // Create a DappStorage with a specific admin (for multi-sender tests).
48
+ fun new_ds_with_admin(admin: address, ctx: &mut TxContext): DappStorage {
49
+ dapp_service::new_dapp_storage<DappTestKey>(
50
+ string(b"Test DApp"),
51
+ string(b""),
52
+ vector[dubhe::type_info::get_package_id<DappTestKey>()],
53
+ 0,
54
+ admin,
55
+ 0,
56
+ 0,
57
+ 0,
58
+ 0,
59
+ 0,
60
+ 0,
61
+ ctx,
62
+ )
63
+ }
64
+
65
+ // ═══════════════════════════════════════════════════════════════════════════════
66
+ // upgrade_dapp
67
+ // ═══════════════════════════════════════════════════════════════════════════════
68
+
69
+ #[test]
70
+ fun test_upgrade_dapp_happy_path() {
71
+ let mut ctx = sui::tx_context::dummy();
72
+ let dh = new_dh(&mut ctx);
73
+ let mut ds = new_ds(&mut ctx);
74
+
75
+ assert!(dapp_service::dapp_version(&ds) == 1);
76
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 2, &mut ctx);
77
+ assert!(dapp_service::dapp_version(&ds) == 2);
78
+ assert!(dapp_service::dapp_package_ids(&ds).contains(&NEW_PKG));
79
+
80
+ dapp_service::destroy_dapp_storage(ds);
81
+ dapp_system::destroy_dapp_hub(dh);
82
+ }
83
+
84
+ #[test]
85
+ fun test_upgrade_dapp_multiple_times() {
86
+ let mut ctx = sui::tx_context::dummy();
87
+ let dh = new_dh(&mut ctx);
88
+ let mut ds = new_ds(&mut ctx);
89
+
90
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, @0xAAA, 2, &mut ctx);
91
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, @0xBBB, 3, &mut ctx);
92
+
93
+ assert!(dapp_service::dapp_version(&ds) == 3);
94
+ let ids = dapp_service::dapp_package_ids(&ds);
95
+ assert!(ids.contains(&@0xAAA));
96
+ assert!(ids.contains(&@0xBBB));
97
+
98
+ dapp_service::destroy_dapp_storage(ds);
99
+ dapp_system::destroy_dapp_hub(dh);
100
+ }
101
+
102
+ #[test]
103
+ #[expected_failure]
104
+ fun test_upgrade_dapp_aborts_for_non_admin() {
105
+ let mut scenario = test_scenario::begin(ADMIN);
106
+ {
107
+ let ctx = test_scenario::ctx(&mut scenario);
108
+ let ds = new_ds_with_admin(ADMIN, ctx);
109
+ transfer::public_share_object(ds);
110
+ };
111
+ test_scenario::next_tx(&mut scenario, ATTACKER);
112
+ {
113
+ let mut ds: DappStorage = test_scenario::take_shared(&scenario);
114
+ let ctx = test_scenario::ctx(&mut scenario);
115
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
116
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 2, ctx);
117
+ dapp_system::destroy_dapp_hub(dh);
118
+ test_scenario::return_shared(ds);
119
+ };
120
+ scenario.end();
121
+ }
122
+
123
+ #[test]
124
+ #[expected_failure]
125
+ fun test_upgrade_dapp_aborts_for_duplicate_package_id() {
126
+ let mut ctx = sui::tx_context::dummy();
127
+ let dh = new_dh(&mut ctx);
128
+ let mut ds = new_ds(&mut ctx);
129
+
130
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 2, &mut ctx);
131
+ // Same package ID again must abort.
132
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 3, &mut ctx);
133
+
134
+ dapp_service::destroy_dapp_storage(ds);
135
+ dapp_system::destroy_dapp_hub(dh);
136
+ }
137
+
138
+ #[test]
139
+ #[expected_failure]
140
+ fun test_upgrade_dapp_aborts_when_version_equal() {
141
+ let mut ctx = sui::tx_context::dummy();
142
+ let dh = new_dh(&mut ctx);
143
+ let mut ds = new_ds(&mut ctx);
144
+ // Current version is 1; passing 1 must abort.
145
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 1, &mut ctx);
146
+ dapp_service::destroy_dapp_storage(ds);
147
+ dapp_system::destroy_dapp_hub(dh);
148
+ }
149
+
150
+ #[test]
151
+ #[expected_failure]
152
+ fun test_upgrade_dapp_aborts_when_version_decreasing() {
153
+ let mut ctx = sui::tx_context::dummy();
154
+ let dh = new_dh(&mut ctx);
155
+ let mut ds = new_ds(&mut ctx);
156
+
157
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, @0xA1, 5, &mut ctx);
158
+ // Passing an older version must also abort.
159
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, @0xA2, 3, &mut ctx);
160
+
161
+ dapp_service::destroy_dapp_storage(ds);
162
+ dapp_system::destroy_dapp_hub(dh);
163
+ }
164
+
165
+ #[test]
166
+ fun test_upgrade_dapp_large_version_jump() {
167
+ let mut ctx = sui::tx_context::dummy();
168
+ let dh = new_dh(&mut ctx);
169
+ let mut ds = new_ds(&mut ctx);
170
+
171
+ // v1 → v100: large jumps are valid as long as the version increases.
172
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 100, &mut ctx);
173
+ assert!(dapp_service::dapp_version(&ds) == 100);
174
+ assert!(dapp_service::dapp_package_ids(&ds).contains(&NEW_PKG));
175
+
176
+ dapp_service::destroy_dapp_storage(ds);
177
+ dapp_system::destroy_dapp_hub(dh);
178
+ }
179
+
180
+ #[test]
181
+ fun test_upgrade_dapp_while_paused() {
182
+ let mut ctx = sui::tx_context::dummy();
183
+ let dh = new_dh(&mut ctx);
184
+ let mut ds = new_ds(&mut ctx);
185
+
186
+ // Admin pauses the DApp first.
187
+ dapp_system::set_paused<DappTestKey>(&dh, &mut ds, true, &mut ctx);
188
+ assert!(dapp_service::dapp_paused(&ds));
189
+
190
+ // Admin can still upgrade even while the DApp is paused.
191
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 2, &mut ctx);
192
+ assert!(dapp_service::dapp_version(&ds) == 2);
193
+ assert!(dapp_service::dapp_paused(&ds)); // still paused after upgrade
194
+
195
+ dapp_service::destroy_dapp_storage(ds);
196
+ dapp_system::destroy_dapp_hub(dh);
197
+ }
198
+
199
+ #[test]
200
+ fun test_upgrade_dapp_new_admin_can_upgrade() {
201
+ // After a two-step ownership transfer, the new admin must be able to upgrade.
202
+ let mut scenario = test_scenario::begin(ADMIN);
203
+ {
204
+ let ctx = test_scenario::ctx(&mut scenario);
205
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
206
+ let mut ds = new_ds_with_admin(ADMIN, ctx);
207
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, NOMINEE, ctx);
208
+ dapp_system::destroy_dapp_hub(dh);
209
+ transfer::public_share_object(ds);
210
+ };
211
+ test_scenario::next_tx(&mut scenario, NOMINEE);
212
+ {
213
+ let mut ds: DappStorage = test_scenario::take_shared(&scenario);
214
+ let ctx = test_scenario::ctx(&mut scenario);
215
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
216
+ dapp_system::accept_ownership<DappTestKey>(&dh, &mut ds, ctx);
217
+ assert!(dapp_service::dapp_admin(&ds) == NOMINEE);
218
+
219
+ // New admin upgrades successfully.
220
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 2, ctx);
221
+ assert!(dapp_service::dapp_version(&ds) == 2);
222
+ dapp_system::destroy_dapp_hub(dh);
223
+ test_scenario::return_shared(ds);
224
+ };
225
+ scenario.end();
226
+ }
227
+
228
+ // ═══════════════════════════════════════════════════════════════════════════════
229
+ // ensure_latest_version
230
+ // ═══════════════════════════════════════════════════════════════════════════════
231
+
232
+ #[test]
233
+ fun test_ensure_latest_version_passes_for_current_version() {
234
+ let mut ctx = sui::tx_context::dummy();
235
+ let dh = new_dh(&mut ctx);
236
+ let mut ds = new_ds(&mut ctx);
237
+
238
+ dapp_system::ensure_latest_version<DappTestKey>(&ds, 1);
239
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 2, &mut ctx);
240
+ dapp_system::ensure_latest_version<DappTestKey>(&ds, 2);
241
+
242
+ dapp_service::destroy_dapp_storage(ds);
243
+ dapp_system::destroy_dapp_hub(dh);
244
+ }
245
+
246
+ #[test]
247
+ #[expected_failure]
248
+ fun test_ensure_latest_version_aborts_for_stale_version() {
249
+ let mut ctx = sui::tx_context::dummy();
250
+ let dh = new_dh(&mut ctx);
251
+ let mut ds = new_ds(&mut ctx);
252
+
253
+ dapp_system::upgrade_dapp<DappTestKey>(&dh, &mut ds, NEW_PKG, 2, &mut ctx);
254
+ // Old code compiled with version=1 — must abort.
255
+ dapp_system::ensure_latest_version<DappTestKey>(&ds, 1);
256
+
257
+ dapp_service::destroy_dapp_storage(ds);
258
+ dapp_system::destroy_dapp_hub(dh);
259
+ }
260
+
261
+ #[test]
262
+ #[expected_failure]
263
+ fun test_ensure_latest_version_aborts_for_future_version() {
264
+ let mut ctx = sui::tx_context::dummy();
265
+ let ds = new_ds(&mut ctx);
266
+
267
+ // DApp is at version=1. Passing a higher version (e.g. from code compiled
268
+ // against a future package) must also abort — the guard rejects any mismatch,
269
+ // not only stale versions.
270
+ dapp_system::ensure_latest_version<DappTestKey>(&ds, 2);
271
+
272
+ dapp_service::destroy_dapp_storage(ds);
273
+ }
274
+
275
+ // ═══════════════════════════════════════════════════════════════════════════════
276
+ // set_paused / ensure_not_paused
277
+ // ═══════════════════════════════════════════════════════════════════════════════
278
+
279
+ #[test]
280
+ fun test_set_paused_admin_can_pause_and_resume() {
281
+ let mut ctx = sui::tx_context::dummy();
282
+ let dh = new_dh(&mut ctx);
283
+ let mut ds = new_ds(&mut ctx);
284
+
285
+ assert!(!dapp_service::dapp_paused(&ds));
286
+
287
+ dapp_system::set_paused<DappTestKey>(&dh, &mut ds, true, &mut ctx);
288
+ assert!(dapp_service::dapp_paused(&ds));
289
+
290
+ dapp_system::set_paused<DappTestKey>(&dh, &mut ds, false, &mut ctx);
291
+ assert!(!dapp_service::dapp_paused(&ds));
292
+
293
+ dapp_service::destroy_dapp_storage(ds);
294
+ dapp_system::destroy_dapp_hub(dh);
295
+ }
296
+
297
+ #[test]
298
+ #[expected_failure]
299
+ fun test_set_paused_aborts_for_non_admin() {
300
+ let mut scenario = test_scenario::begin(ADMIN);
301
+ {
302
+ let ctx = test_scenario::ctx(&mut scenario);
303
+ let ds = new_ds_with_admin(ADMIN, ctx);
304
+ transfer::public_share_object(ds);
305
+ };
306
+ test_scenario::next_tx(&mut scenario, ATTACKER);
307
+ {
308
+ let mut ds: DappStorage = test_scenario::take_shared(&scenario);
309
+ let ctx = test_scenario::ctx(&mut scenario);
310
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
311
+ dapp_system::set_paused<DappTestKey>(&dh, &mut ds, true, ctx);
312
+ dapp_system::destroy_dapp_hub(dh);
313
+ test_scenario::return_shared(ds);
314
+ };
315
+ scenario.end();
316
+ }
317
+
318
+ #[test]
319
+ fun test_ensure_not_paused_passes_when_not_paused() {
320
+ let mut ctx = sui::tx_context::dummy();
321
+ let ds = new_ds(&mut ctx);
322
+ dapp_system::ensure_not_paused<DappTestKey>(&ds);
323
+ dapp_service::destroy_dapp_storage(ds);
324
+ }
325
+
326
+ #[test]
327
+ #[expected_failure]
328
+ fun test_ensure_not_paused_aborts_when_paused() {
329
+ let mut ctx = sui::tx_context::dummy();
330
+ let dh = new_dh(&mut ctx);
331
+ let mut ds = new_ds(&mut ctx);
332
+ dapp_system::set_paused<DappTestKey>(&dh, &mut ds, true, &mut ctx);
333
+ dapp_system::ensure_not_paused<DappTestKey>(&ds);
334
+ dapp_service::destroy_dapp_storage(ds);
335
+ dapp_system::destroy_dapp_hub(dh);
336
+ }
337
+
338
+ // ═══════════════════════════════════════════════════════════════════════════════
339
+ // initial_metadata
340
+ // ═══════════════════════════════════════════════════════════════════════════════
341
+
342
+ #[test]
343
+ fun test_initial_metadata_values() {
344
+ let mut ctx = sui::tx_context::dummy();
345
+ let ds = new_ds(&mut ctx);
346
+
347
+ // Verify all metadata defaults set by create_dapp_storage_for_testing.
348
+ assert!(dapp_service::dapp_name(&ds) == string(b"Test DApp"));
349
+ assert!(dapp_service::dapp_description(&ds) == string(b""));
350
+ assert!(dapp_service::dapp_website_url(&ds) == string(b""));
351
+ assert!(dapp_service::dapp_cover_url(&ds).is_empty());
352
+ assert!(dapp_service::dapp_partners(&ds).is_empty());
353
+ assert!(dapp_service::dapp_version(&ds) == 1);
354
+ assert!(!dapp_service::dapp_paused(&ds));
355
+ assert!(dapp_service::dapp_admin(&ds) == ctx.sender());
356
+ assert!(dapp_service::dapp_pending_admin(&ds) == @0x0);
357
+
358
+ dapp_service::destroy_dapp_storage(ds);
359
+ }
360
+
361
+ // ═══════════════════════════════════════════════════════════════════════════════
362
+ // set_metadata
363
+ // ═══════════════════════════════════════════════════════════════════════════════
364
+
365
+ #[test]
366
+ fun test_set_metadata_admin_updates_all_fields() {
367
+ let mut ctx = sui::tx_context::dummy();
368
+ let dh = new_dh(&mut ctx);
369
+ let mut ds = new_ds(&mut ctx);
370
+
371
+ dapp_system::set_metadata<DappTestKey>(
372
+ &dh,
373
+ &mut ds,
374
+ string(b"New Name"),
375
+ string(b"New description"),
376
+ string(b"https://example.com"),
377
+ vector[string(b"https://img.example.com/cover.png")],
378
+ vector[string(b"Obelisk"), string(b"Sui Foundation")],
379
+ &mut ctx,
380
+ );
381
+
382
+ assert!(dapp_service::dapp_name(&ds) == string(b"New Name"));
383
+ assert!(dapp_service::dapp_description(&ds) == string(b"New description"));
384
+ assert!(dapp_service::dapp_website_url(&ds) == string(b"https://example.com"));
385
+
386
+ let cover = dapp_service::dapp_cover_url(&ds);
387
+ assert!(cover.length() == 1);
388
+ assert!(*cover.borrow(0) == string(b"https://img.example.com/cover.png"));
389
+
390
+ let partners = dapp_service::dapp_partners(&ds);
391
+ assert!(partners.length() == 2);
392
+ assert!(*partners.borrow(0) == string(b"Obelisk"));
393
+ assert!(*partners.borrow(1) == string(b"Sui Foundation"));
394
+
395
+ dapp_service::destroy_dapp_storage(ds);
396
+ dapp_system::destroy_dapp_hub(dh);
397
+ }
398
+
399
+ #[test]
400
+ fun test_set_metadata_clears_vectors_to_empty() {
401
+ let mut ctx = sui::tx_context::dummy();
402
+ let dh = new_dh(&mut ctx);
403
+ let mut ds = new_ds(&mut ctx);
404
+
405
+ // First set some data.
406
+ dapp_system::set_metadata<DappTestKey>(
407
+ &dh,
408
+ &mut ds,
409
+ string(b"Name"),
410
+ string(b"Desc"),
411
+ string(b"https://example.com"),
412
+ vector[string(b"https://cover.png")],
413
+ vector[string(b"Partner A")],
414
+ &mut ctx,
415
+ );
416
+ assert!(!dapp_service::dapp_cover_url(&ds).is_empty());
417
+
418
+ // Then clear vectors back to empty.
419
+ dapp_system::set_metadata<DappTestKey>(
420
+ &dh,
421
+ &mut ds,
422
+ string(b"Name"),
423
+ string(b"Desc"),
424
+ string(b""),
425
+ vector::empty(),
426
+ vector::empty(),
427
+ &mut ctx,
428
+ );
429
+ assert!(dapp_service::dapp_cover_url(&ds).is_empty());
430
+ assert!(dapp_service::dapp_partners(&ds).is_empty());
431
+
432
+ dapp_service::destroy_dapp_storage(ds);
433
+ dapp_system::destroy_dapp_hub(dh);
434
+ }
435
+
436
+ #[test]
437
+ fun test_set_metadata_new_admin_can_update_after_ownership_transfer() {
438
+ let mut scenario = test_scenario::begin(ADMIN);
439
+ {
440
+ let ctx = test_scenario::ctx(&mut scenario);
441
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
442
+ let mut ds = new_ds_with_admin(ADMIN, ctx);
443
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, NOMINEE, ctx);
444
+ dapp_system::destroy_dapp_hub(dh);
445
+ transfer::public_share_object(ds);
446
+ };
447
+ test_scenario::next_tx(&mut scenario, NOMINEE);
448
+ {
449
+ let mut ds: DappStorage = test_scenario::take_shared(&scenario);
450
+ let ctx = test_scenario::ctx(&mut scenario);
451
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
452
+ dapp_system::accept_ownership<DappTestKey>(&dh, &mut ds, ctx);
453
+
454
+ // New admin must be able to update metadata.
455
+ dapp_system::set_metadata<DappTestKey>(
456
+ &dh,
457
+ &mut ds,
458
+ string(b"Renamed"),
459
+ string(b"By new admin"),
460
+ string(b""),
461
+ vector::empty(),
462
+ vector::empty(),
463
+ ctx,
464
+ );
465
+ assert!(dapp_service::dapp_name(&ds) == string(b"Renamed"));
466
+ dapp_system::destroy_dapp_hub(dh);
467
+ test_scenario::return_shared(ds);
468
+ };
469
+ scenario.end();
470
+ }
471
+
472
+ #[test]
473
+ #[expected_failure]
474
+ fun test_set_metadata_aborts_for_non_admin() {
475
+ let mut scenario = test_scenario::begin(ADMIN);
476
+ {
477
+ let ctx = test_scenario::ctx(&mut scenario);
478
+ let ds = new_ds_with_admin(ADMIN, ctx);
479
+ transfer::public_share_object(ds);
480
+ };
481
+ test_scenario::next_tx(&mut scenario, ATTACKER);
482
+ {
483
+ let mut ds: DappStorage = test_scenario::take_shared(&scenario);
484
+ let ctx = test_scenario::ctx(&mut scenario);
485
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
486
+ dapp_system::set_metadata<DappTestKey>(
487
+ &dh,
488
+ &mut ds,
489
+ string(b"Hacked"),
490
+ string(b""),
491
+ string(b""),
492
+ vector::empty(),
493
+ vector::empty(),
494
+ ctx,
495
+ );
496
+ dapp_system::destroy_dapp_hub(dh);
497
+ test_scenario::return_shared(ds);
498
+ };
499
+ scenario.end();
500
+ }
501
+
502
+ #[test]
503
+ #[expected_failure]
504
+ fun test_set_metadata_aborts_for_dapp_key_mismatch() {
505
+ let mut ctx = sui::tx_context::dummy();
506
+ let dh = new_dh(&mut ctx);
507
+ let mut ds = new_ds(&mut ctx);
508
+ // DappOtherKey does not match the storage's DappTestKey — must abort.
509
+ dapp_system::set_metadata<DappOtherKey>(
510
+ &dh,
511
+ &mut ds,
512
+ string(b"Wrong Key"),
513
+ string(b""),
514
+ string(b""),
515
+ vector::empty(),
516
+ vector::empty(),
517
+ &mut ctx,
518
+ );
519
+ dapp_service::destroy_dapp_storage(ds);
520
+ dapp_system::destroy_dapp_hub(dh);
521
+ }
522
+
523
+ // ═══════════════════════════════════════════════════════════════════════════════
524
+ // propose_ownership / accept_ownership
525
+ // ═══════════════════════════════════════════════════════════════════════════════
526
+
527
+ #[test]
528
+ fun test_propose_ownership_sets_pending_admin() {
529
+ let mut ctx = sui::tx_context::dummy();
530
+ let dh = new_dh(&mut ctx);
531
+ let mut ds = new_ds(&mut ctx);
532
+
533
+ assert!(dapp_service::dapp_pending_admin(&ds) == @0x0);
534
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, NOMINEE, &mut ctx);
535
+ assert!(dapp_service::dapp_pending_admin(&ds) == NOMINEE);
536
+ assert!(dapp_service::dapp_admin(&ds) == ctx.sender()); // admin unchanged
537
+
538
+ dapp_service::destroy_dapp_storage(ds);
539
+ dapp_system::destroy_dapp_hub(dh);
540
+ }
541
+
542
+ #[test]
543
+ fun test_propose_ownership_can_be_overwritten() {
544
+ let mut ctx = sui::tx_context::dummy();
545
+ let dh = new_dh(&mut ctx);
546
+ let mut ds = new_ds(&mut ctx);
547
+
548
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, @0xBEE1, &mut ctx);
549
+ assert!(dapp_service::dapp_pending_admin(&ds) == @0xBEE1);
550
+
551
+ // Override with a different nominee — last one wins.
552
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, @0xBEE2, &mut ctx);
553
+ assert!(dapp_service::dapp_pending_admin(&ds) == @0xBEE2);
554
+
555
+ dapp_service::destroy_dapp_storage(ds);
556
+ dapp_system::destroy_dapp_hub(dh);
557
+ }
558
+
559
+ #[test]
560
+ fun test_propose_zero_address_cancels_pending_transfer() {
561
+ let mut ctx = sui::tx_context::dummy();
562
+ let dh = new_dh(&mut ctx);
563
+ let mut ds = new_ds(&mut ctx);
564
+
565
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, NOMINEE, &mut ctx);
566
+ assert!(dapp_service::dapp_pending_admin(&ds) == NOMINEE);
567
+
568
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, @0x0, &mut ctx);
569
+ assert!(dapp_service::dapp_pending_admin(&ds) == @0x0);
570
+
571
+ dapp_service::destroy_dapp_storage(ds);
572
+ dapp_system::destroy_dapp_hub(dh);
573
+ }
574
+
575
+ #[test]
576
+ #[expected_failure]
577
+ fun test_propose_ownership_aborts_for_non_admin() {
578
+ let mut scenario = test_scenario::begin(ADMIN);
579
+ {
580
+ let ctx = test_scenario::ctx(&mut scenario);
581
+ let ds = new_ds_with_admin(ADMIN, ctx);
582
+ transfer::public_share_object(ds);
583
+ };
584
+ test_scenario::next_tx(&mut scenario, ATTACKER);
585
+ {
586
+ let mut ds: DappStorage = test_scenario::take_shared(&scenario);
587
+ let ctx = test_scenario::ctx(&mut scenario);
588
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
589
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, ATTACKER, ctx);
590
+ dapp_system::destroy_dapp_hub(dh);
591
+ test_scenario::return_shared(ds);
592
+ };
593
+ scenario.end();
594
+ }
595
+
596
+ #[test]
597
+ fun test_accept_ownership_two_step_transfer() {
598
+ let mut scenario = test_scenario::begin(ADMIN);
599
+ {
600
+ let ctx = test_scenario::ctx(&mut scenario);
601
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
602
+ let mut ds = new_ds_with_admin(ADMIN, ctx);
603
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, NOMINEE, ctx);
604
+ dapp_system::destroy_dapp_hub(dh);
605
+ transfer::public_share_object(ds);
606
+ };
607
+ test_scenario::next_tx(&mut scenario, NOMINEE);
608
+ {
609
+ let mut ds: DappStorage = test_scenario::take_shared(&scenario);
610
+ let ctx = test_scenario::ctx(&mut scenario);
611
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
612
+ dapp_system::accept_ownership<DappTestKey>(&dh, &mut ds, ctx);
613
+ assert!(dapp_service::dapp_admin(&ds) == NOMINEE);
614
+ assert!(dapp_service::dapp_pending_admin(&ds) == @0x0);
615
+ dapp_system::destroy_dapp_hub(dh);
616
+ test_scenario::return_shared(ds);
617
+ };
618
+ scenario.end();
619
+ }
620
+
621
+ #[test]
622
+ #[expected_failure]
623
+ fun test_accept_ownership_aborts_when_no_pending_transfer() {
624
+ let mut ctx = sui::tx_context::dummy();
625
+ let dh = new_dh(&mut ctx);
626
+ let mut ds = new_ds(&mut ctx);
627
+ // No pending transfer — must abort.
628
+ dapp_system::accept_ownership<DappTestKey>(&dh, &mut ds, &mut ctx);
629
+ dapp_service::destroy_dapp_storage(ds);
630
+ dapp_system::destroy_dapp_hub(dh);
631
+ }
632
+
633
+ #[test]
634
+ #[expected_failure]
635
+ fun test_accept_ownership_aborts_for_wrong_caller() {
636
+ let mut scenario = test_scenario::begin(ADMIN);
637
+ {
638
+ let ctx = test_scenario::ctx(&mut scenario);
639
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
640
+ let mut ds = new_ds_with_admin(ADMIN, ctx);
641
+ dapp_system::propose_ownership<DappTestKey>(&dh, &mut ds, NOMINEE, ctx);
642
+ dapp_system::destroy_dapp_hub(dh);
643
+ transfer::public_share_object(ds);
644
+ };
645
+ // Wrong address tries to accept — must abort.
646
+ test_scenario::next_tx(&mut scenario, ATTACKER);
647
+ {
648
+ let mut ds: DappStorage = test_scenario::take_shared(&scenario);
649
+ let ctx = test_scenario::ctx(&mut scenario);
650
+ let dh = dapp_system::create_dapp_hub_for_testing(ctx);
651
+ dapp_system::accept_ownership<DappTestKey>(&dh, &mut ds, ctx);
652
+ dapp_system::destroy_dapp_hub(dh);
653
+ test_scenario::return_shared(ds);
654
+ };
655
+ scenario.end();
656
+ }
657
+
658
+ // ═══════════════════════════════════════════════════════════════════════════════
659
+ // dapp_key mismatch guards (upgrade_dapp / set_paused / ensure_* / propose / accept)
660
+ // ═══════════════════════════════════════════════════════════════════════════════
661
+
662
+ // Note on upgrade_dapp package-ID semantics:
663
+ // upgrade_dapp validates that the caller's DappKey belongs to a package already
664
+ // registered in dapp_storage.package_ids, OR that its package ID equals new_package_id
665
+ // (allowing a freshly upgraded package to call upgrade_dapp for the first time).
666
+ // This is intentionally a package-level check — any type defined in a registered
667
+ // package is a valid DappKey. DappTestKey and DappOtherKey share the same package ID
668
+ // because they are defined in the same test module, so both can call upgrade_dapp on
669
+ // storage whose package_ids list already contains that package ID.
670
+ // Cross-package mismatch (a completely foreign package attempting to call upgrade_dapp)
671
+ // cannot be simulated within a single test module; that protection is enforced at the
672
+ // package boundary by the package-ID containment check.
673
+ #[test]
674
+ fun test_upgrade_dapp_succeeds_for_same_package_different_key_type() {
675
+ // DappOtherKey is in the same package as DappTestKey; under the new package-ID-
676
+ // based validation, upgrade_dapp should succeed because get_package_id<DappOtherKey>()
677
+ // matches the package ID already stored in dapp_storage.package_ids.
678
+ let mut ctx = sui::tx_context::dummy();
679
+ let dh = new_dh(&mut ctx);
680
+ let mut ds = new_ds(&mut ctx);
681
+ dapp_system::upgrade_dapp<DappOtherKey>(&dh, &mut ds, NEW_PKG, 2, &mut ctx);
682
+ assert!(dapp_service::dapp_version(&ds) == 2);
683
+ assert!(dapp_service::dapp_package_ids(&ds).contains(&NEW_PKG));
684
+ dapp_service::destroy_dapp_storage(ds);
685
+ dapp_system::destroy_dapp_hub(dh);
686
+ }
687
+
688
+ #[test]
689
+ #[expected_failure]
690
+ fun test_set_paused_aborts_for_dapp_key_mismatch() {
691
+ let mut ctx = sui::tx_context::dummy();
692
+ let dh = new_dh(&mut ctx);
693
+ let mut ds = new_ds(&mut ctx);
694
+ dapp_system::set_paused<DappOtherKey>(&dh, &mut ds, true, &mut ctx);
695
+ dapp_service::destroy_dapp_storage(ds);
696
+ dapp_system::destroy_dapp_hub(dh);
697
+ }
698
+
699
+ #[test]
700
+ #[expected_failure]
701
+ fun test_propose_ownership_aborts_for_dapp_key_mismatch() {
702
+ let mut ctx = sui::tx_context::dummy();
703
+ let dh = new_dh(&mut ctx);
704
+ let mut ds = new_ds(&mut ctx);
705
+ dapp_system::propose_ownership<DappOtherKey>(&dh, &mut ds, NOMINEE, &mut ctx);
706
+ dapp_service::destroy_dapp_storage(ds);
707
+ dapp_system::destroy_dapp_hub(dh);
708
+ }
709
+
710
+ #[test]
711
+ #[expected_failure]
712
+ fun test_accept_ownership_aborts_for_dapp_key_mismatch() {
713
+ let mut ctx = sui::tx_context::dummy();
714
+ let dh = new_dh(&mut ctx);
715
+ let mut ds = new_ds(&mut ctx);
716
+ dapp_system::accept_ownership<DappOtherKey>(&dh, &mut ds, &mut ctx);
717
+ dapp_service::destroy_dapp_storage(ds);
718
+ dapp_system::destroy_dapp_hub(dh);
719
+ }
720
+
721
+ #[test]
722
+ #[expected_failure]
723
+ fun test_ensure_latest_version_aborts_for_dapp_key_mismatch() {
724
+ let mut ctx = sui::tx_context::dummy();
725
+ let ds = new_ds(&mut ctx);
726
+ dapp_system::ensure_latest_version<DappOtherKey>(&ds, 1);
727
+ dapp_service::destroy_dapp_storage(ds);
728
+ }
729
+
730
+ #[test]
731
+ #[expected_failure]
732
+ fun test_ensure_not_paused_aborts_for_dapp_key_mismatch() {
733
+ let mut ctx = sui::tx_context::dummy();
734
+ let ds = new_ds(&mut ctx);
735
+ dapp_system::ensure_not_paused<DappOtherKey>(&ds);
736
+ dapp_service::destroy_dapp_storage(ds);
737
+ }
738
+
739
+ // ═══════════════════════════════════════════════════════════════════════════════
740
+ // ensure_dapp_admin
741
+ // ═══════════════════════════════════════════════════════════════════════════════
742
+
743
+ #[test]
744
+ fun test_ensure_dapp_admin_passes_for_admin() {
745
+ let mut ctx = sui::tx_context::dummy();
746
+ let ds = new_ds(&mut ctx);
747
+ // ctx.sender() is the admin because new_ds() creates storage with ctx.sender() as admin.
748
+ dapp_system::ensure_dapp_admin<DappTestKey>(&ds, ctx.sender());
749
+ dapp_service::destroy_dapp_storage(ds);
750
+ }
751
+
752
+ #[test]
753
+ #[expected_failure]
754
+ fun test_ensure_dapp_admin_aborts_for_non_admin() {
755
+ let mut ctx = sui::tx_context::dummy();
756
+ let ds = new_ds(&mut ctx);
757
+ // ATTACKER is not the admin — must abort with no_permission.
758
+ dapp_system::ensure_dapp_admin<DappTestKey>(&ds, ATTACKER);
759
+ dapp_service::destroy_dapp_storage(ds);
760
+ }
761
+
762
+ #[test]
763
+ #[expected_failure]
764
+ fun test_ensure_dapp_admin_aborts_for_dapp_key_mismatch() {
765
+ let mut ctx = sui::tx_context::dummy();
766
+ let ds = new_ds(&mut ctx);
767
+ dapp_system::ensure_dapp_admin<DappOtherKey>(&ds, ctx.sender());
768
+ dapp_service::destroy_dapp_storage(ds);
769
+ }