hacks/btcphrasechecker/main.go
2026-02-12 12:26:39 -08:00

144 lines
4.0 KiB
Go

package main
import (
"flag"
"fmt"
"os"
"btcphrasechecker/bitcoin"
"btcphrasechecker/types"
"github.com/tyler-smith/go-bip39"
)
const (
defaultAddressCount = 20
)
func main() {
mnemonic := flag.String("mnemonic", "", "BIP39 mnemonic phrase")
passphrase := flag.String("passphrase", "", "Optional passphrase")
addressCount := flag.Int("count", defaultAddressCount, "Number of addresses to check per derivation path")
chain := flag.String("chain", "bitcoin", "Blockchain to analyze (bitcoin)")
flag.Parse()
if *mnemonic == "" {
fmt.Println("Usage: btcphrasechecker -mnemonic \"your mnemonic phrase\" [-passphrase \"optional passphrase\"] [-count 20] [-chain bitcoin]")
os.Exit(1)
}
// Validate mnemonic
if !bip39.IsMnemonicValid(*mnemonic) {
fmt.Println("Error: Invalid mnemonic phrase")
os.Exit(1)
}
// Generate seed from mnemonic
seed := bip39.NewSeed(*mnemonic, *passphrase)
// Analyze based on chain
switch types.Chain(*chain) {
case types.ChainBitcoin:
if err := analyzeBitcoin(seed, *addressCount); err != nil {
fmt.Printf("Error analyzing Bitcoin wallet: %v\n", err)
os.Exit(1)
}
default:
fmt.Printf("Error: Unsupported chain '%s'\n", *chain)
os.Exit(1)
}
}
func analyzeBitcoin(seed []byte, addressCount int) error {
// Perform wallet analysis
summary, err := bitcoin.AnalyzeWallet(seed, addressCount, true)
if err != nil {
return err
}
// Fetch transaction history for active addresses
if len(summary.ActiveAddresses) > 0 {
fmt.Println("Fetching transaction history...")
fmt.Println()
if err := bitcoin.FetchTransactionHistory(summary); err != nil {
return err
}
}
// Display summary
displaySummary(summary)
// Display transaction history
if len(summary.TransactionHistory) > 0 {
displayTransactionHistory(summary)
}
return nil
}
func displaySummary(summary *types.WalletSummary) {
fmt.Println("======================")
fmt.Println("Summary")
fmt.Println("======================")
fmt.Printf("Total Balance: %.8f BTC\n", float64(summary.TotalBalance)/100000000.0)
fmt.Printf("Total Received: %.8f BTC (%d transactions)\n",
float64(summary.TotalReceived)/100000000.0,
summary.ReceiveTxCount)
fmt.Printf("Total Sent: %.8f BTC (%d transactions)\n",
float64(summary.TotalSent)/100000000.0,
summary.SendTxCount)
fmt.Printf("Total Transactions: %d\n", summary.TotalTxCount)
fmt.Printf("Active Addresses: %d\n", len(summary.ActiveAddresses))
fmt.Println()
if len(summary.ActiveAddresses) > 0 {
fmt.Println("Active Addresses Summary:")
fmt.Println("-----------------------------------------------------------")
for _, addr := range summary.ActiveAddresses {
fmt.Printf(" %s\n", addr.Address)
fmt.Printf(" Path: %s\n", addr.Path)
fmt.Printf(" Balance: %.8f BTC\n", float64(addr.Balance)/100000000.0)
fmt.Printf(" Received: %.8f BTC\n", float64(addr.Received)/100000000.0)
fmt.Printf(" Sent: %.8f BTC\n", float64(addr.Sent)/100000000.0)
fmt.Printf(" Txs: %d\n", addr.TxCount)
fmt.Println()
}
}
}
func displayTransactionHistory(summary *types.WalletSummary) {
fmt.Println("======================")
fmt.Println("Transaction History")
fmt.Println("======================")
fmt.Printf("%-20s %-12s %-10s %-15s %-15s %s\n",
"Date", "Type", "Confirmed", "Amount (BTC)", "Balance (BTC)", "TxID")
fmt.Println("---------------------------------------------------------------------------------------------------------------------------")
for _, tx := range summary.TransactionHistory {
dateStr := tx.Time.Format("2006-01-02 15:04:05")
confirmedStr := "No"
if tx.Confirmed {
confirmedStr = "Yes"
}
typeSymbol := ""
switch tx.Type {
case "received":
typeSymbol = "+ Received"
case "sent":
typeSymbol = "- Sent"
case "self":
typeSymbol = "↔ Self"
}
fmt.Printf("%-20s %-12s %-10s %14.8f %14.8f %s\n",
dateStr,
typeSymbol,
confirmedStr,
float64(tx.Amount)/100000000.0,
float64(tx.Balance)/100000000.0,
tx.TxID[:16]+"...")
}
fmt.Println()
}