04-web3j交易(Transactions)


文章是本人學(xué)習(xí)過程翻譯帅霜,原文來自官方文檔:https://web3j.readthedocs.io/en/latest/#

官網(wǎng):https://web3j.io/

官方GitHub:https://github.com/web3j/web3j

官方demo:https://github.com/web3j/web3j/tree/master/integration-tests

文檔版本v3.4.0赎瑰。


一般來說羊瘩,在以太坊支持三種類型的交易:

  • 交易以太幣
  • 創(chuàng)建智能合約
  • 發(fā)起交易到智能合約

要進(jìn)行這些交易俩檬,需要消耗gas要糊,如果你只是查詢合約的狀態(tài)則不需要gas.

獲取以太幣(Obtaining Ether)

有兩種獲取以太幣的方法:

  • 挖礦
  • 跟別人購買以太幣

以太坊測(cè)試網(wǎng)(Ethereum testnets)

下面列出的是Ethereum的各種測(cè)試網(wǎng)絡(luò)纲熏,支持各自的客戶端:

  • Rinkeby (Geth only)
  • Kovan (Parity only)
  • Ropsten (Geth and Parity)

對(duì)于開發(fā)者,推薦使用Rinkeby/Kovan測(cè)試網(wǎng)絡(luò)锄俄,因?yàn)樗鼈兪褂肞OA共識(shí)機(jī)制局劲,可以確保交易和區(qū)塊可以及時(shí)被確認(rèn)打包。

Ropsten測(cè)試網(wǎng)絡(luò)很接近Mainet主網(wǎng)奶赠,同樣使用POW共識(shí)機(jī)制鱼填,過去曾經(jīng)被攻擊過,使用它的開發(fā)者可能會(huì)遇到很多問題毅戈。

在Rinkeby網(wǎng)絡(luò)獲取以太幣苹丸,請(qǐng)看here.

在Kovan網(wǎng)絡(luò)獲取以太幣,請(qǐng)看here

在Ropsten網(wǎng)絡(luò)獲取以太幣苇经,你需要把你的錢包地址發(fā)送到web3j Gitter channel

在測(cè)試網(wǎng)/私有網(wǎng)挖礦(Mining on testnet/private blockchains)

在測(cè)試網(wǎng)/私有網(wǎng)挖礦沒有主網(wǎng)那么高難度赘理,只需要一臺(tái)安裝客戶端節(jié)點(diǎn)的普通的電腦。

當(dāng)你通過挖礦獲得以太幣后扇单,你就可以發(fā)起交易了商模。

Gas

要進(jìn)行交易,需要發(fā)起的賬戶花費(fèi)一些gas蜘澜,把交易的結(jié)果提交到以太坊的區(qū)塊上阻桅。你需要指定兩個(gè)參數(shù),讓客戶端節(jié)點(diǎn)在處理交易時(shí)兼都,知道你希望花費(fèi)多少以太幣來完成交易嫂沉。

Gas price gas價(jià)格

web3j使用默認(rèn)價(jià)格22,000,000,000 Wei (22 x 10-8 Ether).這個(gè)默認(rèn)值定義在ManagedTransaction

Gas limit 最高gas

這個(gè)值一般要小于6,700,000, 可以在 https://ethstats.net/ 查看當(dāng)前的gas limit.

這兩個(gè)參數(shù)的設(shè)置會(huì)影響到交易被處理的速度扮碧,您可能需要調(diào)整這些參數(shù),以確保及時(shí)交易發(fā)生趟章。

發(fā)起交易查詢當(dāng)前gas price:

 Transfer transfer = new Transfer(web3j, transactionManager);
 BigInteger gasPrice = transfer.requestCurrentGasPrice();

交易機(jī)制(Transaction mechanisms)

當(dāng)你創(chuàng)建了一個(gè)擁有以太幣的賬戶后杏糙,你可以通過以下兩種交易機(jī)制,和以太坊網(wǎng)絡(luò)(私網(wǎng)/公網(wǎng))交易:

  1. 通過以太坊客戶端簽名交易 - Transaction signing via an Ethereum client
  2. 線下簽名交易 - Offline transaction signing

