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,495 @@
1
+ module harvest::pet_system {
2
+ use sui::clock::Clock;
3
+ use sui::random::{Self, Random};
4
+ use sui::sui::SUI;
5
+ use sui::coin::{Self, Coin};
6
+ use dubhe::dapp_service::{Self, DappHub, DappStorage, UserStorage};
7
+ use dubhe::dapp_system;
8
+ use harvest::dapp_key::DappKey;
9
+ use harvest::migrate;
10
+ use harvest::error;
11
+ use harvest::gold;
12
+ use harvest::common_egg;
13
+ use harvest::rare_egg;
14
+ use harvest::seasonal_egg;
15
+ use harvest::pet_hatch;
16
+ use harvest::pet;
17
+ use harvest::pet_slot_index;
18
+ use harvest::pet_slots;
19
+ use harvest::pet_config;
20
+ use harvest::profile;
21
+
22
+ // ─── Constants ────────────────────────────────────────────────────────────
23
+
24
+ const EGG_COMMON: u8 = 1;
25
+ const EGG_RARE: u8 = 2;
26
+ const EGG_SEASONAL: u8 = 3;
27
+
28
+ const SPECIES_BUNNY: u8 = 1;
29
+ const SPECIES_CHICK: u8 = 2;
30
+ const SPECIES_FOX: u8 = 3;
31
+ const SPECIES_DEER: u8 = 4;
32
+ const SPECIES_DRAGON: u8 = 5;
33
+
34
+ const RARITY_COMMON: u8 = 0;
35
+ const RARITY_UNCOMMON: u8 = 1;
36
+ const RARITY_RARE: u8 = 2;
37
+
38
+ const XP_PER_LEVEL: u32 = 100;
39
+
40
+ const SATIETY_DRAIN_INTERVAL_MS: u64 = 4 * 60 * 60 * 1000;
41
+ const SATIETY_DRAIN_AMOUNT: u8 = 20;
42
+ const MAX_SATIETY: u8 = 100;
43
+ const MAX_HAPPINESS: u8 = 100;
44
+ const MAX_LEVEL: u8 = 10;
45
+ const MAX_PET_SLOTS: u8 = 3;
46
+ const DEFAULT_PET_SLOTS: u8 = 1;
47
+
48
+ const SATIETY_RESTORE_FAVORITE: u8 = 25;
49
+ const SATIETY_RESTORE_OTHER: u8 = 10;
50
+ const HAPPINESS_GAIN_FAVORITE: u8 = 15;
51
+ const HAPPINESS_GAIN_OTHER: u8 = 5;
52
+ const XP_GAIN_FAVORITE: u32 = 20;
53
+ const XP_GAIN_OTHER: u32 = 5;
54
+
55
+ #[error]
56
+ const EHatchNotReady: vector<u8> = b"Egg is not ready to hatch yet";
57
+
58
+ // ─── Buy eggs from shop ───────────────────────────────────────────────────
59
+
60
+ public entry fun buy_common_egg(
61
+ dapp_storage: &DappStorage,
62
+ user_storage: &mut UserStorage,
63
+ count: u64,
64
+ ctx: &mut TxContext,
65
+ ) {
66
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
67
+ error::not_registered(profile::has(user_storage));
68
+ error::insufficient_eggs(count > 0);
69
+ let price = pet_config::get_common_egg_price(dapp_storage) * count;
70
+ error::insufficient_gold(gold::get(user_storage) >= price);
71
+ gold::sub(user_storage, price, ctx);
72
+ common_egg::add(user_storage, count, ctx);
73
+ }
74
+
75
+ public entry fun buy_rare_egg(
76
+ dapp_storage: &DappStorage,
77
+ user_storage: &mut UserStorage,
78
+ count: u64,
79
+ ctx: &mut TxContext,
80
+ ) {
81
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
82
+ error::not_registered(profile::has(user_storage));
83
+ error::insufficient_eggs(count > 0);
84
+ let price = pet_config::get_rare_egg_price(dapp_storage) * count;
85
+ error::insufficient_gold(gold::get(user_storage) >= price);
86
+ gold::sub(user_storage, price, ctx);
87
+ rare_egg::add(user_storage, count, ctx);
88
+ }
89
+
90
+ public entry fun buy_seasonal_egg(
91
+ dapp_storage: &DappStorage,
92
+ user_storage: &mut UserStorage,
93
+ count: u64,
94
+ ctx: &mut TxContext,
95
+ ) {
96
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
97
+ error::not_registered(profile::has(user_storage));
98
+ error::insufficient_eggs(count > 0);
99
+ let price = pet_config::get_seasonal_egg_price(dapp_storage) * count;
100
+ error::insufficient_gold(gold::get(user_storage) >= price);
101
+ gold::sub(user_storage, price, ctx);
102
+ seasonal_egg::add(user_storage, count, ctx);
103
+ }
104
+
105
+ // ─── Hatch flow ───────────────────────────────────────────────────────────
106
+
107
+ /// Place one egg of `egg_type` into the incubation slot.
108
+ public entry fun start_hatch(
109
+ dapp_storage: &DappStorage,
110
+ user_storage: &mut UserStorage,
111
+ egg_type: u8,
112
+ clock: &Clock,
113
+ ctx: &mut TxContext,
114
+ ) {
115
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
116
+ error::not_registered(profile::has(user_storage));
117
+ error::invalid_egg_type(egg_type >= EGG_COMMON && egg_type <= EGG_SEASONAL);
118
+ error::hatch_slot_busy(!pet_hatch::has(user_storage));
119
+
120
+ let bal = egg_balance(user_storage, egg_type);
121
+ error::insufficient_eggs(bal >= 1);
122
+ deduct_egg(user_storage, egg_type, 1, ctx);
123
+
124
+ let now = sui::clock::timestamp_ms(clock);
125
+ let hatch_duration = hatch_duration_ms(dapp_storage, egg_type);
126
+ pet_hatch::set(user_storage, egg_type, now + hatch_duration, ctx);
127
+ }
128
+
129
+ /// Open a ready egg and place the new pet into the ranch (no active slot required).
130
+ /// Uses Sui randomness to determine species and rarity.
131
+ /// Mints a new pet with a globally unique pet_id via ctx.fresh_object_address().
132
+ /// Call assign_slot() afterwards to activate the pet in a display slot.
133
+ public entry fun open_egg(
134
+ dapp_storage: &DappStorage,
135
+ user_storage: &mut UserStorage,
136
+ rng: &Random,
137
+ clock: &Clock,
138
+ ctx: &mut TxContext,
139
+ ) {
140
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
141
+ error::not_registered(profile::has(user_storage));
142
+ error::no_egg_incubating(pet_hatch::has(user_storage));
143
+
144
+ let now = sui::clock::timestamp_ms(clock);
145
+ let hatch_at = pet_hatch::get_hatch_at(user_storage);
146
+ assert!(now >= hatch_at, EHatchNotReady);
147
+
148
+ let egg_type = pet_hatch::get_egg_type(user_storage);
149
+
150
+ // Roll species and rarity
151
+ let mut gen = random::new_generator(rng, ctx);
152
+ let (species, rarity) = roll_pet(&mut gen, egg_type);
153
+
154
+ // Allocate a globally unique pet_id — no on-chain counter needed.
155
+ let pet_id = ctx.fresh_object_address();
156
+
157
+ // Pet lands in ranch: no slot assigned. Player calls assign_slot() to activate.
158
+ // mint() internally calls ensure_has_not + set, preventing duplicate pet_ids.
159
+ pet::mint(user_storage, pet_id, species, rarity, 1, 0, 50, MAX_SATIETY, now, now, ctx);
160
+
161
+ pet_hatch::delete(user_storage, ctx);
162
+ }
163
+
164
+ // ─── Feeding ──────────────────────────────────────────────────────────────
165
+
166
+ /// Feed any owned pet (in ranch or active slot) with `amount` units of `crop_type`.
167
+ /// crop_type: 1=Wheat 2=Corn 3=Carrot 4=Pumpkin
168
+ public entry fun feed_pet(
169
+ dapp_storage: &DappStorage,
170
+ user_storage: &mut UserStorage,
171
+ pet_id: address,
172
+ crop_type: u8,
173
+ amount: u64,
174
+ clock: &Clock,
175
+ ctx: &mut TxContext,
176
+ ) {
177
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
178
+ error::not_registered(profile::has(user_storage));
179
+ error::invalid_crop_type(crop_type >= 1 && crop_type <= 4);
180
+ error::pet_not_found(pet::has(user_storage, pet_id));
181
+ error::insufficient_crops(amount > 0);
182
+
183
+ burn_crops(user_storage, crop_type, amount, ctx);
184
+
185
+ let species = pet::get_species(user_storage, pet_id);
186
+ let is_favorite = is_favorite_food(species, crop_type);
187
+
188
+ let now = sui::clock::timestamp_ms(clock);
189
+ let fed_at = pet::get_fed_at(user_storage, pet_id);
190
+ let current_satiety = pet::get_satiety(user_storage, pet_id);
191
+ let drained = compute_satiety_drain(fed_at, now);
192
+ let after_drain = if (current_satiety > drained) { current_satiety - drained } else { 0 };
193
+
194
+ let (satiety_per, happiness_per, xp_per) = if (is_favorite) {
195
+ (SATIETY_RESTORE_FAVORITE, HAPPINESS_GAIN_FAVORITE, XP_GAIN_FAVORITE)
196
+ } else {
197
+ (SATIETY_RESTORE_OTHER, HAPPINESS_GAIN_OTHER, XP_GAIN_OTHER)
198
+ };
199
+
200
+ let new_satiety = clamp_u8(after_drain + (satiety_per as u8) * (amount as u8), MAX_SATIETY);
201
+ let old_happiness = pet::get_happiness(user_storage, pet_id);
202
+ let new_happiness = clamp_u8(old_happiness + happiness_per * (amount as u8), MAX_HAPPINESS);
203
+
204
+ let old_xp = pet::get_xp(user_storage, pet_id);
205
+ let old_level = pet::get_level(user_storage, pet_id);
206
+ let added_xp = xp_per * (amount as u32);
207
+ let (new_level, new_xp) = compute_level_up(old_level, old_xp, added_xp);
208
+
209
+ let rarity = pet::get_rarity(user_storage, pet_id);
210
+ let born_at = pet::get_born_at(user_storage, pet_id);
211
+ pet::set(
212
+ user_storage, pet_id,
213
+ species, rarity, new_level, new_xp, new_happiness, new_satiety,
214
+ now, born_at,
215
+ ctx,
216
+ );
217
+ }
218
+
219
+ // ─── Slot management ─────────────────────────────────────────────────────
220
+
221
+ /// Purchase an additional active slot (up to MAX_PET_SLOTS).
222
+ public entry fun buy_pet_slot(
223
+ dapp_storage: &DappStorage,
224
+ user_storage: &mut UserStorage,
225
+ ctx: &mut TxContext,
226
+ ) {
227
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
228
+ error::not_registered(profile::has(user_storage));
229
+
230
+ let current = if (pet_slots::has(user_storage)) {
231
+ pet_slots::get(user_storage)
232
+ } else {
233
+ DEFAULT_PET_SLOTS
234
+ };
235
+ error::max_pet_slots_reached(current < MAX_PET_SLOTS);
236
+
237
+ let price = if (current == 1) {
238
+ pet_config::get_slot2_price(dapp_storage)
239
+ } else {
240
+ pet_config::get_slot3_price(dapp_storage)
241
+ };
242
+ error::insufficient_gold(gold::get(user_storage) >= price);
243
+ gold::sub(user_storage, price, ctx);
244
+ pet_slots::set(user_storage, current + 1, ctx);
245
+ }
246
+
247
+ /// Assign a ranch pet to an active display slot.
248
+ /// If the pet is already in another slot it is moved (old slot freed).
249
+ /// Aborts if `slot` is out of range or already occupied by a different pet.
250
+ public entry fun assign_slot(
251
+ dapp_storage: &DappStorage,
252
+ user_storage: &mut UserStorage,
253
+ pet_id: address,
254
+ slot: u8,
255
+ ctx: &mut TxContext,
256
+ ) {
257
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
258
+ error::not_registered(profile::has(user_storage));
259
+ error::pet_not_found(pet::has(user_storage, pet_id));
260
+
261
+ let slots_owned = if (pet_slots::has(user_storage)) {
262
+ pet_slots::get(user_storage)
263
+ } else {
264
+ DEFAULT_PET_SLOTS
265
+ };
266
+ error::invalid_pet_slot(slot < slots_owned);
267
+ error::pet_slot_occupied(!pet_slot_index::has(user_storage, slot));
268
+
269
+ // If this pet is already assigned to a different slot, free that slot first.
270
+ let (found, old_slot) = find_pet_slot(user_storage, pet_id, slots_owned);
271
+ if (found) {
272
+ pet_slot_index::delete(user_storage, old_slot, ctx);
273
+ };
274
+
275
+ pet_slot_index::set(user_storage, slot, pet_id, ctx);
276
+ }
277
+
278
+ /// Move an active pet back to the ranch (free its display slot).
279
+ public entry fun unassign_slot(
280
+ dapp_storage: &DappStorage,
281
+ user_storage: &mut UserStorage,
282
+ slot: u8,
283
+ ctx: &mut TxContext,
284
+ ) {
285
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
286
+ error::not_registered(profile::has(user_storage));
287
+ error::pet_slot_empty(pet_slot_index::has(user_storage, slot));
288
+
289
+ pet_slot_index::delete(user_storage, slot, ctx);
290
+ }
291
+
292
+ /// Permanently release (delete) a pet — works for ranch pets and active-slot pets alike.
293
+ public entry fun dismiss_pet(
294
+ dapp_storage: &DappStorage,
295
+ user_storage: &mut UserStorage,
296
+ pet_id: address,
297
+ ctx: &mut TxContext,
298
+ ) {
299
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
300
+ error::not_registered(profile::has(user_storage));
301
+ error::pet_not_found(pet::has(user_storage, pet_id));
302
+
303
+ // Free the display slot if the pet is currently active.
304
+ let slots_owned = if (pet_slots::has(user_storage)) {
305
+ pet_slots::get(user_storage)
306
+ } else {
307
+ DEFAULT_PET_SLOTS
308
+ };
309
+ let (found, slot) = find_pet_slot(user_storage, pet_id, slots_owned);
310
+ if (found) {
311
+ pet_slot_index::delete(user_storage, slot, ctx);
312
+ };
313
+
314
+ pet::delete(user_storage, pet_id, ctx);
315
+ }
316
+
317
+ // ─── Pet NFT marketplace ─────────────────────────────────────────────────
318
+
319
+ /// List any owned pet (ranch or active slot) for sale.
320
+ /// The active slot (if any) is freed immediately. Satiety is reset so the
321
+ /// listing always shows a "full" pet — cancel restores the pet to ranch.
322
+ public entry fun list_pet(
323
+ dapp_storage: &DappStorage,
324
+ user_storage: &mut UserStorage,
325
+ pet_id: address,
326
+ price: u64,
327
+ ctx: &mut TxContext,
328
+ ) {
329
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
330
+ error::not_registered(profile::has(user_storage));
331
+ error::pet_not_found(pet::has(user_storage, pet_id));
332
+
333
+ // Free active slot if the pet is currently displayed.
334
+ let slots_owned = if (pet_slots::has(user_storage)) {
335
+ pet_slots::get(user_storage)
336
+ } else {
337
+ DEFAULT_PET_SLOTS
338
+ };
339
+ let (found, slot) = find_pet_slot(user_storage, pet_id, slots_owned);
340
+ if (found) {
341
+ pet_slot_index::delete(user_storage, slot, ctx);
342
+ };
343
+
344
+ // Reset satiety to MAX so the listing always shows a healthy pet.
345
+ pet::set_satiety(user_storage, pet_id, MAX_SATIETY, ctx);
346
+
347
+ // take_record removes pet from storage and creates a shared Listing.
348
+ pet::list<SUI>(user_storage, pet_id, price, std::option::none(), ctx);
349
+ }
350
+
351
+ /// Buy a listed pet. The pet lands in the buyer's ranch.
352
+ /// Call assign_slot() afterwards to put it into an active display slot.
353
+ /// Satiety is reset to MAX so the new owner gets a fresh start.
354
+ public entry fun buy_pet(
355
+ dh: &DappHub,
356
+ dapp_storage: &mut DappStorage,
357
+ buyer_storage: &mut UserStorage,
358
+ listing: dapp_service::Listing<SUI>,
359
+ payment: Coin<SUI>,
360
+ ctx: &mut TxContext,
361
+ ) {
362
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
363
+ error::not_registered(profile::has(buyer_storage));
364
+
365
+ // Decode pet_id before the listing is consumed.
366
+ // record_key layout: [TABLE_NAME_bytes, bcs(pet_id)]
367
+ let record_key = dapp_service::listing_record_key(&listing);
368
+ let key_bytes = *record_key.borrow(1);
369
+ let mut bcs = sui::bcs::new(key_bytes);
370
+ let pet_id = sui::bcs::peel_address(&mut bcs);
371
+
372
+ // buy_record writes the pet into buyer_storage keyed by pet_id.
373
+ let change = pet::buy<SUI>(dh, dapp_storage, listing, buyer_storage, payment, ctx);
374
+
375
+ // Reset satiety — buyer gets a fresh start.
376
+ pet::set_satiety(buyer_storage, pet_id, MAX_SATIETY, ctx);
377
+
378
+ return_change(change, ctx);
379
+ }
380
+
381
+ /// Cancel a pet listing and return the pet to the seller's ranch.
382
+ /// No slot is auto-assigned — call assign_slot() to reactivate.
383
+ public entry fun cancel_pet_listing(
384
+ user_storage: &mut UserStorage,
385
+ listing: dapp_service::Listing<SUI>,
386
+ ctx: &mut TxContext,
387
+ ) {
388
+ // restore_record writes the pet back at pet_id in user_storage.
389
+ // Pet lands in ranch — no slot assignment needed.
390
+ pet::cancel_listing<SUI>(listing, user_storage, ctx);
391
+ }
392
+
393
+ // ─── Helpers (private) ────────────────────────────────────────────────────
394
+
395
+ fun egg_balance(user_storage: &UserStorage, egg_type: u8): u64 {
396
+ if (egg_type == EGG_COMMON) { if (common_egg::has(user_storage)) { common_egg::get(user_storage) } else { 0 } }
397
+ else if (egg_type == EGG_RARE) { if (rare_egg::has(user_storage)) { rare_egg::get(user_storage) } else { 0 } }
398
+ else { if (seasonal_egg::has(user_storage)) { seasonal_egg::get(user_storage) } else { 0 } }
399
+ }
400
+
401
+ fun deduct_egg(user_storage: &mut UserStorage, egg_type: u8, amount: u64, ctx: &mut TxContext) {
402
+ if (egg_type == EGG_COMMON) { common_egg::sub(user_storage, amount, ctx) }
403
+ else if (egg_type == EGG_RARE) { rare_egg::sub(user_storage, amount, ctx) }
404
+ else { seasonal_egg::sub(user_storage, amount, ctx) }
405
+ }
406
+
407
+ fun hatch_duration_ms(dapp_storage: &DappStorage, egg_type: u8): u64 {
408
+ if (egg_type == EGG_COMMON) { pet_config::get_common_hatch_ms(dapp_storage) }
409
+ else if (egg_type == EGG_RARE) { pet_config::get_rare_hatch_ms(dapp_storage) }
410
+ else { pet_config::get_seasonal_hatch_ms(dapp_storage) }
411
+ }
412
+
413
+ /// Scan all owned slots to find which slot (if any) contains `pet_id`.
414
+ /// Returns (true, slot_index) or (false, 0).
415
+ /// MAX_PET_SLOTS is 3, so this loop is O(1) in practice.
416
+ fun find_pet_slot(user_storage: &UserStorage, pet_id: address, slots_owned: u8): (bool, u8) {
417
+ let mut i = 0u8;
418
+ while (i < slots_owned) {
419
+ if (pet_slot_index::has(user_storage, i) && pet_slot_index::get(user_storage, i) == pet_id) {
420
+ return (true, i)
421
+ };
422
+ i = i + 1;
423
+ };
424
+ (false, 0)
425
+ }
426
+
427
+ fun roll_pet(gen: &mut sui::random::RandomGenerator, egg_type: u8): (u8, u8) {
428
+ let roll_s = random::generate_u8_in_range(gen, 0, 99);
429
+ let roll_r = random::generate_u8_in_range(gen, 0, 99);
430
+
431
+ if (egg_type == EGG_COMMON) {
432
+ let species = if (roll_s < 70) { SPECIES_BUNNY } else { SPECIES_CHICK };
433
+ (species, RARITY_COMMON)
434
+ } else if (egg_type == EGG_RARE) {
435
+ let species = if (roll_s < 60) { SPECIES_FOX } else if (roll_s < 95) { SPECIES_DEER } else { SPECIES_DRAGON };
436
+ let rarity = if (roll_r < 70) { RARITY_COMMON } else if (roll_r < 95) { RARITY_UNCOMMON } else { RARITY_RARE };
437
+ (species, rarity)
438
+ } else {
439
+ let species = if (roll_s < 60) { SPECIES_FOX } else if (roll_s < 95) { SPECIES_DEER } else { SPECIES_DRAGON };
440
+ let rarity = if (roll_r < 50) { RARITY_UNCOMMON } else { RARITY_RARE };
441
+ (species, rarity)
442
+ }
443
+ }
444
+
445
+ /// Bunny=Carrot(3), Chick=Wheat(1), Fox=Pumpkin(4), Deer=Corn(2), Dragon=any
446
+ fun is_favorite_food(species: u8, crop_type: u8): bool {
447
+ if (species == SPECIES_BUNNY) { crop_type == 3 }
448
+ else if (species == SPECIES_CHICK) { crop_type == 1 }
449
+ else if (species == SPECIES_FOX) { crop_type == 4 }
450
+ else if (species == SPECIES_DEER) { crop_type == 2 }
451
+ else { true }
452
+ }
453
+
454
+ fun compute_satiety_drain(fed_at: u64, now: u64): u8 {
455
+ if (now <= fed_at) return 0;
456
+ let elapsed = now - fed_at;
457
+ let intervals = elapsed / SATIETY_DRAIN_INTERVAL_MS;
458
+ let drain = intervals * (SATIETY_DRAIN_AMOUNT as u64);
459
+ if (drain >= (MAX_SATIETY as u64)) { MAX_SATIETY } else { drain as u8 }
460
+ }
461
+
462
+ fun compute_level_up(old_level: u8, old_xp: u32, added_xp: u32): (u8, u32) {
463
+ let mut level = old_level;
464
+ let mut xp = old_xp + added_xp;
465
+ while (level < MAX_LEVEL && xp >= XP_PER_LEVEL) {
466
+ xp = xp - XP_PER_LEVEL;
467
+ level = level + 1;
468
+ };
469
+ if (level >= MAX_LEVEL) { xp = 0 };
470
+ (level, xp)
471
+ }
472
+
473
+ fun clamp_u8(val: u8, max: u8): u8 {
474
+ if (val > max) { max } else { val }
475
+ }
476
+
477
+ fun burn_crops(user_storage: &mut UserStorage, crop_type: u8, amount: u64, ctx: &mut TxContext) {
478
+ use harvest::wheat;
479
+ use harvest::corn;
480
+ use harvest::carrot;
481
+ use harvest::pumpkin;
482
+ if (crop_type == 1) { wheat::sub(user_storage, amount, ctx) }
483
+ else if (crop_type == 2) { corn::sub(user_storage, amount, ctx) }
484
+ else if (crop_type == 3) { carrot::sub(user_storage, amount, ctx) }
485
+ else { pumpkin::sub(user_storage, amount, ctx) }
486
+ }
487
+
488
+ fun return_change(change: Coin<SUI>, ctx: &TxContext) {
489
+ if (coin::value(&change) > 0) {
490
+ sui::transfer::public_transfer(change, ctx.sender());
491
+ } else {
492
+ coin::destroy_zero(change);
493
+ };
494
+ }
495
+ }
@@ -0,0 +1,70 @@
1
+ module harvest::season_system {
2
+ use sui::clock::Clock;
3
+ use dubhe::dapp_service::{DappStorage, UserStorage};
4
+ use dubhe::dapp_service;
5
+ use dubhe::dapp_system;
6
+ use harvest::dapp_key::DappKey;
7
+ use harvest::migrate;
8
+ use harvest::error;
9
+ use harvest::season_config;
10
+ use harvest::season_stats;
11
+ use harvest::trophy;
12
+ use harvest::profile;
13
+
14
+ #[error]
15
+ const ENotAdmin: vector<u8> = b"Caller is not the DApp admin";
16
+
17
+ /// Admin: start a new season with a bonus crop type.
18
+ public entry fun start_season(
19
+ dapp_storage: &mut DappStorage,
20
+ bonus_crop: u8,
21
+ duration_ms: u64,
22
+ clock: &Clock,
23
+ ctx: &mut TxContext,
24
+ ) {
25
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
26
+ assert!(ctx.sender() == dapp_service::dapp_admin(dapp_storage), ENotAdmin);
27
+
28
+ let now = sui::clock::timestamp_ms(clock);
29
+ let current_id = season_config::get_season_id(dapp_storage);
30
+ season_config::set(dapp_storage, current_id + 1, now + duration_ms, bonus_crop);
31
+ }
32
+
33
+ /// Admin: end the current season early.
34
+ public entry fun end_season(
35
+ dapp_storage: &mut DappStorage,
36
+ ctx: &TxContext,
37
+ ) {
38
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
39
+ assert!(ctx.sender() == dapp_service::dapp_admin(dapp_storage), ENotAdmin);
40
+
41
+ let season_id = season_config::get_season_id(dapp_storage);
42
+ let bonus_crop = season_config::get_bonus_crop(dapp_storage);
43
+ season_config::set(dapp_storage, season_id, 0, bonus_crop);
44
+ }
45
+
46
+ /// Admin: mint a season trophy for a top-ranked player.
47
+ public entry fun award_trophy(
48
+ dapp_storage: &DappStorage,
49
+ user_storage: &mut UserStorage,
50
+ rank: u32,
51
+ ctx: &mut TxContext,
52
+ ) {
53
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
54
+ assert!(ctx.sender() == dapp_service::dapp_admin(dapp_storage), ENotAdmin);
55
+ error::not_registered(profile::has(user_storage));
56
+
57
+ let season_id = season_config::get_season_id(dapp_storage);
58
+ let earned = if (season_stats::has(user_storage)) {
59
+ season_stats::get(user_storage)
60
+ } else {
61
+ 0
62
+ };
63
+
64
+ trophy::set(user_storage, season_id, rank, earned, ctx);
65
+
66
+ if (season_stats::has(user_storage)) {
67
+ season_stats::set(user_storage, 0, ctx);
68
+ };
69
+ }
70
+ }
@@ -0,0 +1,112 @@
1
+ module harvest::shop_system {
2
+ use dubhe::dapp_service::{DappStorage, UserStorage};
3
+ use dubhe::dapp_system;
4
+ use harvest::dapp_key::DappKey;
5
+ use harvest::migrate;
6
+ use harvest::error;
7
+ use harvest::gold;
8
+ use harvest::wheat_seed;
9
+ use harvest::corn_seed;
10
+ use harvest::carrot_seed;
11
+ use harvest::pumpkin_seed;
12
+ use harvest::wheat;
13
+ use harvest::corn;
14
+ use harvest::carrot;
15
+ use harvest::pumpkin;
16
+ use harvest::profile;
17
+ use harvest::shop_config;
18
+
19
+ const CROP_WHEAT: u8 = 1;
20
+ const CROP_CORN: u8 = 2;
21
+ const CROP_CARROT: u8 = 3;
22
+ const CROP_PUMPKIN: u8 = 4;
23
+
24
+ /// Buy `count` seeds of `crop_type` from the system shop using gold.
25
+ /// Seeds are stored in the dedicated *_seed resource (separate from harvested crops).
26
+ public entry fun buy_seeds(
27
+ dapp_storage: &DappStorage,
28
+ user_storage: &mut UserStorage,
29
+ crop_type: u8,
30
+ count: u64,
31
+ ctx: &mut TxContext,
32
+ ) {
33
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
34
+ error::not_registered(profile::has(user_storage));
35
+ error::invalid_crop_type(crop_type >= CROP_WHEAT && crop_type <= CROP_PUMPKIN);
36
+ error::insufficient_crops(count > 0);
37
+
38
+ let price_per_seed = seed_price(dapp_storage, crop_type);
39
+ let total_cost = price_per_seed * count;
40
+ error::insufficient_gold(gold::get(user_storage) >= total_cost);
41
+ gold::sub(user_storage, total_cost, ctx);
42
+ mint_seeds(user_storage, crop_type, count, ctx);
43
+ }
44
+
45
+ /// Purchase an additional farm plot (up to 12 total).
46
+ public entry fun buy_extra_plot(
47
+ dapp_storage: &DappStorage,
48
+ user_storage: &mut UserStorage,
49
+ ctx: &mut TxContext,
50
+ ) {
51
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
52
+ error::not_registered(profile::has(user_storage));
53
+
54
+ let plots_owned = profile::get_plots_owned(user_storage);
55
+ error::max_plots_reached(plots_owned < 12);
56
+
57
+ let price = shop_config::get_extra_plot_price(dapp_storage);
58
+ error::insufficient_gold(gold::get(user_storage) >= price);
59
+ gold::sub(user_storage, price, ctx);
60
+ profile::set_plots_owned(user_storage, plots_owned + 1, ctx);
61
+ }
62
+
63
+ /// Sell harvested crops back to the system at the base gold rate.
64
+ /// Only crop resources (not seeds) can be sold.
65
+ public entry fun sell_crops(
66
+ dapp_storage: &DappStorage,
67
+ user_storage: &mut UserStorage,
68
+ crop_type: u8,
69
+ amount: u64,
70
+ ctx: &mut TxContext,
71
+ ) {
72
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
73
+ error::not_registered(profile::has(user_storage));
74
+ error::invalid_crop_type(crop_type >= CROP_WHEAT && crop_type <= CROP_PUMPKIN);
75
+ error::insufficient_crops(amount > 0);
76
+
77
+ burn_crops(user_storage, crop_type, amount, ctx);
78
+ gold::add(user_storage, sell_price(crop_type) * amount, ctx);
79
+ }
80
+
81
+ // ─── Helpers ──────────────────────────────────────────────────────────────
82
+
83
+ fun seed_price(dapp_storage: &DappStorage, crop_type: u8): u64 {
84
+ if (crop_type == CROP_WHEAT) { shop_config::get_wheat_seed_price(dapp_storage) }
85
+ else if (crop_type == CROP_CORN) { shop_config::get_corn_seed_price(dapp_storage) }
86
+ else if (crop_type == CROP_CARROT) { shop_config::get_carrot_seed_price(dapp_storage) }
87
+ else { shop_config::get_pumpkin_seed_price(dapp_storage) }
88
+ }
89
+
90
+ fun sell_price(crop_type: u8): u64 {
91
+ if (crop_type == CROP_WHEAT) { 8 }
92
+ else if (crop_type == CROP_CORN) { 35 }
93
+ else if (crop_type == CROP_CARROT) { 120 }
94
+ else { 100 }
95
+ }
96
+
97
+ /// Mint seeds into the dedicated seed resource (not the crop resource).
98
+ fun mint_seeds(user_storage: &mut UserStorage, crop_type: u8, amount: u64, ctx: &mut TxContext) {
99
+ if (crop_type == CROP_WHEAT) { wheat_seed::add(user_storage, amount, ctx) }
100
+ else if (crop_type == CROP_CORN) { corn_seed::add(user_storage, amount, ctx) }
101
+ else if (crop_type == CROP_CARROT) { carrot_seed::add(user_storage, amount, ctx) }
102
+ else { pumpkin_seed::add(user_storage, amount, ctx) }
103
+ }
104
+
105
+ /// Burn harvested crops (crop resource, not seeds).
106
+ fun burn_crops(user_storage: &mut UserStorage, crop_type: u8, amount: u64, ctx: &mut TxContext) {
107
+ if (crop_type == CROP_WHEAT) { wheat::sub(user_storage, amount, ctx) }
108
+ else if (crop_type == CROP_CORN) { corn::sub(user_storage, amount, ctx) }
109
+ else if (crop_type == CROP_CARROT) { carrot::sub(user_storage, amount, ctx) }
110
+ else { pumpkin::sub(user_storage, amount, ctx) }
111
+ }
112
+ }