1. 程式人生 > >以太坊學習7--Web3j和智慧合約

以太坊學習7--Web3j和智慧合約

一、Web3j入門

以太坊推出了web3.js的nodejs庫,但是對於學Java出身的而言非常的不習慣,在github中尋找到了Java版本的web3j。輕量級客戶端與以太坊互動的Java庫。
web3j github地址:https://github.com/web3j/web3j
web3j 文件地址:https://web3j.readthedocs.io/en/latest/

一個簡單的例子:
1、建立一個maven專案
2、增加dependencies

<dependency>
   <groupId>org.web3j</groupId>
   <artifactId
>
core</artifactId> <version>3.3.1</version> </dependency>
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.Web3ClientVersion;
import org.web3j.protocol.http.HttpService;

public class Web3Blog1_1 {
    public static void main(String[] args) throws Exception{
        Web3j web3 = Web3j.build
(new HttpService("https://ropsten.infura.io/rq6f6P9wex66SUNzvnDz")); Web3ClientVersion web3ClientVersion = web3.web3ClientVersion().send(); String clientVersion = web3ClientVersion.getWeb3ClientVersion(); System.out.println(clientVersion); } }

這裡寫圖片描述
注:
1.程式碼地址為:https://mainnet.infura.io/rq6f6P9wex66SUNzvnDz


輸出結果為:Geth/v1.8.13-patched-infura-omnibus-b59d4428/linux-amd64/go1.9.2
2.程式碼地址為:https://infuranet.infura.io/rq6f6P9wex66SUNzvnDz
輸出結果為:Parity//v1.6.6-beta-8c6e3f3-20170411/x86_64-linux-gnu/rustc1.16.0
3.程式碼地址為:https://kovan.infura.io/rq6f6P9wex66SUNzvnDz
輸出結果為:Parity//v1.10.6-stable-bc0d134-20180605/x86_64-linux-gnu/rustc1.26.1
4.程式碼地址為:https://rinkeby.infura.io/rq6f6P9wex66SUNzvnDz
輸出結果為:Geth/v1.8.13-stable/linux-amd64/go1.9.2

二、Transaction轉賬

為了完成以太坊交易,必須有幾個先決條件
1、對方的以太坊地址
2、確定要轉賬的金額
3、自己地址的轉賬許可權
4、大於轉賬金額的以太幣,以太幣轉賬其實就是提出一個交易,礦工會幫你計算,計算完成即達成交易,但是礦工計算需要支付一定的費用(GAS),支付過少,計算轉賬就有可能很慢或者不成功。
 
轉賬方式1:

import org.web3j.crypto.Credentials;
import org.web3j.crypto.RawTransaction;
import org.web3j.crypto.TransactionEncoder;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameterName;
import org.web3j.protocol.core.methods.response.EthGetTransactionCount;
import org.web3j.protocol.core.methods.response.EthSendTransaction;
import org.web3j.protocol.http.HttpService;
import org.web3j.utils.Convert;
import org.web3j.utils.Numeric;

import java.math.BigInteger;


public class TransactionTest {
    public static void main(String[] args) throws Exception {
        //設定需要的礦工費
        BigInteger GAS_PRICE = BigInteger.valueOf(22_000_000_000L);
        BigInteger GAS_LIMIT = BigInteger.valueOf(4_300_000);

        //呼叫的是kovan測試環境,這裡使用的是infura這個客戶端
        Web3j web3j = Web3j.build(new HttpService("https://kovan.infura.io/<your-token>"));
        //轉賬人賬戶地址
        String ownAddress = "0xD1c82c71cC567d63Fd53D5B91dcAC6156E5B96B3";
        //被轉人賬戶地址
        String toAddress = "0x6e27727bbb9f0140024a62822f013385f4194999";
        //轉賬人私鑰
        Credentials credentials = Credentials.create("xxxxxxxxxxxxx");
        //        Credentials credentials = WalletUtils.loadCredentials(
        //                "123",
        //                "src/main/resources/UTC--2018-03-01T05-53-37.043Z--d1c82c71cc567d63fd53d5b91dcac6156e5b96b3");

        EthGetTransactionCount ethGetTransactionCount = web3j.ethGetTransactionCount(
                ownAddress, DefaultBlockParameterName.LATEST).sendAsync().get();
        BigInteger nonce = ethGetTransactionCount.getTransactionCount();

        //建立交易,這裡是轉0.5個以太幣
        BigInteger value = Convert.toWei("0.5", Convert.Unit.ETHER).toBigInteger();
        RawTransaction rawTransaction = RawTransaction.createEtherTransaction(
                nonce, GAS_PRICE, GAS_LIMIT, toAddress, value);

        //簽名Transaction,這裡要對交易做簽名
        byte[] signedMessage = TransactionEncoder.signMessage(rawTransaction, credentials);
        String hexValue = Numeric.toHexString(signedMessage);

        //傳送交易
        EthSendTransaction ethSendTransaction =
                web3j.ethSendRawTransaction(hexValue).sendAsync().get();
        String transactionHash = ethSendTransaction.getTransactionHash();

        //獲得到transactionHash後就可以到以太坊的網站上查詢這筆交易的狀態了
        System.out.println(transactionHash);
    }
}

