智能合约开发 - 如何更好的与合约交互

我们从一个简单的例子开始:


pragma solidity ^0.4.0;

contract Calc{
  uint count;

  function add(uint a, uint b) returns(uint){
    count++;
    return a + b;
  }

  function getCount() constant returns (uint){
    return count;
  }
}


上面是 Solidity 智能合约,我们将合约编译发布后,会通过 web3.js 调用,如调用 getCount()

myContract.getCount.call()


web3.js 可以很方便的调用 json-rpc 接口来获得想要的数据,或者发起交易。

不过如果要进一步开发产品的话,会发现只依赖现存的一些调用函数会比较麻烦,举个例子:


pragma solidity ^0.4.0;

contract Item{
  mapping(address => uint256[]) public ownedItems;
  
  function ListItem() returns(mapping){
    return ownedItems[msg.sender];
  }

  function addItem(_itemId) returns (uint256){
    ownedItems[msg.sender].push(_itemId);
    return _itemId
  }
}


如果我们先获得某个地址的 item, 可以通过函数Item.ListItem.call() 获得数据,前端获得数据后展示即可。但需求加上根据条件过滤出 item,根据个人喜好推荐 item,这些原本在传统开发中很容易实现的功能,在智能合约的交互中会变的相对麻烦。


这里面我提供一种思路供大家参考,利用智能合约的 event 事件来同步数据。


event 也可以称为日志,是交易收据(Transaction Receipts)的一部分,他可以用来异步通知客户端交易的执行结果。


pragma solidity ^0.4.0;

contract Item{
  mapping(address => uint256[]) public ownedItems;
  
  event AddItem(address, itemID);  // event
  
  function addItem(_itemId) returns (uint256){
    ownedItems[msg.sender].push(_itemId);
    AddItem(msg.sender, _itemId);
    return _itemId;
  }
}


比如我们可以加个 AddItem 的事件,然后客户端监听事件结果,同步数据到 server 端,server 端保存到数据库后,可以根据需求开发 http 接口供前端调用,如过滤前三个月的,根据浏览量排行。


def handle(self, *args, **options):
    	event_filter = w3.eth.filter({"address": contract_address})
    	poll_interval = 2
    	while True:
    		for event in event_filter.get_new_entries():
    			handle_event(event)
    		time.sleep(poll_interval)


event 可以给参数加 indexed 属性,这样这些参数值会存到日志结构的 topic 部分,有助于过滤和查找。


参考链接:


1. Solidity的event事件(二十一)|入门系列 - 区块链技术博客

2. web3.js编译Solidity,发布,调用全部流程(手把手教程) - Web3.js API 中文文档

发布于 2018-06-19

文章被以下专栏收录