cover

Omni协议.NET开发包

汇智网 / hubwiz.com

为.Net/C#应用快速增加OmniLayer/USDT数字资产支持能力,同时支持使用自己的节点或第三方服务API。

1、开发包概述

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

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

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

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

  • IUtxoCollector:utxo收集器
  • IBroadcaster:裸交易广播器

OmniTool.Net软件包当前版本1.0.0,主要类/接口及关系如下图所示:

omnitool.net uml

OmniTool.Net软件包主要代码文件清单如下:

代码文件说明
OmniTool.slnOmniTool.Net解决方案文件
OmniTool/OmniTool.csprojOmniTool.Net开发库项目文件
OmniTool/OmniClient.csOmniLayer/Bitcoin RPC API客户端
OmniTool/RpcModule.csRPC API模块实现类
OmniTool/ToolKit.cs开发库入口类
OmniTool/IKeyStore.cs密钥存储接口
OmniTool/IUtxoCollector.csUTXO采集器接口
OmniTool/IUtxoSelector.csUTXO选择器接口
OmniTool/IBroadcaster.cs裸交易广播器接口
OmniTool/KeyStoreMemory.cs内存密钥存储库实现类
OmniTool/KeyStoreSqlite.csSQLite密钥存储库实现类
OmniTool/UtxoCollectorRpc.cs基于RPC API的UTXO采集器实现类
OmniTool/UtxoCollectorSmartbit.cs基于云端第三方API的UTXO采集器实现类
OmniTool/UtxoSelectorDefault.csUTXO选择器接口的默认策略实现类
OmniTool/BroadcasterRpc.cs基于RPC API的裸交易广播器实现类
OmniTool/BroadcasterSmartbit.cs基于云端第三方API的裸交易广播器实现类
OmniTool/UtxoBag.csUTXO集合类
OmniTool/Utxo.csUTXO模型类
OmniTool/KeyStoreItem.cs密钥存储记录类
OmniTool/Utils.cs辅助工具类
Demo/Demo.csprojOmniTool.Net演示应用项目文件
Demo/Program.cs演示应用入口代码
Demo/RpcClientDemo.csOmni/Btc RPC API客户端使用方法演示代码
Demo/MemoryKeyStoreDemo.csproj内存密钥库使用方法演示代码
Demo/SqliteKeyStoreDemo.csprojSqlite密钥库使用方法演示代码
Demo/BtcTxRpcDemo.cs比特币转账交易演示代码,基于RPC API
Demo/BtcTxCloudDemo.cs比特币转账交易演示代码,基于第三方服务API
Demo/OmniTxRpcDemo.csOmni/USDT代币转账交易演示代码,基于RPC API
Demo/OmniTxCloudDemo.csOmni/USDT代币转账交易演示代码,基于第三方服务API

2、OmniClient类使用说明

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

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

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

//using OmniTool;
OmniClient client = new OmniClient(
    "http://user:123456@127.0.0.1:8332",       /*节点RPC API的URL*/
    "main"                                     /*接入的Bitcoin网络*/
  );

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

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

var ret = client.Omni.GetBalance(
    "1EXoDusjGwvnjZUyKkxZ4UHEf77z6A5S4P",     /*账户地址*/
    31                                        /*Omni资产ID:USDT=31*/
  );
Console.WriteLine(ret);                       /*返回JToken对象*/

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

var ret = client.Omni.Send(
    "3M9qvHKtgARhqcMtM5cRT9VaiDJ5PSfQGY",     /*代币转出地址*/
    "37FaKponF7zqoMLUjEiko25pDiuVH5YLEa",     /*代币转入地址*/
    31,                                       /*代币ID:USDT*/
    "100.00"                                  /*转移的代币数量*/
  );

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

var ret = client.Btc.ListUnspent(
    6,                                        /*最小确认数*/
    999999,                                   /*最大确认数*/
    new String[]{"mgnucj8nYqdrPFh2JfZSB1NmUThUGnmsqe"}    /*地址清单*/  
  );

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

3、ToolKit类使用说明

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

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

  • 创建一个ToolKit实例
  • 使用AddKey()方法将必要的私钥加入该ToolKit实例,例如转出地址的私钥,因为ToolKit需要利用私钥对裸交易进行签名
  • 使用SendOmnicoin()方法生成并广播Omni代币转账裸交易,或者使用SendBitcoin()方法生成并广播比特币转账裸交易

3.1 Omni/USDT代币转账

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

//using OmniTool;

String network = "main";                         
ToolKit kit = new ToolKit(
    network,                                      /*接入的网络*/
    new KeyStoreMemory(),                         /*使用内存密钥库*/
    new UtxoCollectorSmartbit(network),           /*使用云端Utxo采集器*/
    new UtxoSelectorDefault(),                    /*使用默认策略Utxo选择器*/
    new BroadcasterSmartbit(network)              /*使用云端裸交易广播器*/
  );
