soluser 1.0.1 → 1.0.3
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/README.md +10 -10
- package/bin/index.js +12 -9
- package/package.json +1 -1
- package/src/commands/new.js +29 -11
- package/src/commands/remove.js +2 -2
- package/src/commands/switch.js +2 -2
- package/src/develop.md +6 -0
- package/src/utils/path.js +12 -2
- package/src/utils/solana.js +2 -2
- package/src/utils/throw_error.js +12 -0
package/README.md
CHANGED
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
# soluser
|
|
2
|
-
|
|
2
|
+
## 安装
|
|
3
3
|
```shell
|
|
4
|
+
npm install -g soluser@latest
|
|
5
|
+
```
|
|
6
|
+
## 新建账号
|
|
7
|
+
```shell
|
|
8
|
+
$ soluser new charlie
|
|
4
9
|
$ soluser new alice --word-length 12
|
|
5
10
|
$ soluser new bob --word-length 24 --no-bip39-passphrase
|
|
6
|
-
$ soluser new charlie
|
|
7
11
|
```
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
## 切换账号
|
|
10
14
|
```shell
|
|
11
|
-
$ soluser switch
|
|
15
|
+
$ soluser switch bob
|
|
12
16
|
```
|
|
13
17
|
|
|
14
|
-
|
|
18
|
+
## 列出账号
|
|
15
19
|
```shell
|
|
16
20
|
$ soluser list
|
|
17
21
|
```
|
|
18
22
|
|
|
19
|
-
|
|
23
|
+
## 删除账号
|
|
20
24
|
```shell
|
|
21
25
|
$ soluser remove alice
|
|
22
26
|
```
|
|
23
27
|
|
|
24
|
-
# 本地安装
|
|
25
|
-
```shell
|
|
26
|
-
npm link
|
|
27
|
-
```
|
package/bin/index.js
CHANGED
|
@@ -14,27 +14,30 @@ program
|
|
|
14
14
|
.description('Create a new Solana account')
|
|
15
15
|
.argument('<alias>', 'Alias for the new account (must start with a letter, contain letters, digits, hyphens, or underscores)') // 新增位置参数
|
|
16
16
|
.option('--word-length <number>', 'Number of words in seed phrase (12,15,18,21,24)', 12)
|
|
17
|
-
.option('--
|
|
17
|
+
.option('--without-passphrase', 'Do not prompt for BIP39 passphrase',false)
|
|
18
18
|
.action((alias, options) => { // 第一个参数为位置参数 alias,第二个为选项
|
|
19
|
+
// // 打印选项值验证(调试用)
|
|
20
|
+
// console.log('without-passphrase:', options.withoutPassphrase);
|
|
21
|
+
// console.log("type noPassphrase:", typeof(options.withoutPassphrase), "value:", options.withoutPassphrase)
|
|
22
|
+
|
|
19
23
|
newAccount(
|
|
20
24
|
alias, // 直接使用位置参数的 alias
|
|
21
25
|
parseInt(options.wordLength, 10), //10进制解析
|
|
22
|
-
options.
|
|
26
|
+
options.withoutPassphrase
|
|
23
27
|
);
|
|
24
28
|
});
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
|
|
31
|
+
// 定义切换账号命令(修改后)
|
|
27
32
|
program
|
|
28
33
|
.command('switch')
|
|
29
34
|
.description('Switch active Solana account')
|
|
30
|
-
.
|
|
31
|
-
.action((
|
|
32
|
-
|
|
33
|
-
throw new Error('Alias is required (use --address <alias>)');
|
|
34
|
-
}
|
|
35
|
-
switchAccount(options.address);
|
|
35
|
+
.argument('<alias>', 'Alias of the account to switch to') // 新增位置参数
|
|
36
|
+
.action((alias) => { // 直接使用位置参数 alias
|
|
37
|
+
switchAccount(alias);
|
|
36
38
|
});
|
|
37
39
|
|
|
40
|
+
|
|
38
41
|
// 定义列出账号命令
|
|
39
42
|
program
|
|
40
43
|
.command('list')
|
package/package.json
CHANGED
package/src/commands/new.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
|
-
const { KEYS_DIR, validateAlias, getKeyFilePath } = require('../utils/path');
|
|
2
|
+
const { KEYS_DIR, validateAlias, getKeyFilePath ,existsAccount} = require('../utils/path');
|
|
3
3
|
const { execCommand } = require('../utils/solana');
|
|
4
|
+
const ThrowErorr = require('../utils/throw_error');
|
|
4
5
|
|
|
5
6
|
function newAccount(alias, wordLength = 12, noPassphrase = false) {
|
|
6
7
|
// 1. 确保密钥目录存在
|
|
@@ -10,21 +11,38 @@ function newAccount(alias, wordLength = 12, noPassphrase = false) {
|
|
|
10
11
|
|
|
11
12
|
// 2. 验证参数
|
|
12
13
|
validateAlias(alias);
|
|
14
|
+
|
|
15
|
+
// 3. 新增:检查账号是否已存在
|
|
16
|
+
if (existsAccount(alias)) {
|
|
17
|
+
console.error(`Error: Account "${alias}" already exists.`);
|
|
18
|
+
console.error(` Use "soluser list" to view existing accounts, or choose a different alias.`);
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
// 4. 验证助记词长度(已有逻辑)
|
|
13
24
|
const validWordLengths = [12, 15, 18, 21, 24];
|
|
14
25
|
if (!validWordLengths.includes(wordLength)) {
|
|
15
|
-
|
|
26
|
+
ThrowErorr(`Word length must be one of: ${validWordLengths.join(', ')}`);
|
|
16
27
|
}
|
|
17
28
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
let command = `solana-keygen new --word-count ${wordLength} --outfile ${keyPath}`;
|
|
21
|
-
if (noPassphrase) {
|
|
22
|
-
command += ' --no-bip39-passphrase';
|
|
23
|
-
}
|
|
29
|
+
|
|
30
|
+
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
32
|
+
// 5. 生成密钥对(已有逻辑)
|
|
33
|
+
try {
|
|
34
|
+
let command = `solana-keygen new --word-count ${wordLength} --outfile ${getKeyFilePath(alias)}`;
|
|
35
|
+
|
|
36
|
+
if (noPassphrase) {
|
|
37
|
+
command += ' --no-bip39-passphrase';
|
|
38
|
+
}
|
|
39
|
+
console.log(`Generating key pair for ${alias}...`);
|
|
40
|
+
execCommand(command);
|
|
41
|
+
console.log(`Successfully created account: ${alias} (saved to ${getKeyFilePath(alias)})`);
|
|
42
|
+
} catch (err) {
|
|
43
|
+
console.error(`Error: Failed to generate key pair: ${err.message}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
}
|
|
28
46
|
}
|
|
29
47
|
|
|
30
48
|
module.exports = newAccount;
|
package/src/commands/remove.js
CHANGED
|
@@ -2,7 +2,7 @@ const fs = require('fs');
|
|
|
2
2
|
const { validateAlias, getKeyFilePath } = require('../utils/path');
|
|
3
3
|
const { getActiveKeyPath } = require('../utils/solana');
|
|
4
4
|
const path = require('path');
|
|
5
|
-
|
|
5
|
+
const ThrowErorr = require('../utils/throw_error');
|
|
6
6
|
function removeAccount(alias) {
|
|
7
7
|
// 1. 验证别名格式
|
|
8
8
|
validateAlias(alias);
|
|
@@ -10,7 +10,7 @@ function removeAccount(alias) {
|
|
|
10
10
|
// 2. 检查密钥文件是否存在
|
|
11
11
|
const keyPath = getKeyFilePath(alias);
|
|
12
12
|
if (!fs.existsSync(keyPath)) {
|
|
13
|
-
|
|
13
|
+
ThrowErorr(`Account "${alias}" not found. Use "soluser list" to check existing accounts.`);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
// 3. 检查是否为当前活跃账号
|
package/src/commands/switch.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const { getKeyFilePath } = require('../utils/path');
|
|
3
3
|
const { execCommand } = require('../utils/solana');
|
|
4
|
-
|
|
4
|
+
const ThrowErorr = require('../utils/throw_error');
|
|
5
5
|
function switchAccount(alias) {
|
|
6
6
|
const keyPath = getKeyFilePath(alias);
|
|
7
7
|
|
|
8
8
|
// 验证密钥文件是否存在
|
|
9
9
|
if (!fs.existsSync(keyPath)) {
|
|
10
|
-
|
|
10
|
+
ThrowErorr(`Account ${alias} not found. Check alias or create it with "soluser new".`);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
// 执行切换(调用 solana config set)
|
package/src/develop.md
ADDED
package/src/utils/path.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const path = require('path');
|
|
2
2
|
const os = require('os');
|
|
3
|
-
|
|
3
|
+
const ThrowErorr = require('../utils/throw_error');
|
|
4
4
|
// 密钥存储目录:~/.config/solana/keys
|
|
5
5
|
const KEYS_DIR = path.join(os.homedir(), '.config', 'solana', 'keys');
|
|
6
6
|
|
|
@@ -8,7 +8,7 @@ const KEYS_DIR = path.join(os.homedir(), '.config', 'solana', 'keys');
|
|
|
8
8
|
function validateAlias(alias) {
|
|
9
9
|
const regex = /^[a-zA-Z][a-zA-Z0-9_-]*$/;
|
|
10
10
|
if (!regex.test(alias)) {
|
|
11
|
-
|
|
11
|
+
ThrowErorr('Alias must start with a letter and contain only letters, digits, hyphens, or underscores');
|
|
12
12
|
}
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -17,9 +17,19 @@ function getKeyFilePath(alias) {
|
|
|
17
17
|
return path.join(KEYS_DIR, `${alias}.json`);
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
// 检查账号是否存在(即密钥文件是否存在)
|
|
21
|
+
function existsAccount(alias) {
|
|
22
|
+
const keyPath = getKeyFilePath(alias);
|
|
23
|
+
return fs.existsSync(keyPath); // 返回布尔值:true=存在,false=不存在
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// 记得在顶部导入 fs
|
|
27
|
+
const fs = require('fs');
|
|
28
|
+
|
|
20
29
|
module.exports = {
|
|
21
30
|
KEYS_DIR,
|
|
22
31
|
validateAlias,
|
|
23
32
|
getKeyFilePath,
|
|
33
|
+
existsAccount,
|
|
24
34
|
};
|
|
25
35
|
|
package/src/utils/solana.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
const { execSync } = require('child_process');
|
|
2
2
|
const { getKeyFilePath } = require('./path');
|
|
3
|
-
|
|
3
|
+
const ThrowErorr = require('../utils/throw_error');
|
|
4
4
|
// 执行 shell 命令并返回输出
|
|
5
5
|
function execCommand(command) {
|
|
6
6
|
try {
|
|
7
7
|
return execSync(command, { encoding: 'utf8' }).trim();
|
|
8
8
|
} catch (error) {
|
|
9
|
-
|
|
9
|
+
ThrowErorr(`Command failed: ${command}\n${error.stderr}`);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
12
12
|
|