create-dubhe 1.2.0-pre.123 → 1.2.0-pre.125

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 (131) hide show
  1. package/dist/cli.js +1 -1
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/dapp_key.move +16 -1
  5. package/templates/101/sui-template/packages/contracts/src/counter/sources/codegen/user_storage_init.move +6 -2
  6. package/templates/101/sui-template/packages/contracts/src/dubhe/Move.lock +0 -6
  7. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/dapp_key.move +16 -1
  8. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/dapp_system.move +83 -42
  9. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/fee_test.move +2 -2
  10. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/integration_test.move +1 -1
  11. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/scene_session_test.move +269 -0
  12. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/typed_scene_test.move +25 -9
  13. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/user_storage_test.move +6 -6
  14. package/templates/contract/sui-template/src/dubhe/Move.lock +0 -6
  15. package/templates/contract/sui-template/src/dubhe/sources/codegen/dapp_key.move +16 -1
  16. package/templates/contract/sui-template/src/dubhe/sources/systems/dapp_system.move +83 -42
  17. package/templates/contract/sui-template/src/dubhe/sources/tests/fee_test.move +2 -2
  18. package/templates/contract/sui-template/src/dubhe/sources/tests/integration_test.move +1 -1
  19. package/templates/contract/sui-template/src/dubhe/sources/tests/scene_session_test.move +269 -0
  20. package/templates/contract/sui-template/src/dubhe/sources/tests/typed_scene_test.move +25 -9
  21. package/templates/contract/sui-template/src/dubhe/sources/tests/user_storage_test.move +6 -6
  22. package/templates/contract/sui-template/src/template/sources/codegen/dapp_key.move +16 -1
  23. package/templates/contract/sui-template/src/template/sources/codegen/user_storage_init.move +6 -2
  24. package/templates/nextjs/sui-card-duel/.gitignore_ +51 -0
  25. package/templates/nextjs/sui-card-duel/README.md +213 -0
  26. package/templates/nextjs/sui-card-duel/docker-compose.yml +34 -0
  27. package/templates/nextjs/sui-card-duel/mprocs.yaml +17 -0
  28. package/templates/nextjs/sui-card-duel/package.json +43 -0
  29. package/templates/nextjs/sui-card-duel/packages/client/.gitignore_ +48 -0
  30. package/templates/nextjs/sui-card-duel/packages/client/.prettierignore +1 -0
  31. package/templates/nextjs/sui-card-duel/packages/client/.prettierrc.json +8 -0
  32. package/templates/nextjs/sui-card-duel/packages/client/eslint.config.mjs +22 -0
  33. package/templates/nextjs/sui-card-duel/packages/client/next.config.mjs +8 -0
  34. package/templates/nextjs/sui-card-duel/packages/client/package.json +47 -0
  35. package/templates/nextjs/sui-card-duel/packages/client/postcss.config.mjs +8 -0
  36. package/templates/nextjs/sui-card-duel/packages/client/src/app/admin/ArenaPanel.tsx +307 -0
  37. package/templates/nextjs/sui-card-duel/packages/client/src/app/admin/page.tsx +622 -0
  38. package/templates/nextjs/sui-card-duel/packages/client/src/app/brawl/[id]/page.tsx +559 -0
  39. package/templates/nextjs/sui-card-duel/packages/client/src/app/collection/page.tsx +202 -0
  40. package/templates/nextjs/sui-card-duel/packages/client/src/app/components/CardView.tsx +66 -0
  41. package/templates/nextjs/sui-card-duel/packages/client/src/app/components/GameShell.tsx +294 -0
  42. package/templates/nextjs/sui-card-duel/packages/client/src/app/components/icons.tsx +101 -0
  43. package/templates/nextjs/sui-card-duel/packages/client/src/app/duel/[id]/page.tsx +477 -0
  44. package/templates/nextjs/sui-card-duel/packages/client/src/app/favicon.ico +0 -0
  45. package/templates/nextjs/sui-card-duel/packages/client/src/app/globals.css +85 -0
  46. package/templates/nextjs/sui-card-duel/packages/client/src/app/hooks/useGame.ts +313 -0
  47. package/templates/nextjs/sui-card-duel/packages/client/src/app/layout.tsx +24 -0
  48. package/templates/nextjs/sui-card-duel/packages/client/src/app/leaderboard/page.tsx +123 -0
  49. package/templates/nextjs/sui-card-duel/packages/client/src/app/lib/game.ts +77 -0
  50. package/templates/nextjs/sui-card-duel/packages/client/src/app/lib/scenes.ts +226 -0
  51. package/templates/nextjs/sui-card-duel/packages/client/src/app/market/page.tsx +418 -0
  52. package/templates/nextjs/sui-card-duel/packages/client/src/app/page.tsx +427 -0
  53. package/templates/nextjs/sui-card-duel/packages/client/src/app/providers.tsx +69 -0
  54. package/templates/nextjs/sui-card-duel/packages/client/tailwind.config.ts +21 -0
  55. package/templates/nextjs/sui-card-duel/packages/client/tsconfig.json +30 -0
  56. package/templates/nextjs/sui-card-duel/packages/contracts/.gitignore_ +51 -0
  57. package/templates/nextjs/sui-card-duel/packages/contracts/.prettierignore +1 -0
  58. package/templates/nextjs/sui-card-duel/packages/contracts/.prettierrc.json +8 -0
  59. package/templates/nextjs/sui-card-duel/packages/contracts/Dockerfile +5 -0
  60. package/templates/nextjs/sui-card-duel/packages/contracts/Pub.localnet.toml +13 -0
  61. package/templates/nextjs/sui-card-duel/packages/contracts/card_duel.lock.json +66 -0
  62. package/templates/nextjs/sui-card-duel/packages/contracts/docker-compose.yml +34 -0
  63. package/templates/nextjs/sui-card-duel/packages/contracts/dubhe.config.ts +150 -0
  64. package/templates/nextjs/sui-card-duel/packages/contracts/logs/combined.log +31383 -0
  65. package/templates/nextjs/sui-card-duel/packages/contracts/package.json +49 -0
  66. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/config.ts +17 -0
  67. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-brawl.ts +270 -0
  68. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-duel.ts +272 -0
  69. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-lobby.ts +177 -0
  70. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-market.ts +219 -0
  71. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/e2e-session.ts +342 -0
  72. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/query-dapp-revenue.ts +95 -0
  73. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/seed.ts +92 -0
  74. package/templates/nextjs/sui-card-duel/packages/contracts/scripts/withdraw-dapp-revenue.ts +56 -0
  75. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/Move.toml +15 -0
  76. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/dapp_key.move +46 -0
  77. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/enums/card_kind.move +47 -0
  78. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/enums/match_state.move +37 -0
  79. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/enums/rarity.move +37 -0
  80. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/error.move +126 -0
  81. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/genesis.move +33 -0
  82. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/init_test.move +23 -0
  83. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/objects/arena.move +137 -0
  84. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/permits/brawl_permit.move +125 -0
  85. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/permits/duel_permit.move +125 -0
  86. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/battle_state.move +255 -0
  87. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/card.move +282 -0
  88. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/deck.move +64 -0
  89. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/game_config.move +267 -0
  90. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/gold.move +205 -0
  91. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/resources/profile.move +255 -0
  92. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/scenes/brawl.move +313 -0
  93. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/scenes/duel.move +313 -0
  94. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/codegen/user_storage_init.move +26 -0
  95. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/scripts/deploy_hook.move +32 -0
  96. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/scripts/migrate.move +7 -0
  97. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/arena_system.move +57 -0
  98. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/brawl_system.move +559 -0
  99. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/card_system.move +146 -0
  100. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/duel_system.move +515 -0
  101. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/market_system.move +115 -0
  102. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/systems/player_system.move +37 -0
  103. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/tests/brawl_tests.move +385 -0
  104. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/tests/duel_tests.move +656 -0
  105. package/templates/nextjs/sui-card-duel/packages/contracts/src/card_duel/sources/tests/test_helpers.move +31 -0
  106. package/templates/nextjs/sui-card-duel/packages/contracts/sui-indexer-schema.graphql +5973 -0
  107. package/templates/nextjs/sui-card-duel/pnpm-workspace.yaml +2 -0
  108. package/templates/nextjs/sui-farm/docker-compose.yml +2 -5
  109. package/templates/nextjs/sui-farm/packages/client/src/app/admin/page.tsx +618 -0
  110. package/templates/nextjs/sui-farm/packages/client/src/app/components/ProxyCard.tsx +1 -4
  111. package/templates/nextjs/sui-farm/packages/client/src/app/market/page.tsx +4 -13
  112. package/templates/nextjs/sui-farm/packages/client/src/app/page.tsx +142 -91
  113. package/templates/nextjs/sui-farm/packages/client/src/app/providers.tsx +4 -7
  114. package/templates/nextjs/sui-farm/packages/contracts/Dockerfile +1 -1
  115. package/templates/nextjs/sui-farm/packages/contracts/src/counter/sources/codegen/user_storage_init.move +6 -2
  116. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/dapp_key.move +16 -1
  117. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/permits/world.move +12 -9
  118. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/codegen/user_storage_init.move +6 -2
  119. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/crow_system.move +1 -5
  120. package/templates/nextjs/sui-farm/packages/contracts/src/harvest/sources/systems/world_system.move +1 -1
  121. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/dapp_key.move +16 -1
  122. package/templates/nextjs/sui-template/packages/contracts/src/counter/sources/codegen/user_storage_init.move +6 -2
  123. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/Move.lock +0 -6
  124. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/dapp_key.move +16 -1
  125. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/dapp_system.move +83 -42
  126. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/fee_test.move +2 -2
  127. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/integration_test.move +1 -1
  128. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/scene_session_test.move +269 -0
  129. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/typed_scene_test.move +25 -9
  130. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/user_storage_test.move +6 -6
  131. package/templates/nextjs/sui-farm/packages/client/src/app/hooks/useSessionKey.ts +0 -250
