Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/bitcore-cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
}
],
"bin": {
"wallet": "./bin/wallet"
"bitcore-cli": "./bin/wallet"
},
"scripts": {
"test": "npm run compile && node copyTestWallets && mocha --exit 'build/test/**/*.js'",
Expand Down
2 changes: 1 addition & 1 deletion packages/bitcore-cli/src/commands/create/createMultiSig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export async function createMultiSigWallet(

const copayerName = await getCopayerName();
const addressType = await getAddressType({ chain, network, isMultiSig: true });
const password = await getPassword('Enter a password for the wallet:', { hidden: false });
const password = await getPassword('Lock your wallet with a password:', { hidden: false });

const { key, secret } = await wallet.create({ chain, network, account: 0, n, m, password, mnemonic, addressType, copayerName });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ export async function createSingleSigWallet(
const { verbose, mnemonic } = opts;

const addressType = await getAddressType({ chain, network });
const password = await getPassword('Enter a password for the wallet:', { hidden: false });
const password = await getPassword('Lock your wallet with a password:', { hidden: false });
const copayerName = process.env.USER || 'copayer';

const { key } = await wallet.create({
Expand Down
25 changes: 22 additions & 3 deletions packages/bitcore-cli/src/commands/create/createThresholdSig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ import url from 'url';
import { Key, type Network, TssKey } from '@bitpay-labs/bitcore-wallet-client';
import * as prompt from '@clack/prompts';
import { UserCancelled } from '../../errors';
import { getAddressType, getCopayerName, getPassword } from '../../prompts';
import { getAddressType, getCopayerName, getPassword, promptKeyshareBackup } from '../../prompts';
import { Utils } from '../../utils';
import { exportWallet } from '../export';
import type { CommonArgs } from '../../../types/cli';


Expand All @@ -26,7 +27,7 @@ export async function createThresholdSigWallet(

const copayerName = await getCopayerName();
const addressType = await getAddressType({ chain, network, isMultiSig: false, isTss: true });
const password = await getPassword('Enter a password for the wallet:', { hidden: false });
const password = await getPassword('Lock your wallet with a password:', { hidden: false });

let key;
if (mnemonic) {
Expand All @@ -46,6 +47,16 @@ export async function createThresholdSigWallet(
const tssPassword = crypto.randomBytes(20).toString('hex');
await tss.newKey({ m, n, password: tssPassword });

prompt.note(
'Next, you will be asked to enter party 1\'s public key. Once you enter it, ' +
'a personal join code will be generated for you to give to them.' + os.EOL +
'To get their public key, party 1 should go ahead and start the join process ' +
'for their wallet by running bitcore-cli and selecting `Join Wallet`. Then they follow the ' +
'prompts until it tells them to share the public key with the session leader (you).' + os.EOL + os.EOL +
'Repeat this process for the other party members. Once all members have joined, the TSS ' +
'wallet creation process will finish.'
);

for (let i = 1; i < n; i++) {
const pubkey = await prompt.text({
message: `Enter party ${i}'s public key:`,
Expand Down Expand Up @@ -133,7 +144,15 @@ export async function createThresholdSigWallet(
});
});


// Keyshare backup
const ok = await promptKeyshareBackup();
if (ok) {
await exportWallet({ wallet, opts: { ...opts, readonly: false } });
}

return {
mnemonic: key.get(password).mnemonic
// TSS wallets cannot be restored from a mnemonic alone, so we return null here. All the wallet recovery information is in the keyshare backup file.
mnemonic: null
};
}
5 changes: 2 additions & 3 deletions packages/bitcore-cli/src/commands/create/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,18 +30,17 @@ export async function createWallet(args: CommonArgs<{ mnemonic?: string }>) {
const [m, n] = Utils.parseMN(mOfN);

if (useTss) {
({ mnemonic } = await createThresholdSigWallet({ wallet, chain, network, opts, m, n }));
await createThresholdSigWallet({ wallet, chain, network, opts, m, n });
} else {
({ mnemonic } = await createMultiSigWallet({ wallet, chain, network, opts, m, n }));
}
}

// Re-fetch the client to ensure it has the latest state
// and to complete the wallet creation process

await wallet.getClient({});

if (!opts.mnemonic) {
if (!opts.mnemonic && mnemonic) {
await Utils.showMnemonic(wallet.name, mnemonic, opts);
}
};
6 changes: 3 additions & 3 deletions packages/bitcore-cli/src/commands/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ export async function exportWallet(args: CommonArgs<{ filename?: string; readonl
}
const replaceTilde = str => str.startsWith('~') ? str.replace('~', os.homedir()) : str;

const readOnly = !!opts.readonly || wallet.isReadOnly() || await prompt.confirm({
const readOnly = opts.readonly ?? (wallet.isReadOnly() || await prompt.confirm({
message: 'Export as read-only (cannot send funds)?',
initialValue: false
});
}));
if (prompt.isCancel(readOnly)) {
throw new UserCancelled();
}
Expand Down Expand Up @@ -66,7 +66,7 @@ export async function exportWallet(args: CommonArgs<{ filename?: string; readonl
throw new UserCancelled();
}

const exportPassword = await getPassword('Import/export password:', { hidden: false, minLength: 6 });
const exportPassword = await getPassword('File encryption password:', { hidden: false, minLength: 6 });

await wallet.export({
filename: replaceTilde(filename),
Expand Down
2 changes: 1 addition & 1 deletion packages/bitcore-cli/src/commands/import.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ export async function importWallet(args: CommonArgs) {
throw new UserCancelled();
}

const importPassword = await getPassword('Import/export password:', { hidden: true });
const importPassword = await getPassword('File decryption password:', { hidden: true });

await wallet.import({
filename: replaceTilde(filename),
Expand Down
4 changes: 2 additions & 2 deletions packages/bitcore-cli/src/commands/join/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,12 @@ export async function joinWallet(args: CommonArgs<{ mnemonic?: string }>) {

let mnemonic;
if (useTss) {
({ mnemonic } = await joinThresholdSigWallet(Object.assign({}, args, { chain })));
await joinThresholdSigWallet(Object.assign({}, args, { chain }));
} else {
({ mnemonic } = await joinMultiSigWallet(args));
}

if (!opts.mnemonic) {
if (!opts.mnemonic && mnemonic) {
await Utils.showMnemonic(wallet.name, mnemonic, opts);
}
};
2 changes: 1 addition & 1 deletion packages/bitcore-cli/src/commands/join/joinMultiSig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ export async function joinMultiSigWallet(args: CommonArgs<{ mnemonic?: string }>
} = parsed;

const copayerName = await getCopayerName();
const password = await getPassword('Enter a password for the wallet:', { hidden: false });
const password = await getPassword('Lock your wallet with a password:', { hidden: false });
const { key, joinedWalletName } = await wallet.create({ chain, network, account: 0, n: 2, m: 1, password, mnemonic, copayerName, joinSecret }); // n gets overwritten

prompt.log.success(Utils.colorText(`Wallet joined: ${joinedWalletName}`, 'green'));
Expand Down
15 changes: 12 additions & 3 deletions packages/bitcore-cli/src/commands/join/joinThresholdSig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@ import url from 'url';
import { Key, TssKey } from '@bitpay-labs/bitcore-wallet-client';
import * as prompt from '@clack/prompts';
import { UserCancelled } from '../../errors';
import { getCopayerName, getNetwork, getPassword } from '../../prompts';
import { getCopayerName, getNetwork, getPassword, promptKeyshareBackup } from '../../prompts';
import { Utils } from '../../utils';
import { exportWallet } from '../export';
import type { CommonArgs } from '../../../types/cli';

export async function joinThresholdSigWallet(
Expand All @@ -15,7 +16,7 @@ export async function joinThresholdSigWallet(

const network = await getNetwork();
const copayerName = await getCopayerName();
const password = await getPassword('Enter a password for the wallet:', { hidden: false });
const password = await getPassword('Lock your wallet with a password:', { hidden: false });

let key;
if (mnemonic) {
Expand Down Expand Up @@ -114,7 +115,15 @@ export async function joinThresholdSigWallet(
});
});


// Keyshare backup
const ok = await promptKeyshareBackup();
if (ok) {
await exportWallet({ wallet, opts: { ...opts, readonly: false } });
}

return {
mnemonic: key.get(password).mnemonic
// TSS wallets cannot be restored from a mnemonic alone, so we return null here. All the wallet recovery information is in the keyshare backup file.
mnemonic: null
};
}
2 changes: 1 addition & 1 deletion packages/bitcore-cli/src/commands/status.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export async function walletStatus(args: CommonArgs) {
statusLines.push(`Secret: ${Utils.colorText(w.secret, 'yellow')}`);
}

prompt.note(statusLines.join(os.EOL), `${tokenObj ? '(Linked) ' : ''}Wallet info`);
prompt.note(statusLines.join(os.EOL), `${tokenObj ? '(Linked) ' : ''}Wallet Info`);

const currency = tokenObj?.displayCode || w.coin;
displayBalance(currency, status.balance, Object.assign({ showByAddress: false }, tokenObj));
Expand Down
Loading