以太坊Solidity程式語言開發框架————7、合約互動
背景
標準的與以太坊網路互動的方法是通過以太坊官方構建的Web3庫。儘管這個庫非常有用,但使用其提供介面與合約互動有些困難,特別是以太坊的新手。為降低學習曲線,Truffle使用Ether Pudding庫,它也是基於Web3的基礎之上,目的是為了讓互動更簡單。
讀寫資料
以太坊網路把在網路上讀與寫資料進行了區分,這個區分對於如何寫程式影響很大。通常來說,寫資料被稱作交易(transaction)
,讀資料被稱作呼叫(call)
。對於交易與呼叫,他們分別有如下特性:
交易(Transaction)
交易本質上改變了整個以太坊網路的資料狀態。一個交易可以是向另一個帳戶傳送ether(以太坊網路代幣)這樣的簡單行為,也可以是執行合約函式,新增一個新合約到以太坊網路這樣的複雜行為。交易的典型特徵是寫入(或修改)資料。交易需要花費ether,也被稱作gas,交易的執行需要時間。當你通過交易執行一個合約的函式時,你並不能立即得到執行結果,因為交易並不是立即執行的。大多婁情況下,通過執行交易不會返回值;它會返回一個交易的ID.總的來說,交易具有如下特徵:
- 需要gas(Ether)
- 改變網路的狀態
- 不會立即執行
- 不會暴露返回結果(僅有交易ID)
呼叫
呼叫,則與上述的交易非常不同。呼叫可以在網路上執行程式碼,但沒有資料會被改變(也許僅僅是些臨時變數被改變)。呼叫的執行是免費的,典型的行為就是讀取資料。通過呼叫執行一個合約函式,你會立即得到結果。總的來說,呼叫具有如下特徵:
- 免費(不花費gas)
- 不改變網路狀態
- 立即執行
- 有返回結果。
如果選擇,取決於你想幹什麼,或者說想寫資料,還是讀資料。
介面(abstract)
為了來體驗一下合約介面的作用,我們使用框架自帶的預設metacoin的合約例子。
import "ConvertLib.sol";
contract MetaCoin {
mapping (address => uint) balances;
event Transfer(address indexed _from, address indexed _to, uint256 _value);
function MetaCoin() {
balances[tx.origin] = 10000;
}
function sendCoin(address receiver, uint amount) returns(bool sufficient) {
if (balances[msg.sender] < amount) return false;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Transfer(msg.sender, receiver, amount);
return true;
}
function getBalanceInEth(address addr) returns(uint){
return ConvertLib.convert(getBalance(addr),2);
}
function getBalance(address addr) returns(uint) {
return balances[addr];
}
}
合約有三個方法和一個構造方法。所有三個方法可以被執行為交易或呼叫。
現在我們來看看Truffle和Ether Pudding為我們提供的叫MetaCoin
的Javascript物件,可以在前端中使用:
// Print the deployed version of MetaCoin
console.log(MetaCoin.deployed());
// outputs:
//
// Contract
// - address: "0xa9f441a487754e6b27ba044a5a8eb2eec77f6b92"
// - allEvents: ()
// - getBalance: ()
// - getBalanceInEth: ()
// - sendCoin: ()
介面層提供了合約中以應的函式名。它還包含一個地址,指向到MetaCoin合約的部署版本。
執行合約函式
通過這套框架為我們提供的介面,我們可以簡單的在以太坊網路上執行合約函式。
執行交易
在上述例子MetaCoin合約中,我們有三個可以執行的函式。如果你對這三個函式稍加分析就會發現,只有sendCoin
會對網路造成更改。sendCoin
函式的目標將Meta Coin從一個帳戶傳送到另一些帳戶,這些更改需要被永久存下來。
當呼叫sendCoin
,我們將把他們作為一個交易來執行。下面的例子我們來演示下把10個幣,從一個帳戶發到另一個帳戶,改變要永久的儲存在網路上:
var account_one = "0x1234..."; // an address
var account_two = "0xabcd..."; // another address
var meta = MetaCoin.deployed();
meta.sendCoin(account_two, 10, {from: account_one}).then(function(tx_id) {
// If this callback is called, the transaction was successfully processed.
// Note that Ether Pudding takes care of watching the network and triggering
// this callback.
alert("Transaction successful!")
}).catch(function(e) {
// There was an error! Handle it.
})
上述程式碼有一些有趣點,我們來了解一下:
- 我們直接呼叫介面的
sendCoin
函式。最終是預設以交易的方式來執行的。 - 交易被成功執行時,回撥函式會直到交易被執行時才真正被觸發。這樣帶來的一個好處是你不用一直去檢查交易的狀態。
- 我們對
sendCoin
函式傳遞了第三個引數,需要注意的是原始合約函式的定義中並沒有第三個引數。這裡你看到的是一個特殊的物件,用於編輯一些交易中的指定細節,它可以總是做為第三個引數傳進。這裡,我們設定from
的地址為account_one
.
執行呼叫
繼續用MetaCoin的例子。其中的getBalance
函式就是一個很好的從網路中讀取資料的例子。它壓根不需要進行任何資料上的變更,它只是返回傳入的地址的帳戶餘額,我們來簡單看一下:
var account_one = "0x1234..."; // an address
var meta = MetaCoin.deployed();
meta.getBalance.call(account_one, {from: account_one}).then(function(balance) {
// If this callback is called, the call was successfully executed.
// Note that this returns immediately without any waiting.
// Let's print the return value.
console.log(balance.toNumber());
}).catch(function(e) {
// There was an error! Handle it.
})
一些有意思的地方如下:
- 我們必須通過
.call()
來顯示的向以太坊網路表明,我們並不會持久化一些資料變化。 - 我們得到了返回結果,而不是一個交易ID。這裡有個需要注意的是,以太坊網網路可以處理非常大的數字,我們被返回了一個BigNumber物件,框架再將這個物件轉化了一個number型別。
警告:我們在上述的例子中將返回值轉成了一個number型別,是因為例子中的返回值比較小,如果將一個BigNumber轉換為比javascript支援的number最大整數都大,你將會出現錯誤或不可預期的行為。
捕捉事件(Catching Events)
你的合約可以觸發事件,你可以進行捕捉以進行更多的控制。事件API與Web3一樣。可以參考Web3 documentation來了解更多。
var meta = MetaCoin.deployed();
var transfers = meta.Transfer({fromBlock: "latest"});
transfers.watch(function(error, result) {
// This will catch all Transfer events, regardless of how they originated.
if (error == null) {
console.log(result.args);
}
}
METHOD:DEPLOYED()
每一個抽象出來的合約介面都有一個deployed()
方法,上述例子中,你已經見到過。呼叫這個函式返回一個例項,這個例項代表的是之前部署到網路的合約所對應的抽象介面的例項。
var meta = MetaCoin.deployed();
警告:這僅對使用truffle deploy
部署的合約,且一定是在project configuration
中配置釋出的才有效。如果不是這樣,這個函式執行時會丟擲異常。
METHOD:AT()
類似於deployed()
,你可以通過一個地址來得到一個代表合約的抽象介面例項。當然這個地址一定是這個合約的部署地址。
var meta = MetaCoin.at("0x1234...")
警告:當你的地址不正確,或地址對應的合約不正確時,這個函式並不會丟擲異常。但呼叫介面時會報錯。請保證在使用at()
時輸入正確的地址。
METHOD:NEW()
你可以通過這個方法來部署一個完全全新的合約到網路中。
MetaCoin.new().then(function(instance) {
// `instance` is a new instance of the abstraction.
// If this callback is called, the deployment was successful.
console.log(instance.address);
}).catch(function(e) {
// There was an error! Handle it.
});
需要注意的是這是一個交易,會改變網路的狀態。
如果任何問題,歡迎留言批評指正。
相關文章
- 以太坊Solidity程式語言開發框架————4、編譯合約Solid框架編譯
- 以太坊Solidity程式語言開發框架————8、測試合約Solid框架
- 以太坊Solidity程式語言開發框架————5、移植Solid框架
- 以太坊Solidity程式語言開發框架————9、控制檯Solid框架
- 以太坊Solidity程式語言開發框架————1、Truffle簡介Solid框架
- 以太坊Solidity程式語言開發框架————10、外部指令碼Solid框架指令碼
- 以太坊Solidity程式語言開發框架————11、工作流Solid框架
- 以太坊Solidity程式語言開發框架————13、配置檔案Solid框架
- 以太坊Solidity程式語言開發框架————15、構建流程Solid框架
- 以太坊Solidity程式語言開發框架————16、Truffle命令指南Solid框架
- 以太坊Solidity程式語言開發框架————12、聯絡開發者Solid框架
- 以太坊Solidity程式語言開發框架————3、建立一個工程Solid框架
- 以太坊Solidity程式語言開發框架————6、構建應用Solid框架
- 以太坊Solidity程式語言開發框架————2、網路與APP部署Solid框架APP
- 以太坊Solidity程式語言開發框架————14、網路與APP部署Solid框架APP
- olidity語言開發以太坊智慧合約中的繼承繼承
- 以太坊智慧合約開發第五篇:字串拼接—Solidity字串Solid
- 以太坊智慧合約開發第七篇:智慧合約與網頁互動網頁
- 以太坊智慧合約開發第六篇:truffle開發框架框架
- 用solidity語言開發代幣智慧合約Solid
- 區塊鏈2.0以太坊智慧合約solidity之helloworld區塊鏈Solid
- 分投趣fintoch系統合約開發分析(Solidity程式語言)Solid
- 以太坊智慧合約開發第二篇:理解以太坊相關概念
- eth以太坊智慧合約交易平臺開發
- Conflux與以太坊合約開發工具區別UX
- 智慧合約語言 Solidity 教程系列8 - Solidity APISolidAPI
- 智慧合約語言 Solidity 教程系列8 – Solidity APISolidAPI
- 以太坊開發實戰學習-合約安全(八)
- Forsage佛薩奇合約矩陣(Solidity程式語言)系統開發程式碼詳情矩陣Solid
- 以太坊蜜罐智慧合約分析
- 以太坊智慧合約開發第四篇:實現Hello World智慧合約
- 太坊智慧合約開發第一篇:IDE對solidity語法的支援IDESolid
- NFT鑄造合成LP質押挖礦系統合約開發丨Solidity程式語言Solid
- 以太坊 solidity 隨機抽獎合約——搏一搏,單車變摩托Solid隨機
- 以太坊智慧合約升級策略
- 以太坊智慧合約-猜數字
- Solidity語言學習筆記————32、建立合約Solid筆記
- 智慧合約語言Solidity的最佳VSCode 外掛SolidVSCode