create-dubhe 1.2.0-pre.83 → 1.2.0-pre.85

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 (21) 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/dubhe/Move.lock +3 -3
  5. package/templates/101/sui-template/packages/contracts/src/dubhe/Move.toml +1 -1
  6. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/codegen/genesis.move +1 -2
  7. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/scripts/migrate.move +5 -1
  8. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/systems/address_system.move +296 -0
  9. package/templates/101/sui-template/packages/contracts/src/dubhe/sources/tests/address.move +55 -0
  10. package/templates/contract/sui-template/src/dubhe/Move.lock +3 -3
  11. package/templates/contract/sui-template/src/dubhe/Move.toml +1 -1
  12. package/templates/contract/sui-template/src/dubhe/sources/codegen/genesis.move +1 -2
  13. package/templates/contract/sui-template/src/dubhe/sources/scripts/migrate.move +5 -1
  14. package/templates/contract/sui-template/src/dubhe/sources/systems/address_system.move +296 -0
  15. package/templates/contract/sui-template/src/dubhe/sources/tests/address.move +55 -0
  16. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/Move.lock +3 -3
  17. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/Move.toml +1 -1
  18. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/codegen/genesis.move +1 -2
  19. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/scripts/migrate.move +5 -1
  20. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/systems/address_system.move +296 -0
  21. package/templates/nextjs/sui-template/packages/contracts/src/dubhe/sources/tests/address.move +55 -0
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.83",
65
+ version: "1.2.0-pre.85",
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.83\",\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"]}
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.85\",\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.83",
3
+ "version": "1.2.0-pre.85",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/0xobelisk/dubhe.git"
@@ -2,7 +2,7 @@
2
2
 
3
3
  [move]
4
4
  version = 3
5
- manifest_digest = "F67D57D8267A12BCCF8A98B2566F9B6A8DF5853272672F0EACE1F23EDF0CEAFD"
5
+ manifest_digest = "73896F00312A2E2C47F56DCCABF824967268FF718658DD5D0FFFE2E60824F94A"
6
6
  deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082"
7
7
  dependencies = [
8
8
  { id = "Sui", name = "Sui" },
@@ -28,5 +28,5 @@ flavor = "sui"
28
28
  [env.testnet]
29
29
  chain-id = "4c78adac"
30
30
  original-published-id = "0xa09cd4137e604ec5a7a88f72c572ecd064b0e713a3fbf705a88456cdbccf36c0"
31
- latest-published-id = "0xf98fe9c454a40f7d7fa37e19cf3ca5ea8351e24bb6d9fdd2d4da471c694a1796"
32
- published-version = "2"
31
+ latest-published-id = "0x4613b8a390298cc450fe11360fddf41ba1bde38060163c5ca9f192a25b4f9f2e"
32
+ published-version = "3"
@@ -4,7 +4,7 @@ edition = "2024"
4
4
  version = "1.0.0"
5
5
  license = "apache2.0"
6
6
  authors = ["Obelisk Labs"]
7
- published-at = "0xf98fe9c454a40f7d7fa37e19cf3ca5ea8351e24bb6d9fdd2d4da471c694a1796"
7
+ published-at = "0x4613b8a390298cc450fe11360fddf41ba1bde38060163c5ca9f192a25b4f9f2e"
8
8
 
9
9
  [dependencies]
10
10
  Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.46.3" }
@@ -82,8 +82,7 @@
82
82
  dapp_system::upgrade_dapp(dapp_hub, dapp_key, new_package_id, new_version, ctx);
83
83
  // Register new tables
84
84
  // ==========================================
85
- asset_add_liquidity::register_table(dapp_hub, ctx);
86
- asset_remove_liquidity::register_table(dapp_hub, ctx);
85
+
87
86
  // ==========================================
88
87
  }
89
88
  }
