从广义上讲,有web3j支持三种类型的以太坊交易:

1.以太币从一方交易到另一方

2.创建一个智能合约

3.与智能合约交易

为了进行这些交易,必须有以太币(以太坊区块链的代币)存在于交易发生的以太坊账户中。这是为了支付gas成本,这是为支付参与交易的以太坊客户端的交易执行成本,支付了这个成本就能将结果提交到以太坊区块链上。获得以太币的说明下文会说到。

此外,我们还可以查询智能合约的状态。

如何获得以太币Ether

要想获得以太币Ether你有两种途径可以选择:

1.自己开采挖矿

2.从别人那里获取以太币

在私有链中自己挖矿,或者公共测试链(testnet)是非常简单直接的。但是,在主要的公有链(mainnet)中,它需要很多很明显的专用GPU时间,除非你已经拥有多个专用GPU的矿机,否则基本上不太可行。如果你希望使用私有链,则在这个官方文档中有一些指导。

要购买以太币Ether,你需要通过交易所。由于不同的地区有不同的交易所,你还需要研究自己去哪儿合适。官方文档中包含多个交易所,是一个很好的参考。

以太坊测试链(testnets)

针对Ethereum以太坊有许多专用测试网络或者叫测试链,他们由各种客户端支持。

1.Rinkeby:只支持geth客户端。

2.Kovan:只支持Parity客户端。

3.Ropsten:支持geth和Parity客户端。

对于开发,建议你使用Rinkeby或KoVan测试链。这是因为他们使用的工作量证明POA共识机制,确保交易和块能够一致并及时的创建。Ropsten测试链,虽然最接近公有链(Mainnet),但是因为它使用的工作量证明是POW共识机制,过去已受到攻击,对以太坊开发人员来说往往有更多的问题。

你可以通过Rinkeby测试链的Rinkeby Crypto Fauce请求以太坊币,具体怎么做可以看这里https://www.rinkeby.io/。

有关如何请求Kovan测试链的细节可以在这里找到。

如果你需要在Ropsten上的得到一些以太币,将你的钱包地址的消息发布到web3j gitter channel,然后会发送一些给你。

在testnet测试链或者私有链上挖掘

在ethereum以太坊测试链testnet中,挖掘难度低于公有链mainnet。这意味着你可以用普通的CPU,比如你的笔记本电脑来挖掘新的以太币。你需要做的是运行一个以太坊客户端,例如geth或Parity,开始做一些储备。进一步的资料可在他们的官方网站上获得。

一旦你开采了一些以太币,你就可以开始使用以太坊区块链了。

然而,如上所述,使用Kovan或者Rinkeby测试网络更简单些。

gas

当在Ethereum以太坊发生交易时,必须为执行该交易的客户端支付交易成本,将该交易的输出提交到以太坊区块链Ethereum blockchain。

此成本是通过gas来测量的,其中gas是用于在以太坊虚拟机中执行交易指令的数量。请参阅官方文档以获取更多信息。

当你使用以太坊客户端时,这意味着,有两个参数用来指示你希望花费多少以太来完成传输:

gas price :气体价格,这是每单位gas中以太的消耗量。Web3j使用的默认价格为22000000000 wei(22×10-8 Ether)。这是在交易管理中定义的。

gas limit:气体最大量,这是你愿意在交易执行上花费的gas的最大总量。单个交易在一个以太坊区块中有多大的上限,通常将该值限制为小于6700000。当前的gas限制在这里查https://ethstats.net/。

这两个参数共同决定了你愿意花费在交易成本上的最大量的以太币Ether。也就是说,你花费的gas不会超过gas price * gas limit。gas价格也会影响交易发生的速度,这取决于其他交易是否能为矿工提供更有利的gas价格。

你可能需要调整这些参数以确保交易能及时进行。

交易机制

当你用一些以太币Ether创建了一个有效的帐户时,你可以使用两种机制来与以太坊进行交易。

通过以太坊ethereum客户端进行认证签名交易

离线交易签名认证

这两种机制都是Web3j所支持的。

通过以太坊ethereum客户端进行认证签名交易

为了通过以太坊客户端进行交易,首先需要确保你正在使用的客户端知道你的钱包地址。最好是运行自己的以太坊客户端,比如geth/Parity,以便可以更方便的做到这一点。一旦你有一个客户端运行,你可以创建一个以太坊钱包,通过:

geth Wiki包含了geth支持的良好运行的不同机制,例如导入私有密钥文件,并通过控制台创建新的以太坊帐户。

或者,你可以通过客户端使用JSON-RPC管理命令,例如用personal_newAccount为geth/Parity创建新以太坊账户。

