1. 程式人生 > >c#實戰開發:用.net core開發一個簡單的Web以太坊錢包 (六)

c#實戰開發:用.net core開發一個簡單的Web以太坊錢包 (六)

今天就來開發一個C# 版的簡易錢包 先回顧以前的內容

先看一下視覺化錢包有哪些功能呢?

那這個錢包得有什麼功能呢? 

1.檢視使用者

2.檢視交易記錄

3.轉賬

4.釋出智慧合約

5.代幣轉賬

6.代幣查詢

7.實時同步區塊對比

8.智慧填寫手續費

首先新建一個專案 匯入以太坊.net實現類庫

Install-Package Nethereum.Geth -Version 2.5.1

安裝完 

初始物件 記住初始化連線記得把Geth客戶端開啟建立連線

private const string url = "http://localhost:8546/";
private static Web3Geth Web3 
= new Web3Geth(url);

這個url埠號就是你的公鏈埠 可以不填直接預設 

private static Web3Geth Web3 = new Web3Geth();

接下來我們來一一實現功能  可以先用私鏈測試結果 不會的看前面的文章導讀

1.使用者操作

首先新增一個使用者  

string passPhrase = "a123456";
var Result = await Web3.Personal.NewAccount.SendRequestAsync(passPhrase);

 傳入使用者密碼 等待非同步結果返回 使用者公鑰 

使用者新增好了

 查詢餘額  把剛剛新建的使用者地址傳入

var Result = await Web3.Eth.GetBalance.SendRequestAsync(address);

如果不知道命令可以看

以太坊API中文文件:http://web3.tryblockchain.org/Web3.js-api-refrence.html  

2.以太坊操作

首先考慮錢包的穩定性和同步的差異性 要讓轉賬有效   就要多準備幾個客戶端 防客戶端死掉 先模擬三個客戶端IP

private const string url1 = "http://localhost:8545/";
private const string url2 = "http://localhost:8546/
"; private const string url3 = "http://localhost:8547/";
private static Web3Geth 1Web3 = new Web3Geth(url1);
private static Web3Geth 2Web3 = new Web3Geth(url2);
private static Web3Geth 3Web3 = new Web3Geth(url3);

怎麼知道哪個客戶端死掉了呢?

 var BlockNumber =await Web3.Eth.Blocks.GetBlockNumber.SendRequestAsync();

獲取的當前客戶端區塊同步高度 0就直接切換 初始化物件繼續查     比如在查到5400  但是以太坊瀏覽器上同步區塊是5800 這時你的客戶端同步差異性  區塊太別太大? 手續費輸入多少?

看以太坊的區塊鏈也不是及時同步 怎麼辦呢?

好在發現了一個區塊鏈同步網站

 https://ethstats.net/

可以看到最新的區塊高度 和交易手續費  每秒都在刷  底下各大節點同步最新的資料  把這些資料拿到就可以知道我的客戶端區塊和最高區塊的差距 已經當前最新手續費  這樣可以告訴要轉賬的人 最合理的手續費輸入值。  

我們可以用  HttpClient 但是建立連線之後資料相應太慢根本不能做到實時推送給使用者最新的區塊記錄和手續費 。

不過認真觀察了一下應該是用的websocket 所以

地址被我找到了  這樣就不用爬了  用他的地址寫成exe客戶端建立連線

var ws = new WebSocket("wss://ethstats.net")

但是發現數據不準 什麼情況  發現後面有一個引數

_primuscb=1536930413898-0    那他的規則是什麼呢?

數了一個10秒請求一個新連線 之間沒有回傳 那這個規則只能是寫在JS了 

整整3萬行 不過還是被我找到了

new data()

原來是獲取當前js的時間戳+1;

DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1));
long timeStamp = (long)(DateTime.Now - startTime).TotalMilliseconds+1;
using (var ws = new WebSocket("wss://ethstats.net/primus/?_primuscb=" + timeStamp + "-0"))

不過資料太多要對獲取資料進行篩選 

這些都做好了 就準備轉賬了 先要解鎖要轉賬的使用者

 ulong? ul = null;
 var resultunlock =await Web3.Personal.UnlockAccount.SendRequestAsync(From, FromPassPhrase, ul);

ul  解鎖時間   空預設一次   from 使用者地址    from 使用者地址的私鑰