通過以太坊客戶端簽名交易

通過客戶端交易蚓土,首先你要啟動(dòng)客戶端(geth宏侍、parity),然后使用客戶端來創(chuàng)建你的錢包賬戶:

  • Geth的控制臺(tái)支持導(dǎo)入一個(gè)已經(jīng)存在的私鑰文件蜀漆,或者創(chuàng)建一個(gè)新的賬戶谅河。
  • Geth的控制臺(tái)提供了json-rpc的命令來讓你管理geth,比如 _personal_newAccount _ 來創(chuàng)建一個(gè)新的賬戶确丢。

創(chuàng)建了賬戶后绷耍,你就可以使用web3j來連接客戶端(ipc/http),這不需要提供秘鑰鲜侥,只需要保證客戶端可以連接褂始,連接后可以解鎖賬戶、發(fā)起交易描函,代碼如下:

Admin web3j = Admin.build(new WindowsIpcService("\\\\.\\pipe\\geth.ipc"));
        PersonalUnlockAccount personalUnlockAccount = web3j
                .personalUnlockAccount("0x053b2252a10356ec0ce1cfc587b909beee591409", "111").send();
        System.out.println(personalUnlockAccount.accountUnlocked());
        EthGetTransactionCount ethGetTransactionCount = web3j
                .ethGetTransactionCount("0x053b2252a10356ec0ce1cfc587b909beee591409", DefaultBlockParameterName.LATEST)
                .send();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();
        Transaction transaction = Transaction.createEtherTransaction("0x053b2252a10356ec0ce1cfc587b909beee591409",
                nonce, GAS_PRICE, GAS_LIMIT, "0xc7d9fffaf663c5dfa31b096164cc843c01d0797a", BigInteger.valueOf(20L));
        org.web3j.protocol.core.methods.response.EthSendTransaction transactionResponse = web3j
                .ethSendTransaction(transaction).send();
        String transactionHash = transactionResponse.getTransactionHash();
        System.out.println(transactionHash);

更多實(shí)例請(qǐng)看 DeployContractIT和它的父類 Scenario崎苗。

線下交易簽名(Offline transaction signing)

如果你不想管理你的客戶端節(jié)點(diǎn),或者不想把提供錢包密碼給客戶端節(jié)點(diǎn)舀寓,線下交易簽名比較適合你胆数。

線下交易簽名允許你使用web3j提供的錢包賬戶發(fā)起交易,你完全控制自己的私鑰互墓,交易發(fā)送到網(wǎng)絡(luò)上的其它節(jié)點(diǎn)并傳播幅慌。

通過覆蓋簽名方法ECKeyPair,來發(fā)起交易簽名轰豆。

ECKeyPair:橢圓曲線算法生成秘鑰對(duì)(Elliptic Curve SECP-256k1 generated key pair)

為了實(shí)現(xiàn)線下交易胰伍,你需要使用web3j生成安全的錢包賬戶,并這個(gè)賬戶交易酸休。

創(chuàng)建錢包文件:

String fileName = WalletUtils.generateNewWalletFile(
        "your password",
        new File("/path/to/destination"));

加載錢包文件:

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

credentials 用來簽名交易骂租。

查看完整的錢包文件規(guī)范:Web3 Secret Storage Definition

交易簽名

線下交易使用 RawTransaction 對(duì)象來完成,一共有如下幾步:

  1. 確定交易賬戶的下一個(gè) nonce
  2. 創(chuàng)建 RawTransaction 對(duì)象
  3. 使用 RLP 編碼 RawTransaction 對(duì)象
  4. 簽名 RawTransaction 對(duì)象
  5. 發(fā)送 RawTransaction 對(duì)象給節(jié)點(diǎn)處理斑司。

交易nonce