@@ -2,7 +2,7 @@ module dubhe::migrate {
2
2
  use dubhe::dapp_service::DappHub;
3
3
  use dubhe::genesis;
4
4
 
5
- const ON_CHAIN_VERSION: u32 = 2;
5
+ const ON_CHAIN_VERSION: u32 = 3;
6
6
 
7
7
  public fun on_chain_version(): u32 {
8
8
  ON_CHAIN_VERSION
@@ -11,4 +11,8 @@ module dubhe::migrate {
11
11
  public entry fun migrate_to_v2(dapp_hub: &mut DappHub, new_package_id: address, new_version: u32, ctx: &mut TxContext) {
12
12
  genesis::upgrade(dapp_hub, new_package_id, new_version, ctx);
13
13
  }
14
+
15
+ public entry fun migrate_to_v3(dapp_hub: &mut DappHub, new_package_id: address, new_version: u32, ctx: &mut TxContext) {
16
+ genesis::upgrade(dapp_hub, new_package_id, new_version, ctx);
17
+ }
14
18
  }
@@ -0,0 +1,296 @@
1
+ module dubhe::address_system;
2
+
3
+ use std::ascii::String;
4
+ use sui::address;
5
+ use sui::hex;
6
+
7
+ #[test_only]
8
+ use sui::test_scenario;
9
+
10
+ // TX_HASH signature markers
11
+ const DUBHE_PREFIX: u8 = 0xDB;
12
+ const DUBHE_VERSION: u8 = 0x01;
13
+ const CHAIN_TYPE_EVM: u8 = 0xE1;
14
+ const CHAIN_TYPE_SOLANA: u8 = 0xE2;
15
+
16
+ // Constants
17
+ const TX_HASH_LENGTH: u64 = 32;
18
+ const SOLANA_ADDRESS_LENGTH: u64 = 32;
19
+ const EVM_ADDRESS_LENGTH: u64 = 20;
20
+
21
+ // Error codes
22
+ const E_INVALID_EVM_ADDRESS: u64 = 1;
23
+ const E_INVALID_SOLANA_ADDRESS: u64 = 2;
24
+
25
+ /// Detect chain type from tx_hash signature
26
+ /// Returns: 0 = SUI, 1 = EVM, 2 = Solana
27
+ /// Format: [0xDB][0xDB][0x01][CHAIN_TYPE][...28 bytes...]
28
+ fun detect_chain_type_from_tx_hash(tx_hash: &vector<u8>): u8 {
29
+ if (tx_hash.length() != TX_HASH_LENGTH ||
30
+ tx_hash[0] != DUBHE_PREFIX ||
31
+ tx_hash[1] != DUBHE_PREFIX ||
32
+ tx_hash[2] != DUBHE_VERSION) {
33
+ return 0
34
+ };
35
+
36
+ let chain_type = tx_hash[3];
37
+ if (chain_type == CHAIN_TYPE_EVM) {
38
+ 1
39
+ } else if (chain_type == CHAIN_TYPE_SOLANA) {
40
+ 2
41
+ } else {
42
+ 0
43
+ }
44
+ }
45
+
46
+ fun hex_string_to_bytes(hex_str: String): vector<u8> {
47
+ let bytes = hex_str.into_bytes();
48
+ let hex_bytes = if (bytes.length() >= 2 && bytes[0] == 48 && (bytes[1] == 120 || bytes[1] == 88)) {
49
+ let mut result = vector[];
50
+ let mut i = 2;
51
+ while (i < bytes.length()) {
52
+ result.push_back(bytes[i]);
53
+ i = i + 1;
54
+ };
55
+ result
56
+ } else {
57
+ bytes
58
+ };
59
+ hex::decode(hex_bytes)
60
+ }
61
+
62
+ fun base58_decode(input: String): vector<u8> {
63
+ let base58_alphabet = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
64
+ let input_bytes = input.as_bytes();
65
+ let len = input_bytes.length();
66
+
67
+ let mut result: vector<u8> = vector[];
68
+ let mut j = 0;
69
+ while (j < SOLANA_ADDRESS_LENGTH) {
70
+ result.push_back(0u8);
71
+ j = j + 1;
72
+ };
73
+
74
+ let mut i = 0;
75
+ while (i < len) {
76
+ let c = input_bytes[i];
77
+ let mut char_value: u64 = 0;
78
+ let mut found = false;
79
+ let mut k = 0;
80
+ while (k < 58) {
81
+ if (base58_alphabet[k] == c) {
82
+ char_value = k;
83
+ found = true;
84
+ break
85
+ };
86
+ k = k + 1;
87
+ };
88
+
89
+ assert!(found, E_INVALID_SOLANA_ADDRESS);
90
+
91
+ let mut carry = char_value;
92
+ let mut m = (SOLANA_ADDRESS_LENGTH - 1);
93
+ while (m < SOLANA_ADDRESS_LENGTH) {
94
+ let byte_ref = vector::borrow_mut(&mut result, m);
95
+ let tmp = (*byte_ref as u64) * 58 + carry;
96
+ carry = tmp / 256;
97
+ *byte_ref = ((tmp % 256) as u8);
98
+ if (m == 0) break;
99
+ m = m - 1;
100
+ };
101
+ i = i + 1;
102
+ };
103
+ result
104
+ }
105
+
106
+ /// Convert EVM address to SUI address
107
+ /// Format: [12 zero bytes][20 bytes EVM address]
108
+ public fun evm_to_sui(evm_address_str: String): address {
109
+ let evm_bytes = hex_string_to_bytes(evm_address_str);
110
+ assert!(evm_bytes.length() == EVM_ADDRESS_LENGTH, E_INVALID_EVM_ADDRESS);
111
+
112
+ let mut sui_bytes = vector[];
113
+ let mut i = 0;
114
+ while (i < 12) {
115
+ sui_bytes.push_back(0u8);
116
+ i = i + 1;
117
+ };
118
+ sui_bytes.append(evm_bytes);
119
+ address::from_bytes(sui_bytes)
120
+ }
121
+
122
+ /// Convert Solana address to SUI address
123
+ /// Direct use of 32 bytes from Base58 decode
124
+ public fun solana_to_sui(solana_address_str: String): address {
125
+ let solana_bytes = base58_decode(solana_address_str);
126
+ assert!(solana_bytes.length() == SOLANA_ADDRESS_LENGTH, E_INVALID_SOLANA_ADDRESS);
127
+ address::from_bytes(solana_bytes)
128
+ }
129
+
130
+ fun base58_encode(input: vector<u8>): String {
131
+ let base58_alphabet = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
132
+ let mut result = vector::empty<u8>();
133
+ let mut num = input;
134
+
135
+ let mut leading_zeros = 0;
136
+ let mut i = 0;
137
+ while (i < num.length()) {
138
+ if (num[i] == 0) {
139
+ leading_zeros = leading_zeros + 1;
140
+ i = i + 1;
141
+ } else {
142
+ break
143
+ }
144
+ };
145
+
146
+ while (!is_zero(&num)) {
147
+ let remainder = div_mod_58(&mut num);
148
+ result.push_back(base58_alphabet[remainder]);
149
+ };
150
+
151
+ let mut j = 0;
152
+ while (j < leading_zeros) {
153
+ result.push_back(49);
154
+ j = j + 1;
155
+ };
156
+
157
+ vector::reverse(&mut result);
158
+ result.to_ascii_string()
159
+ }
160
+
161
+ fun is_zero(num: &vector<u8>): bool {
162
+ let mut i = 0;
163
+ while (i < num.length()) {
164
+ if (num[i] != 0) {
165
+ return false
166
+ };
167
+ i = i + 1;
168
+ };
169
+ true
170
+ }
171
+
172
+ fun div_mod_58(num: &mut vector<u8>): u64 {
173
+ let mut remainder: u64 = 0;
174
+ let mut i = 0;
175
+ while (i < num.length()) {
176
+ let byte_ref = vector::borrow_mut(num, i);
177
+ let current = (remainder * 256) + (*byte_ref as u64);
178
+ *byte_ref = ((current / 58) as u8);
179
+ remainder = current % 58;
180
+ i = i + 1;
181
+ };
182
+ remainder
183
+ }
184
+
185
+ /// Get original address format based on tx_hash detection
186
+ /// Returns: EVM (0x...), Solana (Base58), or SUI (0x...) format
187
+ public fun ensure_origin(ctx: &TxContext): String {
188
+ let sui_address = ctx.sender();
189
+ let address_bytes = address::to_bytes(sui_address);
190
+ let tx_hash = ctx.digest();
191
+ let chain_type = detect_chain_type_from_tx_hash(tx_hash);
192
+
193
+ if (chain_type == 1) {
194
+ let mut evm_bytes = vector[];
195
+ let mut j = 12;
196
+ while (j < TX_HASH_LENGTH) {
197
+ evm_bytes.push_back(address_bytes[j]);
198
+ j = j + 1;
199
+ };
200
+ let hex_bytes = hex::encode(evm_bytes);
201
+ let mut result_bytes = b"0x";
202
+ result_bytes.append(hex_bytes);
203
+ result_bytes.to_ascii_string()
204
+ } else if (chain_type == 2) {
205
+ base58_encode(address_bytes)
206
+ } else {
207
+ let hex_bytes = hex::encode(address_bytes);
208
+ let mut result_bytes = b"0x";
209
+ result_bytes.append(hex_bytes);
210
+ result_bytes.to_ascii_string()
211
+ }
212
+ }
213
+
214
+ /// Check if transaction is from EVM chain
215
+ public fun is_evm_address(ctx: &TxContext): bool {
216
+ let tx_hash = ctx.digest();
217
+ detect_chain_type_from_tx_hash(tx_hash) == 1
218
+ }
219
+
220
+ /// Check if transaction is from Solana
221
+ public fun is_solana_address(ctx: &TxContext): bool {
222
+ let tx_hash = ctx.digest();
223
+ detect_chain_type_from_tx_hash(tx_hash) == 2
224
+ }
225
+
226
+ /// Check if transaction is native SUI
227
+ public fun is_sui_address(ctx: &TxContext): bool {
228
+ let tx_hash = ctx.digest();
229
+ detect_chain_type_from_tx_hash(tx_hash) == 0
230
+ }
231
+
232
+ // ========== Test Utilities ==========
233
+
234
+ #[test_only]
235
+ /// Setup test scenario with EVM context
236
+ /// Input: EVM address as byte string, e.g., b"0x9168765EE952de7C6f8fC6FaD5Ec209B960b7622"
237
+ /// Format: [0xDB][0xDB][0x01][0xE1][...28 bytes...]
238
+ public fun setup_evm_scenario(scenario: &mut test_scenario::Scenario, evm_address_bytes: vector<u8>) {
239
+ use std::ascii;
240
+
241
+ // Convert EVM address string to SUI address
242
+ let evm_address_str = ascii::string(evm_address_bytes);
243
+ let sender = evm_to_sui(evm_address_str);
244
+
245
+ // Generate EVM tx_hash with Dubhe prefix at the beginning
246
+ let mut tx_hash = vector::empty<u8>();
247
+
248
+ // Mark as EVM with Dubhe prefix, version, and chain type
249
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
250
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
251
+ tx_hash.push_back(DUBHE_VERSION); // 0x01
252
+ tx_hash.push_back(CHAIN_TYPE_EVM); // 0xE1
253
+
254
+ // Fill remaining 28 bytes
255
+ let mut i = 0;
256
+ while (i < 28) {
257
+ tx_hash.push_back((i as u8));
258
+ i = i + 1;
259
+ };
260
+
261
+ // Set context
262
+ let ctx = test_scenario::ctx(scenario);
263
+ *ctx = tx_context::new(sender, tx_hash, 0, 0, 0);
264
+ }
265
+
266
+ #[test_only]
267
+ /// Setup test scenario with Solana context
268
+ /// Input: Solana address as byte string, e.g., b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L"
269
+ /// Format: [0xDB][0xDB][0x01][0xE2][...28 bytes...]
270
+ public fun setup_solana_scenario(scenario: &mut test_scenario::Scenario, solana_address_bytes: vector<u8>) {
271
+ use std::ascii;
272
+
273
+ // Convert Solana address string to SUI address
274
+ let solana_address_str = ascii::string(solana_address_bytes);
275
+ let sender = solana_to_sui(solana_address_str);
276
+
277
+ // Generate Solana tx_hash with Dubhe prefix at the beginning
278
+ let mut tx_hash = vector::empty<u8>();
279
+
280
+ // Mark as Solana with Dubhe prefix, version, and chain type
281
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
282
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
283
+ tx_hash.push_back(DUBHE_VERSION); // 0x01
284
+ tx_hash.push_back(CHAIN_TYPE_SOLANA); // 0xE2
285
+
286
+ // Fill remaining 28 bytes
287
+ let mut i = 0;
288
+ while (i < 28) {
289
+ tx_hash.push_back(((i + 100) as u8));
290
+ i = i + 1;
291
+ };
292
+
293
+ // Set context
294
+ let ctx = test_scenario::ctx(scenario);
295
+ *ctx = tx_context::new(sender, tx_hash, 0, 0, 0);
296
+ }
@@ -0,0 +1,55 @@
1
+ #[test_only]
2
+ module dubhe::address_test;
3
+
4
+ use dubhe::address_system;
5
+ use sui::test_scenario;
6
+ use std::ascii::string;
7
+
8
+ #[test]
9
+ public fun test_address_conversion() {
10
+ let sui_sender = @0x1462cab50fe5998f8161378e5265f7920bfd9fbce604d602619962f608837217;
11
+ let sui_origin_string = string(b"0x1462cab50fe5998f8161378e5265f7920bfd9fbce604d602619962f608837217");
12
+ let evm_origin_string = string(b"0x9168765ee952de7c6f8fc6fad5ec209b960b7622");
13
+ let solana_origin_string = string(b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L");
14
+ let mut scenario = test_scenario::begin(sui_sender);
15
+
16
+ // Test EVM address conversion
17
+ std::debug::print(&string(b"EVM address:"));
18
+ std::debug::print(&evm_origin_string);
19
+ let evm_sui_address = address_system::evm_to_sui(evm_origin_string);
20
+ std::debug::print(&string(b"EVM->SUI:"));
21
+ std::debug::print(&evm_sui_address.to_ascii_string());
22
+
23
+ // Test Solana address conversion
24
+ let solana_address_str = string(b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L");
25
+ let solana_sui_address = address_system::solana_to_sui(solana_address_str);
26
+ std::debug::print(&string(b"Solana->SUI:"));
27
+ std::debug::print(&solana_sui_address.to_ascii_string());
28
+
29
+ // Test SUI address detection
30
+ {
31
+ let ctx = test_scenario::ctx(&mut scenario);
32
+ assert!(address_system::is_sui_address(ctx));
33
+ assert!(address_system::ensure_origin(ctx) == sui_origin_string);
34
+ };
35
+
36
+ // Test EVM address detection
37
+ address_system::setup_evm_scenario(&mut scenario, b"0x9168765EE952de7C6f8fC6FaD5Ec209B960b7622");
38
+ {
39
+ let ctx = test_scenario::ctx(&mut scenario);
40
+ assert!(address_system::is_evm_address(ctx));
41
+ std::debug::print(&string(b"evm_origin_string:"));
42
+ std::debug::print(&address_system::ensure_origin(ctx));
43
+ assert!(address_system::ensure_origin(ctx) == evm_origin_string);
44
+ };
45
+
46
+ // Test Solana address detection
47
+ address_system::setup_solana_scenario(&mut scenario, b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L");
48
+ {
49
+ let ctx = test_scenario::ctx(&mut scenario);
50
+ assert!(address_system::is_solana_address(ctx));
51
+ assert!(address_system::ensure_origin(ctx) == solana_origin_string);
52
+ };
53
+
54
+ scenario.end();
55
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  [move]
4
4
  version = 3
5
- manifest_digest = "F67D57D8267A12BCCF8A98B2566F9B6A8DF5853272672F0EACE1F23EDF0CEAFD"
5
+ manifest_digest = "73896F00312A2E2C47F56DCCABF824967268FF718658DD5D0FFFE2E60824F94A"
6
6
  deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082"
7
7
  dependencies = [
8
8
  { id = "Sui", name = "Sui" },
@@ -28,5 +28,5 @@ flavor = "sui"
28
28
  [env.testnet]
29
29
  chain-id = "4c78adac"
30
30
  original-published-id = "0xa09cd4137e604ec5a7a88f72c572ecd064b0e713a3fbf705a88456cdbccf36c0"
31
- latest-published-id = "0xf98fe9c454a40f7d7fa37e19cf3ca5ea8351e24bb6d9fdd2d4da471c694a1796"
32
- published-version = "2"
31
+ latest-published-id = "0x4613b8a390298cc450fe11360fddf41ba1bde38060163c5ca9f192a25b4f9f2e"
32
+ published-version = "3"
@@ -4,7 +4,7 @@ edition = "2024"
4
4
  version = "1.0.0"
5
5
  license = "apache2.0"
6
6
  authors = ["Obelisk Labs"]
7
- published-at = "0xf98fe9c454a40f7d7fa37e19cf3ca5ea8351e24bb6d9fdd2d4da471c694a1796"
7
+ published-at = "0x4613b8a390298cc450fe11360fddf41ba1bde38060163c5ca9f192a25b4f9f2e"
8
8
 
9
9
  [dependencies]
10
10
  Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.46.3" }
@@ -82,8 +82,7 @@
82
82
  dapp_system::upgrade_dapp(dapp_hub, dapp_key, new_package_id, new_version, ctx);
83
83
  // Register new tables
84
84
  // ==========================================
85
- asset_add_liquidity::register_table(dapp_hub, ctx);
86
- asset_remove_liquidity::register_table(dapp_hub, ctx);
85
+
87
86
  // ==========================================
88
87
  }
89
88
  }
@@ -2,7 +2,7 @@ module dubhe::migrate {
2
2
  use dubhe::dapp_service::DappHub;
3
3
  use dubhe::genesis;
4
4
 
5
- const ON_CHAIN_VERSION: u32 = 2;
5
+ const ON_CHAIN_VERSION: u32 = 3;
6
6
 
7
7
  public fun on_chain_version(): u32 {
8
8
  ON_CHAIN_VERSION
@@ -11,4 +11,8 @@ module dubhe::migrate {
11
11
  public entry fun migrate_to_v2(dapp_hub: &mut DappHub, new_package_id: address, new_version: u32, ctx: &mut TxContext) {
12
12
  genesis::upgrade(dapp_hub, new_package_id, new_version, ctx);
13
13
  }
14
+
15
+ public entry fun migrate_to_v3(dapp_hub: &mut DappHub, new_package_id: address, new_version: u32, ctx: &mut TxContext) {
16
+ genesis::upgrade(dapp_hub, new_package_id, new_version, ctx);
17
+ }
14
18
  }
@@ -0,0 +1,296 @@
1
+ module dubhe::address_system;
2
+
3
+ use std::ascii::String;
4
+ use sui::address;
5
+ use sui::hex;
6
+
7
+ #[test_only]
8
+ use sui::test_scenario;
9
+
10
+ // TX_HASH signature markers
11
+ const DUBHE_PREFIX: u8 = 0xDB;
12
+ const DUBHE_VERSION: u8 = 0x01;
13
+ const CHAIN_TYPE_EVM: u8 = 0xE1;
14
+ const CHAIN_TYPE_SOLANA: u8 = 0xE2;
15
+
16
+ // Constants
17
+ const TX_HASH_LENGTH: u64 = 32;
18
+ const SOLANA_ADDRESS_LENGTH: u64 = 32;
19
+ const EVM_ADDRESS_LENGTH: u64 = 20;
20
+
21
+ // Error codes
22
+ const E_INVALID_EVM_ADDRESS: u64 = 1;
23
+ const E_INVALID_SOLANA_ADDRESS: u64 = 2;
24
+
25
+ /// Detect chain type from tx_hash signature
26
+ /// Returns: 0 = SUI, 1 = EVM, 2 = Solana
27
+ /// Format: [0xDB][0xDB][0x01][CHAIN_TYPE][...28 bytes...]
28
+ fun detect_chain_type_from_tx_hash(tx_hash: &vector<u8>): u8 {
29
+ if (tx_hash.length() != TX_HASH_LENGTH ||
30
+ tx_hash[0] != DUBHE_PREFIX ||
31
+ tx_hash[1] != DUBHE_PREFIX ||
32
+ tx_hash[2] != DUBHE_VERSION) {
33
+ return 0
34
+ };
35
+
36
+ let chain_type = tx_hash[3];
37
+ if (chain_type == CHAIN_TYPE_EVM) {
38
+ 1
39
+ } else if (chain_type == CHAIN_TYPE_SOLANA) {
40
+ 2
41
+ } else {
42
+ 0
43
+ }
44
+ }
45
+
46
+ fun hex_string_to_bytes(hex_str: String): vector<u8> {
47
+ let bytes = hex_str.into_bytes();
48
+ let hex_bytes = if (bytes.length() >= 2 && bytes[0] == 48 && (bytes[1] == 120 || bytes[1] == 88)) {
49
+ let mut result = vector[];
50
+ let mut i = 2;
51
+ while (i < bytes.length()) {
52
+ result.push_back(bytes[i]);
53
+ i = i + 1;
54
+ };
55
+ result
56
+ } else {
57
+ bytes
58
+ };
59
+ hex::decode(hex_bytes)
60
+ }
61
+
62
+ fun base58_decode(input: String): vector<u8> {
63
+ let base58_alphabet = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
64
+ let input_bytes = input.as_bytes();
65
+ let len = input_bytes.length();
66
+
67
+ let mut result: vector<u8> = vector[];
68
+ let mut j = 0;
69
+ while (j < SOLANA_ADDRESS_LENGTH) {
70
+ result.push_back(0u8);
71
+ j = j + 1;
72
+ };
73
+
74
+ let mut i = 0;
75
+ while (i < len) {
76
+ let c = input_bytes[i];
77
+ let mut char_value: u64 = 0;
78
+ let mut found = false;
79
+ let mut k = 0;
80
+ while (k < 58) {
81
+ if (base58_alphabet[k] == c) {
82
+ char_value = k;
83
+ found = true;
84
+ break
85
+ };
86
+ k = k + 1;
87
+ };
88
+
89
+ assert!(found, E_INVALID_SOLANA_ADDRESS);
90
+
91
+ let mut carry = char_value;
92
+ let mut m = (SOLANA_ADDRESS_LENGTH - 1);
93
+ while (m < SOLANA_ADDRESS_LENGTH) {
94
+ let byte_ref = vector::borrow_mut(&mut result, m);
95
+ let tmp = (*byte_ref as u64) * 58 + carry;
96
+ carry = tmp / 256;
97
+ *byte_ref = ((tmp % 256) as u8);
98
+ if (m == 0) break;
99
+ m = m - 1;
100
+ };
101
+ i = i + 1;
102
+ };
103
+ result
104
+ }
105
+
106
+ /// Convert EVM address to SUI address
107
+ /// Format: [12 zero bytes][20 bytes EVM address]
108
+ public fun evm_to_sui(evm_address_str: String): address {
109
+ let evm_bytes = hex_string_to_bytes(evm_address_str);
110
+ assert!(evm_bytes.length() == EVM_ADDRESS_LENGTH, E_INVALID_EVM_ADDRESS);
111
+
112
+ let mut sui_bytes = vector[];
113
+ let mut i = 0;
114
+ while (i < 12) {
115
+ sui_bytes.push_back(0u8);
116
+ i = i + 1;
117
+ };
118
+ sui_bytes.append(evm_bytes);
119
+ address::from_bytes(sui_bytes)
120
+ }
121
+
122
+ /// Convert Solana address to SUI address
123
+ /// Direct use of 32 bytes from Base58 decode
124
+ public fun solana_to_sui(solana_address_str: String): address {
125
+ let solana_bytes = base58_decode(solana_address_str);
126
+ assert!(solana_bytes.length() == SOLANA_ADDRESS_LENGTH, E_INVALID_SOLANA_ADDRESS);
127
+ address::from_bytes(solana_bytes)
128
+ }
129
+
130
+ fun base58_encode(input: vector<u8>): String {
131
+ let base58_alphabet = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
132
+ let mut result = vector::empty<u8>();
133
+ let mut num = input;
134
+
135
+ let mut leading_zeros = 0;
136
+ let mut i = 0;
137
+ while (i < num.length()) {
138
+ if (num[i] == 0) {
139
+ leading_zeros = leading_zeros + 1;
140
+ i = i + 1;
141
+ } else {
142
+ break
143
+ }
144
+ };
145
+
146
+ while (!is_zero(&num)) {
147
+ let remainder = div_mod_58(&mut num);
148
+ result.push_back(base58_alphabet[remainder]);
149
+ };
150
+
151
+ let mut j = 0;
152
+ while (j < leading_zeros) {
153
+ result.push_back(49);
154
+ j = j + 1;
155
+ };
156
+
157
+ vector::reverse(&mut result);
158
+ result.to_ascii_string()
159
+ }
160
+
161
+ fun is_zero(num: &vector<u8>): bool {
162
+ let mut i = 0;
163
+ while (i < num.length()) {
164
+ if (num[i] != 0) {
165
+ return false
166
+ };
167
+ i = i + 1;
168
+ };
169
+ true
170
+ }
171
+
172
+ fun div_mod_58(num: &mut vector<u8>): u64 {
173
+ let mut remainder: u64 = 0;
174
+ let mut i = 0;
175
+ while (i < num.length()) {
176
+ let byte_ref = vector::borrow_mut(num, i);
177
+ let current = (remainder * 256) + (*byte_ref as u64);
178
+ *byte_ref = ((current / 58) as u8);
179
+ remainder = current % 58;
180
+ i = i + 1;
181
+ };
182
+ remainder
183
+ }
184
+
185
+ /// Get original address format based on tx_hash detection
186
+ /// Returns: EVM (0x...), Solana (Base58), or SUI (0x...) format
187
+ public fun ensure_origin(ctx: &TxContext): String {
188
+ let sui_address = ctx.sender();
189
+ let address_bytes = address::to_bytes(sui_address);
190
+ let tx_hash = ctx.digest();
191
+ let chain_type = detect_chain_type_from_tx_hash(tx_hash);
192
+
193
+ if (chain_type == 1) {
194
+ let mut evm_bytes = vector[];
195
+ let mut j = 12;
196
+ while (j < TX_HASH_LENGTH) {
197
+ evm_bytes.push_back(address_bytes[j]);
198
+ j = j + 1;
199
+ };
200
+ let hex_bytes = hex::encode(evm_bytes);
201
+ let mut result_bytes = b"0x";
202
+ result_bytes.append(hex_bytes);
203
+ result_bytes.to_ascii_string()
204
+ } else if (chain_type == 2) {
205
+ base58_encode(address_bytes)
206
+ } else {
207
+ let hex_bytes = hex::encode(address_bytes);
208
+ let mut result_bytes = b"0x";
209
+ result_bytes.append(hex_bytes);
210
+ result_bytes.to_ascii_string()
211
+ }
212
+ }
213
+
214
+ /// Check if transaction is from EVM chain
215
+ public fun is_evm_address(ctx: &TxContext): bool {
216
+ let tx_hash = ctx.digest();
217
+ detect_chain_type_from_tx_hash(tx_hash) == 1
218
+ }
219
+
220
+ /// Check if transaction is from Solana
221
+ public fun is_solana_address(ctx: &TxContext): bool {
222
+ let tx_hash = ctx.digest();
223
+ detect_chain_type_from_tx_hash(tx_hash) == 2
224
+ }
225
+
226
+ /// Check if transaction is native SUI
227
+ public fun is_sui_address(ctx: &TxContext): bool {
228
+ let tx_hash = ctx.digest();
229
+ detect_chain_type_from_tx_hash(tx_hash) == 0
230
+ }
231
+
232
+ // ========== Test Utilities ==========
233
+
234
+ #[test_only]
235
+ /// Setup test scenario with EVM context
236
+ /// Input: EVM address as byte string, e.g., b"0x9168765EE952de7C6f8fC6FaD5Ec209B960b7622"
237
+ /// Format: [0xDB][0xDB][0x01][0xE1][...28 bytes...]
238
+ public fun setup_evm_scenario(scenario: &mut test_scenario::Scenario, evm_address_bytes: vector<u8>) {
239
+ use std::ascii;
240
+
241
+ // Convert EVM address string to SUI address
242
+ let evm_address_str = ascii::string(evm_address_bytes);
243
+ let sender = evm_to_sui(evm_address_str);
244
+
245
+ // Generate EVM tx_hash with Dubhe prefix at the beginning
246
+ let mut tx_hash = vector::empty<u8>();
247
+
248
+ // Mark as EVM with Dubhe prefix, version, and chain type
249
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
250
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
251
+ tx_hash.push_back(DUBHE_VERSION); // 0x01
252
+ tx_hash.push_back(CHAIN_TYPE_EVM); // 0xE1
253
+
254
+ // Fill remaining 28 bytes
255
+ let mut i = 0;
256
+ while (i < 28) {
257
+ tx_hash.push_back((i as u8));
258
+ i = i + 1;
259
+ };
260
+
261
+ // Set context
262
+ let ctx = test_scenario::ctx(scenario);
263
+ *ctx = tx_context::new(sender, tx_hash, 0, 0, 0);
264
+ }
265
+
266
+ #[test_only]
267
+ /// Setup test scenario with Solana context
268
+ /// Input: Solana address as byte string, e.g., b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L"
269
+ /// Format: [0xDB][0xDB][0x01][0xE2][...28 bytes...]
270
+ public fun setup_solana_scenario(scenario: &mut test_scenario::Scenario, solana_address_bytes: vector<u8>) {
271
+ use std::ascii;
272
+
273
+ // Convert Solana address string to SUI address
274
+ let solana_address_str = ascii::string(solana_address_bytes);
275
+ let sender = solana_to_sui(solana_address_str);
276
+
277
+ // Generate Solana tx_hash with Dubhe prefix at the beginning
278
+ let mut tx_hash = vector::empty<u8>();
279
+
280
+ // Mark as Solana with Dubhe prefix, version, and chain type
281
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
282
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
283
+ tx_hash.push_back(DUBHE_VERSION); // 0x01
284
+ tx_hash.push_back(CHAIN_TYPE_SOLANA); // 0xE2
285
+
286
+ // Fill remaining 28 bytes
287
+ let mut i = 0;
288
+ while (i < 28) {
289
+ tx_hash.push_back(((i + 100) as u8));
290
+ i = i + 1;
291
+ };
292
+
293
+ // Set context
294
+ let ctx = test_scenario::ctx(scenario);
295
+ *ctx = tx_context::new(sender, tx_hash, 0, 0, 0);
296
+ }
@@ -0,0 +1,55 @@
1
+ #[test_only]
2
+ module dubhe::address_test;
3
+
4
+ use dubhe::address_system;
5
+ use sui::test_scenario;
6
+ use std::ascii::string;
7
+
8
+ #[test]
9
+ public fun test_address_conversion() {
10
+ let sui_sender = @0x1462cab50fe5998f8161378e5265f7920bfd9fbce604d602619962f608837217;
11
+ let sui_origin_string = string(b"0x1462cab50fe5998f8161378e5265f7920bfd9fbce604d602619962f608837217");
12
+ let evm_origin_string = string(b"0x9168765ee952de7c6f8fc6fad5ec209b960b7622");
13
+ let solana_origin_string = string(b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L");
14
+ let mut scenario = test_scenario::begin(sui_sender);
15
+
16
+ // Test EVM address conversion
17
+ std::debug::print(&string(b"EVM address:"));
18
+ std::debug::print(&evm_origin_string);
19
+ let evm_sui_address = address_system::evm_to_sui(evm_origin_string);
20
+ std::debug::print(&string(b"EVM->SUI:"));
21
+ std::debug::print(&evm_sui_address.to_ascii_string());
22
+
23
+ // Test Solana address conversion
24
+ let solana_address_str = string(b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L");
25
+ let solana_sui_address = address_system::solana_to_sui(solana_address_str);
26
+ std::debug::print(&string(b"Solana->SUI:"));
27
+ std::debug::print(&solana_sui_address.to_ascii_string());
28
+
29
+ // Test SUI address detection
30
+ {
31
+ let ctx = test_scenario::ctx(&mut scenario);
32
+ assert!(address_system::is_sui_address(ctx));
33
+ assert!(address_system::ensure_origin(ctx) == sui_origin_string);
34
+ };
35
+
36
+ // Test EVM address detection
37
+ address_system::setup_evm_scenario(&mut scenario, b"0x9168765EE952de7C6f8fC6FaD5Ec209B960b7622");
38
+ {
39
+ let ctx = test_scenario::ctx(&mut scenario);
40
+ assert!(address_system::is_evm_address(ctx));
41
+ std::debug::print(&string(b"evm_origin_string:"));
42
+ std::debug::print(&address_system::ensure_origin(ctx));
43
+ assert!(address_system::ensure_origin(ctx) == evm_origin_string);
44
+ };
45
+
46
+ // Test Solana address detection
47
+ address_system::setup_solana_scenario(&mut scenario, b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L");
48
+ {
49
+ let ctx = test_scenario::ctx(&mut scenario);
50
+ assert!(address_system::is_solana_address(ctx));
51
+ assert!(address_system::ensure_origin(ctx) == solana_origin_string);
52
+ };
53
+
54
+ scenario.end();
55
+ }
@@ -2,7 +2,7 @@
2
2
 
3
3
  [move]
4
4
  version = 3
5
- manifest_digest = "F67D57D8267A12BCCF8A98B2566F9B6A8DF5853272672F0EACE1F23EDF0CEAFD"
5
+ manifest_digest = "73896F00312A2E2C47F56DCCABF824967268FF718658DD5D0FFFE2E60824F94A"
6
6
  deps_digest = "F8BBB0CCB2491CA29A3DF03D6F92277A4F3574266507ACD77214D37ECA3F3082"
7
7
  dependencies = [
8
8
  { id = "Sui", name = "Sui" },
@@ -28,5 +28,5 @@ flavor = "sui"
28
28
  [env.testnet]
29
29
  chain-id = "4c78adac"
30
30
  original-published-id = "0xa09cd4137e604ec5a7a88f72c572ecd064b0e713a3fbf705a88456cdbccf36c0"
31
- latest-published-id = "0xf98fe9c454a40f7d7fa37e19cf3ca5ea8351e24bb6d9fdd2d4da471c694a1796"
32
- published-version = "2"
31
+ latest-published-id = "0x4613b8a390298cc450fe11360fddf41ba1bde38060163c5ca9f192a25b4f9f2e"
32
+ published-version = "3"
@@ -4,7 +4,7 @@ edition = "2024"
4
4
  version = "1.0.0"
5
5
  license = "apache2.0"
6
6
  authors = ["Obelisk Labs"]
7
- published-at = "0xf98fe9c454a40f7d7fa37e19cf3ca5ea8351e24bb6d9fdd2d4da471c694a1796"
7
+ published-at = "0x4613b8a390298cc450fe11360fddf41ba1bde38060163c5ca9f192a25b4f9f2e"
8
8
 
9
9
  [dependencies]
10
10
  Sui = { git = "https://github.com/MystenLabs/sui.git", subdir = "crates/sui-framework/packages/sui-framework", rev = "mainnet-v1.46.3" }
@@ -82,8 +82,7 @@
82
82
  dapp_system::upgrade_dapp(dapp_hub, dapp_key, new_package_id, new_version, ctx);
83
83
  // Register new tables
84
84
  // ==========================================
85
- asset_add_liquidity::register_table(dapp_hub, ctx);
86
- asset_remove_liquidity::register_table(dapp_hub, ctx);
85
+
87
86
  // ==========================================
88
87
  }
89
88
  }
@@ -2,7 +2,7 @@ module dubhe::migrate {
2
2
  use dubhe::dapp_service::DappHub;
3
3
  use dubhe::genesis;
4
4
 
5
- const ON_CHAIN_VERSION: u32 = 2;
5
+ const ON_CHAIN_VERSION: u32 = 3;
6
6
 
7
7
  public fun on_chain_version(): u32 {
8
8
  ON_CHAIN_VERSION
@@ -11,4 +11,8 @@ module dubhe::migrate {
11
11
  public entry fun migrate_to_v2(dapp_hub: &mut DappHub, new_package_id: address, new_version: u32, ctx: &mut TxContext) {
12
12
  genesis::upgrade(dapp_hub, new_package_id, new_version, ctx);
13
13
  }
14
+
15
+ public entry fun migrate_to_v3(dapp_hub: &mut DappHub, new_package_id: address, new_version: u32, ctx: &mut TxContext) {
16
+ genesis::upgrade(dapp_hub, new_package_id, new_version, ctx);
17
+ }
14
18
  }
@@ -0,0 +1,296 @@
1
+ module dubhe::address_system;
2
+
3
+ use std::ascii::String;
4
+ use sui::address;
5
+ use sui::hex;
6
+
7
+ #[test_only]
8
+ use sui::test_scenario;
9
+
10
+ // TX_HASH signature markers
11
+ const DUBHE_PREFIX: u8 = 0xDB;
12
+ const DUBHE_VERSION: u8 = 0x01;
13
+ const CHAIN_TYPE_EVM: u8 = 0xE1;
14
+ const CHAIN_TYPE_SOLANA: u8 = 0xE2;
15
+
16
+ // Constants
17
+ const TX_HASH_LENGTH: u64 = 32;
18
+ const SOLANA_ADDRESS_LENGTH: u64 = 32;
19
+ const EVM_ADDRESS_LENGTH: u64 = 20;
20
+
21
+ // Error codes
22
+ const E_INVALID_EVM_ADDRESS: u64 = 1;
23
+ const E_INVALID_SOLANA_ADDRESS: u64 = 2;
24
+
25
+ /// Detect chain type from tx_hash signature
26
+ /// Returns: 0 = SUI, 1 = EVM, 2 = Solana
27
+ /// Format: [0xDB][0xDB][0x01][CHAIN_TYPE][...28 bytes...]
28
+ fun detect_chain_type_from_tx_hash(tx_hash: &vector<u8>): u8 {
29
+ if (tx_hash.length() != TX_HASH_LENGTH ||
30
+ tx_hash[0] != DUBHE_PREFIX ||
31
+ tx_hash[1] != DUBHE_PREFIX ||
32
+ tx_hash[2] != DUBHE_VERSION) {
33
+ return 0
34
+ };
35
+
36
+ let chain_type = tx_hash[3];
37
+ if (chain_type == CHAIN_TYPE_EVM) {
38
+ 1
39
+ } else if (chain_type == CHAIN_TYPE_SOLANA) {
40
+ 2
41
+ } else {
42
+ 0
43
+ }
44
+ }
45
+
46
+ fun hex_string_to_bytes(hex_str: String): vector<u8> {
47
+ let bytes = hex_str.into_bytes();
48
+ let hex_bytes = if (bytes.length() >= 2 && bytes[0] == 48 && (bytes[1] == 120 || bytes[1] == 88)) {
49
+ let mut result = vector[];
50
+ let mut i = 2;
51
+ while (i < bytes.length()) {
52
+ result.push_back(bytes[i]);
53
+ i = i + 1;
54
+ };
55
+ result
56
+ } else {
57
+ bytes
58
+ };
59
+ hex::decode(hex_bytes)
60
+ }
61
+
62
+ fun base58_decode(input: String): vector<u8> {
63
+ let base58_alphabet = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
64
+ let input_bytes = input.as_bytes();
65
+ let len = input_bytes.length();
66
+
67
+ let mut result: vector<u8> = vector[];
68
+ let mut j = 0;
69
+ while (j < SOLANA_ADDRESS_LENGTH) {
70
+ result.push_back(0u8);
71
+ j = j + 1;
72
+ };
73
+
74
+ let mut i = 0;
75
+ while (i < len) {
76
+ let c = input_bytes[i];
77
+ let mut char_value: u64 = 0;
78
+ let mut found = false;
79
+ let mut k = 0;
80
+ while (k < 58) {
81
+ if (base58_alphabet[k] == c) {
82
+ char_value = k;
83
+ found = true;
84
+ break
85
+ };
86
+ k = k + 1;
87
+ };
88
+
89
+ assert!(found, E_INVALID_SOLANA_ADDRESS);
90
+
91
+ let mut carry = char_value;
92
+ let mut m = (SOLANA_ADDRESS_LENGTH - 1);
93
+ while (m < SOLANA_ADDRESS_LENGTH) {
94
+ let byte_ref = vector::borrow_mut(&mut result, m);
95
+ let tmp = (*byte_ref as u64) * 58 + carry;
96
+ carry = tmp / 256;
97
+ *byte_ref = ((tmp % 256) as u8);
98
+ if (m == 0) break;
99
+ m = m - 1;
100
+ };
101
+ i = i + 1;
102
+ };
103
+ result
104
+ }
105
+
106
+ /// Convert EVM address to SUI address
107
+ /// Format: [12 zero bytes][20 bytes EVM address]
108
+ public fun evm_to_sui(evm_address_str: String): address {
109
+ let evm_bytes = hex_string_to_bytes(evm_address_str);
110
+ assert!(evm_bytes.length() == EVM_ADDRESS_LENGTH, E_INVALID_EVM_ADDRESS);
111
+
112
+ let mut sui_bytes = vector[];
113
+ let mut i = 0;
114
+ while (i < 12) {
115
+ sui_bytes.push_back(0u8);
116
+ i = i + 1;
117
+ };
118
+ sui_bytes.append(evm_bytes);
119
+ address::from_bytes(sui_bytes)
120
+ }
121
+
122
+ /// Convert Solana address to SUI address
123
+ /// Direct use of 32 bytes from Base58 decode
124
+ public fun solana_to_sui(solana_address_str: String): address {
125
+ let solana_bytes = base58_decode(solana_address_str);
126
+ assert!(solana_bytes.length() == SOLANA_ADDRESS_LENGTH, E_INVALID_SOLANA_ADDRESS);
127
+ address::from_bytes(solana_bytes)
128
+ }
129
+
130
+ fun base58_encode(input: vector<u8>): String {
131
+ let base58_alphabet = b"123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
132
+ let mut result = vector::empty<u8>();
133
+ let mut num = input;
134
+
135
+ let mut leading_zeros = 0;
136
+ let mut i = 0;
137
+ while (i < num.length()) {
138
+ if (num[i] == 0) {
139
+ leading_zeros = leading_zeros + 1;
140
+ i = i + 1;
141
+ } else {
142
+ break
143
+ }
144
+ };
145
+
146
+ while (!is_zero(&num)) {
147
+ let remainder = div_mod_58(&mut num);
148
+ result.push_back(base58_alphabet[remainder]);
149
+ };
150
+
151
+ let mut j = 0;
152
+ while (j < leading_zeros) {
153
+ result.push_back(49);
154
+ j = j + 1;
155
+ };
156
+
157
+ vector::reverse(&mut result);
158
+ result.to_ascii_string()
159
+ }
160
+
161
+ fun is_zero(num: &vector<u8>): bool {
162
+ let mut i = 0;
163
+ while (i < num.length()) {
164
+ if (num[i] != 0) {
165
+ return false
166
+ };
167
+ i = i + 1;
168
+ };
169
+ true
170
+ }
171
+
172
+ fun div_mod_58(num: &mut vector<u8>): u64 {
173
+ let mut remainder: u64 = 0;
174
+ let mut i = 0;
175
+ while (i < num.length()) {
176
+ let byte_ref = vector::borrow_mut(num, i);
177
+ let current = (remainder * 256) + (*byte_ref as u64);
178
+ *byte_ref = ((current / 58) as u8);
179
+ remainder = current % 58;
180
+ i = i + 1;
181
+ };
182
+ remainder
183
+ }
184
+
185
+ /// Get original address format based on tx_hash detection
186
+ /// Returns: EVM (0x...), Solana (Base58), or SUI (0x...) format
187
+ public fun ensure_origin(ctx: &TxContext): String {
188
+ let sui_address = ctx.sender();
189
+ let address_bytes = address::to_bytes(sui_address);
190
+ let tx_hash = ctx.digest();
191
+ let chain_type = detect_chain_type_from_tx_hash(tx_hash);
192
+
193
+ if (chain_type == 1) {
194
+ let mut evm_bytes = vector[];
195
+ let mut j = 12;
196
+ while (j < TX_HASH_LENGTH) {
197
+ evm_bytes.push_back(address_bytes[j]);
198
+ j = j + 1;
199
+ };
200
+ let hex_bytes = hex::encode(evm_bytes);
201
+ let mut result_bytes = b"0x";
202
+ result_bytes.append(hex_bytes);
203
+ result_bytes.to_ascii_string()
204
+ } else if (chain_type == 2) {
205
+ base58_encode(address_bytes)
206
+ } else {
207
+ let hex_bytes = hex::encode(address_bytes);
208
+ let mut result_bytes = b"0x";
209
+ result_bytes.append(hex_bytes);
210
+ result_bytes.to_ascii_string()
211
+ }
212
+ }
213
+
214
+ /// Check if transaction is from EVM chain
215
+ public fun is_evm_address(ctx: &TxContext): bool {
216
+ let tx_hash = ctx.digest();
217
+ detect_chain_type_from_tx_hash(tx_hash) == 1
218
+ }
219
+
220
+ /// Check if transaction is from Solana
221
+ public fun is_solana_address(ctx: &TxContext): bool {
222
+ let tx_hash = ctx.digest();
223
+ detect_chain_type_from_tx_hash(tx_hash) == 2
224
+ }
225
+
226
+ /// Check if transaction is native SUI
227
+ public fun is_sui_address(ctx: &TxContext): bool {
228
+ let tx_hash = ctx.digest();
229
+ detect_chain_type_from_tx_hash(tx_hash) == 0
230
+ }
231
+
232
+ // ========== Test Utilities ==========
233
+
234
+ #[test_only]
235
+ /// Setup test scenario with EVM context
236
+ /// Input: EVM address as byte string, e.g., b"0x9168765EE952de7C6f8fC6FaD5Ec209B960b7622"
237
+ /// Format: [0xDB][0xDB][0x01][0xE1][...28 bytes...]
238
+ public fun setup_evm_scenario(scenario: &mut test_scenario::Scenario, evm_address_bytes: vector<u8>) {
239
+ use std::ascii;
240
+
241
+ // Convert EVM address string to SUI address
242
+ let evm_address_str = ascii::string(evm_address_bytes);
243
+ let sender = evm_to_sui(evm_address_str);
244
+
245
+ // Generate EVM tx_hash with Dubhe prefix at the beginning
246
+ let mut tx_hash = vector::empty<u8>();
247
+
248
+ // Mark as EVM with Dubhe prefix, version, and chain type
249
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
250
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
251
+ tx_hash.push_back(DUBHE_VERSION); // 0x01
252
+ tx_hash.push_back(CHAIN_TYPE_EVM); // 0xE1
253
+
254
+ // Fill remaining 28 bytes
255
+ let mut i = 0;
256
+ while (i < 28) {
257
+ tx_hash.push_back((i as u8));
258
+ i = i + 1;
259
+ };
260
+
261
+ // Set context
262
+ let ctx = test_scenario::ctx(scenario);
263
+ *ctx = tx_context::new(sender, tx_hash, 0, 0, 0);
264
+ }
265
+
266
+ #[test_only]
267
+ /// Setup test scenario with Solana context
268
+ /// Input: Solana address as byte string, e.g., b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L"
269
+ /// Format: [0xDB][0xDB][0x01][0xE2][...28 bytes...]
270
+ public fun setup_solana_scenario(scenario: &mut test_scenario::Scenario, solana_address_bytes: vector<u8>) {
271
+ use std::ascii;
272
+
273
+ // Convert Solana address string to SUI address
274
+ let solana_address_str = ascii::string(solana_address_bytes);
275
+ let sender = solana_to_sui(solana_address_str);
276
+
277
+ // Generate Solana tx_hash with Dubhe prefix at the beginning
278
+ let mut tx_hash = vector::empty<u8>();
279
+
280
+ // Mark as Solana with Dubhe prefix, version, and chain type
281
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
282
+ tx_hash.push_back(DUBHE_PREFIX); // 0xDB
283
+ tx_hash.push_back(DUBHE_VERSION); // 0x01
284
+ tx_hash.push_back(CHAIN_TYPE_SOLANA); // 0xE2
285
+
286
+ // Fill remaining 28 bytes
287
+ let mut i = 0;
288
+ while (i < 28) {
289
+ tx_hash.push_back(((i + 100) as u8));
290
+ i = i + 1;
291
+ };
292
+
293
+ // Set context
294
+ let ctx = test_scenario::ctx(scenario);
295
+ *ctx = tx_context::new(sender, tx_hash, 0, 0, 0);
296
+ }
@@ -0,0 +1,55 @@
1
+ #[test_only]
2
+ module dubhe::address_test;
3
+
4
+ use dubhe::address_system;
5
+ use sui::test_scenario;
6
+ use std::ascii::string;
7
+
8
+ #[test]
9
+ public fun test_address_conversion() {
10
+ let sui_sender = @0x1462cab50fe5998f8161378e5265f7920bfd9fbce604d602619962f608837217;
11
+ let sui_origin_string = string(b"0x1462cab50fe5998f8161378e5265f7920bfd9fbce604d602619962f608837217");
12
+ let evm_origin_string = string(b"0x9168765ee952de7c6f8fc6fad5ec209b960b7622");
13
+ let solana_origin_string = string(b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L");
14
+ let mut scenario = test_scenario::begin(sui_sender);
15
+
16
+ // Test EVM address conversion
17
+ std::debug::print(&string(b"EVM address:"));
18
+ std::debug::print(&evm_origin_string);
19
+ let evm_sui_address = address_system::evm_to_sui(evm_origin_string);
20
+ std::debug::print(&string(b"EVM->SUI:"));
21
+ std::debug::print(&evm_sui_address.to_ascii_string());
22
+
23
+ // Test Solana address conversion
24
+ let solana_address_str = string(b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L");
25
+ let solana_sui_address = address_system::solana_to_sui(solana_address_str);
26
+ std::debug::print(&string(b"Solana->SUI:"));
27
+ std::debug::print(&solana_sui_address.to_ascii_string());
28
+
29
+ // Test SUI address detection
30
+ {
31
+ let ctx = test_scenario::ctx(&mut scenario);
32
+ assert!(address_system::is_sui_address(ctx));
33
+ assert!(address_system::ensure_origin(ctx) == sui_origin_string);
34
+ };
35
+
36
+ // Test EVM address detection
37
+ address_system::setup_evm_scenario(&mut scenario, b"0x9168765EE952de7C6f8fC6FaD5Ec209B960b7622");
38
+ {
39
+ let ctx = test_scenario::ctx(&mut scenario);
40
+ assert!(address_system::is_evm_address(ctx));
41
+ std::debug::print(&string(b"evm_origin_string:"));
42
+ std::debug::print(&address_system::ensure_origin(ctx));
43
+ assert!(address_system::ensure_origin(ctx) == evm_origin_string);
44
+ };
45
+
46
+ // Test Solana address detection
47
+ address_system::setup_solana_scenario(&mut scenario, b"3vy8k1NAc3Q9EPvqrAuS4DG4qwbgVqfxznEdtcrL743L");
48
+ {
49
+ let ctx = test_scenario::ctx(&mut scenario);
50
+ assert!(address_system::is_solana_address(ctx));
51
+ assert!(address_system::ensure_origin(ctx) == solana_origin_string);
52
+ };
53
+
54
+ scenario.end();
55
+ }