小猿“思前享后”为大家分享优质内容!————Share猿
Hi大家好:
我是Share猿,Share是英文(SHARE),猿是猿猴的猿,在微信公众号、微博、简书、掘金、今日头条、CSDN都可以通过搜索“Share猿”找到我,我等你哦!小猿 “思前享后”为大家分享优质的内容!今天小猿为大家分享:初始web3j
一般情况下,以太坊有三种类型的交易:
1.账号之间以太币的交易
2.创建智能合约
3.智能合约交易
要进行这些交易必须要有以太坊(少量的以太坊)去进行相关的交易。这是为了支付GAS,也就是为你服务的以太坊客户端的交易成本,然后把结果告知整个区块链。
此外,在以太坊网络中智能合约可以被查到,具体怎么查,后续有相关介绍。
4.1获取以太坊
获取以太坊有以下两种方式:
①通过自己挖矿得到。
②通过在别人或者机构中获取到。
在私有环境中挖矿,或者在公有测试环境下进行挖矿是非常简单的。然而,在主网中挖矿需要更多的GPU(CPU 由专为顺序串行处理而优化的几个核心组成,而 GPU 则拥有一个由数以千计的更小、更高效的核心(专为同时处理多重任务而设计)组成的大规模并行计算架构,具体区块可以看这个小视频),如果你想用自己的私有环境在公网上挖矿请参考这里。
要购买以太坊,你需要通过交换。由于不同的地区有不同的交易所,所以你需要找到本地比较好的交易所去进行购买以太坊。
4.2.以太坊网络
以太坊中有许多专用的测试网络,由不同的客户端支持。
- Rinkeby (Geth only)
- Kovan (Parity only)
- Ropsten (Geth and Parity)
对于开发者而言推荐你用Rinkeby 和 Kovan测试网络。这是因为他们用了一种叫做POA的共识机制,确保交易和区块及时的被记录到区块链中。Ropsten 测试网络最接近主网,因为他运用了POW共识机制,Ropsten以往经常遭受攻击,这对开发者来说是一个很大问题。
4.3.在网络上挖矿/独立的区块
在以太坊测试网络上,难度设置的比主网上要低。这意味着你可以通过CPU开发一个自己新的节点,比如用你的笔记本可以做一个节点。你需要做的是运行一个Ethereum客户端,比如Geth或Parity来开始做准备,
更多的说明请在他们的官网上查看。
一旦你挖到以太坊,你就可以再区块链网络上进行交易了。
然后,就像上面提到的,在Kovan和Rinkeby测试网络上运用会更加简单。
4.4.Gas
当一个交易发生在以太坊网络上,交易必须要给客户端支付一定的费用,然后交易才能被记录到区块链上。
这个交易费用是用gas进行计量的,在以太坊网络中,gas是用来表示交易费用的单位。想进一步了解gas请看这里.
当你在客户端中进行交易时,有两个参数决定了你Gas的多少。
Gas price
每笔交易用的Gas。web3j默认的价格是22的负8次方。
Gas limit
gas limit是单个区块允许的最多gas总量,以此可以用来决定单个区块中能打包多少笔交易。一笔单独的交易在以太坊网络上的限制通常是6700000微,目前最新的Gas最高值可以参考这里。
这两个参数决定了你在一笔交易上的花费。你在每笔交易上的花费不能超过gas price*gas limit。gas price决定了你在区块链网络上交易的速度
,gas price的价格对矿工是有利的。
你需要去调整gas的价格去确保交易能够正常进行。
4.5.交易机制
当你在以太坊上创建了账户后,你可以通过以下两种方式进行交易:
①通过以太坊客户端进行交易。
②通过智能合约进行交易。
web3j支持这两种类型的交易。
4.6.通过以太坊客户端进行交易
要在以太坊客户端进行交易,首先你要确保你在客户端有一个钱包地址。你可以自己运行一个客户端去交易,比如Geth/Parity去做这些。
- Geth客户端适用于各种机器,它支持钱包文件的导入和账号的创建。
- 或者,您可以使用JSON-RPC管理您的账户,例如Parith或Geth的帐户。
通过创建钱包文件,你可以通过web3j打开你的账户,首先创建一个web3j的实例,它支持parit/geth的管理命令:
Admin web3j = Admin.build(new HttpService());
然后你可以解锁这个账户,如果成功你就可以进行交易了:
PersonalUnlockAccount personalUnlockAccount = web3j.personalUnlockAccount("0x000...", "a password").send();
if (personalUnlockAccount.accountUnlocked()) {
// send a transaction
}
以这种方式发送的交易应当通过EthSendTransaction方式创建,通过 Transaction 类。
Transaction transaction = Transaction.createContractTransaction(
<from address>,
<nonce>,
BigInteger.valueOf(<gas price>), // we use default gas limit
"0x...<smart contract code to execute>"
);
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(<txHash>)
<nonce> 值从下面的每一个获取到。
请参考测试类DeployContractIT和他的父类 Scenario
进一步理解交易的工作机制。
有关web3j支持的不同管理命令的详细信息可以在 Management APIs.
中找到。
4.7.线下交易签署
如果你不想管理自己的Ethereum客户端,或者不想向Ethereum客户端提供诸如密码之类的钱包细节,那么线下交易签名就是一种选择。
离线交易签名允许你在web3j内使用以太坊式的Ethereum钱包来签署一项交易,这样你就可以完全控制你的私人凭证。离线创建的事务可以发送到网络上的任何Ethereum客户端,如果它是一个有效的事务,那么它将把事务传播给其他节点。
如果需要,您还可以通过数字签名。通过在ECKeyPair上覆盖sign方法来实现。
4.8.创建和使用钱包文件
为了在离线状态下签署交易,你需要有你的以太钱包文件或者与以太坊/账户关联的公钥和私钥。
web3j能够为你生成一个新的安全Ethereum钱包文件,或者使用一个现有的钱包文件。
创建一个新的钱包文件:
String fileName = WalletUtils.generateNewWalletFile(
"your password",
new File("/path/to/destination"));
从钱包文件中加载凭证:
Credentials credentials = WalletUtils.loadCredentials(
"your password",
"/path/to/walletfile");
然后使用这些凭证来签署合约。
请参考 Web3 Secret Storage Definition 查看整体的操作流程。
4.9.确认交易
要在脱机情况下确认交易,应该使用 RawTransaction类来实现此目的。RawTransaction类似于前面提到的类,但是它不需要来自地址,因为这可以从签名中推断出来。
为了创建和确认一个交易,事件的顺序如下:
- 为发送者帐户确定下一个可用的nonce
- 创建RawTransaction对象
- 编译通过RawTransaction实现的 Recursive Length Prefix
代码。 - 确认RawTransaction object
- 发送RawTransaction object给另一个节点。
nonce是一个不断增长的数值,用于唯一地标识事务。一次nonce只能被使用一次,直到一个事务被挖掘出来,可以用同一个nonce发送多个版本的事务,然而,一旦被挖掘,任何后续的提交都将被拒绝。
一旦您获得了下一个可用的nonce,那么就可以使用该值来确认交易:
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
nonce, <gas price>, <gas limit>, <toAddress>, <value>);
然后就可以签名和编码了
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, <credentials>);
String hexValue = Numeric.toHexString(signedMessage);
在这些凭证中,那些被加载的是创建和使用钱包文件的凭证。
交易的发送要用eth_sendRawTransaction
EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
String transactionHash = ethSendTransaction.getTransactionHash();
// poll for transaction response via org.web3j.protocol.Web3j.ethGetTransactionReceipt(<txHash>)
请参考测试类CreateRawTransactionIT看创建和发送原始交易的完整示例。
4.10.交易的noce
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, <gas price>, <gas limit>, <toAddress>, <value>);
4.11.交易类型
web3j中不同类型的交易处理事务和RawTransaction对象。关键的区别在于,事务对象必须始终有一个来源地址,因此,处理这个问题的以太坊客户端发送交易客户端请求知道要使用哪个钱包,以便在消息发送方上签名和发送交易。正如上面所提到的,这对于在离线状态下签署的原始交易来说是不必要的。
接下来的部分概述了不同事务类型所需的关键事务属性,以下属性对所有人来说都是不变的:
- Gas价格
- Gas限制
- Noce(随机数)
- From
事务和RawTransaction对象在随后的所有示例中都可以互换使用。
4.12.转账
在两方之间进行数据的交易时需要交易信息:发送给接受者的地址,从要发送以太的地址发送。
BigInteger value = Convert.toWei("1.0", Convert.Unit.ETHER).toBigInteger();
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
<nonce>, <gas price>, <gas limit>, <toAddress>, value);
// send...
然而,建议您使用Transfer类来发送以太,它负责管理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<address>|<ensName>",
BigDecimal.valueOf(1.0), Convert.Unit.ETHER).send();
4.13.智能合约的编写
当使用下面列出的智能合同包装器时,您将不得不手动执行从可靠性到本机Java类型的所有转换。使用web3j的坚固智能契约包装器更有效,它负责处理所有代码生成和对您的转换。
4.14.创建一个简单的智能合约
要部署新的智能契约,需要提供以下属性:
发送:您希望在智能合同中存放的以太数量(如果没有提供,则假定为零)
智能合约代码:编译后的智能合同创建代码
// using a raw transaction
RawTransaction rawTransaction = RawTransaction.createContractTransaction(
<nonce>,
<gasPrice>,
<gasLimit>,
<value>,
"0x <compiled smart contract code>");
// send...
// get contract address
EthGetTransactionReceipt transactionReceipt =
web3j.ethGetTransactionReceipt(transactionHash).send();
if (transactionReceipt.getTransactionReceipt.isPresent()) {
String contractAddress = transactionReceipt.get().getContractAddress();
} else {
// try again
}
如果智能合约包含构造器,则必须对相关的构造函数字段值进行编码,并将其附加到已编译的智能合约中:
String encodedConstructor =
FunctionEncoder.encodeConstructor(Arrays.asList(new Type(value), ...));
// using a regular transaction
Transaction transaction = Transaction.createContractTransaction(
<fromAddress>,
<nonce>,
<gasPrice>,
<gasLimit>,
<value>,
"0x <compiled smart contract code>" + encodedConstructor);
// send...
4.15.用智能合约进行交易
为了与现有的智能合同进行交易,需要提供以下属性:
接收方:智能合约地址
内容:你希望存在智能合约中的以太坊数量(如果智能合约支持接收以太坊)
数据:编码函数选择器和参数参数
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<Type>() {}, ...));
String encodedFunction = FunctionEncoder.encode(function)
Transaction transaction = Transaction.createFunctionCallTransaction(
<from>, <gasPrice>, <gasLimit>, contractAddress, <funds>, encodedFunction);
org.web3j.protocol.core.methods.response.EthSendTransaction transactionResponse =
web3j.ethSendTransaction(transaction).sendAsync().get();
String transactionHash = transactionResponse.getTransactionHash();
// wait for response using EthGetTransactionReceipt...
不管消息签名的返回类型是什么,都不可能返回事务性功能性调用的值。然而,可以使用过滤器捕获由函数返回的值。详情请参阅过滤器和事件部分。
4.16查询交易状态
这个功能是由ethcall JSON-RPC调用促成的。
ethcall允许您调用智能合同上的方法来查询一个值。这个函数没有任何事务成本,这是因为它没有改变任何智能合同方法的状态,它只是简单地返回它们的值:
Function function = new Function<>(
"functionName",
Arrays.asList(new Type(value)), // Solidity Types in smart contract functions
Arrays.asList(new TypeReference<Type>() {}, ...));
String encodedFunction = FunctionEncoder.encode(function)
org.web3j.protocol.core.methods.response.EthCall response = web3j.ethCall(
Transaction.createEthCallTransaction(<from>, contractAddress, encodedFunction),
DefaultBlockParameterName.LATEST)
.sendAsync().get();
List<Type> someTypes = FunctionReturnDecoder.decode(
response.getValue(), function.getOutputParameters());
→→→目录阅读(小猿英语没过四级,翻译的过程中难免会有好多翻译不到位的地方,如果有错请在评论区及时指正!谢谢!!)
参考文章:
【1】web3j文档·web3j
【2】区块链编程一翻译篇<一>:web3j介绍·Lucien_Lang
扫描以下公众号关注小猿↓↓↓↓↓↓↓↓
更多资讯请在简书、微博、今日头条、掘金、CSDN都可以通过搜索“Share猿”找到小猿哦!!!
网友评论