Skip to content

Commit

Permalink
feat: init
Browse files Browse the repository at this point in the history
  • Loading branch information
mfahriferdiansyah committed Dec 2, 2024
0 parents commit b7c8a02
Show file tree
Hide file tree
Showing 5 changed files with 171 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
*.txt
*.exe
59 changes: 59 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Solana Wallet Generator

A high-performance CLI tool to generate Solana wallets with public keys that match a specified prefix. This tool uses Go's concurrency features for fast parallel processing and writes the matched results (public and private keys) to a `result.txt` file.

## Features
- Generates Solana wallet keypairs (public and private keys).
- Matches public keys against a specified prefix.
- Supports parallel processing with configurable worker threads.
- Saves matched results to a `result.txt` file for later use.

## Requirements
- [Go (Golang)](https://golang.org/dl/) version 1.19 or later.
- Internet connection to install the necessary dependencies.

## Installation

1. Clone the repository:
```
git clone https://github.com/your-username/solana-wallet-generator.git
cd solana-wallet-generator
```
2. Install dependencies:
```
go mod tidy
```
3. Build the executable:
```
go build -o solana-wallet-gen
```
## Usage
Run the program with the desired options:
```
./solana-wallet-gen --prefix <desired-prefix> [--workers <number-of-workers>] [--attempts <max-attempts>]
```
### Options
- `--prefix` (required): The prefix the generated public key should start with.
- `--workers` (optional): Number of concurrent workers (default: 4).
- `--attempts` (optional): Maximum number of attempts per worker (default: unlimited).
### Example
To generate a wallet with a public key starting with `sol`, using 8 workers and up to 1,000,000 attempts per worker:
```
./solana-wallet-gen --prefix "sol" --workers 8 --attempts 1000000
```
### Output
When a match is found:
1. The public and private keys are printed to the terminal.
2. The matched results are saved in the `result.txt` file in the following format:
```
Public Key: solXYZ12345abc...
Private Key: 5TxUHoN123ABCxyz...
```
5 changes: 5 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
module solana-wallet-gen

go 1.23.3

require github.com/mr-tron/base58 v1.2.0
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
103 changes: 103 additions & 0 deletions main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package main

import (
"crypto/ed25519"
"crypto/rand"
"flag"
"fmt"
"os"
"strings"
"sync"
"time"

"github.com/mr-tron/base58"
)

func worker(prefix string, maxAttempts int, result chan<- string, privateKeyChan chan<- string, wg *sync.WaitGroup, id int) {
defer wg.Done()

for attempts := 0; maxAttempts == 0 || attempts < maxAttempts; attempts++ {
publicKey, privateKey := generateKeypair()

if strings.HasPrefix(publicKey, prefix) {
result <- publicKey
privateKeyChan <- privateKey
return
}

if attempts%100000 == 0 && id == 0 {
fmt.Printf("[Worker %d] Attempts: %d\n", id, attempts)
}
}
}

func generateKeypair() (string, string) {
_, privateKey, err := ed25519.GenerateKey(rand.Reader)
if err != nil {
fmt.Println("Error generating keypair:", err)
os.Exit(1)
}

publicKey := privateKey.Public().(ed25519.PublicKey)
return base58.Encode(publicKey), base58.Encode(privateKey)
}

func saveResultToFile(publicKey, privateKey string) {
file, err := os.OpenFile("result.txt", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Println("Error opening result file:", err)
return
}
defer file.Close()

_, err = file.WriteString(fmt.Sprintf("Public Key: %s\nPrivate Key: %s\n\n", publicKey, privateKey))
if err != nil {
fmt.Println("Error writing to result file:", err)
}
}

func main() {
prefix := flag.String("prefix", "", "The prefix to match (required)")
maxAttempts := flag.Int("attempts", 0, "Maximum number of attempts per worker (0 for unlimited)")
workers := flag.Int("workers", 4, "Number of parallel workers")
flag.Parse()

if *prefix == "" {
fmt.Println("Error: --prefix is required")
flag.Usage()
os.Exit(1)
}

fmt.Printf("Searching for wallets starting with: %s\nUsing %d workers...\n", *prefix, *workers)

result := make(chan string, 1)
privateKeyChan := make(chan string, 1)

var wg sync.WaitGroup

start := time.Now()
for i := 0; i < *workers; i++ {
wg.Add(1)
go worker(*prefix, *maxAttempts, result, privateKeyChan, &wg, i)
}

go func() {
wg.Wait()
close(result)
close(privateKeyChan)
}()

select {
case publicKey := <-result:
privateKey := <-privateKeyChan
fmt.Printf("Match found!\n")
fmt.Printf("Public Key: %s\n", publicKey)
fmt.Printf("Private Key: %s\n", privateKey)
fmt.Printf("Elapsed Time: %s\n", time.Since(start))

saveResultToFile(publicKey, privateKey)
case <-time.After(time.Hour * 24):
fmt.Println("Timeout reached. No match found.")
}
}

0 comments on commit b7c8a02

Please sign in to comment.