From 64926d2cf43f1a4ab4f12adc0799420250d11452 Mon Sep 17 00:00:00 2001 From: stojce Date: Mon, 4 Dec 2017 20:11:37 +0100 Subject: [PATCH 01/15] Taker - initial version --- dotnet/.gitignore | 8 + dotnet/.vscode/launch.json | 28 ++++ dotnet/.vscode/settings.json | 3 + dotnet/.vscode/tasks.json | 15 ++ dotnet/EtherDeltaClient.csproj | 18 +++ dotnet/EtherDeltaClient.sln | 17 ++ dotnet/EtherDeltaConfiguration.cs | 17 ++ dotnet/ILogger.cs | 7 + dotnet/Maker.cs | 9 ++ dotnet/Message.cs | 54 +++++++ dotnet/Program.cs | 25 +++ dotnet/README.md | 9 ++ dotnet/Service.cs | 256 ++++++++++++++++++++++++++++++ dotnet/Taker.cs | 173 ++++++++++++++++++++ 14 files changed, 639 insertions(+) create mode 100644 dotnet/.gitignore create mode 100644 dotnet/.vscode/launch.json create mode 100644 dotnet/.vscode/settings.json create mode 100644 dotnet/.vscode/tasks.json create mode 100644 dotnet/EtherDeltaClient.csproj create mode 100644 dotnet/EtherDeltaClient.sln create mode 100644 dotnet/EtherDeltaConfiguration.cs create mode 100644 dotnet/ILogger.cs create mode 100644 dotnet/Maker.cs create mode 100644 dotnet/Message.cs create mode 100644 dotnet/Program.cs create mode 100644 dotnet/README.md create mode 100644 dotnet/Service.cs create mode 100644 dotnet/Taker.cs diff --git a/dotnet/.gitignore b/dotnet/.gitignore new file mode 100644 index 0000000..35c720f --- /dev/null +++ b/dotnet/.gitignore @@ -0,0 +1,8 @@ +*.userprefs +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json +bin/ +obj/ diff --git a/dotnet/.vscode/launch.json b/dotnet/.vscode/launch.json new file mode 100644 index 0000000..e11f7d9 --- /dev/null +++ b/dotnet/.vscode/launch.json @@ -0,0 +1,28 @@ +{ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ + { + "name": ".NET Core Launch (console)", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/netcoreapp2.0/EhterDelta.Bots.Dontnet.dll", + "args": [], + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window + "console": "internalConsole", + "stopAtEntry": false, + "internalConsoleOptions": "openOnSessionStart" + }, + { + "name": ".NET Core Attach", + "type": "coreclr", + "request": "attach", + "processId": "${command:pickProcess}" + } + ] +} \ No newline at end of file diff --git a/dotnet/.vscode/settings.json b/dotnet/.vscode/settings.json new file mode 100644 index 0000000..e3f3c6c --- /dev/null +++ b/dotnet/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "editor.tabSize": 4 +} \ No newline at end of file diff --git a/dotnet/.vscode/tasks.json b/dotnet/.vscode/tasks.json new file mode 100644 index 0000000..769daab --- /dev/null +++ b/dotnet/.vscode/tasks.json @@ -0,0 +1,15 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "command": "dotnet", + "type": "process", + "args": [ + "build", + "${workspaceFolder}/EtherDeltaClient.csproj" + ], + "problemMatcher": "$msCompile" + } + ] +} \ No newline at end of file diff --git a/dotnet/EtherDeltaClient.csproj b/dotnet/EtherDeltaClient.csproj new file mode 100644 index 0000000..1d7f3a3 --- /dev/null +++ b/dotnet/EtherDeltaClient.csproj @@ -0,0 +1,18 @@ + + + + EhterDelta.Bots.Dontnet + $(NethereumVersion) + Stojce Slavkovski + EhterDelta.Bots.Dontnet + Exe + netcoreapp2.0 + + + + + + + + + diff --git a/dotnet/EtherDeltaClient.sln b/dotnet/EtherDeltaClient.sln new file mode 100644 index 0000000..111f959 --- /dev/null +++ b/dotnet/EtherDeltaClient.sln @@ -0,0 +1,17 @@ + +Microsoft Visual Studio Solution File, Format Version 15.00 +# Visual Studio 2017 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EtherDeltaClient", "EtherDeltaClient.csproj", "{2E39944F-2564-4DF5-A46D-011F59CD704B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {2E39944F-2564-4DF5-A46D-011F59CD704B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2E39944F-2564-4DF5-A46D-011F59CD704B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2E39944F-2564-4DF5-A46D-011F59CD704B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2E39944F-2564-4DF5-A46D-011F59CD704B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection +EndGlobal diff --git a/dotnet/EtherDeltaConfiguration.cs b/dotnet/EtherDeltaConfiguration.cs new file mode 100644 index 0000000..87347ba --- /dev/null +++ b/dotnet/EtherDeltaConfiguration.cs @@ -0,0 +1,17 @@ +using System.Runtime.Serialization; +using Nethereum.JsonRpc.Client; + +namespace EhterDelta.Bots.Dontnet +{ + public class EtherDeltaConfiguration + { + public string AddressEtherDelta { get; set; } + public string Provider { get; set; } + public string SocketUrl { get; set; } + public string AbiFile { get; internal set; } + public string TokenFile { get; internal set; } + public string Token { get; internal set; } + public string User { get; internal set; } + public int UnitDecimals { get; internal set; } + } +} \ No newline at end of file diff --git a/dotnet/ILogger.cs b/dotnet/ILogger.cs new file mode 100644 index 0000000..80f1f41 --- /dev/null +++ b/dotnet/ILogger.cs @@ -0,0 +1,7 @@ +namespace EhterDelta.Bots.Dontnet +{ + public interface ILogger + { + void Log(string message); + } +} \ No newline at end of file diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs new file mode 100644 index 0000000..ab216a8 --- /dev/null +++ b/dotnet/Maker.cs @@ -0,0 +1,9 @@ +using System; + +namespace EhterDelta.Bots.Dontnet +{ + class Maker + { + + } +} \ No newline at end of file diff --git a/dotnet/Message.cs b/dotnet/Message.cs new file mode 100644 index 0000000..faa0f6d --- /dev/null +++ b/dotnet/Message.cs @@ -0,0 +1,54 @@ +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace EhterDelta.Bots.Dontnet +{ + internal class Message + { + internal Message() + { + Data = new { }; + } + public string Event { get; set; } + + public dynamic Data { get; set; } + + public override string ToString() + { + var ret = $"42[\"{this.Event}\", {JsonConvert.SerializeObject(Data)}]"; + return ret; + } + + internal static Message ParseMessage(string messageString) + { + var message = new Message(); + + // message is Text/Json + if (messageString.StartsWith("42")) + { + messageString = messageString.Remove(0, 2); + var tmpData = JsonConvert.DeserializeObject(messageString); + + if (tmpData != null) + { + if (tmpData.GetType() == typeof(JArray)) + { + var array = (JArray)tmpData; + if (array.Count > 0 && array[0].GetType() == typeof(JValue)) + { + message.Event = array[0].ToString(); + } + + if (array.Count > 1) + { + message.Data = (object)array[1]; + } + } + } + + } + + return message; + } + } +} \ No newline at end of file diff --git a/dotnet/Program.cs b/dotnet/Program.cs new file mode 100644 index 0000000..af88b68 --- /dev/null +++ b/dotnet/Program.cs @@ -0,0 +1,25 @@ + + +using System; +using System.Linq; + +namespace EhterDelta.Bots.Dontnet +{ + class Program + { + static void Main(string[] args) + { + new Taker( + //new ConsoleLogger() + ); + } + + private class ConsoleLogger : ILogger + { + public void Log(string message) + { + Console.WriteLine($"{DateTimeOffset.Now.DateTime.ToUniversalTime()} : {message}"); + } + } + } +} \ No newline at end of file diff --git a/dotnet/README.md b/dotnet/README.md new file mode 100644 index 0000000..82de585 --- /dev/null +++ b/dotnet/README.md @@ -0,0 +1,9 @@ +# EtherDelta .Net bot # + +## Install NuGet dependencies ## + +`dotnet restore` + +## Run the bot (taker) ## + +`dotnet run` diff --git a/dotnet/Service.cs b/dotnet/Service.cs new file mode 100644 index 0000000..fda4a4c --- /dev/null +++ b/dotnet/Service.cs @@ -0,0 +1,256 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Nethereum.Contracts; +using Nethereum.JsonRpc.Client; +using Nethereum.Web3; +using Newtonsoft.Json.Linq; +using WebSocket4Net; +using Nethereum.Hex.HexTypes; +using Nethereum.RPC.Eth.Transactions; +using Nethereum.RPC.Eth.DTOs; +using System.Numerics; +using Nethereum.Util; + +namespace EhterDelta.Bots.Dontnet +{ + public class Service + { + private WebSocket socket; + const int SocketMessageTimeout = 30000; + private void Log(string message) + { + if (logger != null) + { + logger.Log(message); + } + } + + private void InitSocket() + { + socket = new WebSocket(Config.SocketUrl); + socket.Opened += SocketOpened; + socket.Error += SocketError; + socket.Closed += SocketClosed; + socket.MessageReceived += SocketMessageReceived; + socket.OpenAsync().Wait(); + } + + private ILogger logger; + + public Service(EtherDeltaConfiguration config, ILogger configLogger) + { + logger = configLogger; + + Log("Starting"); + + Orders = new Orders(); + MyOrders = new Orders(); + + Config = config; + Web3 = new Web3(config.Provider); + var addressEtherDelta = Web3.ToChecksumAddress(config.AddressEtherDelta); + + // TODO: check file exists + var abi = File.ReadAllText(config.AbiFile); + EtherDeltaContract = Web3.Eth.GetContract(abi, addressEtherDelta); + + var tokenAbi = File.ReadAllText(config.TokenFile); + EthContract = Web3.Eth.GetContract(tokenAbi, Config.Token); + + InitSocket(); + } + + internal void Close() + { + Log("Closing ..."); + if (socket != null && socket.State == WebSocketState.Open) + { + socket.Close(); + } + } + + private void SocketMessageReceived(object sender, MessageReceivedEventArgs e) + { + Message message = Message.ParseMessage(e.Message); + switch (message.Event) + { + case "market": + UpdateOrders(message.Data.orders); + UpdateTrades(message.Data.trades); + Market = message.Data; + break; + default: + break; + } + } + + private void SocketClosed(object sender, EventArgs e) + { + Log("SOCKET CLOSED"); + Log(e.GetType().ToString()); + + var ea = e as ClosedEventArgs; + if (ea != null) + { + Log(ea.Code.ToString()); + if (ea.Code == 1005) // no reason given + { + Log("Reconnecting..."); + InitSocket(); + } + } + } + + internal async Task GetBalance(string token, string user, int decimalPlacesToUnit) + { + var unitConversion = new UnitConversion(); + BigInteger balance = 0; + user = Web3.ToChecksumAddress(user); + + try + { + if (token == "ETH") + { + balance = await Web3.Eth.GetBalance.SendRequestAsync(user); + Log("ETH - GET BALANCE"); + } + else + { + token = Web3.ToChecksumAddress(token); + var tokenFunction = EthContract.GetFunction("balanceOf"); + balance = await tokenFunction.CallAsync(user); + Log("TOKEN - GET BALANCE"); + } + } + catch (Exception ex) + { + Log(ex.Message); + } + + return unitConversion.FromWei(balance, decimalPlacesToUnit); + } + + internal async Task GetEtherDeltaBalance(string token, string user, int decimalPlacesToUnit) + { + var unitConversion = new UnitConversion(); + BigInteger balance = 0; + + try + { + if (token == "ETH") + { + token = "0x0000000000000000000000000000000000000000"; + } + + var tokenFunction = EtherDeltaContract.GetFunction("balanceOf"); + balance = await tokenFunction.CallAsync(token, user); + Log("ETHER DELTA - GET BALANCE"); + } + catch (Exception ex) + { + Log(ex.Message); + } + + return unitConversion.FromWei(balance, decimalPlacesToUnit); + } + + private void SocketError(object sender, SuperSocket.ClientEngine.ErrorEventArgs e) + { + Log("SOCKET ERROR: "); + Log(e.Exception.Message); + } + + private void SocketOpened(object sender, EventArgs e) + { + Log("SOCKET Connected"); + } + + public async Task WaitForMarket() + { + Market = null; + socket.Send(new Message + { + Event = "getMarket", + Data = new + { + token = Config.Token, + user = Config.User + } + }.ToString()); + + var gotMarket = Task.Run(() => + { + while (Market == null) { Task.Delay(1000); } + }); + + var completed = await Task.WhenAny(gotMarket, Task.Delay(SocketMessageTimeout)); + + if (completed != gotMarket) + { + throw new TimeoutException("Get Market timeout"); + } + } + + private void UpdateOrders(dynamic orders) + { + //var minOrderSize = 0.001; + + if (orders == null) + { + return; + } + + if (orders.GetType() == typeof(JObject)) + { + + var sells = ((JArray)orders.sells).Where(_ => _["tokenGive"] != null && _["tokenGive"].ToString() == Config.Token).ToList(); + if (sells != null && sells.Count > 0) + { + Orders.Sells = sells; + } + + var buys = ((JArray)orders.buys).Where(_ => _["tokenGet"] != null && _["tokenGet"].ToString() == Config.Token).ToList(); + if (buys != null && buys.Count > 0) + { + Orders.Buys = buys; + } + } + + // TODO: update MyOrders + } + + private void UpdateTrades(dynamic trades) + { + if (trades == null) + { + return; + } + + if (trades.GetType() == typeof(JArray)) + { + Trades = trades; + } + } + + public EtherDeltaConfiguration Config { get; } + public Web3 Web3 { get; } + public Contract EtherDeltaContract { get; } + public Contract EthContract { get; } + public Orders Orders { get; set; } + public dynamic Trades { get; set; } + public Orders MyOrders { get; set; } + public List MyTrades { get; set; } + public dynamic Market { get; private set; } + } + + public class Orders + { + public dynamic Sells { get; set; } + public dynamic Buys { get; set; } + } +} \ No newline at end of file diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs new file mode 100644 index 0000000..bdd4d44 --- /dev/null +++ b/dotnet/Taker.cs @@ -0,0 +1,173 @@ +using Nethereum.Web3; +using System.Threading.Tasks; +using Nethereum.Hex.HexTypes; +using Nethereum.Web3.Accounts; +using Nethereum.JsonRpc.Client; +using System; +using System.Linq; +using System.Threading; +using System.Collections.Generic; +using Newtonsoft.Json.Linq; + +namespace EhterDelta.Bots.Dontnet +{ + class Taker + { + public Service service { get; private set; } + + public Taker(ILogger logger = null) + { + var config = new EtherDeltaConfiguration + { + SocketUrl = "wss://socket.etherdelta.com/socket.io/?transport=websocket", + Provider = "https://mainnet.infura.io/Ky03pelFIxoZdAUsr82w", + AddressEtherDelta = "0x8d12a197cb00d4747a1fe03395095ce2a5cc6819", + AbiFile = "../contracts/etherdelta.json", + TokenFile = "../contracts/token.json", + Token = "0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374", + User = "0x6e9bcD9f07d3961444555967D5F8ACaaae1559f4", + UnitDecimals = 18 + }; + + service = new Service(config, logger); + + GetMarket().Wait(); + + Console.WriteLine("Order book"); + + PrintOrders(); + PrintTrades(); + + Task[] tasks = new[] { + GetBalanceAsync("ETH", config.User, config.UnitDecimals), + GetBalanceAsync(config.Token, config.User, config.UnitDecimals), + GetEtherDeltaBalance("ETH", config.User, config.UnitDecimals), + GetEtherDeltaBalance(config.Token, config.User, config.UnitDecimals) + }; + + Task.WhenAll(tasks).Wait(); + } + + private async Task GetEtherDeltaBalance(string token, string user, int unitDecimals) + { + decimal balance = 0; + try + { + balance = await service.GetEtherDeltaBalance(token, user, unitDecimals); + Console.WriteLine($"Ether Delta {token} balance: {balance}"); + } + catch (TimeoutException) + { + Console.WriteLine("Could not get balance"); + } + return balance; + } + + private async Task GetBalanceAsync(string token, string user, int unitDecimals) + { + decimal balance = 0; + + try + { + balance = await service.GetBalance(token, user, unitDecimals); + Console.WriteLine($"Wallet {token} balance: {balance}"); + } + catch (TimeoutException) + { + Console.WriteLine("Could not get balance"); + } + + return balance; + } + + private void PrintTrades() + { + Console.WriteLine("Recent trades"); + int numTrades = 10; + + var trades = service.Trades; + + if (trades != null && trades.GetType() == typeof(JArray)) + { + trades = ((JArray)trades).Take(numTrades).ToArray(); + foreach (var trade in trades) + { + var tradePrice = (double)((JValue)trade.price); + var tradeAmount = (double)((JValue)trade.amount); + var tradeDate = (DateTime)((JValue)trade.date); + + Console.WriteLine($"{tradeDate.ToLocalTime()} {trade.side} {tradeAmount.ToString("N3")} @ {tradePrice.ToString("N9")}"); + } + } + } + + private void PrintOrders() + { + int ordersPerSide = 10; + + List sells = service.Orders != null ? service.Orders.Sells : null; + List buys = service.Orders != null ? service.Orders.Buys : null; + + if (sells == null || buys == null) + { + Console.WriteLine("No sell or buy orders"); + return; + } + + sells = sells.Take(ordersPerSide).Reverse().ToList(); + buys = buys.Take(ordersPerSide).ToList(); + + foreach (var item in sells) + { + Console.WriteLine(FormatItem(item)); + } + + if (buys.Count > 0 && sells.Count > 0) + { + var salesPrice = (double)(sells[sells.Count - 1]["price"]); + var buysPrice = (double)(buys[0]["price"]); + Console.WriteLine($"---- Spread ({(salesPrice - buysPrice).ToString("N9")}) ----"); + } + else + { + Console.WriteLine("--------"); + } + + if (buys != null) + { + foreach (var item in buys) + { + Console.WriteLine(FormatItem(item)); + } + } + + } + + private string FormatItem(dynamic item) + { + item.price = (double)item.price; + item.ethAvailableVolume = (double)item.ethAvailableVolume; + return $"{item.price.ToString("N9")} {item.ethAvailableVolume.ToString("N3")}"; + } + + private async Task GetMarket() + { + try + { + await service.WaitForMarket(); + } + catch (TimeoutException) + { + Console.WriteLine("Could not get Market"); + } + } + + ~Taker() + { + if (service != null) + { + service.Close(); + } + } + } +} \ No newline at end of file From 227dea283ac574c3aae658ccae62c5cdc6cada28 Mon Sep 17 00:00:00 2001 From: stojce Date: Tue, 5 Dec 2017 19:24:37 +0100 Subject: [PATCH 02/15] Run maker or taker bot from command line argumet --- dotnet/EtherDeltaConfiguration.cs | 2 + dotnet/Maker.cs | 75 +++++++++++++++++++++++++++- dotnet/OrderType.cs | 8 +++ dotnet/Program.cs | 36 ++++++++++++-- dotnet/README.md | 12 ++++- dotnet/Service.cs | 39 +++++++++++++-- dotnet/Taker.cs | 82 ++++++++++++++++++++++--------- 7 files changed, 220 insertions(+), 34 deletions(-) create mode 100644 dotnet/OrderType.cs diff --git a/dotnet/EtherDeltaConfiguration.cs b/dotnet/EtherDeltaConfiguration.cs index 87347ba..fb309c3 100644 --- a/dotnet/EtherDeltaConfiguration.cs +++ b/dotnet/EtherDeltaConfiguration.cs @@ -13,5 +13,7 @@ public class EtherDeltaConfiguration public string Token { get; internal set; } public string User { get; internal set; } public int UnitDecimals { get; internal set; } + public int GasLimit { get; internal set; } + public uint GasPrice { get; internal set; } } } \ No newline at end of file diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index ab216a8..0330aa2 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -1,9 +1,80 @@ +using Nethereum.Web3; +using System.Threading.Tasks; +using Nethereum.Hex.HexTypes; +using Nethereum.Web3.Accounts; +using Nethereum.JsonRpc.Client; using System; +using System.Numerics; +using System.Linq; +using System.Threading; +using System.Collections.Generic; +using Newtonsoft.Json.Linq; namespace EhterDelta.Bots.Dontnet { - class Maker + public class Maker : Taker + { + public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(config, logger) { - + var ordersPerSide = 1; + var expires = BlockNumber + 10; + var buyOrdersToPlace = ordersPerSide - service.MyOrders.Buys.length; + var sellOrdersToPlace = ordersPerSide - service.MyOrders.Sells.length; + var buyVolumeToPlace = EtherDeltaETH; + var sellVolumeToPlace = EtherDeltaToken; + + if (service.Orders.Buys.length <= 0 || service.Orders.Sells.length <= 0) + { + throw new Exception("Market is not two-sided, cannot calculate mid-market"); + } + + var bestBuy = decimal.Parse(service.Orders.Buys[0].price); + var bestSell = decimal.Parse(service.Orders.Sells[0].price); + + // Make sure we have a reliable mid market + if (Math.Abs((bestBuy - bestSell) / (bestBuy + bestSell) / 2.0) > 0.05) + { + throw new Exception("Market is too wide, will not place orders"); + } + + var midMarket = (bestBuy + bestSell) / 2.0; + + var orders = new List(); + + for (var i = 0; i < sellOrdersToPlace; i += 1) + { + var price = midMarket + ((i + 1) * midMarket * 0.05); + var amount = service.ToEth(sellVolumeToPlace / sellOrdersToPlace, service.Config.UnitDecimals); + Console.WriteLine($"Sell { amount.toNumber().toFixed(3)} @ { price.toFixed(9)}"); + try + { + var order = service.CreateOrder(OrderType.Sell, expires, price, amount); + orders.Add(order); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + for (var i = 0; i < buyOrdersToPlace; i += 1) + { + var price = midMarket - ((i + 1) * midMarket * 0.05); + var amount = service.ToEth(buyVolumeToPlace / price / buyOrdersToPlace, service.Config.UnitDecimals); + Console.WriteLine($"Buy { amount.ToString("N3")} @ { price.toFixed(9)}"); + try + { + var order = service.CreateOrder(OrderType.Buy, expires, price, amount); + orders.Add(order); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + + Task.WhenAll(orders).Wait(); + + Console.WriteLine("Done"); } + } } \ No newline at end of file diff --git a/dotnet/OrderType.cs b/dotnet/OrderType.cs new file mode 100644 index 0000000..5db6127 --- /dev/null +++ b/dotnet/OrderType.cs @@ -0,0 +1,8 @@ +namespace EhterDelta.Bots.Dontnet +{ + internal enum OrderType + { + Buy, + Sell + } +} \ No newline at end of file diff --git a/dotnet/Program.cs b/dotnet/Program.cs index af88b68..cc8459e 100644 --- a/dotnet/Program.cs +++ b/dotnet/Program.cs @@ -9,9 +9,39 @@ class Program { static void Main(string[] args) { - new Taker( - //new ConsoleLogger() - ); + + if (args.Length < 1 || args[0] != "taker" && args[0] != "maker") + { + Console.WriteLine("Please run with 'taker' or 'maker' argument!"); + return; + } + + var config = new EtherDeltaConfiguration + { + SocketUrl = "wss://socket.etherdelta.com/socket.io/?transport=websocket", + Provider = "https://mainnet.infura.io/Ky03pelFIxoZdAUsr82w", + AddressEtherDelta = "0x8d12a197cb00d4747a1fe03395095ce2a5cc6819", + AbiFile = "../contracts/etherdelta.json", + TokenFile = "../contracts/token.json", + Token = "0x21692a811335301907ecd6343743791802ba7cfd", + User = "0x6e9bcD9f07d3961444555967D5F8ACaaae1559f4", + UnitDecimals = 18 + }; + + ILogger logger = null; + if (args.Length == 2 && args[1] == "-v") + { + logger = new ConsoleLogger(); + } + + if (args[0] != "taker") + { + new Taker(config, logger); + } + else + { + new Maker(config, logger); + } } private class ConsoleLogger : ILogger diff --git a/dotnet/README.md b/dotnet/README.md index 82de585..6efd4ba 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -4,6 +4,14 @@ `dotnet restore` -## Run the bot (taker) ## +## Run the taker bot ## -`dotnet run` +`dotnet run taker` + +## Run the maker bot ## + +`dotnet run maker` + +## Run bot in verbose mode ## + +`dotnet run maker -v` diff --git a/dotnet/Service.cs b/dotnet/Service.cs index fda4a4c..3295163 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -3,6 +3,7 @@ using System.IO; using System.Text; using System.Linq; +using System.Numerics; using System.Threading; using System.Threading.Tasks; using Nethereum.Contracts; @@ -13,13 +14,13 @@ using Nethereum.Hex.HexTypes; using Nethereum.RPC.Eth.Transactions; using Nethereum.RPC.Eth.DTOs; -using System.Numerics; using Nethereum.Util; namespace EhterDelta.Bots.Dontnet { public class Service { + private const string ZeroToken = "0x0000000000000000000000000000000000000000"; private WebSocket socket; const int SocketMessageTimeout = 30000; private void Log(string message) @@ -65,6 +66,38 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) InitSocket(); } + internal async Task GetBlockNumber() + { + return await Web3.Eth.Blocks.GetBlockNumber.SendRequestAsync(); + } + + internal async Task CreateOrder(OrderType orderType, BigInteger expires, BigInteger price, BigInteger amount) + { + await Task.Delay(1); + + var amountBigNum = amount; + var amountBaseBigNum = amount * price; + var contractAddr = Config.AddressEtherDelta; + var tokenGet = orderType == OrderType.Buy ? Config.Token : ZeroToken; + var tokenGive = orderType == OrderType.Sell ? Config.Token : ZeroToken; + var amountGet = orderType == OrderType.Buy ? toWei(amountBigNum, Config.UnitDecimals) : toWei(amountBaseBigNum, Config.UnitDecimals); + var amountGive = orderType == OrderType.Sell ? toWei(amountBigNum, Config.UnitDecimals) : toWei(amountBaseBigNum, Config.UnitDecimals); + var orderNonce = new Random().Next(); + + + //new Nethereum.Signer.MessageSigner().ToString + } + + internal decimal ToEth(dynamic dynamic, object decimals) + { + throw new NotImplementedException(); + } + + private string toWei(BigInteger amountBigNum, int unitDecimals) + { + throw new NotImplementedException(); + } + internal void Close() { Log("Closing ..."); @@ -144,7 +177,7 @@ internal async Task GetEtherDeltaBalance(string token, string user, int { if (token == "ETH") { - token = "0x0000000000000000000000000000000000000000"; + token = ZeroToken; } var tokenFunction = EtherDeltaContract.GetFunction("balanceOf"); @@ -242,8 +275,8 @@ private void UpdateTrades(dynamic trades) public Contract EtherDeltaContract { get; } public Contract EthContract { get; } public Orders Orders { get; set; } - public dynamic Trades { get; set; } public Orders MyOrders { get; set; } + public dynamic Trades { get; set; } public List MyTrades { get; set; } public dynamic Market { get; private set; } } diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs index bdd4d44..ceea7c4 100644 --- a/dotnet/Taker.cs +++ b/dotnet/Taker.cs @@ -4,6 +4,7 @@ using Nethereum.Web3.Accounts; using Nethereum.JsonRpc.Client; using System; +using System.Numerics; using System.Linq; using System.Threading; using System.Collections.Generic; @@ -11,41 +12,43 @@ namespace EhterDelta.Bots.Dontnet { - class Taker + public class Taker { - public Service service { get; private set; } + protected Service service { get; private set; } - public Taker(ILogger logger = null) - { - var config = new EtherDeltaConfiguration - { - SocketUrl = "wss://socket.etherdelta.com/socket.io/?transport=websocket", - Provider = "https://mainnet.infura.io/Ky03pelFIxoZdAUsr82w", - AddressEtherDelta = "0x8d12a197cb00d4747a1fe03395095ce2a5cc6819", - AbiFile = "../contracts/etherdelta.json", - TokenFile = "../contracts/token.json", - Token = "0x8f3470a7388c05ee4e7af3d01d8c722b0ff52374", - User = "0x6e9bcD9f07d3961444555967D5F8ACaaae1559f4", - UnitDecimals = 18 - }; - - service = new Service(config, logger); + protected BigInteger BlockNumber { get; private set; } + protected decimal EtherDeltaETH { get; private set; } + protected decimal WalletETH { get; private set; } - GetMarket().Wait(); + protected decimal EtherDeltaToken { get; private set; } + protected decimal WalletToken { get; private set; } - Console.WriteLine("Order book"); + public Taker(EtherDeltaConfiguration config, ILogger logger = null) + { + Console.ForegroundColor = ConsoleColor.White; + service = new Service(config, logger); - PrintOrders(); - PrintTrades(); + //GetMarket().Wait(); Task[] tasks = new[] { + GetMarket(), GetBalanceAsync("ETH", config.User, config.UnitDecimals), GetBalanceAsync(config.Token, config.User, config.UnitDecimals), GetEtherDeltaBalance("ETH", config.User, config.UnitDecimals), - GetEtherDeltaBalance(config.Token, config.User, config.UnitDecimals) + GetEtherDeltaBalance(config.Token, config.User, config.UnitDecimals), + GetBlockNumber() }; Task.WhenAll(tasks).Wait(); + + PrintOrders(); + PrintTrades(); + PrintWallet(); + } + + private async Task GetBlockNumber() + { + BlockNumber = await service.GetBlockNumber(); } private async Task GetEtherDeltaBalance(string token, string user, int unitDecimals) @@ -54,12 +57,20 @@ private async Task GetEtherDeltaBalance(string token, string user, int try { balance = await service.GetEtherDeltaBalance(token, user, unitDecimals); - Console.WriteLine($"Ether Delta {token} balance: {balance}"); } catch (TimeoutException) { Console.WriteLine("Could not get balance"); } + + if (token == "ETH") + { + EtherDeltaETH = balance; + } + else + { + EtherDeltaToken = balance; + } return balance; } @@ -70,13 +81,20 @@ private async Task GetBalanceAsync(string token, string user, int unitD try { balance = await service.GetBalance(token, user, unitDecimals); - Console.WriteLine($"Wallet {token} balance: {balance}"); } catch (TimeoutException) { Console.WriteLine("Could not get balance"); } + if (token == "ETH") + { + WalletETH = balance; + } + else + { + WalletToken = balance; + } return balance; } @@ -96,13 +114,17 @@ private void PrintTrades() var tradeAmount = (double)((JValue)trade.amount); var tradeDate = (DateTime)((JValue)trade.date); + Console.ForegroundColor = trade.side == "sell" ? ConsoleColor.Red : ConsoleColor.Green; Console.WriteLine($"{tradeDate.ToLocalTime()} {trade.side} {tradeAmount.ToString("N3")} @ {tradePrice.ToString("N9")}"); } } + + Console.ForegroundColor = ConsoleColor.White; } private void PrintOrders() { + Console.WriteLine("Order book"); int ordersPerSide = 10; List sells = service.Orders != null ? service.Orders.Sells : null; @@ -117,10 +139,12 @@ private void PrintOrders() sells = sells.Take(ordersPerSide).Reverse().ToList(); buys = buys.Take(ordersPerSide).ToList(); + Console.ForegroundColor = ConsoleColor.Red; foreach (var item in sells) { Console.WriteLine(FormatItem(item)); } + Console.ForegroundColor = ConsoleColor.White; if (buys.Count > 0 && sells.Count > 0) { @@ -133,6 +157,8 @@ private void PrintOrders() Console.WriteLine("--------"); } + Console.ForegroundColor = ConsoleColor.Green; + if (buys != null) { foreach (var item in buys) @@ -141,8 +167,16 @@ private void PrintOrders() } } + Console.ForegroundColor = ConsoleColor.White; } + private void PrintWallet() + { + Console.WriteLine($"Wallet ETH balance: {WalletETH}"); + Console.WriteLine($"EtherDelta ETH balance: {EtherDeltaETH}"); + Console.WriteLine($"Wallet token balance: {WalletToken}"); + Console.WriteLine($"EtherDelta token balance: {EtherDeltaToken}"); + } private string FormatItem(dynamic item) { item.price = (double)item.price; From 5190acc4a3aab884f448da3a5023951e77030656 Mon Sep 17 00:00:00 2001 From: stojce Date: Tue, 5 Dec 2017 19:53:31 +0100 Subject: [PATCH 03/15] add external configuration file --- dotnet/App.config | 14 ++++++++++++++ dotnet/EtherDeltaClient.csproj | 1 + dotnet/EtherDeltaConfiguration.cs | 3 +++ dotnet/Program.cs | 20 +++++++++++--------- 4 files changed, 29 insertions(+), 9 deletions(-) create mode 100644 dotnet/App.config diff --git a/dotnet/App.config b/dotnet/App.config new file mode 100644 index 0000000..de7e3dd --- /dev/null +++ b/dotnet/App.config @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/dotnet/EtherDeltaClient.csproj b/dotnet/EtherDeltaClient.csproj index 1d7f3a3..3d68bb5 100644 --- a/dotnet/EtherDeltaClient.csproj +++ b/dotnet/EtherDeltaClient.csproj @@ -12,6 +12,7 @@ + diff --git a/dotnet/EtherDeltaConfiguration.cs b/dotnet/EtherDeltaConfiguration.cs index fb309c3..a1023e7 100644 --- a/dotnet/EtherDeltaConfiguration.cs +++ b/dotnet/EtherDeltaConfiguration.cs @@ -12,6 +12,9 @@ public class EtherDeltaConfiguration public string TokenFile { get; internal set; } public string Token { get; internal set; } public string User { get; internal set; } + + public string PrivateKey { get; internal set; } + public int UnitDecimals { get; internal set; } public int GasLimit { get; internal set; } public uint GasPrice { get; internal set; } diff --git a/dotnet/Program.cs b/dotnet/Program.cs index cc8459e..bffd148 100644 --- a/dotnet/Program.cs +++ b/dotnet/Program.cs @@ -2,6 +2,7 @@ using System; using System.Linq; +using System.Configuration; namespace EhterDelta.Bots.Dontnet { @@ -18,14 +19,15 @@ static void Main(string[] args) var config = new EtherDeltaConfiguration { - SocketUrl = "wss://socket.etherdelta.com/socket.io/?transport=websocket", - Provider = "https://mainnet.infura.io/Ky03pelFIxoZdAUsr82w", - AddressEtherDelta = "0x8d12a197cb00d4747a1fe03395095ce2a5cc6819", - AbiFile = "../contracts/etherdelta.json", - TokenFile = "../contracts/token.json", - Token = "0x21692a811335301907ecd6343743791802ba7cfd", - User = "0x6e9bcD9f07d3961444555967D5F8ACaaae1559f4", - UnitDecimals = 18 + SocketUrl = ConfigurationManager.AppSettings["SocketUrl"], + Provider = ConfigurationManager.AppSettings["Provider"], + AddressEtherDelta = ConfigurationManager.AppSettings["AddressEtherDelta"], + AbiFile = ConfigurationManager.AppSettings["AbiFile"], + TokenFile = ConfigurationManager.AppSettings["TokenFile"], + Token = ConfigurationManager.AppSettings["Token"], + User = ConfigurationManager.AppSettings["User"], + PrivateKey = ConfigurationManager.AppSettings["PrivateKey"], + UnitDecimals = int.Parse(ConfigurationManager.AppSettings["UnitDecimals"]), }; ILogger logger = null; @@ -34,7 +36,7 @@ static void Main(string[] args) logger = new ConsoleLogger(); } - if (args[0] != "taker") + if (args[0] == "taker") { new Taker(config, logger); } From e54abba3f1413775d20074dec8d42356f01f3c0e Mon Sep 17 00:00:00 2001 From: stojce Date: Wed, 6 Dec 2017 00:53:34 +0100 Subject: [PATCH 04/15] base bot class --- dotnet/App.config | 4 +- dotnet/BaseBot.cs | 214 ++++++++++++++++++++++++++++++++++++++++++++++ dotnet/Maker.cs | 14 +-- dotnet/Orders.cs | 36 ++++++++ dotnet/README.md | 5 ++ dotnet/Service.cs | 81 ++++++++++++++---- dotnet/Taker.cs | 189 +++------------------------------------- 7 files changed, 338 insertions(+), 205 deletions(-) create mode 100644 dotnet/BaseBot.cs create mode 100644 dotnet/Orders.cs diff --git a/dotnet/App.config b/dotnet/App.config index de7e3dd..4de31bf 100644 --- a/dotnet/App.config +++ b/dotnet/App.config @@ -6,8 +6,8 @@ - - + + diff --git a/dotnet/BaseBot.cs b/dotnet/BaseBot.cs new file mode 100644 index 0000000..de1f452 --- /dev/null +++ b/dotnet/BaseBot.cs @@ -0,0 +1,214 @@ +using Nethereum.Web3; +using System.Threading.Tasks; +using Nethereum.Hex.HexTypes; +using Nethereum.Web3.Accounts; +using Nethereum.JsonRpc.Client; +using System; +using System.Numerics; +using System.Linq; +using System.Threading; +using System.Collections.Generic; +using Newtonsoft.Json.Linq; + +namespace EhterDelta.Bots.Dontnet +{ + public abstract class BaseBot + { + protected Service service { get; set; } + + protected decimal EtherDeltaETH { get; set; } + protected decimal WalletETH { get; set; } + protected decimal EtherDeltaToken { get; set; } + protected decimal WalletToken { get; set; } + + public BaseBot(EtherDeltaConfiguration config, ILogger logger = null) + { + Console.Clear(); + Console.ResetColor(); + service = new Service(config, logger); + + Task[] tasks = new[] { + GetMarket(), + GetBalanceAsync("ETH", config.User), + GetBalanceAsync(config.Token, config.User), + GetEtherDeltaBalance("ETH", config.User), + GetEtherDeltaBalance(config.Token, config.User) + }; + + Task.WaitAll(tasks); + + PrintOrders(); + PrintTrades(); + PrintWallet(); + + Console.WriteLine(); + } + + private async Task GetEtherDeltaBalance(string token, string user) + { + decimal balance = 0; + try + { + balance = await service.GetEtherDeltaBalance(token, user); + } + catch (TimeoutException) + { + Console.WriteLine("Could not get balance"); + } + + if (token == "ETH") + { + EtherDeltaETH = balance; + } + else + { + EtherDeltaToken = balance; + } + return balance; + } + + private async Task GetBalanceAsync(string token, string user) + { + decimal balance = 0; + + try + { + balance = await service.GetBalance(token, user); + } + catch (TimeoutException) + { + Console.WriteLine("Could not get balance"); + } + + if (token == "ETH") + { + WalletETH = balance; + } + else + { + WalletToken = balance; + } + return balance; + } + + private void PrintTrades() + { + Console.WriteLine(); + Console.WriteLine("Recent trades"); + Console.WriteLine("===================================="); + int numTrades = 10; + + var trades = service.Trades; + + if (trades != null && trades.GetType() == typeof(JArray)) + { + trades = ((JArray)trades).Take(numTrades).ToArray(); + foreach (var trade in trades) + { + var tradePrice = (double)((JValue)trade.price); + var tradeAmount = (double)((JValue)trade.amount); + var tradeDate = (DateTime)((JValue)trade.date); + + Console.ForegroundColor = trade.side == "sell" ? ConsoleColor.Red : ConsoleColor.Green; + Console.WriteLine($"{tradeDate.ToLocalTime()} {trade.side} {tradeAmount.ToString("N3")} @ {tradePrice.ToString("N9")}"); + } + } + + Console.ResetColor(); + } + + private void PrintOrders() + { + Console.WriteLine(); + Console.WriteLine("Order book"); + Console.WriteLine("===================================="); + int ordersPerSide = 10; + + List sells = service.Orders != null ? service.Orders.Sells : null; + List buys = service.Orders != null ? service.Orders.Buys : null; + + if (sells == null || buys == null) + { + Console.WriteLine("No sell or buy orders"); + return; + } + + sells = sells.Take(ordersPerSide).Reverse().ToList(); + buys = buys.Take(ordersPerSide).ToList(); + + Console.ForegroundColor = ConsoleColor.Red; + foreach (var item in sells) + { + Console.WriteLine(FormatOrder(item)); + } + Console.ResetColor(); + + if (buys.Count > 0 && sells.Count > 0) + { + var salesPrice = (double)(sells.Last().Price); + var buysPrice = (double)(buys[0]["price"]); + Console.WriteLine($"---- Spread ({(salesPrice - buysPrice).ToString("N9")}) ----"); + } + else + { + Console.WriteLine("--------"); + } + + Console.ForegroundColor = ConsoleColor.Green; + + if (buys != null) + { + foreach (var item in buys) + { + Console.WriteLine(FormatItem(item)); + } + } + + Console.ResetColor(); + } + + private void PrintWallet() + { + Console.WriteLine(); + Console.WriteLine("Account balances"); + Console.WriteLine("===================================="); + Console.WriteLine($"Wallet ETH balance: {WalletETH}"); + Console.WriteLine($"EtherDelta ETH balance: {EtherDeltaETH}"); + Console.WriteLine($"Wallet token balance: {WalletToken}"); + Console.WriteLine($"EtherDelta token balance: {EtherDeltaToken}"); + } + private string FormatItem(dynamic item) + { + var price = (double)item.price; + item.ethAvailableVolume = (double)item.ethAvailableVolume; + return $"{price.ToString("N9")} {item.ethAvailableVolume.ToString("N3"),20}"; + } + + private string FormatOrder(Order item) + { + return $"{item.Price.ToString("N9")} {item.EthAvailableVolume.ToString("N3"),20}"; + } + + private async Task GetMarket() + { + try + { + await service.WaitForMarket(); + } + catch (TimeoutException) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Could not get Market!"); + Console.ResetColor(); + } + } + + ~BaseBot() + { + if (service != null) + { + service.Close(); + } + } + } +} \ No newline at end of file diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index 0330aa2..aa6d9e1 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -12,24 +12,24 @@ namespace EhterDelta.Bots.Dontnet { - public class Maker : Taker + public class Maker : BaseBot { public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(config, logger) { var ordersPerSide = 1; - var expires = BlockNumber + 10; - var buyOrdersToPlace = ordersPerSide - service.MyOrders.Buys.length; - var sellOrdersToPlace = ordersPerSide - service.MyOrders.Sells.length; + var expires = service.GetBlockNumber().Result + 10; + var buyOrdersToPlace = ordersPerSide - service.MyOrders.Buys.Count; + var sellOrdersToPlace = ordersPerSide - service.MyOrders.Sells.Count; var buyVolumeToPlace = EtherDeltaETH; var sellVolumeToPlace = EtherDeltaToken; - if (service.Orders.Buys.length <= 0 || service.Orders.Sells.length <= 0) + if (service.Orders.Buys.Count <= 0 || service.Orders.Sells.Count <= 0) { throw new Exception("Market is not two-sided, cannot calculate mid-market"); } var bestBuy = decimal.Parse(service.Orders.Buys[0].price); - var bestSell = decimal.Parse(service.Orders.Sells[0].price); + var bestSell = service.Orders.Sells[0].Price; // Make sure we have a reliable mid market if (Math.Abs((bestBuy - bestSell) / (bestBuy + bestSell) / 2.0) > 0.05) @@ -45,7 +45,7 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi { var price = midMarket + ((i + 1) * midMarket * 0.05); var amount = service.ToEth(sellVolumeToPlace / sellOrdersToPlace, service.Config.UnitDecimals); - Console.WriteLine($"Sell { amount.toNumber().toFixed(3)} @ { price.toFixed(9)}"); + Console.WriteLine($"Sell { amount.ToString("N3")} @ { price.ToString("N9")}"); try { var order = service.CreateOrder(OrderType.Sell, expires, price, amount); diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs new file mode 100644 index 0000000..349ff1b --- /dev/null +++ b/dotnet/Orders.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using System.Numerics; +using Nethereum.Hex.HexTypes; +using Nethereum.Util; + +namespace EhterDelta.Bots.Dontnet +{ + public class Orders + { + public List Sells { get; set; } + public List Buys { get; set; } + } + + public class Order + { + public string Id { get; set; } + public string Amount { get; set; } + public double Price { get; set; } + public string TokenGet { get; set; } + public HexBigInteger AmountGet { get; set; } + public string TokenGive { get; set; } + public HexBigInteger AmountGive { get; set; } + public BigInteger Expires { get; set; } + public BigInteger Nonce { get; set; } + public string User { get; set; } + public string Updated { get; set; } + public string AvailableVolume { get; set; } + public decimal EthAvailableVolume { get; set; } + public string AvailableVolumeBase { get; set; } + public double EthAvailableVolumeBase { get; set; } + public string AmountFilled { get; set; } + public int V { get; internal set; } + public string R { get; internal set; } + public string S { get; internal set; } + } +} \ No newline at end of file diff --git a/dotnet/README.md b/dotnet/README.md index 6efd4ba..8b0c6a1 100644 --- a/dotnet/README.md +++ b/dotnet/README.md @@ -4,6 +4,11 @@ `dotnet restore` +## Configuration ## + +Add configuration settings into `App.config` file. + + ## Run the taker bot ## `dotnet run taker` diff --git a/dotnet/Service.cs b/dotnet/Service.cs index 3295163..0aef305 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -46,11 +46,19 @@ private void InitSocket() public Service(EtherDeltaConfiguration config, ILogger configLogger) { logger = configLogger; - Log("Starting"); - Orders = new Orders(); - MyOrders = new Orders(); + Orders = new Orders + { + Sells = new List(), + Buys = new List() + }; + + MyOrders = new Orders + { + Sells = new List(), + Buys = new List() + }; Config = config; Web3 = new Web3(config.Provider); @@ -66,6 +74,48 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) InitSocket(); } + internal async Task TakeOrder(Order order, double fraction) + { + Console.WriteLine(order.AmountGet); + var amount = 1 * fraction; + + // var maxGas = 250000; + // var gasPriceWei = 1000000000; // 1 Gwei + + var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); + var fn = EtherDeltaContract.GetFunction("testTrade"); + + var resp = await fn.CallAsync( + order.TokenGet, + order.AmountGet.Value, + order.TokenGive, + order.AmountGive.Value, + order.Expires, + txCount.Value, + order.User, + order.V, + order.R, + order.S, + amount, + Config.User + ); + + + Console.WriteLine(resp); + + + + + var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, 10, + txCount.Value); + + } + + internal Order GetBestAvailableSell() + { + return Orders.Sells.FirstOrDefault(); + } + internal async Task GetBlockNumber() { return await Web3.Eth.Blocks.GetBlockNumber.SendRequestAsync(); @@ -88,7 +138,7 @@ internal async Task CreateOrder(OrderType orderType, BigInteger expires, BigInte //new Nethereum.Signer.MessageSigner().ToString } - internal decimal ToEth(dynamic dynamic, object decimals) + internal BigInteger ToEth(dynamic dynamic, object decimals) { throw new NotImplementedException(); } @@ -139,7 +189,7 @@ private void SocketClosed(object sender, EventArgs e) } } - internal async Task GetBalance(string token, string user, int decimalPlacesToUnit) + internal async Task GetBalance(string token, string user) { var unitConversion = new UnitConversion(); BigInteger balance = 0; @@ -165,10 +215,10 @@ internal async Task GetBalance(string token, string user, int decimalPl Log(ex.Message); } - return unitConversion.FromWei(balance, decimalPlacesToUnit); + return unitConversion.FromWei(balance, Config.UnitDecimals); } - internal async Task GetEtherDeltaBalance(string token, string user, int decimalPlacesToUnit) + internal async Task GetEtherDeltaBalance(string token, string user) { var unitConversion = new UnitConversion(); BigInteger balance = 0; @@ -189,7 +239,7 @@ internal async Task GetEtherDeltaBalance(string token, string user, int Log(ex.Message); } - return unitConversion.FromWei(balance, decimalPlacesToUnit); + return unitConversion.FromWei(balance, Config.UnitDecimals); } private void SocketError(object sender, SuperSocket.ClientEngine.ErrorEventArgs e) @@ -240,9 +290,12 @@ private void UpdateOrders(dynamic orders) if (orders.GetType() == typeof(JObject)) { + var sells = ((JArray)orders.sells) + .Where(_ => _["tokenGive"] != null && _["tokenGive"].ToString() == Config.Token) + .Select(_ => _.ToObject()) + .ToList(); - var sells = ((JArray)orders.sells).Where(_ => _["tokenGive"] != null && _["tokenGive"].ToString() == Config.Token).ToList(); - if (sells != null && sells.Count > 0) + if (sells != null && sells.Count() > 0) { Orders.Sells = sells; } @@ -250,7 +303,7 @@ private void UpdateOrders(dynamic orders) var buys = ((JArray)orders.buys).Where(_ => _["tokenGet"] != null && _["tokenGet"].ToString() == Config.Token).ToList(); if (buys != null && buys.Count > 0) { - Orders.Buys = buys; + Orders.Buys = buys.ToList(); } } @@ -280,10 +333,4 @@ private void UpdateTrades(dynamic trades) public List MyTrades { get; set; } public dynamic Market { get; private set; } } - - public class Orders - { - public dynamic Sells { get; set; } - public dynamic Buys { get; set; } - } } \ No newline at end of file diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs index ceea7c4..01612da 100644 --- a/dotnet/Taker.cs +++ b/dotnet/Taker.cs @@ -12,196 +12,27 @@ namespace EhterDelta.Bots.Dontnet { - public class Taker + public class Taker : BaseBot { - protected Service service { get; private set; } - - protected BigInteger BlockNumber { get; private set; } - protected decimal EtherDeltaETH { get; private set; } - protected decimal WalletETH { get; private set; } - - protected decimal EtherDeltaToken { get; private set; } - protected decimal WalletToken { get; private set; } - - public Taker(EtherDeltaConfiguration config, ILogger logger = null) - { - Console.ForegroundColor = ConsoleColor.White; - service = new Service(config, logger); - - //GetMarket().Wait(); - - Task[] tasks = new[] { - GetMarket(), - GetBalanceAsync("ETH", config.User, config.UnitDecimals), - GetBalanceAsync(config.Token, config.User, config.UnitDecimals), - GetEtherDeltaBalance("ETH", config.User, config.UnitDecimals), - GetEtherDeltaBalance(config.Token, config.User, config.UnitDecimals), - GetBlockNumber() - }; - - Task.WhenAll(tasks).Wait(); - - PrintOrders(); - PrintTrades(); - PrintWallet(); - } - - private async Task GetBlockNumber() - { - BlockNumber = await service.GetBlockNumber(); - } - - private async Task GetEtherDeltaBalance(string token, string user, int unitDecimals) - { - decimal balance = 0; - try - { - balance = await service.GetEtherDeltaBalance(token, user, unitDecimals); - } - catch (TimeoutException) - { - Console.WriteLine("Could not get balance"); - } - - if (token == "ETH") - { - EtherDeltaETH = balance; - } - else - { - EtherDeltaToken = balance; - } - return balance; - } - - private async Task GetBalanceAsync(string token, string user, int unitDecimals) - { - decimal balance = 0; - - try - { - balance = await service.GetBalance(token, user, unitDecimals); - } - catch (TimeoutException) - { - Console.WriteLine("Could not get balance"); - } - - if (token == "ETH") - { - WalletETH = balance; - } - else - { - WalletToken = balance; - } - return balance; - } - - private void PrintTrades() + public Taker(EtherDeltaConfiguration config, ILogger logger = null) : base(config, logger) { - Console.WriteLine("Recent trades"); - int numTrades = 10; - - var trades = service.Trades; + var order = service.GetBestAvailableSell(); - if (trades != null && trades.GetType() == typeof(JArray)) + if (order != null) { - trades = ((JArray)trades).Take(numTrades).ToArray(); - foreach (var trade in trades) - { - var tradePrice = (double)((JValue)trade.price); - var tradeAmount = (double)((JValue)trade.amount); - var tradeDate = (DateTime)((JValue)trade.date); + Console.WriteLine($"Best available: Sell {order.EthAvailableVolume.ToString("N3")} @ {order.Price.ToString("N9")}"); + var desiredAmountBase = 0.001; - Console.ForegroundColor = trade.side == "sell" ? ConsoleColor.Red : ConsoleColor.Green; - Console.WriteLine($"{tradeDate.ToLocalTime()} {trade.side} {tradeAmount.ToString("N3")} @ {tradePrice.ToString("N9")}"); - } - } - - Console.ForegroundColor = ConsoleColor.White; - } - - private void PrintOrders() - { - Console.WriteLine("Order book"); - int ordersPerSide = 10; - - List sells = service.Orders != null ? service.Orders.Sells : null; - List buys = service.Orders != null ? service.Orders.Buys : null; - - if (sells == null || buys == null) - { - Console.WriteLine("No sell or buy orders"); - return; - } - - sells = sells.Take(ordersPerSide).Reverse().ToList(); - buys = buys.Take(ordersPerSide).ToList(); - - Console.ForegroundColor = ConsoleColor.Red; - foreach (var item in sells) - { - Console.WriteLine(FormatItem(item)); - } - Console.ForegroundColor = ConsoleColor.White; - - if (buys.Count > 0 && sells.Count > 0) - { - var salesPrice = (double)(sells[sells.Count - 1]["price"]); - var buysPrice = (double)(buys[0]["price"]); - Console.WriteLine($"---- Spread ({(salesPrice - buysPrice).ToString("N9")}) ----"); + var fraction = Math.Min(desiredAmountBase / order.EthAvailableVolumeBase, 1); + service.TakeOrder(order, fraction).Wait(); } else { - Console.WriteLine("--------"); - } - - Console.ForegroundColor = ConsoleColor.Green; - - if (buys != null) - { - foreach (var item in buys) - { - Console.WriteLine(FormatItem(item)); - } + Console.WriteLine("No Available order"); } - Console.ForegroundColor = ConsoleColor.White; - } - - private void PrintWallet() - { - Console.WriteLine($"Wallet ETH balance: {WalletETH}"); - Console.WriteLine($"EtherDelta ETH balance: {EtherDeltaETH}"); - Console.WriteLine($"Wallet token balance: {WalletToken}"); - Console.WriteLine($"EtherDelta token balance: {EtherDeltaToken}"); - } - private string FormatItem(dynamic item) - { - item.price = (double)item.price; - item.ethAvailableVolume = (double)item.ethAvailableVolume; - return $"{item.price.ToString("N9")} {item.ethAvailableVolume.ToString("N3")}"; - } - private async Task GetMarket() - { - try - { - await service.WaitForMarket(); - } - catch (TimeoutException) - { - Console.WriteLine("Could not get Market"); - } - } - - ~Taker() - { - if (service != null) - { - service.Close(); - } + Console.WriteLine(); } } } \ No newline at end of file From d73fa48b187d0d0dc4767eba382fb34dbf89c85b Mon Sep 17 00:00:00 2001 From: stojce Date: Wed, 6 Dec 2017 17:22:50 +0100 Subject: [PATCH 05/15] code formating --- dotnet/.gitignore | 1 + dotnet/.vscode/launch.json | 15 +- dotnet/BaseBot.cs | 370 ++++++++--------- dotnet/EtherDeltaClient.sln | 2 +- dotnet/EtherDeltaConfiguration.cs | 37 +- dotnet/ILogger.cs | 10 +- dotnet/Maker.cs | 140 +++---- dotnet/Message.cs | 96 ++--- dotnet/OrderType.cs | 12 +- dotnet/Orders.cs | 61 ++- dotnet/Program.cs | 97 +++-- dotnet/Service.cs | 668 +++++++++++++++--------------- dotnet/Taker.cs | 55 +-- 13 files changed, 778 insertions(+), 786 deletions(-) diff --git a/dotnet/.gitignore b/dotnet/.gitignore index 35c720f..a847859 100644 --- a/dotnet/.gitignore +++ b/dotnet/.gitignore @@ -6,3 +6,4 @@ !.vscode/extensions.json bin/ obj/ +.vs \ No newline at end of file diff --git a/dotnet/.vscode/launch.json b/dotnet/.vscode/launch.json index e11f7d9..419e924 100644 --- a/dotnet/.vscode/launch.json +++ b/dotnet/.vscode/launch.json @@ -1,9 +1,9 @@ { - // Use IntelliSense to find out which attributes exist for C# debugging - // Use hover for the description of the existing attributes - // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md - "version": "0.2.0", - "configurations": [ + // Use IntelliSense to find out which attributes exist for C# debugging + // Use hover for the description of the existing attributes + // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md + "version": "0.2.0", + "configurations": [ { "name": ".NET Core Launch (console)", "type": "coreclr", @@ -11,7 +11,10 @@ "preLaunchTask": "build", // If you have changed target frameworks, make sure to update the program path. "program": "${workspaceFolder}/bin/Debug/netcoreapp2.0/EhterDelta.Bots.Dontnet.dll", - "args": [], + "args": [ + "taker", + "-v" + ], "cwd": "${workspaceFolder}", // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window "console": "internalConsole", diff --git a/dotnet/BaseBot.cs b/dotnet/BaseBot.cs index de1f452..01f47d5 100644 --- a/dotnet/BaseBot.cs +++ b/dotnet/BaseBot.cs @@ -1,214 +1,208 @@ -using Nethereum.Web3; -using System.Threading.Tasks; -using Nethereum.Hex.HexTypes; -using Nethereum.Web3.Accounts; -using Nethereum.JsonRpc.Client; +using Newtonsoft.Json.Linq; using System; -using System.Numerics; -using System.Linq; -using System.Threading; using System.Collections.Generic; -using Newtonsoft.Json.Linq; +using System.Linq; +using System.Threading.Tasks; namespace EhterDelta.Bots.Dontnet { - public abstract class BaseBot - { - protected Service service { get; set; } - - protected decimal EtherDeltaETH { get; set; } - protected decimal WalletETH { get; set; } - protected decimal EtherDeltaToken { get; set; } - protected decimal WalletToken { get; set; } - - public BaseBot(EtherDeltaConfiguration config, ILogger logger = null) + public abstract class BaseBot { - Console.Clear(); - Console.ResetColor(); - service = new Service(config, logger); + protected Service Service { get; set; } - Task[] tasks = new[] { - GetMarket(), - GetBalanceAsync("ETH", config.User), - GetBalanceAsync(config.Token, config.User), - GetEtherDeltaBalance("ETH", config.User), - GetEtherDeltaBalance(config.Token, config.User) - }; + protected decimal EtherDeltaETH { get; set; } + protected decimal WalletETH { get; set; } + protected decimal EtherDeltaToken { get; set; } + protected decimal WalletToken { get; set; } - Task.WaitAll(tasks); + public BaseBot(EtherDeltaConfiguration config, ILogger logger = null) + { + Console.Clear(); + Console.ResetColor(); + Service = new Service(config, logger); - PrintOrders(); - PrintTrades(); - PrintWallet(); + Task[] tasks = new[] { + GetMarket(), + GetBalanceAsync("ETH", config.User), + GetBalanceAsync(config.Token, config.User), + GetEtherDeltaBalance("ETH", config.User), + GetEtherDeltaBalance(config.Token, config.User) + }; - Console.WriteLine(); - } + Task.WaitAll(tasks); - private async Task GetEtherDeltaBalance(string token, string user) - { - decimal balance = 0; - try - { - balance = await service.GetEtherDeltaBalance(token, user); - } - catch (TimeoutException) - { - Console.WriteLine("Could not get balance"); - } - - if (token == "ETH") - { - EtherDeltaETH = balance; - } - else - { - EtherDeltaToken = balance; - } - return balance; - } + PrintOrders(); + PrintTrades(); + PrintWallet(); - private async Task GetBalanceAsync(string token, string user) - { - decimal balance = 0; - - try - { - balance = await service.GetBalance(token, user); - } - catch (TimeoutException) - { - Console.WriteLine("Could not get balance"); - } - - if (token == "ETH") - { - WalletETH = balance; - } - else - { - WalletToken = balance; - } - return balance; - } - - private void PrintTrades() - { - Console.WriteLine(); - Console.WriteLine("Recent trades"); - Console.WriteLine("===================================="); - int numTrades = 10; - - var trades = service.Trades; + Console.WriteLine(); + } - if (trades != null && trades.GetType() == typeof(JArray)) - { - trades = ((JArray)trades).Take(numTrades).ToArray(); - foreach (var trade in trades) + private async Task GetEtherDeltaBalance(string token, string user) { - var tradePrice = (double)((JValue)trade.price); - var tradeAmount = (double)((JValue)trade.amount); - var tradeDate = (DateTime)((JValue)trade.date); - - Console.ForegroundColor = trade.side == "sell" ? ConsoleColor.Red : ConsoleColor.Green; - Console.WriteLine($"{tradeDate.ToLocalTime()} {trade.side} {tradeAmount.ToString("N3")} @ {tradePrice.ToString("N9")}"); + decimal balance = 0; + try + { + balance = await Service.GetEtherDeltaBalance(token, user); + } + catch (TimeoutException) + { + Console.WriteLine("Could not get balance"); + } + + if (token == "ETH") + { + EtherDeltaETH = balance; + } + else + { + EtherDeltaToken = balance; + } + return balance; } - } - Console.ResetColor(); - } + private async Task GetBalanceAsync(string token, string user) + { + decimal balance = 0; + + try + { + balance = await Service.GetBalance(token, user); + } + catch (TimeoutException) + { + Console.WriteLine("Could not get balance"); + } + + if (token == "ETH") + { + WalletETH = balance; + } + else + { + WalletToken = balance; + } + return balance; + } - private void PrintOrders() - { - Console.WriteLine(); - Console.WriteLine("Order book"); - Console.WriteLine("===================================="); - int ordersPerSide = 10; - - List sells = service.Orders != null ? service.Orders.Sells : null; - List buys = service.Orders != null ? service.Orders.Buys : null; - - if (sells == null || buys == null) - { - Console.WriteLine("No sell or buy orders"); - return; - } - - sells = sells.Take(ordersPerSide).Reverse().ToList(); - buys = buys.Take(ordersPerSide).ToList(); - - Console.ForegroundColor = ConsoleColor.Red; - foreach (var item in sells) - { - Console.WriteLine(FormatOrder(item)); - } - Console.ResetColor(); - - if (buys.Count > 0 && sells.Count > 0) - { - var salesPrice = (double)(sells.Last().Price); - var buysPrice = (double)(buys[0]["price"]); - Console.WriteLine($"---- Spread ({(salesPrice - buysPrice).ToString("N9")}) ----"); - } - else - { - Console.WriteLine("--------"); - } - - Console.ForegroundColor = ConsoleColor.Green; - - if (buys != null) - { - foreach (var item in buys) + private void PrintTrades() { - Console.WriteLine(FormatItem(item)); + Console.WriteLine(); + Console.WriteLine("Recent trades"); + Console.WriteLine("===================================="); + int numTrades = 10; + + var trades = Service.Trades; + + if (trades != null && trades.GetType() == typeof(JArray)) + { + trades = ((JArray)trades).Take(numTrades).ToArray(); + foreach (var trade in trades) + { + var tradePrice = (double)((JValue)trade.price); + var tradeAmount = (double)((JValue)trade.amount); + var tradeDate = (DateTime)((JValue)trade.date); + + Console.ForegroundColor = trade.side == "sell" ? ConsoleColor.Red : ConsoleColor.Green; + Console.WriteLine($"{tradeDate.ToLocalTime()} {trade.side} {tradeAmount.ToString("N3")} @ {tradePrice.ToString("N9")}"); + } + } + + Console.ResetColor(); } - } - Console.ResetColor(); - } + private void PrintOrders() + { + Console.WriteLine(); + Console.WriteLine("Order book"); + Console.WriteLine("===================================="); + int ordersPerSide = 10; + + List sells = Service.Orders != null ? Service.Orders.Sells : null; + List buys = Service.Orders != null ? Service.Orders.Buys : null; + + if (sells == null || buys == null) + { + Console.WriteLine("No sell or buy orders"); + return; + } + + sells = sells.Take(ordersPerSide).Reverse().ToList(); + buys = buys.Take(ordersPerSide).ToList(); + + Console.ForegroundColor = ConsoleColor.Red; + foreach (var item in sells) + { + Console.WriteLine(FormatOrder(item)); + } + Console.ResetColor(); + + if (buys.Count > 0 && sells.Count > 0) + { + var salesPrice = (double)(sells.Last().Price); + var buysPrice = (double)(buys[0]["price"]); + Console.WriteLine($"---- Spread ({(salesPrice - buysPrice).ToString("N9")}) ----"); + } + else + { + Console.WriteLine("--------"); + } + + Console.ForegroundColor = ConsoleColor.Green; + + if (buys != null) + { + foreach (var item in buys) + { + Console.WriteLine(FormatItem(item)); + } + } + + Console.ResetColor(); + } - private void PrintWallet() - { - Console.WriteLine(); - Console.WriteLine("Account balances"); - Console.WriteLine("===================================="); - Console.WriteLine($"Wallet ETH balance: {WalletETH}"); - Console.WriteLine($"EtherDelta ETH balance: {EtherDeltaETH}"); - Console.WriteLine($"Wallet token balance: {WalletToken}"); - Console.WriteLine($"EtherDelta token balance: {EtherDeltaToken}"); - } - private string FormatItem(dynamic item) - { - var price = (double)item.price; - item.ethAvailableVolume = (double)item.ethAvailableVolume; - return $"{price.ToString("N9")} {item.ethAvailableVolume.ToString("N3"),20}"; - } + private void PrintWallet() + { + Console.WriteLine(); + Console.WriteLine("Account balances"); + Console.WriteLine("===================================="); + Console.WriteLine($"Wallet ETH balance: {WalletETH}"); + Console.WriteLine($"EtherDelta ETH balance: {EtherDeltaETH}"); + Console.WriteLine($"Wallet token balance: {WalletToken}"); + Console.WriteLine($"EtherDelta token balance: {EtherDeltaToken}"); + } + private string FormatItem(dynamic item) + { + var price = (double)item.price; + item.ethAvailableVolume = (double)item.ethAvailableVolume; + return $"{price.ToString("N9")} {item.ethAvailableVolume.ToString("N3"),20}"; + } - private string FormatOrder(Order item) - { - return $"{item.Price.ToString("N9")} {item.EthAvailableVolume.ToString("N3"),20}"; - } + private string FormatOrder(Order item) + { + return $"{item.Price.ToString("N9")} {item.EthAvailableVolume.ToString("N3"),20}"; + } - private async Task GetMarket() - { - try - { - await service.WaitForMarket(); - } - catch (TimeoutException) - { - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine("Could not get Market!"); - Console.ResetColor(); - } - } + private async Task GetMarket() + { + try + { + await Service.WaitForMarket(); + } + catch (TimeoutException) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine("Could not get Market!"); + Console.ResetColor(); + } + } - ~BaseBot() - { - if (service != null) - { - service.Close(); - } + ~BaseBot() + { + if (Service != null) + { + Service.Close(); + } + } } - } } \ No newline at end of file diff --git a/dotnet/EtherDeltaClient.sln b/dotnet/EtherDeltaClient.sln index 111f959..57785e0 100644 --- a/dotnet/EtherDeltaClient.sln +++ b/dotnet/EtherDeltaClient.sln @@ -1,5 +1,5 @@ -Microsoft Visual Studio Solution File, Format Version 15.00 +Microsoft Visual Studio Solution File, Format Version 14.00 # Visual Studio 2017 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EtherDeltaClient", "EtherDeltaClient.csproj", "{2E39944F-2564-4DF5-A46D-011F59CD704B}" EndProject diff --git a/dotnet/EtherDeltaConfiguration.cs b/dotnet/EtherDeltaConfiguration.cs index a1023e7..95c2a12 100644 --- a/dotnet/EtherDeltaConfiguration.cs +++ b/dotnet/EtherDeltaConfiguration.cs @@ -1,22 +1,19 @@ -using System.Runtime.Serialization; -using Nethereum.JsonRpc.Client; - namespace EhterDelta.Bots.Dontnet -{ - public class EtherDeltaConfiguration - { - public string AddressEtherDelta { get; set; } - public string Provider { get; set; } - public string SocketUrl { get; set; } - public string AbiFile { get; internal set; } - public string TokenFile { get; internal set; } - public string Token { get; internal set; } - public string User { get; internal set; } - - public string PrivateKey { get; internal set; } - - public int UnitDecimals { get; internal set; } - public int GasLimit { get; internal set; } - public uint GasPrice { get; internal set; } - } +{ + public class EtherDeltaConfiguration + { + public string AddressEtherDelta { get; set; } + public string Provider { get; set; } + public string SocketUrl { get; set; } + public string AbiFile { get; internal set; } + public string TokenFile { get; internal set; } + public string Token { get; internal set; } + public string User { get; internal set; } + + public string PrivateKey { get; internal set; } + + public int UnitDecimals { get; internal set; } + public int GasLimit { get; internal set; } + public uint GasPrice { get; internal set; } + } } \ No newline at end of file diff --git a/dotnet/ILogger.cs b/dotnet/ILogger.cs index 80f1f41..10984b8 100644 --- a/dotnet/ILogger.cs +++ b/dotnet/ILogger.cs @@ -1,7 +1,7 @@ namespace EhterDelta.Bots.Dontnet -{ - public interface ILogger - { - void Log(string message); - } +{ + public interface ILogger + { + void Log(string message); + } } \ No newline at end of file diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index aa6d9e1..d62c829 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -1,80 +1,72 @@ -using Nethereum.Web3; -using System.Threading.Tasks; -using Nethereum.Hex.HexTypes; -using Nethereum.Web3.Accounts; -using Nethereum.JsonRpc.Client; using System; -using System.Numerics; -using System.Linq; -using System.Threading; using System.Collections.Generic; -using Newtonsoft.Json.Linq; +using System.Threading.Tasks; namespace EhterDelta.Bots.Dontnet -{ - public class Maker : BaseBot - { - public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(config, logger) - { - var ordersPerSide = 1; - var expires = service.GetBlockNumber().Result + 10; - var buyOrdersToPlace = ordersPerSide - service.MyOrders.Buys.Count; - var sellOrdersToPlace = ordersPerSide - service.MyOrders.Sells.Count; - var buyVolumeToPlace = EtherDeltaETH; - var sellVolumeToPlace = EtherDeltaToken; - - if (service.Orders.Buys.Count <= 0 || service.Orders.Sells.Count <= 0) - { - throw new Exception("Market is not two-sided, cannot calculate mid-market"); - } - - var bestBuy = decimal.Parse(service.Orders.Buys[0].price); - var bestSell = service.Orders.Sells[0].Price; - - // Make sure we have a reliable mid market - if (Math.Abs((bestBuy - bestSell) / (bestBuy + bestSell) / 2.0) > 0.05) - { - throw new Exception("Market is too wide, will not place orders"); - } - - var midMarket = (bestBuy + bestSell) / 2.0; - - var orders = new List(); - - for (var i = 0; i < sellOrdersToPlace; i += 1) - { - var price = midMarket + ((i + 1) * midMarket * 0.05); - var amount = service.ToEth(sellVolumeToPlace / sellOrdersToPlace, service.Config.UnitDecimals); - Console.WriteLine($"Sell { amount.ToString("N3")} @ { price.ToString("N9")}"); - try - { - var order = service.CreateOrder(OrderType.Sell, expires, price, amount); - orders.Add(order); - } - catch (Exception ex) - { - Console.WriteLine(ex); - } - } - for (var i = 0; i < buyOrdersToPlace; i += 1) - { - var price = midMarket - ((i + 1) * midMarket * 0.05); - var amount = service.ToEth(buyVolumeToPlace / price / buyOrdersToPlace, service.Config.UnitDecimals); - Console.WriteLine($"Buy { amount.ToString("N3")} @ { price.toFixed(9)}"); - try - { - var order = service.CreateOrder(OrderType.Buy, expires, price, amount); - orders.Add(order); - } - catch (Exception ex) - { - Console.WriteLine(ex); - } - } - - Task.WhenAll(orders).Wait(); - - Console.WriteLine("Done"); +{ + public class Maker : BaseBot + { + public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(config, logger) + { + var ordersPerSide = 1; + var expires = Service.GetBlockNumber().Result + 10; + var buyOrdersToPlace = ordersPerSide - Service.MyOrders.Buys.Count; + var sellOrdersToPlace = ordersPerSide - Service.MyOrders.Sells.Count; + var buyVolumeToPlace = EtherDeltaETH; + var sellVolumeToPlace = EtherDeltaToken; + + if (Service.Orders.Buys.Count <= 0 || Service.Orders.Sells.Count <= 0) + { + throw new Exception("Market is not two-sided, cannot calculate mid-market"); + } + + var bestBuy = decimal.Parse(Service.Orders.Buys[0].price); + var bestSell = Service.Orders.Sells[0].Price; + + // Make sure we have a reliable mid market + if (Math.Abs((bestBuy - bestSell) / (bestBuy + bestSell) / 2.0) > 0.05) + { + throw new Exception("Market is too wide, will not place orders"); + } + + var midMarket = (bestBuy + bestSell) / 2.0; + + var orders = new List(); + + for (var i = 0; i < sellOrdersToPlace; i += 1) + { + var price = midMarket + ((i + 1) * midMarket * 0.05); + var amount = Service.ToEth(sellVolumeToPlace / sellOrdersToPlace, Service.Config.UnitDecimals); + Console.WriteLine($"Sell { amount.ToString("N3")} @ { price.ToString("N9")}"); + try + { + var order = Service.CreateOrder(OrderType.Sell, expires, price, amount); + orders.Add(order); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + for (var i = 0; i < buyOrdersToPlace; i += 1) + { + var price = midMarket - ((i + 1) * midMarket * 0.05); + var amount = Service.ToEth(buyVolumeToPlace / price / buyOrdersToPlace, Service.Config.UnitDecimals); + Console.WriteLine($"Buy { amount.ToString("N3")} @ { price.toFixed(9)}"); + try + { + var order = Service.CreateOrder(OrderType.Buy, expires, price, amount); + orders.Add(order); + } + catch (Exception ex) + { + Console.WriteLine(ex); + } + } + + Task.WhenAll(orders).Wait(); + + Console.WriteLine("Done"); + } } - } } \ No newline at end of file diff --git a/dotnet/Message.cs b/dotnet/Message.cs index faa0f6d..ab25dab 100644 --- a/dotnet/Message.cs +++ b/dotnet/Message.cs @@ -2,53 +2,53 @@ using Newtonsoft.Json.Linq; namespace EhterDelta.Bots.Dontnet -{ - internal class Message - { - internal Message() - { - Data = new { }; +{ + internal class Message + { + internal Message() + { + Data = new { }; + } + public string Event { get; set; } + + public dynamic Data { get; set; } + + public override string ToString() + { + var ret = $"42[\"{this.Event}\", {JsonConvert.SerializeObject(Data)}]"; + return ret; + } + + internal static Message ParseMessage(string messageString) + { + var message = new Message(); + + // message is Text/Json + if (messageString.StartsWith("42")) + { + messageString = messageString.Remove(0, 2); + var tmpData = JsonConvert.DeserializeObject(messageString); + + if (tmpData != null) + { + if (tmpData.GetType() == typeof(JArray)) + { + var array = (JArray)tmpData; + if (array.Count > 0 && array[0].GetType() == typeof(JValue)) + { + message.Event = array[0].ToString(); + } + + if (array.Count > 1) + { + message.Data = (object)array[1]; + } + } + } + + } + + return message; + } } - public string Event { get; set; } - - public dynamic Data { get; set; } - - public override string ToString() - { - var ret = $"42[\"{this.Event}\", {JsonConvert.SerializeObject(Data)}]"; - return ret; - } - - internal static Message ParseMessage(string messageString) - { - var message = new Message(); - - // message is Text/Json - if (messageString.StartsWith("42")) - { - messageString = messageString.Remove(0, 2); - var tmpData = JsonConvert.DeserializeObject(messageString); - - if (tmpData != null) - { - if (tmpData.GetType() == typeof(JArray)) - { - var array = (JArray)tmpData; - if (array.Count > 0 && array[0].GetType() == typeof(JValue)) - { - message.Event = array[0].ToString(); - } - - if (array.Count > 1) - { - message.Data = (object)array[1]; - } - } - } - - } - - return message; - } - } } \ No newline at end of file diff --git a/dotnet/OrderType.cs b/dotnet/OrderType.cs index 5db6127..a39c766 100644 --- a/dotnet/OrderType.cs +++ b/dotnet/OrderType.cs @@ -1,8 +1,8 @@ namespace EhterDelta.Bots.Dontnet -{ - internal enum OrderType - { - Buy, - Sell - } +{ + internal enum OrderType + { + Buy, + Sell + } } \ No newline at end of file diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs index 349ff1b..7a83f26 100644 --- a/dotnet/Orders.cs +++ b/dotnet/Orders.cs @@ -1,36 +1,35 @@ +using Nethereum.Hex.HexTypes; using System.Collections.Generic; using System.Numerics; -using Nethereum.Hex.HexTypes; -using Nethereum.Util; namespace EhterDelta.Bots.Dontnet -{ - public class Orders - { - public List Sells { get; set; } - public List Buys { get; set; } - } - - public class Order - { - public string Id { get; set; } - public string Amount { get; set; } - public double Price { get; set; } - public string TokenGet { get; set; } - public HexBigInteger AmountGet { get; set; } - public string TokenGive { get; set; } - public HexBigInteger AmountGive { get; set; } - public BigInteger Expires { get; set; } - public BigInteger Nonce { get; set; } - public string User { get; set; } - public string Updated { get; set; } - public string AvailableVolume { get; set; } - public decimal EthAvailableVolume { get; set; } - public string AvailableVolumeBase { get; set; } - public double EthAvailableVolumeBase { get; set; } - public string AmountFilled { get; set; } - public int V { get; internal set; } - public string R { get; internal set; } - public string S { get; internal set; } - } +{ + public class Orders + { + public List Sells { get; set; } + public List Buys { get; set; } + } + + public class Order + { + public string Id { get; set; } + public string Amount { get; set; } + public double Price { get; set; } + public string TokenGet { get; set; } + public HexBigInteger AmountGet { get; set; } + public string TokenGive { get; set; } + public HexBigInteger AmountGive { get; set; } + public BigInteger Expires { get; set; } + public BigInteger Nonce { get; set; } + public string User { get; set; } + public string Updated { get; set; } + public string AvailableVolume { get; set; } + public decimal EthAvailableVolume { get; set; } + public string AvailableVolumeBase { get; set; } + public double EthAvailableVolumeBase { get; set; } + public string AmountFilled { get; set; } + public int V { get; internal set; } + public string R { get; internal set; } + public string S { get; internal set; } + } } \ No newline at end of file diff --git a/dotnet/Program.cs b/dotnet/Program.cs index bffd148..290fb92 100644 --- a/dotnet/Program.cs +++ b/dotnet/Program.cs @@ -1,57 +1,56 @@ using System; -using System.Linq; using System.Configuration; namespace EhterDelta.Bots.Dontnet -{ - class Program - { - static void Main(string[] args) - { - - if (args.Length < 1 || args[0] != "taker" && args[0] != "maker") - { - Console.WriteLine("Please run with 'taker' or 'maker' argument!"); - return; - } - - var config = new EtherDeltaConfiguration - { - SocketUrl = ConfigurationManager.AppSettings["SocketUrl"], - Provider = ConfigurationManager.AppSettings["Provider"], - AddressEtherDelta = ConfigurationManager.AppSettings["AddressEtherDelta"], - AbiFile = ConfigurationManager.AppSettings["AbiFile"], - TokenFile = ConfigurationManager.AppSettings["TokenFile"], - Token = ConfigurationManager.AppSettings["Token"], - User = ConfigurationManager.AppSettings["User"], - PrivateKey = ConfigurationManager.AppSettings["PrivateKey"], - UnitDecimals = int.Parse(ConfigurationManager.AppSettings["UnitDecimals"]), - }; - - ILogger logger = null; - if (args.Length == 2 && args[1] == "-v") - { - logger = new ConsoleLogger(); - } - - if (args[0] == "taker") - { - new Taker(config, logger); - } - else - { - new Maker(config, logger); - } - } - - private class ConsoleLogger : ILogger - { - public void Log(string message) - { - Console.WriteLine($"{DateTimeOffset.Now.DateTime.ToUniversalTime()} : {message}"); - } +{ + class Program + { + static void Main(string[] args) + { + + if (args.Length < 1 || args[0] != "taker" && args[0] != "maker") + { + Console.WriteLine("Please run with 'taker' or 'maker' argument!"); + return; + } + + var config = new EtherDeltaConfiguration + { + SocketUrl = ConfigurationManager.AppSettings["SocketUrl"], + Provider = ConfigurationManager.AppSettings["Provider"], + AddressEtherDelta = ConfigurationManager.AppSettings["AddressEtherDelta"], + AbiFile = ConfigurationManager.AppSettings["AbiFile"], + TokenFile = ConfigurationManager.AppSettings["TokenFile"], + Token = ConfigurationManager.AppSettings["Token"], + User = ConfigurationManager.AppSettings["User"], + PrivateKey = ConfigurationManager.AppSettings["PrivateKey"], + UnitDecimals = int.Parse(ConfigurationManager.AppSettings["UnitDecimals"]), + }; + + ILogger logger = null; + if (args.Length == 2 && args[1] == "-v") + { + logger = new ConsoleLogger(); + } + + if (args[0] == "taker") + { + new Taker(config, logger); + } + else + { + new Maker(config, logger); + } + } + + private class ConsoleLogger : ILogger + { + public void Log(string message) + { + Console.WriteLine($"{DateTimeOffset.Now.DateTime.ToUniversalTime()} : {message}"); + } + } } - } } \ No newline at end of file diff --git a/dotnet/Service.cs b/dotnet/Service.cs index 0aef305..28ce266 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -1,336 +1,354 @@ +using Nethereum.Contracts; +using Nethereum.Util; +using Nethereum.Web3; +using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; -using System.Text; using System.Linq; using System.Numerics; -using System.Threading; using System.Threading.Tasks; -using Nethereum.Contracts; -using Nethereum.JsonRpc.Client; -using Nethereum.Web3; -using Newtonsoft.Json.Linq; using WebSocket4Net; -using Nethereum.Hex.HexTypes; -using Nethereum.RPC.Eth.Transactions; -using Nethereum.RPC.Eth.DTOs; -using Nethereum.Util; namespace EhterDelta.Bots.Dontnet -{ - public class Service - { - private const string ZeroToken = "0x0000000000000000000000000000000000000000"; - private WebSocket socket; - const int SocketMessageTimeout = 30000; - private void Log(string message) - { - if (logger != null) - { - logger.Log(message); - } - } - - private void InitSocket() - { - socket = new WebSocket(Config.SocketUrl); - socket.Opened += SocketOpened; - socket.Error += SocketError; - socket.Closed += SocketClosed; - socket.MessageReceived += SocketMessageReceived; - socket.OpenAsync().Wait(); - } - - private ILogger logger; - - public Service(EtherDeltaConfiguration config, ILogger configLogger) - { - logger = configLogger; - Log("Starting"); - - Orders = new Orders - { - Sells = new List(), - Buys = new List() - }; - - MyOrders = new Orders - { - Sells = new List(), - Buys = new List() - }; - - Config = config; - Web3 = new Web3(config.Provider); - var addressEtherDelta = Web3.ToChecksumAddress(config.AddressEtherDelta); - - // TODO: check file exists - var abi = File.ReadAllText(config.AbiFile); - EtherDeltaContract = Web3.Eth.GetContract(abi, addressEtherDelta); - - var tokenAbi = File.ReadAllText(config.TokenFile); - EthContract = Web3.Eth.GetContract(tokenAbi, Config.Token); - - InitSocket(); - } - - internal async Task TakeOrder(Order order, double fraction) - { - Console.WriteLine(order.AmountGet); - var amount = 1 * fraction; - - // var maxGas = 250000; - // var gasPriceWei = 1000000000; // 1 Gwei - - var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); - var fn = EtherDeltaContract.GetFunction("testTrade"); - - var resp = await fn.CallAsync( - order.TokenGet, - order.AmountGet.Value, - order.TokenGive, - order.AmountGive.Value, - order.Expires, - txCount.Value, - order.User, - order.V, - order.R, - order.S, - amount, - Config.User - ); - - - Console.WriteLine(resp); - - - - - var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, 10, - txCount.Value); - - } - - internal Order GetBestAvailableSell() - { - return Orders.Sells.FirstOrDefault(); - } - - internal async Task GetBlockNumber() - { - return await Web3.Eth.Blocks.GetBlockNumber.SendRequestAsync(); - } - - internal async Task CreateOrder(OrderType orderType, BigInteger expires, BigInteger price, BigInteger amount) - { - await Task.Delay(1); - - var amountBigNum = amount; - var amountBaseBigNum = amount * price; - var contractAddr = Config.AddressEtherDelta; - var tokenGet = orderType == OrderType.Buy ? Config.Token : ZeroToken; - var tokenGive = orderType == OrderType.Sell ? Config.Token : ZeroToken; - var amountGet = orderType == OrderType.Buy ? toWei(amountBigNum, Config.UnitDecimals) : toWei(amountBaseBigNum, Config.UnitDecimals); - var amountGive = orderType == OrderType.Sell ? toWei(amountBigNum, Config.UnitDecimals) : toWei(amountBaseBigNum, Config.UnitDecimals); - var orderNonce = new Random().Next(); - - - //new Nethereum.Signer.MessageSigner().ToString +{ + public class Service + { + private const string ZeroToken = "0x0000000000000000000000000000000000000000"; + private WebSocket socket; + const int SocketMessageTimeout = 30000; + private void Log(string message) + { + if (logger != null) + { + logger.Log(message); + } + } + + private void InitSocket() + { + socket = new WebSocket(Config.SocketUrl); + socket.Opened += SocketOpened; + socket.Error += SocketError; + socket.Closed += SocketClosed; + socket.MessageReceived += SocketMessageReceived; + socket.OpenAsync().Wait(); + } + + private ILogger logger; + + public Service(EtherDeltaConfiguration config, ILogger configLogger) + { + logger = configLogger; + Log("Starting"); + + Orders = new Orders + { + Sells = new List(), + Buys = new List() + }; + + MyOrders = new Orders + { + Sells = new List(), + Buys = new List() + }; + + Config = config; + Web3 = new Web3(config.Provider); + var addressEtherDelta = Web3.ToChecksumAddress(config.AddressEtherDelta); + + // TODO: check file exists + var abi = File.ReadAllText(config.AbiFile); + EtherDeltaContract = Web3.Eth.GetContract(abi, addressEtherDelta); + + var tokenAbi = File.ReadAllText(config.TokenFile); + EthContract = Web3.Eth.GetContract(tokenAbi, Config.Token); + + InitSocket(); + } + + internal async Task TakeOrder(Order order, double fraction) + { + Console.WriteLine(order.AmountGet); + var amount = 1 * fraction; + + // var maxGas = 250000; + // var gasPriceWei = 1000000000; // 1 Gwei + + var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); + var fn = EtherDeltaContract.GetFunction("testTrade"); + + var resp = await fn.CallAsync( + order.TokenGet, + order.AmountGet.Value, + order.TokenGive, + order.AmountGive.Value, + order.Expires, + txCount.Value, + order.User, + order.V, + order.R, + order.S, + amount, + Config.User + ); + + + var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, 10, + txCount.Value); + + /** + + + var privateKey = "0xb5b1870957d373ef0eeffecc6e4812c0fd08f554b37b233526acc331bf1544f7"; + var senderAddress = "0x12890d2cce102216644c59daE5baed380d84830c"; + var receiveAddress = "0x13f022d72158410433cbd66f5dd8bf6d2d129924"; + var web3 = new Web3Geth(); + + var txCount = await web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(senderAddress); + var encoded = Web3.OfflineTransactionSigner.SignTransaction(privateKey, receiveAddress, 10, + txCount.Value); + + Assert.True(Web3.OfflineTransactionSigner.VerifyTransaction(encoded)); + + Debug.WriteLine(Web3.OfflineTransactionSigner.GetSenderAddress(encoded)); + Assert.Equal(senderAddress.EnsureHexPrefix().ToLower(), Web3.OfflineTransactionSigner.GetSenderAddress(encoded).EnsureHexPrefix().ToLower()); + + var txId = await web3.Eth.Transactions.SendRawTransaction.SendRequestAsync("0x" + encoded); + var receipt = await web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); + while (receipt == null) + { + Thread.Sleep(1000); + receipt = await web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); + } + + Assert.Equal(txId, receipt.TransactionHash); + return true; + */ + + } + + internal Order GetBestAvailableSell() + { + return Orders.Sells.FirstOrDefault(); + } + + internal async Task GetBlockNumber() + { + return await Web3.Eth.Blocks.GetBlockNumber.SendRequestAsync(); + } + + internal async Task CreateOrder(OrderType orderType, BigInteger expires, BigInteger price, BigInteger amount) + { + await Task.Delay(1); + + var amountBigNum = amount; + var amountBaseBigNum = amount * price; + var contractAddr = Config.AddressEtherDelta; + var tokenGet = orderType == OrderType.Buy ? Config.Token : ZeroToken; + var tokenGive = orderType == OrderType.Sell ? Config.Token : ZeroToken; + var amountGet = orderType == OrderType.Buy ? toWei(amountBigNum, Config.UnitDecimals) : toWei(amountBaseBigNum, Config.UnitDecimals); + var amountGive = orderType == OrderType.Sell ? toWei(amountBigNum, Config.UnitDecimals) : toWei(amountBaseBigNum, Config.UnitDecimals); + var orderNonce = new Random().Next(); + + + //new Nethereum.Signer.MessageSigner().ToString + } + + internal BigInteger ToEth(dynamic dynamic, object decimals) + { + throw new NotImplementedException(); + } + + private string toWei(BigInteger amountBigNum, int unitDecimals) + { + throw new NotImplementedException(); + } + + internal void Close() + { + Log("Closing ..."); + if (socket != null && socket.State == WebSocketState.Open) + { + socket.Close(); + } + } + + private void SocketMessageReceived(object sender, MessageReceivedEventArgs e) + { + Message message = Message.ParseMessage(e.Message); + switch (message.Event) + { + case "market": + UpdateOrders(message.Data.orders); + UpdateTrades(message.Data.trades); + Market = message.Data; + break; + default: + break; + } + } + + private void SocketClosed(object sender, EventArgs e) + { + Log("SOCKET CLOSED"); + Log(e.GetType().ToString()); + + var ea = e as ClosedEventArgs; + if (ea != null) + { + Log(ea.Code.ToString()); + if (ea.Code == 1005) // no reason given + { + Log("Reconnecting..."); + InitSocket(); + } + } + } + + internal async Task GetBalance(string token, string user) + { + var unitConversion = new UnitConversion(); + BigInteger balance = 0; + user = Web3.ToChecksumAddress(user); + + try + { + if (token == "ETH") + { + balance = await Web3.Eth.GetBalance.SendRequestAsync(user); + Log("ETH - GET BALANCE"); + } + else + { + token = Web3.ToChecksumAddress(token); + var tokenFunction = EthContract.GetFunction("balanceOf"); + balance = await tokenFunction.CallAsync(user); + Log("TOKEN - GET BALANCE"); + } + } + catch (Exception ex) + { + Log(ex.Message); + } + + return unitConversion.FromWei(balance, Config.UnitDecimals); + } + + internal async Task GetEtherDeltaBalance(string token, string user) + { + var unitConversion = new UnitConversion(); + BigInteger balance = 0; + + try + { + if (token == "ETH") + { + token = ZeroToken; + } + + var tokenFunction = EtherDeltaContract.GetFunction("balanceOf"); + balance = await tokenFunction.CallAsync(token, user); + Log("ETHER DELTA - GET BALANCE"); + } + catch (Exception ex) + { + Log(ex.Message); + } + + return unitConversion.FromWei(balance, Config.UnitDecimals); + } + + private void SocketError(object sender, SuperSocket.ClientEngine.ErrorEventArgs e) + { + Log("SOCKET ERROR: "); + Log(e.Exception.Message); + } + + private void SocketOpened(object sender, EventArgs e) + { + Log("SOCKET Connected"); + } + + public async Task WaitForMarket() + { + Market = null; + socket.Send(new Message + { + Event = "getMarket", + Data = new + { + token = Config.Token, + user = Config.User + } + }.ToString()); + + var gotMarket = Task.Run(() => + { + while (Market == null) { Task.Delay(1000); } + }); + + var completed = await Task.WhenAny(gotMarket, Task.Delay(SocketMessageTimeout)); + + if (completed != gotMarket) + { + throw new TimeoutException("Get Market timeout"); + } + } + + private void UpdateOrders(dynamic orders) + { + //var minOrderSize = 0.001; + + if (orders == null) + { + return; + } + + if (orders.GetType() == typeof(JObject)) + { + var sells = ((JArray)orders.sells) + .Where(_ => _["tokenGive"] != null && _["tokenGive"].ToString() == Config.Token) + .Select(_ => _.ToObject()) + .ToList(); + + if (sells != null && sells.Count() > 0) + { + Orders.Sells = sells; + } + + var buys = ((JArray)orders.buys).Where(_ => _["tokenGet"] != null && _["tokenGet"].ToString() == Config.Token).ToList(); + if (buys != null && buys.Count > 0) + { + Orders.Buys = buys.ToList(); + } + } + + // TODO: update MyOrders + } + + private void UpdateTrades(dynamic trades) + { + if (trades == null) + { + return; + } + + if (trades.GetType() == typeof(JArray)) + { + Trades = trades; + } + } + + public EtherDeltaConfiguration Config { get; } + public Web3 Web3 { get; } + public Contract EtherDeltaContract { get; } + public Contract EthContract { get; } + public Orders Orders { get; set; } + public Orders MyOrders { get; set; } + public dynamic Trades { get; set; } + public List MyTrades { get; set; } + public dynamic Market { get; private set; } } - - internal BigInteger ToEth(dynamic dynamic, object decimals) - { - throw new NotImplementedException(); - } - - private string toWei(BigInteger amountBigNum, int unitDecimals) - { - throw new NotImplementedException(); - } - - internal void Close() - { - Log("Closing ..."); - if (socket != null && socket.State == WebSocketState.Open) - { - socket.Close(); - } - } - - private void SocketMessageReceived(object sender, MessageReceivedEventArgs e) - { - Message message = Message.ParseMessage(e.Message); - switch (message.Event) - { - case "market": - UpdateOrders(message.Data.orders); - UpdateTrades(message.Data.trades); - Market = message.Data; - break; - default: - break; - } - } - - private void SocketClosed(object sender, EventArgs e) - { - Log("SOCKET CLOSED"); - Log(e.GetType().ToString()); - - var ea = e as ClosedEventArgs; - if (ea != null) - { - Log(ea.Code.ToString()); - if (ea.Code == 1005) // no reason given - { - Log("Reconnecting..."); - InitSocket(); - } - } - } - - internal async Task GetBalance(string token, string user) - { - var unitConversion = new UnitConversion(); - BigInteger balance = 0; - user = Web3.ToChecksumAddress(user); - - try - { - if (token == "ETH") - { - balance = await Web3.Eth.GetBalance.SendRequestAsync(user); - Log("ETH - GET BALANCE"); - } - else - { - token = Web3.ToChecksumAddress(token); - var tokenFunction = EthContract.GetFunction("balanceOf"); - balance = await tokenFunction.CallAsync(user); - Log("TOKEN - GET BALANCE"); - } - } - catch (Exception ex) - { - Log(ex.Message); - } - - return unitConversion.FromWei(balance, Config.UnitDecimals); - } - - internal async Task GetEtherDeltaBalance(string token, string user) - { - var unitConversion = new UnitConversion(); - BigInteger balance = 0; - - try - { - if (token == "ETH") - { - token = ZeroToken; - } - - var tokenFunction = EtherDeltaContract.GetFunction("balanceOf"); - balance = await tokenFunction.CallAsync(token, user); - Log("ETHER DELTA - GET BALANCE"); - } - catch (Exception ex) - { - Log(ex.Message); - } - - return unitConversion.FromWei(balance, Config.UnitDecimals); - } - - private void SocketError(object sender, SuperSocket.ClientEngine.ErrorEventArgs e) - { - Log("SOCKET ERROR: "); - Log(e.Exception.Message); - } - - private void SocketOpened(object sender, EventArgs e) - { - Log("SOCKET Connected"); - } - - public async Task WaitForMarket() - { - Market = null; - socket.Send(new Message - { - Event = "getMarket", - Data = new - { - token = Config.Token, - user = Config.User - } - }.ToString()); - - var gotMarket = Task.Run(() => - { - while (Market == null) { Task.Delay(1000); } - }); - - var completed = await Task.WhenAny(gotMarket, Task.Delay(SocketMessageTimeout)); - - if (completed != gotMarket) - { - throw new TimeoutException("Get Market timeout"); - } - } - - private void UpdateOrders(dynamic orders) - { - //var minOrderSize = 0.001; - - if (orders == null) - { - return; - } - - if (orders.GetType() == typeof(JObject)) - { - var sells = ((JArray)orders.sells) - .Where(_ => _["tokenGive"] != null && _["tokenGive"].ToString() == Config.Token) - .Select(_ => _.ToObject()) - .ToList(); - - if (sells != null && sells.Count() > 0) - { - Orders.Sells = sells; - } - - var buys = ((JArray)orders.buys).Where(_ => _["tokenGet"] != null && _["tokenGet"].ToString() == Config.Token).ToList(); - if (buys != null && buys.Count > 0) - { - Orders.Buys = buys.ToList(); - } - } - - // TODO: update MyOrders - } - - private void UpdateTrades(dynamic trades) - { - if (trades == null) - { - return; - } - - if (trades.GetType() == typeof(JArray)) - { - Trades = trades; - } - } - - public EtherDeltaConfiguration Config { get; } - public Web3 Web3 { get; } - public Contract EtherDeltaContract { get; } - public Contract EthContract { get; } - public Orders Orders { get; set; } - public Orders MyOrders { get; set; } - public dynamic Trades { get; set; } - public List MyTrades { get; set; } - public dynamic Market { get; private set; } - } } \ No newline at end of file diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs index 01612da..a4dbffc 100644 --- a/dotnet/Taker.cs +++ b/dotnet/Taker.cs @@ -1,38 +1,27 @@ -using Nethereum.Web3; -using System.Threading.Tasks; -using Nethereum.Hex.HexTypes; -using Nethereum.Web3.Accounts; -using Nethereum.JsonRpc.Client; using System; -using System.Numerics; -using System.Linq; -using System.Threading; -using System.Collections.Generic; -using Newtonsoft.Json.Linq; namespace EhterDelta.Bots.Dontnet -{ - public class Taker : BaseBot - { - public Taker(EtherDeltaConfiguration config, ILogger logger = null) : base(config, logger) - { - var order = service.GetBestAvailableSell(); - - if (order != null) - { - Console.WriteLine($"Best available: Sell {order.EthAvailableVolume.ToString("N3")} @ {order.Price.ToString("N9")}"); - var desiredAmountBase = 0.001; - - var fraction = Math.Min(desiredAmountBase / order.EthAvailableVolumeBase, 1); - service.TakeOrder(order, fraction).Wait(); - } - else - { - Console.WriteLine("No Available order"); - } - - - Console.WriteLine(); +{ + public class Taker : BaseBot + { + public Taker(EtherDeltaConfiguration config, ILogger logger = null) : base(config, logger) + { + var order = Service.GetBestAvailableSell(); + + if (order != null) + { + Console.WriteLine($"Best available: Sell {order.EthAvailableVolume.ToString("N3")} @ {order.Price.ToString("N9")}"); + var desiredAmountBase = 0.001; + + var fraction = Math.Min(desiredAmountBase / order.EthAvailableVolumeBase, 1); + Service.TakeOrder(order, fraction).Wait(); + } + else + { + Console.WriteLine("No Available order"); + } + + Console.WriteLine(); + } } - } } \ No newline at end of file From 98d9b2d37e4003be59fc9c1161b371b49f5a5749 Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 7 Dec 2017 00:00:46 +0100 Subject: [PATCH 06/15] Take order method on taker bot --- dotnet/Orders.cs | 31 ++++++++-- dotnet/Service.cs | 148 +++++++++++++++++++++++----------------------- dotnet/Taker.cs | 18 ++++-- 3 files changed, 112 insertions(+), 85 deletions(-) diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs index 7a83f26..338fa0c 100644 --- a/dotnet/Orders.cs +++ b/dotnet/Orders.cs @@ -1,8 +1,10 @@ -using Nethereum.Hex.HexTypes; -using System.Collections.Generic; -using System.Numerics; - -namespace EhterDelta.Bots.Dontnet +using Nethereum.Hex.HexTypes; +using System.Collections.Generic; +using System.Numerics; +using Newtonsoft.Json.Linq; +using System; + +namespace EhterDelta.Bots.Dontnet { public class Orders { @@ -31,5 +33,22 @@ public class Order public int V { get; internal set; } public string R { get; internal set; } public string S { get; internal set; } - } + + internal static Order FromJson(JToken jtoken) + { + var order = jtoken.ToObject(); + try + { + order.V = jtoken.Value("v"); + order.R = jtoken.Value("r"); + order.S = jtoken.Value("s"); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + + return order; + } + } } \ No newline at end of file diff --git a/dotnet/Service.cs b/dotnet/Service.cs index 28ce266..f0f75e6 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -1,22 +1,26 @@ -using Nethereum.Contracts; -using Nethereum.Util; -using Nethereum.Web3; -using Newtonsoft.Json.Linq; -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Numerics; -using System.Threading.Tasks; -using WebSocket4Net; - -namespace EhterDelta.Bots.Dontnet +using Nethereum.Contracts; +using Nethereum.Util; +using Nethereum.Web3; +using Newtonsoft.Json.Linq; +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Numerics; +using System.Threading.Tasks; +using WebSocket4Net; +using System.Text; +using Nethereum.ABI; +using Nethereum.Hex.HexConvertors.Extensions; +using Nethereum.RPC.Eth.DTOs; + +namespace EhterDelta.Bots.Dontnet { public class Service { private const string ZeroToken = "0x0000000000000000000000000000000000000000"; private WebSocket socket; - const int SocketMessageTimeout = 30000; + const int SocketMessageTimeout = 20000; private void Log(string message) { if (logger != null) @@ -68,65 +72,58 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) InitSocket(); } - internal async Task TakeOrder(Order order, double fraction) + internal async Task TakeOrder(Order order, double fraction) { - Console.WriteLine(order.AmountGet); - var amount = 1 * fraction; - - // var maxGas = 250000; - // var gasPriceWei = 1000000000; // 1 Gwei + var amount = order.AmountGet * new BigInteger(fraction); var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); - var fn = EtherDeltaContract.GetFunction("testTrade"); - - var resp = await fn.CallAsync( - order.TokenGet, - order.AmountGet.Value, - order.TokenGive, - order.AmountGive.Value, - order.Expires, - txCount.Value, - order.User, - order.V, - order.R, - order.S, - amount, - Config.User + var fnTest = EtherDeltaContract.GetFunction("testTrade"); + + var willPass = await fnTest.CallAsync( + order.TokenGet, + order.AmountGet.Value, + order.TokenGive, + order.AmountGive.Value, + order.Expires, + order.Nonce, + order.User, + order.V, + order.R.HexToByteArray(), + order.S.HexToByteArray(), + amount, + Config.User ); - var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, 10, - txCount.Value); - - /** - - - var privateKey = "0xb5b1870957d373ef0eeffecc6e4812c0fd08f554b37b233526acc331bf1544f7"; - var senderAddress = "0x12890d2cce102216644c59daE5baed380d84830c"; - var receiveAddress = "0x13f022d72158410433cbd66f5dd8bf6d2d129924"; - var web3 = new Web3Geth(); - - var txCount = await web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(senderAddress); - var encoded = Web3.OfflineTransactionSigner.SignTransaction(privateKey, receiveAddress, 10, - txCount.Value); - - Assert.True(Web3.OfflineTransactionSigner.VerifyTransaction(encoded)); - - Debug.WriteLine(Web3.OfflineTransactionSigner.GetSenderAddress(encoded)); - Assert.Equal(senderAddress.EnsureHexPrefix().ToLower(), Web3.OfflineTransactionSigner.GetSenderAddress(encoded).EnsureHexPrefix().ToLower()); - - var txId = await web3.Eth.Transactions.SendRawTransaction.SendRequestAsync("0x" + encoded); - var receipt = await web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); - while (receipt == null) - { - Thread.Sleep(1000); - receipt = await web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); - } - - Assert.Equal(txId, receipt.TransactionHash); - return true; - */ + if (!willPass) + { + Log("Order will fail"); + throw new Exception("Order will fail"); + } + + var fnTrade = EtherDeltaContract.GetFunction("trade"); + var data = fnTrade.GetData( + order.TokenGet, + order.AmountGet.Value, + order.TokenGive, + order.AmountGive.Value, + order.Expires, + order.Nonce, + order.User, + order.V, + order.R.HexToByteArray(), + order.S.HexToByteArray(), + amount + ); + + var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, amount, + txCount, Config.GasPrice, Config.GasLimit, data); + var txId = await Web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(encoded.EnsureHexPrefix()); + + var receipt = await Web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); + + return receipt; } internal Order GetBestAvailableSell() @@ -152,8 +149,6 @@ internal async Task CreateOrder(OrderType orderType, BigInteger expires, BigInte var amountGive = orderType == OrderType.Sell ? toWei(amountBigNum, Config.UnitDecimals) : toWei(amountBaseBigNum, Config.UnitDecimals); var orderNonce = new Random().Next(); - - //new Nethereum.Signer.MessageSigner().ToString } internal BigInteger ToEth(dynamic dynamic, object decimals) @@ -273,6 +268,7 @@ private void SocketOpened(object sender, EventArgs e) public async Task WaitForMarket() { + Log("Wait for Market"); Market = null; socket.Send(new Message { @@ -286,12 +282,16 @@ public async Task WaitForMarket() var gotMarket = Task.Run(() => { - while (Market == null) { Task.Delay(1000); } + while (Market == null) + { + Task.Delay(1000).Wait(); + } }); var completed = await Task.WhenAny(gotMarket, Task.Delay(SocketMessageTimeout)); + Log("Market Completed ..."); - if (completed != gotMarket) + if (!gotMarket.IsCompletedSuccessfully) { throw new TimeoutException("Get Market timeout"); } @@ -309,8 +309,8 @@ private void UpdateOrders(dynamic orders) if (orders.GetType() == typeof(JObject)) { var sells = ((JArray)orders.sells) - .Where(_ => _["tokenGive"] != null && _["tokenGive"].ToString() == Config.Token) - .Select(_ => _.ToObject()) + .Where(jtoken => jtoken["tokenGive"] != null && jtoken["tokenGive"].ToString() == Config.Token) + .Select(jtoken => Order.FromJson(jtoken)) .ToList(); if (sells != null && sells.Count() > 0) @@ -318,7 +318,7 @@ private void UpdateOrders(dynamic orders) Orders.Sells = sells; } - var buys = ((JArray)orders.buys).Where(_ => _["tokenGet"] != null && _["tokenGet"].ToString() == Config.Token).ToList(); + var buys = ((JArray)orders.buys).Where(jtoken => jtoken["tokenGet"] != null && jtoken["tokenGet"].ToString() == Config.Token).ToList(); if (buys != null && buys.Count > 0) { Orders.Buys = buys.ToList(); @@ -350,5 +350,5 @@ private void UpdateTrades(dynamic trades) public dynamic Trades { get; set; } public List MyTrades { get; set; } public dynamic Market { get; private set; } - } + } } \ No newline at end of file diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs index a4dbffc..b1ecad5 100644 --- a/dotnet/Taker.cs +++ b/dotnet/Taker.cs @@ -1,6 +1,6 @@ -using System; - -namespace EhterDelta.Bots.Dontnet +using System; + +namespace EhterDelta.Bots.Dontnet { public class Taker : BaseBot { @@ -14,14 +14,22 @@ public Taker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi var desiredAmountBase = 0.001; var fraction = Math.Min(desiredAmountBase / order.EthAvailableVolumeBase, 1); - Service.TakeOrder(order, fraction).Wait(); + try + { + Service.TakeOrder(order, fraction).Wait(); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } } else { Console.WriteLine("No Available order"); + Console.WriteLine(Service.Orders); } Console.WriteLine(); } - } + } } \ No newline at end of file From 41ac638e4412e9fcb7ab8beb2fa9d5a662f42238 Mon Sep 17 00:00:00 2001 From: stojce Date: Thu, 7 Dec 2017 18:39:51 +0100 Subject: [PATCH 07/15] consolidate data types --- dotnet/BaseBot.cs | 30 ++++++-------- dotnet/Maker.cs | 25 ++++++----- dotnet/Orders.cs | 6 +-- dotnet/Service.cs | 103 ++++++++++++++++++++++++++++------------------ dotnet/Taker.cs | 2 +- 5 files changed, 91 insertions(+), 75 deletions(-) diff --git a/dotnet/BaseBot.cs b/dotnet/BaseBot.cs index 01f47d5..aec2de1 100644 --- a/dotnet/BaseBot.cs +++ b/dotnet/BaseBot.cs @@ -26,7 +26,7 @@ public BaseBot(EtherDeltaConfiguration config, ILogger logger = null) GetBalanceAsync("ETH", config.User), GetBalanceAsync(config.Token, config.User), GetEtherDeltaBalance("ETH", config.User), - GetEtherDeltaBalance(config.Token, config.User) + GetEtherDeltaBalance(config.Token, config.User) }; Task.WaitAll(tasks); @@ -99,8 +99,8 @@ private void PrintTrades() trades = ((JArray)trades).Take(numTrades).ToArray(); foreach (var trade in trades) { - var tradePrice = (double)((JValue)trade.price); - var tradeAmount = (double)((JValue)trade.amount); + var tradePrice = (decimal)((JValue)trade.price); + var tradeAmount = (decimal)((JValue)trade.amount); var tradeDate = (DateTime)((JValue)trade.date); Console.ForegroundColor = trade.side == "sell" ? ConsoleColor.Red : ConsoleColor.Green; @@ -119,7 +119,7 @@ private void PrintOrders() int ordersPerSide = 10; List sells = Service.Orders != null ? Service.Orders.Sells : null; - List buys = Service.Orders != null ? Service.Orders.Buys : null; + List buys = Service.Orders != null ? Service.Orders.Buys : null; if (sells == null || buys == null) { @@ -131,16 +131,16 @@ private void PrintOrders() buys = buys.Take(ordersPerSide).ToList(); Console.ForegroundColor = ConsoleColor.Red; - foreach (var item in sells) + foreach (var order in sells) { - Console.WriteLine(FormatOrder(item)); + Console.WriteLine(FormatOrder(order)); } Console.ResetColor(); if (buys.Count > 0 && sells.Count > 0) { - var salesPrice = (double)(sells.Last().Price); - var buysPrice = (double)(buys[0]["price"]); + var salesPrice = sells.Last().Price; + var buysPrice = buys.Last().Price; Console.WriteLine($"---- Spread ({(salesPrice - buysPrice).ToString("N9")}) ----"); } else @@ -152,9 +152,9 @@ private void PrintOrders() if (buys != null) { - foreach (var item in buys) + foreach (var order in buys) { - Console.WriteLine(FormatItem(item)); + Console.WriteLine(FormatOrder(order)); } } @@ -171,16 +171,10 @@ private void PrintWallet() Console.WriteLine($"Wallet token balance: {WalletToken}"); Console.WriteLine($"EtherDelta token balance: {EtherDeltaToken}"); } - private string FormatItem(dynamic item) - { - var price = (double)item.price; - item.ethAvailableVolume = (double)item.ethAvailableVolume; - return $"{price.ToString("N9")} {item.ethAvailableVolume.ToString("N3"),20}"; - } - private string FormatOrder(Order item) + private string FormatOrder(Order order) { - return $"{item.Price.ToString("N9")} {item.EthAvailableVolume.ToString("N3"),20}"; + return $"{order.Price.ToString("N9")} {order.EthAvailableVolume.ToString("N3"),20}"; } private async Task GetMarket() diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index d62c829..0e0e7cd 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Threading.Tasks; - -namespace EhterDelta.Bots.Dontnet +using System; +using System.Collections.Generic; +using System.Threading.Tasks; + +namespace EhterDelta.Bots.Dontnet { public class Maker : BaseBot { @@ -20,22 +20,21 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi throw new Exception("Market is not two-sided, cannot calculate mid-market"); } - var bestBuy = decimal.Parse(Service.Orders.Buys[0].price); + var bestBuy = Service.Orders.Buys[0].Price; var bestSell = Service.Orders.Sells[0].Price; // Make sure we have a reliable mid market - if (Math.Abs((bestBuy - bestSell) / (bestBuy + bestSell) / 2.0) > 0.05) + if (Math.Abs((bestBuy - bestSell) / (bestBuy + bestSell) / 2) > 0.05m) { throw new Exception("Market is too wide, will not place orders"); } - var midMarket = (bestBuy + bestSell) / 2.0; - + var midMarket = (bestBuy + bestSell) / 2; var orders = new List(); for (var i = 0; i < sellOrdersToPlace; i += 1) { - var price = midMarket + ((i + 1) * midMarket * 0.05); + var price = midMarket + ((i + 1) * midMarket * 0.05m); var amount = Service.ToEth(sellVolumeToPlace / sellOrdersToPlace, Service.Config.UnitDecimals); Console.WriteLine($"Sell { amount.ToString("N3")} @ { price.ToString("N9")}"); try @@ -50,9 +49,9 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi } for (var i = 0; i < buyOrdersToPlace; i += 1) { - var price = midMarket - ((i + 1) * midMarket * 0.05); + var price = midMarket - ((i + 1) * midMarket * 0.05m); var amount = Service.ToEth(buyVolumeToPlace / price / buyOrdersToPlace, Service.Config.UnitDecimals); - Console.WriteLine($"Buy { amount.ToString("N3")} @ { price.toFixed(9)}"); + Console.WriteLine($"Buy { amount.ToString("N3")} @ { price.ToString("N9")}"); try { var order = Service.CreateOrder(OrderType.Buy, expires, price, amount); @@ -68,5 +67,5 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi Console.WriteLine("Done"); } - } + } } \ No newline at end of file diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs index 338fa0c..b2c6a73 100644 --- a/dotnet/Orders.cs +++ b/dotnet/Orders.cs @@ -9,14 +9,14 @@ namespace EhterDelta.Bots.Dontnet public class Orders { public List Sells { get; set; } - public List Buys { get; set; } + public List Buys { get; set; } } public class Order { public string Id { get; set; } public string Amount { get; set; } - public double Price { get; set; } + public decimal Price { get; set; } public string TokenGet { get; set; } public HexBigInteger AmountGet { get; set; } public string TokenGive { get; set; } @@ -28,7 +28,7 @@ public class Order public string AvailableVolume { get; set; } public decimal EthAvailableVolume { get; set; } public string AvailableVolumeBase { get; set; } - public double EthAvailableVolumeBase { get; set; } + public decimal EthAvailableVolumeBase { get; set; } public string AmountFilled { get; set; } public int V { get; internal set; } public string R { get; internal set; } diff --git a/dotnet/Service.cs b/dotnet/Service.cs index f0f75e6..a36f072 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -21,26 +21,9 @@ public class Service private const string ZeroToken = "0x0000000000000000000000000000000000000000"; private WebSocket socket; const int SocketMessageTimeout = 20000; - private void Log(string message) - { - if (logger != null) - { - logger.Log(message); - } - } - - private void InitSocket() - { - socket = new WebSocket(Config.SocketUrl); - socket.Opened += SocketOpened; - socket.Error += SocketError; - socket.Closed += SocketClosed; - socket.MessageReceived += SocketMessageReceived; - socket.OpenAsync().Wait(); - } - private ILogger logger; + public Service(EtherDeltaConfiguration config, ILogger configLogger) { logger = configLogger; @@ -49,13 +32,13 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) Orders = new Orders { Sells = new List(), - Buys = new List() + Buys = new List() }; MyOrders = new Orders { Sells = new List(), - Buys = new List() + Buys = new List() }; Config = config; @@ -72,7 +55,17 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) InitSocket(); } - internal async Task TakeOrder(Order order, double fraction) + public EtherDeltaConfiguration Config { get; } + public Web3 Web3 { get; } + public Contract EtherDeltaContract { get; } + public Contract EthContract { get; } + public Orders Orders { get; set; } + public Orders MyOrders { get; set; } + public dynamic Trades { get; set; } + public List MyTrades { get; set; } + public dynamic Market { get; private set; } + + internal async Task TakeOrder(Order order, decimal fraction) { var amount = order.AmountGet * new BigInteger(fraction); @@ -120,9 +113,7 @@ internal async Task TakeOrder(Order order, double fraction) txCount, Config.GasPrice, Config.GasLimit, data); var txId = await Web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(encoded.EnsureHexPrefix()); - var receipt = await Web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); - return receipt; } @@ -136,12 +127,12 @@ internal async Task GetBlockNumber() return await Web3.Eth.Blocks.GetBlockNumber.SendRequestAsync(); } - internal async Task CreateOrder(OrderType orderType, BigInteger expires, BigInteger price, BigInteger amount) + internal async Task CreateOrder(OrderType orderType, BigInteger expires, decimal price, BigInteger amount) { await Task.Delay(1); var amountBigNum = amount; - var amountBaseBigNum = amount * price; + var amountBaseBigNum = amount * new BigInteger(price); var contractAddr = Config.AddressEtherDelta; var tokenGet = orderType == OrderType.Buy ? Config.Token : ZeroToken; var tokenGive = orderType == OrderType.Sell ? Config.Token : ZeroToken; @@ -299,7 +290,7 @@ public async Task WaitForMarket() private void UpdateOrders(dynamic orders) { - //var minOrderSize = 0.001; + var minOrderSize = 0.001m; if (orders == null) { @@ -318,14 +309,37 @@ private void UpdateOrders(dynamic orders) Orders.Sells = sells; } - var buys = ((JArray)orders.buys).Where(jtoken => jtoken["tokenGet"] != null && jtoken["tokenGet"].ToString() == Config.Token).ToList(); - if (buys != null && buys.Count > 0) + var buys = ((JArray)orders.buys) + .Where(jtoken => jtoken["tokenGet"] != null && jtoken["tokenGet"].ToString() == Config.Token) + .Select(jtoken => Order.FromJson(jtoken)) + .ToList(); + + if (buys != null && buys.Count() > 0) { - Orders.Buys = buys.ToList(); + Orders.Buys = buys; } - } - // TODO: update MyOrders + + var mySells = ((JArray)orders.sells) + .Where(jtoken => jtoken["tokenGive"] != null && jtoken["tokenGive"].ToString() == Config.Token) + .Select(jtoken => Order.FromJson(jtoken)) + .ToList(); + + if (mySells != null && mySells.Count() > 0) + { + MyOrders.Sells = mySells; + } + + var myBuys = ((JArray)orders.buys) + .Where(jtoken => jtoken["tokenGive"] != null && jtoken["tokenGive"].ToString() == Config.Token) + .Select(jtoken => Order.FromJson(jtoken)) + .ToList(); + + if (myBuys != null && myBuys.Count > 0) + { + MyOrders.Buys = myBuys.ToList(); + } + } } private void UpdateTrades(dynamic trades) @@ -341,14 +355,23 @@ private void UpdateTrades(dynamic trades) } } - public EtherDeltaConfiguration Config { get; } - public Web3 Web3 { get; } - public Contract EtherDeltaContract { get; } - public Contract EthContract { get; } - public Orders Orders { get; set; } - public Orders MyOrders { get; set; } - public dynamic Trades { get; set; } - public List MyTrades { get; set; } - public dynamic Market { get; private set; } + + private void Log(string message) + { + if (logger != null) + { + logger.Log(message); + } + } + + private void InitSocket() + { + socket = new WebSocket(Config.SocketUrl); + socket.Opened += SocketOpened; + socket.Error += SocketError; + socket.Closed += SocketClosed; + socket.MessageReceived += SocketMessageReceived; + socket.OpenAsync().Wait(); + } } } \ No newline at end of file diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs index b1ecad5..0459d01 100644 --- a/dotnet/Taker.cs +++ b/dotnet/Taker.cs @@ -11,7 +11,7 @@ public Taker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi if (order != null) { Console.WriteLine($"Best available: Sell {order.EthAvailableVolume.ToString("N3")} @ {order.Price.ToString("N9")}"); - var desiredAmountBase = 0.001; + var desiredAmountBase = 0.001m; var fraction = Math.Min(desiredAmountBase / order.EthAvailableVolumeBase, 1); try From fcb86b6a86639dd2281384c598802a00574a3724 Mon Sep 17 00:00:00 2001 From: stojce Date: Fri, 8 Dec 2017 14:31:01 +0100 Subject: [PATCH 08/15] Trades types --- dotnet/BaseBot.cs | 25 ++++------ dotnet/Maker.cs | 11 +++-- dotnet/Orders.cs | 20 ++++++-- dotnet/Service.cs | 119 ++++++++++++++++++++++------------------------ dotnet/Trade.cs | 46 ++++++++++++++++++ 5 files changed, 135 insertions(+), 86 deletions(-) create mode 100644 dotnet/Trade.cs diff --git a/dotnet/BaseBot.cs b/dotnet/BaseBot.cs index aec2de1..50c1402 100644 --- a/dotnet/BaseBot.cs +++ b/dotnet/BaseBot.cs @@ -92,19 +92,13 @@ private void PrintTrades() Console.WriteLine("===================================="); int numTrades = 10; - var trades = Service.Trades; - - if (trades != null && trades.GetType() == typeof(JArray)) + if (Service.Trades != null) { - trades = ((JArray)trades).Take(numTrades).ToArray(); + var trades = Service.Trades.Take(numTrades); foreach (var trade in trades) { - var tradePrice = (decimal)((JValue)trade.price); - var tradeAmount = (decimal)((JValue)trade.amount); - var tradeDate = (DateTime)((JValue)trade.date); - - Console.ForegroundColor = trade.side == "sell" ? ConsoleColor.Red : ConsoleColor.Green; - Console.WriteLine($"{tradeDate.ToLocalTime()} {trade.side} {tradeAmount.ToString("N3")} @ {tradePrice.ToString("N9")}"); + Console.ForegroundColor = trade.Side == "sell" ? ConsoleColor.Red : ConsoleColor.Green; + Console.WriteLine($"{trade.Date.ToLocalTime()} {trade.Side} {trade.Amount.ToString("N3")} @ {trade.Price.ToString("N9")}"); } } @@ -118,17 +112,14 @@ private void PrintOrders() Console.WriteLine("===================================="); int ordersPerSide = 10; - List sells = Service.Orders != null ? Service.Orders.Sells : null; - List buys = Service.Orders != null ? Service.Orders.Buys : null; - - if (sells == null || buys == null) + if (Service.Orders.Sells.Count() == 0 && Service.Orders.Buys.Count() == 0) { Console.WriteLine("No sell or buy orders"); return; } - sells = sells.Take(ordersPerSide).Reverse().ToList(); - buys = buys.Take(ordersPerSide).ToList(); + var sells = Service.Orders.Sells.Take(ordersPerSide).Reverse(); + var buys = Service.Orders.Buys.Take(ordersPerSide); Console.ForegroundColor = ConsoleColor.Red; foreach (var order in sells) @@ -137,7 +128,7 @@ private void PrintOrders() } Console.ResetColor(); - if (buys.Count > 0 && sells.Count > 0) + if (buys.Count() > 0 && sells.Count() > 0) { var salesPrice = sells.Last().Price; var buysPrice = buys.Last().Price; diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index 0e0e7cd..91fe1f3 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Collections.Generic; using System.Threading.Tasks; @@ -10,18 +11,18 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi { var ordersPerSide = 1; var expires = Service.GetBlockNumber().Result + 10; - var buyOrdersToPlace = ordersPerSide - Service.MyOrders.Buys.Count; - var sellOrdersToPlace = ordersPerSide - Service.MyOrders.Sells.Count; + var buyOrdersToPlace = ordersPerSide - Service.MyOrders.Buys.Count(); + var sellOrdersToPlace = ordersPerSide - Service.MyOrders.Sells.Count(); var buyVolumeToPlace = EtherDeltaETH; var sellVolumeToPlace = EtherDeltaToken; - if (Service.Orders.Buys.Count <= 0 || Service.Orders.Sells.Count <= 0) + if (Service.Orders.Buys.Count() == 0 || Service.Orders.Sells.Count() == 0) { throw new Exception("Market is not two-sided, cannot calculate mid-market"); } - var bestBuy = Service.Orders.Buys[0].Price; - var bestSell = Service.Orders.Sells[0].Price; + var bestBuy = Service.Orders.Buys.First().Price; + var bestSell = Service.Orders.Sells.First().Price; // Make sure we have a reliable mid market if (Math.Abs((bestBuy - bestSell) / (bestBuy + bestSell) / 2) > 0.05m) diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs index b2c6a73..0b45166 100644 --- a/dotnet/Orders.cs +++ b/dotnet/Orders.cs @@ -6,10 +6,10 @@ namespace EhterDelta.Bots.Dontnet { - public class Orders + public class Orders : Object { - public List Sells { get; set; } - public List Buys { get; set; } + public IEnumerable Sells { get; set; } + public IEnumerable Buys { get; set; } } public class Order @@ -50,5 +50,19 @@ internal static Order FromJson(JToken jtoken) return order; } + + public bool Equals(Order other) + { + if (other == null) + { + return false; + } + return other.Id == Id; + } + + public override int GetHashCode() + { + return Id.GetHashCode(); + } } } \ No newline at end of file diff --git a/dotnet/Service.cs b/dotnet/Service.cs index a36f072..90a65c7 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -20,9 +20,9 @@ public class Service { private const string ZeroToken = "0x0000000000000000000000000000000000000000"; private WebSocket socket; - const int SocketMessageTimeout = 20000; + const int socketTimeout = 20000; private ILogger logger; - + private bool gotMarket = false; public Service(EtherDeltaConfiguration config, ILogger configLogger) { @@ -40,6 +40,8 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) Sells = new List(), Buys = new List() }; + Trades = new List(); + MyTrades = new List(); Config = config; Web3 = new Web3(config.Provider); @@ -61,9 +63,8 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) public Contract EthContract { get; } public Orders Orders { get; set; } public Orders MyOrders { get; set; } - public dynamic Trades { get; set; } - public List MyTrades { get; set; } - public dynamic Market { get; private set; } + public IEnumerable Trades { get; set; } + public IEnumerable MyTrades { get; set; } internal async Task TakeOrder(Order order, decimal fraction) { @@ -169,7 +170,13 @@ private void SocketMessageReceived(object sender, MessageReceivedEventArgs e) case "market": UpdateOrders(message.Data.orders); UpdateTrades(message.Data.trades); - Market = message.Data; + gotMarket = true; + break; + case "trades": + UpdateTrades(message.Data); + break; + case "orders": + UpdateOrders(message.Data); break; default: break; @@ -260,7 +267,7 @@ private void SocketOpened(object sender, EventArgs e) public async Task WaitForMarket() { Log("Wait for Market"); - Market = null; + gotMarket = false; socket.Send(new Message { Event = "getMarket", @@ -271,88 +278,77 @@ public async Task WaitForMarket() } }.ToString()); - var gotMarket = Task.Run(() => + var gotMarketTask = Task.Run(() => { - while (Market == null) + while (!gotMarket) { Task.Delay(1000).Wait(); } }); - var completed = await Task.WhenAny(gotMarket, Task.Delay(SocketMessageTimeout)); + var completed = await Task.WhenAny(gotMarketTask, Task.Delay(socketTimeout)); Log("Market Completed ..."); - if (!gotMarket.IsCompletedSuccessfully) + if (!gotMarketTask.IsCompletedSuccessfully) { throw new TimeoutException("Get Market timeout"); } } - private void UpdateOrders(dynamic orders) + private void UpdateOrders(dynamic ordersObj) { var minOrderSize = 0.001m; - + var orders = ordersObj as JObject; if (orders == null) { return; } - if (orders.GetType() == typeof(JObject)) - { - var sells = ((JArray)orders.sells) - .Where(jtoken => jtoken["tokenGive"] != null && jtoken["tokenGive"].ToString() == Config.Token) - .Select(jtoken => Order.FromJson(jtoken)) - .ToList(); - - if (sells != null && sells.Count() > 0) - { - Orders.Sells = sells; - } - - var buys = ((JArray)orders.buys) - .Where(jtoken => jtoken["tokenGet"] != null && jtoken["tokenGet"].ToString() == Config.Token) - .Select(jtoken => Order.FromJson(jtoken)) - .ToList(); - - if (buys != null && buys.Count() > 0) - { - Orders.Buys = buys; - } - - - var mySells = ((JArray)orders.sells) - .Where(jtoken => jtoken["tokenGive"] != null && jtoken["tokenGive"].ToString() == Config.Token) - .Select(jtoken => Order.FromJson(jtoken)) - .ToList(); + var sells = ((JArray)orders["sells"]) + .Where(jtoken => + jtoken["tokenGive"] != null && jtoken["tokenGive"].ToString() == Config.Token && + jtoken["ethAvailableVolumeBase"] != null && jtoken["ethAvailableVolumeBase"].ToObject() > minOrderSize && + (jtoken["deleted"] == null || jtoken["deleted"].ToObject() == false) + ) + .Select(jtoken => Order.FromJson(jtoken)); - if (mySells != null && mySells.Count() > 0) - { - MyOrders.Sells = mySells; - } + if (sells != null && sells.Count() > 0) + { + Log($"Got {sells.Count()} sells"); + Orders.Sells = Orders.Sells.Union(sells); + MyOrders.Sells = MyOrders.Sells.Union(sells.Where(s => s.User == Config.User)); + } - var myBuys = ((JArray)orders.buys) - .Where(jtoken => jtoken["tokenGive"] != null && jtoken["tokenGive"].ToString() == Config.Token) - .Select(jtoken => Order.FromJson(jtoken)) - .ToList(); + var buys = ((JArray)orders["buys"]) + .Where(jtoken => + jtoken["tokenGet"] != null && jtoken["tokenGet"].ToString() == Config.Token && + jtoken["ethAvailableVolumeBase"] != null && jtoken["ethAvailableVolumeBase"].ToObject() > minOrderSize && + (jtoken["deleted"] == null || jtoken["deleted"].ToObject() == false) + ) + .Select(jtoken => Order.FromJson(jtoken)); - if (myBuys != null && myBuys.Count > 0) - { - MyOrders.Buys = myBuys.ToList(); - } + if (buys != null && buys.Count() > 0) + { + Log($"Got {buys.Count()} buys"); + Orders.Buys = Orders.Buys.Union(buys); + MyOrders.Buys = MyOrders.Buys.Union(buys.Where(s => s.User == Config.User)); } } - private void UpdateTrades(dynamic trades) + private void UpdateTrades(JArray trades) { - if (trades == null) - { - return; - } - if (trades.GetType() == typeof(JArray)) - { - Trades = trades; - } + Log($"Got {trades.Count} trades"); + var tradesArray = trades + .Where(jtoken => + jtoken["txHash"] != null && + jtoken["amount"] != null && jtoken["amount"].ToObject() > 0m + ) + .Select(jtoken => Trade.FromJson(jtoken)); + + Log($"Parsed {tradesArray.Count()} trades"); + Trades = Trades.Union(tradesArray); + Log($"total {Trades.Count()} trades"); } @@ -374,4 +370,5 @@ private void InitSocket() socket.OpenAsync().Wait(); } } + } \ No newline at end of file diff --git a/dotnet/Trade.cs b/dotnet/Trade.cs new file mode 100644 index 0000000..e17a0fa --- /dev/null +++ b/dotnet/Trade.cs @@ -0,0 +1,46 @@ +using System; +using Newtonsoft.Json.Linq; + +namespace EhterDelta.Bots.Dontnet +{ + public class Trade + { + public Trade() + { + } + + string TxHash { get; set; } + public decimal Price { get; set; } + public DateTime Date { get; set; } + public decimal Amount { get; set; } + public decimal AmountBase { get; set; } + public string Side { get; set; } + public string Buyer { get; set; } + public string Seller { get; set; } + public string TokenAddr { get; set; } + + public static Trade FromJson(JToken jtoken) + { + var trade = jtoken.ToObject(); + + if (trade.TxHash == null && jtoken["txHash"] != null) + { + trade.TxHash = jtoken["txHash"].ToString(); + } + return trade; + } + + public bool Equals(Trade other) + { + if (other == null) + { + return false; + } + return other.TxHash == TxHash; + } + public override int GetHashCode() + { + return TxHash.GetHashCode(); + } + } +} \ No newline at end of file From 2b08779b0383ce714fe44d6018c22631a4285cde Mon Sep 17 00:00:00 2001 From: stojce Date: Fri, 8 Dec 2017 17:56:11 +0100 Subject: [PATCH 09/15] Trade fixes --- dotnet/App.config | 2 ++ dotnet/EtherDeltaConfiguration.cs | 10 ++++++---- dotnet/Orders.cs | 4 ++++ dotnet/Program.cs | 17 ++++++++++------- dotnet/Service.cs | 19 ++++++++++++------- dotnet/Taker.cs | 10 ++++++++-- dotnet/Trade.cs | 1 + 7 files changed, 43 insertions(+), 20 deletions(-) diff --git a/dotnet/App.config b/dotnet/App.config index 4de31bf..d7f76e6 100644 --- a/dotnet/App.config +++ b/dotnet/App.config @@ -10,5 +10,7 @@ + + \ No newline at end of file diff --git a/dotnet/EtherDeltaConfiguration.cs b/dotnet/EtherDeltaConfiguration.cs index 95c2a12..92ef353 100644 --- a/dotnet/EtherDeltaConfiguration.cs +++ b/dotnet/EtherDeltaConfiguration.cs @@ -1,4 +1,6 @@ -namespace EhterDelta.Bots.Dontnet +using System.Numerics; + +namespace EhterDelta.Bots.Dontnet { public class EtherDeltaConfiguration { @@ -13,7 +15,7 @@ public class EtherDeltaConfiguration public string PrivateKey { get; internal set; } public int UnitDecimals { get; internal set; } - public int GasLimit { get; internal set; } - public uint GasPrice { get; internal set; } - } + public BigInteger GasLimit { get; internal set; } + public BigInteger GasPrice { get; internal set; } + } } \ No newline at end of file diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs index 0b45166..5bcd70a 100644 --- a/dotnet/Orders.cs +++ b/dotnet/Orders.cs @@ -34,6 +34,8 @@ public class Order public string R { get; internal set; } public string S { get; internal set; } + public string Raw { get; internal set; } + internal static Order FromJson(JToken jtoken) { var order = jtoken.ToObject(); @@ -48,6 +50,8 @@ internal static Order FromJson(JToken jtoken) Console.WriteLine(ex.Message); } + order.Raw = jtoken.ToString(); + return order; } diff --git a/dotnet/Program.cs b/dotnet/Program.cs index 290fb92..6239fe5 100644 --- a/dotnet/Program.cs +++ b/dotnet/Program.cs @@ -1,9 +1,10 @@ - - -using System; -using System.Configuration; - -namespace EhterDelta.Bots.Dontnet + + +using System; +using System.Configuration; +using System.Numerics; + +namespace EhterDelta.Bots.Dontnet { class Program { @@ -27,6 +28,8 @@ static void Main(string[] args) User = ConfigurationManager.AppSettings["User"], PrivateKey = ConfigurationManager.AppSettings["PrivateKey"], UnitDecimals = int.Parse(ConfigurationManager.AppSettings["UnitDecimals"]), + GasPrice = new BigInteger(UInt64.Parse(ConfigurationManager.AppSettings["GasPrice"])), + GasLimit = new BigInteger(UInt64.Parse(ConfigurationManager.AppSettings["GasLimit"])) }; ILogger logger = null; @@ -52,5 +55,5 @@ public void Log(string message) Console.WriteLine($"{DateTimeOffset.Now.DateTime.ToUniversalTime()} : {message}"); } } - } + } } \ No newline at end of file diff --git a/dotnet/Service.cs b/dotnet/Service.cs index 90a65c7..50a2c1d 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -13,6 +13,7 @@ using Nethereum.ABI; using Nethereum.Hex.HexConvertors.Extensions; using Nethereum.RPC.Eth.DTOs; +using Nethereum.Hex.HexTypes; namespace EhterDelta.Bots.Dontnet { @@ -68,11 +69,12 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) internal async Task TakeOrder(Order order, decimal fraction) { - var amount = order.AmountGet * new BigInteger(fraction); + var uc = new UnitConversion(); + var amount = order.AmountGet.Value * uc.ToWei(fraction); - var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); - var fnTest = EtherDeltaContract.GetFunction("testTrade"); + Console.WriteLine(order.Raw); + var fnTest = EtherDeltaContract.GetFunction("testTrade"); var willPass = await fnTest.CallAsync( order.TokenGet, order.AmountGet.Value, @@ -88,11 +90,10 @@ internal async Task TakeOrder(Order order, decimal fraction) Config.User ); - if (!willPass) { Log("Order will fail"); - throw new Exception("Order will fail"); + //throw new Exception("Order will fail"); } var fnTrade = EtherDeltaContract.GetFunction("trade"); @@ -110,8 +111,12 @@ internal async Task TakeOrder(Order order, decimal fraction) amount ); - var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, amount, - txCount, Config.GasPrice, Config.GasLimit, data); + var gp = uc.ToWei(32, UnitConversion.EthUnit.Gwei); + + + var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); + var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, 10, + txCount.Value); var txId = await Web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(encoded.EnsureHexPrefix()); var receipt = await Web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs index 0459d01..d9575e2 100644 --- a/dotnet/Taker.cs +++ b/dotnet/Taker.cs @@ -20,13 +20,19 @@ public Taker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi } catch (Exception ex) { - Console.WriteLine(ex.Message); + if (ex.InnerException != null) + { + Console.WriteLine(ex.InnerException.Message); + } + else + { + Console.WriteLine(ex.Message); + } } } else { Console.WriteLine("No Available order"); - Console.WriteLine(Service.Orders); } Console.WriteLine(); diff --git a/dotnet/Trade.cs b/dotnet/Trade.cs index e17a0fa..1dacee4 100644 --- a/dotnet/Trade.cs +++ b/dotnet/Trade.cs @@ -38,6 +38,7 @@ public bool Equals(Trade other) } return other.TxHash == TxHash; } + public override int GetHashCode() { return TxHash.GetHashCode(); From aff673fe1a69119e7fbe86325a51d4cbaf2a1a41 Mon Sep 17 00:00:00 2001 From: stojce Date: Fri, 8 Dec 2017 20:17:46 +0100 Subject: [PATCH 10/15] Maker + user big integer for store --- dotnet/BaseBot.cs | 27 +++++++------- dotnet/Maker.cs | 41 ++++++++++++++------- dotnet/Orders.cs | 2 +- dotnet/Service.cs | 90 ++++++++++++++++++++++++++++++++--------------- dotnet/Taker.cs | 2 ++ 5 files changed, 108 insertions(+), 54 deletions(-) diff --git a/dotnet/BaseBot.cs b/dotnet/BaseBot.cs index 50c1402..770331d 100644 --- a/dotnet/BaseBot.cs +++ b/dotnet/BaseBot.cs @@ -3,6 +3,8 @@ using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; +using System.Numerics; +using Nethereum.Util; namespace EhterDelta.Bots.Dontnet { @@ -10,10 +12,10 @@ public abstract class BaseBot { protected Service Service { get; set; } - protected decimal EtherDeltaETH { get; set; } - protected decimal WalletETH { get; set; } - protected decimal EtherDeltaToken { get; set; } - protected decimal WalletToken { get; set; } + protected BigInteger EtherDeltaETH { get; set; } + protected BigInteger WalletETH { get; set; } + protected BigInteger EtherDeltaToken { get; set; } + protected BigInteger WalletToken { get; set; } public BaseBot(EtherDeltaConfiguration config, ILogger logger = null) { @@ -38,9 +40,9 @@ public BaseBot(EtherDeltaConfiguration config, ILogger logger = null) Console.WriteLine(); } - private async Task GetEtherDeltaBalance(string token, string user) + private async Task GetEtherDeltaBalance(string token, string user) { - decimal balance = 0; + BigInteger balance = 0; try { balance = await Service.GetEtherDeltaBalance(token, user); @@ -61,9 +63,9 @@ private async Task GetEtherDeltaBalance(string token, string user) return balance; } - private async Task GetBalanceAsync(string token, string user) + private async Task GetBalanceAsync(string token, string user) { - decimal balance = 0; + BigInteger balance = 0; try { @@ -154,13 +156,14 @@ private void PrintOrders() private void PrintWallet() { + var uc = new UnitConversion(); Console.WriteLine(); Console.WriteLine("Account balances"); Console.WriteLine("===================================="); - Console.WriteLine($"Wallet ETH balance: {WalletETH}"); - Console.WriteLine($"EtherDelta ETH balance: {EtherDeltaETH}"); - Console.WriteLine($"Wallet token balance: {WalletToken}"); - Console.WriteLine($"EtherDelta token balance: {EtherDeltaToken}"); + Console.WriteLine($"Wallet ETH balance: {uc.FromWei(WalletETH).ToString("N18")}"); + Console.WriteLine($"EtherDelta ETH balance: {uc.FromWei(EtherDeltaETH).ToString("N18")}"); + Console.WriteLine($"Wallet token balance: {uc.FromWei(WalletToken).ToString("N18")}"); + Console.WriteLine($"EtherDelta token balance: {uc.FromWei(EtherDeltaToken).ToString("N18")}"); } private string FormatOrder(Order order) diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index 91fe1f3..ecdcf64 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -1,4 +1,5 @@ using System; +using System.Numerics; using System.Linq; using System.Collections.Generic; using System.Threading.Tasks; @@ -9,6 +10,9 @@ public class Maker : BaseBot { public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(config, logger) { + + PrintMyOrders(); + var ordersPerSide = 1; var expires = Service.GetBlockNumber().Result + 10; var buyOrdersToPlace = ordersPerSide - Service.MyOrders.Buys.Count(); @@ -16,27 +20,29 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi var buyVolumeToPlace = EtherDeltaETH; var sellVolumeToPlace = EtherDeltaToken; - if (Service.Orders.Buys.Count() == 0 || Service.Orders.Sells.Count() == 0) + var bestBuy = Service.GetBestAvailableBuy(); + var bestSell = Service.GetBestAvailableSell(); + + if (bestBuy == null || bestSell == null) { - throw new Exception("Market is not two-sided, cannot calculate mid-market"); + Console.WriteLine("Market is not two-sided, cannot calculate mid-market"); + return; } - var bestBuy = Service.Orders.Buys.First().Price; - var bestSell = Service.Orders.Sells.First().Price; - // Make sure we have a reliable mid market - if (Math.Abs((bestBuy - bestSell) / (bestBuy + bestSell) / 2) > 0.05m) + if (Math.Abs((bestBuy.Price - bestSell.Price) / (bestBuy.Price + bestSell.Price) / 2) > 0.05m) { - throw new Exception("Market is too wide, will not place orders"); + Console.WriteLine("Market is too wide, will not place orders"); + return; } - var midMarket = (bestBuy + bestSell) / 2; - var orders = new List(); + var midMarket = (bestBuy.Price + bestSell.Price) / 2; + var orders = new List(); for (var i = 0; i < sellOrdersToPlace; i += 1) { var price = midMarket + ((i + 1) * midMarket * 0.05m); - var amount = Service.ToEth(sellVolumeToPlace / sellOrdersToPlace, Service.Config.UnitDecimals); + var amount = sellVolumeToPlace / sellOrdersToPlace; Console.WriteLine($"Sell { amount.ToString("N3")} @ { price.ToString("N9")}"); try { @@ -51,11 +57,11 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi for (var i = 0; i < buyOrdersToPlace; i += 1) { var price = midMarket - ((i + 1) * midMarket * 0.05m); - var amount = Service.ToEth(buyVolumeToPlace / price / buyOrdersToPlace, Service.Config.UnitDecimals); + var amount = 0; //buyVolumeToPlace / price / buyOrdersToPlace; Console.WriteLine($"Buy { amount.ToString("N3")} @ { price.ToString("N9")}"); try { - var order = Service.CreateOrder(OrderType.Buy, expires, price, amount); + var order = Service.CreateOrder(OrderType.Buy, expires, price, new BigInteger(amount)); orders.Add(order); } catch (Exception ex) @@ -64,9 +70,18 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi } } - Task.WhenAll(orders).Wait(); + + // orders.ForEach(Service.PlaceOrder); + + // Task.WhenAll(orders).Wait(); Console.WriteLine("Done"); } + + void PrintMyOrders() + { + Console.WriteLine($"My existing buy orders: {Service.MyOrders.Buys.Count()}"); + Console.WriteLine($"My existing sell orders: {Service.MyOrders.Sells.Count()}"); + } } } \ No newline at end of file diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs index 5bcd70a..2040124 100644 --- a/dotnet/Orders.cs +++ b/dotnet/Orders.cs @@ -33,7 +33,7 @@ public class Order public int V { get; internal set; } public string R { get; internal set; } public string S { get; internal set; } - + public string ContractAddr { get; internal set; } public string Raw { get; internal set; } internal static Order FromJson(JToken jtoken) diff --git a/dotnet/Service.cs b/dotnet/Service.cs index 50a2c1d..e497a42 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -72,8 +72,6 @@ internal async Task TakeOrder(Order order, decimal fraction) var uc = new UnitConversion(); var amount = order.AmountGet.Value * uc.ToWei(fraction); - Console.WriteLine(order.Raw); - var fnTest = EtherDeltaContract.GetFunction("testTrade"); var willPass = await fnTest.CallAsync( order.TokenGet, @@ -93,7 +91,7 @@ internal async Task TakeOrder(Order order, decimal fraction) if (!willPass) { Log("Order will fail"); - //throw new Exception("Order will fail"); + throw new Exception("Order will fail"); } var fnTrade = EtherDeltaContract.GetFunction("trade"); @@ -111,12 +109,9 @@ internal async Task TakeOrder(Order order, decimal fraction) amount ); - var gp = uc.ToWei(32, UnitConversion.EthUnit.Gwei); - - var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); - var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, 10, - txCount.Value); + var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, amount, + txCount, Config.GasPrice, Config.GasLimit, data); var txId = await Web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(encoded.EnsureHexPrefix()); var receipt = await Web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); @@ -128,34 +123,71 @@ internal Order GetBestAvailableSell() return Orders.Sells.FirstOrDefault(); } + internal Order GetBestAvailableBuy() + { + return Orders.Buys.FirstOrDefault(); + } + internal async Task GetBlockNumber() { return await Web3.Eth.Blocks.GetBlockNumber.SendRequestAsync(); } - internal async Task CreateOrder(OrderType orderType, BigInteger expires, decimal price, BigInteger amount) + internal Order CreateOrder(OrderType orderType, BigInteger expires, decimal price, BigInteger amount) { - await Task.Delay(1); - var amountBigNum = amount; var amountBaseBigNum = amount * new BigInteger(price); var contractAddr = Config.AddressEtherDelta; var tokenGet = orderType == OrderType.Buy ? Config.Token : ZeroToken; var tokenGive = orderType == OrderType.Sell ? Config.Token : ZeroToken; - var amountGet = orderType == OrderType.Buy ? toWei(amountBigNum, Config.UnitDecimals) : toWei(amountBaseBigNum, Config.UnitDecimals); - var amountGive = orderType == OrderType.Sell ? toWei(amountBigNum, Config.UnitDecimals) : toWei(amountBaseBigNum, Config.UnitDecimals); + var amountGet = orderType == OrderType.Buy ? amountBigNum : amountBaseBigNum; + var amountGive = orderType == OrderType.Sell ? amountBigNum : amountBaseBigNum; var orderNonce = new Random().Next(); - } + var fnTrade = EtherDeltaContract.GetFunction("trade"); - internal BigInteger ToEth(dynamic dynamic, object decimals) - { - throw new NotImplementedException(); - } + // var data = fnTrade.GetData( + // order.TokenGet, + // order.AmountGet.Value, + // order.TokenGive, + // order.AmountGive.Value, + // order.Expires, + // order.Nonce, + // order.User, + // order.V, + // order.R.HexToByteArray(), + // order.S.HexToByteArray(), + // amount + // ); - private string toWei(BigInteger amountBigNum, int unitDecimals) - { - throw new NotImplementedException(); + // var gp = uc.ToWei(32, UnitConversion.EthUnit.Gwei); + + + // var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); + // var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, 10, + // txCount.Value); + + // var txId = await Web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(encoded.EnsureHexPrefix()); + // var receipt = await Web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); + + dynamic sig = new { v = 1, r = "234", s = "342" }; + + var order = new Order + { + AmountGet = new HexBigInteger(amountGet), + AmountGive = new HexBigInteger(amountGive), + TokenGet = tokenGet, + TokenGive = tokenGive, + ContractAddr = contractAddr, + Expires = expires, + Nonce = orderNonce, + User = Config.User, + V = sig.v, + R = sig.r, + S = sig.s, + }; + + return order; } internal void Close() @@ -205,9 +237,8 @@ private void SocketClosed(object sender, EventArgs e) } } - internal async Task GetBalance(string token, string user) + internal async Task GetBalance(string token, string user) { - var unitConversion = new UnitConversion(); BigInteger balance = 0; user = Web3.ToChecksumAddress(user); @@ -231,12 +262,11 @@ internal async Task GetBalance(string token, string user) Log(ex.Message); } - return unitConversion.FromWei(balance, Config.UnitDecimals); + return balance; } - internal async Task GetEtherDeltaBalance(string token, string user) + internal async Task GetEtherDeltaBalance(string token, string user) { - var unitConversion = new UnitConversion(); BigInteger balance = 0; try @@ -255,7 +285,7 @@ internal async Task GetEtherDeltaBalance(string token, string user) Log(ex.Message); } - return unitConversion.FromWei(balance, Config.UnitDecimals); + return balance; } private void SocketError(object sender, SuperSocket.ClientEngine.ErrorEventArgs e) @@ -312,7 +342,7 @@ private void UpdateOrders(dynamic ordersObj) var sells = ((JArray)orders["sells"]) .Where(jtoken => jtoken["tokenGive"] != null && jtoken["tokenGive"].ToString() == Config.Token && - jtoken["ethAvailableVolumeBase"] != null && jtoken["ethAvailableVolumeBase"].ToObject() > minOrderSize && + //jtoken["ethAvailableVolumeBase"] != null && jtoken["ethAvailableVolumeBase"].ToObject() > minOrderSize && (jtoken["deleted"] == null || jtoken["deleted"].ToObject() == false) ) .Select(jtoken => Order.FromJson(jtoken)); @@ -342,6 +372,10 @@ private void UpdateOrders(dynamic ordersObj) private void UpdateTrades(JArray trades) { + if (trades == null) + { + return; + } Log($"Got {trades.Count} trades"); var tradesArray = trades diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs index d9575e2..5b6c804 100644 --- a/dotnet/Taker.cs +++ b/dotnet/Taker.cs @@ -20,6 +20,7 @@ public Taker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi } catch (Exception ex) { + Console.ForegroundColor = ConsoleColor.Red; if (ex.InnerException != null) { Console.WriteLine(ex.InnerException.Message); @@ -28,6 +29,7 @@ public Taker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi { Console.WriteLine(ex.Message); } + Console.ResetColor(); } } else From fe9e01815fbea7fd83931df7ae9aa7511708d729 Mon Sep 17 00:00:00 2001 From: stojce Date: Fri, 8 Dec 2017 23:01:08 +0100 Subject: [PATCH 11/15] Maker orders --- dotnet/.vscode/launch.json | 19 ++++++++++- dotnet/Maker.cs | 26 +++++++++++++-- dotnet/Service.cs | 66 ++++++++++++++++++++------------------ dotnet/Taker.cs | 5 ++- 4 files changed, 81 insertions(+), 35 deletions(-) diff --git a/dotnet/.vscode/launch.json b/dotnet/.vscode/launch.json index 419e924..2db6534 100644 --- a/dotnet/.vscode/launch.json +++ b/dotnet/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": ".NET Core Launch (console)", + "name": "Taker", "type": "coreclr", "request": "launch", "preLaunchTask": "build", @@ -21,6 +21,23 @@ "stopAtEntry": false, "internalConsoleOptions": "openOnSessionStart" }, + { + "name": "Maker", + "type": "coreclr", + "request": "launch", + "preLaunchTask": "build", + // If you have changed target frameworks, make sure to update the program path. + "program": "${workspaceFolder}/bin/Debug/netcoreapp2.0/EhterDelta.Bots.Dontnet.dll", + "args": [ + "maker", + "-v" + ], + "cwd": "${workspaceFolder}", + // For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window + "console": "internalConsole", + "stopAtEntry": false, + "internalConsoleOptions": "openOnSessionStart" + }, { "name": ".NET Core Attach", "type": "coreclr", diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index ecdcf64..2ed5eb5 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -71,9 +71,31 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi } - // orders.ForEach(Service.PlaceOrder); + var orderTasks = new List(); + orders.ForEach(order => + { + orderTasks.Add(Service.TakeOrder(order, 1)); + }); + + + try + { + Task.WaitAll(orderTasks.ToArray()); + } + catch (Exception ex) + { - // Task.WhenAll(orders).Wait(); + Console.ForegroundColor = ConsoleColor.Red; + if (ex.InnerException != null) + { + Console.WriteLine(ex.InnerException.Message); + } + else + { + Console.WriteLine(ex.Message); + } + Console.ResetColor(); + } Console.WriteLine("Done"); } diff --git a/dotnet/Service.cs b/dotnet/Service.cs index e497a42..4655ec1 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -14,6 +14,10 @@ using Nethereum.Hex.HexConvertors.Extensions; using Nethereum.RPC.Eth.DTOs; using Nethereum.Hex.HexTypes; +using Nethereum.ABI.FunctionEncoding; +using Nethereum.ABI.Model; +using Nethereum.Signer; +using Nethereum.ABI.Encoders; namespace EhterDelta.Bots.Dontnet { @@ -67,11 +71,8 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) public IEnumerable Trades { get; set; } public IEnumerable MyTrades { get; set; } - internal async Task TakeOrder(Order order, decimal fraction) + internal async Task TakeOrder(Order order, BigInteger amount) { - var uc = new UnitConversion(); - var amount = order.AmountGet.Value * uc.ToWei(fraction); - var fnTest = EtherDeltaContract.GetFunction("testTrade"); var willPass = await fnTest.CallAsync( order.TokenGet, @@ -109,6 +110,8 @@ internal async Task TakeOrder(Order order, decimal fraction) amount ); + var gas = fnTrade.EstimateGasAsync(); + var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, amount, txCount, Config.GasPrice, Config.GasLimit, data); @@ -135,7 +138,8 @@ internal async Task GetBlockNumber() internal Order CreateOrder(OrderType orderType, BigInteger expires, decimal price, BigInteger amount) { - var amountBigNum = amount; + var uc = new UnitConversion(); + var amountBigNum = orderType == OrderType.Buy ? amount / uc.ToWei(price) : amount; var amountBaseBigNum = amount * new BigInteger(price); var contractAddr = Config.AddressEtherDelta; var tokenGet = orderType == OrderType.Buy ? Config.Token : ZeroToken; @@ -144,33 +148,33 @@ internal Order CreateOrder(OrderType orderType, BigInteger expires, decimal pric var amountGive = orderType == OrderType.Sell ? amountBigNum : amountBaseBigNum; var orderNonce = new Random().Next(); - var fnTrade = EtherDeltaContract.GetFunction("trade"); - - // var data = fnTrade.GetData( - // order.TokenGet, - // order.AmountGet.Value, - // order.TokenGive, - // order.AmountGive.Value, - // order.Expires, - // order.Nonce, - // order.User, - // order.V, - // order.R.HexToByteArray(), - // order.S.HexToByteArray(), - // amount - // ); - - // var gp = uc.ToWei(32, UnitConversion.EthUnit.Gwei); + var plainData = new object[] { + Config.AddressEtherDelta, + tokenGive, + amountGet, + tokenGive, + amountGive, + expires, + orderNonce + }; + var prms = new Parameter[] { + new Parameter("address",1), + new Parameter("address",1), + new Parameter("uint256",1), + new Parameter("address",1), + new Parameter("uint256",1), + new Parameter("uint256",1), + new Parameter("uint256",1), + }; - // var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); - // var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, 10, - // txCount.Value); + var pe = new ParametersEncoder(); + var data = pe.EncodeParameters(prms, plainData); - // var txId = await Web3.Eth.Transactions.SendRawTransaction.SendRequestAsync(encoded.EnsureHexPrefix()); - // var receipt = await Web3.Eth.Transactions.GetTransactionReceipt.SendRequestAsync(txId); + var ms = new MessageSigner(); + var signature = ms.HashAndSign(data, Config.PrivateKey); - dynamic sig = new { v = 1, r = "234", s = "342" }; + var ethEcdsa = MessageSigner.ExtractEcdsaSignature(signature); var order = new Order { @@ -182,9 +186,9 @@ internal Order CreateOrder(OrderType orderType, BigInteger expires, decimal pric Expires = expires, Nonce = orderNonce, User = Config.User, - V = sig.v, - R = sig.r, - S = sig.s, + V = ethEcdsa.V, + R = ethEcdsa.R.ToHex(true), + S = ethEcdsa.S.ToHex(true), }; return order; diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs index 5b6c804..9b127e8 100644 --- a/dotnet/Taker.cs +++ b/dotnet/Taker.cs @@ -1,4 +1,5 @@ using System; +using Nethereum.Util; namespace EhterDelta.Bots.Dontnet { @@ -16,7 +17,9 @@ public Taker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi var fraction = Math.Min(desiredAmountBase / order.EthAvailableVolumeBase, 1); try { - Service.TakeOrder(order, fraction).Wait(); + var uc = new UnitConversion(); + var amount = order.AmountGet.Value * uc.ToWei(fraction); + Service.TakeOrder(order, amount).Wait(); } catch (Exception ex) { From 4a14ae5378e96d2b4bd178d89ac886f14e8e871e Mon Sep 17 00:00:00 2001 From: stojce Date: Sat, 9 Dec 2017 01:48:39 +0100 Subject: [PATCH 12/15] refactor data types --- dotnet/Maker.cs | 9 ++++++--- dotnet/Orders.cs | 12 +++++++----- dotnet/Service.cs | 36 ++++++++++++------------------------ 3 files changed, 25 insertions(+), 32 deletions(-) diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index 2ed5eb5..4f97a45 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -3,6 +3,7 @@ using System.Linq; using System.Collections.Generic; using System.Threading.Tasks; +using Nethereum.Util; namespace EhterDelta.Bots.Dontnet { @@ -36,6 +37,8 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi return; } + var uc = new UnitConversion(); + var midMarket = (bestBuy.Price + bestSell.Price) / 2; var orders = new List(); @@ -46,7 +49,7 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi Console.WriteLine($"Sell { amount.ToString("N3")} @ { price.ToString("N9")}"); try { - var order = Service.CreateOrder(OrderType.Sell, expires, price, amount); + var order = Service.CreateOrder(OrderType.Sell, expires, uc.ToWei(price), amount); orders.Add(order); } catch (Exception ex) @@ -57,11 +60,11 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi for (var i = 0; i < buyOrdersToPlace; i += 1) { var price = midMarket - ((i + 1) * midMarket * 0.05m); - var amount = 0; //buyVolumeToPlace / price / buyOrdersToPlace; + var amount = uc.FromWei(buyVolumeToPlace) / price / buyOrdersToPlace; Console.WriteLine($"Buy { amount.ToString("N3")} @ { price.ToString("N9")}"); try { - var order = Service.CreateOrder(OrderType.Buy, expires, price, new BigInteger(amount)); + var order = Service.CreateOrder(OrderType.Buy, expires, uc.ToWei(price), uc.ToWei(amount)); orders.Add(order); } catch (Exception ex) diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs index 2040124..9834e08 100644 --- a/dotnet/Orders.cs +++ b/dotnet/Orders.cs @@ -3,6 +3,7 @@ using System.Numerics; using Newtonsoft.Json.Linq; using System; +using Nethereum.Hex.HexConvertors.Extensions; namespace EhterDelta.Bots.Dontnet { @@ -38,21 +39,22 @@ public class Order internal static Order FromJson(JToken jtoken) { - var order = jtoken.ToObject(); try { + var order = jtoken.ToObject(); order.V = jtoken.Value("v"); order.R = jtoken.Value("r"); order.S = jtoken.Value("s"); + order.Raw = jtoken.ToString(); + + return order; } catch (Exception ex) { - Console.WriteLine(ex.Message); - } - order.Raw = jtoken.ToString(); + } - return order; + return null; } public bool Equals(Order other) diff --git a/dotnet/Service.cs b/dotnet/Service.cs index 4655ec1..c73ffa0 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -73,8 +73,7 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) internal async Task TakeOrder(Order order, BigInteger amount) { - var fnTest = EtherDeltaContract.GetFunction("testTrade"); - var willPass = await fnTest.CallAsync( + var funvtionInput = new object[] { order.TokenGet, order.AmountGet.Value, order.TokenGive, @@ -85,9 +84,11 @@ internal async Task TakeOrder(Order order, BigInteger amount order.V, order.R.HexToByteArray(), order.S.HexToByteArray(), - amount, - Config.User - ); + amount + }; + + var fnTest = EtherDeltaContract.GetFunction("testTrade"); + var willPass = await fnTest.CallAsync(funvtionInput); if (!willPass) { @@ -96,21 +97,7 @@ internal async Task TakeOrder(Order order, BigInteger amount } var fnTrade = EtherDeltaContract.GetFunction("trade"); - var data = fnTrade.GetData( - order.TokenGet, - order.AmountGet.Value, - order.TokenGive, - order.AmountGive.Value, - order.Expires, - order.Nonce, - order.User, - order.V, - order.R.HexToByteArray(), - order.S.HexToByteArray(), - amount - ); - - var gas = fnTrade.EstimateGasAsync(); + var data = fnTrade.GetData(funvtionInput); var txCount = await Web3.Eth.Transactions.GetTransactionCount.SendRequestAsync(Config.User); var encoded = Web3.OfflineTransactionSigner.SignTransaction(Config.PrivateKey, Config.AddressEtherDelta, amount, @@ -136,11 +123,10 @@ internal async Task GetBlockNumber() return await Web3.Eth.Blocks.GetBlockNumber.SendRequestAsync(); } - internal Order CreateOrder(OrderType orderType, BigInteger expires, decimal price, BigInteger amount) + internal Order CreateOrder(OrderType orderType, BigInteger expires, BigInteger price, BigInteger amount) { - var uc = new UnitConversion(); - var amountBigNum = orderType == OrderType.Buy ? amount / uc.ToWei(price) : amount; - var amountBaseBigNum = amount * new BigInteger(price); + var amountBigNum = orderType == OrderType.Buy ? amount / price : amount; + var amountBaseBigNum = amount * price; var contractAddr = Config.AddressEtherDelta; var tokenGet = orderType == OrderType.Buy ? Config.Token : ZeroToken; var tokenGive = orderType == OrderType.Sell ? Config.Token : ZeroToken; @@ -206,6 +192,7 @@ internal void Close() private void SocketMessageReceived(object sender, MessageReceivedEventArgs e) { Message message = Message.ParseMessage(e.Message); + Log($"Got {message.Event} event"); switch (message.Event) { case "market": @@ -220,6 +207,7 @@ private void SocketMessageReceived(object sender, MessageReceivedEventArgs e) UpdateOrders(message.Data); break; default: + Log(e.Message); break; } } From ea4f03431f2b0cd06c40b92a94f7af323b1c4eb9 Mon Sep 17 00:00:00 2001 From: stojce Date: Sat, 9 Dec 2017 02:09:04 +0100 Subject: [PATCH 13/15] orders paesing --- dotnet/Orders.cs | 9 ++++----- dotnet/Service.cs | 3 ++- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs index 9834e08..7a38926 100644 --- a/dotnet/Orders.cs +++ b/dotnet/Orders.cs @@ -39,22 +39,21 @@ public class Order internal static Order FromJson(JToken jtoken) { + Order order = null; try { - var order = jtoken.ToObject(); + order = jtoken.ToObject(); order.V = jtoken.Value("v"); order.R = jtoken.Value("r"); order.S = jtoken.Value("s"); order.Raw = jtoken.ToString(); - - return order; } - catch (Exception ex) + catch { } - return null; + return order; } public bool Equals(Order other) diff --git a/dotnet/Service.cs b/dotnet/Service.cs index c73ffa0..f9aa96d 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -45,6 +45,7 @@ public Service(EtherDeltaConfiguration config, ILogger configLogger) Sells = new List(), Buys = new List() }; + Trades = new List(); MyTrades = new List(); @@ -334,7 +335,7 @@ private void UpdateOrders(dynamic ordersObj) var sells = ((JArray)orders["sells"]) .Where(jtoken => jtoken["tokenGive"] != null && jtoken["tokenGive"].ToString() == Config.Token && - //jtoken["ethAvailableVolumeBase"] != null && jtoken["ethAvailableVolumeBase"].ToObject() > minOrderSize && + jtoken["ethAvailableVolumeBase"] != null && jtoken["ethAvailableVolumeBase"].ToObject() > minOrderSize && (jtoken["deleted"] == null || jtoken["deleted"].ToObject() == false) ) .Select(jtoken => Order.FromJson(jtoken)); From 68acbec18bf4429eec6ceca98ab48422d5b58103 Mon Sep 17 00:00:00 2001 From: stojce Date: Sat, 9 Dec 2017 11:54:55 +0100 Subject: [PATCH 14/15] remove unused usings --- dotnet/BaseBot.cs | 6 ++---- dotnet/EtherDeltaConfiguration.cs | 2 -- dotnet/ILogger.cs | 4 ++-- dotnet/Maker.cs | 12 +++++------- dotnet/Message.cs | 10 +++++----- dotnet/OrderType.cs | 4 ++-- dotnet/Orders.cs | 10 +++------- dotnet/Service.cs | 18 +++++++----------- dotnet/Taker.cs | 2 +- dotnet/Trade.cs | 2 +- 10 files changed, 28 insertions(+), 42 deletions(-) diff --git a/dotnet/BaseBot.cs b/dotnet/BaseBot.cs index 770331d..b6283cb 100644 --- a/dotnet/BaseBot.cs +++ b/dotnet/BaseBot.cs @@ -1,10 +1,8 @@ -using Newtonsoft.Json.Linq; +using Nethereum.Util; using System; -using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; using System.Numerics; -using Nethereum.Util; +using System.Threading.Tasks; namespace EhterDelta.Bots.Dontnet { diff --git a/dotnet/EtherDeltaConfiguration.cs b/dotnet/EtherDeltaConfiguration.cs index 92ef353..a5e9ec8 100644 --- a/dotnet/EtherDeltaConfiguration.cs +++ b/dotnet/EtherDeltaConfiguration.cs @@ -11,9 +11,7 @@ public class EtherDeltaConfiguration public string TokenFile { get; internal set; } public string Token { get; internal set; } public string User { get; internal set; } - public string PrivateKey { get; internal set; } - public int UnitDecimals { get; internal set; } public BigInteger GasLimit { get; internal set; } public BigInteger GasPrice { get; internal set; } diff --git a/dotnet/ILogger.cs b/dotnet/ILogger.cs index 10984b8..ec4be57 100644 --- a/dotnet/ILogger.cs +++ b/dotnet/ILogger.cs @@ -1,7 +1,7 @@ -namespace EhterDelta.Bots.Dontnet +namespace EhterDelta.Bots.Dontnet { public interface ILogger { void Log(string message); - } + } } \ No newline at end of file diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index 4f97a45..30ea2aa 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -1,9 +1,8 @@ +using Nethereum.Util; using System; -using System.Numerics; -using System.Linq; using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; -using Nethereum.Util; namespace EhterDelta.Bots.Dontnet { @@ -20,7 +19,6 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi var sellOrdersToPlace = ordersPerSide - Service.MyOrders.Sells.Count(); var buyVolumeToPlace = EtherDeltaETH; var sellVolumeToPlace = EtherDeltaToken; - var bestBuy = Service.GetBestAvailableBuy(); var bestSell = Service.GetBestAvailableSell(); @@ -57,6 +55,7 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi Console.WriteLine(ex); } } + for (var i = 0; i < buyOrdersToPlace; i += 1) { var price = midMarket - ((i + 1) * midMarket * 0.05m); @@ -73,14 +72,13 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi } } - var orderTasks = new List(); orders.ForEach(order => { - orderTasks.Add(Service.TakeOrder(order, 1)); + var amount = order.TokenGive == Service.ZeroToken ? order.AmountGet : order.AmountGive; + orderTasks.Add(Service.TakeOrder(order, amount)); }); - try { Task.WaitAll(orderTasks.ToArray()); diff --git a/dotnet/Message.cs b/dotnet/Message.cs index ab25dab..829b1d7 100644 --- a/dotnet/Message.cs +++ b/dotnet/Message.cs @@ -1,7 +1,7 @@ -using Newtonsoft.Json; -using Newtonsoft.Json.Linq; - -namespace EhterDelta.Bots.Dontnet +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +namespace EhterDelta.Bots.Dontnet { internal class Message { @@ -50,5 +50,5 @@ internal static Message ParseMessage(string messageString) return message; } - } + } } \ No newline at end of file diff --git a/dotnet/OrderType.cs b/dotnet/OrderType.cs index a39c766..4964d20 100644 --- a/dotnet/OrderType.cs +++ b/dotnet/OrderType.cs @@ -1,8 +1,8 @@ -namespace EhterDelta.Bots.Dontnet +namespace EhterDelta.Bots.Dontnet { internal enum OrderType { Buy, Sell - } + } } \ No newline at end of file diff --git a/dotnet/Orders.cs b/dotnet/Orders.cs index 7a38926..db69940 100644 --- a/dotnet/Orders.cs +++ b/dotnet/Orders.cs @@ -1,9 +1,8 @@ using Nethereum.Hex.HexTypes; -using System.Collections.Generic; -using System.Numerics; using Newtonsoft.Json.Linq; using System; -using Nethereum.Hex.HexConvertors.Extensions; +using System.Collections.Generic; +using System.Numerics; namespace EhterDelta.Bots.Dontnet { @@ -48,10 +47,7 @@ internal static Order FromJson(JToken jtoken) order.S = jtoken.Value("s"); order.Raw = jtoken.ToString(); } - catch - { - - } + catch { } return order; } diff --git a/dotnet/Service.cs b/dotnet/Service.cs index f9aa96d..edff647 100644 --- a/dotnet/Service.cs +++ b/dotnet/Service.cs @@ -1,5 +1,10 @@ +using Nethereum.ABI.FunctionEncoding; +using Nethereum.ABI.Model; using Nethereum.Contracts; -using Nethereum.Util; +using Nethereum.Hex.HexConvertors.Extensions; +using Nethereum.Hex.HexTypes; +using Nethereum.RPC.Eth.DTOs; +using Nethereum.Signer; using Nethereum.Web3; using Newtonsoft.Json.Linq; using System; @@ -9,21 +14,12 @@ using System.Numerics; using System.Threading.Tasks; using WebSocket4Net; -using System.Text; -using Nethereum.ABI; -using Nethereum.Hex.HexConvertors.Extensions; -using Nethereum.RPC.Eth.DTOs; -using Nethereum.Hex.HexTypes; -using Nethereum.ABI.FunctionEncoding; -using Nethereum.ABI.Model; -using Nethereum.Signer; -using Nethereum.ABI.Encoders; namespace EhterDelta.Bots.Dontnet { public class Service { - private const string ZeroToken = "0x0000000000000000000000000000000000000000"; + public const string ZeroToken = "0x0000000000000000000000000000000000000000"; private WebSocket socket; const int socketTimeout = 20000; private ILogger logger; diff --git a/dotnet/Taker.cs b/dotnet/Taker.cs index 9b127e8..2e297f1 100644 --- a/dotnet/Taker.cs +++ b/dotnet/Taker.cs @@ -1,5 +1,5 @@ -using System; using Nethereum.Util; +using System; namespace EhterDelta.Bots.Dontnet { diff --git a/dotnet/Trade.cs b/dotnet/Trade.cs index 1dacee4..62ba879 100644 --- a/dotnet/Trade.cs +++ b/dotnet/Trade.cs @@ -1,5 +1,5 @@ -using System; using Newtonsoft.Json.Linq; +using System; namespace EhterDelta.Bots.Dontnet { From f937ada8048729e51cfaa8c94ba66d64b1f20120 Mon Sep 17 00:00:00 2001 From: stojce Date: Sat, 9 Dec 2017 11:58:35 +0100 Subject: [PATCH 15/15] maker print error --- dotnet/Maker.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/dotnet/Maker.cs b/dotnet/Maker.cs index 30ea2aa..e510097 100644 --- a/dotnet/Maker.cs +++ b/dotnet/Maker.cs @@ -52,7 +52,9 @@ public Maker(EtherDeltaConfiguration config, ILogger logger = null) : base(confi } catch (Exception ex) { - Console.WriteLine(ex); + Console.ForegroundColor = ConsoleColor.Red; + Console.WriteLine(ex.Message); + Console.ResetColor(); } }