這裡寫圖片描述

1、第27-31行,可以用兩種方式獲得地址的信任憑證,一種是直接使用私鑰,一種是使用keystore檔案
2、https://kovan.etherscan.io/tx/0x0d29fa7db4503f94fd6f4c7894a1fb21a628d96f48f408efc19554d812628a81
這個地址是可以查到你的這筆交易的
0x0d29fa7db4503f94fd6f4c7894a1fb21a628d96f48f408efc19554d812628a81是transactionHash
這個地址是測試地址,如果需要查詢主網上的,刪除kovan
 
轉賬方式2:

import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.Transfer;
import org.web3j.utils.Convert;

import java.math.BigDecimal;

public class TransactionTest2 {
    public static void main(String[] args) throws Exception {
        Web3j web3j = Web3j.build(new HttpService("https://kovan.infura.io/<your-token>"));
        // 被轉人賬戶地址
        String toAddress = "0x6e27727bbb9f0140024a62822f013385f4194999";
        // 轉賬人私鑰
        Credentials credentials = Credentials.create("xxxxxxxx");

        TransactionReceipt transactionReceipt = Transfer.sendFunds(
                web3j, credentials, toAddress,
                BigDecimal.valueOf(0.2), Convert.Unit.ETHER).send();

        System.out.println(transactionReceipt.getTransactionHash());
    }
}

這裡寫圖片描述
注意:
這兩種方式都是離線的,但是第二種程式碼量比較小。

備註:
如果在kovan環境中沒有以太幣的話,可以到https://gitter.im/kovan-testnet/faucet這裡去要,直接註冊賬號之後,把你的賬號地址發到群裡就行了,過幾分鐘就會給你轉錢的(每次只給你轉3個eth且中間間隔為6天),主網的賬號地址和kovan是一樣的,但是裡面的幣是不一樣的。
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
 

三、智慧合約

1、首先我們需要一份寫好的智慧合約

pragma solidity ^0.4.18;

// Example taken from https://www.ethereum.org/greeter, also used in
// https://github.com/ethereum/go-ethereum/wiki/Contract-Tutorial#your-first-citizen-the-greeter

contract mortal {
    /* Define variable owner of the type address*/
    address owner;

    /* this function is executed at initialization and sets the owner of the contract */
    function mortal() { owner = msg.sender; }

    /* Function to recover the funds on the contract */
    function kill() { if (msg.sender == owner) suicide(owner); }
}

contract greeter is mortal {
    /* define variable greeting of the type string */
    string greeting;

    /* this runs when the contract is executed */
    function greeter(string _greeting) public {
        greeting = _greeting;
    }

    /* main function */
    function greet() constant returns (string) {
        return greeting;
    }
}

2、進入https://remix.ethereum.org/ 網站,此網站是線上智慧合約編譯網站,所以比較簡便,不需要安裝truffle等工具
這裡寫圖片描述
點選圖示中details按鈕,會出現智慧合約的ABI和BIN
注:對已經部署好的智慧合約也可以直接在https://etherscan.io/查詢獲得
這裡寫圖片描述
這裡寫圖片描述

這裡寫圖片描述
將BYTECODE中的object複製下來儲存成greeter.bin,點選ABI(Application Binary Interface:應用程式二進位制介面,定義了智慧合約提供的方法功能)旁邊的複製按鈕將其儲存成greeter.abi

進入https://github.com/web3j/web3j/releases/tag/v3.3.1網站,下載web3j-3.3.1.tar,並解壓。
這裡寫圖片描述
進入目錄bin下,將greeter.bin和greeter.abi,複製到目錄下,在此目錄命令列執行

web3j solidity generate --javaTypes greeter.bin greeter.abi -o src/ -p com.your.organisation.name

web3j solidity generate [–javaTypes|–solidityTypes] /path/to/.bin /path/to/.abi -o /path/to/src/main/java -p com.your.organisation.name
-o 是原始碼要放的目錄,-p是包名,–javaTypes也可以選擇–solidityTypes
生成出來Greeter.java
這裡寫圖片描述

import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;

