用 NPM 进行包管理

TronBox 集成 npm,并且知道项目中的 node_modules 目录(如果存在)。这意味着我们可以通过 npm 来使用和分发合约、dapps、Solidity 的合约库,使我们的代码可供其他人使用,也可以使用其他代码。

包文件布局

使用 TronBox 创建的项目默认具有特定的目录结构,这使得它们可以作为包来使用。虽然这种目录结构不是必需的,但如果作为通用约定(或“事实上的标准”),那么通过 NPM 分发合约和 dapp 会更加容易。

TronBox 包中最重要的目录如下:

  • /contracts
  • /build (包含通过 TronBox 创建的 /build/contracts)

第一个目录是我们的合约目录,其中包含 Solidity 合约源文件,合约文件中允许导入其他的合约,也运行其他人导入这些合约。第二个目录是构建目录,更具体地说是 /build/contracts,它以 .json 文件的形式保存构建工件(artifacts),构建的 .json 允许其他人使用 JavaScript 无缝地与我们的合约交互(可以在 dapps、脚本和迁移中使用)。

使用包

在项目中使用包时,在使用其他合约代码时有两个地方需要注意:合约代码和 Javascript 代码(迁移文件和测试文件)。后面为每种情况提供了示例,并讨论了利用其他合约和构建工程文件(artifacts)的技术。

安装

在本例中,我们将使用 TronBox 示例库,它提供了一个部署到测试网络的简单名称注册表。为了将它作为依赖,我们必须首先通过 npm 在项目中安装它:

$ cd my_project
$ npm install example-tronbox-library

请注意,上面的第二个命令下载了包并将其放在 my_project/node_modules 目录中,这对于下面的示例很重要。使用 npm 进行可以参考 npm 文档

在合约代码中使用包

要在合约中使用其他包的合约,像 Solidity 的 import 声明一样简单。我们的导入路径不是 相对或绝对的 ,它表示正在寻找来自特定命名包的文件。使用上面提到的示例库的示例为:

import "example-tronbox-library/contracts/SimpleNameRegistry.sol";

由于路径不是以 ./ 开头,因此 TronBox 知道在项目的 node_modules 目录中查找 example-tronbox-library 文件夹。它将为我们所需合约提供路径。

包的部署地址

有时我们希望合约与包内先前部署的合约进行交互。由于部署的地址存在于包的 .json 文件中,因此必须执行额外的步骤才能将这些地址放入合约中。为此,请使合约接受依赖合约的地址,然后使用迁移。以下是项目中存在依赖合约示例以及迁移示例:

Contract: MyContract.sol

pragma solidity ^0.4.13;

import "example-tronbox-library/contracts/SimpleNameRegistry.sol";

contract MyContract {
  SimpleNameRegistry registry;
  address public owner;

  function MyContract {
    owner = msg.sender;
  }

  // Simple example that uses the deployed registry from the package.
  function getModule(bytes32 name) returns (address) {
    return registry.names(name);
  }

  // Set the registry if you're the owner.
  function setRegistry(address addr) {
    require(msg.sender == owner);

    registry = SimpleNameRegistry(addr);
  }
}

Migration: 3_hook_up_example_library.js

// Note that artifacts.require takes care of creating an abstraction for us.
var SimpleNameRegistry = artifacts.require('example-tronbox-library/SimpleNameRegistry');

module.exports = function (deployer) {
  // Deploy our contract, then set the address of the registry.
  deployer
    .deploy(MyContract)
    .then(function () {
      return MyContract.deployed();
    })
    .then(function (deployed) {
      return deployed.setRegistry(SimpleNameRegistry.address);
    });
};