String privHex = "4aec8e45106....00d5c5a05b";     /*私钥:16进制字符串*/            
kit.addKey(privHex);                              /*将私钥加入ToolKit*/

String from = kit.KeyStore.GetByKey(privHex).Address; /*私钥对应的地址作为发起账号*/
String to = "1GxX5tQR1C.....x2zbdj4mMuDcWR";      /*接收地址*/                    

String txid = kit.SendOmnicoin(
    from,                                         /*发送方地址,私钥必须已经加入钱包*/
    to,                                           /*接收方地址*/
    31,                                           /*转账代币ID,USDT=31*/
    10000                                         /*转账代币数量,调整为最小单位计量的整数*/
 );

Console.WriteLine($"txid => {txid}");             /*打印交易哈希*/

注意:

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

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

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

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

String txid = kit.SendOmnicoin(
    from,                                     /*发送方地址,私钥必须已加入ToolKit*/
    to,                                       /*接收方地址*/
    31,                                       /*转账OMNI代币ID,2:TOMN*/
    10000,                                    /*转账OMNI代币数量*/
    fundAddr: "35stX1w6LKH...CdUhAeqDb6"      /*交易手续费支付地址,私钥必须已加入ToolKit*/
  );

注意:

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

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

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

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

String txid = kit.SendOmnicoin(
    from,                                     /*发送方地址,私钥必须已加入ToolKit*/
    to,                                       /*接收方地址*/
    31,                                       /*转账OMNI代币ID,2:TOMN*/
    10000,                                    /*转账OMNI代币数量*/
    fundAddr: "35stX1w6LKH...CdUhAeqDb6"      /*交易手续费支付地址,私钥必须已加入ToolKit*/
    refer: 1000                               /*转账比特币数量,单位:SATOSHI*/
  );

3.4 指定Omni交易的手续费

SendOmnicoin()方法的默认手续费为10000 SATOSHI,可以使用命名参数 fee来修改这一默认设定,例如设置为3000 SATOSHI

String txid = kit.SendOmnicoin(
    from,                                     /*发送方地址,私钥必须已加入ToolKit*/
    to,                                       /*接收方地址*/
    31,                                       /*转账OMNI代币ID,2:TOMN*/
    10000,                                    /*转账OMNI代币数量*/
    fee: 3000                                 /*交易手续费,单位:SATOSHI*/
  );

3.5 仅生成Omni裸交易但不广播

有时可能只需要生成Omni转账裸交易但并不需要广播出去,可以使用 SendOmnicoin()方法的命名参数broadcast来取消广播,这时将 返回生成的裸交易。例如:

String rawtx = kit.SendOmnicoin(
    from,                                     /*发送方地址,私钥必须已加入ToolKit*/
    to,                                       /*接收方地址*/
    31,                                       /*转账OMNI代币ID,2:TOMN*/
    10000,                                    /*转账OMNI代币数量*/
    broadcast: false                          /*不广播*/
  );
Console.WriteLine(rawtx);                     /*打印裸交易内容*/

3.6 比特币转账

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

例如,下面的代码从ToolKit的某个地址向其他地址转10000 SATOSHI

String privHex = "4aec8e45106....00d5c5a05b";     /*私钥:16进制字符串*/            
kit.addKey(privHex);                              /*将私钥加入ToolKit*/

String from = kit.KeyStore.GetByKey(privHex).Address; /*私钥对应的地址作为发起账号*/
String to = "1GxX5tQR1C.....x2zbdj4mMuDcWR";      /*接收地址*/                    

String txid = kit.SendBitcoin(
    from,                                         /*发送方地址*/
    to,     /*接收方地址*/
    10000                                         /*转账比特币数量,单位:SATOSHI*/
  );

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

String changeAddr = kit.NewAddress();             /*创建新地址*/
String txid = kit.SendBitcoin(
    from,                                         /*发送方地址*/
    to,                                           /*接收方地址*/
    10000,                                        /*转账比特币数量,单位:SATOSHI*/
    fee: 1500,                                    /*手续费,单位:SATOSHI*/
    changeAddr: changeAddr                        /*找零地址*/
  );

类似的,当只需要生成裸交易而不希望广播时,可以使用broadcast命名参数:

String rawtx = kit.SendBitcoin(
    from,                                         /*发送方地址*/
    to,                                           /*接收方地址*/
    10000,                                        /*转账比特币数量,单位:SATOSHI*/
    broadcast: false                              /*找零地址*/
  );

4、UTXO采集器

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

接口方法:

UtxoBag Collect(String[] addresses);               /*提取并返回候选UTXO集合*/

参数addresses用来声明要收集UTXO的地址清单。

当前实现类:

  • UtxoCollectorSmartbit:基于云端第三方API实现的Utxo采集器
  • UtxoCollectorRpc:基于omnicored节点RPC API实现的Utxo采集器

例如,下面的代码使用UtxoCollectorSmartbit获取测试链某个指定地址 的UTXO:

