Omni/USDT PHP开发包简介

OmniTool开发包适用于为PHP应用快速增加对Omni Layer/USDT数字资产的支持能力, 即支持使用自有Omni Layer节点的应用场景,也支持基于第三方API服务和离线裸交易 的轻量级部署场景。下载地址:omni/usdt php开发包

1、OmniTool开发包简介

OmniTool开发包主要包含以下特性:

  • 完善的Omni Layer节点RPC封装
  • 支持利用自有节点或第三方服务获取指定地址的utxo集合
  • 支持离线生成omni代币转账裸交易
  • 支持利用自有节点或第三方服务广播裸交易

OmniTool支持本地部署的Omnicored节点,也支持blockchain.info、btc.com等提供 的开放API,要增加对其他第三方服务的支持也非常简单,只需要参考代码实现如下接口:

  • UtxoCollectorInterface:utxo收集器
  • UtxoSelectorInterface:utxo筛选器
  • BroadcasterInterface:裸交易广播器
  • ExplorerInterface:数据查询接口

OmniTool软件包运行在Php 7.1+环境下,当前版本1.0.0,主要类/接口及关系如下图所示:

omnitool arch

OmniTool的主要代码文件清单如下:

代码文件说明
omni.php/src/RpcClient.phpOmni Layer的RPC协议封装类
omni.php/src/RpcModule.phpOmni Layer的RPC协议分模块访问语法糖
omni.php/src/protocol-spec.jsonOmni Layer协议描述元信息
omni.php/src/SerializeBuffer.phpOmni Layer协议序列化缓冲区
omni.php/src/PayloadFactory.phpOmni Layer协议载荷工厂类
omni.php/src/Utxo.php未消费交易输出类
omni.php/src/UtxoBag.phpUtxo集合类
omni.php/src/UtxoCollectorInterface.phpUtxo收集器接口
omni.php/src/LocalUtxoCollector.php基于OmniCore节点的Utxo收集器实现
omni.php/src/CloudUtxoCollector.php基于第三方服务的Utxo收集器实现
omni.php/src/UtxoSelectorInterface.phpUtxo筛选器接口
omni.php/src/DefaultUtxoSelector.php默认的Utxo筛选器实现
omni.php/src/BroadcasterInterface.php裸交易广播器接口
omni.php/src/LocalBroadcaster.php基于OmniCore节点的裸交易广播器实现
omni.php/src/CloudBroadcaster.php基于第三方服务的裸交易广播器实现
omni.php/src/ExplorerInterface.php数据查询接口
omni.php/src/CloudExplorer.php基于第三方服务的数据查询接口实现
omni.php/src/LocalExplorer.php基于OmniCore节点的数据查询接口实现
omni.php/src/Utils.php常用辅助函数
omni.php/src/Wallet.php离线钱包类
demo/rpc-demo.phpRpcClient使用示例,完整实现OMNI代币的发行与转账
demo/omni-tx-cloud.php创建并广播Omni代币转账裸交易,使用第三方云服务API
demo/omni-tx-local.php创建并广播Omni代币转账裸交易,使用自有节点
demo/btc-tx-cloud.php创建并广播比特币转账裸交易,使用第三方云服务API
demo/btc-tx-local.php创建并广播比特币转账裸交易,使用自有节点
demo/explorer-cloud.php查询指定的地址比特币余额/Omni代币余额,使用第三方云服务API
demo/explorer-local.php查询指定地址的比特币余额/Omni代币余额,使用自有节点
demo/wallet-init.php本地钱包初始化
demo/wallet-demo.php钱包载入、裸交易构造和广播
vendor第三方依赖包目录
composer.jsoncomposer配置文件

2、RpcClient类使用说明

RpcClient类封装了Omni Layer的RPC接口协议。创建RpcClient对象时,需要传入 包含有效身份信息的节点RPC URL。例如,假设安装在本机的omnicored节点软件配置如下:

  • rpcuser:user
  • rpcpassword:123456
  • rpcport:8332

那么可以使用如下的代码来实例化RpcClient:

1
2
3
4
5
use \OmniTool\RpcClient;

$client = new RpcClient(
'http://user:123456@localhost:8332' /*节点RPC接口的URL*/
);

Omni Core节点在Bitcoin原有的RPC接口之外,扩充了额外的接口用来操作Omni层 的数据,这些扩展的RPC接口采用omni_前缀以区隔于Bitcoin的原有RPC接口。为了 便于区隔这两层的RPC调用,RpcClient引入了协议子模块的概念,将Bitcoin的 原始RPC接口和Omni的扩展RPC接口分别挂接到btc子模块和omni子模块。

