Warning
本SDKは新たなSDKとして以下に生まれ変わりました
https://www.nuget.org/packages/SymbolSdk
使用方法は以下になります
https://github.com/0x070696E65/symbol_sdk/tree/main/sdk/csharp/quick_learning_symbol_csharp
ブロックチェーンSymbolとNEMを一つのSDKで両方使えるC#用SDKです。
もちろんUnityで使用可能です。
※Unityのバージョンは2020.3.31, 2021.3.11は動作確認済みです。
https://0x070696e65.github.io/symbol_cs_dual_sdk_reference/
Nuegtを使ってインストールしてください
https://www.nuget.org/packages/CatSdk
dotnet add package CatSdk
nugetを使わない場合は以下でも可能です
Release
よりCatSdk.dllとBouncyCastle.Crypto.dll、2つのファイルをダウンロードし、ご自身のプロジェクト等より参照を追加してください。
Unityの場合はAssetsフォルダ配下に配置すれば自動で参照が追加されます。
リファレンス を参照して利用したいネームスペースを以下のように読み込んでください。
※よく分からない場合でIDE(Visual StudioやRider)を利用している場合は、usingを書かなくとも参照候補が出ると思います。
使い方に関しては以下の速習Symbol for C#を参照してください。
https://github.com/0x070696E65/quick_learning_symbol_csharp
Symbolの学習目的や本SDKのドキュメントとして活用してください。
速習Symbolは以下のオリジナル版をC#に合わせて主にコード箇所を改変したものです。
https://github.com/xembook/quick_learning_symbol
オリジナル版の著作者であるxembookさんにお礼申し上げます。
以下に速習Symbolに含まれていない点は記載しておきます。
var transfer = new TransferTransactionV1()
{
Network = NetworkType.TESTNET,
SignerPublicKey = aliceKeyPair.PublicKey,
RecipientAddress = new UnresolvedAddress(Converter.StringToAddress("ADDRESS")),
Mosaics = new UnresolvedMosaic[]
{
new()
{
MosaicId = new UnresolvedMosaicId(0x65DBB4CC472A5734),
Amount = new Amount(2)
},
new()
{
MosaicId = new UnresolvedMosaicId(0x3A8416DB2D53B6C8),
Amount = new Amount(1)
}
},
Fee = new Amount(500000),
Deadline = new Timestamp(facade.Network.FromDatetime<NetworkTimestamp>(DateTime.UtcNow).AddHours(2).Timestamp),
};
// Transaction構築後にSort()
transfer.Sort();
var facade = new SymbolFacade(Network.TestNet);
var alicePublicKey = new PublicKey(Converter.HexToBytes("ALICE_PUBLIC_KEY"));
var bobPrivateKey = new PrivateKey("BOB_PRIVATE_KEY");
var bobKeyPair = new KeyPair(bobPrivateKey);
var innerTransactions = new IBaseTransaction[] {
new EmbeddedTransferTransactionV1
{
Network = NetworkType.TESTNET,
SignerPublicKey = alicePublicKey,
RecipientAddress = new UnresolvedAddress(Converter.StringToAddress("BOB_ADDRESS")),
Mosaics = new UnresolvedMosaic[]
{
new()
{
MosaicId = new UnresolvedMosaicId(0x3A8416DB2D53B6C8),
Amount = new Amount(100)
}
}
},
new EmbeddedTransferTransactionV1
{
Network = NetworkType.TESTNET,
SignerPublicKey = bobKeyPair.PublicKey,
RecipientAddress = new UnresolvedAddress(Converter.StringToAddress("ALICE_ADDRESS")),
Mosaics = new UnresolvedMosaic[]
{
new()
{
MosaicId = new UnresolvedMosaicId(0x3A8416DB2D53B6C8),
Amount = new Amount(100)
}
}
}
};
var merkleHash = SymbolFacade.HashEmbeddedTransactions(innerTransactions);
var aggTx = new AggregateCompleteTransactionV2 {
Network = NetworkType.TESTNET,
Transactions = innerTransactions,
SignerPublicKey = alicePublicKey,
Fee = new Amount(1000000),
TransactionsHash = merkleHash,
Deadline = new Timestamp(facade.Network.FromDatetime<NetworkTimestamp>(DateTime.UtcNow).AddHours(2).Timestamp),
};
// アグリゲートトランザクションのペイロード
Console.WriteLine(Converter.BytesToHex(aggTx.Serialize()));
C#で取得したペイロードをSSSで署名する
window.SSS.setTransactionByPayload("PAYLOAD");
window.SSS.requestSign().then((signedTx) => {
console.log(signedTx.payload)
});
署名済みペイロードを用いて再度C#でアグリゲートトランザクションの再構築
var ms = new MemoryStream(Converter.HexToBytes("SIGNED_TRASACTION_PEYLOAD"));
var br = new BinaryReader(ms);
var aggTx = AggregateCompleteTransaction.Deserialize(br);
var hash = facade.HashTransaction(aggTx);
var bobCosignature = new Cosignature
{
Signature = bobKeyPair.Sign(hash.bytes),
SignerPublicKey = bobKeyPair.PublicKey
};
aggTx.Cosignatures = new [] {bobCosignature};
var payload = TransactionsFactory.CreatePayload(aggTx);
const string node = "NODE_URL";
using var client = new HttpClient();
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = client.PutAsync(node + "/transactions", content).Result;
var responseDetailsJson = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseDetailsJson);
アグリゲートトランザクションの構築まで上と同じ
var aliceSignature = facade.SignTransaction(aliceKeyPair, aggTx);
TransactionsFactory.AttachSignature(aggTx, aliceSignature);
Console.WriteLine(Converter.BytesToHex(aggTx.Serialize()));
SSSで連署する。requestSignCosignatureTransactionである点に注意
取得するのはトランザクションの署名(signedTx.signature)
window.SSS.setTransactionByPayload("PAYLOAD")
window.SSS.requestSignCosignatureTransaction().then((signedTx) => {
console.log(signedTx.signature)
});
var bobCosignature = new Cosignature
{
Signature = new Signature(Converter.HexToBytes("BOB_SIGNATURE")),
SignerPublicKey = bobKeyPair.PublicKey
};
aggTx.Cosignatures = new [] {bobCosignature};
var payload = TransactionsFactory.CreatePayload(aggTx);
using System.Text;
using CatSdk.CryptoTypes;
using CatSdk.Facade;
using CatSdk.Utils;
using CatSdk.Nem;
var facade = new NemFacade(Network.TestNet);
var timestamp = facade.Network.FromDatetime<NetworkTimestamp>(DateTime.UtcNow);
var deadline = timestamp.AddHours(2);
var tx = new TransferTransactionV1()
{
Network = NetworkType.TESTNET,
RecipientAddress = new Address(Converter.Utf8ToBytes("RECIPIENT_ADDRESS")),
Amount = new Amount(1000000),
MessageEnvelopeSize = 0,
SignerPublicKey = new PublicKey(Converter.HexToBytes("SIGNER_PUBLIC_KEY")),
Fee = new Amount(1000000),
Timestamp = new Timestamp((uint)timestamp.Timestamp - 5),
Deadline = new Timestamp((uint)deadline.Timestamp),
};
var privateKey = new PrivateKey("SIGNER_PRIVATE_KEY");
var keyPair = new KeyPair(privateKey);
var signature = facade.SignTransaction(keyPair, tx);
var payload = TransactionsFactory.AttachSignature(tx, signature);
var signed = TransactionsFactory.AttachSignatureTransaction(tx, signature);
var hash = facade.HashTransaction(signed);
Console.WriteLine(payload);
Console.WriteLine(hash);
Console.WriteLine(signed.Signature);
const string node = "NODE_URL";
using var client = new HttpClient();
var content = new StringContent(payload, Encoding.UTF8, "application/json");
var response = client.PostAsync(node + "/transaction/announce", content).Result;
var problemDetailsJson = await response.Content.ReadAsStringAsync();
Console.WriteLine(problemDetailsJson);