ETH和TRX靓号生成器的Android应用。
1. 项目配置 (app/build.gradle)
plugins {
id 'com.android.application'
id 'kotlin-android'
}
android {
compileSdk 34
defaultConfig {
applicationId "com.example.walletaddressgenerator"
minSdk 21
targetSdk 34
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
buildFeatures {
viewBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'com.google.android.material:material:1.10.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'org.web3j:core:4.9.7'
implementation 'org.tronj:tronj-core:2.1.4'
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.7.0'
implementation 'androidx.activity:activity-ktx:1.8.1'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
}
2. 主界面布局 (res/layout/activity_main.xml)
<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:background="#f5f5f5">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- 标题 -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="ETH/TRX靓号生成器"
android:textSize="24sp"
android:textStyle="bold"
android:textColor="#333333"
android:gravity="center"
android:layout_marginBottom="32dp" />
<!-- 币种选择 -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardCornerRadius="12dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="选择币种"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="12dp" />
<RadioGroup
android:id="@+id/radioGroup"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioEth"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="ETH"
android:checked="true" />
<RadioButton
android:id="@+id/radioTrx"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="TRX" />
</RadioGroup>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- 靓号规则设置 -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardCornerRadius="12dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="靓号规则设置"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="12dp" />
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:boxCornerRadiusBottomEnd="8dp"
app:boxCornerRadiusBottomStart="8dp"
app:boxCornerRadiusTopEnd="8dp"
app:boxCornerRadiusTopStart="8dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etPrefix"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="地址前缀 (如: 0x888)"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="16dp"
app:boxCornerRadiusBottomEnd="8dp"
app:boxCornerRadiusBottomStart="8dp"
app:boxCornerRadiusTopEnd="8dp"
app:boxCornerRadiusTopStart="8dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etSuffix"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="地址后缀 (如: 888)"
android:maxLines="1" />
</com.google.android.material.textfield.TextInputLayout>
<com.google.android.material.textfield.TextInputLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:boxCornerRadiusBottomEnd="8dp"
app:boxCornerRadiusBottomStart="8dp"
app:boxCornerRadiusTopEnd="8dp"
app:boxCornerRadiusTopStart="8dp">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/etCount"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="生成数量 (默认: 10)"
android:inputType="number"
android:maxLines="1"
android:text="10" />
</com.google.android.material.textfield.TextInputLayout>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- 控制按钮 -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="24dp"
app:cardCornerRadius="12dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:padding="16dp">
<Button
android:id="@+id/btnGenerate"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginEnd="8dp"
android:text="开始生成"
android:backgroundTint="#4CAF50"
android:textColor="@android:color/white"
style="@style/Widget.Material3.Button" />
<Button
android:id="@+id/btnStop"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:layout_marginStart="8dp"
android:text="停止生成"
android:backgroundTint="#F44336"
android:textColor="@android:color/white"
style="@style/Widget.Material3.Button" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<!-- 生成结果 -->
<com.google.android.material.card.MaterialCardView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="12dp"
app:cardElevation="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="生成结果"
android:textSize="16sp"
android:textStyle="bold"
android:layout_marginBottom="12dp" />
<TextView
android:id="@+id/tvStatus"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="准备就绪"
android:textSize="14sp"
android:layout_marginBottom="16dp"
android:textColor="#666666" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="400dp"
android:background="#fafafa" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
</LinearLayout>
</ScrollView>
3. 列表项布局 (res/layout/item_address.xml)
<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="8dp"
app:cardCornerRadius="8dp"
app:cardElevation="2dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:padding="16dp">
<TextView
android:id="@+id/tvAddress"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="地址"
android:textSize="14sp"
android:textStyle="bold"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/tvPrivateKey"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="私钥"
android:textSize="12sp"
android:textColor="#666666"
android:layout_marginBottom="8dp" />
<TextView
android:id="@+id/tvIndex"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="序号"
android:textSize="12sp"
android:textColor="#999999" />
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
4. 数据模型 (AddressInfo.kt)
data class AddressInfo(
val index: Int,
val address: String,
val privateKey: String,
val coinType: String
)
5. 适配器 (AddressAdapter.kt)
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
class AddressAdapter : RecyclerView.Adapter<AddressAdapter.ViewHolder>() {
private val addresses = mutableListOf<AddressInfo>()
class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
val tvIndex: TextView = itemView.findViewById(R.id.tvIndex)
val tvAddress: TextView = itemView.findViewById(R.id.tvAddress)
val tvPrivateKey: TextView = itemView.findViewById(R.id.tvPrivateKey)
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context)
.inflate(R.layout.item_address, parent, false)
return ViewHolder(view)
}
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val addressInfo = addresses[position]
holder.tvIndex.text = "序号: ${addressInfo.index}"
holder.tvAddress.text = "地址: ${addressInfo.address}"
holder.tvPrivateKey.text = "私钥: ${addressInfo.privateKey}"
}
override fun getItemCount(): Int = addresses.size
fun addAddress(addressInfo: AddressInfo) {
addresses.add(0, addressInfo) // 添加到开头
notifyItemInserted(0)
}
fun clearAddresses() {
addresses.clear()
notifyDataSetChanged()
}
}
6. 钱包生成工具 (WalletGenerator.kt)
import org.web3j.crypto.ECKeyPair
import org.web3j.crypto.Keys
import org.web3j.utils.Numeric
import java.math.BigInteger
import java.security.SecureRandom
object WalletGenerator {
private val secureRandom = SecureRandom()
// 生成ETH钱包
fun generateEthWallet(): Pair<String, String> {
val ecKeyPair = Keys.createEcKeyPair()
val publicKey = "0x" + Keys.getAddress(ecKeyPair)
val privateKey = ecKeyPair.privateKey.toString(16)
return Pair(publicKey, privateKey)
}
// 生成TRX钱包 (简化版,实际TRX地址生成更复杂)
fun generateTrxWallet(): Pair<String, String> {
// TRX地址生成逻辑 (这里使用简化的实现)
val ecKeyPair = Keys.createEcKeyPair()
val publicKey = "T" + Keys.getAddress(ecKeyPair).substring(2) // 模拟TRX地址格式
val privateKey = ecKeyPair.privateKey.toString(16)
return Pair(publicKey, privateKey)
}
// 检查地址是否符合靓号规则
fun isVanityAddress(address: String, prefix: String?, suffix: String?): Boolean {
var matches = true
if (!prefix.isNullOrEmpty()) {
matches = matches && address.startsWith(prefix, ignoreCase = true)
}
if (!suffix.isNullOrEmpty()) {
matches = matches && address.endsWith(suffix, ignoreCase = true)
}
return matches
}
}
7. 主Activity (MainActivity.kt)
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.Button
import android.widget.RadioGroup
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.textfield.TextInputEditText
import kotlinx.coroutines.*
class MainActivity : AppCompatActivity() {
private lateinit var radioGroup: RadioGroup
private lateinit var etPrefix: TextInputEditText
private lateinit var etSuffix: TextInputEditText
private lateinit var etCount: TextInputEditText
private lateinit var btnGenerate: Button
private lateinit var btnStop: Button
private lateinit var tvStatus: TextView
private lateinit var recyclerView: RecyclerView
private lateinit var adapter: AddressAdapter
private var isGenerating = false
private var generatedCount = 0
private var targetCount = 10
private var totalTried = 0L
private val handler = Handler(Looper.getMainLooper())
private var generationJob: Job? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initViews()
setupRecyclerView()
setupClickListeners()
}
private fun initViews() {
radioGroup = findViewById(R.id.radioGroup)
etPrefix = findViewById(R.id.etPrefix)
etSuffix = findViewById(R.id.etSuffix)
etCount = findViewById(R.id.etCount)
btnGenerate = findViewById(R.id.btnGenerate)
btnStop = findViewById(R.id.btnStop)
tvStatus = findViewById(R.id.tvStatus)
recyclerView = findViewById(R.id.recyclerView)
}
private fun setupRecyclerView() {
adapter = AddressAdapter()
recyclerView.layoutManager = LinearLayoutManager(this)
recyclerView.adapter = adapter
}
private fun setupClickListeners() {
btnGenerate.setOnClickListener {
startGeneration()
}
btnStop.setOnClickListener {
stopGeneration()
}
}
private fun startGeneration() {
if (isGenerating) return
val countText = etCount.text.toString()
targetCount = if (countText.isNotEmpty()) countText.toInt() else 10
if (targetCount <= 0) targetCount = 10
generatedCount = 0
totalTried = 0L
adapter.clearAddresses()
isGenerating = true
updateStatus()
generationJob = CoroutineScope(Dispatchers.Default).launch {
generateAddresses()
}
}
private fun stopGeneration() {
isGenerating = false
generationJob?.cancel()
updateStatus()
}
private suspend fun generateAddresses() {
val prefix = etPrefix.text?.toString()?.trim()
val suffix = etSuffix.text?.toString()?.trim()
val isEth = radioGroup.checkedRadioButtonId == R.id.radioEth
while (isGenerating && generatedCount < targetCount) {
totalTried++
val (address, privateKey) = if (isEth) {
WalletGenerator.generateEthWallet()
} else {
WalletGenerator.generateTrxWallet()
}
if (WalletGenerator.isVanityAddress(address, prefix, suffix)) {
generatedCount++
val addressInfo = AddressInfo(
index = generatedCount,
address = address,
privateKey = privateKey,
coinType = if (isEth) "ETH" else "TRX"
)
withContext(Dispatchers.Main) {
adapter.addAddress(addressInfo)
updateStatus()
}
// 短暂延迟,避免UI更新过快
delay(10)
}
// 每1000次尝试更新一次状态
if (totalTried % 1000 == 0L) {
withContext(Dispatchers.Main) {
updateStatus()
}
}
}
withContext(Dispatchers.Main) {
isGenerating = false
updateStatus()
}
}
private fun updateStatus() {
val coinType = if (radioGroup.checkedRadioButtonId == R.id.radioEth) "ETH" else "TRX"
val prefix = etPrefix.text?.toString()?.trim() ?: "无"
val suffix = etSuffix.text?.toString()?.trim() ?: "无"
val status = if (isGenerating) {
"正在生成 $coinType 靓号...\n" +
"规则: 前缀=$prefix, 后缀=$suffix\n" +
"进度: $generatedCount/$targetCount\n" +
"尝试次数: $totalTried"
} else {
if (generatedCount > 0) {
"生成完成!找到 $generatedCount 个符合条件的 $coinType 地址\n" +
"总尝试次数: $totalTried"
} else {
"准备就绪\n规则: 前缀=$prefix, 后缀=$suffix"
}
}
tvStatus.text = status
}
override fun onDestroy() {
super.onDestroy()
stopGeneration()
}
}
8. AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/Theme.Material3.Light"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
9. 颜色资源 (res/values/colors.xml)
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>
10. 主题资源 (res/values/themes.xml)
<resources xmlns:tools="http://schemas.android.com/tools">
<style name="Base.Theme.WalletAddressGenerator" parent="Theme.Material3.Light">
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
</style>
<style name="Theme.WalletAddressGenerator" parent="Base.Theme.WalletAddressGenerator" />
</resources>
使用说明:
-
功能特点:
- 支持ETH和TRX靓号生成
- 可自定义地址前缀和后缀
- 实时显示生成进度和统计信息
- 显示生成的地址和对应私钥
- 支持停止生成操作
-
使用方法:
- 选择币种(ETH或TRX)
- 设置靓号规则(前缀、后缀)
- 设置生成数量
- 点击"开始生成"按钮
- 查看生成结果
-
注意事项:
- 生成的私钥请妥善保管
- 复杂的靓号规则可能需要较长的生成时间
- 实际TRX地址生成可能需要更复杂的逻辑