例如,获取某个地址的USDT代币余额需要使用Omni层的omni_getbalance 调用,这个RPC调用对应于RpcClient实例的omni子模块的getBalance()方法。 下面的代码获取地址1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P的USDT(资产ID:31) 余额:

1
2
3
4
$ret = $client->omni->getBalance(
'1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P', /*地址*/
31 /*资产ID:USDT*/
);

类似的,可以使用omni_send调用 来执行简单的USDT转账,这个调用对应于RpcClient实例的omni子模块的send()方法。 下面的代码从地址3M9qvHKtgARhqcMtM5cRT9VaiDJ5PSfQGY向地址37FaKponF7zqoMLUjEiko25pDiuVH5YLEa 转入100.0个USDT代币:

1
2
3
4
5
6
$ret = $client->omni->send(
'3M9qvHKtgARhqcMtM5cRT9VaiDJ5PSfQGY', /*代币转出地址*/
'37FaKponF7zqoMLUjEiko25pDiuVH5YLEa', /*代币转入地址*/
31, /*代币ID:USDT*/
"100.00" /*转移的代币数量*/
);

原有的bitoin层的RPC接口则可以通过RpcClient的btc子模块来访问。例如,使用 listunspent调用来获取 本地节点中指定地址的utxo:

1
2
3
4
5
$ret = $client->btc->listUnspent(
6, /*最小确认数*/
999999, /*最大确认数*/
['mgnucj8nYqdrPFh2JfZSB1NmUThUGnmsqe'] /*地址清单*/
);

开发包中的demo/rpc-demo.php示例代码使用RpcClient类完整演示了在Omni层的代币发行 与转账功能,如果你计划搭建自己的Omni Core节点,相信这个示例会有很大帮助。

3、Wallet类使用说明

如果不愿意搭建自己的Omni Core节点,而是希望基于第三方API为自己的PHP应用增加 对Omni Layer/USDT的支持,那么最简单的方法是使用离线交易的入口类Wallet

Wallet类的主要作用是根据创建并广播Omni代币转账裸交易或比特币转账裸交易, 它的基本使用步骤如下:

  • 使用Wallet::cloud()静态方法创建一个支持云端API服务的Wallet实例
  • 使用addKey()方法将必要的私钥加入该Wallet实例,例如转出地址的私钥,因为Wallet需要利用私钥对裸交易进行签名
  • 使用omniSendTx()方法生成Omni代币转账裸交易,或者使用btcSendTx()方法比特币转账裸交易
  • 使用broadcast()方法广播裸交易

3.1 Omni代币转账

使用Wallet实现的Omni代币转账示例代码如下,说明见注释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
require('../vendor/autoload.php');

use OmniTool\Wallet; /*引入开发包*/

$wallet = Wallet::cloud(
'./demo.wallet', /*钱包文件地址,自动创建*/
'testnet' /*网络ID*/
);
$prvKey = '4aec8e45106....00d5c5af494a4e05b'; /*私钥:16进制字符串*/
$wallet->addKey($prvKey); /*将私钥加入钱包,只需加入一次*/

$addressList = $wallet->getAddressList(); /*返回钱包管理的所有地址,数组*/

$rawtx = $wallet->omniSendTx(
$addressList[0], /*发送方地址,私钥必须已经加入钱包*/
'mgYPLmNuZymK...e2XUNF6VFnT', /*接收方地址*/
2, /*转账OMNI代币ID,2:TOMN*/
'0.000001' /*转账OMNI代币数量*/
);

$ret = $wallet->broadcast($rawtx); /*广播OMNI裸交易*/
var_dump($ret);

注意:

  • Wallet实例利用钱包中的私钥生成地址列表,并利用这些地址从第三方服务获取utxo信息。 因此需要钱包中 的私钥对应地址在链上有utxo存在,Wallet对象才能够成功构造裸交易。
  • 转账目标地址应当与创建Wallet对象时指定的链ID一致,例如mainnet的p2pkh地址,前缀应当为1

3.2 指定Omni交易的手续费支付地址

在Omni协议层不需要支付交易手续费,但是Omni交易所嵌入的比特币交易依然需要支付 手续费。默认情况下omniSendTx()方法使用发送方地址支付比特币交易手续费,但可以 传入额外的参数来指定其他地址支付交易手续费,当你的PHP应用需要实现多账户归集 功能时,使用统一的手续费支付地址会更容易管理一些。

例如,下面的代码使用地址mnRo8JyTHDd5NxRb3UvGbAhCBPQTQ4UZ8W支付omni交易的手续费:

1
2
3
4
5
6
7
$rawtx = $wallet->omniSendTx(
$addressList[0], /*发送方地址,私钥必须已经加入钱包*/
'mgYPLmNuZymK...e2XUNF6VFnT', /*接收方地址*/
2, /*转账OMNI代币ID,2:TOMN*/
'0.000001', /*转账OMNI代币数量*/
'mnRo8JyTHDd5...CBPQTQ4UZ8W' /*交易手续费支付地址*/
);

