從廣義上講,有web3j支持三種類型的以太坊交易:
- 1.以太幣從一方交易到另一方
- 2.創(chuàng)建一個(gè)智能合約
- 3.與智能合約交易
為了進(jìn)行這些交易吃既,必須有以太幣(以太坊區(qū)塊鏈的代幣)存在于交易發(fā)生的以太坊賬戶中拒秘。這是為了支付gas成本坛芽,這是為支付參與交易的以太坊客戶端的交易執(zhí)行成本留储,支付了這個(gè)成本就能將結(jié)果提交到以太坊區(qū)塊鏈上。獲得以太幣的說明下文會(huì)說到咙轩。
此外获讳,我們還可以查詢智能合約的狀態(tài)。
如何獲得以太幣Ether
要想獲得以太幣Ether你有兩種途徑可以選擇:
- 1.自己開采挖礦
- 2.從別人那里獲取以太幣
在私有鏈中自己挖礦活喊,或者公共測(cè)試鏈(testnet
)是非常簡(jiǎn)單直接的丐膝。但是,在主要的公有鏈(mainnet
)中钾菊,它需要很多很明顯的專用GPU時(shí)間帅矗,除非你已經(jīng)擁有多個(gè)專用GPU的礦機(jī),否則基本上不太可行煞烫。如果你希望使用私有鏈浑此,則在這個(gè)官方文檔中有一些指導(dǎo)。
要購(gòu)買以太幣Ether滞详,你需要通過交易所凛俱。由于不同的地區(qū)有不同的交易所,你還需要研究自己去哪兒合適料饥。官方文檔中包含多個(gè)交易所蒲犬,是一個(gè)很好的參考。
以太坊測(cè)試鏈(testnets)
針對(duì)Ethereum以太坊有許多專用測(cè)試網(wǎng)絡(luò)或者叫測(cè)試鏈岸啡,他們由各種客戶端支持原叮。
- 1.Rinkeby:只支持geth客戶端。
- 2.Kovan:只支持Parity客戶端巡蘸。
- 3.Ropsten:支持geth和Parity客戶端奋隶。
對(duì)于開發(fā),建議你使用Rinkeby
或KoVan
測(cè)試鏈悦荒。這是因?yàn)樗麄兪褂玫墓ぷ髁孔C明POA
共識(shí)機(jī)制达布,確保交易和塊能夠一致并及時(shí)的創(chuàng)建。Ropsten
測(cè)試鏈逾冬,雖然最接近公有鏈(Mainnet
)黍聂,但是因?yàn)樗褂玫墓ぷ髁孔C明是POW
共識(shí)機(jī)制,過去已受到攻擊身腻,對(duì)以太坊開發(fā)人員來說往往有更多的問題产还。
你可以通過Rinkeby
測(cè)試鏈的Rinkeby Crypto Fauce
請(qǐng)求以太坊幣,具體怎么做可以看這里https://www.rinkeby.io/嘀趟。
有關(guān)如何請(qǐng)求Kovan
測(cè)試鏈的細(xì)節(jié)可以在這里找到脐区。
如果你需要在Ropsten
上的得到一些以太幣,將你的錢包地址的消息發(fā)布到web3j gitter channel她按,然后會(huì)發(fā)送一些給你牛隅。
在testnet測(cè)試鏈或者私有鏈上挖掘
在ethereum以太坊測(cè)試鏈testnet
中炕柔,挖掘難度低于公有鏈mainnet
。這意味著你可以用普通的CPU媒佣,比如你的筆記本電腦來挖掘新的以太幣匕累。你需要做的是運(yùn)行一個(gè)以太坊客戶端,例如geth
或Parity
默伍,開始做一些儲(chǔ)備欢嘿。進(jìn)一步的資料可在他們的官方網(wǎng)站上獲得。
- geth :https://github.com/ethereum/go-ethereum/wiki/Mining
- Parity :https://github.com/paritytech/parity/wiki/Mining
一旦你開采了一些以太幣也糊,你就可以開始使用以太坊區(qū)塊鏈了炼蹦。
然而,如上所述狸剃,使用Kovan
或者Rinkeby
測(cè)試網(wǎng)絡(luò)更簡(jiǎn)單些掐隐。
gas
當(dāng)在Ethereum以太坊發(fā)生交易時(shí),必須為執(zhí)行該交易的客戶端支付交易成本钞馁,將該交易的輸出提交到以太坊區(qū)塊鏈Ethereum blockchain虑省。
此成本是通過gas來測(cè)量的,其中g(shù)as是用于在以太坊虛擬機(jī)中執(zhí)行交易指令的數(shù)量指攒。請(qǐng)參閱官方文檔以獲取更多信息慷妙。
當(dāng)你使用以太坊客戶端時(shí)僻焚,這意味著允悦,有兩個(gè)參數(shù)用來指示你希望花費(fèi)多少以太來完成傳輸:
- gas price :氣體價(jià)格,這是每單位gas中以太的消耗量虑啤。Web3j使用的默認(rèn)價(jià)格為22000000000 wei(22×10-8 Ether)隙弛。這是在交易管理中定義的。
- gas limit:氣體最大量狞山,這是你愿意在交易執(zhí)行上花費(fèi)的gas的最大總量全闷。單個(gè)交易在一個(gè)以太坊區(qū)塊中有多大的上限,通常將該值限制為小于6700000萍启。當(dāng)前的gas限制在這里查https://ethstats.net/总珠。
這兩個(gè)參數(shù)共同決定了你愿意花費(fèi)在交易成本上的最大量的以太幣Ether。也就是說勘纯,你花費(fèi)的gas不會(huì)超過gas price * gas limit
局服。gas價(jià)格也會(huì)影響交易發(fā)生的速度,這取決于其他交易是否能為礦工提供更有利的gas價(jià)格驳遵。
你可能需要調(diào)整這些參數(shù)以確保交易能及時(shí)進(jìn)行淫奔。
交易機(jī)制
當(dāng)你用一些以太幣Ether創(chuàng)建了一個(gè)有效的帳戶時(shí),你可以使用兩種機(jī)制來與以太坊進(jìn)行交易堤结。
- 通過以太坊ethereum客戶端進(jìn)行認(rèn)證簽名交易
- 離線交易簽名認(rèn)證
這兩種機(jī)制都是Web3j所支持的唆迁。
通過以太坊ethereum客戶端進(jìn)行認(rèn)證簽名交易
為了通過以太坊客戶端進(jìn)行交易鸭丛,首先需要確保你正在使用的客戶端知道你的錢包地址。最好是運(yùn)行自己的以太坊客戶端唐责,比如geth
/Parity
鳞溉,以便可以更方便的做到這一點(diǎn)。一旦你有一個(gè)客戶端運(yùn)行妒蔚,你可以創(chuàng)建一個(gè)以太坊錢包穿挨,通過:
- geth Wiki包含了geth支持的良好運(yùn)行的不同機(jī)制,例如導(dǎo)入私有密鑰文件肴盏,并通過控制臺(tái)創(chuàng)建新的以太坊帳戶科盛。
- 或者,你可以通過客戶端使用JSON-RPC管理命令菜皂,例如用
personal_newAccount
為geth
/Parity
創(chuàng)建新以太坊賬戶贞绵。
通過創(chuàng)建你的錢包文件,你可以通過web3j打開帳戶恍飘,首先創(chuàng)建支持geth
/Parity
管理命令的web3j實(shí)例:
Admin web3j = Admin.build(new HttpService());
然后榨崩,你可以解鎖帳戶,并如果是成功的章母,就可以發(fā)送一個(gè)交易:
PersonalUnlockAccount personalUnlockAccount = web3j.personalUnlockAccount("0x000...", "a password").send();
if (personalUnlockAccount.accountUnlocked()) {
// send a transaction
}
以這種方式發(fā)送的交易應(yīng)該通過EthSendTransaction創(chuàng)建母蛛,使用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
值獲得方式,下文會(huì)提到乳怎。
有關(guān)此交易工作流的詳細(xì)信息彩郊,請(qǐng)參閱 DeployContractIT和Scenario。
web3j支持的各種管理命令的進(jìn)一步細(xì)節(jié)在Management APIs中蚪缀。
離線交易簽名認(rèn)證Offline transaction signing
如果你不想管理自己的以太坊客戶端秫逝,或者不想向以太坊客戶端提供諸如密碼之類的錢包詳細(xì)信息,那么就通過離線交易認(rèn)證簽名询枚。
離線交易簽名認(rèn)證允許你在web3j中使用你的以太坊錢包簽署交易违帆,允許你完全控制你的私有憑據(jù)。然后金蜀,離線創(chuàng)建的交易可以被發(fā)送到網(wǎng)絡(luò)上的任何以太坊客戶端刷后,只要它是一個(gè)有效的交易,它會(huì)將交易傳播到其他節(jié)點(diǎn)渊抄。
如果需要尝胆,還可以執(zhí)行進(jìn)程外交易簽名認(rèn)證。這可以通過重寫ECKeyPair的sign
方法來實(shí)現(xiàn)抒线。
創(chuàng)建和使用錢包文件Ethereum wallet file
為了離線脫機(jī)交易班巩,你需要有你的錢包文件或與私密錢包/賬戶相關(guān)的公共和私人密鑰。
web3j能夠?yàn)槟闵梢粋€(gè)新的安全的以太坊錢包文件Ethereum wallet file,或者與也可以通過私鑰來和現(xiàn)有的錢包文件一起工作抱慌。
創(chuàng)建新的錢包文件:
String fileName = WalletUtils.generateNewWalletFile(
"your password",
new File("/path/to/destination"));
加載憑據(jù)從錢包文件:
Credentials credentials = WalletUtils.loadCredentials(
"your password",
"/path/to/walletfile");
然后這些憑據(jù)會(huì)被用來簽署交易逊桦,請(qǐng)參閱Web3安全存儲(chǔ)定義錢包文件規(guī)范Web3 Secret Storage Definition
簽署以太坊交易
要使脫機(jī)簽名交易得到簽署,需要設(shè)定一個(gè)RawTransaction類型抑进。RawTransaction
類似于前面提到的Transaction
類型强经,但是它不需要通過具體的賬號(hào)地址來請(qǐng)求,因?yàn)榭梢詮暮灻型茢喑鰜怼?/p>
為了創(chuàng)建和簽署原生交易寺渗,交易的順序如下:
- 1.確定交易發(fā)起者帳戶的下一個(gè)可用隨機(jī)數(shù)
nonce
- 2.創(chuàng)建
RawTransaction
對(duì)象 - 3.使用遞歸長(zhǎng)度前綴編碼(RLP即Recursive Length Prefix)對(duì)
RawTransaction
對(duì)象進(jìn)行編碼 - 4.簽署
RawTransaction
對(duì)象 - 5.將
RawTransaction
對(duì)象發(fā)送到節(jié)點(diǎn)進(jìn)行處理
nonce
是一個(gè)不斷增長(zhǎng)的數(shù)值匿情,用來唯一地標(biāo)識(shí)交易。一個(gè)nonce
只能使用一次信殊,直到交易被挖掘完成炬称,可以以相同的隨機(jī)數(shù)發(fā)送交易的多個(gè)版本,但是一旦其中一個(gè)被挖掘完成涡拘,其他后續(xù)提交的都將被拒絕玲躯。
一旦獲得下一個(gè)可用的nonce
,該值就可以用來創(chuàng)建transaction
對(duì)象:
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
nonce, <gas price>, <gas limit>, <toAddress>, <value>);
然后可以對(duì)交易進(jìn)行簽名和編碼:
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, <credentials>);
String hexValue = Numeric.toHexString(signedMessage);
其中憑據(jù)是根據(jù)創(chuàng)建和使用錢包文件加載的鳄乏。
然后使用eth_SendRawTransaction發(fā)送交易:
EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).sendAsync().get();
String transactionHash = ethSendTransaction.getTransactionHash();
// poll for transaction response via org.web3j.protocol.Web3j.ethGetTransactionReceipt(<txHash>)
有關(guān)創(chuàng)建和發(fā)送原始事務(wù)的完整示例跷车,請(qǐng)參閱 CreateRawTransactionIT。
交易隨機(jī)數(shù)nonce
nonce
是一個(gè)不斷增長(zhǎng)的數(shù)值橱野,用來唯一地標(biāo)識(shí)交易朽缴。一個(gè)nonce
只能使用一次,直到交易被挖掘完成水援,可以以相同的隨機(jī)數(shù)發(fā)送交易的多個(gè)版本密强,但是一旦其中一個(gè)被挖掘完成,其他后續(xù)提交的都將被拒絕裹唆。
可以通過eth_getTransactionCount
方法獲得下一個(gè)可用的nonce
:
EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
address, DefaultBlockParameterName.LATEST).sendAsync().get();
BigInteger nonce = ethGetTransactionCount.getTransactionCount();
然后可以使用nonce
創(chuàng)建你的交易對(duì)象:
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
nonce, <gas price>, <gas limit>, <toAddress>, <value>);
交易類型
web3j中的不同類型的交易都使用Transaction
和RawTransaction
對(duì)象誓斥。關(guān)鍵的區(qū)別是交易對(duì)象必須始終有一個(gè)地址只洒,以便處理eth_sendTransaction
請(qǐng)求的以太坊客戶端知道要使用哪個(gè)錢包來代表消息發(fā)送者并發(fā)送該交易许帐。如上所述,對(duì)于離線簽名認(rèn)證簽署的原始交易而言毕谴,這不是必須的成畦。
接下來的部分概述了不同交易類型所需的關(guān)鍵交易屬性。下列屬性對(duì)所有人都是不變:
- Gas price 天然氣氣體價(jià)格
- Gas limit 天然氣氣體限制
- Nonce 隨機(jī)數(shù)
- from 發(fā)送地址
Transaction
和RawTransaction
對(duì)象在所有后續(xù)示例中都可互換使用涝开。
以太幣從一方交易到另一方
在雙方之間發(fā)送以太幣Ether需要交易對(duì)象的最少量的信息:
- to :目的地錢包地址
- value:價(jià)值循帐,希望發(fā)送到目的地的以太幣數(shù)量
BigInteger value = Convert.toWei("1.0", Convert.Unit.ETHER).toBigInteger();
RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
<nonce>, <gas price>, <gas limit>, <toAddress>, value);
// send...
但是,建議你使用TransferClass來發(fā)送以太幣Ether舀武,它負(fù)責(zé)對(duì)nonce
管理和通過不斷的輪詢?yōu)槟闾峁╉憫?yīng):
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();
使用智能合約打包器smart contract wrappers
當(dāng)使用下面列出的智能合約打包器時(shí)拄养,將不得不手動(dòng)執(zhí)行從Solidity到本機(jī)Java類型的所有轉(zhuǎn)換。使用Solidity smart contract wrappers是非常有效的银舱,它負(fù)責(zé)所有的代碼生成和轉(zhuǎn)換瘪匿。
創(chuàng)建一個(gè)智能合約
要部署新的智能合約跛梗,需要提供以下屬性:
- value :在智能合約中希望存放的以太坊Ether量(如果沒有提供默認(rèn)為零)
- data :十六進(jìn)制格式化、編譯的智能合約創(chuàng)建代碼
// 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
}
如果智能合約包含構(gòu)造函數(shù)棋弥,則必須對(duì)關(guān)聯(lián)的構(gòu)造函數(shù)字段值進(jìn)行編碼核偿,并將其附加到編譯的智能合約代碼中compiled smart contract code
:
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...
與智能合約交易
要與現(xiàn)有的智能合約進(jìn)行交易,需要提供以下屬性:
- to:智能合同地址
- value:在智能合約中你希望存放的以太幣Ether量(如果智能合約接受以太幣Ether的話)
- data: 已編碼的函數(shù)選擇器和自變量參數(shù)
web3j負(fù)責(zé)函數(shù)編碼顽染,有關(guān)實(shí)現(xiàn)的進(jìn)一步細(xì)節(jié)漾岳,請(qǐng)參閱應(yīng)用程序二進(jìn)制接口部分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...
無論消息簽名的返回類型如何,都不可能從事務(wù)性函數(shù)調(diào)用返回值奈梳。但是坝咐,使用過濾器捕獲函數(shù)返回的值是可能的。詳情請(qǐng)參閱過濾器和事件部分耀找。
查詢智能合約狀態(tài)
這種功能是由eth_call通過JSON-RPC
調(diào)用來實(shí)現(xiàn)的。
eth_call允許你調(diào)用智能合約上的方法來查詢某個(gè)值业崖。此函數(shù)沒有關(guān)聯(lián)交易成本野芒,這是因?yàn)樗桓淖內(nèi)魏沃悄芎霞s方法的狀態(tài),它只返回它們的值:
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());
注意:如果一個(gè)無效的函數(shù)調(diào)用被執(zhí)行双炕,或者得到一個(gè)空null返回結(jié)果時(shí)狞悲,返回值將是一個(gè)Collections.emptyList實(shí)例。
匯智網(wǎng)原創(chuàng)翻譯,原文訪問這里