Skip to content

Latest commit

 

History

History
245 lines (194 loc) · 5.53 KB

智能合约的部署和调用.md

File metadata and controls

245 lines (194 loc) · 5.53 KB

智能合约的部署和调用

部署合约

部署合约需要构建并发送相应的交易到链上执行。

构建合约需要提供合约内容的十六进制字符串,和一些配置参数。

配置参数如下:

参数 含义
$code 合约内容,十六进制的字符串。
$name 合约的名称。普通字符串。可选值。
$codeVersion 合约的版本。普通字符串。可选值。
$author 合约作者。普通字符串。可选值。
$email 合约作者的邮件地址。普通字符串。可选值。
$desc 合约的描述。普通字符串。可选值。
$needStorage 是否需要使用存储。布尔值。可选值。
use ontio\core\transaction\TransactionBuilder;
use ontio\network\JsonRpc;

// 合约内容
$code = '';

// 构建交易
$txBuilder = new TransactionBuilder();
$tx = $txBuilder->makeDeployCodeTransaction(
  $code,
  'name',
  '1.0',
  'alice',
  'mail',
  'desc',
  true,
  self::$gasPrice,
  '30000000',
  self::$adminAddress
);

// 签名交易
$txBuilder->signTransaction($tx, self::$adminPrivateKey);

// 发送交易
$rpc = new JsonRpc('http://127.0.0.1:20336');
$res = $rpc->sendRawTransaction($tx->serialize());

调用合约

合约必须在成功部署后才能调用。 调用合约需要构建并发送相应的交易到链上执行。

通过 abi 文件构建交易

针对于 NEO 虚拟机的智能合约可以编译出相应的 .avm 文件和 .abi 文件。.abi 文件是以 JSON 格式存储,包含了描述智能合约的方法和参数的内容。可以通过读取.abi 文件方便的构建调用合约的交易。构建的交易可能还需要使用用户的私钥签名。

为了对合约方法进行调用,我们需要得到该方法的 abi 信息,以此构造调用请求。abi 信息所涉及的类包括: AbiInfoAbiFunctionParameter

AbiInfo 类用于将 .abi 文件的内容体现到内存中,方便对其中的方法信息的操作。

namespace ontio\smartcontract\abi;

class AbiInfo
{
  /**
   * 智能合约 hash 值,也称合约地址,用来区别不通合约的标志
   *
   * @var string
   */
  public $hash;

  /**
   * 合约的入口函数名
   *
   * @var string
   */
  public $entrypoint;

  /**
   * 合约提供的方法的集合
   *
   * @var AbiFunction[]
   */
  public $functions = [];
}

AbiFunction 类用于将合约中的方法的信息体现到内存中。

namespace ontio\smartcontract\abi;

class AbiFunction
{
  /**
   * 方法名
   *
   * @var string
   */
  public $name;

  /**
   * 方法返回值类型
   *
   * @var string
   */
  public $returnType;

  /**
   * 方法参数列表
   *
   * @var Parameter[]
   */
  public $parameters = [];
}

Parameter 用于对方法的参数信息进行描述。

namespace ontio\smartcontract\abi;

class Parameter
{
  /**
   * 参数名称
   *
   * @var string
   */
  public $name;

  /**
   * 参数类型
   *
   * @var string
   */
  public $type;

  /**
   *  参数值
   *
   * @var string|int|ByteArray
   */
  public $value;
}

下面是一个简单的调用合约的例子:

use ontio\network\JsonRpc;
use ontio\smartcontract\abi\AbiInfo;
use ontio\smartcontract\abi\Parameter;
use ontio\smartcontract\abi\ParameterType;
use ontio\smartcontract\abi\Struct;
use ontio\core\transaction\TransactionBuilder;

// 载入 abi info
$abi = AbiInfo::fromJson(self::$abi);

// 获得方法的 abi 信息
$fn = $abi->getFunction('DeserializeStruct');

// 构造调用参数
$struct = new Struct();
$struct->add(
  100,
  ByteArray::fromBinary('claimid')->toHex()
);

$param = new Parameter($fn->parameters[0]->getName(), ParameterType::ByteArray, $struct);

// 使用上面构造的调用参数
$fn->setParamsValue($param);

// 构造交易
$txBuilder = new TransactionBuilder();
$tx = $txBuilder->makeInvokeTransaction(
  $fn->name,
  $fn->parameters,
  new Address(self::$codeHash),
  '0',
  '30000000',
  self::$adminAddress
);

// 签名交易
$txBuilder->signTransaction($tx, self::$adminPrivateKey);

// 发送交易
$rpc = new JsonRpc('http://127.0.0.1:20336');
$rpc->sendRawTransaction($tx->serialize());

事件推送

通过 websocket 发送请求,可以监听后台推送的消息。如果合约里写明了事件推送,合约方法调用后会有相应的推送消息。

use ontio\core\transaction\TransactionBuilder;
use ontio\crypto\Address;
use ontio\network\WebsocketRpc;

$txBuilder = new TransactionBuilder();
$tx = $txBuilder->makeInvokeTransaction(
  $fn->name,
  $fn->parameters,
  new Address(self::$codeHash),
  '0',
  '30000000',
  self::$adminAddress
);

$rpc = new WebsocketRpc('ws://127.0.0.1:20335');

// 设置过滤器
// 当交易调用成功后,会等待来自链上的消息推送,每接受到一条消息都会调用该过滤器
//
// $conn    当前的 websocket 连接
// $id      本次发送的请求 id
// $txHash  交易 hash
// $msg     链上的消息推送
$filter = function ($deferred, $conn, $id, $txHash, $msg) {
  if($msg->Action === 'Notify') {
      var_dump($msg);
      $deferred->resolve();
      $conn->close();
  }
};

// 默认超时 60 秒
$timeout = 60;
$rpc->send($data, $filter, $timeout);