部署合约需要构建并发送相应的交易到链上执行。
构建合约需要提供合约内容的十六进制字符串,和一些配置参数。
配置参数如下:
参数 | 含义 |
---|---|
$code | 合约内容,十六进制的字符串。 |
$name | 合约的名称。普通字符串。可选值。 |
$codeVersion | 合约的版本。普通字符串。可选值。 |
$author | 合约作者。普通字符串。可选值。 |
合约作者的邮件地址。普通字符串。可选值。 | |
$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());
合约必须在成功部署后才能调用。 调用合约需要构建并发送相应的交易到链上执行。
针对于 NEO 虚拟机的智能合约可以编译出相应的 .avm
文件和 .abi
文件。.abi
文件是以 JSON 格式存储,包含了描述智能合约的方法和参数的内容。可以通过读取.abi
文件方便的构建调用合约的交易。构建的交易可能还需要使用用户的私钥签名。
为了对合约方法进行调用,我们需要得到该方法的 abi 信息,以此构造调用请求。abi 信息所涉及的类包括: AbiInfo
,AbiFunction
和 Parameter
。
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);