Create and Manage Wallets
This tutorial covers creating, securing, and managing ACDC wallets using both the CLI and SDK.
Overview
ACDC wallets support both chains:
| Chain | Address Prefix | Model |
|---|---|---|
| Alpha | ax1 | UTXO/Record (privacy) |
| Delta | dx1 | Account-based |
A single mnemonic generates addresses for both chains.
Using the CLI
Create a New Wallet
# Generate new wallet
acdc wallet create
# Output:
# Wallet created successfully!
#
# Mnemonic (SAVE THIS SECURELY):
# abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about
#
# Alpha Address: ax1qz3k7m8n9p0r2s4t6v8w0x2y4z6a8c0e2g4i6k8m
# Delta Address: dx1abc123def456ghi789jkl012mno345pqr678stu
danger
Save your mnemonic phrase securely. Anyone with your mnemonic has full access to your funds. Never share it, never store it digitally in plain text.
Create with Password Protection
# Create with password-encrypted keystore
acdc wallet create --keystore ~/.acdc/wallet.json
# You'll be prompted:
# Enter password: ********
# Confirm password: ********
#
# Keystore saved to ~/.acdc/wallet.json
Import Existing Wallet
# Import from mnemonic
acdc wallet import
# You'll be prompted:
# Enter mnemonic: <your 12 or 24 word phrase>
#
# Wallet imported successfully!
# Import with keystore
acdc wallet import --keystore ~/.acdc/wallet.json
List Wallets
# List all wallets
acdc wallet list
# Output:
# Wallets:
# 1. dx1abc123... (default)
# 2. dx1def456...
Set Default Wallet
# Set default wallet by address
acdc wallet default dx1def456...
# Or by index
acdc wallet default 2
Using the TypeScript SDK
Generate New Wallet
import { Wallet } from '@acdc/sdk';
// Generate with random entropy
const wallet = Wallet.create();
console.log('Mnemonic:', wallet.mnemonic);
console.log('Delta Address:', wallet.address);
console.log('Alpha Address:', wallet.alphaAddress);
console.log('Private Key:', wallet.privateKey);
// Generate with specific word count
const wallet24 = Wallet.create({ wordCount: 24 });
Import from Mnemonic
import { Wallet } from '@acdc/sdk';
const mnemonic = 'abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about';
// Default derivation path
const wallet = Wallet.fromMnemonic(mnemonic);
// Custom derivation path
const customWallet = Wallet.fromMnemonic(mnemonic, {
path: "m/44'/60'/0'/0/5" // Account index 5
});
console.log('Address:', wallet.address);
Import from Private Key
import { Wallet } from '@acdc/sdk';
const privateKey = '0x...'; // 64 hex characters
const wallet = Wallet.fromPrivateKey(privateKey);
console.log('Address:', wallet.address);
HD Wallet (Multiple Accounts)
import { HDWallet } from '@acdc/sdk';
// Create HD wallet
const hdWallet = HDWallet.fromMnemonic(
'abandon abandon abandon ...'
);
// Derive multiple accounts
const accounts = [];
for (let i = 0; i < 5; i++) {
const account = hdWallet.derive(i);
accounts.push({
index: i,
address: account.address,
privateKey: account.privateKey
});
}
console.log('Accounts:');
accounts.forEach(acc => {
console.log(` ${acc.index}: ${acc.address}`);
});
Encrypt/Decrypt Keystore
import { Wallet, Keystore } from '@acdc/sdk';
const wallet = Wallet.create();
// Encrypt to keystore
const password = 'secure-password';
const keystore = await Keystore.encrypt(wallet.privateKey, password);
// Save to file
const fs = require('fs');
fs.writeFileSync('wallet.json', JSON.stringify(keystore, null, 2));
// Later: decrypt from keystore
const loaded = JSON.parse(fs.readFileSync('wallet.json', 'utf8'));
const decrypted = await Keystore.decrypt(loaded, password);
const restoredWallet = Wallet.fromPrivateKey(decrypted);
console.log('Restored:', restoredWallet.address);
Using the Rust SDK
Generate New Wallet
use acdc_sdk::{Wallet, Mnemonic};
// Generate new wallet
let wallet = Wallet::generate()?;
println!("Mnemonic: {}", wallet.mnemonic().unwrap());
println!("Address: {}", wallet.address());
println!("Private Key: 0x{}", hex::encode(wallet.private_key()));
// Generate with 24 words
let wallet24 = Wallet::generate_with_word_count(24)?;
Import from Mnemonic
use acdc_sdk::{Wallet, Mnemonic};
let phrase = "abandon abandon abandon ...";
let mnemonic = Mnemonic::parse(phrase)?;
// Default derivation
let wallet = Wallet::from_mnemonic(&mnemonic, None)?;
// Custom path
let custom = Wallet::from_mnemonic(&mnemonic, Some("m/44'/60'/0'/0/5"))?;
println!("Address: {}", wallet.address());
HD Wallet
use acdc_sdk::{HDWallet, Mnemonic};
let mnemonic = Mnemonic::parse("abandon abandon ...")?;
let hd = HDWallet::from_mnemonic(&mnemonic)?;
// Derive accounts
for i in 0..5 {
let account = hd.derive(i)?;
println!("Account {}: {}", i, account.address());
}
Wallet Security Best Practices
Mnemonic Storage
Do:
- Write on paper, store in secure location
- Use a hardware wallet for large amounts
- Split mnemonic using Shamir's Secret Sharing
Do Not:
- Store in cloud storage (Google Drive, iCloud, etc.)
- Take screenshots
- Store in plain text files
- Share with anyone
Keystore Files
Do:
- Use strong, unique passwords (20+ characters)
- Store keystore on encrypted drives
- Keep backups in multiple secure locations
Do Not:
- Use simple passwords
- Store password with keystore
- Share keystore files
Development vs Production
// Development: OK to use environment variables
const wallet = Wallet.fromPrivateKey(process.env.DEV_PRIVATE_KEY);
// Production: Use secure key management
import { KMS } from '@acdc/sdk';
const kms = new KMS({
provider: 'aws', // or 'gcp', 'azure', 'vault'
keyId: 'arn:aws:kms:...'
});
const signer = await kms.getSigner();
Multi-Signature Wallets
For enhanced security, use multi-signature wallets:
import { MultiSigWallet } from '@acdc/sdk';
// Create 2-of-3 multisig
const multisig = await MultiSigWallet.create({
owners: [
'dx1owner1...',
'dx1owner2...',
'dx1owner3...'
],
threshold: 2
});
console.log('Multisig address:', multisig.address);
// Create transaction proposal
const proposal = await multisig.proposeTransaction({
to: 'dx1recipient...',
value: parseUnits('10', 18)
});
// Each owner signs
const sig1 = await owner1Wallet.signMultisigProposal(proposal);
const sig2 = await owner2Wallet.signMultisigProposal(proposal);
// Execute with enough signatures
const tx = await multisig.executeTransaction(proposal, [sig1, sig2]);
await tx.wait();
View Keys (Alpha Chain)
For privacy-preserving balance viewing without spending ability:
import { AlphaWallet, ViewKey } from '@acdc/sdk';
const wallet = AlphaWallet.create();
// Derive view key (can see balances, cannot spend)
const viewKey = wallet.deriveViewKey();
console.log('View Key:', viewKey.toString());
// Share view key with auditors/accountants
// They can scan for your records but cannot spend
Address Validation
import { isValidAddress, getAddressChain } from '@acdc/sdk';
// Validate address format
console.log(isValidAddress('dx1abc...')); // true
console.log(isValidAddress('invalid')); // false
// Get chain from address
console.log(getAddressChain('dx1abc...')); // 'delta'
console.log(getAddressChain('ax1xyz...')); // 'alpha'
// Validate and get info
import { Address } from '@acdc/sdk';
try {
const addr = new Address('dx1abc...');
console.log('Chain:', addr.chain);
console.log('Checksum:', addr.toChecksum());
} catch (e) {
console.log('Invalid address');
}
Wallet Recovery
From Mnemonic
acdc wallet recover
# Enter your 12 or 24 word mnemonic phrase:
# > abandon abandon abandon ...
# Wallet recovered successfully!
# Alpha Address: ax1...
# Delta Address: dx1...
From Keystore
acdc wallet recover --keystore wallet.json
# Enter keystore password:
# > ********
# Wallet recovered successfully!
Complete Example
Here is a complete wallet management script:
// wallet-manager.ts
import { Wallet, HDWallet, Keystore } from '@acdc/sdk';
import * as fs from 'fs';
import * as readline from 'readline';
const KEYSTORE_PATH = './wallets';
async function prompt(question: string): Promise<string> {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});
return new Promise(resolve => {
rl.question(question, answer => {
rl.close();
resolve(answer);
});
});
}
async function createWallet() {
const wallet = Wallet.create();
console.log('\nNew Wallet Created!');
console.log('==================');
console.log('Mnemonic:', wallet.mnemonic);
console.log('Delta Address:', wallet.address);
console.log('Alpha Address:', wallet.alphaAddress);
const save = await prompt('\nSave to keystore? (y/n): ');
if (save.toLowerCase() === 'y') {
const password = await prompt('Enter password: ');
const keystore = await Keystore.encrypt(wallet.privateKey, password);
if (!fs.existsSync(KEYSTORE_PATH)) {
fs.mkdirSync(KEYSTORE_PATH);
}
const filename = `${KEYSTORE_PATH}/${wallet.address}.json`;
fs.writeFileSync(filename, JSON.stringify(keystore, null, 2));
console.log(`Saved to ${filename}`);
}
}
async function listWallets() {
if (!fs.existsSync(KEYSTORE_PATH)) {
console.log('No wallets found');
return;
}
const files = fs.readdirSync(KEYSTORE_PATH);
console.log('\nWallets:');
files.forEach((file, i) => {
console.log(` ${i + 1}. ${file.replace('.json', '')}`);
});
}
async function loadWallet() {
const address = await prompt('Enter wallet address: ');
const password = await prompt('Enter password: ');
const filename = `${KEYSTORE_PATH}/${address}.json`;
const keystore = JSON.parse(fs.readFileSync(filename, 'utf8'));
const privateKey = await Keystore.decrypt(keystore, password);
const wallet = Wallet.fromPrivateKey(privateKey);
console.log('\nWallet loaded successfully!');
console.log('Address:', wallet.address);
return wallet;
}
// Main menu
async function main() {
while (true) {
console.log('\nWallet Manager');
console.log('1. Create new wallet');
console.log('2. List wallets');
console.log('3. Load wallet');
console.log('4. Exit');
const choice = await prompt('Choose option: ');
switch (choice) {
case '1': await createWallet(); break;
case '2': await listWallets(); break;
case '3': await loadWallet(); break;
case '4': process.exit(0);
default: console.log('Invalid option');
}
}
}
main().catch(console.error);
Next Steps
- Send Your First Transaction - Use your wallet
- Deploy an ADL Contract - Deploy contracts
- TypeScript SDK Guide - Full SDK reference