create-dubhe 1.2.0-pre.99 → 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 (360) 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 +4 -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 +4 -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/sources/codegen/dapp_key.move +45 -31
  297. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/error.move +10 -0
  298. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/genesis.move +30 -13
  299. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/init_test.move +19 -14
  300. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter1.move +30 -20
  301. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/resources/counter2.move +35 -24
  302. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/user_storage_init.move +26 -0
  303. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/scripts/deploy_hook.move +6 -10
  304. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/systems/counter.move +7 -20
  305. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/tests/counter.move +14 -27
  306. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/Move.lock +33 -30
  307. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/Move.toml +4 -3
  308. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/dapp_key.move +45 -31
  309. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/error.move +170 -0
  310. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/genesis.move +16 -13
  311. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/init_test.move +8 -14
  312. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/account_key.move +1 -3
  313. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/dapp_service.move +1776 -137
  314. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/data_key.move +1 -20
  315. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/events.move +864 -25
  316. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/scripts/deploy_hook.move +15 -16
  317. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/scripts/migrate.move +0 -3
  318. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/address_system.move +25 -17
  319. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/dapp_system.move +2802 -343
  320. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/utils.move +1 -1
  321. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/address.move +173 -55
  322. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/dapp_test.move +769 -0
  323. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/fee_test.move +2965 -0
  324. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/integration_test.move +303 -0
  325. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/listing_test.move +1422 -0
  326. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/scene_session_test.move +269 -0
  327. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/session_test.move +624 -0
  328. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/storage_test.move +700 -0
  329. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/typed_object_test.move +177 -0
  330. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/typed_scene_test.move +452 -0
  331. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/user_storage_test.move +160 -0
  332. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/utils/math.move +4 -3
  333. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/utils/type_info.move +2 -2
  334. package/templates/101/sui-template/packages/contracts/src/counter/Move.lock +0 -41
  335. package/templates/101/sui-template/packages/contracts/src/counter/Published.toml +0 -9
  336. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/errors.move +0 -12
  337. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/errors.move +0 -140
  338. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_config.move +0 -186
  339. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_state.move +0 -306
  340. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_metadata.move +0 -396
  341. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dubhe_config.move +0 -246
  342. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/core/dapp_store.move +0 -29
  343. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/session_system.move +0 -44
  344. package/templates/contract/sui-template/src/dubhe/sources/codegen/errors.move +0 -140
  345. package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dapp_fee_config.move +0 -186
  346. package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dapp_fee_state.move +0 -306
  347. package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dapp_metadata.move +0 -396
  348. package/templates/contract/sui-template/src/dubhe/sources/codegen/resources/dubhe_config.move +0 -246
  349. package/templates/contract/sui-template/src/dubhe/sources/core/dapp_store.move +0 -29
  350. package/templates/contract/sui-template/src/dubhe/sources/systems/session_system.move +0 -44
  351. package/templates/nextjs/sui-template/packages/contracts/src/counter/Move.lock +0 -47
  352. package/templates/nextjs/sui-template/packages/contracts/src/counter/Published.toml +0 -9
  353. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/errors.move +0 -12
  354. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/errors.move +0 -140
  355. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_config.move +0 -186
  356. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_fee_state.move +0 -306
  357. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dapp_metadata.move +0 -396
  358. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/resources/dubhe_config.move +0 -246
  359. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/core/dapp_store.move +0 -29
  360. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/session_system.move +0 -44