以太坊實(shí)戰(zhàn)-再談nonce使用陷阱:https://blog.csdn.net/wo541075754/article/details/79054937

  • nonce 值用來唯一標(biāo)識(shí)賬戶的交易渗饮,一個(gè)值只能使用一次
  • nonce 值可以通過eth_getTransactionCount方法獲取
  • 如果一個(gè)賬戶使用相同的 nonce通過發(fā)起多個(gè)交易,只有一個(gè)交易會(huì)被接受宿刮,(gas price)手續(xù)費(fèi)高的會(huì)覆蓋手續(xù)費(fèi)低的交易互站,如果交易費(fèi)一樣,后發(fā)起的交易會(huì)被拒絕僵缺。
  • Transaction的 nonce 值可以為空胡桃,不指定 nonce 值由客戶端自動(dòng)排序賦值
  • RawTransaction的 nonce 值不能為空
Admin web3j = Admin.build(new HttpService());  // defaults to http://localhost:8545/

Credentials credentials = WalletUtils.loadCredentials("111", "E:\\develop\\geth\\data_dev\\keystore\\UTC--2018-05-05T06-50-18.813015000Z--053b2252a10356ec0ce1cfc587b909beee591409");
  BigInteger value = Convert.toWei("5", Convert.Unit.ETHER).toBigInteger();

// get the next available nonce
EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
             "0x053b2252a10356ec0ce1cfc587b909beee591409", DefaultBlockParameterName.LATEST).send();
BigInteger nonce = ethGetTransactionCount.getTransactionCount();

// create our transaction
RawTransaction rawTransaction  = RawTransaction.createEtherTransaction(
             nonce, GAS_PRICE, GAS_LIMIT,  "0xc7d9fffaf663c5dfa31b096164cc843c01d0797a", value);

// sign & send our transaction
byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
String hexValue = Numeric.toHexString(signedMessage);
EthSendTransaction ethSendTransaction = web3j.ethSendRawTransaction(hexValue).send();
System.out.println(ethSendTransaction.getTransactionHash());

交易類型(Transaction types)

兩種交易類型:

  • Transaction
  • RawTransaction

不管哪種交易類型,都需要下面的參數(shù):

  • Gas price
  • Gas limit
  • Nonce
  • From

從一個(gè)賬戶發(fā)送以太幣到另外一個(gè)賬戶

RawTransaction

BigInteger value = Convert.toWei("1.0", Convert.Unit.ETHER).toBigInteger();
RawTransaction rawTransaction  = RawTransaction.createEtherTransaction(
             <nonce>, <gas price>, <gas limit>, <toAddress>, value);

Transfer

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();

與智能合約交互

在于智能合約交互時(shí)磕潮,你必須執(zhí)行所有的手動(dòng)轉(zhuǎn)換從solidity類型到本地Java類型翠胰。慶幸的時(shí)容贝,使用web3j的Solidity smart contract wrappers ,它可以幫你完成這些轉(zhuǎn)換之景,你可以很方便地使用斤富。

  1. 創(chuàng)建智能合約,有兩個(gè)屬性:
  • value - 你希望存到智能合約的以太幣
  • 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ù)锻狗,需要提供構(gòu)造參數(shù)满力,必須編碼這些參數(shù)并拼到合約代碼后面:

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...

  1. 發(fā)起交易到智能合約

與存在的智能合約交互,需要提供以下屬性:

  • to - 智能合約地址
  • value - 你希望存到智能合約的以太幣
  • data - 編碼后的調(diào)用的函數(shù)和參數(shù)
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...

交易調(diào)用不可能直接得到返回值轻纪,要獲取返回值油额,必須用Filters and Events

更多關(guān)于函數(shù)編碼的介紹桐磁,請(qǐng)看Application Binary Interface

  1. 查詢智能合約的狀態(tài)

