@0xobelisk/sui-cli 1.0.6 ā 1.0.8
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 +15 -15
- package/dist/dubhe.js.map +1 -1
- package/package.json +4 -3
- package/src/commands/test.ts +39 -38
- package/src/utils/callHandler.ts +3 -3
- package/src/utils/publishHandler.ts +2 -2
- package/src/utils/startNode.ts +1 -7
- package/src/utils/storeConfig.ts +0 -1
- package/src/utils/upgradeHandler.ts +88 -56
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@0xobelisk/sui-cli",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.8",
|
|
4
4
|
"description": "Tookit for interacting with move eps framework",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sui",
|
|
@@ -59,11 +59,12 @@
|
|
|
59
59
|
"vitest": "0.31.4"
|
|
60
60
|
},
|
|
61
61
|
"scripts": {
|
|
62
|
-
"build": "pnpm run build:js",
|
|
62
|
+
"build": "pnpm run type-check && pnpm run build:js",
|
|
63
63
|
"build:js": "tsup && chmod +x ./dist/dubhe.js",
|
|
64
64
|
"clean": "pnpm run clean:js",
|
|
65
65
|
"clean:js": "rimraf dist",
|
|
66
66
|
"dev": "tsup --watch",
|
|
67
|
-
"lint": "eslint . --ext .ts"
|
|
67
|
+
"lint": "eslint . --ext .ts",
|
|
68
|
+
"type-check": "tsc --noEmit"
|
|
68
69
|
}
|
|
69
70
|
}
|
package/src/commands/test.ts
CHANGED
|
@@ -1,50 +1,51 @@
|
|
|
1
|
-
import type { CommandModule } from
|
|
2
|
-
import { execSync } from
|
|
3
|
-
import chalk from "chalk";
|
|
1
|
+
import type { CommandModule } from 'yargs';
|
|
2
|
+
import { execSync } from 'child_process';
|
|
4
3
|
import { DubheConfig, loadConfig } from '@0xobelisk/sui-common';
|
|
5
4
|
|
|
6
5
|
type Options = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
'config-path': string;
|
|
7
|
+
test?: string;
|
|
8
|
+
'gas-limit'?: string;
|
|
10
9
|
};
|
|
11
10
|
|
|
12
11
|
const commandModule: CommandModule<Options, Options> = {
|
|
13
|
-
|
|
12
|
+
command: 'test',
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
describe: 'Run tests in Dubhe contracts',
|
|
16
15
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
16
|
+
builder(yargs) {
|
|
17
|
+
return yargs.options({
|
|
18
|
+
'config-path': {
|
|
19
|
+
type: 'string',
|
|
20
|
+
default: 'dubhe.config.ts',
|
|
21
|
+
description: 'Options to pass to forge test',
|
|
22
|
+
},
|
|
23
|
+
test: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
desc: 'Run a specific test',
|
|
26
|
+
},
|
|
27
|
+
'gas-limit': {
|
|
28
|
+
type: 'string',
|
|
29
|
+
desc: 'Set the gas limit for the test',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
},
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
34
|
+
async handler({ 'config-path': configPath, test, 'gas-limit': gasLimit }) {
|
|
35
|
+
// Start an internal anvil process if no world address is provided
|
|
36
|
+
try {
|
|
37
|
+
console.log('š Running move test');
|
|
38
|
+
const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
|
|
39
|
+
const path = process.cwd();
|
|
40
|
+
const projectPath = `${path}/contracts/${dubheConfig.name}`;
|
|
41
|
+
const command = `sui move test --path ${projectPath} ${
|
|
42
|
+
test ? ` --test ${test}` : ''
|
|
43
|
+
} ${gasLimit ? ` --gas-limit ${gasLimit}` : ''}`;
|
|
44
|
+
execSync(command, { stdio: 'inherit', encoding: 'utf-8' });
|
|
45
|
+
} catch (error: any) {
|
|
46
|
+
process.exit(0);
|
|
47
|
+
}
|
|
48
|
+
},
|
|
48
49
|
};
|
|
49
50
|
|
|
50
51
|
export default commandModule;
|
package/src/utils/callHandler.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
TransactionResult,
|
|
6
6
|
} from '@0xobelisk/sui-client';
|
|
7
7
|
import { DubheCliError } from './errors';
|
|
8
|
-
import { validatePrivateKey, getOldPackageId
|
|
8
|
+
import { validatePrivateKey, getOldPackageId } from './utils';
|
|
9
9
|
import { DubheConfig } from '@0xobelisk/sui-common';
|
|
10
10
|
import { loadMetadataFromFile } from './queryStorage';
|
|
11
11
|
|
|
@@ -26,7 +26,7 @@ const BaseTxType = [
|
|
|
26
26
|
function validateParams(params: any[]) {
|
|
27
27
|
try {
|
|
28
28
|
params.forEach(param => {
|
|
29
|
-
const [type,
|
|
29
|
+
const [type, _] = param.split(':');
|
|
30
30
|
if (!BaseTxType.includes(type)) {
|
|
31
31
|
throw new Error(`Invalid param type: ${type}`);
|
|
32
32
|
}
|
|
@@ -162,5 +162,5 @@ in your contracts directory to use the default sui private key.`
|
|
|
162
162
|
params: formattedParams,
|
|
163
163
|
})) as TransactionResult;
|
|
164
164
|
|
|
165
|
-
console.log(result);
|
|
165
|
+
console.log(JSON.stringify(result, null, 2));
|
|
166
166
|
}
|
|
@@ -9,7 +9,6 @@ import { execSync } from 'child_process';
|
|
|
9
9
|
import chalk from 'chalk';
|
|
10
10
|
import { DubheCliError } from './errors';
|
|
11
11
|
import {
|
|
12
|
-
updateVersionInFile,
|
|
13
12
|
saveContractData,
|
|
14
13
|
validatePrivateKey,
|
|
15
14
|
schema,
|
|
@@ -282,7 +281,7 @@ async function publishContract(
|
|
|
282
281
|
capitalizeAndRemoveUnderscores(schemaKey) ===
|
|
283
282
|
getLastSegment(object.objectType)
|
|
284
283
|
) {
|
|
285
|
-
structure = dubheConfig.schemas[schemaKey]
|
|
284
|
+
structure = dubheConfig.schemas[schemaKey];
|
|
286
285
|
}
|
|
287
286
|
}
|
|
288
287
|
|
|
@@ -427,6 +426,7 @@ export async function publishDubheFramework(
|
|
|
427
426
|
version,
|
|
428
427
|
schemas
|
|
429
428
|
);
|
|
429
|
+
await delay(1000);
|
|
430
430
|
console.log(chalk.green('\nā
Dubhe Framework deployed successfully'));
|
|
431
431
|
}
|
|
432
432
|
|
package/src/utils/startNode.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import { execSync, spawn } from 'child_process';
|
|
2
2
|
import chalk from 'chalk';
|
|
3
3
|
import { printDubhe } from './printDubhe';
|
|
4
|
-
import {
|
|
5
|
-
delay,
|
|
6
|
-
DubheCliError,
|
|
7
|
-
publishDubheFramework,
|
|
8
|
-
validatePrivateKey,
|
|
9
|
-
} from '../utils';
|
|
4
|
+
import { delay, DubheCliError, validatePrivateKey } from '../utils';
|
|
10
5
|
import { Dubhe } from '@0xobelisk/sui-client';
|
|
11
|
-
import { getFullnodeUrl, SuiClient } from '@mysten/sui/client';
|
|
12
6
|
|
|
13
7
|
function isSuiStartRunning(): boolean {
|
|
14
8
|
try {
|
package/src/utils/storeConfig.ts
CHANGED
|
@@ -5,62 +5,70 @@ import { execSync } from 'child_process';
|
|
|
5
5
|
import chalk from 'chalk';
|
|
6
6
|
import { DubheCliError, UpgradeError } from './errors';
|
|
7
7
|
import {
|
|
8
|
-
updateVersionInFile,
|
|
9
8
|
getOldPackageId,
|
|
10
9
|
getVersion,
|
|
11
10
|
getUpgradeCap,
|
|
12
11
|
saveContractData,
|
|
13
|
-
validatePrivateKey,
|
|
12
|
+
validatePrivateKey,
|
|
13
|
+
getOnchainSchemas,
|
|
14
|
+
switchEnv,
|
|
14
15
|
} from './utils';
|
|
15
16
|
import * as fs from 'fs';
|
|
16
17
|
import * as path from 'path';
|
|
17
18
|
import { DubheConfig } from '@0xobelisk/sui-common';
|
|
18
19
|
|
|
19
|
-
type ObjectContent = {
|
|
20
|
-
type: string;
|
|
21
|
-
fields: Record<string, any>;
|
|
22
|
-
hasPublicTransfer: boolean;
|
|
23
|
-
dataType: string;
|
|
24
|
-
};
|
|
25
|
-
|
|
26
20
|
type Field = {
|
|
27
21
|
name: string;
|
|
28
22
|
type: string;
|
|
29
|
-
}
|
|
23
|
+
};
|
|
30
24
|
|
|
31
25
|
type Migration = {
|
|
32
26
|
schemaName: string;
|
|
33
27
|
fields: Field[];
|
|
34
28
|
};
|
|
35
29
|
|
|
36
|
-
function updateMigrateMethod(
|
|
37
|
-
|
|
30
|
+
function updateMigrateMethod(
|
|
31
|
+
projectPath: string,
|
|
32
|
+
migrations: Migration[]
|
|
33
|
+
): void {
|
|
34
|
+
migrations.forEach(migration => {
|
|
38
35
|
let filePath = `${projectPath}/sources/codegen/schemas/${migration.schemaName}.move`;
|
|
39
36
|
const fileContent = fs.readFileSync(filePath, 'utf-8');
|
|
40
|
-
const migrateMethodRegex = new RegExp(
|
|
37
|
+
const migrateMethodRegex = new RegExp(
|
|
38
|
+
`public fun migrate\\(_${
|
|
39
|
+
migration.schemaName
|
|
40
|
+
}: &mut ${capitalizeAndRemoveUnderscores(
|
|
41
|
+
migration.schemaName
|
|
42
|
+
)}, _cap: &UpgradeCap\\) {[^}]*}`
|
|
43
|
+
);
|
|
41
44
|
const newMigrateMethod = `
|
|
42
|
-
public fun migrate(${
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
45
|
+
public fun migrate(${
|
|
46
|
+
migration.schemaName
|
|
47
|
+
}: &mut ${capitalizeAndRemoveUnderscores(
|
|
48
|
+
migration.schemaName
|
|
49
|
+
)}, _cap: &UpgradeCap) {
|
|
50
|
+
${migration.fields
|
|
51
|
+
.map(field => {
|
|
52
|
+
let storage_type = '';
|
|
53
|
+
if (field.type.includes('StorageValue')) {
|
|
54
|
+
storage_type = `storage_value::new()`;
|
|
55
|
+
} else if (field.type.includes('StorageMap')) {
|
|
56
|
+
storage_type = `storage_map::new()`;
|
|
57
|
+
} else if (field.type.includes('StorageDoubleMap')) {
|
|
58
|
+
storage_type = `storage_double_map::new()`;
|
|
59
|
+
}
|
|
60
|
+
return `storage_migration::add_field<${field.type}>(&mut ${migration.schemaName}.id, b"${field.name}", ${storage_type});`;
|
|
61
|
+
})
|
|
62
|
+
.join('')}
|
|
56
63
|
}
|
|
57
64
|
`;
|
|
58
65
|
|
|
59
|
-
const updatedContent = fileContent.replace(
|
|
66
|
+
const updatedContent = fileContent.replace(
|
|
67
|
+
migrateMethodRegex,
|
|
68
|
+
newMigrateMethod
|
|
69
|
+
);
|
|
60
70
|
fs.writeFileSync(filePath, updatedContent, 'utf-8');
|
|
61
71
|
});
|
|
62
|
-
|
|
63
|
-
|
|
64
72
|
}
|
|
65
73
|
|
|
66
74
|
function capitalizeAndRemoveUnderscores(input: string): string {
|
|
@@ -82,21 +90,26 @@ function getLastSegment(input: string): string {
|
|
|
82
90
|
function replaceEnvField(
|
|
83
91
|
filePath: string,
|
|
84
92
|
networkType: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
85
|
-
field:
|
|
93
|
+
field:
|
|
94
|
+
| 'original-published-id'
|
|
95
|
+
| 'latest-published-id'
|
|
96
|
+
| 'published-version',
|
|
86
97
|
newValue: string
|
|
87
98
|
): string {
|
|
88
99
|
const envFilePath = path.resolve(filePath);
|
|
89
100
|
const envContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
90
101
|
const envLines = envContent.split('\n');
|
|
91
102
|
|
|
92
|
-
const networkSectionIndex = envLines.findIndex(
|
|
103
|
+
const networkSectionIndex = envLines.findIndex(
|
|
104
|
+
line => line.trim() === `[env.${networkType}]`
|
|
105
|
+
);
|
|
93
106
|
if (networkSectionIndex === -1) {
|
|
94
107
|
console.log(`Network type [env.${networkType}] not found in the file.`);
|
|
95
|
-
return
|
|
108
|
+
return '';
|
|
96
109
|
}
|
|
97
110
|
|
|
98
111
|
let fieldIndex = -1;
|
|
99
|
-
let previousValue: string =
|
|
112
|
+
let previousValue: string = '';
|
|
100
113
|
for (let i = networkSectionIndex + 1; i < envLines.length; i++) {
|
|
101
114
|
const line = envLines[i].trim();
|
|
102
115
|
if (line.startsWith('[')) break; // End of the current network section
|
|
@@ -121,7 +134,7 @@ function replaceEnvField(
|
|
|
121
134
|
export async function upgradeHandler(
|
|
122
135
|
config: DubheConfig,
|
|
123
136
|
name: string,
|
|
124
|
-
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
|
|
137
|
+
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
|
|
125
138
|
) {
|
|
126
139
|
await switchEnv(network);
|
|
127
140
|
|
|
@@ -132,7 +145,7 @@ export async function upgradeHandler(
|
|
|
132
145
|
throw new DubheCliError(
|
|
133
146
|
`Missing PRIVATE_KEY environment variable.
|
|
134
147
|
Run 'echo "PRIVATE_KEY=YOUR_PRIVATE_KEY" > .env'
|
|
135
|
-
in your contracts directory to use the default sui private key
|
|
148
|
+
in your contracts directory to use the default sui private key.`
|
|
136
149
|
);
|
|
137
150
|
|
|
138
151
|
const privateKeyFormat = validatePrivateKey(privateKey);
|
|
@@ -152,24 +165,32 @@ in your contracts directory to use the default sui private key.`,
|
|
|
152
165
|
let oldPackageId = await getOldPackageId(projectPath, network);
|
|
153
166
|
let upgradeCap = await getUpgradeCap(projectPath, network);
|
|
154
167
|
|
|
155
|
-
const original_published_id =
|
|
168
|
+
const original_published_id = replaceEnvField(
|
|
169
|
+
`${projectPath}/Move.lock`,
|
|
170
|
+
network,
|
|
171
|
+
'original-published-id',
|
|
172
|
+
'0x0000000000000000000000000000000000000000000000000000000000000000'
|
|
173
|
+
);
|
|
156
174
|
|
|
157
175
|
let pendingMigration: Migration[] = [];
|
|
158
176
|
let schemas = await getOnchainSchemas(projectPath, network);
|
|
159
177
|
for (let schemaKey in config.schemas) {
|
|
160
|
-
schemas.forEach(
|
|
161
|
-
if (
|
|
178
|
+
schemas.forEach(schema => {
|
|
179
|
+
if (
|
|
180
|
+
capitalizeAndRemoveUnderscores(schemaKey) ==
|
|
181
|
+
getLastSegment(schema.name)
|
|
182
|
+
) {
|
|
162
183
|
let migrate: Migration = { schemaName: '', fields: [] };
|
|
163
184
|
let fields: Field[] = [];
|
|
164
185
|
let isMigration = false;
|
|
165
|
-
for (const key in config.schemas[schemaKey]
|
|
186
|
+
for (const key in config.schemas[schemaKey]) {
|
|
166
187
|
if (!(key in schema.structure)) {
|
|
167
188
|
isMigration = true;
|
|
168
189
|
fields.push({
|
|
169
190
|
name: key,
|
|
170
|
-
type: config.schemas[schemaKey]
|
|
191
|
+
type: config.schemas[schemaKey][key],
|
|
171
192
|
});
|
|
172
|
-
schema.structure[key] = config.schemas[schemaKey]
|
|
193
|
+
schema.structure[key] = config.schemas[schemaKey][key];
|
|
173
194
|
}
|
|
174
195
|
}
|
|
175
196
|
if (isMigration) {
|
|
@@ -181,8 +202,7 @@ in your contracts directory to use the default sui private key.`,
|
|
|
181
202
|
});
|
|
182
203
|
}
|
|
183
204
|
|
|
184
|
-
|
|
185
|
-
pendingMigration.forEach((migration) => {
|
|
205
|
+
pendingMigration.forEach(migration => {
|
|
186
206
|
console.log(`\nš Starting Migration for ${migration.schemaName}...`);
|
|
187
207
|
console.log('š Migration Fields:', migration.fields);
|
|
188
208
|
});
|
|
@@ -200,8 +220,8 @@ in your contracts directory to use the default sui private key.`,
|
|
|
200
220
|
`sui move build --dump-bytecode-as-base64 --path ${path}/contracts/${name}`,
|
|
201
221
|
{
|
|
202
222
|
encoding: 'utf-8',
|
|
203
|
-
}
|
|
204
|
-
)
|
|
223
|
+
}
|
|
224
|
+
)
|
|
205
225
|
);
|
|
206
226
|
|
|
207
227
|
modules = extractedModules;
|
|
@@ -250,21 +270,34 @@ in your contracts directory to use the default sui private key.`,
|
|
|
250
270
|
result.objectChanges!.map(object => {
|
|
251
271
|
if (object.type === 'published') {
|
|
252
272
|
console.log(
|
|
253
|
-
chalk.blue(`${name} PackageId: ${object.packageId}`)
|
|
254
|
-
);
|
|
255
|
-
console.log(
|
|
256
|
-
chalk.blue(`${name} Version: ${oldVersion + 1}`),
|
|
273
|
+
chalk.blue(`${name} PackageId: ${object.packageId}`)
|
|
257
274
|
);
|
|
275
|
+
console.log(chalk.blue(`${name} Version: ${oldVersion + 1}`));
|
|
258
276
|
newPackageId = object.packageId;
|
|
259
277
|
}
|
|
260
278
|
});
|
|
261
279
|
|
|
262
|
-
replaceEnvField(
|
|
263
|
-
|
|
264
|
-
|
|
280
|
+
replaceEnvField(
|
|
281
|
+
`${projectPath}/Move.lock`,
|
|
282
|
+
network,
|
|
283
|
+
'original-published-id',
|
|
284
|
+
original_published_id
|
|
285
|
+
);
|
|
286
|
+
replaceEnvField(
|
|
287
|
+
`${projectPath}/Move.lock`,
|
|
288
|
+
network,
|
|
289
|
+
'latest-published-id',
|
|
290
|
+
newPackageId
|
|
291
|
+
);
|
|
292
|
+
replaceEnvField(
|
|
293
|
+
`${projectPath}/Move.lock`,
|
|
294
|
+
network,
|
|
295
|
+
'published-version',
|
|
296
|
+
oldVersion + 1 + ''
|
|
297
|
+
);
|
|
265
298
|
|
|
266
299
|
console.log(
|
|
267
|
-
chalk.green(`Upgrade Transaction Digest: ${result.digest}`)
|
|
300
|
+
chalk.green(`Upgrade Transaction Digest: ${result.digest}`)
|
|
268
301
|
);
|
|
269
302
|
|
|
270
303
|
saveContractData(
|
|
@@ -273,9 +306,8 @@ in your contracts directory to use the default sui private key.`,
|
|
|
273
306
|
newPackageId,
|
|
274
307
|
upgradeCap,
|
|
275
308
|
oldVersion + 1,
|
|
276
|
-
schemas
|
|
309
|
+
schemas
|
|
277
310
|
);
|
|
278
|
-
|
|
279
311
|
} catch (error: any) {
|
|
280
312
|
console.log(chalk.red('Upgrade failed!'));
|
|
281
313
|
console.error(error.message);
|