I tried fetching total Balance from Binance API in C# using glitch100/BinanceDotNet library with some modifications (like converting those data members from private to public static)
The purpose of this is to be called by an MQL5 function for MT5 usage
My C# code for the DLL is somewhat like this:
using System;
using System.Text;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;
using System.Threading;
using System.IO.Pipes;
using System.IO;
using BinanceExchange.API.Client;
namespace BinanceAPIConnectMetaTrader
{
class Program
{
public static string DataServerReturn = null;
[DllExport("APIFetchTotalFreeBalance", CallingConvention = CallingConvention.StdCall)]
public static IntPtr APIFetchTotalFreeBalance(int _AccountType, IntPtr _ApiKey, IntPtr _SecretKey)
{
if (_AccountType == 0)
{
BinanceExchange.API.Endpoints.APIPrefix = "https://api.binance.com/api";
BinanceExchange.API.Endpoints.WAPIPrefix = "https://api.binance.com/wapi";
BinanceExchange.API.Websockets.AbstractBinanceWebSocketClient.BaseWebsocketUri = "wss://stream.binance.com:9443/ws";
BinanceExchange.API.Websockets.AbstractBinanceWebSocketClient.CombinedWebsocketUri = "wss://stream.binance.com:9443/stream?streams";
}
else
{
BinanceExchange.API.Endpoints.APIPrefix = "https://testnet.binance.vision/api";
BinanceExchange.API.Endpoints.WAPIPrefix = "https://testnet.binance.vision/wapi";
BinanceExchange.API.Websockets.AbstractBinanceWebSocketClient.BaseWebsocketUri = "wss://testnet.binance.vision/ws";
BinanceExchange.API.Websockets.AbstractBinanceWebSocketClient.CombinedWebsocketUri = "wss://testnet.binance.vision/stream?streams";
}
decimal total_free_balance = 0.0M;
string apiKey = new MqlString(_ApiKey).Get();
string secretKey = new MqlString(_SecretKey).Get();
//Initialise the general client with config
var client = new BinanceClient(new ClientConfiguration()
{
ApiKey = apiKey,
SecretKey = secretKey,
});
try
{
client.GetAccountInformation(3500).Result.Balances.ForEach(k =>
{
total_free_balance += k.Free;
});
}
catch (Exception ex)
{
string str = "Exception from dll : " + ex.Message;
return Marshal.StringToHGlobalAuto(str.ToString());
}
IntPtr ret = Marshal.StringToHGlobalAuto(total_free_balance.ToString());
return ret;
}
}
public class StreamString
{
private Stream ioStream;
private UnicodeEncoding streamEncoding;
public StreamString(Stream ioStream)
{
this.ioStream = ioStream;
streamEncoding = new UnicodeEncoding();
}
public string ReadString()
{
int len;
len = ioStream.ReadByte() * 256;
len += ioStream.ReadByte();
byte[] inBuffer = new byte[len];
ioStream.Read(inBuffer, 0, len);
return streamEncoding.GetString(inBuffer);
}
public int WriteString(string outString)
{
byte[] outBuffer = streamEncoding.GetBytes(outString);
int len = outBuffer.Length;
if (len > UInt16.MaxValue)
{
len = (int)UInt16.MaxValue;
}
ioStream.WriteByte((byte)(len / 256));
ioStream.WriteByte((byte)(len & 255));
ioStream.Write(outBuffer, 0, len);
ioStream.Flush();
return outBuffer.Length + 2;
}
}
class MqlString
{
private readonly IntPtr _pointer;
public MqlString(IntPtr pointer)
{
_pointer = pointer;
}
public string Get()
{
int size;
for (int i = 0; ; i += 2)
{
if (Marshal.ReadByte(_pointer, i) == 0)
{
size = i;
break;
}
}
byte[] bytes = new byte[size];
for (int i = 0; i < size; i++)
{
bytes[i] = Marshal.ReadByte(_pointer, i);
}
return Encoding.Unicode.GetString(bytes);
}
}
}
- When this function is called, then the exception is caught & the message is displayed as follows:
Total free balance = Exception from dll : One or more errors occurred.
- After removing try keyword and its braces and commenting out the inside of catch block, when this function is called, then some funny runtime exception is displayed at MT5 side log messages as follows:
Unhandled exception 0xE0434352
00007FFE51603AC0 4881ECD8000000 sub rsp, 0xd8
00007FFE51603AC7 488B0562732200 mov rax, [rip+0x227362]
00007FFE51603ACE 4833C4 xor rax, rsp
00007FFE51603AD1 48898424C0000000 mov [rsp+0xc0], rax
00007FFE51603AD9 488364242800 and qword [rsp+0x28], 0x0
00007FFE51603ADF 488D05DAFFFFFF lea rax, [rip-0x26]
00007FFE51603AE6 83E201 and edx, 0x1
00007FFE51603AE9 894C2420 mov [rsp+0x20], ecx
00007FFE51603AED 89542424 mov [rsp+0x24], edx
00007FFE51603AF1 4889442430 mov [rsp+0x30], rax
00007FFE51603AF6 4D85C9 test r9, r9
00007FFE51603AF9 744B jz 0x7ffe51603b46
00007FFE51603AFB B80F000000 mov eax, 0xf
00007FFE51603B00 488D4C2440 lea rcx, [rsp+0x40]
00007FFE51603B05 443BC0 cmp r8d, eax
00007FFE51603B08 498BD1 mov rdx, r9
00007FFE51603B0B 440F47C0 cmova r8d, eax
00007FFE51603B0F 4489442438 mov [rsp+0x38], r8d
00007FFE51603B14 49C1E003 shl r8, 0x3
00007FFE51603B18 E84AD30400 call 0x7ffe51650e67 ; PublisherFromPackageFullName (kernelbase.dll)
00007FFE51603B1D 488D4C2420 lea rcx, [rsp+0x20]
00007FFE51603B22 48FF15FF441600 call qword near [rip+0x1644ff] ; UnhandledExceptionFilter (kernelbase.dll)
crash --> 00007FFE51603B29 0F1F440000 nop [rax+rax+0x0]
00007FFE51603B2E 488B8C24C0000000 mov rcx, [rsp+0xc0]
00007FFE51603B36 4833CC xor rcx, rsp
00007FFE51603B39 E8A25E0400 call 0x7ffe516499e0 ; RemoveDllDirectory (kernelbase.dll)
00007FFE51603B3E 4881C4D8000000 add rsp, 0xd8
00007FFE51603B45 C3 ret
00007FFE51603B46 8364243800 and dword [rsp+0x38], 0x0
00: 0x00007FFE51603B29
I am really clueless about what this is & how to resolve it.
This code is the problematic part (but it is working fine when built as EXE as in the GitHub page of glitch100/BinanceDotNet/BinanceExchange.Console/ExampleProgram.cs)
client.GetAccountInformation(3500).Result.Balances.ForEach(k =>
{
total_free_balance += k.Free;
});