IUtxoCollector collector = new UtxoCollectorSmartbit(
    "testnet"                                       /*测试链*/
  );
String[] addresses = new String[]{"1C3TZ...brS2xHM"};
UtxoBag collected = collector.Collect(
    addresses                                       /*地址清单*/
  );

5、UTXO选择器

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

接口方法:

UtxoBag Select(long target,UtxoBag collected);       /*选择可消费UTXO,返回UtxoBag对象*/

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

参数collected是候选的utxo集合,通常是IUtxoCollector的Collect()调用 返回的结果。

当前实现类:

  • UtxoSelectorDefault:选择不少于6个确认的未消费UTXO

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

//collected表示候选UTXO集合,来自Utxo采集器的Collect()调用结果

IUtxoSelector selector = new UtxoSelectorDefault();
UtxoBag selected = selector.Select(
    100000,                                         /*最低目标金额*/
    collected                                       /*候选UTXO集合*/
  );
Console.WriteLine($"Total => {selected.Total}");    /*打印输出选中utxo总额*/

考虑到UTXO的不可分割性,筛选出的若干UTXO的总和,有可能超过目标金额。可以使用 UtxoBag实例的Total属性查看集合中的UTXO总额,如上。

6、裸交易广播器

OmniTool.Net使用IBroadcaster接口约定裸交易广播的功能规格。该接口的实现 应当将裸交易广播到Omni/Btc网络中。

接口方法:

String Broadcast(String rawtx);                     /*广播裸交易*/

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

当前实现类:

  • BroadcasterSmartbit
  • BroadcasterRpc

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

IBroadcaster broadcaster = new BroadcasterSmartbit(
    "testnet"                                       /*测试链*/
  );
String txid = broadcaster.Broadcast(
    "01000000011da9283b4...59f58488ac00000000"      /*裸交易*/
  );

7、密钥存储接口

OmniTool.Net使用IKeyStore约定密钥存储的功能规格。

接口方法:

bool Add(KeyStoreItem item);                        /*存入密钥*/
KeyStoreItem[] List();                              /*浏览全部密钥*/
KeyStoreItem GetByKey();                            /*查询指定16进制私钥对应的密钥信息*/  
KeyStoreItem GetByWif();                            /*查询指定WIF格式私钥对应的密钥信息*/
KeyStoreItem GetByAddress();                        /*查询指定地址对应的密钥信息*/
KeyStoreItem GetByScript();                         /*查询指定公钥脚本对应的密钥信息*/

IKeyStore当前实现类有两个:

  • KeyStoreMemory:基于内存字典实现,没有持久化能力,适合调试
  • KeyStoreSqlite:基于Sqlite数据库实现,适合作为生产环境密钥存储的参考实现

密钥存储实例的主要功能就是为ToolKit提供密钥存储和查询能力。下面的代码 使用KeyStoreSqlite来启动ToolKit,生成几个不同类型的地址,导入16进制私钥 和WIF私钥,然后进行查询:

ToolKit kit = new ToolKit(
    "testnet",
    keyStore: new KeyStoreSqlite("./testnet.wallet")
  );

String addr1 = kit.NewAddress("SEGWIT-P2SH");         /*生成隔离见证p2sh地址*/
String addr2 = kit.NewAddress("SEGWIT");              /*生成隔离见证地址*/
String addr3 = kit.NewAddress("P2PKH");               /*生成P2PKH地址,默认选项*/
String addr4 = kit.AddKey(                            /*导入16进制私钥*/
    "4aec8e45106....00d5c5a05b",
    "SEGWIT-P2SH"                                     /*使用该私钥的SEGWIT-P2SH地址*/  
  );  
String addr5 = kit.AddWif(                            /*导入WIF格式的私钥*/
    "cNJFgo1driF...SkdcF6JXXwHMm"                                         
  );                                                  /*默认使用私钥的P2PKH地址*/

KeyStoreItem[] items = kit.List();                    /*返回全部密钥记录*/
foreach(var item in items)
{
  Console.WriteLine($"key => {item.Key}");
  Console.WriteLine($"wif => {item.Wif}");
  Console.WriteLine($"address => {item.Address}");
  Console.WriteLine($"script => {item.Script}");
}  

KeyStoreItem item = Kit.GetByAddress(addr1);          /*查询指定地址的密钥记录*/
Console.WriteLine($"key => {item.Key}");

声 明

本站所提供软件包仅用于学习和研究,请依法合规使用。

本站所提供软件包均提供完整源码,使用前请认真阅读源代码和文档以确保充分理解软件包的设计与功能实现,本站不承担 因不当使用本站所提供软件包而造成的任何法律风险或财产损失责任。

¥3500.00
查看授权信息
  • 付费成功自动开通下载
  • 三个月内代码免费升级
  • 专业人员在线技术支持
  • 支持按需定制(另付费)
下载代码包
版本发布日期地址
1.0.0 2019-11-27
下载最新版
QQ咨询
2860991437
9+