@0xobelisk/sui-cli 1.2.0-pre.113 → 1.2.0-pre.115
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.
- package/dist/dubhe.js +103 -90
- package/dist/dubhe.js.map +1 -1
- package/package.json +3 -3
- package/src/commands/faucet.ts +1 -0
- package/src/commands/shell.ts +4 -3
- package/src/utils/constants.ts +8 -4
- package/src/utils/publishHandler.ts +32 -9
- package/src/utils/storeConfig.ts +18 -3
- package/src/utils/upgradeHandler.ts +38 -10
- package/src/utils/utils.ts +97 -26
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xobelisk/sui-cli",
|
|
3
|
-
"version": "1.2.0-pre.
|
|
3
|
+
"version": "1.2.0-pre.115",
|
|
4
4
|
"description": "Tookit for interacting with move eps framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sui",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"yargs": "^17.7.1",
|
|
48
48
|
"zod": "^3.22.3",
|
|
49
49
|
"zod-validation-error": "^1.3.0",
|
|
50
|
-
"@0xobelisk/sui-client": "1.2.0-pre.
|
|
51
|
-
"@0xobelisk/sui-common": "1.2.0-pre.
|
|
50
|
+
"@0xobelisk/sui-client": "1.2.0-pre.115",
|
|
51
|
+
"@0xobelisk/sui-common": "1.2.0-pre.115"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/cli-progress": "^3.11.5",
|
package/src/commands/faucet.ts
CHANGED
package/src/commands/shell.ts
CHANGED
|
@@ -132,11 +132,12 @@ const ShellCommand: CommandModule<Options, Options> = {
|
|
|
132
132
|
} else {
|
|
133
133
|
yargsInstance.options(builder);
|
|
134
134
|
}
|
|
135
|
+
const userArgs = parts.slice(1);
|
|
136
|
+
const hasNetworkFlag = userArgs.includes('--network') || userArgs.includes('-n');
|
|
135
137
|
const argv = yargsInstance.parseSync([
|
|
136
138
|
commandName,
|
|
137
|
-
'--network',
|
|
138
|
-
|
|
139
|
-
...parts.slice(1)
|
|
139
|
+
...(hasNetworkFlag ? [] : ['--network', network]),
|
|
140
|
+
...userArgs
|
|
140
141
|
]);
|
|
141
142
|
if (handler) {
|
|
142
143
|
await handler(argv);
|
package/src/utils/constants.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
export
|
|
2
|
-
|
|
1
|
+
export {
|
|
2
|
+
TESTNET_DUBHE_HUB_OBJECT_ID,
|
|
3
|
+
TESTNET_DUBHE_FRAMEWORK_PACKAGE_ID,
|
|
4
|
+
MAINNET_DUBHE_HUB_OBJECT_ID,
|
|
5
|
+
MAINNET_DUBHE_FRAMEWORK_PACKAGE_ID
|
|
6
|
+
} from '@0xobelisk/sui-client';
|
|
3
7
|
|
|
4
|
-
|
|
5
|
-
|
|
8
|
+
// Keep legacy alias for backwards compatibility within this package
|
|
9
|
+
export { TESTNET_DUBHE_FRAMEWORK_PACKAGE_ID as TESTNET_ORIGINAL_DUBHE_PACKAGE_ID } from '@0xobelisk/sui-client';
|
|
@@ -265,6 +265,13 @@ async function publishContract(
|
|
|
265
265
|
const pubfilePath =
|
|
266
266
|
network === 'localnet' ? getEphemeralPubFilePath(process.cwd(), network) : undefined;
|
|
267
267
|
|
|
268
|
+
// Move.toml paths — declared early so both the Published.toml handling block and
|
|
269
|
+
// the localnet env-patching block can reference them.
|
|
270
|
+
const contractMoveTomlPath = `${projectPath}/Move.toml`;
|
|
271
|
+
const dubheMoveTomlPath = path.join(path.dirname(projectPath), 'dubhe', 'Move.toml');
|
|
272
|
+
let savedContractMoveToml: string | null = null;
|
|
273
|
+
let savedDubheMoveToml: string | null = null;
|
|
274
|
+
|
|
268
275
|
// So the build uses package address 0x0: for localnet always remove the contract's
|
|
269
276
|
// Published.toml; for testnet/mainnet/devnet only when --force (clear current network entry).
|
|
270
277
|
// Otherwise Sui CLI bakes the existing [published.<network>] address into the bytecode and
|
|
@@ -278,11 +285,20 @@ async function publishContract(
|
|
|
278
285
|
if (network === 'localnet' && fs.existsSync(contractPublishedTomlPath)) {
|
|
279
286
|
savedContractPublishedToml = fs.readFileSync(contractPublishedTomlPath, 'utf-8');
|
|
280
287
|
fs.unlinkSync(contractPublishedTomlPath);
|
|
281
|
-
} else if (
|
|
288
|
+
} else if (network === 'testnet' || network === 'mainnet' || network === 'devnet') {
|
|
282
289
|
const entry = getPublishedTomlEntry(projectPath, network);
|
|
283
|
-
if (entry) {
|
|
290
|
+
if (entry && force) {
|
|
291
|
+
// Existing entry + --force: clear it so the build uses 0x0 instead of the old address.
|
|
284
292
|
savedContractPublishedEntry = { network, entry };
|
|
285
293
|
clearPublishedTomlEntry(projectPath, network);
|
|
294
|
+
} else if (!entry) {
|
|
295
|
+
// No Published.toml entry for this network (first-time deploy to this network).
|
|
296
|
+
// The Sui CLI has no per-network override and falls back to Move.toml's [addresses]
|
|
297
|
+
// value, which may be non-zero from a previous deployment on a different network,
|
|
298
|
+
// causing PublishErrorNonZeroAddress.
|
|
299
|
+
// Temporarily zero out Move.toml before building so the self-address is 0x0.
|
|
300
|
+
savedContractMoveToml = fs.readFileSync(contractMoveTomlPath, 'utf-8');
|
|
301
|
+
updateMoveTomlAddress(projectPath, '0x0');
|
|
286
302
|
}
|
|
287
303
|
}
|
|
288
304
|
|
|
@@ -300,10 +316,6 @@ async function publishContract(
|
|
|
300
316
|
// Sui CLI 1.40+ checks that the active environment is declared in Move.toml
|
|
301
317
|
// even when --build-env is specified. Temporarily inject localnet into [environments]
|
|
302
318
|
// for both the contract and its dubhe dependency.
|
|
303
|
-
const contractMoveTomlPath = `${projectPath}/Move.toml`;
|
|
304
|
-
const dubheMoveTomlPath = path.join(path.dirname(projectPath), 'dubhe', 'Move.toml');
|
|
305
|
-
let savedContractMoveToml: string | null = null;
|
|
306
|
-
let savedDubheMoveToml: string | null = null;
|
|
307
319
|
if (network === 'localnet') {
|
|
308
320
|
savedContractMoveToml = patchMoveTomlWithLocalnetEnv(contractMoveTomlPath, chainId);
|
|
309
321
|
savedDubheMoveToml = patchMoveTomlWithLocalnetEnv(dubheMoveTomlPath, chainId);
|
|
@@ -450,7 +462,11 @@ async function publishContract(
|
|
|
450
462
|
upgradeCapId,
|
|
451
463
|
version,
|
|
452
464
|
resources,
|
|
453
|
-
enums
|
|
465
|
+
enums,
|
|
466
|
+
// localnet: persist the locally deployed framework ID so the SDK can be
|
|
467
|
+
// initialised without hardcoding it. testnet/mainnet use a well-known
|
|
468
|
+
// constant already embedded in the SDK defaults, so we store undefined.
|
|
469
|
+
network === 'localnet' ? await getOriginalDubhePackageId(network) : undefined
|
|
454
470
|
);
|
|
455
471
|
|
|
456
472
|
await saveMetadata(dubheConfig.name, network, packageId);
|
|
@@ -459,7 +475,11 @@ async function publishContract(
|
|
|
459
475
|
let config = JSON.parse(fs.readFileSync(`${process.cwd()}/dubhe.config.json`, 'utf-8'));
|
|
460
476
|
config.original_package_id = packageId;
|
|
461
477
|
config.dubhe_object_id = dubheDappHub;
|
|
462
|
-
|
|
478
|
+
// When deploying the dubhe framework itself, the "original dubhe package ID" is
|
|
479
|
+
// the package we just published. For user packages, look up the well-known
|
|
480
|
+
// framework address for the target network from the client config.
|
|
481
|
+
config.original_dubhe_package_id =
|
|
482
|
+
dubheConfig.name === 'dubhe' ? packageId : await getOriginalDubhePackageId(network);
|
|
463
483
|
config.start_checkpoint = startCheckpoint;
|
|
464
484
|
|
|
465
485
|
fs.writeFileSync(`${process.cwd()}/dubhe.config.json`, JSON.stringify(config, null, 2));
|
|
@@ -625,7 +645,10 @@ export async function publishDubheFramework(
|
|
|
625
645
|
upgradeCapId,
|
|
626
646
|
version,
|
|
627
647
|
{},
|
|
628
|
-
{}
|
|
648
|
+
{},
|
|
649
|
+
// Store the localnet framework package ID so other packages can read it
|
|
650
|
+
// from deployment JSON and pass it to the Dubhe client constructor.
|
|
651
|
+
network === 'localnet' ? packageId : undefined
|
|
629
652
|
);
|
|
630
653
|
|
|
631
654
|
updateEnvFile(`${projectPath}/Move.lock`, network, 'publish', chainId, packageId);
|
package/src/utils/storeConfig.ts
CHANGED
|
@@ -1,16 +1,31 @@
|
|
|
1
1
|
import { mkdirSync, writeFileSync } from 'fs';
|
|
2
2
|
import { dirname } from 'path';
|
|
3
3
|
import { DubheConfig } from '@0xobelisk/sui-common';
|
|
4
|
-
import { getDeploymentJson, getDubheDappHub } from './utils';
|
|
4
|
+
import { getDeploymentJson, getDubheDappHub, getOriginalDubhePackageId } from './utils';
|
|
5
5
|
|
|
6
6
|
async function storeConfig(network: string, packageId: string, outputPath: string) {
|
|
7
7
|
const dubheDappHub = await getDubheDappHub(network);
|
|
8
|
-
|
|
8
|
+
|
|
9
|
+
// Mirror getDubheDappHub: for localnet the framework is deployed ephemerally so we
|
|
10
|
+
// read its package ID from src/dubhe/.history/sui_localnet/latest.json (same source
|
|
11
|
+
// as DUBHE_SCHEMA_ID above). For testnet/mainnet the SDK resolves the framework
|
|
12
|
+
// address automatically via getDefaultConfig(), so we emit undefined.
|
|
13
|
+
let frameworkPackageId: string | undefined;
|
|
14
|
+
if (network === 'localnet') {
|
|
15
|
+
frameworkPackageId = await getOriginalDubhePackageId(network);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const frameworkIdLine =
|
|
19
|
+
frameworkPackageId !== undefined
|
|
20
|
+
? `\n// Published package ID of the dubhe framework — required for proxy operations.\nexport const FRAMEWORK_PACKAGE_ID: string | undefined = '${frameworkPackageId}';\n`
|
|
21
|
+
: `\n// Published package ID of the dubhe framework — required for proxy operations.\n// For testnet/mainnet the SDK resolves this automatically via getDefaultConfig().\nexport const FRAMEWORK_PACKAGE_ID: string | undefined = undefined;\n`;
|
|
22
|
+
|
|
23
|
+
const code = `type NetworkType = 'testnet' | 'mainnet' | 'devnet' | 'localnet';
|
|
9
24
|
|
|
10
25
|
export const NETWORK: NetworkType = '${network}';
|
|
11
26
|
export const PACKAGE_ID = '${packageId}';
|
|
12
27
|
export const DUBHE_SCHEMA_ID = '${dubheDappHub}';
|
|
13
|
-
`;
|
|
28
|
+
${frameworkIdLine}`;
|
|
14
29
|
|
|
15
30
|
writeOutput(code, outputPath, 'storeConfig');
|
|
16
31
|
}
|
|
@@ -11,14 +11,15 @@ import {
|
|
|
11
11
|
initializeDubhe,
|
|
12
12
|
getOnchainResources,
|
|
13
13
|
getStartCheckpoint,
|
|
14
|
-
|
|
14
|
+
appendMigrateFunction,
|
|
15
15
|
getDubheDappHub,
|
|
16
16
|
updatePublishedToml,
|
|
17
17
|
clearPublishedTomlEntry,
|
|
18
18
|
restorePublishedTomlEntry,
|
|
19
19
|
readPublishedToml,
|
|
20
20
|
updateEphemeralPubFile,
|
|
21
|
-
getEphemeralPubFilePath
|
|
21
|
+
getEphemeralPubFilePath,
|
|
22
|
+
updateMoveTomlAddress
|
|
22
23
|
} from './utils';
|
|
23
24
|
import * as fs from 'fs';
|
|
24
25
|
import * as path from 'path';
|
|
@@ -96,12 +97,14 @@ export async function upgradeHandler(
|
|
|
96
97
|
});
|
|
97
98
|
|
|
98
99
|
const tables = pendingMigration.map((migration) => migration.name);
|
|
99
|
-
//
|
|
100
|
-
//
|
|
101
|
-
//
|
|
102
|
-
//
|
|
100
|
+
// When new resources are detected, generate the migrate_to_vN entry function in
|
|
101
|
+
// migrate.move so the on-chain migration transaction can register the new package
|
|
102
|
+
// ID and version via dapp_system::upgrade_dapp.
|
|
103
|
+
// Note: the current framework stores data as dynamic fields and does NOT use
|
|
104
|
+
// register_table; genesis::migrate() is intentionally left empty and is called
|
|
105
|
+
// from migrate_to_vN solely to keep the extension point for future use.
|
|
103
106
|
if (tables.length > 0) {
|
|
104
|
-
|
|
107
|
+
appendMigrateFunction(projectPath, config.name, oldVersion + 1);
|
|
105
108
|
}
|
|
106
109
|
|
|
107
110
|
const original_published_id = replaceEnvField(
|
|
@@ -120,8 +123,11 @@ export async function upgradeHandler(
|
|
|
120
123
|
|
|
121
124
|
// For localnet upgrades: refresh Pub.localnet.toml with dubhe's current address
|
|
122
125
|
// so that the build can resolve the dubhe dependency.
|
|
126
|
+
// Skip this step when upgrading dubhe itself — dubhe has no local dubhe dependency,
|
|
127
|
+
// and adding its own address to the pubfile causes PublishErrorNonZeroAddress because
|
|
128
|
+
// the Sui CLI treats the root package's pubfile entry as a non-zero self-address.
|
|
123
129
|
const cwd = process.cwd();
|
|
124
|
-
if (network === 'localnet') {
|
|
130
|
+
if (network === 'localnet' && name !== 'dubhe') {
|
|
125
131
|
const dubheProjectPath = `${cwd}/src/dubhe`;
|
|
126
132
|
const dubheEntries = readPublishedToml(dubheProjectPath);
|
|
127
133
|
const dubheEntry = dubheEntries['localnet'];
|
|
@@ -139,15 +145,32 @@ export async function upgradeHandler(
|
|
|
139
145
|
|
|
140
146
|
try {
|
|
141
147
|
let modules: any, dependencies: any, digest: any;
|
|
148
|
+
// When upgrading dubhe itself on localnet, Move.toml has a non-zero 'dubhe' address
|
|
149
|
+
// (the mainnet/testnet deploy address). This gets baked into the upgrade bytecode as the
|
|
150
|
+
// self-address, causing PublishErrorNonZeroAddress. Zero it out before the build and
|
|
151
|
+
// restore it afterwards — mirroring what publishDubheFramework does.
|
|
152
|
+
let savedDubheMoveTomlContent: string | null = null;
|
|
153
|
+
if (network === 'localnet' && name === 'dubhe') {
|
|
154
|
+
const moveTomlPath = `${projectPath}/Move.toml`;
|
|
155
|
+
savedDubheMoveTomlContent = fs.readFileSync(moveTomlPath, 'utf-8');
|
|
156
|
+
updateMoveTomlAddress(projectPath, '0x0');
|
|
157
|
+
}
|
|
142
158
|
try {
|
|
143
159
|
// For localnet: use --build-env testnet --pubfile-path Pub.localnet.toml
|
|
144
160
|
// so the package compiles with address 0x0 (not in pubfile) and links
|
|
145
161
|
// against the already-published dubhe dependency (from pubfile).
|
|
162
|
+
// Exception: when upgrading dubhe itself, skip the pubfile — dubhe has no
|
|
163
|
+
// local dubhe dependency and including itself in the pubfile causes
|
|
164
|
+
// PublishErrorNonZeroAddress.
|
|
146
165
|
// For testnet/mainnet: use -e <network> as usual.
|
|
147
166
|
let buildCmd: string;
|
|
148
167
|
if (network === 'localnet') {
|
|
149
|
-
|
|
150
|
-
|
|
168
|
+
if (name !== 'dubhe') {
|
|
169
|
+
const pubfilePath = getEphemeralPubFilePath(cwd, network);
|
|
170
|
+
buildCmd = `sui move build --dump-bytecode-as-base64 --no-tree-shaking --build-env testnet --pubfile-path ${pubfilePath} --path ${path}/src/${name}`;
|
|
171
|
+
} else {
|
|
172
|
+
buildCmd = `sui move build --dump-bytecode-as-base64 --no-tree-shaking --build-env testnet --path ${path}/src/${name}`;
|
|
173
|
+
}
|
|
151
174
|
} else {
|
|
152
175
|
buildCmd = `sui move build --dump-bytecode-as-base64 --no-tree-shaking -e ${network} --path ${path}/src/${name}`;
|
|
153
176
|
}
|
|
@@ -167,6 +190,11 @@ export async function upgradeHandler(
|
|
|
167
190
|
restorePublishedTomlEntry(projectPath, network, savedPublishedEntry);
|
|
168
191
|
}
|
|
169
192
|
throw new UpgradeError(error.stdout || error.stderr || error.message);
|
|
193
|
+
} finally {
|
|
194
|
+
// Always restore dubhe Move.toml after build (success or error)
|
|
195
|
+
if (savedDubheMoveTomlContent !== null) {
|
|
196
|
+
fs.writeFileSync(`${projectPath}/Move.toml`, savedDubheMoveTomlContent, 'utf-8');
|
|
197
|
+
}
|
|
170
198
|
}
|
|
171
199
|
|
|
172
200
|
console.log('\n🚀 Starting Upgrade Process...');
|
package/src/utils/utils.ts
CHANGED
|
@@ -6,10 +6,15 @@ import { FsIibError } from './errors';
|
|
|
6
6
|
import * as fs from 'fs';
|
|
7
7
|
import chalk from 'chalk';
|
|
8
8
|
import { spawn } from 'child_process';
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
Dubhe,
|
|
11
|
+
NetworkType,
|
|
12
|
+
SuiMoveNormalizedModules,
|
|
13
|
+
loadMetadata,
|
|
14
|
+
getDefaultConfig
|
|
15
|
+
} from '@0xobelisk/sui-client';
|
|
10
16
|
import { DubheCliError } from './errors';
|
|
11
17
|
import { Component, MoveType, DubheConfig } from '@0xobelisk/sui-common';
|
|
12
|
-
import { TESTNET_DUBHE_HUB_OBJECT_ID, TESTNET_ORIGINAL_DUBHE_PACKAGE_ID } from './constants';
|
|
13
18
|
|
|
14
19
|
export type DeploymentJsonType = {
|
|
15
20
|
projectName: string;
|
|
@@ -21,6 +26,12 @@ export type DeploymentJsonType = {
|
|
|
21
26
|
version: number;
|
|
22
27
|
resources: Record<string, Component | MoveType>;
|
|
23
28
|
enums?: Record<string, string[]>;
|
|
29
|
+
/**
|
|
30
|
+
* Published package ID of the Dubhe framework used by this deployment.
|
|
31
|
+
* Populated for localnet (ephemeral deploy); undefined for testnet/mainnet
|
|
32
|
+
* where the SDK already knows the well-known constant.
|
|
33
|
+
*/
|
|
34
|
+
frameworkPackageId?: string;
|
|
24
35
|
};
|
|
25
36
|
|
|
26
37
|
export function validatePrivateKey(privateKey: string): false | string {
|
|
@@ -96,36 +107,36 @@ export async function getDubheDappHub(network: string) {
|
|
|
96
107
|
const path = process.cwd();
|
|
97
108
|
const contractPath = `${path}/src/dubhe`;
|
|
98
109
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
throw new Error(`Invalid network: ${network}`);
|
|
110
|
+
if (network === 'localnet') {
|
|
111
|
+
return await getDeploymentDappHub(contractPath, 'localnet');
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const config = getDefaultConfig(network as NetworkType);
|
|
115
|
+
if (!config.dappHubId) {
|
|
116
|
+
throw new Error(
|
|
117
|
+
`DappHub object ID is not configured for network "${network}". ` +
|
|
118
|
+
`Update MAINNET_DUBHE_HUB_OBJECT_ID / TESTNET_DUBHE_HUB_OBJECT_ID in @0xobelisk/sui-client.`
|
|
119
|
+
);
|
|
110
120
|
}
|
|
121
|
+
return config.dappHubId;
|
|
111
122
|
}
|
|
112
123
|
|
|
113
124
|
export async function getOriginalDubhePackageId(network: string) {
|
|
114
125
|
const path = process.cwd();
|
|
115
126
|
const contractPath = `${path}/src/dubhe`;
|
|
116
127
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
throw new Error(`Invalid network: ${network}`);
|
|
128
|
+
if (network === 'localnet') {
|
|
129
|
+
return await getOldPackageId(contractPath, network);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const config = getDefaultConfig(network as NetworkType);
|
|
133
|
+
if (!config.frameworkPackageId) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`Framework package ID is not configured for network "${network}". ` +
|
|
136
|
+
`Update MAINNET_DUBHE_FRAMEWORK_PACKAGE_ID / TESTNET_DUBHE_FRAMEWORK_PACKAGE_ID in @0xobelisk/sui-client.`
|
|
137
|
+
);
|
|
128
138
|
}
|
|
139
|
+
return config.frameworkPackageId;
|
|
129
140
|
}
|
|
130
141
|
export async function getOnchainResources(
|
|
131
142
|
projectPath: string,
|
|
@@ -158,6 +169,14 @@ export async function getDappHub(projectPath: string, network: string): Promise<
|
|
|
158
169
|
return deployment.dappHub;
|
|
159
170
|
}
|
|
160
171
|
|
|
172
|
+
export async function getFrameworkPackageIdFromDeployment(
|
|
173
|
+
projectPath: string,
|
|
174
|
+
network: string
|
|
175
|
+
): Promise<string | undefined> {
|
|
176
|
+
const deployment = await getDeploymentJson(projectPath, network);
|
|
177
|
+
return deployment.frameworkPackageId;
|
|
178
|
+
}
|
|
179
|
+
|
|
161
180
|
export async function getUpgradeCap(projectPath: string, network: string): Promise<string> {
|
|
162
181
|
const deployment = await getDeploymentJson(projectPath, network);
|
|
163
182
|
return deployment.upgradeCap;
|
|
@@ -177,7 +196,8 @@ export async function saveContractData(
|
|
|
177
196
|
upgradeCap: string,
|
|
178
197
|
version: number,
|
|
179
198
|
resources: Record<string, Component | MoveType>,
|
|
180
|
-
enums?: Record<string, string[]
|
|
199
|
+
enums?: Record<string, string[]>,
|
|
200
|
+
frameworkPackageId?: string
|
|
181
201
|
) {
|
|
182
202
|
const DeploymentData: DeploymentJsonType = {
|
|
183
203
|
projectName,
|
|
@@ -188,7 +208,8 @@ export async function saveContractData(
|
|
|
188
208
|
upgradeCap,
|
|
189
209
|
version,
|
|
190
210
|
resources,
|
|
191
|
-
enums
|
|
211
|
+
enums,
|
|
212
|
+
frameworkPackageId
|
|
192
213
|
};
|
|
193
214
|
|
|
194
215
|
const path = process.cwd();
|
|
@@ -929,3 +950,53 @@ export function updateGenesisUpgradeFunction(path: string, tables: string[]) {
|
|
|
929
950
|
|
|
930
951
|
fs.writeFileSync(genesisPath, updatedContent, 'utf-8');
|
|
931
952
|
}
|
|
953
|
+
|
|
954
|
+
/**
|
|
955
|
+
* Appends a `migrate_to_vN` entry function to the package's migrate.move.
|
|
956
|
+
*
|
|
957
|
+
* This function is called by upgradeHandler when new resources are detected
|
|
958
|
+
* (pendingMigration.length > 0). The generated function delegates to
|
|
959
|
+
* `genesis::migrate`, which provides an extension point (separator comments)
|
|
960
|
+
* for any future resource-registration steps. The `new_package_id` and
|
|
961
|
+
* `new_version` arguments are kept in the signature to match the on-chain
|
|
962
|
+
* call emitted by upgradeHandler even though dapp_system::upgrade_dapp is
|
|
963
|
+
* public(package) in dubhe and cannot be called from external packages.
|
|
964
|
+
*/
|
|
965
|
+
export function appendMigrateFunction(
|
|
966
|
+
projectPath: string,
|
|
967
|
+
packageName: string,
|
|
968
|
+
newVersion: number
|
|
969
|
+
): void {
|
|
970
|
+
const migratePath = `${projectPath}/sources/scripts/migrate.move`;
|
|
971
|
+
if (!fs.existsSync(migratePath)) {
|
|
972
|
+
throw new Error(`migrate.move not found at ${migratePath}`);
|
|
973
|
+
}
|
|
974
|
+
|
|
975
|
+
const content = fs.readFileSync(migratePath, 'utf-8');
|
|
976
|
+
|
|
977
|
+
// Idempotency: skip if the function already exists
|
|
978
|
+
if (content.includes(`migrate_to_v${newVersion}`)) {
|
|
979
|
+
return;
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
const migrateFunction = `
|
|
983
|
+
public entry fun migrate_to_v${newVersion}(
|
|
984
|
+
dapp_hub: &mut dubhe::dapp_service::DappHub,
|
|
985
|
+
_new_package_id: address,
|
|
986
|
+
_new_version: u32,
|
|
987
|
+
ctx: &mut TxContext
|
|
988
|
+
) {
|
|
989
|
+
${packageName}::genesis::migrate(dapp_hub, ctx);
|
|
990
|
+
}
|
|
991
|
+
`;
|
|
992
|
+
|
|
993
|
+
// Insert the new function before the closing brace of the module
|
|
994
|
+
const closingBraceIdx = content.lastIndexOf('}');
|
|
995
|
+
if (closingBraceIdx === -1) {
|
|
996
|
+
throw new Error(`Could not find closing brace in ${migratePath}`);
|
|
997
|
+
}
|
|
998
|
+
|
|
999
|
+
const updated =
|
|
1000
|
+
content.slice(0, closingBraceIdx) + migrateFunction + content.slice(closingBraceIdx);
|
|
1001
|
+
fs.writeFileSync(migratePath, updated, 'utf-8');
|
|
1002
|
+
}
|