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
@@ -11,11 +11,7 @@ import { useDubhe } from '@0xobelisk/react/sui';
11
11
  import dubheMetadata from 'contracts/dubhe.config.json';
12
12
 
13
13
  // Counter resource/table name from dubhe.config (resources.value)
14
- const COUNTER_RESOURCE_NAME = (() => {
15
- const resources = (dubheMetadata as { resources?: Record<string, unknown>[] })?.resources;
16
- const first = resources?.[0];
17
- return first && typeof first === 'object' ? Object.keys(first)[0] ?? 'value' : 'value';
18
- })();
14
+ const TABLE_NAME = 'value';
19
15
 
20
16
  export default function Home() {
21
17
  const [value, setValue] = useAtom(Value);
@@ -27,6 +23,30 @@ export default function Home() {
27
23
  const [ecsInitialized, setEcsInitialized] = useState(false);
28
24
  const [activeTab, setActiveTab] = useState<'ecs' | 'graphql'>('ecs');
29
25
 
26
+ // UserStorage state
27
+ const [userStorageId, setUserStorageId] = useState<string | null>(null);
28
+ const [userStorageLoading, setUserStorageLoading] = useState(false);
29
+ const [userStorageFields, setUserStorageFields] = useState<{
30
+ write_count: bigint;
31
+ settled_count: bigint;
32
+ write_bytes: bigint;
33
+ settled_bytes: bigint;
34
+ unsettled_count: bigint;
35
+ unsettled_bytes: bigint;
36
+ session_key: string;
37
+ session_expires_at: bigint;
38
+ } | null>(null);
39
+ const [dappStorageFields, setDappStorageFields] = useState<{
40
+ name: string;
41
+ credit_pool: bigint;
42
+ free_credit: bigint;
43
+ suspended: boolean;
44
+ base_fee_per_write: bigint;
45
+ bytes_fee_per_byte: bigint;
46
+ total_settled: bigint;
47
+ } | null>(null);
48
+ const [settleLoading, setSettleLoading] = useState(false);
49
+
30
50
  // General query state
31
51
  const [availableComponents, setAvailableComponents] = useState<string[]>([]);
32
52
  const [availableResources, setAvailableResources] = useState<string[]>([]);
@@ -44,7 +64,153 @@ export default function Home() {
44
64
  const [resourceQueryLoading, setResourceQueryLoading] = useState(false);
45
65
  const [tableQueryLoading, setTableQueryLoading] = useState(false);
46
66
 
47
- const { contract, graphqlClient, ecsWorld, network, address, dubheSchemaId } = useDubhe();
67
+ const { contract, graphqlClient, ecsWorld, network, address, dappHubId, dappStorageId } =
68
+ useDubhe();
69
+
70
+ /**
71
+ * Look up the UserStorage object ID for the current address.
72
+ * Stores the result in state so subsequent transactions can reference it.
73
+ */
74
+ const fetchUserStorageId = async (currentAddress: string) => {
75
+ if (!currentAddress) return;
76
+ try {
77
+ const id = await contract.getUserStorageId(currentAddress);
78
+ setUserStorageId(id);
79
+ if (id) {
80
+ await refreshStorageFields(id);
81
+ } else {
82
+ setUserStorageFields(null);
83
+ }
84
+ } catch (error) {
85
+ console.error('Failed to query UserStorage ID:', error);
86
+ setUserStorageId(null);
87
+ setUserStorageFields(null);
88
+ }
89
+ };
90
+
91
+ /**
92
+ * Register a UserStorage for the current address.
93
+ * Each address may only register once per DApp.
94
+ */
95
+ const registerUserStorage = async () => {
96
+ if (!dappHubId || !dappStorageId) {
97
+ toast.error('dappHubId or dappStorageId is not configured.');
98
+ return;
99
+ }
100
+ setUserStorageLoading(true);
101
+ try {
102
+ const result = await contract.initUserStorage({
103
+ dappHubId,
104
+ dappStorageId,
105
+ onSuccess: async (res) => {
106
+ // Extract the newly created UserStorage object ID from object changes.
107
+ const created = res.objectChanges?.find(
108
+ (c: any) =>
109
+ c.type === 'created' &&
110
+ typeof c.objectType === 'string' &&
111
+ c.objectType.includes('::dapp_service::UserStorage')
112
+ ) as any;
113
+ if (created?.objectId) {
114
+ setUserStorageId(created.objectId);
115
+ await refreshStorageFields(created.objectId);
116
+ } else {
117
+ // Fall back to on-chain query if objectChanges is not available.
118
+ await fetchUserStorageId(address);
119
+ }
120
+ toast('UserStorage registered', {
121
+ description: 'You can now interact with the counter.',
122
+ action: {
123
+ label: 'Check in Explorer',
124
+ onClick: () => window.open(contract.getTxExplorerUrl(res.digest), '_blank')
125
+ }
126
+ });
127
+ },
128
+ onError: (error) => {
129
+ console.error('UserStorage registration failed:', error);
130
+ toast.error('Registration failed. Please try again.');
131
+ }
132
+ });
133
+ } catch (error) {
134
+ console.error('registerUserStorage error:', error);
135
+ toast.error('Registration failed. Please try again.');
136
+ } finally {
137
+ setUserStorageLoading(false);
138
+ }
139
+ };
140
+
141
+ /**
142
+ * Refresh on-chain fields for the UserStorage and DappStorage objects.
143
+ * Called after any state-mutating transaction and on UserStorage ID change.
144
+ */
145
+ const refreshStorageFields = async (storageId: string) => {
146
+ try {
147
+ const [usFields, dsFields] = await Promise.all([
148
+ contract.getUserStorageFields(storageId),
149
+ dappStorageId ? contract.getDappStorageFields(dappStorageId) : null
150
+ ]);
151
+ setUserStorageFields({
152
+ write_count: usFields.write_count,
153
+ settled_count: usFields.settled_count,
154
+ write_bytes: usFields.write_bytes,
155
+ settled_bytes: usFields.settled_bytes,
156
+ unsettled_count: usFields.unsettled_count,
157
+ unsettled_bytes: usFields.unsettled_bytes,
158
+ session_key: usFields.session_key,
159
+ session_expires_at: usFields.session_expires_at
160
+ });
161
+ if (dsFields) {
162
+ setDappStorageFields({
163
+ name: dsFields.name,
164
+ credit_pool: dsFields.credit_pool,
165
+ free_credit: dsFields.free_credit,
166
+ suspended: dsFields.suspended,
167
+ base_fee_per_write: dsFields.base_fee_per_write,
168
+ bytes_fee_per_byte: dsFields.bytes_fee_per_byte,
169
+ total_settled: dsFields.total_settled
170
+ });
171
+ }
172
+ } catch (error) {
173
+ console.error('Failed to refresh storage fields:', error);
174
+ }
175
+ };
176
+
177
+ /**
178
+ * Settle accumulated write debt for the current user.
179
+ * Calls dapp_system::settle_writes on the framework.
180
+ */
181
+ const handleSettleWrites = async () => {
182
+ if (!dappHubId || !dappStorageId || !userStorageId) {
183
+ toast.error('Missing required IDs for settlement.');
184
+ return;
185
+ }
186
+ setSettleLoading(true);
187
+ try {
188
+ await contract.settleWrites({
189
+ dappHubId,
190
+ dappStorageId,
191
+ userStorageId,
192
+ onSuccess: async (res) => {
193
+ await refreshStorageFields(userStorageId);
194
+ toast('Settlement successful', {
195
+ description: 'Write debt has been settled.',
196
+ action: {
197
+ label: 'Check in Explorer',
198
+ onClick: () => window.open(contract.getTxExplorerUrl(res.digest), '_blank')
199
+ }
200
+ });
201
+ },
202
+ onError: (error) => {
203
+ console.error('Settlement failed:', error);
204
+ toast.error('Settlement failed. Please try again.');
205
+ }
206
+ });
207
+ } catch (error) {
208
+ console.error('handleSettleWrites error:', error);
209
+ toast.error('Settlement failed. Please try again.');
210
+ } finally {
211
+ setSettleLoading(false);
212
+ }
213
+ };
48
214
 
49
215
  /**
50
216
  * Discover available tables and components
@@ -202,8 +368,8 @@ export default function Home() {
202
368
  return;
203
369
  }
204
370
  console.log('currentAddress', currentAddress);
205
- const result = await graphqlClient.getTableByCondition(COUNTER_RESOURCE_NAME, {
206
- id: currentAddress
371
+ const result = await graphqlClient.getTableByCondition(TABLE_NAME, {
372
+ entityId: currentAddress
207
373
  });
208
374
 
209
375
  console.log('result', result);
@@ -238,8 +404,8 @@ export default function Home() {
238
404
  return;
239
405
  }
240
406
 
241
- const record = (await ecsWorld.getResource<any>(COUNTER_RESOURCE_NAME, {
242
- id: currentAddress
407
+ const record = (await ecsWorld.getResource<any>(TABLE_NAME, {
408
+ entityId: currentAddress
243
409
  })) as { value?: number } | null;
244
410
  const counterValue = record?.value ?? 0;
245
411
  setEcsValue(counterValue);
@@ -255,15 +421,21 @@ export default function Home() {
255
421
  };
256
422
 
257
423
  /**
258
- * Increments the counter value
424
+ * Increments the counter value via the user's UserStorage.
425
+ * Requires the user to have called registerUserStorage first.
259
426
  */
260
427
  const incrementCounter = async () => {
428
+ if (!userStorageId) {
429
+ toast.error('UserStorage not found. Please register first.');
430
+ return;
431
+ }
261
432
  setLoading(true);
262
433
  try {
263
434
  const tx = new Transaction();
435
+ // counter_system::inc takes only the UserStorage shared object.
264
436
  (await contract.tx.counter_system.inc({
265
437
  tx,
266
- params: [tx.object(dubheSchemaId), tx.pure.u32(1)],
438
+ params: [tx.object(userStorageId)],
267
439
  isRaw: true
268
440
  })) as TransactionResult;
269
441
 
@@ -279,6 +451,10 @@ export default function Home() {
279
451
  }
280
452
  });
281
453
  }, 200);
454
+ // Refresh storage fields so the UI reflects the new write counters.
455
+ if (userStorageId) {
456
+ await refreshStorageFields(userStorageId);
457
+ }
282
458
  },