注意:

  • 即使指定了余额充足的手续费支付地址,Omni交易的发送方依然必须有微量的比特币 余额(546 SATOSHI),因为Omni协议需要交易发送方至少有一个可用UTXO。
  • 手续费支付地址同时也是找零地址,多余的比特币将返回至该地址

3.3 指定Omni交易的比特币转账数量

由于Omni交易要求发送方必须有可用的UTXO,因此为了便于接收Omni代币的地址可以 继续流通所持有的Omni代币,omniSendTx()方法在默认情况下将向接收方地址转入 微量的比特币(546 SATOSHI),可以在调用该方法时修改这个默认数值。

例如,下面的代码转入接收方1000个SATOSHI:

1
2
3
4
5
6
7
8
$rawtx = $wallet->omniSendTx(
$addressList[0], /*发送方地址,私钥必须已经加入钱包*/
'mgYPLmNuZymK...e2XUNF6VFnT', /*接收方地址
2, /*转账OMNI代币ID,2:TOMN*/
'0.000001', /*转账OMNI代币数量*/
'mnRo8JyTHDd5...CBPQTQ4UZ8W', /*交易手续费支付地址*/
1000 /*转账比特币数量,单位:SATOSHI*/
);

3.4 比特币转账

OmniTool也支持比特币转账裸交易的生成与广播。

例如,下面的代码从钱包的第一个地址向指定接受地址转入1000个SATOSHI:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
require('../vendor/autoload.php');

use OmniTool\Wallet;

$wallet = Wallet::cloud('./demo.wallet','testnet');
$addressList = $wallet->getAddressList();

$rawtx = $wallet->btcSendTx(
$addressList[0], /*发送方地址*/
'moneyqMan7u...8qVrc9ikLP', /*接收方地址*/
1000, /*转账比特币数量,单位:SATOSHI*/
500 /*手续费,单位:SATOSHI*/
);
echo 'btc rawtx => ' . $rawtx . PHP_EOL;

$ret = $wallet->broadcast($rawtx); /*广播裸交易*/

默认情况下,btcSendTx()使用发送方地址作为找零地址,也可以在调用时指定其他地址 作为找零地址,例如,下面的代码创建一个新地址接收找零:

1
2
3
4
5
6
7
8
$changeAddress = $wallet->getNewAddress();          /*创建新地址*/
$rawtx = $wallet->btcSendTx(
$addressList[0], /*发送方地址*/
'moneyqMan7u...8qVrc9ikLP', /*接收方地址*/
1000, /*转账比特币数量,单位:SATOSHI*/
500, /*手续费,单位:SATOSHI*/
$changeAddress /*找零地址*/
);

4、UTXO收集器

OmniTool使用接口UtxoCollectorInterface来约定UTXO的收集功能。 该接口的实现需要支持获取指定地址的候选UTXO集合,可指定多个地址。

接口方法:

  • collect($addressList):提取并返回候选UTXO集合

参数$addressList用来声明要收集UTXO的地址清单,类型为数组。

当前实现类:

  • CloudUtxoCollector:基于blockchain.com的开放API实现的Utxo收集器
  • LocalUtxoCollector:基于omnicored节点RPC API实现的Utxo收集器

例如,下面的代码使用CloudUtxoCollector获取地址mi8BvbK73nDQfaN3acpaFGYQKhfQ5ysKRn 的UTXO:

1
2
3
4
5
6
7
8
use OmniTool\CloudUtxoCollector;

$collector = new CloudUtxoCollector(
'testnet' /*测试网*/
);
$candidateBag = $collector->collect(
['mi8BvbK73nDQ...KhfQ5ysKRn'] /*地址清单*/
);

5、UTXO筛选器

OmniTool使用UtxoSelectorInterface来约定UTXO筛选功能。该接口的实现需要 根据目标金额从候选UTXO中选择可用UTXO,并返回新的UtxoBag实例。

接口方法:

  • select($target,$candidates):选择可消费UTXO,返回UtxoBag对象

参数$target声明要达成的最低金额目标,单位:wei。

参数$candidates是候选的utxo集合,通常是UtxoCollectorInterface实现对象的collect()调用 返回的UtxoBag对象。

当前实现类:

  • DefaultUtxoSelector

例如下面的代码使用DefaultUtxoSelector实例从候选UTXO中删选出至少100000 wei 的UTXO:

1
2
3
4
5
6
7
use OmniTool\DefaultUtxoSelector;

$selector = new DefaultUtxoSelector();
$selectedBag = $selector->select(
100000, /*最低目标金额*/
$candidateBag /*候选UTXO集合*/
);