可以通過eth_call這個(gè)JSON-RPC call接口來查詢合約狀態(tài)悔耘,這個(gè)調(diào)用不用花費(fèi)gas讲岁,因?yàn)樗鼪]有改變賬戶的狀態(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)用,或一個(gè)空的結(jié)果,返回值將Collections.emptyList的實(shí)例()

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市缓艳,隨后出現(xiàn)的幾起案子校摩,更是在濱河造成了極大的恐慌,老刑警劉巖阶淘,帶你破解...
    沈念sama閱讀 217,734評(píng)論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衙吩,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡溪窒,警方通過查閱死者的電腦和手機(jī)坤塞,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,931評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來澈蚌,“玉大人摹芙,你說我怎么就攤上這事⊥鹈椋” “怎么了浮禾?”我有些...
    開封第一講書人閱讀 164,133評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長份汗。 經(jīng)常有香客問我盈电,道長,這世上最難降的妖魔是什么杯活? 我笑而不...
    開封第一講書人閱讀 58,532評(píng)論 1 293
  • 正文 為了忘掉前任匆帚,我火速辦了婚禮,結(jié)果婚禮上旁钧,老公的妹妹穿的比我還像新娘卷扮。我一直安慰自己荡澎,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,585評(píng)論 6 392
  • 文/花漫 我一把揭開白布晤锹。 她就那樣靜靜地躺著摩幔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鞭铆。 梳的紋絲不亂的頭發(fā)上或衡,一...
    開封第一講書人閱讀 51,462評(píng)論 1 302
  • 那天,我揣著相機(jī)與錄音车遂,去河邊找鬼封断。 笑死,一個(gè)胖子當(dāng)著我的面吹牛舶担,可吹牛的內(nèi)容都是我干的坡疼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,262評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼衣陶,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼柄瑰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起剪况,我...
    開封第一講書人閱讀 39,153評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤教沾,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后译断,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體授翻,經(jīng)...
    沈念sama閱讀 45,587評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,792評(píng)論 3 336
  • 正文 我和宋清朗相戀三年孙咪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了堪唐。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,919評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡翎蹈,死狀恐怖淮菠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情杨蛋,我是刑警寧澤兜材,帶...
    沈念sama閱讀 35,635評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站逞力,受9級(jí)特大地震影響曙寡,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜寇荧,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,237評(píng)論 3 329
  • 文/蒙蒙 一举庶、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧揩抡,春花似錦户侥、人聲如沸镀琉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,855評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽屋摔。三九已至,卻和暖如春替梨,著一層夾襖步出監(jiān)牢的瞬間钓试,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,983評(píng)論 1 269
  • 我被黑心中介騙來泰國打工副瀑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弓熏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,048評(píng)論 3 370
  • 正文 我出身青樓糠睡,卻偏偏與公主長得像挽鞠,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子狈孔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,864評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • 簡介 不管你們知不知道以太坊(Ethereum blockchain)是什么信认,但是你們大概都聽說過以太坊。最近在新...
    Lilymoana閱讀 3,892評(píng)論 1 22
  • 1 偉大的開拓者-比特幣 1) 比特幣產(chǎn)生 2008年除抛,中本聰(Satoshi Nakamoto)發(fā)表了一...
    金子_c38e閱讀 7,345評(píng)論 0 18
  • 青城雨夜 半生浮云飄北庭狮杨,而立蒼海落南郡母截。 莫道高處天云淡到忽,卻了狂生一世愿。
    無盡狂歌閱讀 140評(píng)論 0 0
  • 褒揚(yáng) 一心二意三色眼清寇,四體五臟六腑健喘漏。 七竅八璞九腸通,十指千夫萬眾羨华烟。 貶斥 一心二意三色晴翩迈,四肢五官...
    文字砌匠閱讀 180評(píng)論 0 3
  • 出生,兩歲那年盔夜。 不知哪里傳來消息负饲,一種類似于“筆仙兒”的無人算命,轉(zhuǎn)到我們村喂链。 相傳返十,每個(gè)村只有一人,能端著鍋拍...
    果慧_631e閱讀 416評(píng)論 5 5