@@ -0,0 +1,342 @@
1
+ /**
2
+ * e2e-session.ts — Session-key delegated duel flow on localnet.
3
+ *
4
+ * Usage:
5
+ * cd templates/nextjs/sui-card-duel/packages/contracts
6
+ * pnpm tsx scripts/e2e-session.ts
7
+ *
8
+ * Player B never signs game actions with the main wallet: a session key is
9
+ * activated once, then accept_duel / attack / finish_duel / cleanup are all
10
+ * signed by the session key while every on-chain identity (permit
11
+ * participant, scene fields, profile, gold) resolves to B's canonical owner
12
+ * (the main wallet). Finally the session is deactivated and a further
13
+ * session-signed action is expected to fail.
14
+ */
15
+
16
+ import {
17
+ Dubhe,
18
+ Transaction,
19
+ getFullnodeUrl,
20
+ Ed25519Keypair,
21
+ loadMetadata
22
+ } from '@0xobelisk/sui-client';
23
+ import { PackageId, DappHubId, DappStorageId, FrameworkPackageId } from './config.ts';
24
+
25
+ const NETWORK = 'localnet' as const;
26
+ const GRAPHQL = 'http://127.0.0.1:4000/graphql';
27
+ const CLOCK = '0x6';
28
+ const STAKE = 50n;
29
+ const SESSION_DURATION_MS = 60n * 60n * 1000n; // 1 hour
30
+
31
+ function newDubhe(metadata: any, secretKey: string) {
32
+ return new Dubhe({
33
+ networkType: NETWORK,
34
+ packageId: PackageId,
35
+ metadata,
36
+ secretKey,
37
+ suiRpcUrl: getFullnodeUrl(NETWORK),
38
+ dappHubId: DappHubId,
39
+ dappStorageId: DappStorageId,
40
+ frameworkPackageId: FrameworkPackageId
41
+ });
42
+ }
43
+
44
+ async function gql(query: string): Promise<any> {
45
+ const res = await fetch(GRAPHQL, {
46
+ method: 'POST',
47
+ headers: { 'Content-Type': 'application/json' },
48
+ body: JSON.stringify({ query })
49
+ });
50
+ const json = await res.json();
51
+ if (json.errors) throw new Error(JSON.stringify(json.errors));
52
+ return json.data;
53
+ }
54
+
55
+ async function send(dubhe: Dubhe, label: string, build: (tx: Transaction) => void) {
56
+ const tx = new Transaction();
57
+ build(tx);
58
+ const result = await dubhe.signAndSendTxn({ tx });
59
+ const status = (result as any).effects?.status?.status;
60
+ if (status !== 'success') {
61
+ throw new Error(`${label} failed: ${JSON.stringify((result as any).effects?.status)}`);
62
+ }
63
+ await dubhe.waitForTransaction(result.digest);
64
+ console.log(` ✓ ${label} (${result.digest})`);
65
+ return result as any;
66
+ }
67
+
68
+ /** Expect the transaction to fail (abort or rejection). */
69
+ async function mustFail(dubhe: Dubhe, label: string, build: (tx: Transaction) => void) {
70
+ try {
71
+ const tx = new Transaction();
72
+ build(tx);
73
+ const result = await dubhe.signAndSendTxn({ tx });
74
+ const status = (result as any).effects?.status?.status;
75
+ if (status === 'success') {
76
+ throw new Error(`${label}: expected failure but transaction succeeded`);
77
+ }
78
+ console.log(` ✓ ${label} rejected on-chain as expected`);
79
+ } catch (err: any) {
80
+ if (String(err.message ?? err).includes('expected failure')) throw err;
81
+ console.log(` ✓ ${label} rejected as expected (${String(err.message ?? err).slice(0, 80)}…)`);
82
+ }
83
+ }
84
+
85
+ async function main() {
86
+ const metadata = await loadMetadata(NETWORK, PackageId);
87
+
88
+ const keyA = new Ed25519Keypair();
89
+ const keyB = new Ed25519Keypair();
90
+ const keyS = new Ed25519Keypair(); // B's session key
91
+ const A = newDubhe(metadata, keyA.getSecretKey());
92
+ const B = newDubhe(metadata, keyB.getSecretKey());
93
+ const S = newDubhe(metadata, keyS.getSecretKey());
94
+ const addrA = A.getAddress();
95
+ const addrB = B.getAddress();
96
+ const addrS = S.getAddress();
97
+ console.log(`Player A (main): ${addrA}`);
98
+ console.log(`Player B (main): ${addrB}`);
99
+ console.log(`B session key: ${addrS}`);
100
+
101
+ // ── 1. Fund all three wallets (session key needs gas of its own) ──────────
102
+ console.log('\n[1] Faucet');
103
+ await A.requestFaucet(addrA, NETWORK);
104
+ await B.requestFaucet(addrB, NETWORK);
105
+ await S.requestFaucet(addrS, NETWORK);
106
+ await new Promise((r) => setTimeout(r, 2000));
107
+
108
+ // ── 2. Onboarding with the main wallets ──────────────────────────────────
109
+ console.log('\n[2] Onboarding (main wallets)');
110
+ const userStorageIds: Record<string, string> = {};
111
+ for (const [who, dubhe] of [
112
+ ['A', A],
113
+ ['B', B]
114
+ ] as const) {
115
+ const result = await send(dubhe, `init_user_storage (${who})`, (tx) => {
116
+ tx.moveCall({
117
+ target: `${PackageId}::user_storage_init::init_user_storage`,
118
+ arguments: [tx.object(DappHubId), tx.object(DappStorageId)]
119
+ });
120
+ });
121
+ const usId = (result.objectChanges ?? []).find(
122
+ (c: any) => c.type === 'created' && c.objectType?.endsWith('::dapp_service::UserStorage')
123
+ )?.objectId;
124
+ if (!usId) throw new Error(`UserStorage not found in init tx for ${who}`);
125
+ userStorageIds[who] = usId;
126
+ await send(dubhe, `register (${who})`, (tx) => {
127
+ tx.moveCall({
128
+ target: `${PackageId}::player_system::register`,
129
+ arguments: [tx.object(DappStorageId), tx.object(usId)]
130
+ });
131
+ });
132
+ }
133
+ const usA = userStorageIds['A'];
134
+ const usB = userStorageIds['B'];
135
+
136
+ // ── 3. B activates a session key (the only main-wallet signature left) ───
137
+ console.log('\n[3] activate_session (B main wallet delegates to session key)');
138
+ await send(B, 'activate_session (B → S)', (tx) => {
139
+ tx.moveCall({
140
+ target: `${FrameworkPackageId}::dapp_system::activate_session`,
141
+ typeArguments: [`${PackageId}::dapp_key::DappKey`],
142
+ arguments: [
143
+ tx.object(DappHubId),
144
+ tx.object(usB),
145
+ tx.pure.address(addrS),
146
+ tx.pure.u64(SESSION_DURATION_MS),
147
+ tx.object(CLOCK)
148
+ ]
149
+ });
150
+ });
151
+
152
+ // ── 4. Starter decks via the indexer ─────────────────────────────────────
153
+ console.log('\n[4] Starter decks (via indexer)');
154
+ const readDeck = async (addr: string): Promise<string[]> => {
155
+ for (let i = 0; i < 30; i++) {
156
+ const data = await gql(`{ decks { nodes { entityId cardIds } } }`);
157
+ const row = data.decks.nodes.find((n: any) => n.entityId === addr);
158
+ const ids = row?.cardIds;
159
+ if (Array.isArray(ids) && ids.length === 5) return ids.map(String);
160
+ if (typeof ids === 'string') {
161
+ const parsed = JSON.parse(ids);
162
+ if (Array.isArray(parsed) && parsed.length === 5) return parsed.map(String);
163
+ }
164
+ await new Promise((r) => setTimeout(r, 2000));
165
+ }
166
+ throw new Error(`deck for ${addr} not indexed in time`);
167
+ };
168
+ const deckA = await readDeck(addrA);
169
+ const deckB = await readDeck(addrB);
170
+ console.log(` Deck A: ${deckA.length} cards`);
171
+ console.log(` Deck B: ${deckB.length} cards`);
172
+
173
+ // ── 5. A challenges B (main wallet) ──────────────────────────────────────
174
+ console.log('\n[5] create_duel (A main wallet)');
175
+ const createResult = await send(A, `create_duel (A → B, stake ${STAKE})`, (tx) => {
176
+ tx.moveCall({
177
+ target: `${PackageId}::duel_system::create_duel`,
178
+ arguments: [
179
+ tx.object(DappStorageId),
180
+ tx.object(usA),
181
+ tx.pure.address(addrB),
182
+ tx.pure.u64(STAKE),
183
+ tx.object(CLOCK)
184
+ ]
185
+ });
186
+ });
187
+ const created = (createResult.objectChanges ?? []).filter((c: any) => c.type === 'created');
188
+ const sceneId = created.find((c: any) => c.objectType?.includes('SceneStorage<'))?.objectId;
189
+ const permitId = created.find((c: any) => c.objectType?.includes('ScenePermit<'))?.objectId;
190
+ if (!sceneId || !permitId) throw new Error('scene/permit not found in object changes');
191
+ console.log(` Scene: ${sceneId}`);
192
+ console.log(` Permit: ${permitId}`);
193
+
194
+ // ── 6. B's session key plays the whole match ─────────────────────────────
195
+ // accept_duel must register B's canonical owner (main wallet), not the
196
+ // session address, so the duel below sees addrB as the opponent.
197
+ console.log('\n[6] Session-signed match (B never touches the main wallet)');
198
+ await send(S, 'accept_duel (B via session key)', (tx) => {
199
+ tx.moveCall({
200
+ target: `${PackageId}::duel_system::accept_duel`,
201
+ arguments: [
202
+ tx.object(DappStorageId),
203
+ tx.object(usB),
204
+ tx.object(permitId),
205
+ tx.object(sceneId),
206
+ tx.object(CLOCK)
207
+ ]
208
+ });
209
+ });
210
+
211
+ const attack = (dubhe: Dubhe, mine: string, theirs: string, cardId: string, label: string) =>
212
+ send(dubhe, label, (tx) => {
213
+ tx.moveCall({
214
+ target: `${PackageId}::duel_system::attack`,
215
+ arguments: [
216
+ tx.object(DappStorageId),
217
+ tx.object(mine),
218
+ tx.object(theirs),
219
+ tx.object(permitId),
220
+ tx.object(sceneId),
221
+ tx.pure.address(cardId),
222
+ tx.object(CLOCK)
223
+ ]
224
+ });
225
+ });
226
+
227
+ // Challenger (A) moves first; B's turns are all session-signed reactive
228
+ // writes against A's UserStorage.
229
+ await attack(A, usA, usB, deckA[0], 'A strikes (12 dmg, B: 30→18)');
230
+ await attack(S, usB, usA, deckB[0], 'B strikes via session (12 dmg, A: 30→18)');
231
+ await attack(A, usA, usB, deckA[1], 'A strikes (12 dmg, B: 18→6)');
232
+ await attack(S, usB, usA, deckB[3], 'B fireballs via session (18 dmg, A: 18→0 KO)');
233
+
234
+ // ── 7. Session-signed settlement: pot must go to B's canonical owner ─────
235
+ console.log('\n[7] Settlement (session-signed)');
236
+ const arenaData = await gql(`{ dubheObjectStorages { nodes { objectId objectType } } }`);
237
+ const arenaId = arenaData.dubheObjectStorages.nodes.find((n: any) =>
238
+ n.objectType?.toLowerCase().includes('arena')
239
+ )?.objectId;
240
+ if (!arenaId) throw new Error('arena object not found via GraphQL');
241
+
242
+ await send(S, 'finish_duel (B via session, pot → canonical owner)', (tx) => {
243
+ tx.moveCall({
244
+ target: `${PackageId}::duel_system::finish_duel`,
245
+ arguments: [
246
+ tx.object(DappStorageId),
247
+ tx.object(usB),
248
+ tx.object(permitId),
249
+ tx.object(sceneId),
250
+ tx.object(arenaId)
251
+ ]
252
+ });
253
+ });
254
+ await send(A, 'leave_duel (A main wallet)', (tx) => {
255
+ tx.moveCall({
256
+ target: `${PackageId}::duel_system::leave_duel`,
257
+ arguments: [tx.object(permitId), tx.object(sceneId), tx.object(usA)]
258
+ });
259
+ });
260
+ await send(S, 'cleanup_duel (session-signed)', (tx) => {
261
+ tx.moveCall({
262
+ target: `${PackageId}::duel_system::cleanup_duel`,
263
+ arguments: [tx.object(sceneId), tx.object(permitId)]
264
+ });
265
+ });
266
+
267
+ // ── 8. Verify all identity resolves to the main wallets ──────────────────
268
+ console.log('\n[8] Verify identities via the indexer');
269
+ let goldA = 0n;
270
+ let goldB = 0n;
271
+ let profA: any = {};
272
+ let profB: any = {};
273
+ let sessionRows = 0;
274
+ for (let i = 0; i < 30; i++) {
275
+ const data = await gql(
276
+ `{ golds { nodes { entityId amount } } profiles { nodes { entityId wins losses rating } } }`
277
+ );
278
+ goldA = BigInt(data.golds.nodes.find((n: any) => n.entityId === addrA)?.amount ?? 0);
279
+ goldB = BigInt(data.golds.nodes.find((n: any) => n.entityId === addrB)?.amount ?? 0);
280
+ profA = data.profiles.nodes.find((n: any) => n.entityId === addrA) ?? {};
281
+ profB = data.profiles.nodes.find((n: any) => n.entityId === addrB) ?? {};
282
+ sessionRows =
283
+ data.golds.nodes.filter((n: any) => n.entityId === addrS).length +
284
+ data.profiles.nodes.filter((n: any) => n.entityId === addrS).length;
285
+ if (goldB === 547n && Number(profB.wins) === 1) break;
286
+ await new Promise((r) => setTimeout(r, 2000));
287
+ }
288
+ console.log(` A gold=${goldA} profile=${JSON.stringify(profA)}`);
289
+ console.log(` B gold=${goldB} profile=${JSON.stringify(profB)}`);
290
+
291
+ // pot=100, rake=3, winner nets +47, loser -50
292
+ if (goldB !== 547n) throw new Error(`B gold expected 547, got ${goldB}`);
293
+ if (goldA !== 450n) throw new Error(`A gold expected 450, got ${goldA}`);
294
+ if (Number(profB.wins) !== 1 || Number(profB.rating) !== 1225)
295
+ throw new Error(`B profile wrong: ${JSON.stringify(profB)}`);
296
+ if (Number(profA.losses) !== 1 || Number(profA.rating) !== 1175)
297
+ throw new Error(`A profile wrong: ${JSON.stringify(profA)}`);
298
+ if (sessionRows !== 0)
299
+ throw new Error(`session address ${addrS} must own no game state, found ${sessionRows} rows`);
300
+
301
+ // Permit participants must have been registered as main wallets only.
302
+ const parts = await gql(
303
+ `{ dubheScenePermitParticipants { nodes { permitId participant active } } }`
304
+ );
305
+ const duelParts = parts.dubheScenePermitParticipants.nodes.filter(
306
+ (n: any) => n.permitId === permitId
307
+ );
308
+ console.log(` Permit participants: ${JSON.stringify(duelParts)}`);
309
+ if (duelParts.some((n: any) => n.participant === addrS))
310
+ throw new Error('session address leaked into permit participants');
311
+ if (!duelParts.some((n: any) => n.participant === addrB))
312
+ throw new Error("B's canonical owner missing from permit participants");
313
+
314
+ // ── 9. Deactivated sessions must lose write access ────────────────────────
315
+ console.log('\n[9] deactivate_session + negative check');
316
+ await send(B, 'deactivate_session (B main wallet)', (tx) => {
317
+ tx.moveCall({
318
+ target: `${FrameworkPackageId}::dapp_system::deactivate_session`,
319
+ typeArguments: [`${PackageId}::dapp_key::DappKey`],
320
+ arguments: [tx.object(DappHubId), tx.object(usB)]
321
+ });
322
+ });
323
+ await mustFail(S, 'create_duel signed by revoked session', (tx) => {
324
+ tx.moveCall({
325
+ target: `${PackageId}::duel_system::create_duel`,
326
+ arguments: [
327
+ tx.object(DappStorageId),
328
+ tx.object(usB),
329
+ tx.pure.address(addrA),
330
+ tx.pure.u64(STAKE),
331
+ tx.object(CLOCK)
332
+ ]
333
+ });
334
+ });
335
+
336
+ console.log('\n✅ E2E session flow passed!');
337
+ }
338
+
339
+ main().catch((err) => {
340
+ console.error(err);
341
+ process.exit(1);
342
+ });
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Query dapp_revenue balance stored in DappStorage as a dynamic field.
3
+ *
4
+ * Run:
5
+ * cd templates/nextjs/sui-card-duel/packages/contracts
6
+ * npx tsx scripts/query-dapp-revenue.ts
7
+ */
8
+
9
+ import { SuiClient } from '@0xobelisk/sui-client';
10
+ import { Network, DappStorageId, FrameworkPackageId } from './config.ts';
11
+
12
+ const RPC: Record<string, string> = {
13
+ localnet: 'http://127.0.0.1:9000',
14
+ devnet: 'https://fullnode.devnet.sui.io',
15
+ testnet: 'https://fullnode.testnet.sui.io',
16
+ mainnet: 'https://fullnode.mainnet.sui.io'
17
+ };
18
+
19
+ const COIN_SUI = '0x2::sui::SUI';
20
+
21
+ async function queryDappRevenue() {
22
+ const client = new SuiClient({ url: RPC[Network] ?? RPC.localnet });
23
+
24
+ console.log(`Network : ${Network}`);
25
+ console.log(`Storage : ${DappStorageId}`);
26
+ console.log(`Framework: ${FrameworkPackageId}`);
27
+ console.log('');
28
+
29
+ if (!FrameworkPackageId) {
30
+ console.error('FrameworkPackageId is undefined in deployment.ts');
31
+ process.exit(1);
32
+ }
33
+
34
+ // ── 1. Query dapp_revenue via getDynamicFieldObject ────────────────────────
35
+ const revenueKeyType = `${FrameworkPackageId}::dapp_service::DappRevenueKey<${COIN_SUI}>`;
36
+
37
+ let revenueBalance = 0n;
38
+ try {
39
+ const result = await client.getDynamicFieldObject({
40
+ parentId: DappStorageId,
41
+ name: {
42
+ // Sui serializes empty structs with a synthetic dummy_field: bool
43
+ type: revenueKeyType,
44
+ value: { dummy_field: false }
45
+ }
46
+ });
47
+
48
+ if (result.error) {
49
+ // Field not yet created → balance is 0
50
+ console.log('dapp_revenue field not found (no fees collected yet)');
51
+ } else {
52
+ const fields = (result.data?.content as any)?.fields;
53
+ // Balance<SUI> is a struct with field `value: u64`
54
+ revenueBalance = BigInt(fields?.value ?? fields?.balance ?? 0);
55
+ }
56
+ } catch (e: any) {
57
+ // 404 / field not found → balance is 0
58
+ if (!e?.message?.includes('not found') && !e?.message?.includes('dynamic field')) {
59
+ throw e;
60
+ }
61
+ console.log('dapp_revenue dynamic field does not exist yet (0 revenue)');
62
+ }
63
+
64
+ const mist = revenueBalance;
65
+ const sui = Number(mist) / 1e9;
66
+
67
+ console.log(`─── DApp Revenue Balance ──────────────`);
68
+ console.log(` ${mist} MIST`);
69
+ console.log(` ${sui.toFixed(9)} SUI`);
70
+ console.log('');
71
+
72
+ // ── 2. Also read DappStorage basic info ───────────────────────────────────
73
+ const storageObj = await client.getObject({
74
+ id: DappStorageId,
75
+ options: { showContent: true }
76
+ });
77
+ const sf = (storageObj.data?.content as any)?.fields ?? {};
78
+
79
+ const creditPool = BigInt(sf.credit_pool ?? 0);
80
+ const freeCredit = BigInt(sf.free_credit ?? 0);
81
+ const totalSettled = BigInt(sf.total_settled ?? 0);
82
+ const settlementMode = Number(sf.settlement_mode ?? 0);
83
+
84
+ console.log(`─── DApp Storage Summary ───────────────`);
85
+ console.log(
86
+ ` settlement_mode : ${settlementMode === 0 ? '0 (DAPP_SUBSIDIZES)' : '1 (USER_PAYS)'}`
87
+ );
88
+ console.log(` credit_pool : ${Number(creditPool) / 1e9} SUI (${creditPool} MIST)`);
89
+ console.log(` free_credit : ${Number(freeCredit) / 1e9} SUI (${freeCredit} MIST)`);
90
+ console.log(` total_settled : ${Number(totalSettled) / 1e9} SUI (${totalSettled} MIST)`);
91
+ console.log(` paused : ${sf.paused}`);
92
+ console.log(` version : ${sf.version}`);
93
+ }
94
+
95
+ queryDappRevenue().catch(console.error);
@@ -0,0 +1,92 @@
1
+ /**
2
+ * seed.ts — Populate initial on-chain state after deployment.
3
+ *
4
+ * Usage:
5
+ * cd templates/nextjs/sui-card-duel/packages/contracts
6
+ * pnpm tsx scripts/seed.ts localnet
7
+ * pnpm tsx scripts/seed.ts testnet
8
+ *
9
+ * The deploy_hook.move already initialises game_config and creates the arena
10
+ * object during the publish transaction. This script is for one-off admin
11
+ * actions:
12
+ * 1. Override the game config (pack price, rake, HP, turn timeout).
13
+ * 2. Verify the DappStorage fields.
14
+ */
15
+
16
+ import * as dotenv from 'dotenv';
17
+ import {
18
+ Dubhe,
19
+ Transaction,
20
+ getFullnodeUrl,
21
+ NetworkType,
22
+ loadMetadata
23
+ } from '@0xobelisk/sui-client';
24
+ import { Network, PackageId, DappHubId, DappStorageId, FrameworkPackageId } from './config.ts';
25
+
26
+ dotenv.config();
27
+
28
+ // ---------------------------------------------------------------------------
29
+ // Main
30
+ // ---------------------------------------------------------------------------
31
+ async function main() {
32
+ const networkArg = (process.argv[2] ?? Network) as NetworkType;
33
+ const privateKey = process.env.PRIVATE_KEY;
34
+ if (!privateKey) {
35
+ throw new Error('PRIVATE_KEY env var not set. Run: pnpm account:gen and set in .env');
36
+ }
37
+
38
+ if (!PackageId || PackageId === '0x0') {
39
+ throw new Error('PackageId is 0x0 — deploy the contract first with: pnpm deploy ' + networkArg);
40
+ }
41
+
42
+ const metadata = await loadMetadata(networkArg, PackageId);
43
+ const dubhe = new Dubhe({
44
+ networkType: networkArg,
45
+ packageId: PackageId,
46
+ metadata,
47
+ secretKey: privateKey,
48
+ suiRpcUrl: getFullnodeUrl(networkArg),
49
+ dappHubId: DappHubId,
50
+ dappStorageId: DappStorageId,
51
+ frameworkPackageId: FrameworkPackageId
52
+ });
53
+
54
+ const adminAddress = dubhe.getAddress();
55
+ console.log(`Admin address: ${adminAddress}`);
56
+ console.log(`Network: ${networkArg}`);
57
+ console.log(`Package ID: ${PackageId}`);
58
+ console.log('');
59
+
60
+ // ── 1. (Re)apply the game config ──────────────────────────────────────────
61
+ console.log('Setting game config...');
62
+ const tx1 = new Transaction();
63
+ await dubhe.tx.arena_system.set_game_config({
64
+ tx: tx1,
65
+ params: [
66
+ tx1.object(DappStorageId),
67
+ tx1.pure.u64(100), // pack_price (gold)
68
+ tx1.pure.u64(500), // starting_gold
69
+ tx1.pure.u64(300), // rake_bps (3%)
70
+ tx1.pure.u64(30), // max_hp
71
+ tx1.pure.u64(5 * 60 * 1000) // turn_timeout_ms (5 minutes)
72
+ ]
73
+ });
74
+ const result1 = await dubhe.signAndSendTxn({ tx: tx1 });
75
+ console.log(`Game config set! Digest: ${result1.digest}`);
76
+
77
+ // ── 2. Verify DApp storage fields ─────────────────────────────────────────
78
+ if (DappStorageId) {
79
+ console.log('\nDappStorage fields:');
80
+ const storageFields = await dubhe.getDappStorageFields(DappStorageId);
81
+ console.log(
82
+ JSON.stringify(storageFields, (_, v) => (typeof v === 'bigint' ? v.toString() : v), 2)
83
+ );
84
+ }
85
+
86
+ console.log('\nSeed complete!');
87
+ }
88
+
89
+ main().catch((err) => {
90
+ console.error(err);
91
+ process.exit(1);
92
+ });
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Flush accumulated DApp revenue from DappStorage to the DApp admin wallet.
3
+ *
4
+ * Calls: dapp_system::withdraw_dapp_revenue<DappKey, SUI>(dh, dapp_storage, ctx)
5
+ * The Move function internally transfers the Coin to the stored dapp_admin address —
6
+ * anyone can trigger this (permissionless), only gas is needed.
7
+ *
8
+ * Run:
9
+ * cd templates/nextjs/sui-card-duel/packages/contracts
10
+ * PRIVATE_KEY="suiprivkey1q..." npx tsx scripts/withdraw-dapp-revenue.ts
11
+ */
12
+
13
+ import { Dubhe, NetworkType, Transaction } from '@0xobelisk/sui-client';
14
+ import { Network, DappHubId, DappStorageId, PackageId, FrameworkPackageId } from './config.ts';
15
+
16
+ const COIN_SUI = '0x2::sui::SUI';
17
+ const DAPP_KEY_TYPE = `${PackageId}::dapp_key::DappKey`;
18
+
19
+ async function main() {
20
+ const secretKey = process.env.PRIVATE_KEY;
21
+ if (!secretKey) {
22
+ console.error('Error: set PRIVATE_KEY env var (any key with enough SUI for gas)');
23
+ console.error(' PRIVATE_KEY="suiprivkey1q..." npx tsx scripts/withdraw-dapp-revenue.ts');
24
+ process.exit(1);
25
+ }
26
+
27
+ const dubhe = new Dubhe({
28
+ networkType: Network as NetworkType,
29
+ packageId: PackageId,
30
+ metadata: undefined,
31
+ secretKey
32
+ });
33
+
34
+ console.log(`Caller address : ${dubhe.getAddress()} (pays gas only)`);
35
+ console.log(`DappStorageId : ${DappStorageId}`);
36
+ console.log('');
37
+
38
+ // withdraw_dapp_revenue is void — the Move contract transfers funds to dapp_admin directly.
39
+ const tx = new Transaction();
40
+ tx.moveCall({
41
+ target: `${FrameworkPackageId}::dapp_system::withdraw_dapp_revenue`,
42
+ typeArguments: [DAPP_KEY_TYPE, COIN_SUI],
43
+ arguments: [tx.object(DappHubId), tx.object(DappStorageId)]
44
+ });
45
+
46
+ console.log('Sending withdraw_dapp_revenue transaction...');
47
+ const result = await dubhe.signAndSendTxn({ tx });
48
+
49
+ if (result.effects?.status?.status === 'success') {
50
+ console.log(`✅ Success! Digest: ${result.digest}`);
51
+ } else {
52
+ console.error('❌ Transaction failed:', result.effects?.status);
53
+ }
54
+ }
55
+
56
+ main().catch(console.error);
@@ -0,0 +1,15 @@
1
+ [package]
2
+ name = "card_duel"
3
+ version = "1.0.0"
4
+ edition = "2024"
5
+
6
+ [dependencies]
7
+ Dubhe = { local = "../dubhe" }
8
+
9
+ [addresses]
10
+ card_duel = "0x0"
11
+
12
+ [environments]
13
+ localnet = "cbd74b91"
14
+ testnet = "4c78adac"
15
+ mainnet = "35834a8a"
@@ -0,0 +1,46 @@
1
+ // Copyright (c) Obelisk Labs, Inc.
2
+ // SPDX-License-Identifier: Apache-2.0
3
+
4
+ /* Autogenerated file. Do not edit manually. */
5
+
6
+ module card_duel::dapp_key {
7
+ use std::type_name;
8
+ use sui::address;
9
+ use std::ascii::String;
10
+
11
+ /// DappKey — package-level authorization token for this DApp.
12
+ ///
13
+ /// SECURITY: `new()` is intentionally `public(package)`.
14
+ /// Only code compiled into this package can construct a DappKey instance.
15
+ /// All framework write functions (`set_record`, `set_field`,
16
+ /// `take_record`, `create_user_storage`, …) require `_auth: DappKey`
17
+ /// as proof that the call originated from inside this package — an
18
+ /// external PTB cannot fabricate that proof.
19
+ ///
20
+ /// NEVER change `new()` to `public`, and never accept a DappKey
21
+ /// value as a parameter from an external caller. Either mistake removes
22
+ /// every package-level access guard, allowing any PTB to write arbitrary
23
+ /// user data or register UserStorages without going through the DApp's
24
+ /// own entry functions.
25
+
26
+ public struct DappKey has copy, drop {}
27
+
28
+ /// Constructs an authorization token. Callable only from within this package.
29
+ /// Pass the result as `_auth` to any framework function that requires it.
30
+ public(package) fun new(): DappKey {
31
+ DappKey {}
32
+ }
33
+
34
+ public fun to_string(): String {
35
+ type_name::with_defining_ids<DappKey>().into_string()
36
+ }
37
+
38
+ public fun package_id(): address {
39
+ let package_id_str = type_name::with_defining_ids<DappKey>().address_string();
40
+ address::from_ascii_bytes(package_id_str.as_bytes())
41
+ }
42
+
43
+ public fun eq<DappKey1: copy + drop, DappKey2: copy + drop>(_: &DappKey1, _: &DappKey2): bool {
44
+ type_name::with_defining_ids<DappKey1>() == type_name::with_defining_ids<DappKey2>()
45
+ }
46
+ }