通过创建你的钱包文件,你可以通过web3j打开帐户,首先创建支持geth/Parity管理命令的web3j实例:

Admin web3j = Admin.build(new HttpService());

然后,你可以解锁帐户,并如果是成功的,就可以发送一个交易:

PersonalUnlockAccount personalUnlockAccount = web3j.personalUnlockAccount("0x000...", "a password").send();

if (personalUnlockAccount.accountUnlocked()) {

// send a transaction

}

Transaction transaction = Transaction.createContractTransaction(

,

,

BigInteger.valueOf(), // we use default gas limit

"0x..."

);

org.web3j.protocol.core.methods.response.EthSendTransaction

transactionResponse = parity.ethSendTransaction(ethSendTransaction)

.send();

String transactionHash = transactionResponse.getTransactionHash();

// poll for transaction response via org.web3j.protocol.Web3j.ethGetTransactionReceipt()

其中nonce值获得方式,下文会提到。 有关此交易工作流的详细信息,请参阅DeployContractIT和Scenario。

web3j支持的各种管理命令的进一步细节在Management APIs中。

离线交易签名认证Offline transaction signing

如果你不想管理自己的以太坊客户端,或者不想向以太坊客户端提供诸如密码之类的钱包详细信息,那么就通过离线交易认证签名。

离线交易签名认证允许你在web3j中使用你的以太坊钱包签署交易,允许你完全控制你的私有凭据。然后,离线创建的交易可以被发送到网络上的任何以太坊客户端,只要它是一个有效的交易,它会将交易传播到其他节点。

如果需要,还可以执行进程外交易签名认证。这可以通过重写ECKeyPair的sign方法来实现。

创建和使用钱包文件Ethereum wallet file

为了离线脱机交易,你需要有你的钱包文件或与私密钱包/账户相关的公共和私人密钥。

web3j能够为你生成一个新的安全的以太坊钱包文件Ethereum wallet file,或者与也可以通过私钥来和现有的钱包文件一起工作。

创建新的钱包文件:

String fileName = WalletUtils.generateNewWalletFile(

"your password",

new File("/path/to/destination"));

加载凭据从钱包文件:

Credentials credentials = WalletUtils.loadCredentials(

"your password",

"/path/to/walletfile");

然后这些凭据会被用来签署交易,请参阅Web3安全存储定义钱包文件规范Web3 Secret Storage Definition

签署以太坊交易

要使脱机签名交易得到签署,需要设定一个RawTransaction类型。RawTransaction类似于前面提到的Transaction类型,但是它不需要通过具体的账号地址来请求,因为可以从签名中推断出来。

为了创建和签署原生交易,交易的顺序如下:

1.确定交易发起者帐户的下一个可用随机数nonce

2.创建RawTransaction对象

3.使用递归长度前缀编码(RLP即Recursive Length Prefix)对RawTransaction对象进行编码

4.签署RawTransaction对象

5.将RawTransaction对象发送到节点进行处理

nonce是一个不断增长的数值,用来唯一地标识交易。一个nonce只能使用一次,直到交易被挖掘完成,可以以相同的随机数发送交易的多个版本,但是一旦其中一个被挖掘完成,其他后续提交的都将被拒绝。

一旦获得下一个可用的nonce,该值就可以用来创建transaction对象:

RawTransaction rawTransaction = RawTransaction.createEtherTransaction(

nonce, , , , );

然后可以对交易进行签名和编码:

byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, );

String hexValue = Numeric.toHexString(signedMessage);

其中凭据是根据创建和使用钱包文件加载的。

EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();

String transactionHash = ethSendTransaction.getTransactionHash();

// poll for transaction response via org.web3j.protocol.Web3j.ethGetTransactionReceipt()

交易随机数nonce

nonce是一个不断增长的数值,用来唯一地标识交易。一个nonce只能使用一次,直到交易被挖掘完成,可以以相同的随机数发送交易的多个版本,但是一旦其中一个被挖掘完成,其他后续提交的都将被拒绝。

可以通过eth_getTransactionCount方法获得下一个可用的nonce:

EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(

address, DefaultBlockParameterName.LATEST).sendAsync().get();

BigInteger nonce = ethGetTransactionCount.getTransactionCount();

然后可以使用nonce创建你的交易对象:

RawTransaction rawTransaction = RawTransaction.createEtherTransaction(

nonce, , , , );

交易类型

web3j中的不同类型的交易都使用Transaction和RawTransaction对象。关键的区别是交易对象必须始终有一个地址,以便处理eth_sendTransaction请求的以太坊客户端知道要使用哪个钱包来代表消息发送者并发送该交易。如上所述,对于离线签名认证签署的原始交易而言,这不是必须的。

接下来的部分概述了不同交易类型所需的关键交易属性。下列属性对所有人都是不变:

Gas price 天然气气体价格

Gas limit 天然气气体限制

Nonce 随机数

from 发送地址

Transaction和RawTransaction对象在所有后续示例中都可互换使用。

以太币从一方交易到另一方

在双方之间发送以太币Ether需要交易对象的最少量的信息:

to :目的地钱包地址

value:价值,希望发送到目的地的以太币数量

BigInteger value = Convert.toWei("1.0", Convert.Unit.ETHER).toBigInteger();

RawTransaction rawTransaction = RawTransaction.createEtherTransaction(

, , , , value);

// send...

但是,建议你使用TransferClass来发送以太币Ether,它负责对nonce管理和通过不断的轮询为你提供响应:

Web3j web3 = Web3j.build(new HttpService()); // defaults to http://localhost:8545/

Credentials credentials = WalletUtils.loadCredentials("password", "/path/to/walletfile");

TransactionReceipt transactionReceipt = Transfer.sendFunds(

web3, credentials, "0x

|",

BigDecimal.valueOf(1.0), Convert.Unit.ETHER).send();

使用智能合约打包器smart contract wrappers

当使用下面列出的智能合约打包器时,将不得不手动执行从Solidity到本机Java类型的所有转换。使用Solidity smart contract wrappers是非常有效的,它负责所有的代码生成和转换。

创建一个智能合约

要部署新的智能合约,需要提供以下属性:

value :在智能合约中希望存放的以太坊Ether量(如果没有提供默认为零)

data :十六进制格式化、编译的智能合约创建代码

// using a raw transaction

RawTransaction rawTransaction = RawTransaction.createContractTransaction(

,

,

,

,

"0x ");

// send...

// get contract address

EthGetTransactionReceipt transactionReceipt =

web3j.ethGetTransactionReceipt(transactionHash).send();

if (transactionReceipt.getTransactionReceipt.isPresent()) {

String contractAddress = transactionReceipt.get().getContractAddress();

} else {

// try again

}

如果智能合约包含构造函数,则必须对关联的构造函数字段值进行编码,并将其附加到编译的智能合约代码中compiled smart contract code:

String encodedConstructor =

FunctionEncoder.encodeConstructor(Arrays.asList(new Type(value), ...));

// using a regular transaction

Transaction transaction = Transaction.createContractTransaction(

,

,

,

,

,

"0x " + encodedConstructor);

// send...

与智能合约交易

要与现有的智能合约进行交易,需要提供以下属性:

to:智能合同地址

value:在智能合约中你希望存放的以太币Ether量(如果智能合约接受以太币Ether的话)

data: 已编码的函数选择器和自变量参数

web3j负责函数编码,有关实现的进一步细节,请参阅应用程序二进制接口部分Application Binary Interface。

Function function = new Function<>(

"functionName", // function we're calling

Arrays.asList(new Type(value), ...), // Parameters to pass as Solidity Types

Arrays.asList(new TypeReference() {}, ...));

String encodedFunction = FunctionEncoder.encode(function)

Transaction transaction = Transaction.createFunctionCallTransaction(

, , , contractAddress, , encodedFunction);

org.web3j.protocol.core.methods.response.EthSendTransaction transactionResponse =

web3j.ethSendTransaction(transaction).sendAsync().get();

String transactionHash = transactionResponse.getTransactionHash();

// wait for response using EthGetTransactionReceipt...

无论消息签名的返回类型如何,都不可能从事务性函数调用返回值。但是,使用过滤器捕获函数返回的值是可能的。详情请参阅过滤器和事件部分。

查询智能合约状态

这种功能是由eth_call通过JSON-RPC调用来实现的。

eth_call允许你调用智能合约上的方法来查询某个值。此函数没有关联交易成本,这是因为它不改变任何智能合约方法的状态,它只返回它们的值:

Function function = new Function<>(

"functionName",

Arrays.asList(new Type(value)), // Solidity Types in smart contract functions

Arrays.asList(new TypeReference() {}, ...));

String encodedFunction = FunctionEncoder.encode(function)

org.web3j.protocol.core.methods.response.EthCall response = web3j.ethCall(

Transaction.createEthCallTransaction(, contractAddress, encodedFunction),

DefaultBlockParameterName.LATEST)

.sendAsync().get();

List someTypes = FunctionReturnDecoder.decode(

response.getValue(), function.getOutputParameters());

注意:如果一个无效的函数调用被执行,或者得到一个空null返回结果时,返回值将是一个Collections.emptyList实例。

web3j教程,主要是针对java和android程序员进行区块链以太坊开发的web3j开发详解。

以太坊教程,主要介绍智能合约与dapp应用开发,适合入门。

