5、Solidity编程语言开发框架之合约交互

背景

标准的与以太坊网络交互的方法是通过以太坊官方构建的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.
});

需要注意的是这是一个交易,会改变网络的状态。技术整理学什么网整理

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
使⽤solidity编程语⾔编写智能合约 智能合约编程语⾔ solidity语⾔ ⽂章⽬录 前⾔ 随着区块链技术的不断发展,区块链被越来越多运⽤到⽣活,什么是区块链智能合约嘞?简单说下,智能合约,就是⼀段写在区块链上的 代码,⼀旦某个事件触发合约的条款,代码即⾃动执⾏。也就是说,满⾜条件就执⾏,不需要⼈为操控。智能合约是区块链上的⼀段程 序,没有智能合约,区块链还是区块链。⽐较扯的是很多链为了让⾃⼰有智能合约,于是移植了兼容以太坊的智能合约功能。⽽solidity语 ⾔的闻名,正是因为使⽤solidity语⾔编写的以太坊智能合约的成功,以太坊的巨⼤成功,使得solidity语⾔⼀夜成名。 ⼀、solidity语⾔是什么? Solidity是⼀种智能合约⾼级语⾔,运⾏在Ethereum虚拟机(EVM)之上。Solidity是⾯向智能合约的编程语⾔。也即Solidity发明出来的 ⽬的就是为了实现智能合约。但是请注意,智能合约的实现⼿段不⽌是Solidity,其他的语⾔⽐如Go, JS等同样可以⽤来实现智能合约。只 不过Solidity专门⽤来做这件事情,是不是就⽐其他的语⾔更好⽤,需要慢慢发现。使⽤solidity语⾔来进⾏智能合约的编程。 以下介绍⼏个有关solidity编程智能合约的⽹站。 1.在线编译运⾏智能合约⽹站 Remix。 2.简单学习区块链智能合约⽹站 cryptozombies。 ⼆、⼀个简单的solidity智能合约 1.编写智能合约 我们⾸先打开在线智能合约⽹站。 创建⼀个新sol⽂件,如图命名为ZombieFactory.sol 开始编写合约,有关僵⼫⼯⼚合约如下: 代码如下(⽰例): pragma solidity ^0.4.19; contract ZombieFactory { event NewZombie(uint zombieId, string name, uint dna); uint dnaDigits = 16; uint dnaModulus = 10 ** dnaDigits; struct Zombie { string name; uint dna; } Zombie[] public zombies; function _createZombie(string _name, uint _dna) private { uint id = zombies.push(Zombie(_name, _dna)) - 1; NewZombie(id, _name, _dna); } function _generateRandomDna(string _str) private view returns (uint) { uint rand = uint(keccak256(_str)); return rand % dnaModulus; } function createRandomZombie(string _name) public { uint randDna = _generateRandomDna(_name); _createZombie(_name, randDna); } } 2.编译合约 注意编译合约,应该选择符合智能合约编写版本的版本要求,这⾥我们选择0.4.19+commit.c4cbbb05.Emscripten.clang编译器版本。 点击开始编译(Ctrl+s)进⾏编译,编译成功之后,在下⽅会出现绿⾊的合约名字,即⼀下界⾯ 这就表⽰智能合约成功编译。 3.部署合约 在智能合约成功编译,之后我们就需要将智能合约部署到区块链上⾯,因为我们在这⾥是进⾏学习测试,因此我们在测试⽹络上⾯部署合 约。在节点环境选择JS虚拟机。选择之后,他就会给你提供测试⽹络上⾯的地址,⾥⾯有100ETH的gas费⽤,⾜够智能合约部署和使⽤的 gas消费。 选择好节点环境之后,接下来正式进⼊部署环节,总共有两种部署⽅式,我们是编写智能合约进⾏部署,因此我们之间点击部署按钮就⾏, 下⽅那个输⼊合约地址进⾏部署,现在暂时⽤不到。 成功部署之后,在下⽅就会显⽰部署成功的合约名字。 在这个ZombieFactory智能合约,有⼀个public⽅法和⼀个数组zombies。 可以调⽤createRandomZombie⽅法创建⾃⼰的Zombie。 注意因为在区块链⽹络上⾯进⾏合约的部署,和调⽤都需要你花费gas进⾏使⽤,就相当于你开⾼速需要油费⼀样。 因此进⾏⼀系列的部署和调⽤之后,该账户的ETH余额会减少。 总结 第⼀次solidity语⾔来部署合约,我感到⼀种想要了解区块链智能合约的迫切感。初探智能合约世界,感到⾃⼰所拥有知识的不⾜,各种编 程语⾔皆有所通,骚年,认真学习吧,哈哈

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值