//轉賬
 var txId = Web3.Eth.Transactions.SendTransaction.SendRequestAsync(
new TransactionInput { From = From, To = To, Value = new HexBigInteger(long.Parse(GasPrice)), Gas = new HexBigInteger(long.Parse(GasLimit)) }).Result;

From  要轉賬地址  To 被轉賬地址    GasPrice 轉賬可以數量   Gas 數量  可以直接用 websocket 獲取到最新的資料 填入 GasPrice,Gas 

轉賬成功後  會返回交易雜湊 可以在以太坊瀏覽器上檢視

把剛剛的交易回傳的雜湊傳入 看交易詳情

Transaction Result =await Web3.Eth.Transactions.GetTransactionByHash.SendRequestAsync(txId);

3.智慧合約

首先生成智慧合約abi 網站

https://ethereum.github.io/browser-solidity/#optimize=false&version=soljson-v0.4.24+commit.e67f0147.js

   public static string BYTECODE = "0x6060......5654“

很長

  var senderAddress = "0x12890d2cce102216644c59daE5baed380d84830c";
 var privatekey = "0xb5b1870957d373ef0eeffecc6e4812c0fd08f554b37b233526acc331bf1544f7";
var url = "https://rinkeby.infura.io/";
var deploymentMessage = new StandardTokenDeployment
            {
                TotalSupply = 100000,
                FromAddress = senderAddress
            };
 var web3 = new Web3.Web3(new Account(privatekey), url);

            var deploymentHandler = web3.Eth.GetContractDeploymentHandler<StandardTokenDeployment>();
            var transactionReceipt = await deploymentHandler.SendRequestAndWaitForReceiptAsync(deploymentMessage);

            ContractAddress = transactionReceipt.ContractAddress;

先獲取發只能合約使用者的私鑰 讓後

填入釋出數量 名字 返回合約雜湊

var senderAddress = "0x12890d2cce102216644c59daE5baed380d84830c";
 var balanceOfFunctionMessage = new BalanceOfFunction()
            {
                Owner = senderAddress,
            };
     var balanceHandler = web3.Eth.GetContractQueryHandler<BalanceOfFunction>();
            var balance = await balanceHandler.QueryAsync<BigInteger>(balanceOfFunctionMessage, contractAddress);

查詢合同剩餘幣數  讓後就是合同代筆轉賬

 var senderAddress = "0x12890d2cce102216644c59daE5baed380d84830c";
            var receiverAddress = "0xde0B295669a9FD93d5F28D9Ec85E40f4cb697BAe";
            var privatekey = "0xb5b1870957d373ef0eeffecc6e4812c0fd08f554b37b233526acc331bf1544f7";
            var url = "https://rinkeby.infura.io/";

var web3 =  new Web3.Web3(new Account(privatekey), url);

     var transactionMessage = new TransferFunction()
            {
                FromAddress = senderAddress,
                To = receiverAddress,
                TokenAmount = 100,
                //Set our own price
                GasPrice =  Web3.Web3.Convert.ToWei(25, UnitConversion.EthUnit.Gwei)
                
            };


  var transferHandler = web3.Eth.GetContractTransactionHandler<TransferFunction>();

            /// this is done automatically so is not needed.
            var estimate = await transferHandler.EstimateGasAsync(transactionMessage, ContractAddress);
            transactionMessage.Gas = estimate.Value;


            var transactionHash = await transferHandler.SendRequestAsync(transactionMessage, ContractAddress);

最後返回交易雜湊  

一下是上面用到的開源例項庫 他還可以還發以太坊遊戲 

https://nethereum.readthedocs.io/en/latest/introduction/web3/

https://github.com/Nethereum/Nethereum

因為是開源的大家可以自己去學習  

https://gitter.im/Nethereum/Nethereum  ETH學習論壇

智慧合約

https://github.com/Nethereum/Nethereum/blob/master/src/Nethereum.Accounts.IntegrationTests/SignOfflineTransactionTest.cs#L23-L39

https://github.com/Nethereum/Nethereum.Workbooks/blob/master/docs/nethereum-infura-transfer.workbook

https://github.com/Nethereum/Nethereum.Workbooks/blob/master/docs/nethereum-cqs-test.workbook

至此 大致功能已經完成! 感謝觀看! 下期比特幣!