@vultisig/cli 0.2.0 → 0.3.0
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/CHANGELOG.md +49 -0
- package/dist/index.js +122 -21
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# @vultisig/cli
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#71](https://github.com/vultisig/vultisig-sdk/pull/71) [`cc4e5fd`](https://github.com/vultisig/vultisig-sdk/commit/cc4e5fd2ff83bcce1723435107af869a43ea069f) Thanks [@bornslippynuxx](https://github.com/bornslippynuxx)! - Update CLI to support SDK vault creation API changes
|
|
8
|
+
|
|
9
|
+
**Breaking Changes:**
|
|
10
|
+
- Renamed `import-seedphrase` command to `create-from-seedphrase` to match SDK naming
|
|
11
|
+
- `vultisig import-seedphrase fast` → `vultisig create-from-seedphrase fast`
|
|
12
|
+
- `vultisig import-seedphrase secure` → `vultisig create-from-seedphrase secure`
|
|
13
|
+
|
|
14
|
+
**New Features:**
|
|
15
|
+
- Added `join secure` command to join existing SecureVault creation sessions
|
|
16
|
+
- Supports QR payload via `--qr`, `--qr-file`, or interactive prompt
|
|
17
|
+
- Auto-detects if mnemonic is required based on session type
|
|
18
|
+
- Example: `vultisig join secure --qr "vultisig://..."`
|
|
19
|
+
|
|
20
|
+
**Internal Changes:**
|
|
21
|
+
- Updated SDK API calls to use new method names:
|
|
22
|
+
- `importSeedphraseAsFastVault` → `createFastVaultFromSeedphrase`
|
|
23
|
+
- `importSeedphraseAsSecureVault` → `createSecureVaultFromSeedphrase`
|
|
24
|
+
- Renamed internal functions and types to match SDK naming conventions
|
|
25
|
+
|
|
26
|
+
### Patch Changes
|
|
27
|
+
|
|
28
|
+
- [#71](https://github.com/vultisig/vultisig-sdk/pull/71) [`fee3f37`](https://github.com/vultisig/vultisig-sdk/commit/fee3f375f85011d14be814f06ff3d7f6684ea2fe) Thanks [@bornslippynuxx](https://github.com/bornslippynuxx)! - fix: address CodeRabbit PR #71 review suggestions
|
|
29
|
+
|
|
30
|
+
**Critical fixes:**
|
|
31
|
+
- JoinSecureVaultService: require `devices` parameter instead of defaulting to 2
|
|
32
|
+
- CLI vault-management: validate `devices` parameter before calling SDK
|
|
33
|
+
- parseKeygenQR: throw error on unknown libType instead of silently defaulting
|
|
34
|
+
|
|
35
|
+
**Code quality:**
|
|
36
|
+
- Replace try-catch with attempt() pattern in JoinSecureVaultService and parseKeygenQR
|
|
37
|
+
- Add abort signal checks in SecureVaultJoiner callbacks
|
|
38
|
+
|
|
39
|
+
**Documentation:**
|
|
40
|
+
- Add onProgress callback to joinSecureVault README documentation
|
|
41
|
+
- Fix markdown heading format in SDK-USERS-GUIDE.md
|
|
42
|
+
- Add language specifier to code block in CLAUDE.md
|
|
43
|
+
|
|
44
|
+
**Tests:**
|
|
45
|
+
- Fix Korean test mnemonic (removed invalid comma)
|
|
46
|
+
- Add Korean language detection test
|
|
47
|
+
- Remove sensitive private key logging in test helpers
|
|
48
|
+
|
|
49
|
+
- Updated dependencies [[`fee3f37`](https://github.com/vultisig/vultisig-sdk/commit/fee3f375f85011d14be814f06ff3d7f6684ea2fe), [`695e664`](https://github.com/vultisig/vultisig-sdk/commit/695e664668082ca55861cf4d8fcc8c323be94c06), [`4edf52d`](https://github.com/vultisig/vultisig-sdk/commit/4edf52d3a2985d2adf772239bf19b8301f360af8), [`d145809`](https://github.com/vultisig/vultisig-sdk/commit/d145809eb68653a3b22921fcb90ebc985de2b16a)]:
|
|
50
|
+
- @vultisig/sdk@0.3.0
|
|
51
|
+
|
|
3
52
|
## 0.2.0
|
|
4
53
|
|
|
5
54
|
### Minor Changes
|
package/dist/index.js
CHANGED
|
@@ -1103,9 +1103,10 @@ var require_main = __commonJS({
|
|
|
1103
1103
|
|
|
1104
1104
|
// src/index.ts
|
|
1105
1105
|
import "dotenv/config";
|
|
1106
|
-
import { Vultisig as Vultisig4 } from "@vultisig/sdk";
|
|
1106
|
+
import { parseKeygenQR, Vultisig as Vultisig4 } from "@vultisig/sdk";
|
|
1107
1107
|
import chalk12 from "chalk";
|
|
1108
1108
|
import { program } from "commander";
|
|
1109
|
+
import { promises as fs3 } from "fs";
|
|
1109
1110
|
import inquirer8 from "inquirer";
|
|
1110
1111
|
|
|
1111
1112
|
// src/core/command-context.ts
|
|
@@ -2506,7 +2507,7 @@ async function executeInfo(ctx2) {
|
|
|
2506
2507
|
}
|
|
2507
2508
|
displayVaultInfo(vault);
|
|
2508
2509
|
}
|
|
2509
|
-
async function
|
|
2510
|
+
async function executeCreateFromSeedphraseFast(ctx2, options) {
|
|
2510
2511
|
const { mnemonic, name, password, email, discoverChains, chains, signal } = options;
|
|
2511
2512
|
const validateSpinner = createSpinner("Validating seedphrase...");
|
|
2512
2513
|
const validation = await ctx2.sdk.validateSeedphrase(mnemonic);
|
|
@@ -2539,7 +2540,7 @@ async function executeImportSeedphraseFast(ctx2, options) {
|
|
|
2539
2540
|
}
|
|
2540
2541
|
const importSpinner = createSpinner("Importing seedphrase...");
|
|
2541
2542
|
const vaultId = await withAbortSignal(
|
|
2542
|
-
ctx2.sdk.
|
|
2543
|
+
ctx2.sdk.createFastVaultFromSeedphrase({
|
|
2543
2544
|
mnemonic,
|
|
2544
2545
|
name,
|
|
2545
2546
|
password,
|
|
@@ -2573,7 +2574,7 @@ async function executeImportSeedphraseFast(ctx2, options) {
|
|
|
2573
2574
|
verifySpinner.succeed("Email verified successfully!");
|
|
2574
2575
|
setupVaultEvents(vault);
|
|
2575
2576
|
await ctx2.setActiveVault(vault);
|
|
2576
|
-
success("\n+ Vault
|
|
2577
|
+
success("\n+ Vault created from seedphrase!");
|
|
2577
2578
|
info("\nYour vault is ready. Run the following commands:");
|
|
2578
2579
|
printResult(chalk5.cyan(" vultisig balance ") + "- View balances");
|
|
2579
2580
|
printResult(chalk5.cyan(" vultisig addresses ") + "- View addresses");
|
|
@@ -2623,7 +2624,7 @@ async function executeImportSeedphraseFast(ctx2, options) {
|
|
|
2623
2624
|
}
|
|
2624
2625
|
throw new Error("Verification loop exited unexpectedly");
|
|
2625
2626
|
}
|
|
2626
|
-
async function
|
|
2627
|
+
async function executeCreateFromSeedphraseSecure(ctx2, options) {
|
|
2627
2628
|
const { mnemonic, name, password, threshold, shares: totalShares, discoverChains, chains, signal } = options;
|
|
2628
2629
|
const validateSpinner = createSpinner("Validating seedphrase...");
|
|
2629
2630
|
const validation = await ctx2.sdk.validateSeedphrase(mnemonic);
|
|
@@ -2657,7 +2658,7 @@ async function executeImportSeedphraseSecure(ctx2, options) {
|
|
|
2657
2658
|
const importSpinner = createSpinner("Importing seedphrase as secure vault...");
|
|
2658
2659
|
try {
|
|
2659
2660
|
const result = await withAbortSignal(
|
|
2660
|
-
ctx2.sdk.
|
|
2661
|
+
ctx2.sdk.createSecureVaultFromSeedphrase({
|
|
2661
2662
|
mnemonic,
|
|
2662
2663
|
name,
|
|
2663
2664
|
password,
|
|
@@ -2713,16 +2714,62 @@ Or use this URL: ${qrPayload}
|
|
|
2713
2714
|
warn(`
|
|
2714
2715
|
Important: Save your vault backup file (.vult) in a secure location.`);
|
|
2715
2716
|
warn(`This is a ${threshold}-of-${totalShares} vault. You'll need ${threshold} devices to sign transactions.`);
|
|
2716
|
-
success("\n+ Vault
|
|
2717
|
+
success("\n+ Vault created from seedphrase!");
|
|
2717
2718
|
return result.vault;
|
|
2718
2719
|
} catch (err) {
|
|
2719
|
-
importSpinner.fail("Secure vault
|
|
2720
|
+
importSpinner.fail("Secure vault creation failed");
|
|
2720
2721
|
if (err.message?.includes("not implemented")) {
|
|
2721
|
-
warn("\nSecure vault seedphrase
|
|
2722
|
+
warn("\nSecure vault creation from seedphrase is not yet implemented in the SDK");
|
|
2722
2723
|
}
|
|
2723
2724
|
throw err;
|
|
2724
2725
|
}
|
|
2725
2726
|
}
|
|
2727
|
+
async function executeJoinSecure(ctx2, options) {
|
|
2728
|
+
const { qrPayload, mnemonic, password, devices, signal } = options;
|
|
2729
|
+
if (!devices || devices < 2) {
|
|
2730
|
+
throw new Error("devices is required when joining a SecureVault (minimum 2)");
|
|
2731
|
+
}
|
|
2732
|
+
const spinner = createSpinner("Joining SecureVault session...");
|
|
2733
|
+
try {
|
|
2734
|
+
const result = await withAbortSignal(
|
|
2735
|
+
ctx2.sdk.joinSecureVault(qrPayload, {
|
|
2736
|
+
mnemonic,
|
|
2737
|
+
password,
|
|
2738
|
+
devices,
|
|
2739
|
+
onProgress: (step) => {
|
|
2740
|
+
spinner.text = `${step.message} (${step.progress}%)`;
|
|
2741
|
+
},
|
|
2742
|
+
onDeviceJoined: (deviceId, totalJoined, required) => {
|
|
2743
|
+
if (!isSilent()) {
|
|
2744
|
+
spinner.text = `Device joined: ${totalJoined}/${required} (${deviceId})`;
|
|
2745
|
+
} else if (!isJsonOutput()) {
|
|
2746
|
+
printResult(`Device joined: ${totalJoined}/${required}`);
|
|
2747
|
+
}
|
|
2748
|
+
}
|
|
2749
|
+
}),
|
|
2750
|
+
signal
|
|
2751
|
+
);
|
|
2752
|
+
setupVaultEvents(result.vault);
|
|
2753
|
+
await ctx2.setActiveVault(result.vault);
|
|
2754
|
+
spinner.succeed(`Joined SecureVault: ${result.vault.name}`);
|
|
2755
|
+
if (isJsonOutput()) {
|
|
2756
|
+
outputJson({
|
|
2757
|
+
vault: {
|
|
2758
|
+
id: result.vaultId,
|
|
2759
|
+
name: result.vault.name,
|
|
2760
|
+
type: "secure"
|
|
2761
|
+
}
|
|
2762
|
+
});
|
|
2763
|
+
return result.vault;
|
|
2764
|
+
}
|
|
2765
|
+
warn("\nImportant: Save your vault backup file (.vult) in a secure location.");
|
|
2766
|
+
success("\n+ Successfully joined vault!");
|
|
2767
|
+
return result.vault;
|
|
2768
|
+
} catch (err) {
|
|
2769
|
+
spinner.fail("Failed to join SecureVault session");
|
|
2770
|
+
throw err;
|
|
2771
|
+
}
|
|
2772
|
+
}
|
|
2726
2773
|
|
|
2727
2774
|
// src/commands/swap.ts
|
|
2728
2775
|
async function executeSwapChains(ctx2) {
|
|
@@ -3040,8 +3087,9 @@ var COMMANDS = [
|
|
|
3040
3087
|
"vaults",
|
|
3041
3088
|
"vault",
|
|
3042
3089
|
"import",
|
|
3043
|
-
"
|
|
3090
|
+
"create-from-seedphrase",
|
|
3044
3091
|
"create",
|
|
3092
|
+
"join",
|
|
3045
3093
|
"info",
|
|
3046
3094
|
"export",
|
|
3047
3095
|
// Wallet operations
|
|
@@ -3099,13 +3147,20 @@ function createCompleter(ctx2) {
|
|
|
3099
3147
|
const partial = parts[1] || "";
|
|
3100
3148
|
return completeChainName(partial);
|
|
3101
3149
|
}
|
|
3102
|
-
if ((command === "create" || command === "
|
|
3150
|
+
if ((command === "create" || command === "create-from-seedphrase") && parts.length === 2) {
|
|
3103
3151
|
const types = ["fast", "secure"];
|
|
3104
3152
|
const partial = parts[1] || "";
|
|
3105
3153
|
const partialLower = partial.toLowerCase();
|
|
3106
3154
|
const matches = types.filter((t) => t.startsWith(partialLower));
|
|
3107
3155
|
return [matches.length ? matches : types, partial];
|
|
3108
3156
|
}
|
|
3157
|
+
if (command === "join" && parts.length === 2) {
|
|
3158
|
+
const types = ["secure"];
|
|
3159
|
+
const partial = parts[1] || "";
|
|
3160
|
+
const partialLower = partial.toLowerCase();
|
|
3161
|
+
const matches = types.filter((t) => t.startsWith(partialLower));
|
|
3162
|
+
return [matches.length ? matches : types, partial];
|
|
3163
|
+
}
|
|
3109
3164
|
const hits = COMMANDS.filter((c) => c.startsWith(line));
|
|
3110
3165
|
const show = hits.length ? hits : COMMANDS;
|
|
3111
3166
|
return [show, line];
|
|
@@ -3863,7 +3918,7 @@ Error: ${error2.message}`));
|
|
|
3863
3918
|
case "create":
|
|
3864
3919
|
await this.createVault(args);
|
|
3865
3920
|
break;
|
|
3866
|
-
case "
|
|
3921
|
+
case "create-from-seedphrase":
|
|
3867
3922
|
await this.importSeedphrase(args);
|
|
3868
3923
|
break;
|
|
3869
3924
|
case "info":
|
|
@@ -4049,7 +4104,7 @@ Error: ${error2.message}`));
|
|
|
4049
4104
|
async importSeedphrase(args) {
|
|
4050
4105
|
const type = args[0]?.toLowerCase();
|
|
4051
4106
|
if (!type || type !== "fast" && type !== "secure") {
|
|
4052
|
-
console.log(chalk9.cyan("Usage:
|
|
4107
|
+
console.log(chalk9.cyan("Usage: create-from-seedphrase <fast|secure>"));
|
|
4053
4108
|
console.log(chalk9.gray(" fast - Import with VultiServer (2-of-2)"));
|
|
4054
4109
|
console.log(chalk9.gray(" secure - Import with device coordination (N-of-M)"));
|
|
4055
4110
|
return;
|
|
@@ -4085,7 +4140,7 @@ Error: ${error2.message}`));
|
|
|
4085
4140
|
const discoverStr = await this.prompt("Discover chains with balances? (y/n)", "y");
|
|
4086
4141
|
const discoverChains = discoverStr.toLowerCase() === "y";
|
|
4087
4142
|
vault = await this.withCancellation(
|
|
4088
|
-
(signal) =>
|
|
4143
|
+
(signal) => executeCreateFromSeedphraseFast(this.ctx, {
|
|
4089
4144
|
mnemonic,
|
|
4090
4145
|
name,
|
|
4091
4146
|
password,
|
|
@@ -4116,7 +4171,7 @@ Error: ${error2.message}`));
|
|
|
4116
4171
|
const discoverStr = await this.prompt("Discover chains with balances? (y/n)", "y");
|
|
4117
4172
|
const discoverChains = discoverStr.toLowerCase() === "y";
|
|
4118
4173
|
vault = await this.withCancellation(
|
|
4119
|
-
(signal) =>
|
|
4174
|
+
(signal) => executeCreateFromSeedphraseSecure(this.ctx, {
|
|
4120
4175
|
mnemonic,
|
|
4121
4176
|
name,
|
|
4122
4177
|
password: password || void 0,
|
|
@@ -4387,7 +4442,7 @@ var cachedVersion = null;
|
|
|
4387
4442
|
function getVersion() {
|
|
4388
4443
|
if (cachedVersion) return cachedVersion;
|
|
4389
4444
|
if (true) {
|
|
4390
|
-
cachedVersion = "0.
|
|
4445
|
+
cachedVersion = "0.3.0";
|
|
4391
4446
|
return cachedVersion;
|
|
4392
4447
|
}
|
|
4393
4448
|
try {
|
|
@@ -4906,7 +4961,7 @@ program.command("import <file>").description("Import vault from .vult file").act
|
|
|
4906
4961
|
await executeImport(context, file);
|
|
4907
4962
|
})
|
|
4908
4963
|
);
|
|
4909
|
-
var
|
|
4964
|
+
var createFromSeedphraseCmd = program.command("create-from-seedphrase").description("Create vault from BIP39 seedphrase");
|
|
4910
4965
|
async function promptSeedphrase() {
|
|
4911
4966
|
info("\nEnter your 12 or 24-word recovery phrase.");
|
|
4912
4967
|
info("Words will be hidden as you type.\n");
|
|
@@ -4927,7 +4982,26 @@ async function promptSeedphrase() {
|
|
|
4927
4982
|
]);
|
|
4928
4983
|
return answer.mnemonic.trim().toLowerCase();
|
|
4929
4984
|
}
|
|
4930
|
-
|
|
4985
|
+
async function promptQrPayload() {
|
|
4986
|
+
info("\nEnter the QR code payload from the initiator device.");
|
|
4987
|
+
info('The payload starts with "vultisig://".\n');
|
|
4988
|
+
const answer = await inquirer8.prompt([
|
|
4989
|
+
{
|
|
4990
|
+
type: "input",
|
|
4991
|
+
name: "qrPayload",
|
|
4992
|
+
message: "QR Payload:",
|
|
4993
|
+
validate: (input) => {
|
|
4994
|
+
const trimmed = input.trim();
|
|
4995
|
+
if (!trimmed.startsWith("vultisig://")) {
|
|
4996
|
+
return 'QR payload must start with "vultisig://"';
|
|
4997
|
+
}
|
|
4998
|
+
return true;
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
]);
|
|
5002
|
+
return answer.qrPayload.trim();
|
|
5003
|
+
}
|
|
5004
|
+
createFromSeedphraseCmd.command("fast").description("Create FastVault from seedphrase (server-assisted 2-of-2)").requiredOption("--name <name>", "Vault name").requiredOption("--password <password>", "Vault password").requiredOption("--email <email>", "Email for verification").option("--mnemonic <words>", "Seedphrase (12 or 24 words, space-separated)").option("--discover-chains", "Scan chains for existing balances").option("--chains <chains>", "Specific chains to enable (comma-separated)").action(
|
|
4931
5005
|
withExit(
|
|
4932
5006
|
async (options) => {
|
|
4933
5007
|
const context = await init(program.opts().vault);
|
|
@@ -4948,7 +5022,7 @@ importSeedphraseCmd.command("fast").description("Import as FastVault (server-ass
|
|
|
4948
5022
|
}
|
|
4949
5023
|
}
|
|
4950
5024
|
}
|
|
4951
|
-
await
|
|
5025
|
+
await executeCreateFromSeedphraseFast(context, {
|
|
4952
5026
|
mnemonic,
|
|
4953
5027
|
name: options.name,
|
|
4954
5028
|
password: options.password,
|
|
@@ -4959,7 +5033,7 @@ importSeedphraseCmd.command("fast").description("Import as FastVault (server-ass
|
|
|
4959
5033
|
}
|
|
4960
5034
|
)
|
|
4961
5035
|
);
|
|
4962
|
-
|
|
5036
|
+
createFromSeedphraseCmd.command("secure").description("Create SecureVault from seedphrase (multi-device MPC)").requiredOption("--name <name>", "Vault name").option("--password <password>", "Vault password (optional)").option("--threshold <m>", "Signing threshold", "2").option("--shares <n>", "Total shares", "3").option("--mnemonic <words>", "Seedphrase (12 or 24 words)").option("--discover-chains", "Scan chains for existing balances").option("--chains <chains>", "Specific chains to enable (comma-separated)").action(
|
|
4963
5037
|
withExit(
|
|
4964
5038
|
async (options) => {
|
|
4965
5039
|
const context = await init(program.opts().vault);
|
|
@@ -4980,7 +5054,7 @@ importSeedphraseCmd.command("secure").description("Import as SecureVault (multi-
|
|
|
4980
5054
|
}
|
|
4981
5055
|
}
|
|
4982
5056
|
}
|
|
4983
|
-
await
|
|
5057
|
+
await executeCreateFromSeedphraseSecure(context, {
|
|
4984
5058
|
mnemonic,
|
|
4985
5059
|
name: options.name,
|
|
4986
5060
|
password: options.password,
|
|
@@ -4992,6 +5066,33 @@ importSeedphraseCmd.command("secure").description("Import as SecureVault (multi-
|
|
|
4992
5066
|
}
|
|
4993
5067
|
)
|
|
4994
5068
|
);
|
|
5069
|
+
var joinCmd = program.command("join").description("Join an existing vault creation session");
|
|
5070
|
+
joinCmd.command("secure").description("Join a SecureVault creation session").option("--qr <payload>", "QR code payload from initiator (vultisig://...)").option("--qr-file <path>", "Read QR payload from file").option("--mnemonic <words>", "Seedphrase (required for seedphrase-based sessions)").option("--password <password>", "Vault password (optional)").option("--devices <n>", "Total devices in session", "2").action(
|
|
5071
|
+
withExit(
|
|
5072
|
+
async (options) => {
|
|
5073
|
+
const context = await init(program.opts().vault);
|
|
5074
|
+
let qrPayload = options.qr;
|
|
5075
|
+
if (!qrPayload && options.qrFile) {
|
|
5076
|
+
qrPayload = (await fs3.readFile(options.qrFile, "utf-8")).trim();
|
|
5077
|
+
}
|
|
5078
|
+
if (!qrPayload) {
|
|
5079
|
+
qrPayload = await promptQrPayload();
|
|
5080
|
+
}
|
|
5081
|
+
const qrParams = await parseKeygenQR(qrPayload);
|
|
5082
|
+
let mnemonic = options.mnemonic;
|
|
5083
|
+
if (qrParams.libType === "KEYIMPORT" && !mnemonic) {
|
|
5084
|
+
info("\nThis session requires a seedphrase to join.");
|
|
5085
|
+
mnemonic = await promptSeedphrase();
|
|
5086
|
+
}
|
|
5087
|
+
await executeJoinSecure(context, {
|
|
5088
|
+
qrPayload,
|
|
5089
|
+
mnemonic,
|
|
5090
|
+
password: options.password,
|
|
5091
|
+
devices: parseInt(options.devices, 10)
|
|
5092
|
+
});
|
|
5093
|
+
}
|
|
5094
|
+
)
|
|
5095
|
+
);
|
|
4995
5096
|
program.command("verify <vaultId>").description("Verify vault with email verification code").option("-r, --resend", "Resend verification email").option("--code <code>", "Verification code").option("--email <email>", "Email address (required for --resend)").option("--password <password>", "Vault password (required for --resend)").action(
|
|
4996
5097
|
withExit(
|
|
4997
5098
|
async (vaultId, options) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vultisig/cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Command-line wallet for Vultisig - multi-chain MPC wallet management",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
},
|
|
49
49
|
"homepage": "https://vultisig.com",
|
|
50
50
|
"dependencies": {
|
|
51
|
-
"@vultisig/sdk": "^0.
|
|
51
|
+
"@vultisig/sdk": "^0.3.0",
|
|
52
52
|
"chalk": "^5.3.0",
|
|
53
53
|
"cli-table3": "^0.6.5",
|
|
54
54
|
"commander": "^12.0.0",
|