package/dist/cli.js CHANGED
@@ -62,7 +62,7 @@ var CHAINS = [
62
62
  // package.json
63
63
  var package_default = {
64
64
  name: "create-dubhe",
65
- version: "1.2.0-pre.123",
65
+ version: "1.2.0-pre.125",
66
66
  repository: {
67
67
  type: "git",
68
68
  url: "https://github.com/0xobelisk/dubhe.git"
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/bin/cli.ts","../src/config/chains.ts","../package.json","../src/exists.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport glob from 'fast-glob';\nimport yargsInteractive from 'yargs-interactive';\nimport { CHAINS } from '../config/chains';\nimport packageJson from '../../package.json';\nimport { exists } from '../exists';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst cwd = process.cwd();\n\nconst init = async () => {\n // Prepare chain options\n const chainChoices = CHAINS.map(({ title, description, value }) => ({\n name: `${title} - ${description}`,\n value\n }));\n\n // Step 1: Choose project name and chain\n const firstStep = await yargsInteractive()\n .usage('$0 [args]')\n .interactive({\n interactive: { default: true },\n projectName: {\n describe: 'Name your project',\n type: 'input'\n },\n chain: {\n describe: 'Pick your chain',\n type: 'list',\n choices: chainChoices.map((c) => c.value)\n },\n dubheVersion: {\n describe: 'The version of Dubhe packages to use, defaults to latest',\n type: 'input',\n default: packageJson.version\n }\n });\n\n const { projectName, chain, dubheVersion } = firstStep;\n if (!projectName) throw new Error('No project name provided.');\n\n // Get available templates based on the selected chain\n const selectedChain = CHAINS.find((c) => c.value === chain);\n if (!selectedChain) {\n throw new Error('Invalid chain selection');\n }\n\n // Prepare platform options\n const platformChoices = selectedChain.supportedTemplates.map(({ title, description, value }) => ({\n name: `${title} - ${description}`,\n value\n }));\n\n // Step 2: Choose platform\n const secondStep = await yargsInteractive()\n .usage('$0 [args]')\n .interactive({\n interactive: { default: true },\n platform: {\n describe: 'Pick your platform',\n type: 'list',\n choices: platformChoices.map((c) => c.value)\n }\n });\n\n const { platform } = secondStep;\n\n const selectedTemplate = selectedChain.supportedTemplates.find((t) => t.value === platform);\n if (!selectedTemplate) {\n throw new Error('Invalid platform selection');\n }\n\n const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent);\n const pkgManager = pkgInfo ? pkgInfo.name : 'npm';\n\n const sourceDir = path.join(\n __dirname,\n '..',\n 'templates',\n selectedTemplate.path.replace('{chain}', chain)\n );\n\n if (!(await exists(sourceDir))) {\n throw new Error(`Template directory not found: ${sourceDir}`);\n }\n\n const destDir = path.join(process.cwd(), projectName);\n if (await exists(destDir)) {\n throw new Error(`Target directory \"${destDir}\" already exists.`);\n }\n\n const files = await glob('**/*', { cwd: sourceDir, dot: true });\n\n for (const filename of files) {\n const sourceFile = path.join(sourceDir, filename);\n const destFile = path.join(destDir, filename);\n\n await fs.mkdir(path.dirname(destFile), { recursive: true });\n\n if (/package\\.json$/.test(sourceFile)) {\n const source = await fs.readFile(sourceFile, 'utf-8');\n await fs.writeFile(destFile, source.replaceAll(/{{dubhe-version}}/g, dubheVersion), 'utf-8');\n } else if (/\\.gitignore_$/.test(sourceFile)) {\n await fs.copyFile(sourceFile, destFile.replace(/_$/, ''));\n } else {\n await fs.copyFile(sourceFile, destFile);\n }\n }\n\n const cdProjectName = path.relative(cwd, destDir);\n\n const styles = {\n success: '\\x1b[32m%s\\x1b[0m',\n info: '\\x1b[36m%s\\x1b[0m',\n command: '\\x1b[33m%s\\x1b[0m',\n separator: '\\x1b[90m%s\\x1b[0m'\n };\n\n console.log('\\n' + '='.repeat(60));\n console.log(styles.success, '🎉 Project creation successful!');\n console.log(styles.info, `📁 Project location: ${destDir}`);\n console.log(styles.separator, '-'.repeat(60));\n console.log(styles.info, 'Next steps:\\n');\n\n if (destDir !== cwd) {\n console.log(\n styles.command,\n ` cd ${cdProjectName.includes(' ') ? `\"${cdProjectName}\"` : cdProjectName}`\n );\n }\n\n const actualTemplate = selectedTemplate.value;\n\n switch (actualTemplate) {\n case '101':\n case 'web':\n console.log(styles.command, ` ${pkgManager} install`);\n console.log(styles.command, ` ${pkgManager} dubhe doctor`);\n console.log(styles.command, ` ${pkgManager} run dev`);\n break;\n case 'contract':\n console.log(styles.command, ` ${pkgManager} install`);\n console.log(styles.command, ` ${pkgManager} dubhe doctor`);\n break;\n }\n\n console.log(styles.separator, '\\n' + '='.repeat(60) + '\\n');\n};\n\nfunction pkgFromUserAgent(userAgent: string | undefined) {\n if (!userAgent) return undefined;\n const pkgSpec = userAgent.split(' ')[0];\n const pkgSpecArr = pkgSpec.split('/');\n return {\n name: pkgSpecArr[0],\n version: pkgSpecArr[1]\n };\n}\n\ninit().catch((e) => {\n console.error(e);\n});\n","interface Template {\n title: string;\n description: string;\n value: string;\n path: string;\n}\n\ninterface Chain {\n title: string;\n description: string;\n value: string;\n supportedTemplates: Template[];\n}\n\nconst TEMPLATES = {\n QUICK_START: {\n title: '101',\n description: 'Quick start',\n value: '101',\n path: '101/{chain}-template'\n },\n WEB: {\n title: 'Web',\n description: 'Web template',\n value: 'web',\n path: 'nextjs/{chain}-template'\n },\n CONTRACT: {\n title: 'Contract',\n description: 'Contract template',\n value: 'contract',\n path: 'contract/{chain}-template'\n }\n} as const;\n\nexport const CHAINS: Chain[] = [\n {\n title: 'sui',\n description: 'Sui',\n value: 'sui',\n supportedTemplates: [TEMPLATES.QUICK_START, TEMPLATES.WEB, TEMPLATES.CONTRACT]\n },\n {\n title: 'aptos',\n description: 'Aptos',\n value: 'aptos',\n supportedTemplates: [TEMPLATES.QUICK_START, TEMPLATES.WEB, TEMPLATES.CONTRACT]\n },\n {\n title: 'rooch',\n description: 'Rooch',\n value: 'rooch',\n supportedTemplates: [TEMPLATES.QUICK_START]\n },\n {\n title: 'initia',\n description: 'Initia',\n value: 'initia',\n supportedTemplates: [TEMPLATES.QUICK_START]\n },\n {\n title: 'movement',\n description: 'Movement',\n value: 'movement',\n supportedTemplates: [TEMPLATES.QUICK_START]\n }\n];\n","{\n \"name\": \"create-dubhe\",\n \"version\": \"1.2.0-pre.123\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/0xobelisk/dubhe.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"team@obelisk.build\",\n \"type\": \"module\",\n \"bin\": \"bin/cli.js\",\n \"files\": [\n \"bin\",\n \"dist\",\n \"templates\"\n ],\n \"scripts\": {\n \"build\": \"pnpm run type-check && pnpm run build:js\",\n \"build:js\": \"tsup && pnpm run copy-templates\",\n \"clean\": \"pnpm run clean:js\",\n \"clean:js\": \"shx rm -rf dist\",\n \"cocos-js-build\": \"cd cocos-lib-builder && npm i && browserify aptos.js -p esmify > ../templates/cocos/aptos-template/assets/lib/dubhe.js && browserify sui.js -p esmify > ../templates/cocos/sui-template/assets/lib/dubhe.js\",\n \"copy-templates\": \"tsx ./scripts/copy-templates.ts\",\n \"dev\": \"tsup --watch\",\n \"format\": \"prettier --write .\",\n \"format:check\": \"prettier --check .\",\n \"lint\": \"eslint . --ext .ts\",\n \"type-check\": \"tsc --noEmit\",\n \"validate\": \"pnpm format:check && pnpm lint && pnpm type-check\"\n },\n \"dependencies\": {\n \"browser-resolve\": \"^2.0.0\",\n \"browser-sync\": \"^2.29.3\",\n \"fast-glob\": \"^3.3.3\",\n \"yargs-interactive\": \"^3.0.1\"\n },\n \"devDependencies\": {\n \"@types/cross-spawn\": \"^6.0.2\",\n \"@types/minimist\": \"^1.2.2\",\n \"@types/prompts\": \"^2.4.3\",\n \"@types/yargs-interactive\": \"^2.1.6\",\n \"browserify\": \"^17.0.0\",\n \"cross-spawn\": \"^7.0.3\",\n \"eslint\": \"^9.0.0\",\n \"eslint-config-prettier\": \"^9.1.0\",\n \"esmify\": \"^2.1.1\",\n \"kolorist\": \"^1.7.0\",\n \"prettier\": \"3.3.3\",\n \"prompts\": \"^2.4.2\",\n \"typescript\": \"^5.8.3\"\n },\n \"engines\": {\n \"node\": \">=22.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","import fs from 'node:fs/promises';\n\nexport async function exists(path: string) {\n try {\n await fs.access(path);\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":";AAAA,SAAS,qBAAqB;AAC9B,OAAOA,SAAQ;AACf,OAAO,UAAU;AACjB,OAAO,UAAU;AACjB,OAAO,sBAAsB;;;ACU7B,IAAM,YAAY;AAAA,EAChB,aAAa;AAAA,IACX,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,KAAK;AAAA,IACH,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AAAA,EACA,UAAU;AAAA,IACR,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,MAAM;AAAA,EACR;AACF;AAEO,IAAM,SAAkB;AAAA,EAC7B;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,oBAAoB,CAAC,UAAU,aAAa,UAAU,KAAK,UAAU,QAAQ;AAAA,EAC/E;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,oBAAoB,CAAC,UAAU,aAAa,UAAU,KAAK,UAAU,QAAQ;AAAA,EAC/E;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,oBAAoB,CAAC,UAAU,WAAW;AAAA,EAC5C;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,oBAAoB,CAAC,UAAU,WAAW;AAAA,EAC5C;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,aAAa;AAAA,IACb,OAAO;AAAA,IACP,oBAAoB,CAAC,UAAU,WAAW;AAAA,EAC5C;AACF;;;AClEA;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,YAAc;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,EACT;AAAA,EACA,SAAW;AAAA,EACX,QAAU;AAAA,EACV,MAAQ;AAAA,EACR,KAAO;AAAA,EACP,OAAS;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,YAAY;AAAA,IACZ,OAAS;AAAA,IACT,YAAY;AAAA,IACZ,kBAAkB;AAAA,IAClB,kBAAkB;AAAA,IAClB,KAAO;AAAA,IACP,QAAU;AAAA,IACV,gBAAgB;AAAA,IAChB,MAAQ;AAAA,IACR,cAAc;AAAA,IACd,UAAY;AAAA,EACd;AAAA,EACA,cAAgB;AAAA,IACd,mBAAmB;AAAA,IACnB,gBAAgB;AAAA,IAChB,aAAa;AAAA,IACb,qBAAqB;AAAA,EACvB;AAAA,EACA,iBAAmB;AAAA,IACjB,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,IAClB,4BAA4B;AAAA,IAC5B,YAAc;AAAA,IACd,eAAe;AAAA,IACf,QAAU;AAAA,IACV,0BAA0B;AAAA,IAC1B,QAAU;AAAA,IACV,UAAY;AAAA,IACZ,UAAY;AAAA,IACZ,SAAW;AAAA,IACX,YAAc;AAAA,EAChB;AAAA,EACA,SAAW;AAAA,IACT,MAAQ;AAAA,EACV;AAAA,EACA,eAAiB;AAAA,IACf,QAAU;AAAA,EACZ;AACF;;;ACzDA,OAAO,QAAQ;AAEf,eAAsB,OAAOC,OAAc;AACzC,MAAI;AACF,UAAM,GAAG,OAAOA,KAAI;AACpB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;;;AHAA,IAAM,aAAa,cAAc,YAAY,GAAG;AAChD,IAAM,YAAY,KAAK,QAAQ,UAAU;AAEzC,IAAM,MAAM,QAAQ,IAAI;AAExB,IAAM,OAAO,YAAY;AAEvB,QAAM,eAAe,OAAO,IAAI,CAAC,EAAE,OAAO,aAAa,MAAM,OAAO;AAAA,IAClE,MAAM,GAAG,KAAK,MAAM,WAAW;AAAA,IAC/B;AAAA,EACF,EAAE;AAGF,QAAM,YAAY,MAAM,iBAAiB,EACtC,MAAM,WAAW,EACjB,YAAY;AAAA,IACX,aAAa,EAAE,SAAS,KAAK;AAAA,IAC7B,aAAa;AAAA,MACX,UAAU;AAAA,MACV,MAAM;AAAA,IACR;AAAA,IACA,OAAO;AAAA,MACL,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,aAAa,IAAI,CAAC,MAAM,EAAE,KAAK;AAAA,IAC1C;AAAA,IACA,cAAc;AAAA,MACZ,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,gBAAY;AAAA,IACvB;AAAA,EACF,CAAC;AAEH,QAAM,EAAE,aAAa,OAAO,aAAa,IAAI;AAC7C,MAAI,CAAC,YAAa,OAAM,IAAI,MAAM,2BAA2B;AAG7D,QAAM,gBAAgB,OAAO,KAAK,CAAC,MAAM,EAAE,UAAU,KAAK;AAC1D,MAAI,CAAC,eAAe;AAClB,UAAM,IAAI,MAAM,yBAAyB;AAAA,EAC3C;AAGA,QAAM,kBAAkB,cAAc,mBAAmB,IAAI,CAAC,EAAE,OAAO,aAAa,MAAM,OAAO;AAAA,IAC/F,MAAM,GAAG,KAAK,MAAM,WAAW;AAAA,IAC/B;AAAA,EACF,EAAE;AAGF,QAAM,aAAa,MAAM,iBAAiB,EACvC,MAAM,WAAW,EACjB,YAAY;AAAA,IACX,aAAa,EAAE,SAAS,KAAK;AAAA,IAC7B,UAAU;AAAA,MACR,UAAU;AAAA,MACV,MAAM;AAAA,MACN,SAAS,gBAAgB,IAAI,CAAC,MAAM,EAAE,KAAK;AAAA,IAC7C;AAAA,EACF,CAAC;AAEH,QAAM,EAAE,SAAS,IAAI;AAErB,QAAM,mBAAmB,cAAc,mBAAmB,KAAK,CAAC,MAAM,EAAE,UAAU,QAAQ;AAC1F,MAAI,CAAC,kBAAkB;AACrB,UAAM,IAAI,MAAM,4BAA4B;AAAA,EAC9C;AAEA,QAAM,UAAU,iBAAiB,QAAQ,IAAI,qBAAqB;AAClE,QAAM,aAAa,UAAU,QAAQ,OAAO;AAE5C,QAAM,YAAY,KAAK;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,IACA,iBAAiB,KAAK,QAAQ,WAAW,KAAK;AAAA,EAChD;AAEA,MAAI,CAAE,MAAM,OAAO,SAAS,GAAI;AAC9B,UAAM,IAAI,MAAM,iCAAiC,SAAS,EAAE;AAAA,EAC9D;AAEA,QAAM,UAAU,KAAK,KAAK,QAAQ,IAAI,GAAG,WAAW;AACpD,MAAI,MAAM,OAAO,OAAO,GAAG;AACzB,UAAM,IAAI,MAAM,qBAAqB,OAAO,mBAAmB;AAAA,EACjE;AAEA,QAAM,QAAQ,MAAM,KAAK,QAAQ,EAAE,KAAK,WAAW,KAAK,KAAK,CAAC;AAE9D,aAAW,YAAY,OAAO;AAC5B,UAAM,aAAa,KAAK,KAAK,WAAW,QAAQ;AAChD,UAAM,WAAW,KAAK,KAAK,SAAS,QAAQ;AAE5C,UAAMC,IAAG,MAAM,KAAK,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAE1D,QAAI,iBAAiB,KAAK,UAAU,GAAG;AACrC,YAAM,SAAS,MAAMA,IAAG,SAAS,YAAY,OAAO;AACpD,YAAMA,IAAG,UAAU,UAAU,OAAO,WAAW,sBAAsB,YAAY,GAAG,OAAO;AAAA,IAC7F,WAAW,gBAAgB,KAAK,UAAU,GAAG;AAC3C,YAAMA,IAAG,SAAS,YAAY,SAAS,QAAQ,MAAM,EAAE,CAAC;AAAA,IAC1D,OAAO;AACL,YAAMA,IAAG,SAAS,YAAY,QAAQ;AAAA,IACxC;AAAA,EACF;AAEA,QAAM,gBAAgB,KAAK,SAAS,KAAK,OAAO;AAEhD,QAAM,SAAS;AAAA,IACb,SAAS;AAAA,IACT,MAAM;AAAA,IACN,SAAS;AAAA,IACT,WAAW;AAAA,EACb;AAEA,UAAQ,IAAI,OAAO,IAAI,OAAO,EAAE,CAAC;AACjC,UAAQ,IAAI,OAAO,SAAS,wCAAiC;AAC7D,UAAQ,IAAI,OAAO,MAAM,+BAAwB,OAAO,EAAE;AAC1D,UAAQ,IAAI,OAAO,WAAW,IAAI,OAAO,EAAE,CAAC;AAC5C,UAAQ,IAAI,OAAO,MAAM,eAAe;AAExC,MAAI,YAAY,KAAK;AACnB,YAAQ;AAAA,MACN,OAAO;AAAA,MACP,QAAQ,cAAc,SAAS,GAAG,IAAI,IAAI,aAAa,MAAM,aAAa;AAAA,IAC5E;AAAA,EACF;AAEA,QAAM,iBAAiB,iBAAiB;AAExC,UAAQ,gBAAgB;AAAA,IACtB,KAAK;AAAA,IACL,KAAK;AACH,cAAQ,IAAI,OAAO,SAAS,KAAK,UAAU,UAAU;AACrD,cAAQ,IAAI,OAAO,SAAS,KAAK,UAAU,eAAe;AAC1D,cAAQ,IAAI,OAAO,SAAS,KAAK,UAAU,UAAU;AACrD;AAAA,IACF,KAAK;AACH,cAAQ,IAAI,OAAO,SAAS,KAAK,UAAU,UAAU;AACrD,cAAQ,IAAI,OAAO,SAAS,KAAK,UAAU,eAAe;AAC1D;AAAA,EACJ;AAEA,UAAQ,IAAI,OAAO,WAAW,OAAO,IAAI,OAAO,EAAE,IAAI,IAAI;AAC5D;AAEA,SAAS,iBAAiB,WAA+B;AACvD,MAAI,CAAC,UAAW,QAAO;AACvB,QAAM,UAAU,UAAU,MAAM,GAAG,EAAE,CAAC;AACtC,QAAM,aAAa,QAAQ,MAAM,GAAG;AACpC,SAAO;AAAA,IACL,MAAM,WAAW,CAAC;AAAA,IAClB,SAAS,WAAW,CAAC;AAAA,EACvB;AACF;AAEA,KAAK,EAAE,MAAM,CAAC,MAAM;AAClB,UAAQ,MAAM,CAAC;AACjB,CAAC;","names":["fs","path","fs"]}
1
+ {"version":3,"sources":["../src/bin/cli.ts","../src/config/chains.ts","../package.json","../src/exists.ts"],"sourcesContent":["import { fileURLToPath } from 'node:url';\nimport fs from 'node:fs/promises';\nimport path from 'node:path';\nimport glob from 'fast-glob';\nimport yargsInteractive from 'yargs-interactive';\nimport { CHAINS } from '../config/chains';\nimport packageJson from '../../package.json';\nimport { exists } from '../exists';\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\n\nconst cwd = process.cwd();\n\nconst init = async () => {\n // Prepare chain options\n const chainChoices = CHAINS.map(({ title, description, value }) => ({\n name: `${title} - ${description}`,\n value\n }));\n\n // Step 1: Choose project name and chain\n const firstStep = await yargsInteractive()\n .usage('$0 [args]')\n .interactive({\n interactive: { default: true },\n projectName: {\n describe: 'Name your project',\n type: 'input'\n },\n chain: {\n describe: 'Pick your chain',\n type: 'list',\n choices: chainChoices.map((c) => c.value)\n },\n dubheVersion: {\n describe: 'The version of Dubhe packages to use, defaults to latest',\n type: 'input',\n default: packageJson.version\n }\n });\n\n const { projectName, chain, dubheVersion } = firstStep;\n if (!projectName) throw new Error('No project name provided.');\n\n // Get available templates based on the selected chain\n const selectedChain = CHAINS.find((c) => c.value === chain);\n if (!selectedChain) {\n throw new Error('Invalid chain selection');\n }\n\n // Prepare platform options\n const platformChoices = selectedChain.supportedTemplates.map(({ title, description, value }) => ({\n name: `${title} - ${description}`,\n value\n }));\n\n // Step 2: Choose platform\n const secondStep = await yargsInteractive()\n .usage('$0 [args]')\n .interactive({\n interactive: { default: true },\n platform: {\n describe: 'Pick your platform',\n type: 'list',\n choices: platformChoices.map((c) => c.value)\n }\n });\n\n const { platform } = secondStep;\n\n const selectedTemplate = selectedChain.supportedTemplates.find((t) => t.value === platform);\n if (!selectedTemplate) {\n throw new Error('Invalid platform selection');\n }\n\n const pkgInfo = pkgFromUserAgent(process.env.npm_config_user_agent);\n const pkgManager = pkgInfo ? pkgInfo.name : 'npm';\n\n const sourceDir = path.join(\n __dirname,\n '..',\n 'templates',\n selectedTemplate.path.replace('{chain}', chain)\n );\n\n if (!(await exists(sourceDir))) {\n throw new Error(`Template directory not found: ${sourceDir}`);\n }\n\n const destDir = path.join(process.cwd(), projectName);\n if (await exists(destDir)) {\n throw new Error(`Target directory \"${destDir}\" already exists.`);\n }\n\n const files = await glob('**/*', { cwd: sourceDir, dot: true });\n\n for (const filename of files) {\n const sourceFile = path.join(sourceDir, filename);\n const destFile = path.join(destDir, filename);\n\n await fs.mkdir(path.dirname(destFile), { recursive: true });\n\n if (/package\\.json$/.test(sourceFile)) {\n const source = await fs.readFile(sourceFile, 'utf-8');\n await fs.writeFile(destFile, source.replaceAll(/{{dubhe-version}}/g, dubheVersion), 'utf-8');\n } else if (/\\.gitignore_$/.test(sourceFile)) {\n await fs.copyFile(sourceFile, destFile.replace(/_$/, ''));\n } else {\n await fs.copyFile(sourceFile, destFile);\n }\n }\n\n const cdProjectName = path.relative(cwd, destDir);\n\n const styles = {\n success: '\\x1b[32m%s\\x1b[0m',\n info: '\\x1b[36m%s\\x1b[0m',\n command: '\\x1b[33m%s\\x1b[0m',\n separator: '\\x1b[90m%s\\x1b[0m'\n };\n\n console.log('\\n' + '='.repeat(60));\n console.log(styles.success, '🎉 Project creation successful!');\n console.log(styles.info, `📁 Project location: ${destDir}`);\n console.log(styles.separator, '-'.repeat(60));\n console.log(styles.info, 'Next steps:\\n');\n\n if (destDir !== cwd) {\n console.log(\n styles.command,\n ` cd ${cdProjectName.includes(' ') ? `\"${cdProjectName}\"` : cdProjectName}`\n );\n }\n\n const actualTemplate = selectedTemplate.value;\n\n switch (actualTemplate) {\n case '101':\n case 'web':\n console.log(styles.command, ` ${pkgManager} install`);\n console.log(styles.command, ` ${pkgManager} dubhe doctor`);\n console.log(styles.command, ` ${pkgManager} run dev`);\n break;\n case 'contract':\n console.log(styles.command, ` ${pkgManager} install`);\n console.log(styles.command, ` ${pkgManager} dubhe doctor`);\n break;\n }\n\n console.log(styles.separator, '\\n' + '='.repeat(60) + '\\n');\n};\n\nfunction pkgFromUserAgent(userAgent: string | undefined) {\n if (!userAgent) return undefined;\n const pkgSpec = userAgent.split(' ')[0];\n const pkgSpecArr = pkgSpec.split('/');\n return {\n name: pkgSpecArr[0],\n version: pkgSpecArr[1]\n };\n}\n\ninit().catch((e) => {\n console.error(e);\n});\n","interface Template {\n title: string;\n description: string;\n value: string;\n path: string;\n}\n\ninterface Chain {\n title: string;\n description: string;\n value: string;\n supportedTemplates: Template[];\n}\n\nconst TEMPLATES = {\n QUICK_START: {\n title: '101',\n description: 'Quick start',\n value: '101',\n path: '101/{chain}-template'\n },\n WEB: {\n title: 'Web',\n description: 'Web template',\n value: 'web',\n path: 'nextjs/{chain}-template'\n },\n CONTRACT: {\n title: 'Contract',\n description: 'Contract template',\n value: 'contract',\n path: 'contract/{chain}-template'\n }\n} as const;\n\nexport const CHAINS: Chain[] = [\n {\n title: 'sui',\n description: 'Sui',\n value: 'sui',\n supportedTemplates: [TEMPLATES.QUICK_START, TEMPLATES.WEB, TEMPLATES.CONTRACT]\n },\n {\n title: 'aptos',\n description: 'Aptos',\n value: 'aptos',\n supportedTemplates: [TEMPLATES.QUICK_START, TEMPLATES.WEB, TEMPLATES.CONTRACT]\n },\n {\n title: 'rooch',\n description: 'Rooch',\n value: 'rooch',\n supportedTemplates: [TEMPLATES.QUICK_START]\n },\n {\n title: 'initia',\n description: 'Initia',\n value: 'initia',\n supportedTemplates: [TEMPLATES.QUICK_START]\n },\n {\n title: 'movement',\n description: 'Movement',\n value: 'movement',\n supportedTemplates: [TEMPLATES.QUICK_START]\n }\n];\n","{\n \"name\": \"create-dubhe\",\n \"version\": \"1.2.0-pre.125\",\n \"repository\": {\n \"type\": \"git\",\n \"url\": \"https://github.com/0xobelisk/dubhe.git\"\n },\n \"license\": \"MIT\",\n \"author\": \"team@obelisk.build\",\n \"type\": \"module\",\n \"bin\": \"bin/cli.js\",\n \"files\": [\n \"bin\",\n \"dist\",\n \"templates\"\n ],\n \"scripts\": {\n \"build\": \"pnpm run type-check && pnpm run build:js\",\n \"build:js\": \"tsup && pnpm run copy-templates\",\n \"clean\": \"pnpm run clean:js\",\n \"clean:js\": \"shx rm -rf dist\",\n \"cocos-js-build\": \"cd cocos-lib-builder && npm i && browserify aptos.js -p esmify > ../templates/cocos/aptos-template/assets/lib/dubhe.js && browserify sui.js -p esmify > ../templates/cocos/sui-template/assets/lib/dubhe.js\",\n \"copy-templates\": \"tsx ./scripts/copy-templates.ts\",\n \"dev\": \"tsup --watch\",\n \"format\": \"prettier --write .\",\n \"format:check\": \"prettier --check .\",\n \"lint\": \"eslint . --ext .ts\",\n \"type-check\": \"tsc --noEmit\",\n \"validate\": \"pnpm format:check && pnpm lint && pnpm type-check\"\n },\n \"dependencies\": {\n \"browser-resolve\": \"^2.0.0\",\n \"browser-sync\": \"^2.29.3\",\n \"fast-glob\": \"^3.3.3\",\n \"yargs-interactive\": \"^3.0.1\"\n },\n \"devDependencies\": {\n \"@types/cross-spawn\": \"^6.0.2\",\n \"@types/minimist\": \"^1.2.2\",\n \"@types/prompts\": \"^2.4.3\",\n \"@types/yargs-interactive\": \"^2.1.6\",\n \"browserify\": \"^17.0.0\",\n \"cross-spawn\": \"^7.0.3\",\n \"eslint\": \"^9.0.0\",\n \"eslint-config-prettier\": \"^9.1.0\",\n \"esmify\": \"^2.1.1\",\n \"kolorist\": \"^1.7.0\",\n \"prettier\": \"3.3.3\",\n \"prompts\": \"^2.4.2\",\n \"typescript\": \"^5.8.3\"\n },\n \"engines\": {\n \"node\": \">=22.0.0\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n }\n}\n","import fs from 'node:fs/promises';\n\nexport async function exists(path: string) {\n try {\n await fs.access(path);\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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","names":["fs","path","fs"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-dubhe",
3
- "version": "1.2.0-pre.123",
3
+ "version": "1.2.0-pre.125",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/0xobelisk/dubhe.git"
@@ -8,10 +8,25 @@ module counter::dapp_key {
8
8
  use sui::address;
9
9
  use std::ascii::String;
10
10
 
11
- /// Authorization token for the app.
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.
12
25
 
13
26
  public struct DappKey has copy, drop {}
14
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.
15
30
  public(package) fun new(): DappKey {
16
31
  DappKey {}
17
32
  }
@@ -6,17 +6,21 @@
6
6
  module counter::user_storage_init {
7
7
  use dubhe::dapp_service::{DappHub, DappStorage};
8
8
  use dubhe::dapp_system;
9
+ use counter::dapp_key;
9
10
  use counter::dapp_key::DappKey;
11
+ use counter::migrate;
10
12
 
11
13
  /// Create a UserStorage for the transaction sender within this DApp.
12
14
  /// Must be called once before the user can interact with any user-level resources.
13
- /// Aborts if the DApp is currently suspended or the framework version has advanced.
15
+ /// Aborts if the DApp version does not match this package, the DApp is paused,
16
+ /// or the framework version has advanced.
14
17
  #[allow(lint(public_entry))]
15
18
  public entry fun init_user_storage(
16
19
  dapp_hub: &DappHub,
17
20
  dapp_storage: &mut DappStorage,
18
21
  ctx: &mut TxContext,
19
22
  ) {
20
- dapp_system::create_user_storage<DappKey>(dapp_hub, dapp_storage, ctx);
23
+ dapp_system::ensure_latest_version<DappKey>(dapp_storage, migrate::on_chain_version());
24
+ dapp_system::create_user_storage(dapp_key::new(), dapp_hub, dapp_storage, ctx);
21
25
  }
22
26
  }
@@ -39,9 +39,3 @@ source = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-f
39
39
  use_environment = "testnet"
40
40
  manifest_digest = "7AFB66695545775FBFBB2D3078ADFD084244D5002392E837FDE21D9EA1C6D01C"
41
41
  deps = { MoveStdlib = "MoveStdlib" }
42
-
43
- [env.mainnet]
44
- chain-id = "35834a8a"
45
- original-published-id = "0xdd59a0e210585ec38da6d966d2936c7476b9e08b3cc2f785ca998d084bf24c81"
46
- latest-published-id = "0xdd59a0e210585ec38da6d966d2936c7476b9e08b3cc2f785ca998d084bf24c81"
47
- published-version = "1"
@@ -8,10 +8,25 @@ module dubhe::dapp_key {
8
8
  use sui::address;
9
9
  use std::ascii::String;
10
10
 
11
- /// Authorization token for the app.
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.
12
25
 
13
26
  public struct DappKey has copy, drop {}
14
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.
15
30
  public(package) fun new(): DappKey {
16
31
  DappKey {}
17
32
  }
@@ -147,6 +147,7 @@ public fun create_dapp<DappKey: copy + drop>(
147
147
  /// canonical owner also cannot create a duplicate while their storage is held
148
148
  /// by the proxy.
149
149
  public fun create_user_storage<DappKey: copy + drop>(
150
+ _auth: DappKey,
150
151
  dapp_hub: &DappHub,
151
152
  dapp_storage: &mut DappStorage,
152
153
  ctx: &mut TxContext,
@@ -277,9 +278,10 @@ public fun delete_field<DappKey: copy + drop>(
277
278
  //
278
279
  // Reactive writes allow one participant to modify another participant's UserStorage
279
280
  // within a shared scene context. Four-layer security:
280
- // 1. ctx.sender() must be from.canonical_owner (only owner can initiate)
281
- // 2. from must be a registered scene participant
282
- // 3. target must be a registered scene participant
281
+ // 1. ctx.sender() must be authorized to write `from` (canonical owner or its
282
+ // active session key sessions are delegated proxies for in-scene actions)
283
+ // 2. from's canonical owner must be a registered scene participant
284
+ // 3. target's canonical owner must be a registered scene participant
283
285
  // 4. scene must be active (not expired)
284
286
  //
285
287
  // Write fees are charged to the initiator (`from`) under the initiator-pays model.
@@ -303,8 +305,8 @@ public fun set_record_reactive<DappKey: copy + drop, PermType>(
303
305
  let scene_id = dapp_service::scene_permit_id(permit);
304
306
  let meta = dapp_service::scene_permit_meta(permit);
305
307
 
306
- // 1. Sender must be the initiator's canonical owner.
307
- error::not_canonical_owner(ctx.sender() == dapp_service::canonical_owner(from));
308
+ // 1. Sender must be authorized to write `from` (canonical owner or active session key).
309
+ error::no_permission(dapp_service::is_write_authorized(from, ctx.sender(), ctx.epoch_timestamp_ms()));
308
310
  // 2. Initiator must be a scene participant (O(1) DF lookup).
309
311
  error::not_scene_participant(dapp_service::is_scene_participant(scene_id, dapp_service::canonical_owner(from)));
310
312
  // 3. Target must be a scene participant (O(1) DF lookup).
@@ -342,7 +344,7 @@ public fun set_field_reactive<DappKey: copy + drop, PermType>(
342
344
  let scene_id = dapp_service::scene_permit_id(permit);
343
345
  let meta = dapp_service::scene_permit_meta(permit);
344
346
 
345
- error::not_canonical_owner(ctx.sender() == dapp_service::canonical_owner(from));
347
+ error::no_permission(dapp_service::is_write_authorized(from, ctx.sender(), ctx.epoch_timestamp_ms()));
346
348
  error::not_scene_participant(dapp_service::is_scene_participant(scene_id, dapp_service::canonical_owner(from)));
347
349
  error::not_scene_participant(dapp_service::is_scene_participant(scene_id, dapp_service::canonical_owner(target)));
348
350
  error::scene_expired(dapp_service::is_scene_active(meta, ctx.epoch_timestamp_ms()));
@@ -503,19 +505,27 @@ public fun remove_object_field<DappKey: copy + drop, ObjType, T: store + copy +
503
505
 
504
506
  /// Remove and return a native-typed field from a permit-bound SceneStorage Bag.
505
507
  /// Emits a Dubhe_Scene_DeleteField event so off-chain indexers stay in sync.
508
+ /// The caller identifies as `user_storage`'s canonical owner; the transaction may be
509
+ /// signed by the canonical owner or its active session key (is_write_authorized).
506
510
  public fun remove_scene_field<DappKey: copy + drop, PermType, SceneType, T: store + copy + drop>(
507
- _auth: DappKey,
508
- permit: &ScenePermit<PermType>,
509
- storage: &mut SceneStorage<SceneType>,
510
- field_name: vector<u8>,
511
- ctx: &TxContext,
511
+ _auth: DappKey,
512
+ permit: &ScenePermit<PermType>,
513
+ storage: &mut SceneStorage<SceneType>,
514
+ user_storage: &UserStorage,
515
+ field_name: vector<u8>,
516
+ ctx: &TxContext,
512
517
  ): T {
513
518
  let dapp_key_str = type_info::get_type_name_string<DappKey>();
514
519
  error::dapp_key_mismatch(dapp_service::scene_storage_dapp_key(storage) == dapp_key_str);
515
520
  error::dapp_key_mismatch(dapp_service::scene_permit_dapp_key(permit) == dapp_key_str);
521
+ error::dapp_key_mismatch(dapp_service::user_storage_dapp_key(user_storage) == dapp_key_str);
516
522
  assert_scene_storage_bound_to_permit(permit, storage);
517
- error::scene_expired(dapp_service::is_scene_active(dapp_service::scene_permit_meta(permit), ctx.epoch_timestamp_ms()));
518
- error::not_scene_participant(dapp_service::is_participant_in_scene_permit(permit, ctx.sender()));
523
+ let now_ms = ctx.epoch_timestamp_ms();
524
+ error::scene_expired(dapp_service::is_scene_active(dapp_service::scene_permit_meta(permit), now_ms));
525
+ error::no_permission(dapp_service::is_write_authorized(user_storage, ctx.sender(), now_ms));
526
+ error::not_scene_participant(dapp_service::is_participant_in_scene_permit(
527
+ permit, dapp_service::canonical_owner(user_storage)
528
+ ));
519
529
 
520
530
  let scene_type = *dapp_service::scene_storage_type(storage);
521
531
  let scene_id = sui::object::uid_to_address(dapp_service::scene_storage_id(storage));
@@ -728,20 +738,28 @@ public fun share_scene_storage<DappKey: copy + drop, SceneType>(
728
738
  }
729
739
 
730
740
  /// Write a native-typed field into a permit-bound SceneStorage Bag and emit an event.
741
+ /// The caller identifies as `user_storage`'s canonical owner; the transaction may be
742
+ /// signed by the canonical owner or its active session key (is_write_authorized).
731
743
  public fun set_scene_field<DappKey: copy + drop, PermType, SceneType, T: store + copy + drop>(
732
- _auth: DappKey,
733
- permit: &ScenePermit<PermType>,
734
- storage: &mut SceneStorage<SceneType>,
735
- field_name: vector<u8>,
736
- value: T,
737
- ctx: &TxContext,
744
+ _auth: DappKey,
745
+ permit: &ScenePermit<PermType>,
746
+ storage: &mut SceneStorage<SceneType>,
747
+ user_storage: &UserStorage,
748
+ field_name: vector<u8>,
749
+ value: T,
750
+ ctx: &TxContext,
738
751
  ) {
739
752
  let dapp_key_str = type_info::get_type_name_string<DappKey>();
740
753
  error::dapp_key_mismatch(dapp_service::scene_storage_dapp_key(storage) == dapp_key_str);
741
754
  error::dapp_key_mismatch(dapp_service::scene_permit_dapp_key(permit) == dapp_key_str);
755
+ error::dapp_key_mismatch(dapp_service::user_storage_dapp_key(user_storage) == dapp_key_str);
742
756
  assert_scene_storage_bound_to_permit(permit, storage);
743
- error::scene_expired(dapp_service::is_scene_active(dapp_service::scene_permit_meta(permit), ctx.epoch_timestamp_ms()));
744
- error::not_scene_participant(dapp_service::is_participant_in_scene_permit(permit, ctx.sender()));
757
+ let now_ms = ctx.epoch_timestamp_ms();
758
+ error::scene_expired(dapp_service::is_scene_active(dapp_service::scene_permit_meta(permit), now_ms));
759
+ error::no_permission(dapp_service::is_write_authorized(user_storage, ctx.sender(), now_ms));
760
+ error::not_scene_participant(dapp_service::is_participant_in_scene_permit(
761
+ permit, dapp_service::canonical_owner(user_storage)
762
+ ));
745
763
 
746
764
  let event_bytes = sui::bcs::to_bytes(&value);
747
765
  dapp_service::set_scene_field(storage, field_name, value);
@@ -828,19 +846,25 @@ public fun destroy_scene_permit<DappKey: copy + drop, PermType>(
828
846
  }
829
847
 
830
848
  /// Helper: accept a scene invitation for a ScenePermit-backed scene.
831
- /// Moves ctx.sender() from the invitees list to confirmed participants.
849
+ /// Moves the caller's canonical owner from the invitees list to confirmed
850
+ /// participants. The transaction may be signed by the canonical owner or its
851
+ /// active session key (is_write_authorized) — the registered identity is
852
+ /// always the canonical owner address.
832
853
  /// Guards: scene must be active AND the invitation window must not have expired.
833
854
  public fun accept_scene_permit_invitation<DappKey: copy + drop, PermType>(
834
- _auth: DappKey,
835
- permit: &mut ScenePermit<PermType>,
836
- ctx: &TxContext,
855
+ _auth: DappKey,
856
+ permit: &mut ScenePermit<PermType>,
857
+ user_storage: &UserStorage,
858
+ ctx: &TxContext,
837
859
  ) {
838
860
  let dapp_key_str = type_info::get_type_name_string<DappKey>();
839
861
  error::dapp_key_mismatch(dapp_service::scene_permit_dapp_key(permit) == dapp_key_str);
862
+ error::dapp_key_mismatch(dapp_service::user_storage_dapp_key(user_storage) == dapp_key_str);
840
863
 
841
864
  // Check both permit activity and invitation window before mutating.
842
865
  // The immutable borrow of `meta` is released at the end of this block.
843
866
  let now_ms = ctx.epoch_timestamp_ms();
867
+ error::no_permission(dapp_service::is_write_authorized(user_storage, ctx.sender(), now_ms));
844
868
  {
845
869
  let meta = dapp_service::scene_permit_meta(permit);
846
870
  error::scene_expired(dapp_service::is_scene_active(meta, now_ms));
@@ -850,54 +874,71 @@ public fun accept_scene_permit_invitation<DappKey: copy + drop, PermType>(
850
874
  };
851
875
  };
852
876
 
853
- dapp_service::accept_invitation_in_scene_permit(permit, ctx.sender());
877
+ let owner = dapp_service::canonical_owner(user_storage);
878
+ dapp_service::accept_invitation_in_scene_permit(permit, owner);
854
879
  dubhe_events::emit_scene_permit_accept(
855
880
  dapp_key_str,
856
881
  *dapp_service::scene_permit_type(permit),
857
882
  sui::object::uid_to_address(dapp_service::scene_permit_id(permit)),
858
- ctx.sender(),
883
+ owner,
859
884
  );
860
885
  }
861
886
 
862
- /// Helper: add the caller as a confirmed participant in a ScenePermit.
887
+ /// Helper: add the caller's canonical owner as a confirmed participant in a
888
+ /// ScenePermit. The transaction may be signed by the canonical owner or its
889
+ /// active session key (is_write_authorized) — the registered identity is
890
+ /// always the canonical owner address.
863
891
  /// The permit must still be active — joining an expired permit is meaningless and
864
892
  /// wastes gas on a DF write that can never be used for reactive writes.
865
893
  public fun join_scene_permit<DappKey: copy + drop, PermType>(
866
- _auth: DappKey,
867
- permit: &mut ScenePermit<PermType>,
868
- ctx: &TxContext,
894
+ _auth: DappKey,
895
+ permit: &mut ScenePermit<PermType>,
896
+ user_storage: &UserStorage,
897
+ ctx: &TxContext,
869
898
  ) {
870
899
  let dapp_key_str = type_info::get_type_name_string<DappKey>();
871
900
  error::dapp_key_mismatch(dapp_service::scene_permit_dapp_key(permit) == dapp_key_str);
872
- error::scene_expired(dapp_service::is_scene_active(dapp_service::scene_permit_meta(permit), ctx.epoch_timestamp_ms()));
873
- let was_participant = dapp_service::is_participant_in_scene_permit(permit, ctx.sender());
874
- dapp_service::add_participant_in_scene_permit(permit, ctx.sender());
901
+ error::dapp_key_mismatch(dapp_service::user_storage_dapp_key(user_storage) == dapp_key_str);
902
+ let now_ms = ctx.epoch_timestamp_ms();
903
+ error::scene_expired(dapp_service::is_scene_active(dapp_service::scene_permit_meta(permit), now_ms));
904
+ error::no_permission(dapp_service::is_write_authorized(user_storage, ctx.sender(), now_ms));
905
+ let owner = dapp_service::canonical_owner(user_storage);
906
+ let was_participant = dapp_service::is_participant_in_scene_permit(permit, owner);
907
+ dapp_service::add_participant_in_scene_permit(permit, owner);
875
908
  if (!was_participant) {
876
909
  dubhe_events::emit_scene_permit_join(
877
910
  dapp_key_str,
878
911
  *dapp_service::scene_permit_type(permit),
879
912
  sui::object::uid_to_address(dapp_service::scene_permit_id(permit)),
880
- ctx.sender(),
913
+ owner,
881
914
  );
882
915
  };
883
916
  }
884
917
 
885
- /// Helper: remove the caller from participants in a SceneStorage scene.
918
+ /// Helper: remove the caller's canonical owner from participants in a
919
+ /// SceneStorage scene. The transaction may be signed by the canonical owner or
920
+ /// its active session key (is_write_authorized).
886
921
  public fun leave_scene_permit<DappKey: copy + drop, PermType>(
887
- _auth: DappKey,
888
- permit: &mut ScenePermit<PermType>,
889
- ctx: &TxContext,
922
+ _auth: DappKey,
923
+ permit: &mut ScenePermit<PermType>,
924
+ user_storage: &UserStorage,
925
+ ctx: &TxContext,
890
926
  ) {
891
927
  let dapp_key_str = type_info::get_type_name_string<DappKey>();
892
928
  error::dapp_key_mismatch(dapp_service::scene_permit_dapp_key(permit) == dapp_key_str);
893
- let was_participant = dapp_service::is_participant_in_scene_permit(permit, ctx.sender());
894
- dapp_service::remove_participant_in_scene_permit(permit, ctx.sender());
929
+ error::dapp_key_mismatch(dapp_service::user_storage_dapp_key(user_storage) == dapp_key_str);
930
+ error::no_permission(dapp_service::is_write_authorized(
931
+ user_storage, ctx.sender(), ctx.epoch_timestamp_ms()
932
+ ));
933
+ let owner = dapp_service::canonical_owner(user_storage);
934
+ let was_participant = dapp_service::is_participant_in_scene_permit(permit, owner);
935
+ dapp_service::remove_participant_in_scene_permit(permit, owner);
895
936
  if (was_participant) {
896
937
  dubhe_events::emit_scene_permit_leave(
897
938
  dapp_key_str,
898
939
  *dapp_service::scene_permit_type(permit),
899
940
  sui::object::uid_to_address(dapp_service::scene_permit_id(permit)),
900
- ctx.sender(),
941
+ owner,
901
942
  );
902
943
  };
903
944
  }
@@ -700,7 +700,7 @@ fun test_create_user_storage_succeeds_at_correct_version() {
700
700
  // Framework version == FRAMEWORK_VERSION (1) — must succeed.
701
701
  assert!(dapp_service::framework_version(&dh) == dapp_system::framework_version());
702
702
 
703
- dapp_system::create_user_storage<FeeKey>(&dh, &mut ds, ctx);
703
+ dapp_system::create_user_storage(FeeKey {}, &dh, &mut ds, ctx);
704
704
  assert!(dapp_service::has_registered_user_storage(&ds, sender));
705
705
 
706
706
  dapp_system::destroy_dapp_hub(dh);
@@ -753,7 +753,7 @@ fun test_create_user_storage_aborts_after_framework_version_bump() {
753
753
  dapp_service::set_framework_version(&mut dh, 2);
754
754
 
755
755
  // This package still has FRAMEWORK_VERSION = 1, so the call must abort.
756
- dapp_system::create_user_storage<FeeKey>(&dh, &mut ds, ctx);
756
+ dapp_system::create_user_storage(FeeKey {}, &dh, &mut ds, ctx);
757
757
 
758
758
  dapp_system::destroy_dapp_hub(dh);
759
759
  dapp_system::destroy_dapp_storage(ds);
@@ -251,7 +251,7 @@ fun test_user_can_always_create_storage() {
251
251
  test_scenario::next_tx(&mut scenario, USER_A);
252
252
  {
253
253
  let ctx = test_scenario::ctx(&mut scenario);
254
- dapp_system::create_user_storage<GameKey>(&dh, &mut ds, ctx);
254
+ dapp_system::create_user_storage(GameKey {}, &dh, &mut ds, ctx);
255
255
  assert!(dapp_service::has_registered_user_storage(&ds, USER_A));
256
256
  };
257
257