-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
259 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,77 @@ | ||
# tongen | ||
Ton Wallet v5 vanity address | ||
# TON Wallet Address Finder | ||
|
||
generate custom TON wallet addresses (V5) that end with a specific suffix. | ||
|
||
## Features | ||
- **Multi-threaded**: Utilizes multiple CPU cores to generate wallets in parallel. | ||
- **Custom suffix**: Check if wallet addresses end with a specific string (case-sensitive or case-insensitive). | ||
- **Supports Mainnet/Testnet**: Select the network where the wallets are generated. | ||
- **Bounceable/non-bounceable**: Option to generate bounceable or non-bounceable addresses. | ||
- **Real-time logging**: Logs the number of addresses processed every second. | ||
|
||
## Installation | ||
|
||
1. Ensure you have [Go installed](https://go.dev/doc/install). | ||
2. Clone the repository and navigate to the project directory. | ||
```bash | ||
git clone https://github.com/ariadata/tongen.git | ||
cd tongen | ||
``` | ||
|
||
3. Build the project using the following command: | ||
|
||
```bash | ||
# Linux | ||
CGO_ENABLED=0 go build -o tongen main.go | ||
# Windows | ||
go build -o tongen.exe main.go | ||
``` | ||
You should now have an executable named tongen in your project directory. | ||
### Download Pre-built Binaries [Click Here](https://github.com/ariadata/tongen/releases) | ||
```bash | ||
# Linux | ||
curl -sSfL https://raw.githubusercontent.com/ariadata/tongen/main/build/tongen -o tongen && chmod +x tongen | ||
# Windows | ||
curl -sSfL https://raw.githubusercontent.com/ariadata/tongen/main/build/tongen.exe -o tongen.exe | ||
``` | ||
### Usage | ||
|
||
> `-suffix` (required): The desired suffix that the wallet address should end with. | ||
|
||
> `-case-sensitive` (optional): Enable case-sensitive suffix matching. Defaults to false. | ||
|
||
> `-bounce` (optional): Enable bounceable addresses. Defaults to false. | ||
|
||
> `-threads` (optional): Number of parallel threads. Defaults to 0 (use all CPU cores). | ||
|
||
> `-testnet` (optional): Use the testnet instead of the mainnet. Defaults to false. | ||
|
||
## Examples: | ||
```bash | ||
# Generate a wallet non-bouncable address that ends with "_Neo" (case-sensitive) using all CPU cores on the mainnet | ||
./tongen -suffix="_Neo" -case-sensitive=true -bounce=false -threads=0 -testnet=false | ||
# Generate a wallet bouncable address that ends with "_Test" (not case-insensitive) using 4 threads on testnet | ||
./tongen -suffix="_Test" -case-sensitive=false -bounce=true -threads=4 -testnet=false | ||
``` | ||
|
||
### Example Output: | ||
```bash | ||
2024/10/01 20:00:01 Using 8 threads | ||
2024/10/01 20:00:02 Processed 65 addresses in the last second | ||
2024/10/01 20:00:03 Processed 68 addresses in the last second | ||
=== FOUND === | ||
Seed phrase: "apple banana cherry date elephant ..." | ||
Wallet address: UQDxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx | ||
``` | ||
|
||
----- | ||
|
||
## Contributing | ||
Feel free to submit issues, fork the repository, and make contributions. Pull requests are welcome! | ||
|
||
License | ||
This project is licensed under the MIT License. |
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module github.com/ariadata/tongen | ||
|
||
go 1.22.5 | ||
|
||
require github.com/xssnick/tonutils-go v1.9.9 | ||
|
||
require ( | ||
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a // indirect | ||
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1 // indirect | ||
golang.org/x/crypto v0.26.0 // indirect | ||
golang.org/x/sys v0.24.0 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a h1:dlRvE5fWabOchtH7znfiFCcOvmIYgOeAS5ifBXBlh9Q= | ||
github.com/oasisprotocol/curve25519-voi v0.0.0-20230904125328-1f23a7beb09a/go.mod h1:hVoHR2EVESiICEMbg137etN/Lx+lSrHPTD39Z/uE+2s= | ||
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1 h1:NVK+OqnavpyFmUiKfUMHrpvbCi2VFoWTrcpI7aDaJ2I= | ||
github.com/sigurn/crc16 v0.0.0-20240131213347-83fcde1e29d1/go.mod h1:9/etS5gpQq9BJsJMWg1wpLbfuSnkm8dPF6FdW2JXVhA= | ||
github.com/xssnick/tonutils-go v1.9.9 h1:J0hVJI4LNEFHqgRHzpWTjFuv/Ga89OqLRUc9gxmjCoc= | ||
github.com/xssnick/tonutils-go v1.9.9/go.mod h1:p1l1Bxdv9sz6x2jfbuGQUGJn6g5cqg7xsTp8rBHFoJY= | ||
golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= | ||
golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= | ||
golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= | ||
golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,160 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"fmt" | ||
"log" | ||
"os" | ||
"runtime" | ||
"strings" | ||
"sync" | ||
"sync/atomic" | ||
"time" | ||
|
||
"github.com/xssnick/tonutils-go/ton/wallet" | ||
) | ||
|
||
// Input parameters | ||
type Config struct { | ||
Suffix string | ||
CaseSensitive bool | ||
Bounce bool | ||
Threads int | ||
Testnet bool | ||
} | ||
|
||
func main() { | ||
// Parse input parameters | ||
config := parseFlags() | ||
|
||
// Determine the number of threads (default: use all CPU cores if threads=0) | ||
if config.Threads == 0 { | ||
config.Threads = runtime.NumCPU() | ||
} | ||
log.Printf("Using %d threads\n", config.Threads) | ||
|
||
// Channel to signal when a match is found | ||
stopChan := make(chan struct{}) | ||
|
||
// Use sync.Once to ensure stopChan is closed only once | ||
var once sync.Once | ||
|
||
// Start tracking the number of processed wallets | ||
var counter uint64 | ||
var wg sync.WaitGroup | ||
|
||
// Start logging progress every second | ||
go logProgress(&counter, stopChan) | ||
|
||
// Start wallet generation and processing | ||
for i := 0; i < config.Threads; i++ { | ||
wg.Add(1) | ||
go func() { | ||
defer wg.Done() | ||
processWallets(config, &counter, stopChan, &once) | ||
}() | ||
} | ||
|
||
// Wait for all threads to finish | ||
wg.Wait() | ||
} | ||
|
||
// parseFlags handles command-line input parameters | ||
func parseFlags() Config { | ||
suffix := flag.String("suffix", "", "Desired contract address suffix (required)") | ||
caseSensitive := flag.Bool("case-sensitive", false, "Enable case-sensitive suffix matching (default: false)") | ||
bounce := flag.Bool("bounce", false, "Enable bounceable address (default: false)") | ||
threads := flag.Int("threads", 0, "Number of parallel threads (default: 0, meaning use all CPU cores)") | ||
testnet := flag.Bool("testnet", false, "Use testnet (default: false)") | ||
flag.Parse() | ||
|
||
if *suffix == "" { | ||
flag.PrintDefaults() | ||
os.Exit(1) | ||
} | ||
|
||
return Config{ | ||
Suffix: *suffix, | ||
CaseSensitive: *caseSensitive, | ||
Bounce: *bounce, | ||
Threads: *threads, | ||
Testnet: *testnet, | ||
} | ||
} | ||
|
||
// processWallets generates wallets, checks if the address matches the suffix, and stops on a match | ||
func processWallets(config Config, counter *uint64, stopChan chan struct{}, once *sync.Once) { | ||
for { | ||
select { | ||
case <-stopChan: | ||
return | ||
default: | ||
// Generate the seed phrase | ||
seed := wallet.NewSeed() | ||
|
||
// Create a V5R1Final wallet using the seed | ||
w, err := wallet.FromSeed(nil, seed, wallet.ConfigV5R1Final{ | ||
NetworkGlobalID: getNetworkID(config.Testnet), | ||
Workchain: 0, // Base workchain | ||
}) | ||
if err != nil { | ||
log.Printf("Failed to create wallet: %v", err) | ||
continue | ||
} | ||
|
||
// Get the wallet address | ||
addr := w.WalletAddress() | ||
// Get the address string (mainnet or testnet) and check bounceable flag | ||
addressStr := addr.Testnet(config.Testnet).Bounce(config.Bounce).String() | ||
|
||
// Case-sensitive or case-insensitive suffix comparison | ||
if config.CaseSensitive { | ||
if strings.HasSuffix(addressStr, config.Suffix) { | ||
printFoundWallet(seed, addressStr) | ||
once.Do(func() { close(stopChan) }) | ||
return | ||
} | ||
} else { | ||
if strings.HasSuffix(strings.ToLower(addressStr), strings.ToLower(config.Suffix)) { | ||
printFoundWallet(seed, addressStr) | ||
once.Do(func() { close(stopChan) }) | ||
return | ||
} | ||
} | ||
|
||
// Increment the counter | ||
atomic.AddUint64(counter, 1) | ||
} | ||
} | ||
} | ||
|
||
// logProgress logs how many wallets were processed in the last second | ||
func logProgress(counter *uint64, stopChan chan struct{}) { | ||
var lastCount uint64 | ||
for { | ||
select { | ||
case <-stopChan: | ||
return | ||
case <-time.After(1 * time.Second): | ||
currentCount := atomic.LoadUint64(counter) | ||
processedLastSecond := currentCount - lastCount | ||
lastCount = currentCount | ||
log.Printf("Processed %d addresses in the last second\n", processedLastSecond) | ||
} | ||
} | ||
} | ||
|
||
// getNetworkID returns the correct network ID for mainnet or testnet | ||
func getNetworkID(isTestnet bool) int32 { | ||
if isTestnet { | ||
return -3 // Testnet Global ID | ||
} | ||
return -239 // Mainnet Global ID | ||
} | ||
|
||
// printFoundWallet prints the found seed and wallet address | ||
func printFoundWallet(seed []string, address string) { | ||
fmt.Println("=== FOUND ===") | ||
fmt.Println("Seed phrase:", strings.Join(seed, " ")) | ||
fmt.Println("Wallet address:", address) | ||
} |