Nethereum以太坊開發快速入門
Nethereum基本上是目前唯一可用的.NET平臺下的web3.js移植包。在這個教程中,我們將首先編寫並部署一個簡單的智慧合約,然後建立一個簡單的.NET應用,並使用Nethereum來訪問以太坊上的智慧合約。Nethereum是通過以太坊節點旳標準RPC介面訪問智慧合約,因此使用Nethereum可以對接所有的以太坊節點實現,例如geth或parity。
如果你希望快速掌握Netherem的開發,可以訪問匯智網的互動教程C#以太坊開發詳解,技術問題可以直接諮詢課程助教。
智慧合約開發與部署
首先安裝開發用以太坊節點軟體Ganache:
~$ npm install -g ganache-cli
然後安裝以太坊開發框架Truffle:
~$ npm install -g truffle
現在建立一個專案目錄,進入該目錄,並執行truffle init
進行初始化:
~$ mkdir demo && cd hubwiz
~/hubwiz$ truffle init
truffle會建立一些新的資料夾:contract、test、migration等。在contract資料夾中,建立一個新的合約檔案Vote.sol:
~/hubwiz/contracts$ touch Vote.sol
按如下內容編輯Vote.sol,這個合約只是簡單地跟蹤兩個候選人的得票數,它使用交易發起賬戶作為投票人,並且每個賬戶只能投一票:
pragma solidity ^0.4.16; contract Vote { uint public candidate1; uint public candidate2; mapping (address => bool) public voted; function castVote(uint candidate) public { require(!voted[msg.sender] && (candidate == 1 || candidate == 2)); if(candidate == 1){ candidate1++; }else{ candidate2++; } voted[msg.sender] = true; } }
接下來在migration資料夾建立一個新的js檔案2_vote.js,內容如下:
var vote = artifacts.require("Vote");
module.exports = function(deployer) {
// deployment steps
deployer.deploy(vote);
};
然後開啟專案資料夾下的truffle.js,用以下內容替換:
module.exports = {
networks: {
ganache: {
host: "127.0.0.1",
port: 7545,
network_id: "*" // Match any network id
}
}
};
現在開啟一個終端,啟動ganache:
~$ ganache-cli
然後開啟另一個終端,用truffle部署合約:
~/hubwiz$ truffle deploy --reset --network ganache
你會看到終端輸出類似下面的合約地址,拷貝下來,後面還要用到:
Vote: 0xe4e47451aad6c89a6d9e4ad104a7b77ffe1d3b36
.Net應用開發與智慧合約訪問
建立一個新的控制檯專案,新增對如下開發包的依賴:
- Nethereum.Web3
- Nethereum.Contracts
然後按如下內容修改program.cs:
using System;
using System.Numerics;
using System.Threading.Tasks;
using Nethereum.Contracts;
using Nethereum.Hex.HexTypes;
using Nethereum.Web3;
namespace console
{
class Program
{
static void Main(string[] args)
{
//The URL endpoint for the blockchain network.
string url = "HTTP://localhost:7545";
//The contract address:合約部署的地址
string address = "0x345cA3e014Aaf5dcA488057592ee47305D9B3e10";
//The ABI for the contract.
string ABI = @"[{'constant':true,'inputs':[],'name':'candidate1','outputs':[{'name':'','type':'uint256'}],'payable':false,'stateMutability':'view','type':'function'},{'constant':false,'inputs':[{'name':'candidate','type':'uint256'}],'name':'castVote','outputs':[],'payable':false,'stateMutability':'nonpayable','type':'function'},{'constant':true,'inputs':[],'name':'candidate2','outputs':[{'name':'','type':'uint256'}],'payable':false,'stateMutability':'view','type':'function'},{'constant':true,'inputs':[{'name':'','type':'address'}],'name':'voted','outputs':[{'name':'','type':'bool'}],'payable':false,'stateMutability':'view','type':'function'}]";
//Creates the connecto to the network and gets an instance of the contract.
Web3 web3 = new Web3(url);
Contract voteContract = web3.Eth.GetContract(ABI, address);
//Reads the vote count for Candidate 1 and Candidate 2
Task<BigInteger> candidate1Function = voteContract.GetFunction("candidate1").CallAsync<BigInteger>();
candidate1Function.Wait();
int candidate1 = (int)candidate1Function.Result;
Task<BigInteger> candidate2Function = voteContract.GetFunction("candidate2").CallAsync<BigInteger>();
candidate2Function.Wait();
int candidate2 = (int)candidate2Function.Result;
Console.WriteLine("Candidate 1 votes: {0}", candidate1);
Console.WriteLine("Candidate 2 votes: {0}", candidate2);
//Prompts for the account address.
Console.Write("Enter the address of your account: ");
string accountAddress = Console.ReadLine();
//Prompts for the users vote.
int vote = 0;
Console.Write("Press 1 to vote for candidate 1, Press 2 to vote for candidate 2: ");
Int32.TryParse(Convert.ToChar(Console.Read()).ToString(), out vote);
Console.WriteLine("You pressed {0}", vote);
//Executes the vote on the contract.
try{
HexBigInteger gas = new HexBigInteger(new BigInteger(400000));
HexBigInteger value = new HexBigInteger(new BigInteger(0));
Task<string> castVoteFunction = voteContract.GetFunction("castVote").SendTransactionAsync(accountAddress, gas, value, vote);
castVoteFunction.Wait();
Console.WriteLine("Vote Cast!");
}catch(Exception e){
Console.WriteLine("Error: {0}", e.Message);
}
}
}
}
別忘了用你自己部署的合約地址修改上面程式碼中的合約地址。現在執行應用,就可以投票了!
用Nethereum很容易就可以為.Net應用新增訪問以太坊智慧合約的能力,由於Nethereum基於.NET平臺,因此它可以用於.NET Core應用、.NET Standard應用、Xamarin以及各種windows應用中。