1. 程式人生 > >星雲鏈智能合約開發(八):智能合約中調用內置庫

星雲鏈智能合約開發(八):智能合約中調用內置庫

星雲鏈智能合約開發 智能合約中調用內置庫 Nebulas智能合約開發

BigNumber

BigNumber 模塊構建於 bignumber.js之上,用來處理任意精度的十進制和非十進制運算。合約可以直接使用 BigNumber 來處理交易和其他轉賬操作中涉及到的數值計算。

var value = new BigNumber(0);
value.plus(1);
…

Storage

storage 模塊用來支持Nebulas上的數據持久化存儲。功能上類似於傳統的鍵值存儲系統,當然存儲不是免費的,需要消耗一定的 GAS。LocalContractStorage 是可以直接在合約中使用的內置storage對象,可存儲的數據類型包括數字、字符串和 JavaScript 對象(需要序列化為字符串)。鏈上數據只能被存儲它們的合約訪問和修改。

基礎

LocalContractStorage 支持三個操作:set、get`和 del,分別實現存儲、讀取和刪除數據功能:
“use strict”;
var BankVaultContract = function () {
  // nothing
};
BankVaultContract.prototype = {
  init: function() {
      // nothing
  },
  set: function(name, value) { // name=”robin”, value=10000
      LocalContractStorage.set(“name”, name);
      // put 操作相當於 set
      LocalContractStorage.put(“value”, value);
  },
  get: function() {
      var name = LocalContractStorage.get(“name”);
      console.log(name);  // 打印 ‘robin’
      var value = LocalContractStorage.get(“value”);
     console.log(value); // 打印 ‘10000’
  },
  del: function() {
      var result = LocalContractStorage.del(“name”);
      console.log(result); // 打印 ‘robin’
      // delete 操作相當於 del
      result = LocalContractStorage.delete(“value”);
      console.log(result); // 打印 ‘10000’
      // 刪除操作之後數據就不能被讀取
  }
};
module.exports = BankVaultContract;

進階

除上述基本用法之外,LocalContractStorage還支持綁定以下兩類鏈上存儲空間到合約屬性上:單值類型(storage property)和Map類型(storage map)。

單值存儲(Storage Property)

只能存放一個值,對被綁定合約屬性的讀寫都直接作用到LocalContractStorage 上。有兩種方法可以定義這種綁定:

// 綁定一個單值存儲空間到`obj` 上名為 `fieldName` 的屬性 ,
// descriptor定義了這個屬性的序列化方法。
//
// 默認的 descriptor實現是 JSON.parse() 和 JSON.stringify()。
// descriptor 為 ‘null’ 或 ‘undefined’時,默認 descriptor 將被使用。
// return this
defineProperty(obj, fieldName, [descriptor]);
// 批量綁定多個單值存儲空間到 `obj`
// return this
defineProperties(obj, {
  fieldName1: descriptor1,
  fieldName2: descriptor2
});

通常我們會在初始化操作裏完成綁定,如下所示:

“use strict”;
var BankVaultContract = function () {
   // 因為傳值為 ‘null’,將會使用默認的 descriptor實現(序列化方法)
   LocalContractStorage.defineProperty(this, “name1”, null);
   // 一個自定義的 `descriptor` 實現
   // 在解析的時候返回 BigNumber 對象
   LocalContractStorage.defineProperty(this, “value1”, {
       stringify: function (obj) {
           return obj.toString();
       },
       parse: function (str) {
           return new BigNumber(str);
       }
   });
   // 用默認的序列化實現批量綁定
   LocalContractStorage.defineProperties(this, {
       name2: null,
       value2: null
   });
};
module.exports = BankVaultContract;

之後,讀寫綁定的屬性就如同直接訪問LocalContractStorage:

BankVaultContract.prototype = {
   init: function(name, value) { // name=”robin”, value=1
       this.name1 = name;
       this.value1 = value;
   },
   testStorage: function(name, value) { // name=”ROBIN”, value=2
       this.name2 = name;
       this.value2 = value;
       bool r = this.value1.lessThan(new BigNumber(0));
       console.log(this.name1 + “:” + r);           // robin:false
       console.log(this.name2 + “:” + this.value2); // ROBIN:2
   }
};

Map存儲(Storage Map)

Nebulas 存儲支持Map數據結構,有 del/delete、get 和 set/put這些操作,在遇到某些需要存儲鍵值數據的場景時,就可以使用它。同樣地,有兩個方法來定義Map:

// 綁定單個map存儲空間到名為`mapName`的合約屬性,默認的 descriptor 實現和 defineProperty一樣
// 返回 this
defineMapProperty(obj, mapName, [descriptor]);
// 批量綁定
// 返回 this
defineMapProperties(obj, {
   mapName1: descriptor1,
   mapName2: descriptor2
});

來看一個如何使用Map的例子:

‘use strict’;
var BankVaultContract = function () {
   LocalContractStorage.defineMapProperty(this, “userMap”);
   LocalContractStorage.defineMapProperty(this, “userBalanceMap”, {
       stringify: function (obj) {
           return obj.toString();
       },
       parse: function (str) {
           return new BigNumber(str);
       }
   });
   LocalContractStorage.defineMapProperties(this,{
       key1Map: null,
       key2Map: null
   });
};
BankVaultContract.prototype = {
   init: function () {
   },
   testStorage: function () {
       this.userMap.set(“robin”, “1”);
       this.userBalanceMap.set(“robin”,new BigNumber(1));
   },
   testRead: function () {
       // 讀取和存儲數據
       var balance = this.userBalanceMap.get(“robin”);
       this.key1Map.set(“robin”, balance.toString());
       this.key2Map.set(“robin”, balance.toString());
   }
};
module.exports = BankVaultContract;

Blockchain

Blockchain 模塊用來獲取當前正在執行的合約內的交易和區塊信息。另外,還提供了若幹有用的方法,諸如從合約賬戶中轉出 NAS,進行地址格式驗證等。

Blockchain 有兩個屬性:

  1. block 執行合約的當前區塊,它具有下列屬性:
    • timestamp 區塊時間戳
    • height 區塊高度
  2. transaction 執行合約的當前交易,它具有下列屬性:
    • hash 交易哈希值
    • from 交易源地址
    • to 交易目的地址,對於合約調用就是合約地址
    • value 交易數值,字符串, 合約內用BigNumber存儲計算
    • nonce 交易的 nonce 值
    • timestamp 交易時間戳
    • gasPrice 交易的 gasPrice,字符串,合約內用 BigNumber 存儲計算
    • gasLimit 交易的 gasLimit,字符串,合約內用 BigNumber 存儲計算

      Blockchain 還提供了兩個方法:

  3. transfer(address, value) 將 NAS 從合約轉出到address對應的賬戶。
    • 參數 address:接收 NAS 的 Nebulas 賬戶地址
    • 參數 value:轉移數值,一個 BigNumber 對象
      返回:0 – 轉移成功,1 – 轉移失敗
  4. verifyAddress(address) 驗證參數 address 是否為一個有效的 Nebulas 地址。

返回:1 – 地址有效,0 – 地址無效

下面是用這個模塊實現的簡單實例:

‘use strict’;
var BankVaultContract = function () {};
BankVaultContract.prototype = {
   init: function () {
       console.log(‘init: Blockchain.block.height = ‘ + Blockchain.block.height);
       console.log(‘init: Blockchain.transaction.from = ‘ + Blockchain.transaction.from);
   },
   transfer: function (address, value) {
       var result = Blockchain.transfer(address, value);
       console.log(“transfer result:”, result);
   },
   verifyAddress: function (address) {
    var result = Blockchain.verifyAddress(address);
       console.log(“verifyAddress result:”, result);
   }
};
module.exports = BankVaultContract;

事件(Event)

Event 模塊用來記錄在合約執行過程中產生的事件。被記錄的事件存儲在鏈上的事件Trie結構中,可以通過事件查詢方法 rpc.getEventsByHash 獲取所有事件。通過Event模塊輸出的事件其最終Topic由用戶自定義topic加固定前綴 chain.contract. 兩部分構成 。使用方法如下:

Event.Trigger(topic, obj);
· topic:用戶定義的topic
· obj:JSON 對象
下面是示例:
‘use strict’;
var BankVaultContract = function () {};
BankVaultContract.prototype = {
   init: function () {},
testEvent: function() {
       // 實際被存儲的topic是“chain.contract.topic”
       Event.Trigger(“topic“, {
   Data: {
value: “Event test.”
   }
       });
   }
};
module.exports = BankVaultContract;

控制臺(Console)

console 模塊提供了一個簡單的調試控制臺,類似於網頁瀏覽器提供的 JavaScript 控制臺。console 將把所有接收到的 args 以指定級別打印到 Nebulas Logger 上。

  • console.log([…args<any>])?—?— info 級別
  • console.debug([…args<any>])?—?— debug 級別
  • console.warn([…args<any>])?—?— warn 級別
  • console.error([…args<any>])?—?— error 級別
  • console.info([…args<any>])?—?— console.log() 別名
    以上就是與智能合約相關的內置功能模塊介紹。

星雲鏈智能合約開發(八):智能合約中調用內置庫