public class Greeter extends Contract {
    private static final String BINARY = "6060604052341561000f57600080fd5b6040516103203803806103208339810160405280805160008054600160a060020a03191633600160a060020a03161790559190910190506001818051610059929160200190610060565b50506100fb565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106100a157805160ff19168380011785556100ce565b828001600101855582156100ce579182015b828111156100ce5782518255916020019190600101906100b3565b506100da9291506100de565b5090565b6100f891905b808211156100da57600081556001016100e4565b90565b6102168061010a6000396000f30060606040526004361061004b5763ffffffff7c010000000000000000000000000000000000000000000000000000000060003504166341c0e1b58114610050578063cfae321714610065575b600080fd5b341561005b57600080fd5b6100636100ef565b005b341561007057600080fd5b610078610130565b60405160208082528190810183818151815260200191508051906020019080838360005b838110156100b457808201518382015260200161009c565b50505050905090810190601f1680156100e15780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b6000543373ffffffffffffffffffffffffffffffffffffffff9081169116141561012e5760005473ffffffffffffffffffffffffffffffffffffffff16ff5b565b6101386101d8565b60018054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156101ce5780601f106101a3576101008083540402835291602001916101ce565b820191906000526020600020905b8154815290600101906020018083116101b157829003601f168201915b5050505050905090565b602060405190810160405260008152905600a165627a7a723058209dd925f8a845985cc97b98b1d11e67cb72915d7316a7eeb4e28cec3f5f398c9f0029";

    protected Greeter(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    protected Greeter(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }

    public RemoteCall<TransactionReceipt> kill() {
        Function function = new Function(
                "kill",
                Arrays.<Type>asList(),
                Collections.<TypeReference<?>>emptyList());
        return executeRemoteCallTransaction(function);
    }

    public RemoteCall<String> greet() {
        Function function = new Function("greet",
                Arrays.<Type>asList(),
                Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
        return executeRemoteCallSingleValueReturn(function, String.class);
    }

    public static RemoteCall<Greeter> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, String _greeting) {
        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(_greeting)));
        return deployRemoteCall(Greeter.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor);
    }

    public static RemoteCall<Greeter> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, String _greeting) {
        String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(new org.web3j.abi.datatypes.Utf8String(_greeting)));
        return deployRemoteCall(Greeter.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor);
    }

    public static Greeter load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
        return new Greeter(contractAddress, web3j, credentials, gasPrice, gasLimit);
    }

    public static Greeter load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
        return new Greeter(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
    }
}

3、部署智慧合約

import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.http.HttpService;
import org.web3j.tx.Contract;

public class SmartContractTest {
    public static void main(String[] args) throws Exception {
        Web3j web3j = Web3j.build(new HttpService("https://kovan.infura.io/<your-token>"));
        Credentials credentials = Credentials.create("xxxxxxxxxxxxxxxxxxx");
        //部署智慧合約
        Greeter greeter = Greeter.deploy(web3j,credentials,Contract.GAS_PRICE,Contract.GAS_LIMIT,"zx").send();
        System.out.println(greeter.getContractAddress());
        //呼叫智慧合約
        System.out.println(greeter.greet().send());
    }
}

相關推薦

學習7--Web3j智慧合約

一、Web3j入門 以太坊推出了web3.js的nodejs庫,但是對於學Java出身的而言非常的不習慣,在github中尋找到了Java版本的web3j。輕量級客戶端與以太坊互動的Java庫。 web3j github地址:https://github.c

web3j教程:過濾器(filter)篩選智慧合約事件(event)監聽

web3j過濾器提供以太坊網路發生的某些事件的通知,對java和安卓程式設計師來說很有用。在Ethereum以太坊中支援三類過濾器: 塊濾波器(Block filters) 未決交易過濾器(Pending transaction filters) 主題過濾器

java開發使用web3jspring boot構建區塊鏈應用

區塊鏈最近IT世界的流行語之一。這項有關數字加密貨幣的技術,並與比特幣一起構成了這個熱門的流行趨勢。它是去中心化的,不可變的分塊資料結構,這是可以安全連線和使用的密碼演算法。在這種結構中的每一區塊通常包含前一個區塊的加密雜湊,一個時間戳,和交易資料。區塊鏈是點對點管理網路的,

Dapp專案-拍賣網站-智慧合約編寫測試

修訂日期 姓名 郵箱 2018-10-18 brucefeng [email protected] 前言 寫這篇文章的初衷其實很簡單,在MyEtherWallet上申請以太坊ENS的時候

使用ENS自定義智慧合約的地址管理

我們的目標是支援以太坊錢包和信用卡支付,以減少技術嫻熟的客戶的依賴。如果客戶決定使用信用卡付款,我們必須使用我們的錢包並代他付款。 為此,我們決定在Ruby中構建後端,並在React中使用兩個分散的前端客戶端(dApp)。我們還利用了web3,這是最成熟的庫,允許連線到以太坊節點。由於它

DAO之流動民主智慧合約