考虑到UTXO的不可分割性,筛选出的若干UTXO的总和,有可能超过目标金额。可以使用 UtxoBag实例的getTotal()方法查看集合中的UTXO总额:

1
echo 'total wei in bag => ' . $selectedBag->getTotal() . PHP_EOL;

6、裸交易广播器

OmniTool使用BroadcasterInterface来约定裸交易广播的功能。该接口的实现 应当将裸交易广播到Omni网络中。

接口方法:

  • broadcast($rawtx):广播裸交易

参数$rawtx用来声明要广播的裸交易,类型为16进制字符串。

当前实现类:

  • CloudBroadcaster
  • LocalBroadcaster

例如,下面的代码使用CloudBroadcaster将裸交易码流广播到Omni网络中:

1
2
3
4
5
6
7
8
use OmniTool\CloudBroadcaster;

$broadcaster = new CloudBroadcaster(
'testnet' /*测试网*/
);
$ret = $broadcaster->broadcast(
'01000000011da9283b4...59f58488ac00000000' /*裸交易*/
);

7、数据查询接口

OmniTool使用ExplorerInterface来约定Omni数据查询功能。

接口方法:

  • getBtcBalance($address):查询指定地址的比特币余额
  • getOmniBalance($address,$propertyId):查询指定地址的Omni代币余额

当前实现类:

  • CloudBroadcaster
  • LocalBroadcaster

例如,下面的代码使用CloudExplorer查询地址1Jekm8ZswQmDhLFMp9cuYb1Kcq26riFp6m 的比特币余额与USDT代币余额:

1
2
3
4
5
6
7
8
9
10
11
use OmniTool\CloudExplorer;

$explorer = new CloudExplorer('mainnet');

$address = '1Jekm8ZswQmDhLFMp9cuYb1Kcq26riFp6m';

$balance = $explorer->getBtcBalance($address);
echo 'btc balance => ' . PHP_EOL;

$balance = $explorer->getOmniBalance($address,31);
echo 'usdt balance => ' . $balance['balance']. PHP_EOL;

如果你想学习区块链并在Blockchain Technologies建立职业生涯,那么请查看我们分享的一些以太坊、比特币、EOS、Fabric、Tendermint等区块链相关的交互式在线编程实战教程:

  • java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。
  • python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和交易等内容。
  • 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
  • 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • ERC721以太坊通证实战,课程以一个数字艺术品创作与分享DApp的实战开发为主线,深入讲解以太坊非同质化通证的概念、标准与开发方案。内容包含ERC-721标准的自主实现,讲解OpenZeppelin合约代码库二次开发,实战项目采用Truffle,IPFS,实现了通证以及去中心化的通证交易所。
  • C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和交易等。
  • java比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Java代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Java工程师不可多得的比特币开发学习课程。
  • php比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在Php代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是Php工程师不可多得的比特币开发学习课程。
  • c#比特币开发教程,本课程面向初学者,内容即涵盖比特币的核心概念,例如区块链存储、去中心化共识机制、密钥与脚本、交易与UTXO等,同时也详细讲解如何在C#代码中集成比特币支持功能,例如创建地址、管理钱包、构造裸交易等,是C#工程师不可多得的比特币开发学习课程。
  • EOS入门教程,本课程帮助你快速入门EOS区块链去中心化应用的开发,内容涵盖EOS工具链、账户与钱包、发行代币、智能合约开发与部署、使用代码与智能合约交互等核心知识点,最后综合运用各知识点完成一个便签DApp的开发。
  • 深入浅出玩转EOS钱包开发,本课程以手机EOS钱包的完整开发过程为主线,深入学习EOS区块链应用开发,课程内容即涵盖账户、计算资源、智能合约、动作与交易等EOS区块链的核心概念,同时也讲解如何使用eosjs和eosjs-ecc开发包访问EOS区块链,以及如何在React前端应用中集成对EOS区块链的支持。课程内容深入浅出,非常适合前端工程师深入学习EOS区块链应用开发。
  • Hyperledger Fabric 区块链开发详解,本课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、nodejs链码与应用开发的操作实践,是Nodejs工程师学习Fabric区块链开发的最佳选择。
  • Hyperledger Fabric java 区块链开发详解,课程面向初学者,内容即包含Hyperledger Fabric的身份证书与MSP服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含Fabric网络设计、java链码与应用开发的操作实践,是java工程师学习Fabric区块链开发的最佳选择。
  • tendermint区块链开发详解,本课程适合希望使用tendermint进行区块链开发的工程师,课程内容即包括tendermint应用开发模型中的核心概念,例如ABCI接口、默克尔树、多版本状态库等,也包括代币发行等丰富的实操代码,是go语言工程师快速入门区块链开发的最佳选择。