# IoTeX Node.js SDK - Account Management & HD Wallet Guide

Complete guide to account creation, keystore management, HD wallets, and cryptographic operations.

## Table of Contents

1. [Quick Start](#quick-start)
2. [Keystore Account Management](#keystore-account-management)
3. [HD Wallet (BIP39/BIP44)](#hd-wallet-bip39bip44)
4. [Message Signing & Verification](#message-signing--verification)
5. [Address Conversion](#address-conversion)
6. [Security Best Practices](#security-best-practices)
7. [Advanced Cryptography](#advanced-cryptography)

---

## Quick Start

### Create Your First Account

```typescript
import { IoTeXSDK } from 'iotex-node-sdk';

const sdk = IoTeXSDK.mainnet();
await sdk.connect();

// Create a new account with encrypted keystore
const { address, privateKey } = await sdk.account.create('my-secure-password');
console.log('New account:', address);
console.log('Private key (save it!):', privateKey);

sdk.disconnect();
```

### Access Existing Account

```typescript
// List all keystore accounts
const accounts = sdk.account.list();
console.log('Your accounts:', accounts);

// Check if account exists
if (sdk.account.exists('io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v')) {
  const meta = await sdk.account.getMeta('io1gh7xfrsnj6p5uqgjpk9xq6jg9na28aewgp7a9v');
  console.log('Balance:', meta.balance, 'IOTX');
}
```

---

## Keystore Account Management

The keystore is an encrypted file system that securely stores private keys.

### Storage Location

```
~/.iotex-node-sdk/keystore/
├── account1.json
├── account2.json
└── ...
```

Each file is an encrypted JSON keystore compatible with ethers.js format.

### Create New Account

```typescript
const { address, privateKey } = await sdk.account.create('secure-password');

// Returns:
// {
//   address: "io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw",
//   privateKey: "0x1234567890abcdef..." (for backup only)
// }

// Save this private key in a safe place!
// You can use it to restore the account later
```

### Import Private Key

If you have a private key from another wallet:

```typescript
const importedAddress = await sdk.account.importKey(
  '0x1234567890abcdef...',  // Private key
  'secure-password'
);

console.log('Imported account:', importedAddress);
```

### Export Private Key

```typescript
// Export private key from keystore
const privateKey = await sdk.account.exportKey(
  'io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw',
  'password-to-decrypt'
);

console.log('Private key:', privateKey);
// ⚠️ CAUTION: Keep this private!
```

### List All Accounts

```typescript
const accounts = sdk.account.list();

console.log('Your accounts:');
accounts.forEach(acc => {
  console.log(`  ${acc.address}`);
  console.log(`  Public key: ${acc.publicKey}`);
});
```

### Check Account Existence

```typescript
const exists = sdk.account.exists('io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw');
if (exists) {
  console.log('Account found in keystore');
} else {
  console.log('Account not in keystore');
}
```

### Delete Account

```typescript
// Permanently delete account from keystore
await sdk.account.delete('io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw');
console.log('Account deleted');

// ⚠️ WARNING: This is permanent! Make sure you have the private key backed up
```

### Update Account Password

```typescript
await sdk.account.updatePassword(
  'io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw',
  'old-password',
  'new-secure-password'
);

console.log('Password updated');
```

### Sign Message with Account

```typescript
const signature = await sdk.account.sign(
  'io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw',
  'password',
  'message-to-sign'
);

console.log('Signature:', signature);

// Verify the signature
const isValid = sdk.account.verify(
  'message-to-sign',
  signature,
  'io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw'
);

console.log('Signature valid:', isValid);
```

### Get Keystore Directory

```typescript
const dir = sdk.account.getKeystoreDir();
console.log('Keystore location:', dir);
// /Users/username/.iotex-node-sdk/keystore/
```

---

## HD Wallet (BIP39/BIP44)

HD (Hierarchical Deterministic) wallets allow you to generate multiple accounts from a single mnemonic seed phrase.

### Wallet Derivation Path

IoTeX uses BIP44 standard:

```
m/44'/304'/account'/change/index
     ↑    ↑       ↑      ↑     ↑
     |    |       |      |     └─ Address index (0, 1, 2, ...)
     |    |       |      └─────── Change type (0=external, 1=internal)
     |    |       └──────────── Account number (0, 1, 2, ...)
     |    └──────────────────── Coin type 304 (IoTeX)
     └───────────────────────── Purpose: 44 (BIP44)
```

### Examples:
- `m/44'/304'/0'/0/0` - Account 0, external address 0
- `m/44'/304'/0'/0/1` - Account 0, external address 1
- `m/44'/304'/1'/0/0` - Account 1, external address 0

### Create New HD Wallet

```typescript
// Create with 12-word mnemonic
const mnemonic = await sdk.account.createHDWallet('secure-password');

console.log('Your mnemonic:');
console.log(mnemonic);
// word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12

// ⚠️ SAVE THIS MNEMONIC SOMEWHERE SAFE!
// Anyone with this mnemonic can access all your accounts
```

### Create with Chinese Wordlist

```typescript
const mnemonic = await sdk.account.createHDWallet('secure-password', 'chinese');
// Returns mnemonic in Chinese
```

### Import Mnemonic

If you have an existing 12-word mnemonic:

```typescript
await sdk.account.importHDWallet(
  'word1 word2 word3 word4 word5 word6 word7 word8 word9 word10 word11 word12',
  'secure-password'
);

console.log('Mnemonic imported');
```

### Derive Accounts from HD Wallet

```typescript
// Derive first address of first account
const account1 = await sdk.account.deriveHDAccount('password', 0, 0, 0);
console.log('Address 1:', account1.address);

// Derive second address of first account
const account2 = await sdk.account.deriveHDAccount('password', 0, 0, 1);
console.log('Address 2:', account2.address);

// Derive first address of second account
const account3 = await sdk.account.deriveHDAccount('password', 1, 0, 0);
console.log('Address 3:', account3.address);

// Returns:
// {
//   address: "io1...",
//   publicKey: "0x...",
//   privateKey: "0x..." (temporary, not stored)
// }
```

### Derive Multiple Addresses

```typescript
// Create 5 addresses from account 0
const addresses = [];

for (let i = 0; i < 5; i++) {
  const account = await sdk.account.deriveHDAccount('password', 0, 0, i);
  addresses.push(account.address);
  console.log(`Address ${i + 1}: ${account.address}`);
}
```

### Export Mnemonic

```typescript
const mnemonic = await sdk.account.exportHDWalletMnemonic('password');

console.log('Your mnemonic:');
console.log(mnemonic);

// ⚠️ KEEP THIS SECRET!
```

### Check HD Wallet Status

```typescript
const exists = sdk.account.hdWalletExists();

if (exists) {
  console.log('HD Wallet is configured');
} else {
  console.log('No HD Wallet found');
}
```

### Update HD Wallet Password

```typescript
await sdk.account.updateHDWalletPassword('old-password', 'new-secure-password');
console.log('HD Wallet password updated');
```

### Delete HD Wallet

```typescript
sdk.account.deleteHDWallet();
console.log('HD Wallet deleted');

// ⚠️ PERMANENT! Make sure you have the mnemonic backed up
```

### Get HD Wallet Config File

```typescript
const configFile = sdk.account.getHDWalletConfigFile();
console.log('Config location:', configFile);
// /Users/username/.iotex-node-sdk/hdwallet
```

---

## Message Signing & Verification

Sign and verify messages using account private keys or HD wallet accounts.

### Sign Message with Keystore Account

```typescript
// Sign using account in keystore
const signature = await sdk.account.sign(
  'io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw',
  'password',
  'Hello, IoTeX!'
);

console.log('Signature:', signature);

// Message prefix is added automatically (Ethereum-style):
// "\x19Ethereum Signed Message:\n13Hello, IoTeX!"
```

### Sign Message with HD Wallet Account

```typescript
import { signMessage } from 'iotex-node-sdk';

// Derive account
const account = await sdk.account.deriveHDAccount('password', 0, 0, 0);

// Sign with private key
const signature = await signMessage(account.privateKey, 'Hello, IoTeX!');

console.log('Signature:', signature);
```

### Sign Message with Raw Private Key

```typescript
import { signMessage } from 'iotex-node-sdk';

const signature = await signMessage(
  '0x1234567890abcdef...',  // Private key
  'Message to sign'
);

console.log('Signature:', signature);
```

### Verify Signature

```typescript
import { verifyMessage } from 'iotex-node-sdk';

const isValid = verifyMessage(
  'Hello, IoTeX!',
  '0x...signature...',
  'io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw'  // Signer address
);

console.log('Signature valid:', isValid);
// Returns: true | false
```

### Verify with Any Address Format

```typescript
import { verifyMessage } from 'iotex-node-sdk';

// Works with both IoTeX and Ethereum addresses
const isValid = verifyMessage(
  'message',
  '0xsignature',
  '0xb8744ae4032be5e5ef9fab94ee9c3bf38d5d2ae0'  // Ethereum address
);
```

---

## Address Conversion

Convert between IoTeX and Ethereum address formats.

### IoTeX to Ethereum

```typescript
const ioAddress = 'io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw';
const ethAddress = sdk.account.toEthAddress(ioAddress);

console.log('Ethereum:', ethAddress);
// 0xb8744ae4032be5e5ef9fab94ee9c3bf38d5d2ae0
```

### Ethereum to IoTeX

```typescript
const ethAddress = '0xb8744ae4032be5e5ef9fab94ee9c3bf38d5d2ae0';
const ioAddress = sdk.account.toIoAddress(ethAddress);

console.log('IoTeX:', ioAddress);
// io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw
```

### Same Address, Different Format

The same underlying account can be represented in both formats:

```typescript
const ioAddr = 'io1hp6y4eqr90j7tmul4w2wa8pm7wx462hq0mg4tw';
const ethAddr = sdk.account.toEthAddress(ioAddr);
const backToIo = sdk.account.toIoAddress(ethAddr);

console.log(ioAddr === backToIo);  // true
```

---

## Security Best Practices

### 1. Secure Password Storage

❌ **Never hardcode passwords:**
```typescript
// DON'T DO THIS
const password = 'my-password-123';
const { address } = await sdk.account.create(password);
```

✅ **Use environment variables:**
```typescript
const password = process.env.IOTEX_PASSWORD;
if (!password) {
  throw new Error('IOTEX_PASSWORD environment variable not set');
}
const { address } = await sdk.account.create(password);
```

✅ **Or use a secrets manager:**
```typescript
import { secretsManager } from '@aws-sdk/client-secrets-manager';

const password = await getSecretFromSecretsManager('iotex-wallet-password');
const { address } = await sdk.account.create(password);
```

### 2. Backup Your Mnemonic

```typescript
// Export mnemonic regularly
const mnemonic = await sdk.account.exportHDWalletMnemonic('password');

// Store in secure location:
// - Hardware wallet
// - Encrypted backup
// - Safe deposit box
// - NOT in email or cloud without encryption

// Never share with anyone!
```

### 3. Backup Private Keys

```typescript
// When creating accounts, save the private key
const { address, privateKey } = await sdk.account.create('password');

// Store securely:
fs.writeFileSync('/secure/backup/privatekey.txt', privateKey, { mode: 0o600 });

// Never commit to Git or share publicly
```

### 4. Always Disconnect

```typescript
try {
  await sdk.connect();
  // Your operations
} finally {
  sdk.disconnect();  // Always disconnect
}
```

### 5. Validate Addresses

```typescript
import { isValidIoAddress } from 'iotex-node-sdk';

const userInput = getUserAddressInput();

if (!isValidIoAddress(userInput)) {
  throw new Error('Invalid address format');
}

const balance = await sdk.account.getBalance(userInput);
```

### 6. Use Strong Passwords

Password requirements:
- Minimum 12 characters
- Mix of uppercase, lowercase, numbers, symbols
- Not dictionary words or common phrases

```typescript
import { isValidPassword } from 'your-validation-library';

const password = getUserPassword();

if (!isValidPassword(password)) {
  throw new Error('Password does not meet security requirements');
}
```

### 7. Limit Account Access

```typescript
// Don't share keystore files or config
fs.chmodSync(path.join(os.homedir(), '.iotex-node-sdk'), 0o700);

// Only current user can read
// Others: no access
```

### 8. Rotate Passwords Regularly

```typescript
// Change password every 90 days
await sdk.account.updatePassword(
  'io1...',
  'old-password',
  'new-strong-password'
);

// For HD wallets
await sdk.account.updateHDWalletPassword('old-password', 'new-password');
```

---

## Advanced Cryptography

Low-level cryptographic operations for advanced users.

### Generate Random Key Pair

```typescript
import { generateKeyPair } from 'iotex-node-sdk';

const { address, privateKey, publicKey } = generateKeyPair();

console.log('Address:', address);
console.log('Private Key:', privateKey);
console.log('Public Key:', publicKey);
```

### Derive Keys from Private Key

```typescript
import { getPublicKey, getAddress } from 'iotex-node-sdk';

const privateKey = '0x1234567890abcdef...';

// Get public key
const publicKey = getPublicKey(privateKey);
console.log('Public key:', publicKey);

// Get IoTeX address
const address = getAddress(privateKey);
console.log('IoTeX address:', address);

// Get Ethereum address
import { getEthAddress } from 'iotex-node-sdk';
const ethAddress = getEthAddress(privateKey);
console.log('Ethereum address:', ethAddress);
```

### Hashing

```typescript
import { hashSHA256, hashKeccak256 } from 'iotex-node-sdk';

// SHA256
const sha256 = hashSHA256('data-to-hash');
console.log('SHA256:', sha256.toString('hex'));

// Keccak256
const keccak256 = hashKeccak256('data-to-hash');
console.log('Keccak256:', keccak256);
```

### Encrypt & Decrypt Data

```typescript
import { encrypt, decrypt, deriveKeyFromPassword } from 'iotex-node-sdk';

const password = 'secure-password';
const key = deriveKeyFromPassword(password);

const data = Buffer.from('sensitive-data');
const encrypted = encrypt(data, key);
console.log('Encrypted:', encrypted.toString('hex'));

const decrypted = decrypt(encrypted, key);
console.log('Decrypted:', decrypted.toString());
```

### Parse HD Derivation Path

```typescript
import { Account } from 'iotex-node-sdk';

const path = "m/44'/304'/0'/0/5";
const { account, change, index } = Account.parseHDPath(path);

console.log('Account:', account);  // 0
console.log('Change:', change);    // 0
console.log('Index:', index);      // 5
```

---

## Complete Account Management Example

```typescript
import {
  IoTeXSDK,
  isValidIoAddress,
  IoTeXError
} from 'iotex-node-sdk';

async function accountManagementExample() {
  const sdk = IoTeXSDK.mainnet();
  await sdk.connect();

  try {
    console.log('=== Creating New Account ===');
    const { address: newAddr, privateKey } =
      await sdk.account.create('secure-password');
    console.log('New address:', newAddr);
    console.log('Backup this private key:', privateKey);

    console.log('\n=== Creating HD Wallet ===');
    const mnemonic = await sdk.account.createHDWallet('password');
    console.log('Mnemonic (save it!):', mnemonic);

    console.log('\n=== Deriving Accounts ===');
    for (let i = 0; i < 3; i++) {
      const account = await sdk.account.deriveHDAccount('password', 0, 0, i);
      console.log(`Account ${i}: ${account.address}`);
    }

    console.log('\n=== Message Signing ===');
    const message = 'Hello, IoTeX!';
    const signature = await sdk.account.sign(newAddr, 'secure-password', message);
    console.log('Message:', message);
    console.log('Signature:', signature);

    const isValid = sdk.account.verify(message, signature, newAddr);
    console.log('Signature valid:', isValid);

    console.log('\n=== Account Management ===');
    const accounts = sdk.account.list();
    console.log(`Total accounts: ${accounts.length}`);

    if (isValidIoAddress(newAddr)) {
      console.log('Address is valid');
    }

    console.log('\n=== Address Conversion ===');
    const ethAddr = sdk.account.toEthAddress(newAddr);
    console.log('Ethereum format:', ethAddr);

    const backToIo = sdk.account.toIoAddress(ethAddr);
    console.log('Back to IoTeX:', backToIo);

  } catch (error) {
    if (error instanceof IoTeXError) {
      console.error(`Error [${error.code}]: ${error.message}`);
    } else {
      console.error('Error:', error);
    }
  } finally {
    sdk.disconnect();
  }
}

accountManagementExample();
```

---

## Troubleshooting

### Account Not Found After Creation

```typescript
const { address } = await sdk.account.create('password');
const exists = sdk.account.exists(address);

if (!exists) {
  // Account creation failed or keystore issue
  const keystoreDir = sdk.account.getKeystoreDir();
  console.log('Check keystore:', keystoreDir);
}
```

### Password Incorrect Error

```typescript
try {
  const key = await sdk.account.exportKey(address, 'wrong-password');
} catch (error) {
  if (error instanceof IoTeXError) {
    if (error.code === 'INVALID_ARGUMENT') {
      console.error('Incorrect password');
    }
  }
}
```

### HD Wallet Not Found

```typescript
if (!sdk.account.hdWalletExists()) {
  console.log('Create HD wallet first:');
  const mnemonic = await sdk.account.createHDWallet('password');
  console.log('Mnemonic:', mnemonic);
}
```

### Address Format Issues

```typescript
import { isValidIoAddress, isValidEthAddress } from 'iotex-node-sdk';

const addr = getUserInput();

if (isValidIoAddress(addr)) {
  // Use as IoTeX address
} else if (isValidEthAddress(addr)) {
  // Convert to IoTeX: sdk.account.toIoAddress(addr)
} else {
  console.error('Invalid address format');
}
```

---

## See Also

- [API_COMPLETE_REFERENCE.md](./API_COMPLETE_REFERENCE.md) - Full API documentation
- [README_QUERIES.md](./README_QUERIES.md) - Query examples
- [GETTING_STARTED.md](./GETTING_STARTED.md) - Setup guide
- [IoTeX Docs](https://docs.iotex.io) - Official documentation
