diff --git a/.gitignore b/.gitignore index 5bf053a..446cab1 100644 --- a/.gitignore +++ b/.gitignore @@ -101,6 +101,8 @@ ENV/ # mypy .mypy_cache/ +# Distribution / packaging VSCode .vscode/ C++/analyseValgrind.sh C++/analyseValgrind.txt +C#/obj \ No newline at end of file diff --git a/C#/App.config b/C#/App.config new file mode 100644 index 0000000..88fa402 --- /dev/null +++ b/C#/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/C#/BismuthAPI.cs b/C#/BismuthAPI.cs new file mode 100644 index 0000000..afb809c --- /dev/null +++ b/C#/BismuthAPI.cs @@ -0,0 +1,107 @@ +using System; +using System.Linq; +using System.Net.Sockets; +using System.Net.NetworkInformation; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; +using System.IO; +using System.Text; + +public class BismuthAPI +{ + private string server; + private int port; + private TcpClient tcpClientAPI = null; + private NetworkStream tcpStream; + + public BismuthAPI(string nodeServer, int nodePort) + { + this.server = nodeServer; + this.port = nodePort; + this.cnxCheck(); + } + + ~BismuthAPI() + { + tcpStream.Close(); + tcpClientAPI.Close(); + } + + public string Command(params object[] cmds) + { + for (int i = 0; i < cmds.Length; i++) this.Send(cmds[i]); + return this.Receive(); + } + + public string Receive() + { + Byte[] lengthSocketMessage = new Byte[10]; + String responseData = String.Empty; + + Int32 nBytes = tcpStream.Read(lengthSocketMessage, 0, lengthSocketMessage.Length); + responseData = System.Text.Encoding.ASCII.GetString(lengthSocketMessage, 0, nBytes); + Int32 socketLenReceiveMessage = Int32.Parse(responseData); + int socketTotalReceiveBytes = 0; + + string strJson; + using (MemoryStream ms = new MemoryStream()) + { + Byte[] data = new Byte[socketLenReceiveMessage]; + + int numBytesRead; + while ((numBytesRead = tcpStream.Read(data, 0, data.Length)) > 0) + { + Console.WriteLine("numBytesRead: "+ numBytesRead); + ms.Write(data, 0, numBytesRead); + socketTotalReceiveBytes += numBytesRead; + if (socketTotalReceiveBytes == socketLenReceiveMessage) break; + } + strJson = Encoding.ASCII.GetString(ms.ToArray(), 0, (int)ms.Length); + } + + return strJson; + } + + public void Send(object cmd) + { + Byte[] data; + + string socketMessage = JsonConvert.SerializeObject(cmd); + socketMessage = string.Format("{0:D10}", socketMessage.Length) + socketMessage; + data = System.Text.Encoding.ASCII.GetBytes(socketMessage); + tcpStream.Write(data, 0, data.Length); + } + + static public string JsonDump(string jsonData) + { + JToken jt = JToken.Parse(jsonData); + return jt.ToString(); + } + + private void cnxCheck() + { + if (this.tcpClientAPI == null) + { + try + { + this.tcpClientAPI = new TcpClient(this.server, this.port); + this.tcpStream = this.tcpClientAPI.GetStream(); + } + catch (SocketException e) + { + Console.WriteLine("SocketException: {0}", e); + } + } + } + + private TcpState getTCPState() + { + var foo = IPGlobalProperties.GetIPGlobalProperties() + .GetActiveTcpConnections() + .SingleOrDefault(x => x.LocalEndPoint.Equals(this.tcpClientAPI.Client.LocalEndPoint) + && x.RemoteEndPoint.Equals(this.tcpClientAPI.Client.RemoteEndPoint) + ); + + return foo != null ? foo.State : TcpState.Unknown; + } +} diff --git a/C#/BismuthAPI.csproj b/C#/BismuthAPI.csproj new file mode 100644 index 0000000..6a21428 --- /dev/null +++ b/C#/BismuthAPI.csproj @@ -0,0 +1,70 @@ + + + + + Debug + AnyCPU + {B49F850E-3516-451F-9B26-550E24C9FB0B} + Exe + Properties + BismuthAPI + BismuthAPI + v4.5.2 + 512 + true + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Demo_getaddress_since + + + + packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll + True + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/C#/BismuthAPI.sln b/C#/BismuthAPI.sln new file mode 100644 index 0000000..bf6bed9 --- /dev/null +++ b/C#/BismuthAPI.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "BismuthAPI", "BismuthAPI.csproj", "{B49F850E-3516-451F-9B26-550E24C9FB0B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {B49F850E-3516-451F-9B26-550E24C9FB0B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B49F850E-3516-451F-9B26-550E24C9FB0B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B49F850E-3516-451F-9B26-550E24C9FB0B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B49F850E-3516-451F-9B26-550E24C9FB0B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/C#/Demo.cs b/C#/Demo.cs new file mode 100644 index 0000000..ceea6aa --- /dev/null +++ b/C#/Demo.cs @@ -0,0 +1,54 @@ +using System; + +class Demo + { + static void Main(string[] args) + { + string ret = String.Empty; + + BismuthAPI connectionBismuthAPI = new BismuthAPI("127.0.0.1", 5658); + + // Ask for general status + Console.WriteLine("statusjson:"); + ret = connectionBismuthAPI.Command("statusjson"); + Console.WriteLine(ret); + Console.WriteLine(); + + // Gets a specific block details + Console.WriteLine("blockget(558742):"); + ret = connectionBismuthAPI.Command("blockget", 558742); + Console.WriteLine(ret); + Console.WriteLine(); + + // Gets latest block and diff + Console.WriteLine("difflast:"); + ret = connectionBismuthAPI.Command("difflast"); + Console.WriteLine(ret); + Console.WriteLine(); + + // Gets tx detail, raw format + Console.WriteLine("api_gettransaction('K1iuKwkOac4HSuzEBDxmqb5dOmfXEK98BaWQFHltdrbDd0C5iIEbh/Fj', false):"); + ret = connectionBismuthAPI.Command("api_gettransaction", "K1iuKwkOac4HSuzEBDxmqb5dOmfXEK98BaWQFHltdrbDd0C5iIEbh/Fj", false); + Console.WriteLine(ret); + Console.WriteLine(); + + // Gets tx detail, json format + Console.WriteLine("api_gettransaction('K1iuKwkOac4HSuzEBDxmqb5dOmfXEK98BaWQFHltdrbDd0C5iIEbh/Fj', true):"); + ret = connectionBismuthAPI.Command("api_gettransaction", "K1iuKwkOac4HSuzEBDxmqb5dOmfXEK98BaWQFHltdrbDd0C5iIEbh/Fj", true); + Console.WriteLine(ret); + Console.WriteLine(); + + // Gets addresses balances + Console.WriteLine("api_listbalance(['731337bb0f76463d578626a48367dfea4c6efcfa317604814f875d10','340c195f768be515488a6efedb958e135150b2ef3e53573a7017ac7d'], 0, true):"); + string[] addresses = new string[] { "731337bb0f76463d578626a48367dfea4c6efcfa317604814f875d10", "340c195f768be515488a6efedb958e135150b2ef3e53573a7017ac7d" }; + ret = connectionBismuthAPI.Command("api_listbalance", addresses, 0, true); + Console.WriteLine(ret); + Console.WriteLine(); + + // Ask for a new keys/address set + Console.WriteLine("keygen:"); + ret = connectionBismuthAPI.Command("keygen"); + Console.WriteLine(ret); + Console.WriteLine(); + } +} diff --git a/C#/Demo_getaddress_since.cs b/C#/Demo_getaddress_since.cs new file mode 100644 index 0000000..cba5e7a --- /dev/null +++ b/C#/Demo_getaddress_since.cs @@ -0,0 +1,46 @@ +using System; + +class Demo_getaddress_since +{ + static string Get_address_since(int since, int min_conf, string address) + { + BismuthAPI connectionBismuthAPI = new BismuthAPI("127.0.0.1", 5658); + + // Command first + connectionBismuthAPI.Send("api_getaddresssince"); + // Then last block + connectionBismuthAPI.Send(since); + // min confirmations + connectionBismuthAPI.Send(min_conf); + // and finally the address + connectionBismuthAPI.Send(address); + + return connectionBismuthAPI.Receive(); + } + + static void Usage(string message) + { + Console.WriteLine(message); + Console.WriteLine("Usage: BismuthAPI
"); + Environment.Exit(1); + } + + static void Main(string[] args) + { + string res_as_native_dict = String.Empty; + int since, min_conf; + string address; + + if (args.Length != 3) Usage("Please enter arguments."); + if (int.TryParse(args[0], out since) == false) Usage("Please enter a numeric argument for last known block: "); + if (int.TryParse(args[1], out min_conf) == false) Usage("Please enter a numeric argument for min confirmations: "); + address = args[2]; + + Console.WriteLine("api_getaddresssince since " + since + " minconf=" + min_conf + " for address " + address); + res_as_native_dict = Get_address_since(since, min_conf, address); + Console.WriteLine(BismuthAPI.JsonDump(res_as_native_dict)); + Console.WriteLine(); + + Environment.Exit(0); + } +} \ No newline at end of file diff --git a/C#/Properties/AssemblyInfo.cs b/C#/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..6aa87f8 --- /dev/null +++ b/C#/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("BismuthAPI")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("BismuthAPI")] +[assembly: AssemblyCopyright("Copyright © 2018")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("b49f850e-3516-451f-9b26-550e24c9fb0b")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/C#/README.md b/C#/README.md new file mode 100644 index 0000000..17a4285 --- /dev/null +++ b/C#/README.md @@ -0,0 +1,31 @@ +# C# code for Bismuth Native API access + +Demonstrates the use of a simple C# client library. + ++ [BismuthAPI.cs](BismuthAPI.cs) : C# Client library ++ [Demo.cs](Demo.cs) : A simple demo app, showing a few simple commands. It's needs a running node. ++ [Demo_getaddress_since.cs](Demo_getaddress_since.cs) : A simple demo app, showing the `api_getaddresssince` api command. It's needs a running node. + +## Notes + +Use [newtonsoft-json](https://www.nuget.org/packages/Newtonsoft.Json/) package to parse JSON API response. To download from NuGet, You can do this a couple of ways. + +**Via the "Solution Explorer"** + + Simply right-click the "References" folder and select "Manage NuGet Packages..." + Once that window comes up click on the option labeled "Online" in the left most part of the dialog. + Then in the search bar in the upper right type "json.net" + Click "Install" and you're done. + +**Via the "Package Manager Console"** + + Open the console. "View" > "Other Windows" > "Package Manager Console" + Then type the following: + + Install-Package Newtonsoft.Json + +For more info on how to use the "Package Manager Console" check out the [nuget docs](https://docs.microsoft.com/fr-fr/nuget/tools/package-manager-console). + +### Patches + +Anybody can contribute to development. If you are contributing a source code change, use a merge request of a Git branch. \ No newline at end of file diff --git a/C#/packages.config b/C#/packages.config new file mode 100644 index 0000000..07e3593 --- /dev/null +++ b/C#/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file