@0xobelisk/sui-cli 1.2.0-pre.123 → 1.2.0-pre.125
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/dubhe.js +104 -114
- package/dist/dubhe.js.map +1 -1
- package/package.json +3 -3
- package/src/utils/publishHandler.ts +5 -116
- package/src/utils/upgradeHandler.ts +13 -57
- package/src/utils/utils.ts +20 -0
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.125",
|
|
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.125",
|
|
51
|
+
"@0xobelisk/sui-common": "1.2.0-pre.125"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/cli-progress": "^3.11.5",
|
|
@@ -16,7 +16,8 @@ import {
|
|
|
16
16
|
getEphemeralPubFilePath,
|
|
17
17
|
getPublishedTomlEntry,
|
|
18
18
|
clearPublishedTomlEntry,
|
|
19
|
-
restorePublishedTomlEntry
|
|
19
|
+
restorePublishedTomlEntry,
|
|
20
|
+
removeEnvFromMoveLock
|
|
20
21
|
} from './utils';
|
|
21
22
|
import { DubheConfig } from '@0xobelisk/sui-common';
|
|
22
23
|
import * as fs from 'fs';
|
|
@@ -48,116 +49,6 @@ function patchMoveTomlWithLocalnetEnv(moveTomlPath: string, chainId: string): st
|
|
|
48
49
|
return content;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
|
-
async function removeEnvContent(
|
|
52
|
-
filePath: string,
|
|
53
|
-
networkType: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
|
|
54
|
-
): Promise<void> {
|
|
55
|
-
if (!fs.existsSync(filePath)) {
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
const content = fs.readFileSync(filePath, 'utf-8');
|
|
59
|
-
const regex = new RegExp(`\\[env\\.${networkType}\\][\\s\\S]*?(?=\\[|$)`, 'g');
|
|
60
|
-
const updatedContent = content.replace(regex, '');
|
|
61
|
-
fs.writeFileSync(filePath, updatedContent, 'utf-8');
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
interface EnvConfig {
|
|
65
|
-
chainId: string;
|
|
66
|
-
originalPublishedId: string;
|
|
67
|
-
latestPublishedId: string;
|
|
68
|
-
publishedVersion: number;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function updateEnvFile(
|
|
72
|
-
filePath: string,
|
|
73
|
-
networkType: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
74
|
-
operation: 'publish' | 'upgrade',
|
|
75
|
-
chainId: string,
|
|
76
|
-
publishedId: string
|
|
77
|
-
): void {
|
|
78
|
-
const envFilePath = path.resolve(filePath);
|
|
79
|
-
const envContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
80
|
-
const envLines = envContent.split('\n');
|
|
81
|
-
|
|
82
|
-
const networkSectionIndex = envLines.findIndex((line) => line.trim() === `[env.${networkType}]`);
|
|
83
|
-
const config: EnvConfig = {
|
|
84
|
-
chainId: chainId,
|
|
85
|
-
originalPublishedId: '',
|
|
86
|
-
latestPublishedId: '',
|
|
87
|
-
publishedVersion: 0
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
if (networkSectionIndex === -1) {
|
|
91
|
-
// If network section is not found, add a new section
|
|
92
|
-
if (operation === 'publish') {
|
|
93
|
-
config.originalPublishedId = publishedId;
|
|
94
|
-
config.latestPublishedId = publishedId;
|
|
95
|
-
config.publishedVersion = 1;
|
|
96
|
-
} else {
|
|
97
|
-
throw new Error(
|
|
98
|
-
`Network type [env.${networkType}] not found in the file and cannot upgrade.`
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
} else {
|
|
102
|
-
for (let i = networkSectionIndex + 1; i < envLines.length; i++) {
|
|
103
|
-
const line = envLines[i].trim();
|
|
104
|
-
if (line.startsWith('[')) break; // End of the current network section
|
|
105
|
-
|
|
106
|
-
const [key, value] = line.split('=').map((part) => part.trim().replace(/"/g, ''));
|
|
107
|
-
switch (key) {
|
|
108
|
-
case 'original-published-id':
|
|
109
|
-
config.originalPublishedId = value;
|
|
110
|
-
break;
|
|
111
|
-
case 'latest-published-id':
|
|
112
|
-
config.latestPublishedId = value;
|
|
113
|
-
break;
|
|
114
|
-
case 'published-version':
|
|
115
|
-
config.publishedVersion = parseInt(value, 10);
|
|
116
|
-
break;
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
if (operation === 'publish') {
|
|
121
|
-
config.originalPublishedId = publishedId;
|
|
122
|
-
config.latestPublishedId = publishedId;
|
|
123
|
-
config.publishedVersion = 1;
|
|
124
|
-
} else if (operation === 'upgrade') {
|
|
125
|
-
config.latestPublishedId = publishedId;
|
|
126
|
-
config.publishedVersion += 1;
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
const updatedSection = `
|
|
131
|
-
[env.${networkType}]
|
|
132
|
-
chain-id = "${config.chainId}"
|
|
133
|
-
original-published-id = "${config.originalPublishedId}"
|
|
134
|
-
latest-published-id = "${config.latestPublishedId}"
|
|
135
|
-
published-version = "${config.publishedVersion}"
|
|
136
|
-
`;
|
|
137
|
-
|
|
138
|
-
const newEnvContent =
|
|
139
|
-
networkSectionIndex === -1
|
|
140
|
-
? envContent + updatedSection
|
|
141
|
-
: envLines.slice(0, networkSectionIndex).join('\n') + updatedSection;
|
|
142
|
-
|
|
143
|
-
fs.writeFileSync(envFilePath, newEnvContent, 'utf-8');
|
|
144
|
-
}
|
|
145
|
-
// function capitalizeAndRemoveUnderscores(input: string): string {
|
|
146
|
-
// return input
|
|
147
|
-
// .split('_')
|
|
148
|
-
// .map((word, index) => {
|
|
149
|
-
// return index === 0
|
|
150
|
-
// ? word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()
|
|
151
|
-
// : word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
152
|
-
// })
|
|
153
|
-
// .join('');
|
|
154
|
-
// }
|
|
155
|
-
//
|
|
156
|
-
// function getLastSegment(input: string): string {
|
|
157
|
-
// const segments = input.split('::');
|
|
158
|
-
// return segments.length > 0 ? segments[segments.length - 1] : '';
|
|
159
|
-
// }
|
|
160
|
-
|
|
161
52
|
/**
|
|
162
53
|
* Build a Move package and return [modules, dependencies] as base64 arrays.
|
|
163
54
|
*
|
|
@@ -258,7 +149,7 @@ async function publishContract(
|
|
|
258
149
|
const chainId = await waitForNode(dubhe);
|
|
259
150
|
console.log(' ├─ Validating Environment...');
|
|
260
151
|
|
|
261
|
-
|
|
152
|
+
removeEnvFromMoveLock(`${projectPath}/Move.lock`, network);
|
|
262
153
|
console.log(` └─ Account: ${dubhe.getAddress()}`);
|
|
263
154
|
|
|
264
155
|
// Ensure src/dubhe/Published.toml references the canonical framework address
|
|
@@ -442,7 +333,6 @@ async function publishContract(
|
|
|
442
333
|
|
|
443
334
|
console.log(` └─ Transaction: ${result.digest}`);
|
|
444
335
|
|
|
445
|
-
updateEnvFile(`${projectPath}/Move.lock`, network, 'publish', chainId, packageId);
|
|
446
336
|
updatePublishedToml(projectPath, network, chainId, packageId, packageId, 1);
|
|
447
337
|
|
|
448
338
|
console.log('\n⚡ Executing Deploy Hook...');
|
|
@@ -588,14 +478,14 @@ export async function publishDubheFramework(
|
|
|
588
478
|
|
|
589
479
|
const chainId = await waitForNode(dubhe);
|
|
590
480
|
|
|
591
|
-
|
|
481
|
+
removeEnvFromMoveLock(`${projectPath}/Move.lock`, network);
|
|
592
482
|
if (network === 'localnet') {
|
|
593
483
|
// When building with --build-env testnet, Sui CLI reads Move.lock's [env.testnet] section
|
|
594
484
|
// and bakes its original-published-id (non-zero for a previously published dubhe) into the
|
|
595
485
|
// bytecode as the package self-address. Publishing then fails with PublishErrorNonZeroAddress
|
|
596
486
|
// because Sui requires the self-address to be 0x0 for a first-time publish.
|
|
597
487
|
// Fix: clear the testnet env section before building so the CLI uses 0x0 from Move.toml.
|
|
598
|
-
|
|
488
|
+
removeEnvFromMoveLock(`${projectPath}/Move.lock`, 'testnet');
|
|
599
489
|
}
|
|
600
490
|
await updateMoveTomlAddress(projectPath, '0x0');
|
|
601
491
|
|
|
@@ -715,7 +605,6 @@ export async function publishDubheFramework(
|
|
|
715
605
|
network === 'localnet' ? packageId : undefined
|
|
716
606
|
);
|
|
717
607
|
|
|
718
|
-
updateEnvFile(`${projectPath}/Move.lock`, network, 'publish', chainId, packageId);
|
|
719
608
|
updatePublishedToml(projectPath, network, chainId, packageId, packageId, 1);
|
|
720
609
|
|
|
721
610
|
// For localnet: write dubhe's published address to Pub.localnet.toml so that
|
|
@@ -23,10 +23,10 @@ import {
|
|
|
23
23
|
updateEphemeralPubFile,
|
|
24
24
|
getEphemeralPubFilePath,
|
|
25
25
|
updateMoveTomlAddress,
|
|
26
|
-
appendPackageIdToConfig
|
|
26
|
+
appendPackageIdToConfig,
|
|
27
|
+
removeEnvFromMoveLock
|
|
27
28
|
} from './utils';
|
|
28
29
|
import * as fs from 'fs';
|
|
29
|
-
import * as path from 'path';
|
|
30
30
|
import { DubheConfig } from '@0xobelisk/sui-common';
|
|
31
31
|
|
|
32
32
|
type Migration = {
|
|
@@ -34,46 +34,6 @@ type Migration = {
|
|
|
34
34
|
fields: any;
|
|
35
35
|
};
|
|
36
36
|
|
|
37
|
-
function replaceEnvField(
|
|
38
|
-
filePath: string,
|
|
39
|
-
networkType: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
40
|
-
field: 'original-published-id' | 'latest-published-id' | 'published-version',
|
|
41
|
-
newValue: string
|
|
42
|
-
): string {
|
|
43
|
-
const envFilePath = path.resolve(filePath);
|
|
44
|
-
const envContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
45
|
-
const envLines = envContent.split('\n');
|
|
46
|
-
|
|
47
|
-
const networkSectionIndex = envLines.findIndex((line) => line.trim() === `[env.${networkType}]`);
|
|
48
|
-
if (networkSectionIndex === -1) {
|
|
49
|
-
console.log(`Network type [env.${networkType}] not found in the file.`);
|
|
50
|
-
return '';
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
let fieldIndex = -1;
|
|
54
|
-
let previousValue: string = '';
|
|
55
|
-
for (let i = networkSectionIndex + 1; i < envLines.length; i++) {
|
|
56
|
-
const line = envLines[i].trim();
|
|
57
|
-
if (line.startsWith('[')) break; // End of the current network section
|
|
58
|
-
|
|
59
|
-
if (line.startsWith(field)) {
|
|
60
|
-
fieldIndex = i;
|
|
61
|
-
previousValue = line.split('=')[1].trim().replace(/"/g, '');
|
|
62
|
-
break;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
if (fieldIndex !== -1) {
|
|
67
|
-
envLines[fieldIndex] = `${field} = "${newValue}"`;
|
|
68
|
-
const newEnvContent = envLines.join('\n');
|
|
69
|
-
fs.writeFileSync(envFilePath, newEnvContent, 'utf-8');
|
|
70
|
-
} else {
|
|
71
|
-
console.log(`${field} not found for [env.${networkType}].`);
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return previousValue;
|
|
75
|
-
}
|
|
76
|
-
|
|
77
37
|
export async function upgradeHandler(
|
|
78
38
|
config: DubheConfig,
|
|
79
39
|
name: string,
|
|
@@ -119,12 +79,11 @@ export async function upgradeHandler(
|
|
|
119
79
|
appendMigrateFunction(projectPath, config.name, oldVersion + 1);
|
|
120
80
|
}
|
|
121
81
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
);
|
|
82
|
+
// Read original_published_id from Published.toml before clearing it.
|
|
83
|
+
// Published.toml is the canonical source of truth for deployed addresses;
|
|
84
|
+
// Move.lock [env.*] is owned by the Sui CLI and must not be read or written
|
|
85
|
+
// by our toolchain.
|
|
86
|
+
const original_published_id = readPublishedToml(projectPath)[network]?.originalId ?? '';
|
|
128
87
|
|
|
129
88
|
// For persistent networks (testnet/mainnet): zero out Published.toml so the
|
|
130
89
|
// package compiles with address 0x0 for upgrade.
|
|
@@ -133,6 +92,12 @@ export async function upgradeHandler(
|
|
|
133
92
|
const savedPublishedEntry =
|
|
134
93
|
network !== 'localnet' ? clearPublishedTomlEntry(projectPath, network) : undefined;
|
|
135
94
|
|
|
95
|
+
// Clear Move.lock [env.*] so the Sui CLI does not pick up a stale non-zero
|
|
96
|
+
// address and fail with PublishErrorNonZeroAddress during build.
|
|
97
|
+
// We intentionally do NOT write it back afterwards — Published.toml is the
|
|
98
|
+
// source of truth and the Sui CLI will regenerate the lock section if needed.
|
|
99
|
+
removeEnvFromMoveLock(`${projectPath}/Move.lock`, network);
|
|
100
|
+
|
|
136
101
|
// For testnet/mainnet: auto-sync src/dubhe/Published.toml to the canonical
|
|
137
102
|
// framework address from the SDK before building. Prevents
|
|
138
103
|
// VMVerificationOrDeserializationError when the framework was redeployed
|
|
@@ -265,15 +230,6 @@ export async function upgradeHandler(
|
|
|
265
230
|
}
|
|
266
231
|
});
|
|
267
232
|
|
|
268
|
-
replaceEnvField(
|
|
269
|
-
`${projectPath}/Move.lock`,
|
|
270
|
-
network,
|
|
271
|
-
'original-published-id',
|
|
272
|
-
original_published_id
|
|
273
|
-
);
|
|
274
|
-
replaceEnvField(`${projectPath}/Move.lock`, network, 'latest-published-id', newPackageId);
|
|
275
|
-
replaceEnvField(`${projectPath}/Move.lock`, network, 'published-version', oldVersion + 1 + '');
|
|
276
|
-
|
|
277
233
|
// Update Published.toml with the new package ID after upgrade.
|
|
278
234
|
// For localnet: savedPublishedEntry is undefined (we skip clearPublishedTomlEntry),
|
|
279
235
|
// so fall back to reading the current Published.toml entry for chainId/originalId.
|
package/src/utils/utils.ts
CHANGED
|
@@ -1250,3 +1250,23 @@ export function appendPackageIdToConfig(configJsonPath: string, newPackageId: st
|
|
|
1250
1250
|
fs.writeFileSync(configJsonPath, JSON.stringify(configJson, null, 2));
|
|
1251
1251
|
}
|
|
1252
1252
|
}
|
|
1253
|
+
|
|
1254
|
+
/**
|
|
1255
|
+
* Strip the [env.<network>] section from a Move.lock file before a build.
|
|
1256
|
+
*
|
|
1257
|
+
* Move.lock is owned by the Sui CLI and should never be written by our CLI.
|
|
1258
|
+
* We only remove stale [env.*] entries so the Sui CLI does not pick up an
|
|
1259
|
+
* old non-zero address and fail with PublishErrorNonZeroAddress. After the
|
|
1260
|
+
* publish/upgrade the entry is intentionally left absent — Published.toml is
|
|
1261
|
+
* the canonical source of truth for deployed addresses across our toolchain.
|
|
1262
|
+
*/
|
|
1263
|
+
export function removeEnvFromMoveLock(
|
|
1264
|
+
filePath: string,
|
|
1265
|
+
networkType: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
|
|
1266
|
+
): void {
|
|
1267
|
+
if (!fs.existsSync(filePath)) return;
|
|
1268
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
1269
|
+
const regex = new RegExp(`\\[env\\.${networkType}\\][\\s\\S]*?(?=\\[|$)`, 'g');
|
|
1270
|
+
const updated = content.replace(regex, '');
|
|
1271
|
+
fs.writeFileSync(filePath, updated, 'utf-8');
|
|
1272
|
+
}
|