以太坊开发,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。

汇智网原创翻译,转载请标明出处。原文访问其官方博客

java 以太坊 智能合约_web3j教程:java使用web3j开发以太坊智能合约交易相关推荐

  1. java和以太坊交互_java类库web3j开发以太坊智能合约快速入门

    web3j简介 web3j是一个轻量级.高度模块化.响应式.类型安全的Java和Android类库提供丰富API,用于处理以太坊智能合约及与以太坊网络上的客户端(节点)进行集成. 可以通过它进行以太坊 ...

  2. JAVA使用web3j开发以太坊实战案例

    JAVA使用web3j开发以太坊实战案例 必读 1.前言 2.基础(必看) 3.web3j引入 4.创建账户(离线创建) 5.geth节点搭建.基本使用及一般问题 6.常量类 后面内容都要用到(必备! ...

  3. 以太坊教程:入门学习开发以太坊dapp

    一.区块链 1. 分布式去中心化 比特币设计的初衷就是要避免依赖中心化的机构,没有发行机构,也不可能操纵发行数量.既然没有中心化的信用机构,在电子货币运行的过程中,也势必需要一种机制来认可运行在区块链 ...

  4. eclipse启动提示java,Eclipse启动时报错-JSP教程,Java技巧及代码

    前些日子下载了最新版本的eclipse3.0,解压到d:\eclipse目录下,启动时弹出一个小提示框说出错请查看eclipse\configuration\下的一个*******.log文件.文件中 ...

  5. 我的世界java怎么开创造,MOD制作教程JAVA篇

    您尚未登录,立即登录享受更好的浏览体验! 您需要 登录 才可以下载或查看,没有帐号?注册(register) x 本帖最后由 heidada 于 2011-5-12 21:33 编辑 首先我阅读了这个 ...

  6. java inner class,C# Inner Class vs. java 的inner class比较-JSP教程,Java技巧及代码

    作者: leafwiz www.aspcool.com 时间:2004-11-6 15:50:57 阅读次数:1811 今天朋友问到,为什么在c#中inner class不能够访问外部类的非静态成员, ...

  7. java final 变量 回收_java入门教程-Java中final,finally,finalize三个关键字的区别

    final 当这个关键字修饰一个类时,意味着他不能派生出新的子类,也就是说不能被继承,因此一个类不能被同时声明为abstract和final.当final修饰变量或者方法时,可以保证他们在使用中不会被 ...

  8. java源代码连接jsp,java网络五子棋的源代码-JSP教程,Java技巧及代码

    下面的源代码分为4个文件: chessclient.java:客户端主程序. chessinterface.java:客户端的界面. chesspad.java:棋盘的绘制. chessserver. ...

  9. java视频教程千峰_java基础教程-Java开发入门视频教程-千锋教育视频资源库

    第1节 - Java由来及语言特点 点击播放 第2节 - Java的执行机制及第一个应用程序 点击播放 第3节 - 类的阐述及Package相关 点击播放 第4节 - Java的编码规范 点击播放 第 ...

最新文章

  1. 使用post向webservice发送请求,并且返回值
  2. ffmpeg与x264有什么区别?
  3. C语言带参数的main()函数
  4. flask框架(四):通过局域网访问网站
  5. LeetCode(700)——二叉搜索树中的搜索(JavaScript)
  6. 使用 SignalR 实现推送功能
  7. 一行代码安装xgboost
  8. linux在路径下创建文件,从可以在Linux中打开的文件路径创建文件
  9. as常用固定搭配_常见固定搭配
  10. 【C++】 ArcFace Demo2.0版
  11. 在EditPlus中配置java快捷键
  12. MediaCodec解析MP4视频
  13. 视频传输协议详解(RTMP、RTSP、HLS)
  14. 浅谈Hibernate的flush机制
  15. Andriod中如何新建lunch项
  16. 同步锁Synchronized和ReentrantLock区别
  17. 解决微信emjoy特殊符号插入数据库出错
  18. Flink1.14.4 与 Flinkcdc 2.2.1 遇keng
  19. 什么是构造方法,为什么要使用构造方法
  20. 工作中如何时间管理?

热门文章

  1. s5pv210——按键
  2. 汇编指令的学习4——ldm/stm指令、栈的处理
  3. shell的debug模式
  4. 2017.10.25水题大作战题解
  5. 浅析Java内存模型
  6. 《你的灯亮着吗》 读书笔记三
  7. MVC中根据后台绝对路径读取图片并显示在IMG中
  8. Unable to open /dev/sda的原因之一
  9. Ural 1519. Formula 1 优美的插头DP
  10. Visual studio 2012 ultimate 安装遇到 Prerequisites , 错误的函数 incorrect function