Skip to content

Commit

Permalink
refactor(account)!: combine account create and account save
Browse files Browse the repository at this point in the history
BREAKING CHANGE: `account save` removed
Use `account create` instead:
```diff
-$ aecli account save ./my-wallet.json <hex secret key>
+$ aecli account create ./my-wallet.json <hex secret key>
```
  • Loading branch information
davidyuk committed Apr 11, 2024
1 parent 74dad73 commit fdaeeff
Show file tree
Hide file tree
Showing 7 changed files with 31 additions and 62 deletions.
2 changes: 1 addition & 1 deletion CLI.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ Your address is: ak_2a1j2Mk9YSmC1gioUq4PWRm3bsv887MbuRVwyv4KaUGoR1eiKi
Using this command, you can pass the private key to generate a wallet with a key pair.

```
$ aecli account save ./wallet.json <your_private_key>
$ aecli account create ./wallet.json <your_private_key>
```
You will get the following:
```
Expand Down
46 changes: 18 additions & 28 deletions src/actions/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
// This script initialize all `account` function

import fs from 'fs-extra';
import { generateKeyPair, verifyMessage as _verifyMessage } from '@aeternity/aepp-sdk';
import { writeWallet } from '../utils/account.js';
import {
generateKeyPair, verifyMessage as _verifyMessage, getAddressFromPriv, dump,
} from '@aeternity/aepp-sdk';
import { getFullPath } from '../utils/helpers.js';
import CliError from '../utils/CliError.js';
import { initSdkByWalletFile, getAccountByWalletFile } from '../utils/cli.js';
import { print, printUnderscored } from '../utils/print.js';
import { PROMPT_TYPE, prompt } from '../utils/prompt.js';
Expand Down Expand Up @@ -86,38 +89,25 @@ export async function getAddress(walletPath, options) {
}
}

// ## Create secure `wallet` file
// ## Create secure `wallet` file by secret key of generate one
// This function allow you to generate `keypair` and write it to secure `ethereum` like key-file
export async function createSecureWallet(walletPath, { password, overwrite, json }) {
const { secretKey } = generateKeyPair(true);
const { publicKey, path } = await writeWallet(walletPath, secretKey, password, overwrite);
if (json) {
print({
publicKey,
path,
});
} else {
printUnderscored('Address', publicKey);
printUnderscored('Path', path);
}
}

// ## Create secure `wallet` file from `private-key`
// This function allow you to generate `keypair` from `private-key` and write it to secure `ethereum` like key-file
export async function createSecureWalletByPrivKey(
export async function createWallet(
walletPath,
secretKey,
secretKey = generateKeyPair().secretKey,
{ password, overwrite, json },
) {
secretKey = Buffer.from(secretKey.trim(), 'hex');
const { publicKey, path } = await writeWallet(walletPath, secretKey, password, overwrite);
secretKey = Buffer.from(secretKey, 'hex');
walletPath = getFullPath(walletPath);
if (!overwrite && await fs.exists(walletPath) && !await prompt(PROMPT_TYPE.askOverwrite)) {
throw new CliError(`Wallet already exist at ${walletPath}`);
}
password ??= await prompt(PROMPT_TYPE.askPassword);
await fs.outputJson(walletPath, await dump(walletPath, password, secretKey));
const publicKey = getAddressFromPriv(secretKey);
if (json) {
print({
publicKey,
path,
});
print({ publicKey, path: walletPath });
} else {
printUnderscored('Address', publicKey);
printUnderscored('Path', path);
printUnderscored('Path', walletPath);
}
}
23 changes: 8 additions & 15 deletions src/commands/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -67,25 +67,18 @@ addCommonOptions(program
// ## Initialize `create` command
//
// You can use this command to generate `keypair` and encrypt it by password.
// Secret key can be provided in options, or cli will generate one.
// This command create `ethereum like keyfile`.
//
// Example: `aecli account create ./mykeys/my-wallet.json --password testpassword`
addCommonOptions(program
.command('create <wallet_path>')
.argument('[privkey]', 'Secret key as 64-bytes encoded as hex')
.option('--overwrite', 'Overwrite if exist')
.description('Create a secure wallet')
.action(Account.createSecureWallet));
.description('Create a secure wallet by a private key or generate one.')
.addHelpText('after', `
// ## Initialize `save` command
//
// You can use this command to generate `keypair` from `private-key` and encrypt it by password.
// This command create `ethereum like keyfile`.
//
// Example: `aecli account save ./mykeys/my-wallet.json 1902855723940510273412074210842018342148234 --password testpassword`
addCommonOptions(program
.command('save <wallet_path> <privkey>')
.option('--overwrite', 'Overwrite if exist')
.description('Save a private keys string to a password protected file wallet')
.action(Account.createSecureWalletByPrivKey));
Example call:
$ aecli account create ./my-wallet.json --password top-secret
$ aecli account create ./my-wallet.json 9ebd7beda0c79af72a42ece3821a56eff16359b6df376cf049aee995565f022f840c974b97164776454ba119d84edc4d6058a8dec92b6edc578ab2d30b4c4200`)
.action(Account.createWallet));

export default program;
16 changes: 1 addition & 15 deletions src/utils/account.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,9 @@
// # Utils `account` Module
// That script contains helper function's for work with `account`
import fs from 'fs-extra';
import {
generateKeyPairFromSecret, getAddressFromPriv, dump, recover, encode, Encoding,
} from '@aeternity/aepp-sdk';
import { getAddressFromPriv, recover } from '@aeternity/aepp-sdk';
import { PROMPT_TYPE, prompt } from './prompt.js';
import { getFullPath } from './helpers.js';
import CliError from './CliError.js';

export async function writeWallet(walletPath, secretKey, password, overwrite) {
const path = getFullPath(walletPath);
if (!overwrite && await fs.exists(path) && !await prompt(PROMPT_TYPE.askOverwrite)) {
throw new CliError(`Wallet already exist at ${path}`);
}
password ??= await prompt(PROMPT_TYPE.askPassword);
await fs.outputJson(path, await dump(path, password, secretKey));
const { publicKey } = generateKeyPairFromSecret(secretKey);
return { publicKey: encode(publicKey, Encoding.AccountAddress), path };
}

// Get account file by path, decrypt it using password and return `keypair`
export async function getWalletByPathAndDecrypt(walletPath, password) {
Expand Down
2 changes: 1 addition & 1 deletion test/account.js
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ Address _________________________________ ${resJson.publicKey}
});

it('Create Wallet From Private Key', async () => {
await executeAccount(['save', walletName, '--password', 'test', keypair.secretKey, '--overwrite']);
await executeAccount(['create', walletName, '--password', 'test', keypair.secretKey, '--overwrite']);
expect(await fs.exists(walletName)).to.be.equal(true);
expect((await executeAccount(['address', walletName, '--password', 'test', '--json'])).publicKey)
.to.equal(keypair.publicKey);
Expand Down
2 changes: 1 addition & 1 deletion test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export async function getSdk() {
accounts: [new MemoryAccount(tempKeyPair.secretKey)],
});
await Promise.all([
executeProgram(accountProgram, ['save', WALLET_NAME, '--password', 'test', tempKeyPair.secretKey, '--overwrite']),
executeProgram(accountProgram, ['create', WALLET_NAME, '--password', 'test', tempKeyPair.secretKey, '--overwrite']),
sdk.spend(1e26, tempKeyPair.publicKey, { onAccount: new MemoryAccount(keypair.secretKey) }),
]);
return sdk;
Expand Down
2 changes: 1 addition & 1 deletion test/tx.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ describe('Transaction Module', () => {
before(async () => {
sdk = await getSdk();
await sdk.spend(1e24, TX_KEYS.publicKey);
await executeProgram(accountProgram, ['save', WALLET_NAME, '--password', 'test', TX_KEYS.secretKey]);
await executeProgram(accountProgram, ['create', WALLET_NAME, '--password', 'test', TX_KEYS.secretKey]);
});

it('builds tx', async () => {
Expand Down

0 comments on commit fdaeeff

Please sign in to comment.