Decentralized Autonomous Organization,簡稱DAO,以太坊中重要的概念。一般翻譯為去中心化的自治組織。 投票支付合約的所有費用和行動需要時間,並要求使用者始終保持活躍,知情和專注。另一個有趣的方法是選擇一個可以控制合約的指定賬戶,然後能夠迅速做出決定。

區塊鏈開發(六)系統下truffle構建智慧合約

truffle環境安裝 針對truffle 環境安裝這裡不多敘述,可以搜一下… 初始化 開啟終端建立一個目錄 mkdir test cd test truffle init 會生成檔案 新建合約檔案 然後可以用vscod

學習7)利用RPC-JSON【post|get】與節點進行互動【2】關於呼叫eth_sendTransaction失敗的檢查方法

關於呼叫eth_sendTransaction失敗的檢查方法 本篇主要講利用JSON-RPC介面呼叫以太坊中已經部署好的合約函式時,如果出現呼叫失敗的檢查方法。  前置知識: 呼叫eth_sendTransaction所需的abi編碼:https:/

學習(二)--geth入門命令miner.start返回null的問題

geth --datadir "./ethdev" --nodiscover console 2>>geth.log  //geth 進入控制檯 --datadir 指定鏈的目錄 與公有鏈區分開進入命令列模式,其中引數–datadir 代表資料夾地址,–nodis

學習之Java開發框架web3j的使用---部署合約

智慧合約名以 HelloContract 為例 1,編譯合約原始碼 命令:solc HelloContract.sol –bin –abi –optimize -o outputPath solc .sol –bin

從零構建(Ethereum)智能合約到項目實戰——學習筆記7

framework 地址 查看 數組 mic ont 案例 ray 測試 P28 、1-Solidity Types - 地址(Address) - 初識 P29 、2-Solidity Types - 地址(Address) - msg.P 、senderP30 、3

學習6--智慧合約的線上IDE工具

導語: Remix有哪些功能? 開發智慧合約(集成了solidity語言的編輯器) 動態除錯(debug)智慧合約 訪問已部署的智慧合約的狀態和屬性 程式碼分析,給出錯誤提示,並給出最佳實踐的提示 除錯和測試Dapp(需要藉助於Mist或者其它注入

學習筆記(七)——Truffle整合Nodejs

這篇文章的內容緊接著上章的內容,上一篇講了truffle合約部署的基本操作,文章最後講了通過console來呼叫部署成功的合約中的方法,之所以truffle console能夠直接呼叫合約中的方式,是因

學習(5)利用Web3.js與節點互動【1】

利用Web3.js與節點互動  一、環境配置 【寫在最前:本文用到的主要工具:node.js+geth+ web3.js 1.0.0-beta.18】 1、確保已經安裝node.js 個人在debian9上安裝nodejs的經歷比較坎坷,但是據說ubuntu上安裝方便

學習(6)關於web3.js 1.0版本中event事件無法觸發的問題

關於web3.js 1.0版本中event事件無法觸發的問題 寫在最前:請檢查你的provider連線方式,http provider已不支援event事件的觸發了 具體請看官方源文件 一、問題還原: (1)先給出智慧合約程式碼 合約內容比較簡單 deposi

學習(8)編寫C++程式與節點進行互動【2】

編寫C++程式與節點進行互動 【1】簡單版本,需對http request有一定了解,以及QT的基本操作  【2】進行類的封裝,個人水平有限,如有紕漏,請下方留言   測試環境: debian 9 QT 5.5 geth/v1.8.1

學習(::)簡單專案實戰

簡單專案實戰 目的:以html+js構建網頁,展示鏈上資訊。 一、合約 合約內容: 用結構體user記錄【使用者】個人資訊,對映為users 用結構體consignment記錄【電能】交易訂單,對映為orders 利用call獲取訂單的資訊

學習(9)關於geth搭建私有鏈下呼叫合約遇到require (false)會消耗完所有gas的解決方案【國內首發】

關於geth搭建私有鏈下呼叫合約遇到require (false)會消耗完所有gas的解決方案 如果你沒遇到過這個問題,你會覺得很奇怪,Solidity的關鍵字require,根據用法解釋:https://ethfans.org/posts/when-to-use-revert-as

原始碼深入分析(3)-- RPC通訊例項原理程式碼分析(上)

上一節提到,以太坊在node start的時候啟動了RPC服務,以太坊通過Rpc服務來實現以太坊相關介面的遠端呼叫。這節我們用個例項來看看以太坊 RPC是如何工作的,以及以太坊RPC的原始碼的實現一,RPC通訊例項1,RPC啟動命令 :geth --rpcgo-ethereu

學習(五)--ubuntu下安裝atom編輯器

在你的Ubuntu安裝AtomPPA安裝,開啟終端使用以下命令安裝:sudo add-apt-repository ppa:webupd8team/atom sudo apt-get update sudo apt-get install atom 解除安裝Atomsudo apt-get remove at