接上篇我们创建以太坊钱包
钱包创建好,最基础的功能那就是查询钱包余额和转账了。
以太坊有几个网络可以供我们开发测使用。我们使用ropsten作为测试网络。
下面我们需要几步创建自己的测试钱包。
这样自己测试账号里 就可以看到余额,可以调用web3j的方法,去进行操作了。
ps:我测试代码是拿kotlin来写,其中的api调用涉及耗时操作,依赖了rxjava 使用其操作符来处理
HttpService的创建需要传入一个url,就是请求的服务器地址,我们去https://infura.io/dashboard 注册一下账号,拿到我们需要的url
- 查看=以太坊版本信息
val web3j =
Web3j.build(HttpService("https://ropsten.infura.io/v3/eebd564220cc400cad3a0167c3edd0c7")) // defaults to http://localhost:8545/
val version = Single.fromCallable { web3j.ethProtocolVersion().send().protocolVersion }
.subscribeOn(
Schedulers.io()
).observeOn(AndroidSchedulers.mainThread())
version.subscribe(object : SingleObserver<String> {
override fun onSubscribe(d: Disposable) {
}
override fun onSuccess(o: String) {
println("请求成功版本+++++$o")
}
override fun onError(e: Throwable) {
println("请求版本异常+++++$e")
}
})
}
对请求做一下,封装处理
初始化web3j对象,传入自己的okhttp请求,格式化日志输出
object Web3jUtil {
fun initWeb3j(url: String? = "https://ropsten.infura.io/v3/eebd564220cc400cad3a0167c3edd0c7"): Web3j {
return Web3j.build(HttpService(url, createOkHttpClient(), false))
}
private fun createOkHttpClient(): OkHttpClient {
val builder = OkHttpClient.Builder()
builder.writeTimeout((30 * 1000).toLong(), TimeUnit.SECONDS)
.connectTimeout((30 * 1000).toLong(), TimeUnit.SECONDS)
configureLogging(builder)
return builder.build()
}
private fun configureLogging(builder: OkHttpClient.Builder) {
val logging = HttpLoggingInterceptor(
HttpLoggingInterceptor.Logger { msg -> Log.i("TAG", "+++log: $msg") })
logging.level = HttpLoggingInterceptor.Level.BODY
builder.addInterceptor(logging)
}
}
查询余额,转账处理的请求
object EthService {
/**
* 获取以太坊余额
*/
fun getEthBalance(address: String): Single<BigInteger> {
return Single.fromCallable {
Web3jUtil.initWeb3j()
.ethGetBalance(address, DefaultBlockParameterName.LATEST)
.send()
.balance
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
/**
* 以太坊转账
*/
@SuppressLint("CheckResult")
fun ethTransfer(
toAddress: String,
keypair: ECKeyPair
): Single<TransactionReceipt> {
val credentials = Credentials.create(keypair)
return Single.fromCallable {
Transfer.sendFunds(
Web3jUtil.initWeb3j(),
credentials,
toAddress,
BigDecimal.valueOf(1),
Convert.Unit.ETHER
)
.send()
}.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}
/**
* 以太坊转账
* nonce:当前账户下有效的随机数 用来唯一地标识交易。一个nonce只能使用一次,直到交易被挖掘完成
* gasPrice:挖矿中用到的gas对eth的价格。好比汽油价格。
* gasLimit:针对本次交易所使用的最大gas数量
* to:转入的地址
* value:转入的ETH数量
* data:进行合约调用的时使用
*
*/
@SuppressLint("CheckResult")
fun ethTransferCustom(
fromAddress: String,
toAddress: String,
keypair: ECKeyPair,
amount: String
): Single<EthSendTransaction> {
val credentials = Credentials.create(keypair)
val web3j = Web3jUtil.initWeb3j()
val single = Single.fromCallable {
web3j
.ethGetTransactionCount(fromAddress, DefaultBlockParameterName.LATEST)
.send()
}.flatMap { transactionCount ->
val nonce = transactionCount.transactionCount
//创建交易对象
val gasPrice = Convert.toWei("18", Convert.Unit.GWEI).toBigInteger()
val gasLimit = Convert.toWei("450000", Convert.Unit.WEI).toBigInteger()
val value = Convert.toWei(amount, Convert.Unit.ETHER).toBigInteger()
val rawTransaction = RawTransaction.createEtherTransaction(
nonce, gasPrice, gasLimit, toAddress, value
)
val signMessage = TransactionEncoder.signMessage(rawTransaction, credentials)
val hexValue = Numeric.toHexString(signMessage)
Single.fromCallable {
web3j.ethSendRawTransaction(hexValue).send()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
}.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
return single
}
下面是页面中的调用
/**
* 获取余额
*/
private fun getBalance() {
val address = "0x8d2CCC9f30E530197871f13C8811f506CA7750A7"
val balance = EthService.getEthBalance(address)
balance.subscribe(object : SingleObserver<BigInteger> {
override fun onSubscribe(d: Disposable) {
}
override fun onSuccess(bigInteger: BigInteger) {
val decimal = Convert.fromWei(bigInteger.toString(), Convert.Unit.ETHER)
tvBalance.text = decimal.toString()
println("请求成功+++++$decimal")
}
override fun onError(e: Throwable) {
println("请求异常+++++$e")
}
})
}
/**
* 简单使用Transfer转账
*/
private fun transfer(toAddress: String) {
val wallet = GlobalInstance.instance.wallet
val transfer = EthService.ethTransfer(toAddress, wallet?.keyPair!!)
transfer.subscribe(object : SingleObserver<TransactionReceipt> {
override fun onSuccess(t: TransactionReceipt) {
println("转账成功+++++${t.blockHash}")
getBalance()
}
override fun onSubscribe(d: Disposable) {
}
override fun onError(e: Throwable) {
println("转账失败+++++$e")
}
})
}
/**
* 自定义转账
*/
private fun transferCustom(toAddress: String) {
val wallet = GlobalInstance.instance.wallet
val transferCustom = EthService.ethTransferCustom(wallet?.address!!,toAddress, wallet.keyPair, "1")
transferCustom.subscribe(object : SingleObserver<EthSendTransaction> {
override fun onSuccess(t: EthSendTransaction) {
if (t.hasError()) {
println("自定义转账失败+++++${t.error.message}")
} else {
println("自定义转账成功+++++${t.transactionHash}")
}
}
override fun onSubscribe(d: Disposable) {
}
override fun onError(e: Throwable) {
println("自定义转账失败+++++$e")
}
})
}