@0xobelisk/sui-cli 0.5.29 ā 0.5.31
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 +60 -60
- package/dist/dubhe.js.map +1 -1
- package/package.json +2 -2
- package/src/commands/build.ts +56 -0
- package/src/commands/checkBalance.ts +35 -0
- package/src/commands/generateKey.ts +35 -0
- package/src/commands/index.ts +9 -1
- package/src/commands/localnode.ts +4 -38
- package/src/commands/storeConfig.ts +44 -0
- package/src/commands/test.ts +17 -7
- package/src/utils/checkBalance.ts +55 -0
- package/src/utils/errors.ts +31 -31
- package/src/utils/generateAccount.ts +100 -0
- package/src/utils/publishHandler.ts +73 -33
- package/src/utils/startNode.ts +117 -0
- package/src/utils/storeConfig.ts +79 -0
- package/src/utils/utils.ts +0 -2
- package/src/utils/localnode/index.ts +0 -3
- package/src/utils/localnode/start.ts +0 -87
- package/src/utils/localnode/status.ts +0 -38
- package/src/utils/localnode/stop.ts +0 -58
package/src/commands/index.ts
CHANGED
|
@@ -4,9 +4,13 @@ import localnode from './localnode';
|
|
|
4
4
|
import faucet from './faucet';
|
|
5
5
|
import schemagen from './schemagen';
|
|
6
6
|
import publish from './publish';
|
|
7
|
-
import upgrade from
|
|
7
|
+
import upgrade from './upgrade';
|
|
8
8
|
import test from './test';
|
|
9
|
+
import build from './build';
|
|
9
10
|
import hello from './hello';
|
|
11
|
+
import generateKey from './generateKey';
|
|
12
|
+
import checkBalance from './checkBalance';
|
|
13
|
+
import storeConfig from './storeConfig';
|
|
10
14
|
|
|
11
15
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- Each command has different options
|
|
12
16
|
export const commands: CommandModule<any, any>[] = [
|
|
@@ -16,5 +20,9 @@ export const commands: CommandModule<any, any>[] = [
|
|
|
16
20
|
schemagen,
|
|
17
21
|
upgrade,
|
|
18
22
|
test,
|
|
23
|
+
build,
|
|
19
24
|
hello,
|
|
25
|
+
generateKey,
|
|
26
|
+
checkBalance,
|
|
27
|
+
storeConfig,
|
|
20
28
|
];
|
|
@@ -1,45 +1,18 @@
|
|
|
1
1
|
import type { CommandModule } from 'yargs';
|
|
2
|
-
import {
|
|
2
|
+
import { startLocalNode } from '../utils/startNode';
|
|
3
3
|
|
|
4
4
|
const commandModule: CommandModule = {
|
|
5
|
-
command: '
|
|
5
|
+
command: 'node',
|
|
6
6
|
|
|
7
7
|
describe: 'Manage local Sui node',
|
|
8
8
|
|
|
9
9
|
builder(yargs) {
|
|
10
10
|
return yargs
|
|
11
|
-
.positional('action', {
|
|
12
|
-
describe: 'Action to perform',
|
|
13
|
-
choices: ['start', 'stop', 'status', 'restart'],
|
|
14
|
-
type: 'string',
|
|
15
|
-
demandOption: true,
|
|
16
|
-
})
|
|
17
|
-
.option('background', {
|
|
18
|
-
alias: 'b',
|
|
19
|
-
type: 'boolean',
|
|
20
|
-
description: 'Run node in background',
|
|
21
|
-
default: false,
|
|
22
|
-
});
|
|
23
11
|
},
|
|
24
12
|
|
|
25
|
-
async handler(
|
|
26
|
-
const { action, background } = argv;
|
|
27
|
-
|
|
13
|
+
async handler() {
|
|
28
14
|
try {
|
|
29
|
-
|
|
30
|
-
case 'start':
|
|
31
|
-
await startLocalnode(background as boolean);
|
|
32
|
-
break;
|
|
33
|
-
case 'stop':
|
|
34
|
-
await stopLocalnode();
|
|
35
|
-
break;
|
|
36
|
-
case 'status':
|
|
37
|
-
await checkLocalNodeStatus();
|
|
38
|
-
break;
|
|
39
|
-
case 'restart':
|
|
40
|
-
await restartNode(background as boolean);
|
|
41
|
-
break;
|
|
42
|
-
}
|
|
15
|
+
await startLocalNode();
|
|
43
16
|
} catch (error) {
|
|
44
17
|
console.error('Error executing command:', error);
|
|
45
18
|
process.exit(1);
|
|
@@ -47,11 +20,4 @@ const commandModule: CommandModule = {
|
|
|
47
20
|
},
|
|
48
21
|
};
|
|
49
22
|
|
|
50
|
-
async function restartNode(background: boolean) {
|
|
51
|
-
console.log('Restarting local Sui node...');
|
|
52
|
-
await stopLocalnode();
|
|
53
|
-
await startLocalnode(background);
|
|
54
|
-
console.log('Local node has been restarted');
|
|
55
|
-
}
|
|
56
|
-
|
|
57
23
|
export default commandModule;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { CommandModule } from 'yargs';
|
|
2
|
+
import { storeConfigHandler } from '../utils/storeConfig';
|
|
3
|
+
import { loadConfig, DubheConfig } from '@0xobelisk/sui-common';
|
|
4
|
+
|
|
5
|
+
type Options = {
|
|
6
|
+
'config-path': string;
|
|
7
|
+
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet';
|
|
8
|
+
'output-path': string;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const commandModule: CommandModule<Options, Options> = {
|
|
12
|
+
command: 'store-config',
|
|
13
|
+
|
|
14
|
+
describe: 'Store configuration for the Dubhe project',
|
|
15
|
+
|
|
16
|
+
builder: {
|
|
17
|
+
'config-path': {
|
|
18
|
+
type: 'string',
|
|
19
|
+
default: 'dubhe.config.ts',
|
|
20
|
+
desc: 'Path to the config file',
|
|
21
|
+
},
|
|
22
|
+
network: {
|
|
23
|
+
type: 'string',
|
|
24
|
+
choices: ['mainnet', 'testnet', 'devnet', 'localnet'],
|
|
25
|
+
desc: 'Network to store config for',
|
|
26
|
+
},
|
|
27
|
+
'output-path': {
|
|
28
|
+
type: 'string',
|
|
29
|
+
desc: 'Path to output the configuration',
|
|
30
|
+
},
|
|
31
|
+
},
|
|
32
|
+
async handler({ 'config-path': configPath, network, outputPath }) {
|
|
33
|
+
try {
|
|
34
|
+
const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
|
|
35
|
+
await storeConfigHandler(dubheConfig, network, outputPath);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
console.error('Error storing config:', error);
|
|
38
|
+
process.exit(1);
|
|
39
|
+
}
|
|
40
|
+
process.exit(0);
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export default commandModule;
|
package/src/commands/test.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { CommandModule } from "yargs";
|
|
2
2
|
import { execSync } from "child_process";
|
|
3
3
|
import chalk from "chalk";
|
|
4
|
+
import { DubheConfig, loadConfig } from '@0xobelisk/sui-common';
|
|
4
5
|
|
|
5
6
|
type Options = {
|
|
6
|
-
|
|
7
|
+
'config-path': string;
|
|
8
|
+
'test'?: string;
|
|
7
9
|
};
|
|
8
10
|
|
|
9
11
|
const commandModule: CommandModule<Options, Options> = {
|
|
@@ -13,20 +15,28 @@ const commandModule: CommandModule<Options, Options> = {
|
|
|
13
15
|
|
|
14
16
|
builder(yargs) {
|
|
15
17
|
return yargs.options({
|
|
16
|
-
|
|
18
|
+
'config-path': {
|
|
17
19
|
type: "string",
|
|
18
|
-
default: ".",
|
|
20
|
+
default: "dubhe.config.ts",
|
|
19
21
|
description: "Options to pass to forge test",
|
|
20
22
|
},
|
|
23
|
+
test: {
|
|
24
|
+
type: 'string',
|
|
25
|
+
desc: 'Run a specific test',
|
|
26
|
+
},
|
|
21
27
|
});
|
|
22
28
|
},
|
|
23
29
|
|
|
24
|
-
async handler({
|
|
30
|
+
async handler({ 'config-path': configPath, test }) {
|
|
25
31
|
// Start an internal anvil process if no world address is provided
|
|
26
32
|
try {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
console.log('š Running move test');
|
|
34
|
+
const dubheConfig = (await loadConfig(configPath)) as DubheConfig;
|
|
35
|
+
const path = process.cwd();
|
|
36
|
+
const projectPath = `${path}/contracts/${dubheConfig.name}`;
|
|
37
|
+
const command = `sui move test --path ${projectPath} ${test ? ` --test ${test}` : ''}`;
|
|
38
|
+
const output = execSync(command, { encoding: "utf-8" });
|
|
39
|
+
console.log(output);
|
|
30
40
|
} catch (error: any) {
|
|
31
41
|
console.error(chalk.red("Error executing sui move test:"));
|
|
32
42
|
console.log(error.stdout);
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Dubhe, NetworkType } from '@0xobelisk/sui-client';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import dotenv from 'dotenv';
|
|
4
|
+
import { validatePrivateKey } from './utils';
|
|
5
|
+
import { DubheCliError } from './errors';
|
|
6
|
+
dotenv.config();
|
|
7
|
+
|
|
8
|
+
export async function checkBalanceHandler(
|
|
9
|
+
network: 'mainnet' | 'testnet' | 'devnet' | 'loclnet',
|
|
10
|
+
amount: number = 2
|
|
11
|
+
) {
|
|
12
|
+
try {
|
|
13
|
+
console.log(
|
|
14
|
+
chalk.blue(
|
|
15
|
+
`Note: You need at least 2 SUI for transaction fees and staking, and registering a Dapp will reserve 1 SUI for Dubhe Dapp Staking, which can be retrieved upon unregistering.`
|
|
16
|
+
)
|
|
17
|
+
);
|
|
18
|
+
|
|
19
|
+
const privateKey = process.env.PRIVATE_KEY;
|
|
20
|
+
if (!privateKey) {
|
|
21
|
+
throw new DubheCliError(
|
|
22
|
+
`Missing PRIVATE_KEY environment variable.
|
|
23
|
+
Run 'echo "PRIVATE_KEY=YOUR_PRIVATE_KEY" > .env'
|
|
24
|
+
in your contracts directory to use the default sui private key.`
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
const privateKeyFormat = validatePrivateKey(privateKey);
|
|
28
|
+
if (privateKeyFormat === false) {
|
|
29
|
+
throw new DubheCliError(`Please check your privateKey.`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const dubhe = new Dubhe({
|
|
33
|
+
secretKey: process.env.PRIVATE_KEY,
|
|
34
|
+
networkType: network as NetworkType,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const balance = await dubhe.getBalance();
|
|
38
|
+
const balanceInSUI = Number(balance.totalBalance) / 1_000_000_000;
|
|
39
|
+
|
|
40
|
+
if (balanceInSUI < amount) {
|
|
41
|
+
// console.log(chalk.yellow(`Account balance is less than 2 SUI.`));
|
|
42
|
+
throw new DubheCliError(
|
|
43
|
+
`Account balance is less than ${amount} SUI. Please get more SUI.`
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
console.log(
|
|
48
|
+
chalk.green(
|
|
49
|
+
`Current account balance: ${balanceInSUI.toFixed(4)} SUI`
|
|
50
|
+
)
|
|
51
|
+
);
|
|
52
|
+
} catch (error) {
|
|
53
|
+
throw new DubheCliError('Failed to check balance: ' + error);
|
|
54
|
+
}
|
|
55
|
+
}
|
package/src/utils/errors.ts
CHANGED
|
@@ -1,46 +1,46 @@
|
|
|
1
|
-
import chalk from
|
|
2
|
-
import { ZodError } from
|
|
3
|
-
import { fromZodError, ValidationError } from
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { ZodError } from 'zod';
|
|
3
|
+
import { fromZodError, ValidationError } from 'zod-validation-error';
|
|
4
4
|
|
|
5
5
|
export class NotInsideProjectError extends Error {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
name = 'NotInsideProjectError';
|
|
7
|
+
message = 'You are not inside a Dubhe project';
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export class DubheCliError extends Error {
|
|
11
|
-
|
|
11
|
+
name = 'DubheCliError';
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export class UpgradeError extends Error {
|
|
15
|
-
|
|
15
|
+
name = 'UpgradeError';
|
|
16
16
|
}
|
|
17
17
|
|
|
18
18
|
export class FsIibError extends Error {
|
|
19
|
-
|
|
19
|
+
name = 'FsIibError';
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export function logError(error: unknown) {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
23
|
+
if (error instanceof ValidationError) {
|
|
24
|
+
console.log(chalk.redBright(error.message));
|
|
25
|
+
} else if (error instanceof ZodError) {
|
|
26
|
+
// TODO currently this error shouldn't happen, use `fromZodErrorCustom`
|
|
27
|
+
const validationError = fromZodError(error, {
|
|
28
|
+
prefixSeparator: '\n- ',
|
|
29
|
+
issueSeparator: '\n- ',
|
|
30
|
+
});
|
|
31
|
+
console.log(chalk.redBright(validationError.message));
|
|
32
|
+
} else if (error instanceof NotInsideProjectError) {
|
|
33
|
+
console.log(chalk.red(error.message));
|
|
34
|
+
console.log('');
|
|
35
|
+
// TODO add docs to the website and update the link to the specific page
|
|
36
|
+
console.log(
|
|
37
|
+
chalk.blue(
|
|
38
|
+
`To learn more about Dubhe's configuration, please go to https://github.com/0xobelisk`
|
|
39
|
+
)
|
|
40
|
+
);
|
|
41
|
+
} else if (error instanceof DubheCliError) {
|
|
42
|
+
console.log(chalk.red(error));
|
|
43
|
+
} else {
|
|
44
|
+
console.log(error);
|
|
45
|
+
}
|
|
46
46
|
}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { Dubhe } from '@0xobelisk/sui-client';
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import chalk from 'chalk';
|
|
4
|
+
|
|
5
|
+
export async function generateAccountHandler(
|
|
6
|
+
force: boolean = false,
|
|
7
|
+
outputTsPath: string
|
|
8
|
+
) {
|
|
9
|
+
const path = process.cwd();
|
|
10
|
+
let privateKey: string;
|
|
11
|
+
|
|
12
|
+
if (force) {
|
|
13
|
+
const dubhe = new Dubhe();
|
|
14
|
+
const keypair = dubhe.getKeypair();
|
|
15
|
+
privateKey = keypair.getSecretKey();
|
|
16
|
+
|
|
17
|
+
fs.writeFileSync(`${path}/.env`, `PRIVATE_KEY=${privateKey}`);
|
|
18
|
+
console.log(chalk.green(`File created at: ${path}/.env`));
|
|
19
|
+
|
|
20
|
+
if (outputTsPath) {
|
|
21
|
+
const dir = outputTsPath.substring(
|
|
22
|
+
0,
|
|
23
|
+
outputTsPath.lastIndexOf('/')
|
|
24
|
+
);
|
|
25
|
+
if (!fs.existsSync(dir)) {
|
|
26
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
27
|
+
}
|
|
28
|
+
fs.writeFileSync(
|
|
29
|
+
outputTsPath,
|
|
30
|
+
`export const PRIVATEKEY = '${privateKey}';
|
|
31
|
+
export const ACCOUNT = '${keypair.toSuiAddress()}';
|
|
32
|
+
`
|
|
33
|
+
);
|
|
34
|
+
console.log(chalk.green(`File created at: ${outputTsPath}`));
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.log(
|
|
38
|
+
chalk.blue(`Force generate new Account: ${keypair.toSuiAddress()}`)
|
|
39
|
+
);
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Check if .env file exists and has content
|
|
44
|
+
try {
|
|
45
|
+
const envContent = fs.readFileSync(`${path}/.env`, 'utf8');
|
|
46
|
+
const match = envContent.match(/PRIVATE_KEY=(.+)/);
|
|
47
|
+
if (match && match[1]) {
|
|
48
|
+
privateKey = match[1];
|
|
49
|
+
const dubhe = new Dubhe({ secretKey: privateKey });
|
|
50
|
+
const keypair = dubhe.getKeypair();
|
|
51
|
+
|
|
52
|
+
if (outputTsPath) {
|
|
53
|
+
const dir = outputTsPath.substring(
|
|
54
|
+
0,
|
|
55
|
+
outputTsPath.lastIndexOf('/')
|
|
56
|
+
);
|
|
57
|
+
if (!fs.existsSync(dir)) {
|
|
58
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
59
|
+
}
|
|
60
|
+
fs.writeFileSync(
|
|
61
|
+
outputTsPath,
|
|
62
|
+
`export const PRIVATEKEY = '${privateKey}';
|
|
63
|
+
export const ACCOUNT = '${keypair.toSuiAddress()}';
|
|
64
|
+
`
|
|
65
|
+
);
|
|
66
|
+
console.log(chalk.green(`File created at: ${outputTsPath}`));
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
console.log(
|
|
70
|
+
chalk.blue(`Using existing Account: ${keypair.toSuiAddress()}`)
|
|
71
|
+
);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
// .env file doesn't exist or failed to read, continue to generate new account
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// If no existing private key, generate new account
|
|
79
|
+
const dubhe = new Dubhe();
|
|
80
|
+
const keypair = dubhe.getKeypair();
|
|
81
|
+
privateKey = keypair.getSecretKey();
|
|
82
|
+
fs.writeFileSync(`${path}/.env`, `PRIVATE_KEY=${privateKey}`);
|
|
83
|
+
console.log(chalk.green(`File created at: ${path}/.env`));
|
|
84
|
+
|
|
85
|
+
if (outputTsPath) {
|
|
86
|
+
const dir = outputTsPath.substring(0, outputTsPath.lastIndexOf('/'));
|
|
87
|
+
if (!fs.existsSync(dir)) {
|
|
88
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
89
|
+
}
|
|
90
|
+
fs.writeFileSync(
|
|
91
|
+
outputTsPath,
|
|
92
|
+
`export const PRIVATEKEY = '${privateKey}';
|
|
93
|
+
export const ACCOUNT = '${keypair.toSuiAddress()}';
|
|
94
|
+
`
|
|
95
|
+
);
|
|
96
|
+
console.log(chalk.green(`File created at: ${outputTsPath}`));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
console.log(chalk.blue(`Generate new Account: ${keypair.toSuiAddress()}`));
|
|
100
|
+
}
|
|
@@ -12,7 +12,11 @@ import {
|
|
|
12
12
|
updateVersionInFile,
|
|
13
13
|
saveContractData,
|
|
14
14
|
validatePrivateKey,
|
|
15
|
-
schema,
|
|
15
|
+
schema,
|
|
16
|
+
getSchemaHub,
|
|
17
|
+
updateDubheDependency,
|
|
18
|
+
switchEnv,
|
|
19
|
+
delay,
|
|
16
20
|
} from './utils';
|
|
17
21
|
import { DubheConfig } from '@0xobelisk/sui-common';
|
|
18
22
|
import * as fs from 'fs';
|
|
@@ -22,9 +26,12 @@ async function getDappsObjectId(
|
|
|
22
26
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
|
|
23
27
|
) {
|
|
24
28
|
switch (network) {
|
|
25
|
-
case
|
|
29
|
+
case 'localnet': {
|
|
26
30
|
const path = process.cwd();
|
|
27
|
-
return await getSchemaHub(
|
|
31
|
+
return await getSchemaHub(
|
|
32
|
+
`${path}/contracts/dubhe-framework`,
|
|
33
|
+
network
|
|
34
|
+
);
|
|
28
35
|
}
|
|
29
36
|
case 'testnet':
|
|
30
37
|
return '0x8dbf8d28ac027ba214c9e0951b09f6842843be6cb87242b7d9a326a2677cd47a';
|
|
@@ -33,12 +40,18 @@ async function getDappsObjectId(
|
|
|
33
40
|
}
|
|
34
41
|
}
|
|
35
42
|
|
|
36
|
-
function removeEnvContent(
|
|
43
|
+
function removeEnvContent(
|
|
44
|
+
filePath: string,
|
|
45
|
+
networkType: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
|
|
46
|
+
): void {
|
|
37
47
|
if (!fs.existsSync(filePath)) {
|
|
38
48
|
return;
|
|
39
49
|
}
|
|
40
50
|
const content = fs.readFileSync(filePath, 'utf-8');
|
|
41
|
-
const regex = new RegExp(
|
|
51
|
+
const regex = new RegExp(
|
|
52
|
+
`\\[env\\.${networkType}\\][\\s\\S]*?(?=\\[|$)`,
|
|
53
|
+
'g'
|
|
54
|
+
);
|
|
42
55
|
const updatedContent = content.replace(regex, '');
|
|
43
56
|
fs.writeFileSync(filePath, updatedContent, 'utf-8');
|
|
44
57
|
}
|
|
@@ -56,12 +69,20 @@ const chainIds: { [key: string]: string } = {
|
|
|
56
69
|
mainnet: '35834a8a',
|
|
57
70
|
};
|
|
58
71
|
|
|
59
|
-
function updateEnvFile(
|
|
72
|
+
function updateEnvFile(
|
|
73
|
+
filePath: string,
|
|
74
|
+
networkType: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
75
|
+
operation: 'publish' | 'upgrade',
|
|
76
|
+
chainId: string,
|
|
77
|
+
publishedId: string
|
|
78
|
+
): void {
|
|
60
79
|
const envFilePath = path.resolve(filePath);
|
|
61
80
|
const envContent = fs.readFileSync(envFilePath, 'utf-8');
|
|
62
81
|
const envLines = envContent.split('\n');
|
|
63
82
|
|
|
64
|
-
const networkSectionIndex = envLines.findIndex(
|
|
83
|
+
const networkSectionIndex = envLines.findIndex(
|
|
84
|
+
line => line.trim() === `[env.${networkType}]`
|
|
85
|
+
);
|
|
65
86
|
const config: EnvConfig = {
|
|
66
87
|
chainId: chainId,
|
|
67
88
|
originalPublishedId: '',
|
|
@@ -76,14 +97,18 @@ function updateEnvFile(filePath: string, networkType: 'mainnet' | 'testnet' | 'd
|
|
|
76
97
|
config.latestPublishedId = publishedId;
|
|
77
98
|
config.publishedVersion = 1;
|
|
78
99
|
} else {
|
|
79
|
-
throw new Error(
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Network type [env.${networkType}] not found in the file and cannot upgrade.`
|
|
102
|
+
);
|
|
80
103
|
}
|
|
81
104
|
} else {
|
|
82
105
|
for (let i = networkSectionIndex + 1; i < envLines.length; i++) {
|
|
83
106
|
const line = envLines[i].trim();
|
|
84
107
|
if (line.startsWith('[')) break; // End of the current network section
|
|
85
108
|
|
|
86
|
-
const [key, value] = line
|
|
109
|
+
const [key, value] = line
|
|
110
|
+
.split('=')
|
|
111
|
+
.map(part => part.trim().replace(/"/g, ''));
|
|
87
112
|
switch (key) {
|
|
88
113
|
case 'original-published-id':
|
|
89
114
|
config.originalPublishedId = value;
|
|
@@ -115,9 +140,11 @@ latest-published-id = "${config.latestPublishedId}"
|
|
|
115
140
|
published-version = "${config.publishedVersion}"
|
|
116
141
|
`;
|
|
117
142
|
|
|
118
|
-
const newEnvContent =
|
|
119
|
-
|
|
120
|
-
|
|
143
|
+
const newEnvContent =
|
|
144
|
+
networkSectionIndex === -1
|
|
145
|
+
? envContent + updatedSection
|
|
146
|
+
: envLines.slice(0, networkSectionIndex).join('\n') +
|
|
147
|
+
updatedSection;
|
|
121
148
|
|
|
122
149
|
fs.writeFileSync(envFilePath, newEnvContent, 'utf-8');
|
|
123
150
|
}
|
|
@@ -137,7 +164,7 @@ function getLastSegment(input: string): string {
|
|
|
137
164
|
return segments.length > 0 ? segments[segments.length - 1] : '';
|
|
138
165
|
}
|
|
139
166
|
|
|
140
|
-
function buildContract(projectPath: string):
|
|
167
|
+
function buildContract(projectPath: string): string[][] {
|
|
141
168
|
let modules: any, dependencies: any;
|
|
142
169
|
try {
|
|
143
170
|
const buildResult = JSON.parse(
|
|
@@ -145,6 +172,7 @@ function buildContract(projectPath: string): string[][] {
|
|
|
145
172
|
`sui move build --dump-bytecode-as-base64 --path ${projectPath}`,
|
|
146
173
|
{
|
|
147
174
|
encoding: 'utf-8',
|
|
175
|
+
stdio: 'pipe',
|
|
148
176
|
}
|
|
149
177
|
)
|
|
150
178
|
);
|
|
@@ -167,7 +195,7 @@ async function publishContract(
|
|
|
167
195
|
projectPath: string
|
|
168
196
|
) {
|
|
169
197
|
const dappsObjectId = await getDappsObjectId(network);
|
|
170
|
-
console.log(
|
|
198
|
+
console.log('dappsObjectId', dappsObjectId);
|
|
171
199
|
const chainId = await client.getChainIdentifier();
|
|
172
200
|
removeEnvContent(`${projectPath}/Move.lock`, network);
|
|
173
201
|
console.log('\nš Starting Contract Publication...');
|
|
@@ -226,7 +254,7 @@ async function publishContract(
|
|
|
226
254
|
}
|
|
227
255
|
if (
|
|
228
256
|
object.type === 'created' &&
|
|
229
|
-
object.objectType.includes(
|
|
257
|
+
object.objectType.includes('schema_hub')
|
|
230
258
|
) {
|
|
231
259
|
console.log(` āā Schema Hub: ${object.objectId}`);
|
|
232
260
|
schemaHubId = object.objectId;
|
|
@@ -235,14 +263,20 @@ async function publishContract(
|
|
|
235
263
|
|
|
236
264
|
console.log(` āā Transaction: ${result.digest}`);
|
|
237
265
|
|
|
238
|
-
updateEnvFile(
|
|
266
|
+
updateEnvFile(
|
|
267
|
+
`${projectPath}/Move.lock`,
|
|
268
|
+
network,
|
|
269
|
+
'publish',
|
|
270
|
+
chainId,
|
|
271
|
+
packageId
|
|
272
|
+
);
|
|
239
273
|
|
|
240
274
|
console.log('\nā” Executing Deploy Hook...');
|
|
241
275
|
await delay(5000);
|
|
242
276
|
|
|
243
277
|
const deployHookTx = new Transaction();
|
|
244
278
|
deployHookTx.setGasBudget(2000000000);
|
|
245
|
-
const [txCoin] = deployHookTx.splitCoins(deployHookTx.gas, [
|
|
279
|
+
const [txCoin] = deployHookTx.splitCoins(deployHookTx.gas, ['1000000000']);
|
|
246
280
|
deployHookTx.moveCall({
|
|
247
281
|
target: `${packageId}::deploy_hook::run`,
|
|
248
282
|
arguments: [
|
|
@@ -250,7 +284,7 @@ async function publishContract(
|
|
|
250
284
|
deployHookTx.object(dappsObjectId),
|
|
251
285
|
deployHookTx.object(upgradeCapId),
|
|
252
286
|
deployHookTx.object('0x6'),
|
|
253
|
-
txCoin
|
|
287
|
+
txCoin,
|
|
254
288
|
],
|
|
255
289
|
});
|
|
256
290
|
|
|
@@ -275,14 +309,18 @@ async function publishContract(
|
|
|
275
309
|
deployHookResult.objectChanges?.map(object => {
|
|
276
310
|
if (
|
|
277
311
|
object.type === 'created' &&
|
|
278
|
-
object.objectType.includes('_schema') &&
|
|
312
|
+
object.objectType.includes('_schema') &&
|
|
313
|
+
!object.objectType.includes('dynamic_field')
|
|
279
314
|
) {
|
|
280
315
|
console.log(` āā ${object.objectType}`);
|
|
281
316
|
console.log(` āā ID: ${object.objectId}`);
|
|
282
317
|
|
|
283
318
|
let structure: Record<string, string> = {};
|
|
284
319
|
for (let schemaKey in dubheConfig.schemas) {
|
|
285
|
-
if (
|
|
320
|
+
if (
|
|
321
|
+
capitalizeAndRemoveUnderscores(schemaKey) ===
|
|
322
|
+
getLastSegment(object.objectType)
|
|
323
|
+
) {
|
|
286
324
|
structure = dubheConfig.schemas[schemaKey].structure;
|
|
287
325
|
}
|
|
288
326
|
}
|
|
@@ -302,7 +340,7 @@ async function publishContract(
|
|
|
302
340
|
upgradeCapId,
|
|
303
341
|
schemaHubId,
|
|
304
342
|
version,
|
|
305
|
-
schemas
|
|
343
|
+
schemas
|
|
306
344
|
);
|
|
307
345
|
console.log('\nā
Contract Publication Complete\n');
|
|
308
346
|
} else {
|
|
@@ -315,10 +353,10 @@ async function publishContract(
|
|
|
315
353
|
}
|
|
316
354
|
}
|
|
317
355
|
|
|
318
|
-
async function publishDubheFramework(
|
|
356
|
+
export async function publishDubheFramework(
|
|
319
357
|
client: SuiClient,
|
|
320
358
|
dubhe: Dubhe,
|
|
321
|
-
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
|
|
359
|
+
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet'
|
|
322
360
|
) {
|
|
323
361
|
const path = process.cwd();
|
|
324
362
|
const projectPath = `${path}/contracts/dubhe-framework`;
|
|
@@ -334,7 +372,6 @@ async function publishDubheFramework(
|
|
|
334
372
|
const keypair = dubhe.getKeypair();
|
|
335
373
|
console.log(` āā Account: ${keypair.toSuiAddress()}`);
|
|
336
374
|
|
|
337
|
-
|
|
338
375
|
console.log('\nš¦ Building Contract...');
|
|
339
376
|
const [modules, dependencies] = buildContract(projectPath);
|
|
340
377
|
|
|
@@ -380,10 +417,7 @@ async function publishDubheFramework(
|
|
|
380
417
|
console.log(` āā Upgrade Cap: ${object.objectId}`);
|
|
381
418
|
upgradeCapId = object.objectId;
|
|
382
419
|
}
|
|
383
|
-
if (
|
|
384
|
-
object.type === 'created' &&
|
|
385
|
-
object.objectType.includes("dapps")
|
|
386
|
-
) {
|
|
420
|
+
if (object.type === 'created' && object.objectType.includes('dapps')) {
|
|
387
421
|
console.log(` āā Dapps: ${object.objectId}`);
|
|
388
422
|
schemaHubId = object.objectId;
|
|
389
423
|
}
|
|
@@ -391,23 +425,29 @@ async function publishDubheFramework(
|
|
|
391
425
|
|
|
392
426
|
console.log(` āā Transaction: ${result.digest}`);
|
|
393
427
|
|
|
394
|
-
updateEnvFile(
|
|
428
|
+
updateEnvFile(
|
|
429
|
+
`${projectPath}/Move.lock`,
|
|
430
|
+
network,
|
|
431
|
+
'publish',
|
|
432
|
+
chainId,
|
|
433
|
+
packageId
|
|
434
|
+
);
|
|
395
435
|
|
|
396
436
|
saveContractData(
|
|
397
|
-
|
|
437
|
+
'dubhe-framework',
|
|
398
438
|
network,
|
|
399
439
|
packageId,
|
|
400
440
|
upgradeCapId,
|
|
401
441
|
schemaHubId,
|
|
402
442
|
version,
|
|
403
|
-
schemas
|
|
443
|
+
schemas
|
|
404
444
|
);
|
|
405
445
|
}
|
|
406
446
|
|
|
407
447
|
export async function publishHandler(
|
|
408
448
|
dubheConfig: DubheConfig,
|
|
409
449
|
network: 'mainnet' | 'testnet' | 'devnet' | 'localnet',
|
|
410
|
-
contractName?: string
|
|
450
|
+
contractName?: string
|
|
411
451
|
) {
|
|
412
452
|
await switchEnv(network);
|
|
413
453
|
|
|
@@ -427,7 +467,7 @@ in your contracts directory to use the default sui private key.`
|
|
|
427
467
|
const dubhe = new Dubhe({ secretKey: privateKeyFormat });
|
|
428
468
|
const client = new SuiClient({ url: getFullnodeUrl(network) });
|
|
429
469
|
|
|
430
|
-
if (contractName ==
|
|
470
|
+
if (contractName == 'dubhe-framework') {
|
|
431
471
|
await publishDubheFramework(client, dubhe, network);
|
|
432
472
|
} else {
|
|
433
473
|
const path = process.cwd();
|