Android 以太坊钱包转账及余额查询

接上篇我们创建以太坊钱包
钱包创建好,最基础的功能那就是查询钱包余额和转账了。

准备工作

以太坊有几个网络可以供我们开发测使用。我们使用ropsten作为测试网络。

下面我们需要几步创建自己的测试钱包。

  1. Chrome浏览器 安装metamask插件,创建钱包,选择Ropsten测试网络
    Android 以太坊钱包转账及余额查询_第1张图片
  2. 通过水龙头网站 向自己测试钱包转账https://faucet.metamask.io/
    Android 以太坊钱包转账及余额查询_第2张图片
    https://ropsten.etherscan.io/可以通过地址查询交易记录

这样自己测试账号里 就可以看到余额,可以调用web3j的方法,去进行操作了。

ps:我测试代码是拿kotlin来写,其中的api调用涉及耗时操作,依赖了rxjava 使用其操作符来处理

HttpService的创建需要传入一个url,就是请求的服务器地址,我们去https://infura.io/dashboard 注册一下账号,拿到我们需要的url
Android 以太坊钱包转账及余额查询_第3张图片

  • 查看=以太坊版本信息
        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")
            }

        })
    }

你可能感兴趣的:(区块链,android)