@0xobelisk/sui-cli 1.2.0-pre.119 → 1.2.0-pre.120
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 +100 -100
- package/dist/dubhe.js.map +1 -1
- package/package.json +3 -3
- package/src/commands/build.ts +8 -2
- package/src/commands/checkBalance.ts +17 -9
- package/src/commands/faucet.ts +8 -3
- package/src/commands/info.ts +8 -2
- package/src/commands/loadMetadata.ts +13 -2
- package/src/commands/publish.ts +14 -2
- package/src/commands/shell.ts +11 -2
- package/src/commands/switchEnv.ts +13 -6
- package/src/commands/upgrade.ts +13 -2
- package/src/utils/checkBalance.ts +6 -2
- package/src/utils/metadataHandler.ts +4 -3
- package/src/utils/publishHandler.ts +18 -6
- package/src/utils/upgradeHandler.ts +14 -3
- package/src/utils/utils.ts +59 -11
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.120",
|
|
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.120",
|
|
51
|
+
"@0xobelisk/sui-common": "1.2.0-pre.120"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/cli-progress": "^3.11.5",
|
package/src/commands/build.ts
CHANGED
|
@@ -10,6 +10,7 @@ type Options = {
|
|
|
10
10
|
'config-path': string;
|
|
11
11
|
network: any;
|
|
12
12
|
'dump-bytecode-as-base64'?: boolean;
|
|
13
|
+
'rpc-url'?: string;
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
/**
|
|
@@ -61,6 +62,10 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
61
62
|
type: 'boolean',
|
|
62
63
|
default: false,
|
|
63
64
|
desc: 'Dump bytecode as base64'
|
|
65
|
+
},
|
|
66
|
+
'rpc-url': {
|
|
67
|
+
type: 'string',
|
|
68
|
+
desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
|
|
64
69
|
}
|
|
65
70
|
});
|
|
66
71
|
},
|
|
@@ -68,7 +73,8 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
68
73
|
async handler({
|
|
69
74
|
'config-path': configPath,
|
|
70
75
|
network,
|
|
71
|
-
'dump-bytecode-as-base64': dumpBytecodeAsBase64
|
|
76
|
+
'dump-bytecode-as-base64': dumpBytecodeAsBase64,
|
|
77
|
+
'rpc-url': rpcUrl
|
|
72
78
|
}) {
|
|
73
79
|
try {
|
|
74
80
|
if (network == 'default') {
|
|
@@ -77,7 +83,7 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
77
83
|
}
|
|
78
84
|
console.log('🚀 Running move build');
|
|
79
85
|
const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
|
|
80
|
-
await switchEnv(network);
|
|
86
|
+
await switchEnv(network, rpcUrl);
|
|
81
87
|
|
|
82
88
|
const projectPath = nodePath.join(process.cwd(), 'src', dubheConfig.name);
|
|
83
89
|
const lintResults = lintSystemGuards(projectPath);
|
|
@@ -6,26 +6,34 @@ import { getDefaultNetwork } from '../utils';
|
|
|
6
6
|
|
|
7
7
|
type Options = {
|
|
8
8
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet' | 'default';
|
|
9
|
+
'rpc-url'?: string;
|
|
9
10
|
};
|
|
10
11
|
|
|
11
12
|
const commandModule: CommandModule<Options, Options> = {
|
|
12
13
|
command: 'check-balance',
|
|
13
14
|
describe: 'Check the balance of the account',
|
|
14
|
-
builder
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
15
|
+
builder(yargs) {
|
|
16
|
+
return yargs.options({
|
|
17
|
+
network: {
|
|
18
|
+
type: 'string',
|
|
19
|
+
choices: ['mainnet', 'testnet', 'devnet', 'localnet', 'default'],
|
|
20
|
+
desc: 'Network to check balance on',
|
|
21
|
+
default: 'default'
|
|
22
|
+
},
|
|
23
|
+
'rpc-url': {
|
|
24
|
+
type: 'string',
|
|
25
|
+
desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
|
|
26
|
+
}
|
|
27
|
+
}) as any;
|
|
21
28
|
},
|
|
22
|
-
async handler({ network }) {
|
|
29
|
+
async handler({ network, 'rpc-url': rpcUrl }) {
|
|
23
30
|
try {
|
|
24
31
|
if (network == 'default') {
|
|
25
32
|
network = await getDefaultNetwork();
|
|
26
33
|
console.log(chalk.yellow(`Use default network: [${network}]`));
|
|
27
34
|
}
|
|
28
|
-
|
|
35
|
+
const fullnodeUrls = rpcUrl ? [rpcUrl] : undefined;
|
|
36
|
+
await checkBalanceHandler(network, fullnodeUrls);
|
|
29
37
|
} catch (error) {
|
|
30
38
|
console.error('Error checking balance:', error);
|
|
31
39
|
handlerExit(1);
|
package/src/commands/faucet.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { handlerExit } from './shell';
|
|
|
7
7
|
type Options = {
|
|
8
8
|
network: any;
|
|
9
9
|
recipient?: string;
|
|
10
|
+
'rpc-url'?: string;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
const MAX_RETRIES = 60; // 60s timeout
|
|
@@ -30,14 +31,18 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
30
31
|
type: 'string',
|
|
31
32
|
alias: 'r',
|
|
32
33
|
desc: 'Sui address to fund'
|
|
34
|
+
},
|
|
35
|
+
'rpc-url': {
|
|
36
|
+
type: 'string',
|
|
37
|
+
desc: 'Custom RPC endpoint URL for balance check (overrides the default for the selected network)'
|
|
33
38
|
}
|
|
34
39
|
});
|
|
35
40
|
},
|
|
36
41
|
|
|
37
|
-
async handler({ network, recipient }) {
|
|
42
|
+
async handler({ network, recipient, 'rpc-url': rpcUrl }) {
|
|
38
43
|
let faucet_address = '';
|
|
39
44
|
if (recipient === undefined) {
|
|
40
|
-
const dubhe = initializeDubhe(network);
|
|
45
|
+
const dubhe = initializeDubhe({ network });
|
|
41
46
|
faucet_address = dubhe.getAddress();
|
|
42
47
|
} else {
|
|
43
48
|
faucet_address = recipient;
|
|
@@ -108,7 +113,7 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
108
113
|
process.stdout.write('\r' + ' '.repeat(50) + '\r');
|
|
109
114
|
|
|
110
115
|
console.log(' └─ Checking balance...');
|
|
111
|
-
const client = new SuiClient({ url: getFullnodeUrl(network) });
|
|
116
|
+
const client = new SuiClient({ url: rpcUrl || getFullnodeUrl(network) });
|
|
112
117
|
let params = {
|
|
113
118
|
owner: faucet_address
|
|
114
119
|
} as GetBalanceParams;
|
package/src/commands/info.ts
CHANGED
|
@@ -7,6 +7,7 @@ dotenv.config();
|
|
|
7
7
|
|
|
8
8
|
type Options = {
|
|
9
9
|
network: any;
|
|
10
|
+
'rpc-url'?: string;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
const InfoCommand: CommandModule<Options, Options> = {
|
|
@@ -19,16 +20,21 @@ const InfoCommand: CommandModule<Options, Options> = {
|
|
|
19
20
|
choices: ['mainnet', 'testnet', 'devnet', 'localnet', 'default'],
|
|
20
21
|
default: 'default',
|
|
21
22
|
desc: 'Node network (mainnet/testnet/devnet/localnet)'
|
|
23
|
+
},
|
|
24
|
+
'rpc-url': {
|
|
25
|
+
type: 'string',
|
|
26
|
+
desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
|
|
22
27
|
}
|
|
23
28
|
});
|
|
24
29
|
},
|
|
25
|
-
handler: async ({ network }) => {
|
|
30
|
+
handler: async ({ network, 'rpc-url': rpcUrl }) => {
|
|
26
31
|
try {
|
|
27
32
|
if (network == 'default') {
|
|
28
33
|
network = await getDefaultNetwork();
|
|
29
34
|
console.log(chalk.yellow(`Use default network: [${network}]`));
|
|
30
35
|
}
|
|
31
|
-
const
|
|
36
|
+
const fullnodeUrls = rpcUrl ? [rpcUrl] : undefined;
|
|
37
|
+
const dubhe = initializeDubhe({ network, fullnodeUrls });
|
|
32
38
|
const keypair = dubhe.getSigner();
|
|
33
39
|
|
|
34
40
|
console.log(chalk.blue('Account Information:'));
|
|
@@ -10,6 +10,7 @@ type Options = {
|
|
|
10
10
|
network: any;
|
|
11
11
|
'config-path': string;
|
|
12
12
|
'package-id'?: string;
|
|
13
|
+
'rpc-url'?: string;
|
|
13
14
|
};
|
|
14
15
|
|
|
15
16
|
const commandModule: CommandModule<Options, Options> = {
|
|
@@ -34,18 +35,28 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
34
35
|
type: 'string',
|
|
35
36
|
desc: 'Package ID to load metadata for',
|
|
36
37
|
optional: true
|
|
38
|
+
},
|
|
39
|
+
'rpc-url': {
|
|
40
|
+
type: 'string',
|
|
41
|
+
desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
|
|
37
42
|
}
|
|
38
43
|
});
|
|
39
44
|
},
|
|
40
45
|
|
|
41
|
-
async handler({
|
|
46
|
+
async handler({
|
|
47
|
+
network,
|
|
48
|
+
'config-path': configPath,
|
|
49
|
+
'package-id': packageId,
|
|
50
|
+
'rpc-url': rpcUrl
|
|
51
|
+
}) {
|
|
42
52
|
try {
|
|
43
53
|
if (network == 'default') {
|
|
44
54
|
network = await getDefaultNetwork();
|
|
45
55
|
console.log(chalk.yellow(`Use default network: [${network}]`));
|
|
46
56
|
}
|
|
47
57
|
const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
|
|
48
|
-
|
|
58
|
+
const fullnodeUrls = rpcUrl ? [rpcUrl] : undefined;
|
|
59
|
+
await loadMetadataHandler(dubheConfig, network, packageId, fullnodeUrls);
|
|
49
60
|
} catch (error: any) {
|
|
50
61
|
logError(error);
|
|
51
62
|
handlerExit(1);
|
package/src/commands/publish.ts
CHANGED
|
@@ -18,6 +18,7 @@ type Options = {
|
|
|
18
18
|
'config-path': string;
|
|
19
19
|
force: boolean;
|
|
20
20
|
'gas-budget'?: number;
|
|
21
|
+
'rpc-url'?: string;
|
|
21
22
|
};
|
|
22
23
|
|
|
23
24
|
const commandModule: CommandModule<Options, Options> = {
|
|
@@ -47,11 +48,21 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
47
48
|
type: 'boolean',
|
|
48
49
|
default: false,
|
|
49
50
|
desc: 'Clear existing published state for this network before build (use when re-publishing or to fix PublishErrorNonZeroAddress)'
|
|
51
|
+
},
|
|
52
|
+
'rpc-url': {
|
|
53
|
+
type: 'string',
|
|
54
|
+
desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
|
|
50
55
|
}
|
|
51
56
|
});
|
|
52
57
|
},
|
|
53
58
|
|
|
54
|
-
async handler({
|
|
59
|
+
async handler({
|
|
60
|
+
network,
|
|
61
|
+
'config-path': configPath,
|
|
62
|
+
'gas-budget': gasBudget,
|
|
63
|
+
force,
|
|
64
|
+
'rpc-url': rpcUrl
|
|
65
|
+
}) {
|
|
55
66
|
try {
|
|
56
67
|
if (network == 'default') {
|
|
57
68
|
network = await getDefaultNetwork();
|
|
@@ -73,8 +84,9 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
73
84
|
}
|
|
74
85
|
}
|
|
75
86
|
|
|
87
|
+
const fullnodeUrls = rpcUrl ? [rpcUrl] : undefined;
|
|
76
88
|
execSync(`pnpm dubhe convert-json --config-path ${configPath}`, { encoding: 'utf-8' });
|
|
77
|
-
await publishHandler(dubheConfig, network, force, gasBudget);
|
|
89
|
+
await publishHandler(dubheConfig, network, force, gasBudget, fullnodeUrls);
|
|
78
90
|
} catch (error: any) {
|
|
79
91
|
logError(error);
|
|
80
92
|
handlerExit(1);
|
package/src/commands/shell.ts
CHANGED
|
@@ -20,6 +20,7 @@ export const handlerExit = (status: number = 0) => {
|
|
|
20
20
|
|
|
21
21
|
type Options = {
|
|
22
22
|
network: any;
|
|
23
|
+
'rpc-url'?: string;
|
|
23
24
|
};
|
|
24
25
|
|
|
25
26
|
const parseCommandNames = () => {
|
|
@@ -38,10 +39,14 @@ const ShellCommand: CommandModule<Options, Options> = {
|
|
|
38
39
|
choices: ['mainnet', 'testnet', 'devnet', 'localnet', 'default'],
|
|
39
40
|
default: 'default',
|
|
40
41
|
desc: 'Node network (mainnet/testnet/devnet/localnet)'
|
|
42
|
+
},
|
|
43
|
+
'rpc-url': {
|
|
44
|
+
type: 'string',
|
|
45
|
+
desc: 'Custom RPC endpoint URL injected into every sub-command (overrides the default for the selected network)'
|
|
41
46
|
}
|
|
42
47
|
});
|
|
43
48
|
},
|
|
44
|
-
handler: async ({ network }) => {
|
|
49
|
+
handler: async ({ network, 'rpc-url': rpcUrl }) => {
|
|
45
50
|
if (network == 'default') {
|
|
46
51
|
network = await getDefaultNetwork();
|
|
47
52
|
console.log(chalk.yellow(`Use default network: [${network}]`));
|
|
@@ -60,7 +65,9 @@ const ShellCommand: CommandModule<Options, Options> = {
|
|
|
60
65
|
const rl = readline.createInterface({
|
|
61
66
|
input: process.stdin,
|
|
62
67
|
output: process.stdout,
|
|
63
|
-
prompt: `dubhe(${chalk.green(network)}
|
|
68
|
+
prompt: `dubhe(${chalk.green(network)}${
|
|
69
|
+
rpcUrl ? chalk.gray('[custom-rpc]') : ''
|
|
70
|
+
}) ${chalk.bold('>')} `,
|
|
64
71
|
completer: completer,
|
|
65
72
|
historySize: 200
|
|
66
73
|
});
|
|
@@ -134,9 +141,11 @@ const ShellCommand: CommandModule<Options, Options> = {
|
|
|
134
141
|
}
|
|
135
142
|
const userArgs = parts.slice(1);
|
|
136
143
|
const hasNetworkFlag = userArgs.includes('--network') || userArgs.includes('-n');
|
|
144
|
+
const hasRpcUrlFlag = userArgs.includes('--rpc-url');
|
|
137
145
|
const argv = yargsInstance.parseSync([
|
|
138
146
|
commandName,
|
|
139
147
|
...(hasNetworkFlag ? [] : ['--network', network]),
|
|
148
|
+
...(hasRpcUrlFlag || !rpcUrl ? [] : ['--rpc-url', rpcUrl]),
|
|
140
149
|
...userArgs
|
|
141
150
|
]);
|
|
142
151
|
if (handler) {
|
|
@@ -4,21 +4,28 @@ import { handlerExit } from './shell';
|
|
|
4
4
|
|
|
5
5
|
type Options = {
|
|
6
6
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet' | 'default';
|
|
7
|
+
'rpc-url'?: string;
|
|
7
8
|
};
|
|
8
9
|
|
|
9
10
|
const commandModule: CommandModule<Options, Options> = {
|
|
10
11
|
command: 'switch-env',
|
|
11
12
|
describe: 'Switch environment',
|
|
12
13
|
builder(yargs) {
|
|
13
|
-
return yargs.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
14
|
+
return yargs.options({
|
|
15
|
+
network: {
|
|
16
|
+
type: 'string',
|
|
17
|
+
choices: ['mainnet', 'testnet', 'devnet', 'localnet'] as const,
|
|
18
|
+
default: 'localnet',
|
|
19
|
+
desc: 'Switch to node network (mainnet/testnet/devnet/localnet)'
|
|
20
|
+
},
|
|
21
|
+
'rpc-url': {
|
|
22
|
+
type: 'string',
|
|
23
|
+
desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
|
|
24
|
+
}
|
|
18
25
|
}) as any;
|
|
19
26
|
},
|
|
20
27
|
async handler(argv: ArgumentsCamelCase<Options>) {
|
|
21
|
-
await switchEnv(argv.network as 'mainnet' | 'testnet' | 'devnet' | 'localnet');
|
|
28
|
+
await switchEnv(argv.network as 'mainnet' | 'testnet' | 'devnet' | 'localnet', argv['rpc-url']);
|
|
22
29
|
handlerExit();
|
|
23
30
|
}
|
|
24
31
|
};
|
package/src/commands/upgrade.ts
CHANGED
|
@@ -11,6 +11,7 @@ type Options = {
|
|
|
11
11
|
network: any;
|
|
12
12
|
'config-path': string;
|
|
13
13
|
'bump-version': boolean;
|
|
14
|
+
'rpc-url'?: string;
|
|
14
15
|
};
|
|
15
16
|
|
|
16
17
|
const commandModule: CommandModule<Options, Options> = {
|
|
@@ -35,11 +36,20 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
35
36
|
type: 'boolean',
|
|
36
37
|
default: false,
|
|
37
38
|
desc: 'Force a version bump even when no new resources were added (use for breaking logic changes or security fixes that must invalidate old clients)'
|
|
39
|
+
},
|
|
40
|
+
'rpc-url': {
|
|
41
|
+
type: 'string',
|
|
42
|
+
desc: 'Custom RPC endpoint URL (overrides the default for the selected network)'
|
|
38
43
|
}
|
|
39
44
|
});
|
|
40
45
|
},
|
|
41
46
|
|
|
42
|
-
async handler({
|
|
47
|
+
async handler({
|
|
48
|
+
network,
|
|
49
|
+
'config-path': configPath,
|
|
50
|
+
'bump-version': bumpVersion,
|
|
51
|
+
'rpc-url': rpcUrl
|
|
52
|
+
}) {
|
|
43
53
|
try {
|
|
44
54
|
if (network == 'default') {
|
|
45
55
|
network = await getDefaultNetwork();
|
|
@@ -61,7 +71,8 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
73
|
|
|
64
|
-
|
|
74
|
+
const fullnodeUrls = rpcUrl ? [rpcUrl] : undefined;
|
|
75
|
+
await upgradeHandler(dubheConfig, dubheConfig.name, network, bumpVersion, fullnodeUrls);
|
|
65
76
|
} catch (error: any) {
|
|
66
77
|
logError(error);
|
|
67
78
|
handlerExit(1);
|
|
@@ -4,10 +4,14 @@ import { initializeDubhe } from './utils';
|
|
|
4
4
|
import { DubheCliError } from './errors';
|
|
5
5
|
dotenv.config();
|
|
6
6
|
|
|
7
|
-
export async function checkBalanceHandler(
|
|
7
|
+
export async function checkBalanceHandler(
|
|
8
|
+
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
9
|
+
fullnodeUrls?: string[]
|
|
10
|
+
) {
|
|
8
11
|
try {
|
|
9
12
|
const dubhe = initializeDubhe({
|
|
10
|
-
network
|
|
13
|
+
network,
|
|
14
|
+
fullnodeUrls
|
|
11
15
|
});
|
|
12
16
|
|
|
13
17
|
const balance = await dubhe.getBalance();
|
|
@@ -4,13 +4,14 @@ import { getOldPackageId, saveMetadata } from './utils';
|
|
|
4
4
|
export async function loadMetadataHandler(
|
|
5
5
|
dubheConfig: DubheConfig,
|
|
6
6
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
7
|
-
packageId?: string
|
|
7
|
+
packageId?: string,
|
|
8
|
+
fullnodeUrls?: string[]
|
|
8
9
|
) {
|
|
9
10
|
if (packageId) {
|
|
10
|
-
await saveMetadata(dubheConfig.name, network, packageId);
|
|
11
|
+
await saveMetadata(dubheConfig.name, network, packageId, fullnodeUrls);
|
|
11
12
|
} else {
|
|
12
13
|
const projectPath = `${process.cwd()}/src/${dubheConfig.name}`;
|
|
13
14
|
const packageId = await getOldPackageId(projectPath, network);
|
|
14
|
-
await saveMetadata(dubheConfig.name, network, packageId);
|
|
15
|
+
await saveMetadata(dubheConfig.name, network, packageId, fullnodeUrls);
|
|
15
16
|
}
|
|
16
17
|
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
saveMetadata,
|
|
12
12
|
getOriginalDubhePackageId,
|
|
13
13
|
updatePublishedToml,
|
|
14
|
+
syncDubheFrameworkAddress,
|
|
14
15
|
updateEphemeralPubFile,
|
|
15
16
|
getEphemeralPubFilePath,
|
|
16
17
|
getPublishedTomlEntry,
|
|
@@ -246,7 +247,8 @@ async function publishContract(
|
|
|
246
247
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
247
248
|
projectPath: string,
|
|
248
249
|
gasBudget?: number,
|
|
249
|
-
force?: boolean
|
|
250
|
+
force?: boolean,
|
|
251
|
+
fullnodeUrls?: string[]
|
|
250
252
|
) {
|
|
251
253
|
console.log('\n🚀 Starting Contract Publication...');
|
|
252
254
|
console.log(` ├─ Project: ${projectPath}`);
|
|
@@ -259,6 +261,14 @@ async function publishContract(
|
|
|
259
261
|
await removeEnvContent(`${projectPath}/Move.lock`, network);
|
|
260
262
|
console.log(` └─ Account: ${dubhe.getAddress()}`);
|
|
261
263
|
|
|
264
|
+
// Ensure src/dubhe/Published.toml references the canonical framework address
|
|
265
|
+
// for this network before building. This is a no-op when the address is
|
|
266
|
+
// already current, and automatically corrects stale entries whenever the
|
|
267
|
+
// framework is redeployed on testnet/mainnet without a manual file update.
|
|
268
|
+
if (dubheConfig.name !== 'dubhe') {
|
|
269
|
+
syncDubheFrameworkAddress(process.cwd(), network, chainId);
|
|
270
|
+
}
|
|
271
|
+
|
|
262
272
|
console.log('\n📦 Building Contract...');
|
|
263
273
|
// For localnet: pass the ephemeral pubfile so the build system can resolve
|
|
264
274
|
// the dubhe dependency that was just published in publishDubheFramework().
|
|
@@ -506,7 +516,7 @@ async function publishContract(
|
|
|
506
516
|
dappStorageId || undefined
|
|
507
517
|
);
|
|
508
518
|
|
|
509
|
-
await saveMetadata(dubheConfig.name, network, packageId);
|
|
519
|
+
await saveMetadata(dubheConfig.name, network, packageId, fullnodeUrls);
|
|
510
520
|
|
|
511
521
|
// Insert package id to dubhe config
|
|
512
522
|
let config = JSON.parse(fs.readFileSync(`${process.cwd()}/dubhe.config.json`, 'utf-8'));
|
|
@@ -717,12 +727,14 @@ export async function publishHandler(
|
|
|
717
727
|
dubheConfig: DubheConfig,
|
|
718
728
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
719
729
|
force: boolean,
|
|
720
|
-
gasBudget?: number
|
|
730
|
+
gasBudget?: number,
|
|
731
|
+
fullnodeUrls?: string[]
|
|
721
732
|
) {
|
|
722
|
-
await switchEnv(network);
|
|
733
|
+
await switchEnv(network, fullnodeUrls?.[0]);
|
|
723
734
|
|
|
724
735
|
const dubhe = initializeDubhe({
|
|
725
|
-
network
|
|
736
|
+
network,
|
|
737
|
+
fullnodeUrls
|
|
726
738
|
});
|
|
727
739
|
|
|
728
740
|
const path = process.cwd();
|
|
@@ -732,5 +744,5 @@ export async function publishHandler(
|
|
|
732
744
|
await publishDubheFramework(dubhe, network);
|
|
733
745
|
}
|
|
734
746
|
|
|
735
|
-
await publishContract(dubhe, dubheConfig, network, projectPath, gasBudget, force);
|
|
747
|
+
await publishContract(dubhe, dubheConfig, network, projectPath, gasBudget, force, fullnodeUrls);
|
|
736
748
|
}
|
|
@@ -16,6 +16,7 @@ import {
|
|
|
16
16
|
getDappStorageId,
|
|
17
17
|
getOriginalDubhePackageId,
|
|
18
18
|
updatePublishedToml,
|
|
19
|
+
syncDubheFrameworkAddress,
|
|
19
20
|
clearPublishedTomlEntry,
|
|
20
21
|
restorePublishedTomlEntry,
|
|
21
22
|
readPublishedToml,
|
|
@@ -76,14 +77,15 @@ export async function upgradeHandler(
|
|
|
76
77
|
config: DubheConfig,
|
|
77
78
|
name: string,
|
|
78
79
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
79
|
-
bumpVersion: boolean = false
|
|
80
|
+
bumpVersion: boolean = false,
|
|
81
|
+
fullnodeUrls?: string[]
|
|
80
82
|
) {
|
|
81
|
-
await switchEnv(network);
|
|
83
|
+
await switchEnv(network, fullnodeUrls?.[0]);
|
|
82
84
|
|
|
83
85
|
const path = process.cwd();
|
|
84
86
|
const projectPath = `${path}/src/${name}`;
|
|
85
87
|
|
|
86
|
-
const dubhe = initializeDubhe({ network });
|
|
88
|
+
const dubhe = initializeDubhe({ network, fullnodeUrls });
|
|
87
89
|
|
|
88
90
|
let oldVersion = Number(await getVersion(projectPath, network));
|
|
89
91
|
let oldPackageId = await getOldPackageId(projectPath, network);
|
|
@@ -130,6 +132,15 @@ export async function upgradeHandler(
|
|
|
130
132
|
const savedPublishedEntry =
|
|
131
133
|
network !== 'localnet' ? clearPublishedTomlEntry(projectPath, network) : undefined;
|
|
132
134
|
|
|
135
|
+
// For testnet/mainnet: auto-sync src/dubhe/Published.toml to the canonical
|
|
136
|
+
// framework address from the SDK before building. Prevents
|
|
137
|
+
// VMVerificationOrDeserializationError when the framework was redeployed
|
|
138
|
+
// since the Published.toml was last written. Skip when upgrading dubhe itself.
|
|
139
|
+
if (name !== 'dubhe' && (network === 'testnet' || network === 'mainnet')) {
|
|
140
|
+
const chainId = await dubhe.suiInteractor.currentClient.getChainIdentifier();
|
|
141
|
+
syncDubheFrameworkAddress(path, network, chainId);
|
|
142
|
+
}
|
|
143
|
+
|
|
133
144
|
// For localnet upgrades: refresh Pub.localnet.toml with dubhe's current address
|
|
134
145
|
// so that the build can resolve the dubhe dependency.
|
|
135
146
|
// Skip this step when upgrading dubhe itself — dubhe has no local dubhe dependency,
|
package/src/utils/utils.ts
CHANGED
|
@@ -250,13 +250,14 @@ export async function saveContractData(
|
|
|
250
250
|
export async function saveMetadata(
|
|
251
251
|
projectName: string,
|
|
252
252
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
253
|
-
packageId: string
|
|
253
|
+
packageId: string,
|
|
254
|
+
fullnodeUrls?: string[]
|
|
254
255
|
) {
|
|
255
256
|
const path = process.cwd();
|
|
256
257
|
|
|
257
258
|
// Save metadata files
|
|
258
259
|
try {
|
|
259
|
-
const metadata = await loadMetadata(network, packageId);
|
|
260
|
+
const metadata = await loadMetadata(network, packageId, fullnodeUrls);
|
|
260
261
|
if (metadata) {
|
|
261
262
|
const metadataJson = JSON.stringify(metadata, null, 2);
|
|
262
263
|
|
|
@@ -396,6 +397,46 @@ export function getPublishedTomlEntry(
|
|
|
396
397
|
return entries[network];
|
|
397
398
|
}
|
|
398
399
|
|
|
400
|
+
/**
|
|
401
|
+
* Syncs the Dubhe framework address in `src/dubhe/Published.toml` with the
|
|
402
|
+
* canonical package ID from the SDK's `getDefaultConfig` for the given network.
|
|
403
|
+
*
|
|
404
|
+
* This prevents `VMVerificationOrDeserializationError` during `publish` and
|
|
405
|
+
* `upgrade` when the framework has been redeployed on testnet/mainnet but the
|
|
406
|
+
* local `Published.toml` still references the old address. The function is a
|
|
407
|
+
* no-op for localnet and devnet (no stable canonical address exists there).
|
|
408
|
+
*
|
|
409
|
+
* @param contractsRootDir - The contracts working directory (process.cwd() in CLI context)
|
|
410
|
+
* @param network - Target network
|
|
411
|
+
* @param chainId - Live chain identifier obtained from the node
|
|
412
|
+
*/
|
|
413
|
+
export function syncDubheFrameworkAddress(
|
|
414
|
+
contractsRootDir: string,
|
|
415
|
+
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
416
|
+
chainId: string
|
|
417
|
+
): void {
|
|
418
|
+
if (network === 'localnet' || network === 'devnet') return;
|
|
419
|
+
|
|
420
|
+
const frameworkPackageId = getDefaultConfig(network as NetworkType).frameworkPackageId;
|
|
421
|
+
if (!frameworkPackageId) return;
|
|
422
|
+
|
|
423
|
+
const dubhePath = pathJoin(contractsRootDir, 'src', 'dubhe');
|
|
424
|
+
if (!fs.existsSync(dubhePath)) return;
|
|
425
|
+
|
|
426
|
+
const existing = getPublishedTomlEntry(dubhePath, network);
|
|
427
|
+
if (existing?.publishedAt === frameworkPackageId) return;
|
|
428
|
+
|
|
429
|
+
updatePublishedToml(dubhePath, network, chainId, frameworkPackageId, frameworkPackageId, 1);
|
|
430
|
+
console.log(
|
|
431
|
+
chalk.gray(
|
|
432
|
+
` ├─ Auto-synced dubhe framework address for ${network}: ${frameworkPackageId.slice(
|
|
433
|
+
0,
|
|
434
|
+
10
|
|
435
|
+
)}...`
|
|
436
|
+
)
|
|
437
|
+
);
|
|
438
|
+
}
|
|
439
|
+
|
|
399
440
|
export function clearPublishedTomlEntry(
|
|
400
441
|
packagePath: string,
|
|
401
442
|
network: string
|
|
@@ -570,7 +611,8 @@ async function checkRpcAvailability(rpcUrl: string): Promise<boolean> {
|
|
|
570
611
|
}
|
|
571
612
|
|
|
572
613
|
export async function addEnv(
|
|
573
|
-
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
|
|
614
|
+
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
615
|
+
rpcUrl?: string
|
|
574
616
|
): Promise<void> {
|
|
575
617
|
const rpcMap = {
|
|
576
618
|
localnet: 'http://127.0.0.1:9000',
|
|
@@ -579,13 +621,13 @@ export async function addEnv(
|
|
|
579
621
|
mainnet: 'https://fullnode.mainnet.sui.io:443/'
|
|
580
622
|
};
|
|
581
623
|
|
|
582
|
-
const
|
|
624
|
+
const resolvedRpcUrl = rpcUrl || rpcMap[network];
|
|
583
625
|
|
|
584
626
|
// Check RPC availability first
|
|
585
|
-
const isRpcAvailable = await checkRpcAvailability(
|
|
627
|
+
const isRpcAvailable = await checkRpcAvailability(resolvedRpcUrl);
|
|
586
628
|
if (!isRpcAvailable) {
|
|
587
629
|
throw new Error(
|
|
588
|
-
`RPC endpoint ${
|
|
630
|
+
`RPC endpoint ${resolvedRpcUrl} is not available. Please check your network connection or try again later.`
|
|
589
631
|
);
|
|
590
632
|
}
|
|
591
633
|
|
|
@@ -595,7 +637,7 @@ export async function addEnv(
|
|
|
595
637
|
|
|
596
638
|
const suiProcess = spawn(
|
|
597
639
|
'sui',
|
|
598
|
-
['client', 'new-env', '--alias', network, '--rpc',
|
|
640
|
+
['client', 'new-env', '--alias', network, '--rpc', resolvedRpcUrl],
|
|
599
641
|
{
|
|
600
642
|
env: { ...process.env },
|
|
601
643
|
stdio: 'pipe'
|
|
@@ -716,10 +758,13 @@ export async function getDefaultNetwork(): Promise<NetworkAlias> {
|
|
|
716
758
|
return currentAlias as NetworkAlias;
|
|
717
759
|
}
|
|
718
760
|
|
|
719
|
-
export async function switchEnv(
|
|
761
|
+
export async function switchEnv(
|
|
762
|
+
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
763
|
+
rpcUrl?: string
|
|
764
|
+
) {
|
|
720
765
|
try {
|
|
721
766
|
// First, try to add the environment
|
|
722
|
-
await addEnv(network);
|
|
767
|
+
await addEnv(network, rpcUrl);
|
|
723
768
|
|
|
724
769
|
// Then switch to the specified environment
|
|
725
770
|
return new Promise<void>((resolve, reject) => {
|
|
@@ -793,18 +838,21 @@ export function loadKey(): string {
|
|
|
793
838
|
export function initializeDubhe({
|
|
794
839
|
network,
|
|
795
840
|
packageId,
|
|
796
|
-
metadata
|
|
841
|
+
metadata,
|
|
842
|
+
fullnodeUrls
|
|
797
843
|
}: {
|
|
798
844
|
network: NetworkType;
|
|
799
845
|
packageId?: string;
|
|
800
846
|
metadata?: SuiMoveNormalizedModules;
|
|
847
|
+
fullnodeUrls?: string[];
|
|
801
848
|
}): Dubhe {
|
|
802
849
|
const privateKey = loadKey();
|
|
803
850
|
return new Dubhe({
|
|
804
851
|
networkType: network,
|
|
805
852
|
secretKey: privateKey,
|
|
806
853
|
packageId,
|
|
807
|
-
metadata
|
|
854
|
+
metadata,
|
|
855
|
+
fullnodeUrls
|
|
808
856
|
});
|
|
809
857
|
}
|
|
810
858
|
|