diff --git a/all.sln b/all.sln
index 3e3a5d1..dcebc5a 100644
--- a/all.sln
+++ b/all.sln
@@ -20,6 +20,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Client.Test", "test\AE
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Client.Abp", "src\AElf.Client.Abp\AElf.Client.Abp.csproj", "{BBE11EF4-5CD6-4918-8E6C-74BF61C1A87F}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AElf.Inscription", "src\AElf.Inscription\AElf.Inscription.csproj", "{D5CA0435-4C95-4A97-8BE3-CD972E1CE1E7}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -33,6 +35,7 @@ Global
{BE0E29FA-A9C6-4E03-9E0C-297CCF7C5729} = {5D1BDC45-D6F1-4359-868B-CB85CEC4ABD8}
{4D019C99-8B1C-42B0-8630-F1E3661F414B} = {7CD2B508-C765-4720-B430-94E79135797A}
{BBE11EF4-5CD6-4918-8E6C-74BF61C1A87F} = {940361AC-2167-4D30-A4F6-9A543C608196}
+ {D5CA0435-4C95-4A97-8BE3-CD972E1CE1E7} = {940361AC-2167-4D30-A4F6-9A543C608196}
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{1AE7844D-B4D9-4F5A-9D25-7E551B61138E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -63,5 +66,9 @@ Global
{BBE11EF4-5CD6-4918-8E6C-74BF61C1A87F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BBE11EF4-5CD6-4918-8E6C-74BF61C1A87F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BBE11EF4-5CD6-4918-8E6C-74BF61C1A87F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D5CA0435-4C95-4A97-8BE3-CD972E1CE1E7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D5CA0435-4C95-4A97-8BE3-CD972E1CE1E7}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D5CA0435-4C95-4A97-8BE3-CD972E1CE1E7}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D5CA0435-4C95-4A97-8BE3-CD972E1CE1E7}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal
diff --git a/src/AElf.Client/AElf.Client.csproj b/src/AElf.Client/AElf.Client.csproj
index 259e45a..320df69 100644
--- a/src/AElf.Client/AElf.Client.csproj
+++ b/src/AElf.Client/AElf.Client.csproj
@@ -11,6 +11,7 @@
+
diff --git a/src/AElf.Inscription/AElf.Inscription.csproj b/src/AElf.Inscription/AElf.Inscription.csproj
new file mode 100644
index 0000000..b9d9d3f
--- /dev/null
+++ b/src/AElf.Inscription/AElf.Inscription.csproj
@@ -0,0 +1,14 @@
+
+
+
+ netstandard2.1
+ enable
+
+
+
+
+
+
+
+
+
diff --git a/src/AElf.Inscription/Inscription.cs b/src/AElf.Inscription/Inscription.cs
new file mode 100644
index 0000000..fdf75f6
--- /dev/null
+++ b/src/AElf.Inscription/Inscription.cs
@@ -0,0 +1,404 @@
+//
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: inscription.proto
+//
+#pragma warning disable 1591, 0612, 3021, 8981
+#region Designer generated code
+
+using pb = global::Google.Protobuf;
+using pbc = global::Google.Protobuf.Collections;
+using pbr = global::Google.Protobuf.Reflection;
+using scg = global::System.Collections.Generic;
+namespace AElf.Inscription {
+
+ /// Holder for reflection information generated from inscription.proto
+ public static partial class InscriptionReflection {
+
+ #region Descriptor
+ /// File descriptor for inscription.proto
+ public static pbr::FileDescriptor Descriptor {
+ get { return descriptor; }
+ }
+ private static pbr::FileDescriptor descriptor;
+
+ static InscriptionReflection() {
+ byte[] descriptorData = global::System.Convert.FromBase64String(
+ string.Concat(
+ "ChFpbnNjcmlwdGlvbi5wcm90bxIQYWVsZi5pbnNjcmlwdGlvbhoPYWVsZi9j",
+ "b3JlLnByb3RvInwKHFRyYW5zZmVySW5wdXRXaXRoSW5zY3JpcHRpb24SGQoC",
+ "dG8YASABKAsyDS5hZWxmLkFkZHJlc3MSDgoGc3ltYm9sGAIgASgJEg4KBmFt",
+ "b3VudBgDIAEoAxIMCgRtZW1vGAQgASgJEhMKC2luc2NyaXB0aW9uGCogASgM",
+ "QhOqAhBBRWxmLkluc2NyaXB0aW9uYgZwcm90bzM="));
+ descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
+ new pbr::FileDescriptor[] { global::AElf.Types.CoreReflection.Descriptor, },
+ new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
+ new pbr::GeneratedClrTypeInfo(typeof(global::AElf.Inscription.TransferInputWithInscription), global::AElf.Inscription.TransferInputWithInscription.Parser, new[]{ "To", "Symbol", "Amount", "Memo", "Inscription" }, null, null, null, null)
+ }));
+ }
+ #endregion
+
+ }
+ #region Messages
+ public sealed partial class TransferInputWithInscription : pb::IMessage
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ , pb::IBufferMessage
+ #endif
+ {
+ private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new TransferInputWithInscription());
+ private pb::UnknownFieldSet _unknownFields;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pb::MessageParser Parser { get { return _parser; } }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public static pbr::MessageDescriptor Descriptor {
+ get { return global::AElf.Inscription.InscriptionReflection.Descriptor.MessageTypes[0]; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ pbr::MessageDescriptor pb::IMessage.Descriptor {
+ get { return Descriptor; }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public TransferInputWithInscription() {
+ OnConstruction();
+ }
+
+ partial void OnConstruction();
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public TransferInputWithInscription(TransferInputWithInscription other) : this() {
+ to_ = other.to_ != null ? other.to_.Clone() : null;
+ symbol_ = other.symbol_;
+ amount_ = other.amount_;
+ memo_ = other.memo_;
+ inscription_ = other.inscription_;
+ _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public TransferInputWithInscription Clone() {
+ return new TransferInputWithInscription(this);
+ }
+
+ /// Field number for the "to" field.
+ public const int ToFieldNumber = 1;
+ private global::AElf.Types.Address to_;
+ ///
+ /// The receiver of the token.
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public global::AElf.Types.Address To {
+ get { return to_; }
+ set {
+ to_ = value;
+ }
+ }
+
+ /// Field number for the "symbol" field.
+ public const int SymbolFieldNumber = 2;
+ private string symbol_ = "";
+ ///
+ /// The token symbol to transfer.
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string Symbol {
+ get { return symbol_; }
+ set {
+ symbol_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "amount" field.
+ public const int AmountFieldNumber = 3;
+ private long amount_;
+ ///
+ /// The amount to to transfer.
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public long Amount {
+ get { return amount_; }
+ set {
+ amount_ = value;
+ }
+ }
+
+ /// Field number for the "memo" field.
+ public const int MemoFieldNumber = 4;
+ private string memo_ = "";
+ ///
+ /// The memo.
+ ///
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public string Memo {
+ get { return memo_; }
+ set {
+ memo_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ /// Field number for the "inscription" field.
+ public const int InscriptionFieldNumber = 42;
+ private pb::ByteString inscription_ = pb::ByteString.Empty;
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public pb::ByteString Inscription {
+ get { return inscription_; }
+ set {
+ inscription_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+ }
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override bool Equals(object other) {
+ return Equals(other as TransferInputWithInscription);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public bool Equals(TransferInputWithInscription other) {
+ if (ReferenceEquals(other, null)) {
+ return false;
+ }
+ if (ReferenceEquals(other, this)) {
+ return true;
+ }
+ if (!object.Equals(To, other.To)) return false;
+ if (Symbol != other.Symbol) return false;
+ if (Amount != other.Amount) return false;
+ if (Memo != other.Memo) return false;
+ if (Inscription != other.Inscription) return false;
+ return Equals(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override int GetHashCode() {
+ int hash = 1;
+ if (to_ != null) hash ^= To.GetHashCode();
+ if (Symbol.Length != 0) hash ^= Symbol.GetHashCode();
+ if (Amount != 0L) hash ^= Amount.GetHashCode();
+ if (Memo.Length != 0) hash ^= Memo.GetHashCode();
+ if (Inscription.Length != 0) hash ^= Inscription.GetHashCode();
+ if (_unknownFields != null) {
+ hash ^= _unknownFields.GetHashCode();
+ }
+ return hash;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public override string ToString() {
+ return pb::JsonFormatter.ToDiagnosticString(this);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void WriteTo(pb::CodedOutputStream output) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ output.WriteRawMessage(this);
+ #else
+ if (to_ != null) {
+ output.WriteRawTag(10);
+ output.WriteMessage(To);
+ }
+ if (Symbol.Length != 0) {
+ output.WriteRawTag(18);
+ output.WriteString(Symbol);
+ }
+ if (Amount != 0L) {
+ output.WriteRawTag(24);
+ output.WriteInt64(Amount);
+ }
+ if (Memo.Length != 0) {
+ output.WriteRawTag(34);
+ output.WriteString(Memo);
+ }
+ if (Inscription.Length != 0) {
+ output.WriteRawTag(210, 2);
+ output.WriteBytes(Inscription);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(output);
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
+ if (to_ != null) {
+ output.WriteRawTag(10);
+ output.WriteMessage(To);
+ }
+ if (Symbol.Length != 0) {
+ output.WriteRawTag(18);
+ output.WriteString(Symbol);
+ }
+ if (Amount != 0L) {
+ output.WriteRawTag(24);
+ output.WriteInt64(Amount);
+ }
+ if (Memo.Length != 0) {
+ output.WriteRawTag(34);
+ output.WriteString(Memo);
+ }
+ if (Inscription.Length != 0) {
+ output.WriteRawTag(210, 2);
+ output.WriteBytes(Inscription);
+ }
+ if (_unknownFields != null) {
+ _unknownFields.WriteTo(ref output);
+ }
+ }
+ #endif
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public int CalculateSize() {
+ int size = 0;
+ if (to_ != null) {
+ size += 1 + pb::CodedOutputStream.ComputeMessageSize(To);
+ }
+ if (Symbol.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Symbol);
+ }
+ if (Amount != 0L) {
+ size += 1 + pb::CodedOutputStream.ComputeInt64Size(Amount);
+ }
+ if (Memo.Length != 0) {
+ size += 1 + pb::CodedOutputStream.ComputeStringSize(Memo);
+ }
+ if (Inscription.Length != 0) {
+ size += 2 + pb::CodedOutputStream.ComputeBytesSize(Inscription);
+ }
+ if (_unknownFields != null) {
+ size += _unknownFields.CalculateSize();
+ }
+ return size;
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(TransferInputWithInscription other) {
+ if (other == null) {
+ return;
+ }
+ if (other.to_ != null) {
+ if (to_ == null) {
+ To = new global::AElf.Types.Address();
+ }
+ To.MergeFrom(other.To);
+ }
+ if (other.Symbol.Length != 0) {
+ Symbol = other.Symbol;
+ }
+ if (other.Amount != 0L) {
+ Amount = other.Amount;
+ }
+ if (other.Memo.Length != 0) {
+ Memo = other.Memo;
+ }
+ if (other.Inscription.Length != 0) {
+ Inscription = other.Inscription;
+ }
+ _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
+ }
+
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ public void MergeFrom(pb::CodedInputStream input) {
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ input.ReadRawMessage(this);
+ #else
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input);
+ break;
+ case 10: {
+ if (to_ == null) {
+ To = new global::AElf.Types.Address();
+ }
+ input.ReadMessage(To);
+ break;
+ }
+ case 18: {
+ Symbol = input.ReadString();
+ break;
+ }
+ case 24: {
+ Amount = input.ReadInt64();
+ break;
+ }
+ case 34: {
+ Memo = input.ReadString();
+ break;
+ }
+ case 338: {
+ Inscription = input.ReadBytes();
+ break;
+ }
+ }
+ }
+ #endif
+ }
+
+ #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+ [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+ void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) {
+ uint tag;
+ while ((tag = input.ReadTag()) != 0) {
+ switch(tag) {
+ default:
+ _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input);
+ break;
+ case 10: {
+ if (to_ == null) {
+ To = new global::AElf.Types.Address();
+ }
+ input.ReadMessage(To);
+ break;
+ }
+ case 18: {
+ Symbol = input.ReadString();
+ break;
+ }
+ case 24: {
+ Amount = input.ReadInt64();
+ break;
+ }
+ case 34: {
+ Memo = input.ReadString();
+ break;
+ }
+ case 338: {
+ Inscription = input.ReadBytes();
+ break;
+ }
+ }
+ }
+ }
+ #endif
+
+ }
+
+ #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/src/AElf.Inscription/Protobuf/aelf/core.proto b/src/AElf.Inscription/Protobuf/aelf/core.proto
new file mode 100644
index 0000000..c990aa9
--- /dev/null
+++ b/src/AElf.Inscription/Protobuf/aelf/core.proto
@@ -0,0 +1,157 @@
+syntax = "proto3";
+
+package aelf;
+
+option csharp_namespace = "AElf.Types";
+
+message Transaction {
+ // The address of the sender of the transaction.
+ Address from = 1;
+ // The address of the contract when calling a contract.
+ Address to = 2;
+ // The height of the referenced block hash.
+ int64 ref_block_number = 3;
+ // The first four bytes of the referenced block hash.
+ bytes ref_block_prefix = 4;
+ // The name of a method in the smart contract at the To address.
+ string method_name = 5;
+ // The parameters to pass to the smart contract method.
+ bytes params = 6;
+ // When signing a transaction it’s actually a subset of the fields: from/to and the target method as well as
+ // the parameter that were given. It also contains the reference block number and prefix.
+ bytes signature = 10000;
+}
+
+message StatePath {
+ // The partial path of the state path.
+ repeated string parts = 1;
+}
+
+message ScopedStatePath {
+ // The scope address, which will be the contract address.
+ Address address = 1;
+ // The path of contract state.
+ StatePath path = 2;
+}
+
+enum TransactionResultStatus {
+ // The execution result of the transaction does not exist.
+ NOT_EXISTED = 0;
+ // The transaction is in the transaction pool waiting to be packaged.
+ PENDING = 1;
+ // Transaction execution failed.
+ FAILED = 2;
+ // The transaction was successfully executed and successfully packaged into a block.
+ MINED = 3;
+ // When executed in parallel, there are conflicts with other transactions.
+ CONFLICT = 4;
+ // The transaction is waiting for validation.
+ PENDING_VALIDATION = 5;
+ // Transaction validation failed.
+ NODE_VALIDATION_FAILED = 6;
+}
+
+message TransactionResult {
+ // The transaction id.
+ Hash transaction_id = 1;
+ // The transaction result status.
+ TransactionResultStatus status = 2;
+ // The log events.
+ repeated LogEvent logs = 3;
+ // Bloom filter for transaction logs. A transaction log event can be defined in the contract and stored
+ // in the bloom filter after the transaction is executed. Through this filter, we can quickly search for
+ // and determine whether a log exists in the transaction result.
+ bytes bloom = 4;
+ // The return value of the transaction execution.
+ bytes return_value = 5;
+ // The height of the block hat packages the transaction.
+ int64 block_number = 6;
+ // The hash of the block hat packages the transaction.
+ Hash block_hash = 7;
+ // Failed execution error message.
+ string error = 10;
+}
+
+message LogEvent {
+ // The contract address.
+ Address address = 1;
+ // The name of the log event.
+ string name = 2;
+ // The indexed data, used to calculate bloom.
+ repeated bytes indexed = 3;
+ // The non indexed data.
+ bytes non_indexed = 4;
+}
+
+message SmartContractRegistration {
+ // The category of contract code(0: C#).
+ sint32 category = 1;
+ // The byte array of the contract code.
+ bytes code = 2;
+ // The hash of the contract code.
+ Hash code_hash = 3;
+ // Whether it is a system contract.
+ bool is_system_contract = 4;
+ // The version of the current contract.
+ int32 version = 5;
+ // The version of the contract.
+ string contract_version = 6;
+ // The address of the current contract.
+ Address contract_address = 7;
+ // Indicates if the contract is the user contract.
+ bool is_user_contract = 8;
+}
+
+message TransactionExecutingStateSet {
+ // The changed states.
+ map writes = 1;
+ // The read states.
+ map reads = 2;
+ // The deleted states.
+ map deletes = 3;
+}
+
+message Address
+{
+ bytes value = 1;
+}
+
+message Hash
+{
+ bytes value = 1;
+}
+
+message SInt32Value
+{
+ sint32 value = 1;
+}
+
+message SInt64Value
+{
+ sint64 value = 1;
+}
+
+message MerklePath {
+ // The merkle path nodes.
+ repeated MerklePathNode merkle_path_nodes = 1;
+}
+
+message MerklePathNode{
+ // The node hash.
+ Hash hash = 1;
+ // Whether it is a left child node.
+ bool is_left_child_node = 2;
+}
+
+message BinaryMerkleTree {
+ // The leaf nodes.
+ repeated Hash nodes = 1;
+ // The root node hash.
+ Hash root = 2;
+ // The count of leaf node.
+ int32 leaf_count = 3;
+}
+
+message BigIntValue {
+ string value = 1;
+}
\ No newline at end of file
diff --git a/src/AElf.Inscription/Protobuf/inscription.proto b/src/AElf.Inscription/Protobuf/inscription.proto
new file mode 100644
index 0000000..f35ea88
--- /dev/null
+++ b/src/AElf.Inscription/Protobuf/inscription.proto
@@ -0,0 +1,18 @@
+syntax = "proto3";
+
+package aelf.inscription;
+import "aelf/core.proto";
+
+option csharp_namespace = "AElf.Inscription";
+
+message TransferInputWithInscription {
+ // The receiver of the token.
+ aelf.Address to = 1;
+ // The token symbol to transfer.
+ string symbol = 2;
+ // The amount to to transfer.
+ int64 amount = 3;
+ // The memo.
+ string memo = 4;
+ bytes inscription = 42;
+}
diff --git a/test/AElf.Client.Test/InscriptionTest.cs b/test/AElf.Client.Test/InscriptionTest.cs
new file mode 100644
index 0000000..1c7bc8b
--- /dev/null
+++ b/test/AElf.Client.Test/InscriptionTest.cs
@@ -0,0 +1,75 @@
+using System;
+using System.Text;
+using System.Threading.Tasks;
+using AElf.Types;
+using AElf.Client.Dto;
+using AElf.Inscription;
+using Google.Protobuf;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace AElf.Client.Test;
+
+public class InscriptionTest
+{
+ private const string BaseUrl = "https://aelf-test-node.aelf.io";
+
+ // example contract-method-name
+ private string ContractMethodName => "GetContractAddressByName";
+
+ // Address and privateKey of a node.
+ private readonly string _address;
+ private const string PrivateKey = "345af4fbb6d6142f15ec0f5ebae680195bb655f88f22573ac01222bbf537e9ca";
+
+ private AElfClient Client { get; }
+ private readonly ITestOutputHelper _testOutputHelper;
+
+ private const string UserName = "test1";
+ private const string Password = "test";
+
+ public InscriptionTest(ITestOutputHelper testOutputHelper)
+ {
+ _testOutputHelper = testOutputHelper;
+ Client = new AElfClient(BaseUrl, userName: UserName, password: Password);
+
+ // To get address from privateKey.s
+ _address = Client.GetAddressFromPrivateKey(PrivateKey);
+ }
+
+ [Fact]
+ public async Task Test_Inscribe()
+ {
+ var tokenContractAddress =
+ await Client.GetContractAddressByNameAsync(HashHelper.ComputeFrom("AElf.ContractNames.Token"));
+
+ // Using example https://ethscriptions.com/ethscriptions/0x6317e5bcc0b2d41f8de41d30b77e8e49e465766ca634f024c8ae913898620e94
+
+ var dataUrl =
+ "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAAEACAYAAABccqhmAAAACXBIWXMAAAsSAAALEgHS3X78AAAFUmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSfvu78nIGlkPSdXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQnPz4KPHg6eG1wbWV0YSB4bWxuczp4PSdhZG9iZTpuczptZXRhLycgeDp4bXB0az0nSW1hZ2U6OkV4aWZUb29sIDEyLjY0Jz4KPHJkZjpSREYgeG1sbnM6cmRmPSdodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjJz4KCiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0nJwogIHhtbG5zOmRjPSdodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyc+CiAgPGRjOmRlc2NyaXB0aW9uPgogICA8cmRmOkFsdD4KICAgIDxyZGY6bGkgeG1sOmxhbmc9J3gtZGVmYXVsdCc+eyYjMzk7bmFtZSYjMzk7OiYjMzk7QmV2JiMzOTssJiMzOTtudW1iZXImIzM5OzozMDUwLCYjMzk7ZGVzY3JpcHRpb24mIzM5OzomIzM5O0h5cHBvY3JpdGV6IGlzIG9uZSBvZiB0aGUgZmlyc3Qgb3JpZ2luYWwgY29sbGVjdGlvbnMgbWFkZSBzcGVjaWZpY2FsbHkgZm9yIEV0aHNjcmlwdGlvbnMuIEEgY29sbGVjdGlvbiBvZiBkZWdlbiBoeXBwb3MgZm9yIFdlYjMgcGVvcGxlIHdobyBoYXRlIHRvIGxvdmUgV2ViMy4mIzM5OywmIzM5O2V4dGVybmFsX3VybCYjMzk7OiYjMzk7aHR0cHM6Ly93d3cuaHlwcG9jcml0ZXouY29tJiMzOTssJiMzOTthdHRyaWJ1dGVzJiMzOTs6W3smIzM5O3RyYWl0X3R5cGUmIzM5OzomIzM5O1RlYW0mIzM5OywmIzM5O3ZhbHVlJiMzOTs6JiMzOTtCbHVlJiMzOTt9LHsmIzM5O3RyYWl0X3R5cGUmIzM5OzomIzM5O0hhbmQmIzM5OywmIzM5O3ZhbHVlJiMzOTs6JiMzOTtIb21lLVJ1bm5lciYjMzk7fSx7JiMzOTt0cmFpdF90eXBlJiMzOTs6JiMzOTtNb3V0aCYjMzk7LCYjMzk7dmFsdWUmIzM5OzomIzM5O0RyYWluZXImIzM5O30seyYjMzk7dHJhaXRfdHlwZSYjMzk7OiYjMzk7RXllcyYjMzk7LCYjMzk7dmFsdWUmIzM5OzomIzM5O0NlbGVicyYjMzk7fSx7JiMzOTt0cmFpdF90eXBlJiMzOTs6JiMzOTtTaGlydCYjMzk7LCYjMzk7dmFsdWUmIzM5OzomIzM5O1BsYXlhaCYjMzk7fSx7JiMzOTt0cmFpdF90eXBlJiMzOTs6JiMzOTtIZWFkJiMzOTssJiMzOTt2YWx1ZSYjMzk7OiYjMzk7QnJhaWQmIzM5O30seyYjMzk7dHJhaXRfdHlwZSYjMzk7OiYjMzk7U2tpbiYjMzk7LCYjMzk7dmFsdWUmIzM5OzomIzM5O01laCYjMzk7fSx7JiMzOTt0cmFpdF90eXBlJiMzOTs6JiMzOTtCYWNrZ3JvdW5kJiMzOTssJiMzOTt2YWx1ZSYjMzk7OiYjMzk7RW52eSYjMzk7fV19PC9yZGY6bGk+CiAgIDwvcmRmOkFsdD4KICA8L2RjOmRlc2NyaXB0aW9uPgogPC9yZGY6RGVzY3JpcHRpb24+CjwvcmRmOlJERj4KPC94OnhtcG1ldGE+Cjw/eHBhY2tldCBlbmQ9J3InPz7GH63uAAAOiElEQVR4nO3dX4wdZRnH8XPQRBJjSK3i2W2lNPECbFoWBM2SkihXJRotlW7VosUthlLQlBIhkBIPFEFI+KNCWwVaS2mEUtuKGLhqL9iwSKHQ1goXKhigu4AbYgwXJsTjhVfPb9p5eDtzzszZ5/u5e/bMzhnX5uF9nnnnmebYVLvTABDSSVVfAIDqkACAwEgAQGAfrfoCABzfwpltE49NtY953IliBQAERgIAAiMBAIHRAwBqRGv+Tsdu02k2myYu2hNgBQAERgIAAiMBAIHRAwAqpDV/Y5fU/H+3H5fdE2AFAARGAgACIwEAgdEDAHooU/Ovf8PGS2xNrzKf/s32BBbOTOsJsAIAAiMBAIGRAIDA6AEAXZSp+c+4x8bzZttYewI3fTb/84PyhYk9AVYAQGAkACAwEgAQGD0AoIu05l448xp7wI3yC7etSfuCG++18av2/OwDAHBcJAAgMBIAEBg9AKCHknsCet9/+04bJ9b8ihUAEBgJAAiMBAAERg8AqJDbE9guv1Cw5lesAIDASABAYCQAIDB6AECNeD2BojW/YgUABEYCAAIjAQCB0QMAaqzsml+xAgACIwEAgZEAgMBIAEBgJAAgMBIAEBgJAAiMfQDBjCx4MOn4HYcu79KVnJh+v/66YQUABEYCAAIjAQCB0QOY5rRmfuixPYm/v9jEva6p+/36644VABAYCQAIjAQABEYPILiVy2yN7NXYqffhuy31+mGxAgACIwEAgZEAgMDoASBJ0Rqbmr1eWAEAgZEAgMBIAEBgzbGpdqfqi0B5vPv0dau5u90T0PPzLIDFCgAIjAQABEYCAAJjH8A0V7eaX9X9+qY7VgBAYCQAIDASABAY+wD6XNGZeVU7/PILuZ/PHzq31O9jX4DFCgAIjAQABEYCAAJjH0BBC2e2u3r+sSl7/qprfq9mr/r7yu4ZTHesAIDASABAYCQAIDB6AA63xr/+R/mfrx4t+P1DJh6cNbvQ+VJ5Nfjdt7Z7ch0f1padT+Z+rj2T6O8OZAUABEYCAAIjAQCB0QMQmZr/Hy/n/8KGzSZsbd1h4snh85K+v7Xqx/KDlgm7fd/fq/nvWd828d7nDpj4zNMHTDwwYOO94/b4sl04bPcBbNn5RFe/r9+xAgACIwEAgZEAgMDC9wAyNf+ebTZ+6bCNx/ebUGv+13ZNmnjuElvTT64YSfx92wMom1fz3/XTton3PVduDa89g1TNZtPEnY4db6E9CG+fQDSsAIDASABAYCQAILBwPQD3Pr/W/GfPt7H0AFKl1vxl16ype/ubxzzqxH1+7mDJZ0QRrACAwEgAQGAkACCwad8DcO/zi8xefIfW8Hecv9Z+/uzdJtYav+r7/FrzXzn579zjLxw+x8Spe/tvbnw86XjPxtYnTPzK6xMmnpiwse4L2HlkVanX029YAQCBkQCAwEgAQGB93wNInsuve/ml5tea3qM1vzp52O5Nf21X2p31uUu+ZmJvX4Bf899iYq/mx/TGCgAIjAQABEYCAALrux5A6n19pTX/navz9+JrT+DN85+RM+7O/b6bm9fKT2zP4Hpnn0Dxmr9t4qI1v/6+7gvQ++7dVrfr6TesAIDASABAYCQAILDa9wDcmt+Z0ef53vvybr8VNpy75FETv/bsBSZenukJWNulR1B1zf+Txvu5v5+6V1/Pr3vtu02fBdC9/b2+nn7DCgAIjAQABEYCAAKrfQ8gw6n5U2foXfTPV+wPdAZgYk9htvQIGs6zAp7Umn948j0T65sNL258LPd8RXsE2hPQGr0or+ZX+vkl8zaVej39jhUAEBgJAAiMBAAE1hybanf8w6rjzfFvfWmRibUHsHLZ4tzzH710iT2fM7ff4z1LkPr7a9e1Tazv6jt/wtb83ba78R8Tlz3jT6XW/EjDCgAIjAQABEYCAALru30AWvN71tywLvfz6974S9L5vDn+2oPQmX7K6xFUXfMrbx9BUdT8vcUKAAiMBAAERgIAAqt9D6DVsjW3zvC7bkN+TT5/6FwTZ/bWD59nwsnVoyaeKz2HyUn7/U+N5e/V955N8HoEVdf8npcbH5h4KPGf1MaW3UdAzd9brACAwEgAQGAkACCw2vUA9Hltr+afXDFi4tFv2pp68+9sDa49gcYfHs69nsk/PW1/MGco93hP9vn+/5poePJfub8/3ppR6Pt1XkDR82fnD3xwnCOPff6qa37991b19fQaKwAgMBIAEBgJAAisdj2AoiYuy+8JdJr2eN1FkPb0fvdpzdx+Z16h87VbR/I/Tzy/nk/3SeizAzozsNc1uH5fs9bTMLqPFQAQGAkACIwEAATW/z2AO35h4+vtu/60J6BaW+27/xryLEBjw+YTvbIPZe26W0ysc/6L1vzKO1/71MNy/PzjHHns862SLor2MIakB9DtnoCeb2JiwsSp7w7MzKh0jE2lHd9rrACAwEgAQGAkACCw2vcAdO+/VxOm1miZ+/4v2RpY5wUUlXkWQej8gMuW2n0MN79dbk9AeTW/uqK5wMYfsXHjXRsOtH5rYu0BVL1PQOm/p+c3fMvE553xGRPvf/VtE39Rfr9uPQFWAEBgJAAgMBIAEFjt3w1YNu9dg5n7/rLP4M77bE3q1fRl+/4ltidQ9j4BrelTDXza1vgT73476XjtAagNrVNM3JR5Cmrv+AETn3m6ve+v+wD0WYZMzX+lvd7GvjW535/pCay2+06q7gmwAgACIwEAgZEAgMBqvw+gqEzNv2dbqefXGX/d7gnoPoGiPYGya/5U2iPw9gmslpmJG6UnsHc8/z0NqmjNrzW+OvjnV5Kup9dYAQCBkQCAwEgAQGDTrgeQqfllPkCG7P1vbd1h4rVy39+Tnftvld0j6PWzA5n7/PJ8/WAr7fl6ldoT0PcqXDh8jol1H0CzaYdCunv7N9rrSa3pnz98MOn4XmMFAARGAgACIwEAgfV9D8C9z3+2PN/u7PU/adbsci7sOLrdI/jN47pP4Osmbr9zpol/1Tlk4qL7AvS9C0V5PQHtQSi35pf7/GXX/A88Yz+veu+/YgUABEYCAAIjAQCB9d08APc+v87w0x7AnCETak02suDB3O9fc8M65wq7q2iPIPXZgfap9t1/qc/Xe/MAlPdsQeGa35nhN91rfsUKAAiMBAAERgIAAqt9D8Cd4adz/Mf321ju8xetyZbOf6DQ76e65sabcj8vuyegtOZXXg8glVfjK2r+YlgBAIGRAIDASABAYLXrASTP8Eu8z+/xavz7v/xm7ucXb7fx7uXy+f1pm+UH580ycbd7AjpPYN+zxXoA3r6BVNT85WIFAARGAgACIwEAgdV/HoDe10/93DEiNf+MT87MPX7dobNMfPIcqcmXX2LCbE/Atly8nsDRI2+ZeHDeehNrT6Doewp0noA3Yy8r7b8p2jPQeQJvTzhz+6n5C2EFAARGAgACIwEAgdWuB6A1lu4L6Nxgj99++2kmPt2p0bTmf2jH71MuL+PaVaMmvnWOHNDnPYF0+XP6lb7X4KKF9vqo+buLFQAQGAkACIwEAARW/2cB9Pl/Z65/Zsaf1PxrpEYuuybWnoDuE1h3itcTsHHdnh3Izg+w/w3ZsvOJpPNR81eLFQAQGAkACIwEAARWu30AGTrzT+f+F1T2ffK7NtkexXTbJ6D37ctGzd9brACAwEgAQGAkACCw+vcACj7vXzWvJ9BYYHsAZSvaE0ilPYSVyxbb63nLzlTsdGyPY/9G+y5Bav7uYgUABEYCAAIjAQCB1b8HoEp+11+vZXsCdsZgY7mtYcvm9QTKNnHUfl+ncdpxjvw/r+bXGl9pzT8wOOvYB6LRaLACAEIjAQCBkQCAwGrXA/BmAvZbze/RnsDoyGwTe+8iLEp7Al+49PHc4198Mn/fgr67r/NXmbn4uR+a8OHmp0w88OTW3PM/sEHnEVid9/Qn2vOw8yEeP/yD3PNNd6wAgMBIAEBgJAAgsNrNBCzKmwGYqvtz9K3RkW+YeODse0384iNLe3k5GdojOPBHez1a8+8dP2Ti516w8eyf7839vhWNKXv+TI1fjM5QjNYTYAUABEYCAAIjAQCB1W4fAOqtaM2vxi6wNb7u5d/1Hdui2n2V/Tz1vQkq+2xErH0CrACAwEgAQGAkACAwegA1t2WlrbkP7bOfL/hKd7+/OcPGRWv+1w/YfQReze/ZfVXaexM80XoCrACAwEgAQGAkACAwegCOst8dWLayewK9rvnP+Wr+/AF9V6LavVxiegJJWAEAgZEAgMBIAEBg9ABqZvMOW3MvkvkAT99na1JVdk+g7Jo/+zy/3eeQmUm43M4g1J6AxvQE0rACAAIjAQCBkQCAwOgBJOr1voCyewLqrCU21vv+t/3yERNrja/8mj+fzjz0egJV6/eeACsAIDASABAYCQAIjB5An/F6Akrf1Xf0LfuuwdSaX2t8Vfbcfq8nsO4U2SdQ8D5/Uf3WE2AFAARGAgACIwEAgfFuwJLVbV7AymWLTbztZ1eYWPf2ezX/wV1p39/tmYVF6fyDorweSN3eRcgKAAiMBAAERgIAAuv7fQBLpeaPzqv5Vdk1v/KeRSibPtvgeWrsBf+gBPMuGDXxkWfy5ydUjRUAEBgJAAiMBAAE1vc9AKXPxy+6er2Jr+nyvoC6v0fg0V/b//1a8w8M2vvUjUb+vIFuq7qmT3XXps0mbs6w//8PDPbyanysAIDASABAYCQAILC+6wHofX9vJl40Dz22x8TflX0BR+XP5dXMqTMIU3k1ftU1fVF6/aPO/IZeYwUABEYCAAIjAQCB9V0PoN9UvS9AewJV05r/zvs2mbjXfx99dkKV/ffTfSgjC2418Y5Dl5f6fR5WAEBgJAAgMBIAENi07wFU/WyAqron0Gteza/07+Op298v9fqrxgoACIwEAARGAgAC6/v3AhR9NmDR1fb59173BFTdalrdu+79fVNr/ujuvZ19AAAqQgIAAiMBAIH9D3viRPQzSUTtAAAAAElFTkSuQmCC";
+
+ var methodName = "Transfer";
+ var param = new TransferInputWithInscription
+ {
+ To = new Address { Value = Address.FromBase58("hvydyxP4xbM85oe2ipneoMFFtxzF9xi2u6h2MxZxLPTxbnRQL").Value },
+ Symbol = "ELF",
+ Amount = 1,
+ Memo = "",
+ Inscription = ByteString.CopyFrom(Encoding.UTF8.GetBytes(dataUrl))
+ };
+ var ownerAddress = Client.GetAddressFromPrivateKey(PrivateKey);
+ var transaction =
+ await Client.GenerateTransactionAsync(ownerAddress, tokenContractAddress.ToBase58(), methodName, param);
+ var txWithSign = Client.SignTransaction(PrivateKey, transaction);
+
+ var result = await Client.SendTransactionAsync(new SendTransactionInput
+ {
+ RawTransaction = txWithSign.ToByteArray().ToHex()
+ });
+
+ await Task.Delay(4000);
+ // After the transaction is mined, query the execution results.
+ var transactionResult = await Client.GetTransactionResultAsync(result.TransactionId);
+ _testOutputHelper.WriteLine($"TransactionId is: {result.TransactionId}");
+ _testOutputHelper.WriteLine(transactionResult.Status);
+ }
+}
\ No newline at end of file