283
459
  onError: (error) => {
284
460
  console.error('Transaction failed:', error);
@@ -302,9 +478,9 @@ export default function Home() {
302
478
  if (!currentAddress) return null;
303
479
 
304
480
  // GraphQL plural form for subscription response key (e.g. value -> values)
305
- const pluralKey = `${COUNTER_RESOURCE_NAME}s`;
306
- const observable = graphqlClient.subscribeToTableChanges(COUNTER_RESOURCE_NAME, {
307
- filter: { id: { equalTo: currentAddress } },
481
+ const pluralKey = `${TABLE_NAME}s`;
482
+ const observable = graphqlClient.subscribeToTableChanges(TABLE_NAME, {
483
+ filter: { entityId: { equalTo: currentAddress } },
308
484
  initialEvent: true,
309
485
  onData: (data: any) => {
310
486
  const nodes = data?.listen?.query?.[pluralKey]?.nodes ?? [];
@@ -327,42 +503,35 @@ export default function Home() {
327
503
  };
328
504
 
329
505
  /**
330
- * Subscribe to counter changes using ECS World (resource name from dubhe.config)
506
+ * Subscribe to counter changes using ECS World.
331
507
  */
332
508
  const subscribeToCounterWithECS = () => {
333
509
  try {
334
- const currentAddress = address;
335
- if (!currentAddress) return null;
336
-
337
- const pluralKey = `${COUNTER_RESOURCE_NAME}s`;
338
- const observable = ecsWorld.subscribeToResourceChanges(COUNTER_RESOURCE_NAME, {
339
- filter: { id: { equalTo: currentAddress } },
340
- initialEvent: true
341
- });
342
-
343
- return observable.subscribe({
510
+ const subscription = ecsWorld.onEntityComponent<any>(TABLE_NAME, address).subscribe({
344
511
  next: (result: any) => {
345
- const data = result?.data ?? result;
346
- const nodes = data?.listen?.query?.[pluralKey]?.nodes ?? [];
347
- const node =
348
- nodes.find((n: any) => (n?.entityId ?? n?.entity_id) === currentAddress) ?? nodes[0];
349
- if (node?.value !== undefined) {
350
- setEcsValue(node.value);
351
- setValue(node.value);
352
- toast('ECS Real-time Update', {
353
- description: `New value: ${node.value} (Address: ${currentAddress.slice(0, 6)}...)`
354
- });
512
+ if (result) {
513
+ const componentData = result.data as any;
514
+ if (componentData?.value !== undefined) {
515
+ setEcsValue(componentData.value);
516
+ setValue(componentData.value);
517
+ toast('ECS Real-time Update', {
518
+ description: `New value: ${componentData.value} (Address: ${address.slice(
519
+ 0,
520
+ 6
521
+ )}...)`
522
+ });
523
+ }
355
524
  }
356
- },
357
- error: (error: any) => console.error('❌ ECS subscription failed:', error)
525
+ }
358
526
  });
527
+ return subscription;
359
528
  } catch (error) {
360
529
  console.error('❌ ECS subscription setup failed:', error);
361
530
  return null;
362
531
  }
363
532
  };
364
533
 
365
- // Handle state reset when address changes
534
+ // Handle state reset and UserStorage lookup when address changes
366
535
  useEffect(() => {
367
536
  if (address) {
368
537
  console.log(`🏠 Address initialized/changed: ${address}`);
@@ -372,6 +541,10 @@ export default function Home() {
372
541
  setValue(0);
373
542
  setEcsValue(0);
374
543
  setGraphqlValue(0);
544
+ setUserStorageId(null);
545
+
546
+ // Look up the UserStorage for this address.
547
+ fetchUserStorageId(address);
375
548
  } else {
376
549
  console.log('🏠 No address available');
377
550
 
@@ -380,6 +553,7 @@ export default function Home() {
380
553
  setValue(0);
381
554
  setEcsValue(0);
382
555
  setGraphqlValue(0);
556
+ setUserStorageId(null);
383
557
  }
384
558
  }, [address]);
385
559
 
@@ -524,6 +698,172 @@ export default function Home() {
524
698
  </p>
525
699
  </div>
526
700
 
701
+ {/* UserStorage Status */}
702
+ <div
703
+ className={`rounded-xl p-4 text-sm font-medium flex flex-col sm:flex-row items-center justify-between gap-3 ${
704
+ userStorageId
705
+ ? 'bg-green-50 border border-green-200 text-green-700'
706
+ : 'bg-amber-50 border border-amber-200 text-amber-700'
707
+ }`}
708
+ >
709
+ <span>
710
+ {userStorageId ? (
711
+ <>
712
+ ✅ UserStorage:{' '}
713
+ <span className="font-mono text-xs">
714
+ {userStorageId.slice(0, 10)}...{userStorageId.slice(-6)}
715
+ </span>
716
+ </>
717
+ ) : (
718
+ '⚠️ No UserStorage found. Register to start playing.'
719
+ )}
720
+ </span>
721
+ {!userStorageId && (
722
+ <button
723
+ type="button"
724
+ className="px-4 py-2 bg-amber-500 text-white rounded-lg hover:bg-amber-600 disabled:opacity-50 font-medium whitespace-nowrap"
725
+ onClick={registerUserStorage}
726
+ disabled={userStorageLoading}
727
+ >
728
+ {userStorageLoading ? 'Registering...' : '📝 Register UserStorage'}
729
+ </button>
730
+ )}
731
+ </div>
732
+
733
+ {/* UserStorage & DappStorage field details */}
734
+ {userStorageId && (
735
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
736
+ {/* UserStorage fields */}
737
+ {userStorageFields && (
738
+ <div className="bg-indigo-50 border border-indigo-200 rounded-xl p-4">
739
+ <div className="flex items-center justify-between mb-3">
740
+ <h4 className="font-semibold text-indigo-700 text-sm">
741
+ 📦 UserStorage Fields
742
+ </h4>
743
+ <button
744
+ type="button"
745
+ className="text-xs px-2 py-1 bg-indigo-100 text-indigo-600 rounded hover:bg-indigo-200"
746
+ onClick={() => refreshStorageFields(userStorageId)}
747
+ >
748
+ ↻ Refresh
749
+ </button>
750
+ </div>
751
+ <dl className="space-y-1 text-xs font-mono">
752
+ <div className="flex justify-between">
753
+ <dt className="text-gray-500">write_count</dt>
754
+ <dd className="text-gray-800">
755
+ {userStorageFields.write_count.toString()}
756
+ </dd>
757
+ </div>
758
+ <div className="flex justify-between">
759
+ <dt className="text-gray-500">settled_count</dt>
760
+ <dd className="text-gray-800">
761
+ {userStorageFields.settled_count.toString()}
762
+ </dd>
763
+ </div>
764
+ <div
765
+ className={`flex justify-between font-semibold ${
766
+ userStorageFields.unsettled_count > BigInt(0)
767
+ ? 'text-orange-600'
768
+ : 'text-green-600'
769
+ }`}
770
+ >
771
+ <dt>unsettled_count</dt>
772
+ <dd>{userStorageFields.unsettled_count.toString()}</dd>
773
+ </div>
774
+ <div className="flex justify-between">
775
+ <dt className="text-gray-500">write_bytes</dt>
776
+ <dd className="text-gray-800">
777
+ {userStorageFields.write_bytes.toString()}
778
+ </dd>
779
+ </div>
780
+ <div className="flex justify-between">
781
+ <dt className="text-gray-500">settled_bytes</dt>
782
+ <dd className="text-gray-800">
783
+ {userStorageFields.settled_bytes.toString()}
784
+ </dd>
785
+ </div>
786
+ <div
787
+ className={`flex justify-between font-semibold ${
788
+ userStorageFields.unsettled_bytes > BigInt(0)
789
+ ? 'text-orange-600'
790
+ : 'text-green-600'
791
+ }`}
792
+ >
793
+ <dt>unsettled_bytes</dt>
794
+ <dd>{userStorageFields.unsettled_bytes.toString()}</dd>
795
+ </div>
796
+ </dl>
797
+ {userStorageFields.unsettled_count > BigInt(0) && (
798
+ <button
799
+ type="button"
800
+ className="mt-3 w-full px-3 py-2 bg-orange-500 text-white rounded-lg hover:bg-orange-600 disabled:opacity-50 text-sm font-medium"
801
+ onClick={handleSettleWrites}
802
+ disabled={settleLoading}
803
+ >
804
+ {settleLoading ? 'Settling...' : '💸 Settle Writes'}
805
+ </button>
806
+ )}
807
+ </div>
808
+ )}
809
+
810
+ {/* DappStorage fields */}
811
+ {dappStorageFields && (
812
+ <div className="bg-purple-50 border border-purple-200 rounded-xl p-4">
813
+ <h4 className="font-semibold text-purple-700 text-sm mb-3">
814
+ 🏗️ DappStorage Fields
815
+ </h4>
816
+ <dl className="space-y-1 text-xs font-mono">
817
+ <div className="flex justify-between">
818
+ <dt className="text-gray-500">name</dt>
819
+ <dd className="text-gray-800 truncate max-w-[120px]">
820
+ {dappStorageFields.name || '—'}
821
+ </dd>
822
+ </div>
823
+ <div className="flex justify-between">
824
+ <dt className="text-gray-500">credit_pool</dt>
825
+ <dd className="text-gray-800">
826
+ {dappStorageFields.credit_pool.toString()}
827
+ </dd>
828
+ </div>
829
+ <div className="flex justify-between">
830
+ <dt className="text-gray-500">free_credit</dt>
831
+ <dd className="text-gray-800">
832
+ {dappStorageFields.free_credit.toString()}
833
+ </dd>
834
+ </div>
835
+ <div className="flex justify-between">
836
+ <dt className="text-gray-500">total_settled</dt>
837
+ <dd className="text-gray-800">
838
+ {dappStorageFields.total_settled.toString()}
839
+ </dd>
840
+ </div>
841
+ <div className="flex justify-between">
842
+ <dt className="text-gray-500">base_fee_per_write</dt>
843
+ <dd className="text-gray-800">
844
+ {dappStorageFields.base_fee_per_write.toString()}
845
+ </dd>
846
+ </div>
847
+ <div className="flex justify-between">
848
+ <dt className="text-gray-500">bytes_fee_per_byte</dt>
849
+ <dd className="text-gray-800">
850
+ {dappStorageFields.bytes_fee_per_byte.toString()}
851
+ </dd>
852
+ </div>
853
+ <div
854
+ className={`flex justify-between font-semibold ${
855
+ dappStorageFields.suspended ? 'text-red-600' : 'text-green-600'
856
+ }`}
857
+ >
858
+ <dt>suspended</dt>
859
+ <dd>{dappStorageFields.suspended ? 'YES' : 'NO'}</dd>
860
+ </div>
861
+ </dl>
862
+ </div>
863
+ )}
864
+ </div>
865
+ )}
866
+
527
867
  {/* ECS Counter Display */}
528
868
  <div className="text-center bg-gradient-to-r from-indigo-50 to-purple-50 rounded-xl p-8">
529
869
  <div className="text-6xl font-bold text-indigo-600 mb-4">{ecsValue}</div>
@@ -534,7 +874,7 @@ export default function Home() {
534
874
  type="button"
535
875
  className="px-8 py-3 bg-indigo-600 text-white rounded-lg hover:bg-indigo-700 disabled:opacity-50 font-medium text-lg"
536
876
  onClick={() => incrementCounter()}
537
- disabled={loading}
877
+ disabled={loading || !userStorageId}
538
878
  >
539
879
  {loading ? 'Processing...' : '🚀 Increment Counter'}
540
880
  </button>
@@ -666,6 +1006,170 @@ export default function Home() {
666
1006
  </p>
667
1007
  </div>
668
1008
 
1009
+ {/* UserStorage Status (GraphQL tab) */}
1010
+ <div
1011
+ className={`rounded-xl p-4 text-sm font-medium flex flex-col sm:flex-row items-center justify-between gap-3 ${
1012
+ userStorageId
1013
+ ? 'bg-green-50 border border-green-200 text-green-700'
1014
+ : 'bg-amber-50 border border-amber-200 text-amber-700'
1015
+ }`}
1016
+ >
1017
+ <span>
1018
+ {userStorageId ? (
1019
+ <>
1020
+ ✅ UserStorage:{' '}
1021
+ <span className="font-mono text-xs">
1022
+ {userStorageId.slice(0, 10)}...{userStorageId.slice(-6)}
1023
+ </span>
1024
+ </>
1025
+ ) : (
1026
+ '⚠️ No UserStorage found. Register to start playing.'
1027
+ )}
1028
+ </span>
1029
+ {!userStorageId && (
1030
+ <button
1031
+ type="button"
1032
+ className="px-4 py-2 bg-amber-500 text-white rounded-lg hover:bg-amber-600 disabled:opacity-50 font-medium whitespace-nowrap"
1033
+ onClick={registerUserStorage}
1034
+ disabled={userStorageLoading}
1035
+ >
1036
+ {userStorageLoading ? 'Registering...' : '📝 Register UserStorage'}
1037
+ </button>
1038
+ )}
1039
+ </div>
1040
+
1041
+ {/* UserStorage & DappStorage field details (GraphQL tab) */}
1042
+ {userStorageId && (
1043
+ <div className="grid grid-cols-1 md:grid-cols-2 gap-4">
1044
+ {userStorageFields && (
1045
+ <div className="bg-blue-50 border border-blue-200 rounded-xl p-4">
1046
+ <div className="flex items-center justify-between mb-3">
1047
+ <h4 className="font-semibold text-blue-700 text-sm">
1048
+ 📦 UserStorage Fields
1049
+ </h4>
1050
+ <button
1051
+ type="button"
1052
+ className="text-xs px-2 py-1 bg-blue-100 text-blue-600 rounded hover:bg-blue-200"
1053
+ onClick={() => refreshStorageFields(userStorageId)}
1054
+ >
1055
+ ↻ Refresh
1056
+ </button>
1057
+ </div>
1058
+ <dl className="space-y-1 text-xs font-mono">
1059
+ <div className="flex justify-between">
1060
+ <dt className="text-gray-500">write_count</dt>
1061
+ <dd className="text-gray-800">
1062
+ {userStorageFields.write_count.toString()}
1063
+ </dd>
1064
+ </div>
1065
+ <div className="flex justify-between">
1066
+ <dt className="text-gray-500">settled_count</dt>
1067
+ <dd className="text-gray-800">
1068
+ {userStorageFields.settled_count.toString()}
1069
+ </dd>
1070
+ </div>
1071
+ <div
1072
+ className={`flex justify-between font-semibold ${
1073
+ userStorageFields.unsettled_count > BigInt(0)
1074
+ ? 'text-orange-600'
1075
+ : 'text-green-600'
1076
+ }`}
1077
+ >
1078
+ <dt>unsettled_count</dt>
1079
+ <dd>{userStorageFields.unsettled_count.toString()}</dd>
1080
+ </div>
1081
+ <div className="flex justify-between">
1082
+ <dt className="text-gray-500">write_bytes</dt>
1083
+ <dd className="text-gray-800">
1084
+ {userStorageFields.write_bytes.toString()}
1085
+ </dd>
1086
+ </div>
1087
+ <div className="flex justify-between">
1088
+ <dt className="text-gray-500">settled_bytes</dt>
1089
+ <dd className="text-gray-800">
1090
+ {userStorageFields.settled_bytes.toString()}
1091
+ </dd>
1092
+ </div>
1093
+ <div
1094
+ className={`flex justify-between font-semibold ${
1095
+ userStorageFields.unsettled_bytes > BigInt(0)
1096
+ ? 'text-orange-600'
1097
+ : 'text-green-600'
1098
+ }`}
1099
+ >
1100
+ <dt>unsettled_bytes</dt>
1101
+ <dd>{userStorageFields.unsettled_bytes.toString()}</dd>
1102
+ </div>
1103
+ </dl>
1104
+ {userStorageFields.unsettled_count > BigInt(0) && (
1105
+ <button
1106
+ type="button"
1107
+ className="mt-3 w-full px-3 py-2 bg-orange-500 text-white rounded-lg hover:bg-orange-600 disabled:opacity-50 text-sm font-medium"
1108
+ onClick={handleSettleWrites}
1109
+ disabled={settleLoading}
1110
+ >
1111
+ {settleLoading ? 'Settling...' : '💸 Settle Writes'}
1112
+ </button>
1113
+ )}
1114
+ </div>
1115
+ )}
1116
+
1117
+ {dappStorageFields && (
1118
+ <div className="bg-cyan-50 border border-cyan-200 rounded-xl p-4">
1119
+ <h4 className="font-semibold text-cyan-700 text-sm mb-3">
1120
+ 🏗️ DappStorage Fields
1121
+ </h4>
1122
+ <dl className="space-y-1 text-xs font-mono">
1123
+ <div className="flex justify-between">
1124
+ <dt className="text-gray-500">name</dt>
1125
+ <dd className="text-gray-800 truncate max-w-[120px]">
1126
+ {dappStorageFields.name || '—'}
1127
+ </dd>
1128
+ </div>
1129
+ <div className="flex justify-between">
1130
+ <dt className="text-gray-500">credit_pool</dt>
1131
+ <dd className="text-gray-800">
1132
+ {dappStorageFields.credit_pool.toString()}
1133
+ </dd>
1134
+ </div>
1135
+ <div className="flex justify-between">
1136
+ <dt className="text-gray-500">free_credit</dt>
1137
+ <dd className="text-gray-800">
1138
+ {dappStorageFields.free_credit.toString()}
1139
+ </dd>
1140
+ </div>
1141
+ <div className="flex justify-between">
1142
+ <dt className="text-gray-500">total_settled</dt>
1143
+ <dd className="text-gray-800">
1144
+ {dappStorageFields.total_settled.toString()}
1145
+ </dd>
1146
+ </div>
1147
+ <div className="flex justify-between">
1148
+ <dt className="text-gray-500">base_fee_per_write</dt>
1149
+ <dd className="text-gray-800">
1150
+ {dappStorageFields.base_fee_per_write.toString()}
1151
+ </dd>
1152
+ </div>
1153
+ <div className="flex justify-between">
1154
+ <dt className="text-gray-500">bytes_fee_per_byte</dt>
1155
+ <dd className="text-gray-800">
1156
+ {dappStorageFields.bytes_fee_per_byte.toString()}
1157
+ </dd>
1158
+ </div>
1159
+ <div
1160
+ className={`flex justify-between font-semibold ${
1161
+ dappStorageFields.suspended ? 'text-red-600' : 'text-green-600'
1162
+ }`}
1163
+ >
1164
+ <dt>suspended</dt>
1165
+ <dd>{dappStorageFields.suspended ? 'YES' : 'NO'}</dd>
1166
+ </div>
1167
+ </dl>
1168
+ </div>
1169
+ )}
1170
+ </div>
1171
+ )}
1172
+
669
1173
  {/* GraphQL Counter Display */}
670
1174
  <div className="text-center bg-gradient-to-r from-blue-50 to-cyan-50 rounded-xl p-8">
671
1175
  <div className="text-6xl font-bold text-blue-600 mb-4">{graphqlValue}</div>
@@ -676,7 +1180,7 @@ export default function Home() {
676
1180
  type="button"
677
1181
  className="px-8 py-3 bg-blue-600 text-white rounded-lg hover:bg-blue-700 disabled:opacity-50 font-medium text-lg"
678
1182
  onClick={() => incrementCounter()}
679
- disabled={loading}
1183
+ disabled={loading || !userStorageId}
680
1184
  >
681
1185
  {loading ? 'Processing...' : '🚀 Increment Counter'}
682
1186
  </button>