├── .gitignore ├── README.md ├── screenshots ├── EditBotsDialog.png ├── EditDealsDialog.png ├── InProgress.png ├── MainscreenBots.png ├── MainscreenDeals.png └── ManageAccounts.png └── src ├── 3Commas.BulkEditor.sln └── 3Commas.BulkEditor ├── 3Commas.BulkEditor.csproj ├── App.config ├── Infrastructure ├── Container.cs ├── IKeyStore.cs ├── IMessageBoxService.cs ├── IViewBase.cs ├── KeyStore.cs ├── KeysChangedEventArgs.cs ├── MessageBoxService.cs └── Presenter.cs ├── Misc ├── AssemblyHelper.cs ├── BotWithExchangeInfo.cs ├── ComboBoxItem.cs ├── ControlHelper.cs ├── DealWithExchangeInfo.cs ├── Extensions.cs ├── TextBoxLogger.cs ├── XCommasAccount.cs ├── XCommasAccounts.cs └── XCommasLayer.cs ├── Program.cs ├── Properties ├── AssemblyInfo.cs ├── Resources.Designer.cs ├── Resources.resx ├── Settings.Designer.cs ├── Settings.settings └── app.manifest ├── Resources ├── 3Commas.png ├── AddItem_16x16.png ├── AddNewDataSource_16x16.png ├── AddNewDataSource_16x161.png ├── AddNewDataSource_16x162.png ├── Add_16x16.png ├── Add_16x161.png ├── Cancel_16x16.png ├── Clear_16x16.png ├── Close_16x16.png ├── Convert_16x16.png ├── Copy_16x16.png ├── Currency_16x16.png ├── Currency_32x32.png ├── DeleteDataSource_16x16.png ├── Delete_16x16.png ├── Delete_16x161.png ├── EditDataSource_16x16.png ├── EditDataSource_16x161.png ├── Edit_16x16.png ├── Edit_16x161.png ├── Export_16x16.png ├── Financial_16x16.png ├── Hide_16x16.png ├── Hide_32x32.png ├── Info_16x16.png ├── Info_16x161.png ├── Properties_16x16.png ├── Warning_16x16.png ├── download.png ├── loader.gif ├── loader2.gif └── loader4.gif ├── Views ├── AboutBox │ ├── AboutBox.Designer.cs │ ├── AboutBox.cs │ └── AboutBox.resx ├── AddFundsDialog │ ├── AddFundsDialog.Designer.cs │ ├── AddFundsDialog.cs │ ├── AddFundsDialog.resx │ └── AddFundsDto.cs ├── BaseControls │ ├── EntityTableControl.Designer.cs │ ├── EntityTableControl.cs │ ├── EntityTableControl.resx │ └── IsBusyEventArgs.cs ├── ChooseSignal │ ├── ChooseSignal.Designer.cs │ ├── ChooseSignal.cs │ └── ChooseSignal.resx ├── CopyBotDialog │ ├── AccountViewModel.cs │ ├── CopyBotDialog.Designer.cs │ ├── CopyBotDialog.cs │ └── CopyBotDialog.resx ├── EditBotDialog │ ├── EditBotDialog.Designer.cs │ ├── EditBotDialog.cs │ ├── EditBotDialog.resx │ └── EditDto.cs ├── EditDealDialog │ ├── EditDealDialog.Designer.cs │ ├── EditDealDialog.cs │ ├── EditDealDialog.resx │ └── EditDealDto.cs ├── EditGridBotDialog │ ├── EditGridBotDialog.Designer.cs │ ├── EditGridBotDialog.cs │ ├── EditGridBotDialog.resx │ └── EditGridBotDto.cs ├── MainForm │ ├── IMainForm.cs │ ├── MainForm.Designer.cs │ ├── MainForm.cs │ ├── MainForm.resx │ └── MainFormPresenter.cs ├── ManageBotControl │ ├── BotTableControl.cs │ ├── BotTableControl.resx │ ├── BotViewModel.cs │ ├── ManageBotControl.Designer.cs │ ├── ManageBotControl.cs │ └── ManageBotControl.resx ├── ManageDealControl │ ├── DealTableControl.cs │ ├── DealTableControl.resx │ ├── DealViewModel.cs │ ├── ManageDealControl.Designer.cs │ ├── ManageDealControl.cs │ └── ManageDealControl.resx ├── ManageGridBotControl │ ├── GridBotTableControl.cs │ ├── GridBotTableControl.resx │ ├── GridBotViewModel.cs │ ├── ManageGridBotControl.Designer.cs │ ├── ManageGridBotControl.cs │ └── ManageGridBotControl.resx ├── ProgressView │ ├── ProgressView.Designer.cs │ ├── ProgressView.cs │ └── ProgressView.resx └── Settings │ ├── AddAccountDialog.Designer.cs │ ├── AddAccountDialog.cs │ ├── AddAccountDialog.resx │ ├── Settings.Designer.cs │ ├── Settings.cs │ └── Settings.resx ├── packages.config └── robot.ico /README.md: -------------------------------------------------------------------------------- 1 | # 3Commas.BulkEditor 2 | 3 | This unofficial tool allows you to bulk edit deals and bots (DCA & Grid) of multiple 3Commas Accounts 4 | 5 | 6 | ## Technical description 7 | 8 | The implementation is based on .Net Framework. 9 | 10 | Implementation is build upon the AdvancedDataGridView and 3Commas.Net library. Thanks for the brilliant work! 11 | 12 | If you need something, [let me know](https://github.com/MarcDrexler/3Commas.BulkEditor/issues). 13 | 14 | Also if you think something is broken or have any questions, please open an [Issue](https://github.com/MarcDrexler/3Commas.BulkEditor/issues). 15 | 16 | 17 | ## Features 18 | 19 | - Add multiple 3Commas Accounts 20 | - Bots 21 | - View all of your DCA and Grid bots 22 | - Filtering, sorting, etc 23 | - Stop All Bots 24 | - Bulk Edit 25 | - Bulk Copy 26 | - Bulk Delete 27 | - Deals 28 | - View all of your deals 29 | - Filtering, sorting, etc 30 | - Bulk Edit 31 | - Bulk Enable/Disable TTP 32 | - Bulk Cancel 33 | - Bulk Panic Sell 34 | - Bulk Add Funds 35 | 36 | ## Screenshots 37 | 38 | ![Manage Accounts](https://github.com/MarcDrexler/3Commas.BulkEditor/blob/master/screenshots/ManageAccounts.png) 39 | 40 | ![Main Screen Bots](https://github.com/MarcDrexler/3Commas.BulkEditor/blob/master/screenshots/MainscreenBots.png) 41 | 42 | ![Edit Bots Dialog](https://github.com/MarcDrexler/3Commas.BulkEditor/blob/master/screenshots/EditBotsDialog.png) 43 | 44 | ![Main Screen Deals](https://github.com/MarcDrexler/3Commas.BulkEditor/blob/master/screenshots/MainscreenDeals.png) 45 | 46 | ![Edit Deals Dialog](https://github.com/MarcDrexler/3Commas.BulkEditor/blob/master/screenshots/EditDealsDialog.png) 47 | 48 | ![In Progress Dialog](https://github.com/MarcDrexler/3Commas.BulkEditor/blob/master/screenshots/InProgress.png) 49 | 50 | ## Prerequisites 51 | 52 | - Windows 10 53 | - .NET Framework 4.7.2 (which already might be installed on your Windows machine) 54 | - 3Commas API key and secret 55 | 56 | **Note:** By default, API keys are not stored on your computer and must be entered again the next time the application is started. There is an option to persist ApiKey and Secret. However, use is at your own risk. Other programs could read this information. 57 | 58 | ## Installer 59 | 60 | I use MS ClickOnce for installation and updates. 61 | 62 | An installer with the current version is hosted [here](https://marcdrexler.blob.core.windows.net/bulkeditor/BulkEditor.application) 63 | 64 | Updates are automatically checked for each start. 65 | 66 | Because the package is not signed with a public certificate, you might see some security warnings when installing and starting the app. 67 | 68 | ## Support 69 | 70 | I develop and maintain this package on my own for free in my spare time. 71 | Donations are greatly appreciated and a motivation to keep improving. 72 | 73 | XMR: 89rmrxDAGAWWhSZXhnNf335qYfyXz4vQsNAM1VFSg6Y7Tve9BGF9pwte9ps61E9FY76r4onhWw7e19eu7fM8BARQMRHNBt7 74 | 75 | or 76 | 77 | Buy Me A Coffee 78 | 79 | Best used with [Binance](https://www.binance.com/en/register?ref=37132298) and [3Commas](https://3commas.io/?c=tc240413) :v: 80 | 81 | -------------------------------------------------------------------------------- /screenshots/EditBotsDialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/screenshots/EditBotsDialog.png -------------------------------------------------------------------------------- /screenshots/EditDealsDialog.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/screenshots/EditDealsDialog.png -------------------------------------------------------------------------------- /screenshots/InProgress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/screenshots/InProgress.png -------------------------------------------------------------------------------- /screenshots/MainscreenBots.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/screenshots/MainscreenBots.png -------------------------------------------------------------------------------- /screenshots/MainscreenDeals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/screenshots/MainscreenDeals.png -------------------------------------------------------------------------------- /screenshots/ManageAccounts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/screenshots/ManageAccounts.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio Version 16 4 | VisualStudioVersion = 16.0.30406.217 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "3Commas.BulkEditor", "3Commas.BulkEditor\3Commas.BulkEditor.csproj", "{02D16940-5926-45EA-A706-21B8D3E1F643}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | EndGlobalSection 13 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 14 | {02D16940-5926-45EA-A706-21B8D3E1F643}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 15 | {02D16940-5926-45EA-A706-21B8D3E1F643}.Debug|Any CPU.Build.0 = Debug|Any CPU 16 | {02D16940-5926-45EA-A706-21B8D3E1F643}.Release|Any CPU.ActiveCfg = Release|Any CPU 17 | {02D16940-5926-45EA-A706-21B8D3E1F643}.Release|Any CPU.Build.0 = Release|Any CPU 18 | EndGlobalSection 19 | GlobalSection(SolutionProperties) = preSolution 20 | HideSolutionNode = FALSE 21 | EndGlobalSection 22 | GlobalSection(ExtensibilityGlobals) = postSolution 23 | SolutionGuid = {62584358-3810-4548-BCD9-DC2AB25F5DDC} 24 | EndGlobalSection 25 | EndGlobal 26 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 |
6 | 7 | 8 | 9 | 10 | 11 | 12 | <_3Commas.BulkEditor.Properties.Settings> 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Infrastructure/Container.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using _3Commas.BulkEditor.Views.CopyBotDialog; 4 | using M.EventBroker; 5 | using M.EventBroker.EvenHandlerRunners; 6 | using Microsoft.Extensions.Logging; 7 | 8 | namespace _3Commas.BulkEditor.Infrastructure 9 | { 10 | public static class ObjectContainer 11 | { 12 | public static IMessageBoxService MessageBoxService { get; } = new MessageBoxService(); 13 | public static ILogger Logger { get; set; } 14 | public static IEventBroker EventBroker { get; set; } = new EventBroker(new UnrestrictedThreadPoolRunner()); 15 | public static IKeyStore KeyManager { get; set; } = new KeyStore(); 16 | 17 | public static class Cache 18 | { 19 | public static void SetAccounts(List accounts) 20 | { 21 | Accounts = accounts; 22 | } 23 | 24 | public static List Accounts { get; private set; } = new List(); 25 | 26 | public static void SetPairs(List pairs) 27 | { 28 | Pairs = pairs.OrderBy(x => x).ToList(); 29 | } 30 | 31 | public static List Pairs { get; private set; } = new List(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Infrastructure/IKeyStore.cs: -------------------------------------------------------------------------------- 1 | using _3Commas.BulkEditor.Misc; 2 | 3 | namespace _3Commas.BulkEditor.Infrastructure 4 | { 5 | public interface IKeyStore 6 | { 7 | XCommasAccounts Read(); 8 | void Save(XCommasAccounts accounts); 9 | void Clear(); 10 | } 11 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Infrastructure/IMessageBoxService.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace _3Commas.BulkEditor.Infrastructure 4 | { 5 | public interface IMessageBoxService 6 | { 7 | DialogResult ShowError(string text, string title = "Error"); 8 | DialogResult ShowQuestion(string text); 9 | DialogResult ShowInformation(string text); 10 | } 11 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Infrastructure/IViewBase.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace _3Commas.BulkEditor.Infrastructure 4 | { 5 | public interface IViewBase : IWin32Window 6 | { 7 | } 8 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Infrastructure/KeyStore.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Text; 3 | using _3Commas.BulkEditor.Misc; 4 | using Microsoft.Extensions.Logging; 5 | using Newtonsoft.Json; 6 | 7 | namespace _3Commas.BulkEditor.Infrastructure 8 | { 9 | public class KeyStore : IKeyStore 10 | { 11 | public XCommasAccounts Read() 12 | { 13 | var result = new XCommasAccounts(); 14 | try 15 | { 16 | var accounts = Properties.Settings.Default.Keys; 17 | if (!string.IsNullOrWhiteSpace(accounts)) 18 | { 19 | byte[] byteArray = Convert.FromBase64String(accounts); 20 | string jsonBack = Encoding.UTF8.GetString(byteArray); 21 | result = JsonConvert.DeserializeObject(jsonBack); 22 | } 23 | } 24 | catch (Exception e) 25 | { 26 | ObjectContainer.Logger?.LogError($"Error while reading accounts: {e}"); 27 | } 28 | return result; 29 | } 30 | 31 | public void Save(XCommasAccounts accounts) 32 | { 33 | string json = JsonConvert.SerializeObject(accounts); 34 | string base64EncodedAccounts = Convert.ToBase64String(Encoding.UTF8.GetBytes(json)); 35 | Properties.Settings.Default.Keys = base64EncodedAccounts; 36 | Properties.Settings.Default.Save(); 37 | } 38 | 39 | public void Clear() 40 | { 41 | if (!string.IsNullOrWhiteSpace(Properties.Settings.Default.Keys)) 42 | { 43 | Properties.Settings.Default.Keys = ""; 44 | Properties.Settings.Default.Save(); 45 | } 46 | } 47 | } 48 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Infrastructure/KeysChangedEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using _3Commas.BulkEditor.Misc; 3 | 4 | namespace _3Commas.BulkEditor.Infrastructure 5 | { 6 | public class KeysChangedEventArgs : EventArgs 7 | { 8 | public XCommasAccounts Keys { get; set; } 9 | } 10 | 11 | public class StopAllBotsEventArgs : EventArgs 12 | { 13 | } 14 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Infrastructure/MessageBoxService.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace _3Commas.BulkEditor.Infrastructure 4 | { 5 | public class MessageBoxService : IMessageBoxService 6 | { 7 | public DialogResult ShowError(string text, string title = "Error") 8 | { 9 | return MessageBox.Show(Form.ActiveForm, text, title, MessageBoxButtons.OK, MessageBoxIcon.Error); 10 | } 11 | 12 | public DialogResult ShowQuestion(string text) 13 | { 14 | return MessageBox.Show(Form.ActiveForm, text, "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question); 15 | } 16 | 17 | public DialogResult ShowInformation(string text) 18 | { 19 | return MessageBox.Show(Form.ActiveForm, text, "Information", MessageBoxButtons.OK, MessageBoxIcon.Information); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Infrastructure/Presenter.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | 3 | namespace _3Commas.BulkEditor.Infrastructure 4 | { 5 | public abstract class PresenterBase where TView: IWin32Window 6 | { 7 | protected PresenterBase(TView view) 8 | { 9 | View = view; 10 | } 11 | 12 | public TView View { get; set; } 13 | } 14 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Misc/AssemblyHelper.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | 3 | namespace _3Commas.BulkEditor.Misc 4 | { 5 | public static class AssemblyHelper 6 | { 7 | public static string AssemblyTitle 8 | { 9 | get 10 | { 11 | var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false); 12 | if (attributes.Length > 0) 13 | { 14 | var titleAttribute = (AssemblyTitleAttribute)attributes[0]; 15 | if (titleAttribute.Title != "") 16 | { 17 | return titleAttribute.Title; 18 | } 19 | } 20 | return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase); 21 | } 22 | } 23 | 24 | public static string AssemblyVersion => Assembly.GetExecutingAssembly().GetName().Version.ToString(); 25 | 26 | public static string AssemblyDescription 27 | { 28 | get 29 | { 30 | var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false); 31 | return attributes.Length == 0 ? "" : ((AssemblyDescriptionAttribute)attributes[0]).Description; 32 | } 33 | } 34 | 35 | public static string AssemblyProduct 36 | { 37 | get 38 | { 39 | var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false); 40 | return attributes.Length == 0 ? "" : ((AssemblyProductAttribute)attributes[0]).Product; 41 | } 42 | } 43 | 44 | public static string AssemblyCopyright 45 | { 46 | get 47 | { 48 | var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false); 49 | return attributes.Length == 0 ? "" : ((AssemblyCopyrightAttribute)attributes[0]).Copyright; 50 | } 51 | } 52 | 53 | public static string AssemblyCompany 54 | { 55 | get 56 | { 57 | var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false); 58 | return attributes.Length == 0 ? "" : ((AssemblyCompanyAttribute)attributes[0]).Company; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Misc/BotWithExchangeInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using XCommas.Net.Objects; 3 | 4 | namespace _3Commas.BulkEditor.Misc 5 | { 6 | public class BotWithExchangeInfo 7 | { 8 | public Guid XCommasAccount { get; set; } 9 | public string XCommasAccountName { get; set; } 10 | public Bot Bot { get; set; } 11 | 12 | public BotWithExchangeInfo(Guid xCommasAccount, string xCommasAccountName, Bot bot) 13 | { 14 | XCommasAccount = xCommasAccount; 15 | XCommasAccountName = xCommasAccountName; 16 | Bot = bot; 17 | } 18 | } 19 | 20 | public class GridBotWithExchangeInfo 21 | { 22 | public Guid XCommasAccount { get; set; } 23 | public string XCommasAccountName { get; set; } 24 | public GridBot Bot { get; set; } 25 | 26 | public GridBotWithExchangeInfo(Guid xCommasAccount, string xCommasAccountName, GridBot bot) 27 | { 28 | XCommasAccount = xCommasAccount; 29 | XCommasAccountName = xCommasAccountName; 30 | Bot = bot; 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Misc/ComboBoxItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace _3Commas.BulkEditor.Misc 4 | { 5 | public class ComboBoxItem 6 | { 7 | public ComboBoxItem(Enum enumValue, string displayString) 8 | { 9 | EnumValue = enumValue; 10 | Text = displayString; 11 | } 12 | 13 | public Enum EnumValue { get; } 14 | public string Text { get; set; } 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Misc/ControlHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | 4 | namespace _3Commas.BulkEditor.Misc 5 | { 6 | public static class ControlHelper 7 | { 8 | public static void AddValuesToCombobox(ComboBox comboBox, TEnum defaultValue) 9 | { 10 | AddValuesToCombobox(comboBox); 11 | comboBox.Text = defaultValue.ToString(); 12 | } 13 | 14 | public static void AddValuesToCombobox(ComboBox comboBox) 15 | { 16 | foreach (TEnum time in (TEnum[])Enum.GetValues(typeof(TEnum))) 17 | { 18 | comboBox.Items.Add(time.ToString()); 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Misc/DealWithExchangeInfo.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using XCommas.Net.Objects; 3 | 4 | namespace _3Commas.BulkEditor.Misc 5 | { 6 | public class DealWithExchangeInfo 7 | { 8 | public Guid XCommasAccount { get; set; } 9 | public string XCommasAccountName { get; set; } 10 | public Deal Deal { get; set; } 11 | 12 | public DealWithExchangeInfo(Guid xCommasAccount, string xCommasAccountName, Deal deal) 13 | { 14 | XCommasAccount = xCommasAccount; 15 | XCommasAccountName = xCommasAccountName; 16 | Deal = deal; 17 | } 18 | } 19 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Misc/Extensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading.Tasks; 3 | using System.Windows.Forms; 4 | using XCommas.Net.Objects; 5 | 6 | namespace _3Commas.BulkEditor.Misc 7 | { 8 | public static class Extensions 9 | { 10 | public static string ToHumanReadableString(this BotStrategy strategy) 11 | { 12 | switch (strategy) 13 | { 14 | case RsiBotStrategy rsiBotStrategy: 15 | return $"RSI {rsiBotStrategy.Options.Time.ToHumanReadableString()} {rsiBotStrategy.Options.Points}"; 16 | case ManualStrategy manualStrategy: 17 | return "Manual"; 18 | case QflBotStrategy qflBotStrategy: 19 | return $"QFL {qflBotStrategy.Options.Type} {qflBotStrategy.Options.Percent}%"; 20 | case NonStopBotStrategy nonStopBotStrategy: 21 | return "NonStop"; 22 | case UltBotStrategy ultBotStrategy: 23 | return $"ULT {ultBotStrategy.Options.Time.ToHumanReadableString()} {ultBotStrategy.Options.Points}"; 24 | case TradingViewBotStrategy tradingViewBotStrategy: 25 | return $"TradingView {tradingViewBotStrategy.Options.Type} {tradingViewBotStrategy.Options.Time.ToHumanReadableString()}"; 26 | case TaPresetsBotStrategy taPresetsBotStrategy: 27 | return $"{taPresetsBotStrategy.Name} {taPresetsBotStrategy.Options.Type} {taPresetsBotStrategy.Options.Time.ToHumanReadableString()}"; 28 | case CqsPremiumBotStrategy cqsPremiumBotStrategy: 29 | case CqsTelegramBotStrategy cqsTelegramBotStrategy: 30 | case UnknownStrategy unknownStrategy: 31 | return strategy.Name; 32 | default: 33 | throw new ArgumentOutOfRangeException(nameof(strategy)); 34 | } 35 | } 36 | 37 | private static string ToHumanReadableString(this IndicatorTime time) 38 | { 39 | switch (time) 40 | { 41 | case IndicatorTime.ThreeMinutes: 42 | return "3m"; 43 | case IndicatorTime.FiveMinutes: 44 | return "5m"; 45 | case IndicatorTime.FifteenMinutes: 46 | return "15m"; 47 | case IndicatorTime.ThirtyMinutes: 48 | return "30m"; 49 | case IndicatorTime.OneHour: 50 | return "1h"; 51 | case IndicatorTime.TwoHours: 52 | return "2h"; 53 | case IndicatorTime.FourHours: 54 | return "4h"; 55 | default: 56 | throw new ArgumentOutOfRangeException(nameof(time), time, null); 57 | } 58 | } 59 | 60 | private static string ToHumanReadableString(this TradingViewTime time) 61 | { 62 | switch (time) 63 | { 64 | case TradingViewTime.OneMinute: 65 | return "1min"; 66 | case TradingViewTime.FiveMinutes: 67 | return "5min"; 68 | case TradingViewTime.FifteenMinutes: 69 | return "15min"; 70 | case TradingViewTime.OneHour: 71 | return "1h"; 72 | case TradingViewTime.FourHours: 73 | return "4h"; 74 | case TradingViewTime.OneDay: 75 | return "1d"; 76 | case TradingViewTime.OneWeek: 77 | return "1w"; 78 | case TradingViewTime.OneMonth: 79 | return "1month"; 80 | case TradingViewTime.Cumulative: 81 | return "Cumulative"; 82 | default: 83 | throw new ArgumentOutOfRangeException(nameof(time), time, null); 84 | } 85 | } 86 | 87 | public static void RunInUiThread(this UserControl control, Func func) 88 | { 89 | if (control.InvokeRequired) 90 | { 91 | control.Invoke(new MethodInvoker(async delegate 92 | { 93 | await func.Invoke(); 94 | })); 95 | } 96 | } 97 | 98 | public static void RunInUiThread(this UserControl control, Action func) 99 | { 100 | if (control.InvokeRequired) 101 | { 102 | control.Invoke(new MethodInvoker(func.Invoke)); 103 | } 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Misc/TextBoxLogger.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using Microsoft.Extensions.Logging; 4 | using _3Commas.BulkEditor.Misc; 5 | 6 | namespace _3Commas.BulkEditor.Misc 7 | { 8 | internal class TextBoxLogger : ILogger 9 | { 10 | private readonly TextBox _txtOutput; 11 | 12 | public TextBoxLogger(TextBox txtOutput) 13 | { 14 | this._txtOutput = txtOutput; 15 | } 16 | 17 | public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) 18 | { 19 | string message = ""; 20 | if (formatter != null) 21 | { 22 | message += formatter(state, exception); 23 | } 24 | 25 | if (_txtOutput.InvokeRequired) 26 | { 27 | _txtOutput.BeginInvoke(new MethodInvoker(() => 28 | { 29 | _txtOutput.AppendText($"{DateTime.Now} {logLevel}: {message}{Environment.NewLine}"); 30 | })); 31 | } 32 | else 33 | { 34 | _txtOutput.AppendText($"{DateTime.Now} {logLevel}: {message}{Environment.NewLine}"); 35 | } 36 | } 37 | 38 | public bool IsEnabled(LogLevel logLevel) 39 | { 40 | return true; 41 | } 42 | 43 | public IDisposable BeginScope(TState state) 44 | { 45 | return new NoopDisposable(); 46 | } 47 | 48 | private class NoopDisposable : IDisposable 49 | { 50 | public void Dispose() 51 | { 52 | } 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Misc/XCommasAccount.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace _3Commas.BulkEditor.Misc 4 | { 5 | [Serializable] 6 | public class XCommasAccount 7 | { 8 | public Guid Id { get; set; } = Guid.NewGuid(); 9 | public string Name { get; set; } 10 | public string ApiKey { get; set; } 11 | public string Secret { get; set; } 12 | } 13 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Misc/XCommasAccounts.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | 5 | namespace _3Commas.BulkEditor.Misc 6 | { 7 | [Serializable] 8 | public class XCommasAccounts 9 | { 10 | public List Accounts { get; set; } = new List(); 11 | 12 | public bool IsEmpty => !Accounts.Any(); 13 | } 14 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Configuration; 3 | using System.Windows.Forms; 4 | using _3Commas.BulkEditor.Views.MainForm; 5 | 6 | namespace _3Commas.BulkEditor 7 | { 8 | static class Program 9 | { 10 | /// 11 | /// The main entry point for the application. 12 | /// 13 | [STAThread] 14 | static void Main() 15 | { 16 | Application.EnableVisualStyles(); 17 | Application.SetCompatibleTextRenderingDefault(false); 18 | EncryptConfigFile(); 19 | 20 | try 21 | { 22 | Application.Run(new MainForm()); 23 | } 24 | catch (Exception e) 25 | { 26 | MessageBox.Show("Sorry, but something went wrong!" + Environment.NewLine + Environment.NewLine + 27 | "Please let me know that there was a problem and I will try to fix it for you. You can report this error here: " + 28 | "https://github.com/MarcDrexler/3Commas.BulkEditor/issues" + Environment.NewLine + Environment.NewLine + 29 | "Error Details: " + Environment.NewLine + 30 | e.ToString(), "Sorry!", MessageBoxButtons.OK, MessageBoxIcon.Error); 31 | } 32 | } 33 | 34 | private static void EncryptConfigFile() 35 | { 36 | try 37 | { 38 | System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal); 39 | ConfigurationSection section = config.GetSection("userSettings/_3Commas.BulkEditor.Properties.Settings"); 40 | if (!section.SectionInformation.IsProtected) 41 | { 42 | section.SectionInformation.ProtectSection("RsaProtectedConfigurationProvider"); 43 | section.SectionInformation.ForceSave = true; 44 | config.Save(ConfigurationSaveMode.Full); 45 | } 46 | } 47 | catch 48 | { 49 | // ignore 50 | } 51 | } 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Bulk Editor")] 8 | [assembly: AssemblyDescription("Bulk Editor for 3Commas DCA+Grid Bots & Deals")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("Bulk Editor")] 12 | [assembly: AssemblyCopyright("Copyright © 2021")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("02d16940-5926-45ea-a706-21b8d3e1f643")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.31.0.0")] 35 | [assembly: AssemblyFileVersion("1.31.0.0")] 36 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace _3Commas.BulkEditor.Properties { 12 | 13 | 14 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 15 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")] 16 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { 17 | 18 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 19 | 20 | public static Settings Default { 21 | get { 22 | return defaultInstance; 23 | } 24 | } 25 | 26 | [global::System.Configuration.UserScopedSettingAttribute()] 27 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 28 | [global::System.Configuration.DefaultSettingValueAttribute("")] 29 | public string ApiKey3Commas { 30 | get { 31 | return ((string)(this["ApiKey3Commas"])); 32 | } 33 | set { 34 | this["ApiKey3Commas"] = value; 35 | } 36 | } 37 | 38 | [global::System.Configuration.UserScopedSettingAttribute()] 39 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 40 | [global::System.Configuration.DefaultSettingValueAttribute("")] 41 | public string Secret3Commas { 42 | get { 43 | return ((string)(this["Secret3Commas"])); 44 | } 45 | set { 46 | this["Secret3Commas"] = value; 47 | } 48 | } 49 | 50 | [global::System.Configuration.UserScopedSettingAttribute()] 51 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 52 | [global::System.Configuration.DefaultSettingValueAttribute("")] 53 | public string Keys { 54 | get { 55 | return ((string)(this["Keys"])); 56 | } 57 | set { 58 | this["Keys"] = value; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Properties/app.manifest: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 48 | 55 | 56 | 70 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/3Commas.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/3Commas.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/AddItem_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/AddItem_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/AddNewDataSource_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/AddNewDataSource_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/AddNewDataSource_16x161.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/AddNewDataSource_16x161.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/AddNewDataSource_16x162.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/AddNewDataSource_16x162.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Add_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Add_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Add_16x161.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Add_16x161.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Cancel_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Cancel_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Clear_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Clear_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Close_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Close_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Convert_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Convert_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Copy_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Copy_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Currency_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Currency_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Currency_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Currency_32x32.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/DeleteDataSource_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/DeleteDataSource_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Delete_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Delete_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Delete_16x161.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Delete_16x161.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/EditDataSource_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/EditDataSource_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/EditDataSource_16x161.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/EditDataSource_16x161.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Edit_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Edit_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Edit_16x161.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Edit_16x161.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Export_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Export_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Financial_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Financial_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Hide_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Hide_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Hide_32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Hide_32x32.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Info_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Info_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Info_16x161.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Info_16x161.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Properties_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Properties_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/Warning_16x16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/Warning_16x16.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/download.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/download.png -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/loader.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/loader.gif -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/loader2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/loader2.gif -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Resources/loader4.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/Resources/loader4.gif -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/AboutBox/AboutBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Diagnostics.CodeAnalysis; 4 | using System.Windows.Forms; 5 | using _3Commas.BulkEditor.Misc; 6 | 7 | namespace _3Commas.BulkEditor.Views.AboutBox 8 | { 9 | [SuppressMessage("ReSharper", "LocalizableElement")] 10 | sealed partial class AboutBox : Form 11 | { 12 | public AboutBox() 13 | { 14 | InitializeComponent(); 15 | 16 | this.Text = $"About {AssemblyHelper.AssemblyTitle}"; 17 | this.labelProductName.Text = AssemblyHelper.AssemblyProduct; 18 | this.labelVersion.Text = $"Version {AssemblyHelper.AssemblyVersion}"; 19 | this.textBoxDescription.Text = AssemblyHelper.AssemblyDescription; 20 | } 21 | 22 | private void pbBuyMeACoffee_Click(object sender, EventArgs e) 23 | { 24 | Process.Start("https://www.buymeacoffee.com/marcdrexler"); 25 | } 26 | 27 | private void linkGithubProject_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 28 | { 29 | Process.Start("https://github.com/MarcDrexler/3Commas.BulkEditor/issues/new"); 30 | } 31 | 32 | private void linkLabelChangelog_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) 33 | { 34 | Process.Start("https://github.com/MarcDrexler/3Commas.BulkEditor/releases"); 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/AboutBox/AboutBox.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/AddFundsDialog/AddFundsDialog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using _3Commas.BulkEditor.Infrastructure; 6 | using _3Commas.BulkEditor.Misc; 7 | using _3Commas.BulkEditor.Views.EditDealDialog; 8 | using XCommas.Net.Objects; 9 | 10 | namespace _3Commas.BulkEditor.Views.AddFundsDialog 11 | { 12 | public partial class AddFundsDialog : Form 13 | { 14 | private readonly IMessageBoxService _mbs = new MessageBoxService(); 15 | 16 | public AddFundsDialog() 17 | { 18 | InitializeComponent(); 19 | } 20 | 21 | public AddFundsDto EditDto { get; set; } = new AddFundsDto(); 22 | 23 | private void btnCreate_Click(object sender, EventArgs e) 24 | { 25 | if (IsValid()) 26 | { 27 | if (radioBtc.Checked) EditDto.QtyInBTC = (decimal)numQtyBtc.Value; 28 | if (radioUsdt.Checked) EditDto.QtyInUSD = (decimal)numQtyUsdt.Value; 29 | this.DialogResult = DialogResult.OK; 30 | } 31 | } 32 | 33 | private bool IsValid() 34 | { 35 | var errors = new List(); 36 | 37 | if (radioBtc.Checked && numQtyBtc.Value < 0) errors.Add("Amount in BTC missing."); 38 | if (radioUsdt.Checked && numQtyUsdt.Value < 0) errors.Add("Amount in USD missing."); 39 | 40 | if (errors.Any()) 41 | { 42 | _mbs.ShowError(String.Join(Environment.NewLine, errors), "Validation Error"); 43 | } 44 | 45 | return !errors.Any(); 46 | } 47 | 48 | private void radioUsdt_CheckedChanged(object sender, EventArgs e) 49 | { 50 | lblUsdt.Visible = sender == radioUsdt && radioUsdt.Checked; 51 | numQtyUsdt.Visible = sender == radioUsdt && radioUsdt.Checked; 52 | lblBtc.Visible = sender == radioBtc && radioBtc.Checked; 53 | numQtyBtc.Visible = sender == radioBtc && radioBtc.Checked; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/AddFundsDialog/AddFundsDialog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/AddFundsDialog/AddFundsDto.cs: -------------------------------------------------------------------------------- 1 | namespace _3Commas.BulkEditor.Views.AddFundsDialog 2 | { 3 | public class AddFundsDto 4 | { 5 | public decimal? QtyInBTC { get; set; } 6 | public decimal? QtyInUSD { get; set; } 7 | } 8 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/BaseControls/EntityTableControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/BaseControls/IsBusyEventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace _3Commas.BulkEditor.Views.BaseControls 4 | { 5 | public class IsBusyEventArgs : EventArgs 6 | { 7 | public bool IsBusy { get; private set; } 8 | 9 | public IsBusyEventArgs(bool isBusy) 10 | { 11 | IsBusy = isBusy; 12 | } 13 | } 14 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ChooseSignal/ChooseSignal.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/CopyBotDialog/AccountViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using XCommas.Net.Objects; 3 | 4 | namespace _3Commas.BulkEditor.Views.CopyBotDialog 5 | { 6 | public class AccountViewModel : Account 7 | { 8 | public Guid XCommasAccountId { get; set; } 9 | public string XCommasAccountName { get; set; } 10 | } 11 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/CopyBotDialog/CopyBotDialog.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace _3Commas.BulkEditor.Views.CopyBotDialog 2 | { 3 | partial class CopyBotDialog 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.lblAccount = new System.Windows.Forms.Label(); 32 | this.cmbAccount = new System.Windows.Forms.ComboBox(); 33 | this.btnCancel = new System.Windows.Forms.Button(); 34 | this.btnCreate = new System.Windows.Forms.Button(); 35 | this.cmbIsEnabled = new System.Windows.Forms.ComboBox(); 36 | this.lblState = new System.Windows.Forms.Label(); 37 | this.SuspendLayout(); 38 | // 39 | // lblAccount 40 | // 41 | this.lblAccount.AutoSize = true; 42 | this.lblAccount.Location = new System.Drawing.Point(26, 29); 43 | this.lblAccount.Name = "lblAccount"; 44 | this.lblAccount.Size = new System.Drawing.Size(81, 13); 45 | this.lblAccount.TabIndex = 94; 46 | this.lblAccount.Text = "Target Account"; 47 | // 48 | // cmbAccount 49 | // 50 | this.cmbAccount.FormattingEnabled = true; 51 | this.cmbAccount.Location = new System.Drawing.Point(113, 26); 52 | this.cmbAccount.Name = "cmbAccount"; 53 | this.cmbAccount.Size = new System.Drawing.Size(178, 21); 54 | this.cmbAccount.TabIndex = 5; 55 | // 56 | // btnCancel 57 | // 58 | this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 59 | this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 60 | this.btnCancel.Location = new System.Drawing.Point(234, 99); 61 | this.btnCancel.Name = "btnCancel"; 62 | this.btnCancel.Size = new System.Drawing.Size(88, 23); 63 | this.btnCancel.TabIndex = 52; 64 | this.btnCancel.Text = "&Cancel"; 65 | this.btnCancel.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 66 | this.btnCancel.UseVisualStyleBackColor = true; 67 | // 68 | // btnCreate 69 | // 70 | this.btnCreate.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); 71 | this.btnCreate.Location = new System.Drawing.Point(139, 99); 72 | this.btnCreate.Name = "btnCreate"; 73 | this.btnCreate.Size = new System.Drawing.Size(89, 23); 74 | this.btnCreate.TabIndex = 51; 75 | this.btnCreate.Text = "&OK"; 76 | this.btnCreate.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 77 | this.btnCreate.UseVisualStyleBackColor = true; 78 | this.btnCreate.Click += new System.EventHandler(this.btnCreate_Click); 79 | // 80 | // cmbIsEnabled 81 | // 82 | this.cmbIsEnabled.FormattingEnabled = true; 83 | this.cmbIsEnabled.Location = new System.Drawing.Point(113, 53); 84 | this.cmbIsEnabled.Name = "cmbIsEnabled"; 85 | this.cmbIsEnabled.Size = new System.Drawing.Size(178, 21); 86 | this.cmbIsEnabled.TabIndex = 116; 87 | // 88 | // lblState 89 | // 90 | this.lblState.AutoSize = true; 91 | this.lblState.Location = new System.Drawing.Point(10, 56); 92 | this.lblState.Name = "lblState"; 93 | this.lblState.Size = new System.Drawing.Size(97, 13); 94 | this.lblState.TabIndex = 117; 95 | this.lblState.Text = "State of copied bot"; 96 | // 97 | // ChooseAccount 98 | // 99 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 100 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 101 | this.ClientSize = new System.Drawing.Size(334, 134); 102 | this.Controls.Add(this.cmbIsEnabled); 103 | this.Controls.Add(this.lblState); 104 | this.Controls.Add(this.btnCancel); 105 | this.Controls.Add(this.btnCreate); 106 | this.Controls.Add(this.lblAccount); 107 | this.Controls.Add(this.cmbAccount); 108 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 109 | this.MaximizeBox = false; 110 | this.MinimizeBox = false; 111 | this.Name = "ChooseAccount"; 112 | this.ShowIcon = false; 113 | this.ShowInTaskbar = false; 114 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 115 | this.Load += new System.EventHandler(this.ChooseAccount_Load); 116 | this.ResumeLayout(false); 117 | this.PerformLayout(); 118 | 119 | } 120 | 121 | #endregion 122 | private System.Windows.Forms.Button btnCreate; 123 | private System.Windows.Forms.Label lblAccount; 124 | private System.Windows.Forms.ComboBox cmbAccount; 125 | private System.Windows.Forms.Button btnCancel; 126 | private System.Windows.Forms.ComboBox cmbIsEnabled; 127 | private System.Windows.Forms.Label lblState; 128 | } 129 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/CopyBotDialog/CopyBotDialog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using System.Windows.Forms; 6 | using _3Commas.BulkEditor.Infrastructure; 7 | using _3Commas.BulkEditor.Misc; 8 | using Microsoft.Extensions.Logging; 9 | 10 | namespace _3Commas.BulkEditor.Views.CopyBotDialog 11 | { 12 | public partial class CopyBotDialog : Form 13 | { 14 | private readonly XCommasAccounts _keys; 15 | private readonly ILogger _logger; 16 | private readonly IMessageBoxService _mbs = new MessageBoxService(); 17 | 18 | public CopyBotDialog(XCommasAccounts keys, ILogger logger) 19 | { 20 | _keys = keys; 21 | _logger = logger; 22 | InitializeComponent(); 23 | 24 | cmbIsEnabled.Items.Add("Same as original bot"); 25 | cmbIsEnabled.Items.Add("Enabled"); 26 | cmbIsEnabled.Items.Add("Disabled"); 27 | cmbIsEnabled.SelectedIndex = 0; 28 | } 29 | 30 | public AccountViewModel Account { get; private set; } 31 | public bool? IsEnabled { get; set; } 32 | 33 | private async void ChooseAccount_Load(object sender, EventArgs e) 34 | { 35 | await BindAccountsAndSetSelection(); 36 | } 37 | 38 | private async Task BindAccountsAndSetSelection() 39 | { 40 | var botMgr = new XCommasLayer(_keys, _logger); 41 | var accounts = await botMgr.RetrieveAccounts(); 42 | cmbAccount.DataSource = accounts; 43 | cmbAccount.ValueMember = nameof(AccountViewModel.Id); 44 | cmbAccount.DisplayMember = nameof(AccountViewModel.Name); 45 | } 46 | 47 | private void btnCreate_Click(object sender, EventArgs e) 48 | { 49 | if (IsValid()) 50 | { 51 | Account = cmbAccount.SelectedItem as AccountViewModel; 52 | if (cmbIsEnabled.SelectedIndex == 0) 53 | { 54 | IsEnabled = null; 55 | } 56 | else if (cmbIsEnabled.SelectedIndex == 1) 57 | { 58 | IsEnabled = true; 59 | } 60 | else if (cmbIsEnabled.SelectedIndex == 2) 61 | { 62 | IsEnabled = false; 63 | } 64 | 65 | this.DialogResult = DialogResult.OK; 66 | } 67 | } 68 | 69 | private bool IsValid() 70 | { 71 | var errors = new List(); 72 | 73 | if (cmbAccount.SelectedItem == null) errors.Add("No \"Account\" selected."); 74 | 75 | if (errors.Any()) 76 | { 77 | _mbs.ShowError(String.Join(Environment.NewLine, errors), "Validation Error"); 78 | } 79 | 80 | return !errors.Any(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/CopyBotDialog/CopyBotDialog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/EditBotDialog/EditBotDialog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 90 125 | 126 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/EditBotDialog/EditDto.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using XCommas.Net.Objects; 3 | 4 | namespace _3Commas.BulkEditor.Views.EditBotDialog 5 | { 6 | public class EditBotDto 7 | { 8 | public int? Cooldown { get; set; } 9 | public decimal? MartingaleStepCoefficient { get; set; } 10 | public decimal? MartingaleVolumeCoefficient { get; set; } 11 | public decimal? SafetyOrderStepPercentage { get; set; } 12 | public int? ActiveSafetyOrdersCount { get; set; } 13 | public int? MaxSafetyOrders { get; set; } 14 | public decimal? TrailingDeviation { get; set; } 15 | public bool? TrailingEnabled { get; set; } 16 | public decimal? TakeProfit { get; set; } 17 | public decimal? SafetyOrderVolume { get; set; } 18 | public string Name { get; set; } 19 | public decimal? BaseOrderVolume { get; set; } 20 | public StartOrderType? StartOrderType { get; set; } 21 | public bool? IsEnabled { get; set; } 22 | public DisableAfterDealsCountDto DisableAfterDealsCountInfo { get; set; } 23 | public List DealStartConditions { get; set; } = new List(); 24 | public VolumeType? BaseOrderVolumeType { get; set; } 25 | public VolumeType? SafetyOrderVolumeType { get; set; } 26 | public decimal? StopLossPercentage { get; set; } 27 | public StopLossType? StopLossType { get; set; } 28 | public bool? StopLossTimeoutEnabled { get; set; } 29 | public int? StopLossTimeout { get; set; } 30 | public LeverageType? LeverageType { get; set; } 31 | public decimal? LeverageCustomValue { get; set; } 32 | public TakeProfitType? TakeProfitType { get; set; } 33 | public int? MaxActiveDeals { get; internal set; } 34 | public string Pair { get; set; } 35 | public ProfitCurrency? ProfitCurrency { get; set; } 36 | public decimal? MaxPrice { get; set; } 37 | } 38 | 39 | public class DisableAfterDealsCountDto 40 | { 41 | public bool Enable { get; set; } 42 | public int Value { get; set; } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/EditDealDialog/EditDealDialog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using _3Commas.BulkEditor.Infrastructure; 6 | using _3Commas.BulkEditor.Misc; 7 | using XCommas.Net.Objects; 8 | 9 | namespace _3Commas.BulkEditor.Views.EditDealDialog 10 | { 11 | public partial class EditDealDialog : Form 12 | { 13 | private readonly int _dealCount; 14 | private readonly XCommasLayer _manager; 15 | private readonly IMessageBoxService _mbs = new MessageBoxService(); 16 | private readonly List _startConditions = new List(); 17 | 18 | public EditDealDialog(int dealCount, XCommasLayer manager) 19 | { 20 | _dealCount = dealCount; 21 | _manager = manager; 22 | InitializeComponent(); 23 | 24 | numTargetProfit.DataBindings.Add(nameof(NumericUpDown.Visible), chkChangeTargetProfit, nameof(CheckBox.Checked)); 25 | cmbTakeProfitType.DataBindings.Add(nameof(ComboBox.Visible), chkChangeTakeProfitType, nameof(CheckBox.Checked)); 26 | cmbTtpEnabled.DataBindings.Add(nameof(ComboBox.Visible), chkChangeTrailingEnabled, nameof(CheckBox.Checked)); 27 | numTrailingDeviation.DataBindings.Add(nameof(NumericUpDown.Visible), chkChangeTrailingDeviation, nameof(CheckBox.Checked)); 28 | numMaxSafetyTradesCount.DataBindings.Add(nameof(NumericUpDown.Visible), chkChangeMaxSafetyTradesCount, nameof(CheckBox.Checked)); 29 | numMaxActiveSafetyTradesCount.DataBindings.Add(nameof(NumericUpDown.Visible), chkChangeMaxActiveSafetyTradesCount, nameof(CheckBox.Checked)); 30 | numStopLossPercentage.DataBindings.Add(nameof(NumericUpDown.Visible), chkStopLossPercentage, nameof(CheckBox.Checked)); 31 | cmbStopLossType.DataBindings.Add(nameof(ComboBox.Visible), chkStopLossType, nameof(CheckBox.Checked)); 32 | cmbStopLossTimeoutEnabled.DataBindings.Add(nameof(ComboBox.Visible), chkStopLossTimeoutEnabled, nameof(CheckBox.Checked)); 33 | numStopLossTimeout.DataBindings.Add(nameof(NumericUpDown.Visible), chkStopLossTimeout, nameof(CheckBox.Checked)); 34 | 35 | ControlHelper.AddValuesToCombobox(cmbTakeProfitType); 36 | ControlHelper.AddValuesToCombobox(cmbStopLossType); 37 | 38 | cmbTtpEnabled.Items.Add("Enable"); 39 | cmbTtpEnabled.Items.Add("Disable"); 40 | cmbStopLossTimeoutEnabled.Items.Add("Enable"); 41 | cmbStopLossTimeoutEnabled.Items.Add("Disable"); 42 | } 43 | 44 | public EditDealDto EditDto { get; set; } = new EditDealDto(); 45 | 46 | public bool HasChanges => Controls.OfType().Any(x => x.Checked); 47 | 48 | private void btnCreate_Click(object sender, EventArgs e) 49 | { 50 | if (!HasChanges) 51 | { 52 | _mbs.ShowInformation("No changes to save."); 53 | return; 54 | } 55 | 56 | if (IsValid()) 57 | { 58 | if (chkChangeTargetProfit.Checked) EditDto.TakeProfit = numTargetProfit.Value; 59 | if (chkChangeTakeProfitType.Checked) 60 | { 61 | Enum.TryParse(cmbTakeProfitType.SelectedItem.ToString(), out TakeProfitType takeProfitType); 62 | EditDto.TakeProfitType = takeProfitType; 63 | } 64 | if (chkChangeTrailingEnabled.Checked) EditDto.TrailingEnabled = cmbTtpEnabled.SelectedItem.ToString() == "Enable" ? true : false; 65 | if (chkChangeTrailingDeviation.Checked) EditDto.TrailingDeviation = numTrailingDeviation.Value; 66 | if (chkChangeMaxSafetyTradesCount.Checked) EditDto.MaxSafetyOrders = (int)numMaxSafetyTradesCount.Value; 67 | if (chkChangeMaxActiveSafetyTradesCount.Checked) EditDto.ActiveSafetyOrdersCount = (int)numMaxActiveSafetyTradesCount.Value; 68 | if (chkStopLossPercentage.Checked) EditDto.StopLossPercentage = numStopLossPercentage.Value; 69 | if (chkStopLossType.Checked) 70 | { 71 | Enum.TryParse(cmbStopLossType.SelectedItem.ToString(), out StopLossType stopLossType); 72 | EditDto.StopLossType = stopLossType; 73 | } 74 | if (chkStopLossTimeoutEnabled.Checked) EditDto.StopLossTimeoutEnabled = cmbStopLossTimeoutEnabled.SelectedItem.ToString() == "Enable" ? true : false; 75 | if (chkStopLossTimeout.Checked) EditDto.StopLossTimeout = (int)numStopLossTimeout.Value; 76 | 77 | this.DialogResult = DialogResult.OK; 78 | } 79 | } 80 | 81 | private bool IsValid() 82 | { 83 | var errors = new List(); 84 | 85 | if (chkChangeTakeProfitType.Checked && cmbTakeProfitType.SelectedItem == null) errors.Add("New value for \"Take Profit Type\" missing."); 86 | if (chkChangeTrailingEnabled.Checked && cmbTtpEnabled.SelectedItem == null) errors.Add("New value for \"TTP Enabled\" missing."); 87 | 88 | if (errors.Any()) 89 | { 90 | _mbs.ShowError(String.Join(Environment.NewLine, errors), "Validation Error"); 91 | } 92 | 93 | return !errors.Any(); 94 | } 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/EditDealDialog/EditDealDialog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/EditDealDialog/EditDealDto.cs: -------------------------------------------------------------------------------- 1 | using XCommas.Net.Objects; 2 | 3 | namespace _3Commas.BulkEditor.Views.EditDealDialog 4 | { 5 | public class EditDealDto 6 | { 7 | public int? ActiveSafetyOrdersCount { get; set; } 8 | public int? MaxSafetyOrders { get; set; } 9 | public decimal? TrailingDeviation { get; set; } 10 | public bool? TrailingEnabled { get; set; } 11 | public decimal? TakeProfit { get; set; } 12 | public string Name { get; set; } 13 | public decimal? StopLossPercentage { get; set; } 14 | public StopLossType? StopLossType { get; set; } 15 | public bool? StopLossTimeoutEnabled { get; set; } 16 | public int? StopLossTimeout { get; set; } 17 | public TakeProfitType? TakeProfitType { get; set; } 18 | } 19 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/EditGridBotDialog/EditGridBotDialog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Windows.Forms; 5 | using _3Commas.BulkEditor.Infrastructure; 6 | using _3Commas.BulkEditor.Misc; 7 | 8 | namespace _3Commas.BulkEditor.Views.EditGridBotDialog 9 | { 10 | public partial class EditGridBotDialog : Form 11 | { 12 | private readonly int _botCount; 13 | private readonly XCommasLayer _manager; 14 | private readonly IMessageBoxService _mbs = new MessageBoxService(); 15 | 16 | public EditGridBotDialog(int botCount, XCommasLayer manager) 17 | { 18 | _botCount = botCount; 19 | _manager = manager; 20 | InitializeComponent(); 21 | 22 | cmbIsEnabled.DataBindings.Add(nameof(ComboBox.Visible), chkChangeIsEnabled, nameof(CheckBox.Checked)); 23 | numUpperLimit.DataBindings.Add(nameof(NumericUpDown.Visible), chkChangeUpperLimit, nameof(CheckBox.Checked)); 24 | numLowerLimit.DataBindings.Add(nameof(NumericUpDown.Visible), chkChangeLowerLimit, nameof(CheckBox.Checked)); 25 | numGridQuantity.DataBindings.Add(nameof(NumericUpDown.Visible), chkChangeGridQuantity, nameof(CheckBox.Checked)); 26 | numQuantityPerGrid.DataBindings.Add(nameof(NumericUpDown.Visible), chkChangeQuantityPerGrid, nameof(CheckBox.Checked)); 27 | 28 | cmbIsEnabled.Items.Add("Enable"); 29 | cmbIsEnabled.Items.Add("Disable"); 30 | } 31 | 32 | public EditGridBotDto EditDto { get; set; } = new EditGridBotDto(); 33 | 34 | public bool HasChanges => panel1.Controls.OfType().Any(x => x.Checked); 35 | 36 | private void btnCreate_Click(object sender, EventArgs e) 37 | { 38 | if (!HasChanges) 39 | { 40 | _mbs.ShowInformation("No changes to save."); 41 | return; 42 | } 43 | 44 | if (IsValid()) 45 | { 46 | var dr = _mbs.ShowQuestion($"Save these settings to {_botCount} bots now?"); 47 | if (dr == DialogResult.Yes) 48 | { 49 | if (chkChangeIsEnabled.Checked) 50 | { 51 | if (cmbIsEnabled.SelectedItem.ToString() == "Enable") EditDto.IsEnabled = true; 52 | else if (cmbIsEnabled.SelectedItem.ToString() == "Disable") EditDto.IsEnabled = false; 53 | } 54 | 55 | if (chkChangeLowerLimit.Checked) EditDto.LowerLimitPrice = numLowerLimit.Value; 56 | if (chkChangeUpperLimit.Checked) EditDto.UpperLimitPrice = numUpperLimit.Value; 57 | if (chkChangeQuantityPerGrid.Checked) EditDto.QuantityPerGrid = numQuantityPerGrid.Value; 58 | if (chkChangeGridQuantity.Checked) EditDto.GridsQuantity = Convert.ToInt32(numGridQuantity.Value); 59 | 60 | this.DialogResult = DialogResult.OK; 61 | } 62 | } 63 | } 64 | 65 | private bool IsValid() 66 | { 67 | var errors = new List(); 68 | 69 | if (chkChangeIsEnabled.Checked && cmbIsEnabled.SelectedItem == null) errors.Add("New value for \"Enabled\" missing."); 70 | if (chkChangeUpperLimit.Checked && numUpperLimit.Value == 0) errors.Add("New value for \"Upper Limit Price\" missing."); 71 | if (chkChangeLowerLimit.Checked && numLowerLimit.Value == 0) errors.Add("New value for \"Lower Limit Price\" missing."); 72 | if (chkChangeQuantityPerGrid.Checked && numQuantityPerGrid.Value == 0) errors.Add("New value for \"Quantity per Grid\" missing."); 73 | if (chkChangeGridQuantity.Checked && numGridQuantity.Value == 0) errors.Add("New value for \"Grid Quantity\" missing."); 74 | 75 | if (errors.Any()) 76 | { 77 | _mbs.ShowError(String.Join(Environment.NewLine, errors), "Validation Error"); 78 | } 79 | 80 | return !errors.Any(); 81 | } 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/EditGridBotDialog/EditGridBotDialog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/EditGridBotDialog/EditGridBotDto.cs: -------------------------------------------------------------------------------- 1 | namespace _3Commas.BulkEditor.Views.EditGridBotDialog 2 | { 3 | public class EditGridBotDto 4 | { 5 | public bool? IsEnabled { get; set; } 6 | public decimal? QuantityPerGrid { get; set; } 7 | public decimal? UpperLimitPrice { get; set; } 8 | public decimal? LowerLimitPrice { get; set; } 9 | public int? GridsQuantity { get; set; } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/MainForm/IMainForm.cs: -------------------------------------------------------------------------------- 1 | using System.Threading.Tasks; 2 | using _3Commas.BulkEditor.Infrastructure; 3 | using _3Commas.BulkEditor.Misc; 4 | using Microsoft.Extensions.Logging; 5 | 6 | namespace _3Commas.BulkEditor.Views.MainForm 7 | { 8 | public interface IMainForm : IViewBase 9 | { 10 | void ClearLog(); 11 | void InitGrids(XCommasAccounts keys, ILogger logger, IMessageBoxService mbs); 12 | void SetAccountCount(int numberOfAccounts); 13 | void EnablePanicButton(); 14 | void SetExchangeCount(int accountsCount); 15 | } 16 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/MainForm/MainForm.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using _3Commas.BulkEditor.Infrastructure; 4 | using _3Commas.BulkEditor.Misc; 5 | using Microsoft.Extensions.Logging; 6 | 7 | namespace _3Commas.BulkEditor.Views.MainForm 8 | { 9 | public sealed partial class MainForm : Form, IMainForm 10 | { 11 | private readonly MainFormPresenter _presenter; 12 | 13 | public MainForm() 14 | { 15 | InitializeComponent(); 16 | 17 | Text = $"{AssemblyHelper.AssemblyTitle} {AssemblyHelper.AssemblyVersion}"; 18 | 19 | ObjectContainer.Logger = new TextBoxLogger(txtOutput); 20 | 21 | _presenter = new MainFormPresenter(this, ObjectContainer.Logger, ObjectContainer.MessageBoxService, ObjectContainer.EventBroker); 22 | } 23 | 24 | private async void MainForm_Load(object sender, EventArgs e) 25 | { 26 | await _presenter.OnViewReady(); 27 | } 28 | 29 | private void btnClear_Click(object sender, EventArgs e) 30 | { 31 | _presenter.OnClear(); 32 | } 33 | 34 | private void btnAbout_Click(object sender, EventArgs e) 35 | { 36 | AboutBox.AboutBox box = new AboutBox.AboutBox(); 37 | box.ShowDialog(this); 38 | } 39 | 40 | public void ClearLog() 41 | { 42 | txtOutput.Clear(); 43 | } 44 | 45 | public void InitGrids(XCommasAccounts keys, ILogger logger, IMessageBoxService mbs) 46 | { 47 | manageBotControl.Init(keys, logger, mbs); 48 | manageGridBotControl.Init(keys, logger, mbs); 49 | manageDealControl.Init(keys, logger, mbs); 50 | } 51 | 52 | private void tabControl1_SelectedIndexChanged(object sender, EventArgs e) 53 | { 54 | NotifyCurrentTab(); 55 | } 56 | 57 | public void SetAccountCount(int numberOfAccounts) 58 | { 59 | lblAccountsLoaded.Text = $"3Commas Accounts loaded: {numberOfAccounts}"; 60 | } 61 | 62 | public void SetExchangeCount(int numberOfExchanges) 63 | { 64 | lblExchangesLoaded.Text = $"Total Exchanges loaded: {numberOfExchanges}"; 65 | } 66 | 67 | public void EnablePanicButton() 68 | { 69 | btnStopAllBots.Enabled = true; 70 | } 71 | 72 | private void NotifyCurrentTab() 73 | { 74 | // Workaround: 75 | // we can only set the datasource if the grid is really visible to the user. Otherwise this gridview will throw an exception while binding the data :/ 76 | if (tabControl1.SelectedTab.Text == "DCA Bots") 77 | { 78 | manageBotControl.SetDataSource(); 79 | } 80 | else if (tabControl1.SelectedTab.Text == "Grid Bots") 81 | { 82 | manageGridBotControl.SetDataSource(); 83 | } 84 | else 85 | { 86 | manageDealControl.SetDataSource(); 87 | } 88 | } 89 | 90 | private void btnStopAllBots_Click(object sender, EventArgs e) 91 | { 92 | _presenter.OnStopAllBots(); 93 | } 94 | 95 | private void btnManageApiKeys_Click(object sender, EventArgs e) 96 | { 97 | _presenter.OnManageApiKeys(); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/MainForm/MainFormPresenter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Net.Http; 5 | using System.Threading.Tasks; 6 | using System.Windows.Forms; 7 | using _3Commas.BulkEditor.Infrastructure; 8 | using _3Commas.BulkEditor.Misc; 9 | using M.EventBroker; 10 | using Microsoft.Extensions.Logging; 11 | 12 | namespace _3Commas.BulkEditor.Views.MainForm 13 | { 14 | public class MainFormPresenter : PresenterBase 15 | { 16 | private XCommasAccounts _keys; 17 | private readonly ILogger _logger; 18 | private readonly IMessageBoxService _mbs; 19 | private readonly IEventBroker _eventBroker; 20 | 21 | public MainFormPresenter(IMainForm view, ILogger logger, IMessageBoxService mbs, IEventBroker eventBroker) : base(view) 22 | { 23 | _logger = logger; 24 | _mbs = mbs; 25 | _eventBroker = eventBroker; 26 | 27 | GetOrMigrateSettings(); 28 | } 29 | 30 | private void GetOrMigrateSettings() 31 | { 32 | var apiKey = Properties.Settings.Default.ApiKey3Commas; 33 | var secret = Properties.Settings.Default.Secret3Commas; 34 | _keys = ObjectContainer.KeyManager.Read(); 35 | if (!string.IsNullOrWhiteSpace(apiKey) && !string.IsNullOrWhiteSpace(secret) && _keys.IsEmpty) 36 | { 37 | _keys = new XCommasAccounts { Accounts = new List { new XCommasAccount { ApiKey = apiKey, Secret = secret, Name = "default" } } }; 38 | ObjectContainer.KeyManager.Save(_keys); 39 | } 40 | } 41 | 42 | internal async Task OnViewReady() 43 | { 44 | if (!_keys.IsEmpty) await LoadAccounts(); 45 | View.InitGrids(_keys, _logger, _mbs); 46 | await ShowMessage(); 47 | } 48 | 49 | private async Task LoadAccounts() 50 | { 51 | var xCommas = new XCommasLayer(_keys, _logger); 52 | var exchanges = await xCommas.RetrieveAccounts(); 53 | ObjectContainer.Cache.SetAccounts(exchanges); 54 | var pairs = await xCommas.GetMarketPairs(); 55 | ObjectContainer.Cache.SetPairs(pairs); 56 | View.SetAccountCount(_keys.Accounts.Count); 57 | View.SetExchangeCount(exchanges.Count); 58 | View.EnablePanicButton(); 59 | } 60 | 61 | private async Task ShowMessage() 62 | { 63 | try 64 | { 65 | HttpClient client = new HttpClient(); 66 | string result = await client.GetStringAsync("https://marcdrexler.blob.core.windows.net/bulkeditor/message.txt"); 67 | if (!String.IsNullOrWhiteSpace(result)) 68 | { 69 | _mbs.ShowInformation(result); 70 | } 71 | } 72 | catch 73 | { 74 | // ignore 75 | } 76 | } 77 | 78 | public async void OnManageApiKeys() 79 | { 80 | var settingsPersisted = !string.IsNullOrWhiteSpace(Properties.Settings.Default.ApiKey3Commas); 81 | var settings = new Settings.Settings(settingsPersisted, "3Commas Accounts", _keys); 82 | var dr = settings.ShowDialog(); 83 | if (dr == DialogResult.OK) 84 | { 85 | _keys = new XCommasAccounts {Accounts = settings.Accounts.ToList()}; 86 | 87 | await LoadAccounts(); 88 | _eventBroker.Publish(new KeysChangedEventArgs() {Keys = _keys}); 89 | } 90 | } 91 | 92 | public void OnClear() 93 | { 94 | View.ClearLog(); 95 | } 96 | 97 | public void OnStopAllBots() 98 | { 99 | _eventBroker.Publish(new StopAllBotsEventArgs()); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageBotControl/BotTableControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageBotControl/BotViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | using _3Commas.BulkEditor.Misc; 5 | using XCommas.Net.Objects; 6 | 7 | namespace _3Commas.BulkEditor.Views.ManageBotControl 8 | { 9 | public class BotViewModel : Bot 10 | { 11 | [DisplayName("Type")] 12 | public string BotType 13 | { 14 | get 15 | { 16 | switch (Type) 17 | { 18 | case "Bot::SingleBot": 19 | return "Simple"; 20 | case "Bot::MultiBot": 21 | return "Composite"; 22 | default: 23 | return Type; 24 | } 25 | } 26 | } 27 | 28 | [DisplayName("Deal Start Condition")] 29 | public string DealStartCondition => string.Join(", ", Strategies.Select(x => x.ToHumanReadableString())); 30 | 31 | [DisplayName("Pair")] 32 | public string Pair => String.Join(", ", Pairs); 33 | 34 | [DisplayName("Enabled")] 35 | public new bool IsEnabled { get; set; } 36 | 37 | [DisplayName("Account")] 38 | public new string AccountName { get; set; } 39 | 40 | [DisplayName("TP")] 41 | public new string TakeProfit { get; set; } 42 | 43 | [DisplayName("TP Type")] 44 | public new TakeProfitType TakeProfitType { get; set; } 45 | 46 | [DisplayName("Profit Ratio")] 47 | public decimal ProfitRatio => FinishedDealsCount > 0 ? Math.Round(FinishedDealsProfitUsd / FinishedDealsCount, 2) : 0; 48 | 49 | public Guid XCommasAccountId { get; set; } 50 | 51 | [DisplayName("3Commas Account")] 52 | public string XCommasAccountName { get; set; } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageBotControl/ManageBotControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageDealControl/DealTableControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using _3Commas.BulkEditor.Infrastructure; 6 | using _3Commas.BulkEditor.Misc; 7 | using _3Commas.BulkEditor.Views.BaseControls; 8 | using _3Commas.BulkEditor.Views.ManageBotControl; 9 | using AutoMapper; 10 | using AutoMapper.Configuration; 11 | using Microsoft.Extensions.Logging; 12 | using XCommas.Net.Objects; 13 | 14 | namespace _3Commas.BulkEditor.Views.ManageDealControl 15 | { 16 | public class DealTableControl : EntityTableControl 17 | { 18 | private XCommasAccounts _keys; 19 | private ILogger _logger; 20 | 21 | public DealTableControl() 22 | { 23 | InitializeComponent(); 24 | OnRefreshClicked += OnOnRefreshClicked; 25 | } 26 | 27 | public void Init(XCommasAccounts keys, ILogger logger, IMessageBoxService mbs) 28 | { 29 | _keys = keys; 30 | _logger = logger; 31 | base.Init("Deals", keys); 32 | } 33 | 34 | private async void OnOnRefreshClicked(object sender, EventArgs e) 35 | { 36 | await RefreshData(_keys); 37 | } 38 | 39 | public List SelectedItems 40 | { 41 | get 42 | { 43 | var selectedIds = base.SelectedIds; 44 | return base.Items.Where(x => selectedIds.Contains(x.Id)).ToList(); 45 | } 46 | } 47 | 48 | public async Task RefreshData(XCommasAccounts keys) 49 | { 50 | await base.RefreshData(async () => 51 | { 52 | var botMgr = new XCommasLayer(keys, _logger); 53 | var allDeals = (await botMgr.GetAllDeals()).OrderBy(x => x.Deal.Id).ToList(); 54 | 55 | var cfg = new MapperConfigurationExpression(); 56 | cfg.CreateMap(); 57 | var mapperConfig = new MapperConfiguration(cfg); 58 | var mapper = mapperConfig.CreateMapper(); 59 | 60 | var result = new List(); 61 | foreach (var dealWithExchangeInfo in allDeals) 62 | { 63 | var dealViewModel = mapper.Map(dealWithExchangeInfo.Deal); 64 | dealViewModel.XCommasAccountId = dealWithExchangeInfo.XCommasAccount; 65 | dealViewModel.XCommasAccountName = dealWithExchangeInfo.XCommasAccountName; 66 | result.Add(dealViewModel); 67 | } 68 | return result; 69 | }, 70 | new Tuple[] 71 | { 72 | new Tuple(nameof(DealViewModel.Id), 65), 73 | new Tuple(nameof(DealViewModel.DealType), 50), 74 | new Tuple(nameof(DealViewModel.XCommasAccountName), 100), 75 | new Tuple(nameof(DealViewModel.Account), 100), 76 | new Tuple(nameof(DealViewModel.BotId), 55), 77 | new Tuple(nameof(DealViewModel.BotName), 130), 78 | new Tuple(nameof(DealViewModel.Pair), 100), 79 | new Tuple(nameof(DealViewModel.DealHasErrors), 50), 80 | new Tuple(nameof(DealViewModel.ErrorMessage), 100), 81 | new Tuple(nameof(DealViewModel.TakeProfit), 50), 82 | new Tuple(nameof(DealViewModel.TakeProfitType), 70), 83 | new Tuple(nameof(DealViewModel.IsTrailingEnabled), 70), 84 | new Tuple(nameof(DealViewModel.TrailingDeviation), 90), 85 | new Tuple(nameof(DealViewModel.TrailingMaxPrice), 80), 86 | new Tuple(nameof(DealViewModel.BoughtAmount), 80), 87 | new Tuple(nameof(DealViewModel.BoughtVolume), 80), 88 | new Tuple(nameof(DealViewModel.BoughtAveragePrice), 80), 89 | new Tuple(nameof(DealViewModel.SoldAmount), 80), 90 | new Tuple(nameof(DealViewModel.SoldVolume), 80), 91 | new Tuple(nameof(DealViewModel.SoldAveragePrice), 80), 92 | new Tuple(nameof(DealViewModel.BaseOrderVolume), 80), 93 | new Tuple(nameof(DealViewModel.BaseOrderVolumeType), 80), 94 | new Tuple(nameof(DealViewModel.SafetyOrderVolume), 80), 95 | new Tuple(nameof(DealViewModel.SafetyOrderVolumeType), 80), 96 | new Tuple(nameof(DealViewModel.MartingaleCoefficient), 80), 97 | new Tuple(nameof(DealViewModel.MaxSafetyOrders), 80), 98 | new Tuple(nameof(DealViewModel.ActiveSafetyOrdersCount), 80), 99 | new Tuple(nameof(DealViewModel.CompletedSafetyOrdersCount), 80), 100 | new Tuple(nameof(DealViewModel.CurrentActiveSafetyOrdersCount), 80), 101 | new Tuple(nameof(DealViewModel.SafetyOrderStepPercentage), 80), 102 | new Tuple(nameof(DealViewModel.IsCancellable), 80), 103 | new Tuple(nameof(DealViewModel.IsPanicSellable), 80), 104 | new Tuple(nameof(DealViewModel.CreatedAt), 100), 105 | new Tuple(nameof(DealViewModel.UpdatedAt), 100) 106 | }); 107 | } 108 | 109 | private void InitializeComponent() 110 | { 111 | SuspendLayout(); 112 | // 113 | // DealTableControl 114 | // 115 | AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 116 | Name = "DealTableControl"; 117 | ResumeLayout(false); 118 | PerformLayout(); 119 | 120 | } 121 | } 122 | } 123 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageDealControl/DealTableControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageDealControl/DealViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | using _3Commas.BulkEditor.Infrastructure; 5 | using XCommas.Net.Objects; 6 | 7 | namespace _3Commas.BulkEditor.Views.ManageDealControl 8 | { 9 | public class DealViewModel : Deal 10 | { 11 | [DisplayName("Type")] public new string DealType { get; set; } 12 | 13 | [DisplayName("Account")] 14 | public string Account 15 | { 16 | get { return ObjectContainer.Cache.Accounts.SingleOrDefault(x => x.Id == AccountId)?.Name; } 17 | } 18 | 19 | public Guid XCommasAccountId { get; set; } 20 | 21 | [DisplayName("3Commas Account")] 22 | public string XCommasAccountName { get; set; } 23 | } 24 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageDealControl/ManageDealControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageGridBotControl/GridBotTableControl.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Threading.Tasks; 5 | using _3Commas.BulkEditor.Misc; 6 | using _3Commas.BulkEditor.Views.BaseControls; 7 | using AutoMapper; 8 | using AutoMapper.Configuration; 9 | using Microsoft.Extensions.Logging; 10 | using XCommas.Net.Objects; 11 | 12 | namespace _3Commas.BulkEditor.Views.ManageGridBotControl 13 | { 14 | public class GridBotTableControl : EntityTableControl 15 | { 16 | private XCommasAccounts _keys; 17 | private ILogger _logger; 18 | 19 | public GridBotTableControl() 20 | { 21 | InitializeComponent(); 22 | OnRefreshClicked += OnOnRefreshClicked; 23 | } 24 | 25 | public void Init(XCommasAccounts keys, ILogger logger) 26 | { 27 | _keys = keys; 28 | _logger = logger; 29 | base.Init("Grid Bots", _keys); 30 | } 31 | 32 | private async void OnOnRefreshClicked(object sender, EventArgs e) 33 | { 34 | await RefreshData(_keys); 35 | } 36 | 37 | public async Task RefreshData(XCommasAccounts keys) 38 | { 39 | await base.RefreshData(async () => 40 | { 41 | var botMgr = new XCommasLayer(keys, _logger); 42 | var allBots = (await botMgr.GetAllGridBots()).OrderBy(x => x.Bot.Id).ToList(); 43 | 44 | var cfg = new MapperConfigurationExpression(); 45 | cfg.CreateMap(); 46 | var mapperConfig = new MapperConfiguration(cfg); 47 | var mapper = mapperConfig.CreateMapper(); 48 | 49 | var result = new List(); 50 | foreach (var botWithExchangeInfo in allBots) 51 | { 52 | var botViewModel = mapper.Map(botWithExchangeInfo.Bot); 53 | botViewModel.XCommasAccountId = botWithExchangeInfo.XCommasAccount; 54 | botViewModel.XCommasAccountName = botWithExchangeInfo.XCommasAccountName; 55 | result.Add(botViewModel); 56 | } 57 | 58 | return result; 59 | }, 60 | new[] 61 | { 62 | new Tuple(nameof(GridBotViewModel.Id), 55), 63 | new Tuple(nameof(GridBotViewModel.IsEnabled), 80), 64 | new Tuple(nameof(GridBotViewModel.XCommasAccountName), 120), 65 | new Tuple(nameof(GridBotViewModel.AccountName), 120), 66 | new Tuple(nameof(GridBotViewModel.Name), 120), 67 | new Tuple(nameof(GridBotViewModel.Pair), 100), 68 | // new Tuple(nameof(GridBotViewModel.LeverageType), 80), 69 | // new Tuple(nameof(GridBotViewModel.LeverageCustomValue), 80), 70 | new Tuple(nameof(GridBotViewModel.UpperLimitPrice), 100), 71 | new Tuple(nameof(GridBotViewModel.LowerLimitPrice), 100), 72 | new Tuple(nameof(GridBotViewModel.GridsQuantity), 100), 73 | new Tuple(nameof(GridBotViewModel.QuantityPerGrid), 100), 74 | new Tuple(nameof(GridBotViewModel.CreatedAt), 100), 75 | new Tuple(nameof(GridBotViewModel.UpdatedAt), 100), 76 | }); 77 | } 78 | 79 | private void InitializeComponent() 80 | { 81 | SuspendLayout(); 82 | // 83 | // BotTableControl 84 | // 85 | AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 86 | Name = "GridBotTableControl"; 87 | ResumeLayout(false); 88 | PerformLayout(); 89 | 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageGridBotControl/GridBotTableControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageGridBotControl/GridBotViewModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Linq; 4 | using _3Commas.BulkEditor.Misc; 5 | using XCommas.Net.Objects; 6 | 7 | namespace _3Commas.BulkEditor.Views.ManageGridBotControl 8 | { 9 | public class GridBotViewModel : GridBot 10 | { 11 | //[DisplayName("Type")] 12 | //public string BotType 13 | //{ 14 | // get 15 | // { 16 | // switch (Type) 17 | // { 18 | // case "Bot::SingleBot": 19 | // return "Simple"; 20 | // case "Bot::MultiBot": 21 | // return "Composite"; 22 | // default: 23 | // return Type; 24 | // } 25 | // } 26 | //} 27 | 28 | //[DisplayName("Deal Start Condition")] 29 | //public string DealStartCondition => string.Join(", ", Strategies.Select(x => x.ToHumanReadableString())); 30 | 31 | //[DisplayName("Pair")] 32 | //public string Pair => String.Join(", ", Pairs); 33 | 34 | //[DisplayName("Enabled")] 35 | //public new bool IsEnabled { get; set; } 36 | 37 | //[DisplayName("Account")] 38 | //public new string AccountName { get; set; } 39 | 40 | //[DisplayName("TP")] 41 | //public new string TakeProfit { get; set; } 42 | 43 | //[DisplayName("TP Type")] 44 | //public new TakeProfitType TakeProfitType { get; set; } 45 | 46 | //[DisplayName("Profit Ratio")] 47 | //public decimal ProfitRatio => FinishedDealsCount > 0 ? Math.Round(FinishedDealsProfitUsd / FinishedDealsCount, 2) : 0; 48 | 49 | public Guid XCommasAccountId { get; set; } 50 | 51 | [DisplayName("3Commas Account")] 52 | public string XCommasAccountName { get; set; } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ManageGridBotControl/ManageGridBotControl.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ProgressView/ProgressView.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace _3Commas.BulkEditor.Views.ProgressView 2 | { 3 | partial class ProgressView 4 | { 5 | /// 6 | /// Required designer variable. 7 | /// 8 | private System.ComponentModel.IContainer components = null; 9 | 10 | /// 11 | /// Clean up any resources being used. 12 | /// 13 | /// true if managed resources should be disposed; otherwise, false. 14 | protected override void Dispose(bool disposing) 15 | { 16 | if (disposing && (components != null)) 17 | { 18 | components.Dispose(); 19 | } 20 | base.Dispose(disposing); 21 | } 22 | 23 | #region Windows Form Designer generated code 24 | 25 | /// 26 | /// Required method for Designer support - do not modify 27 | /// the contents of this method with the code editor. 28 | /// 29 | private void InitializeComponent() 30 | { 31 | this.btnCancel = new System.Windows.Forms.Button(); 32 | this.progressBar = new System.Windows.Forms.ProgressBar(); 33 | this.lblProgress = new System.Windows.Forms.Label(); 34 | this.btnClose = new System.Windows.Forms.Button(); 35 | this.lblPercentage = new System.Windows.Forms.Label(); 36 | this.SuspendLayout(); 37 | // 38 | // btnCancel 39 | // 40 | this.btnCancel.Image = global::_3Commas.BulkEditor.Properties.Resources.Close_16x16; 41 | this.btnCancel.Location = new System.Drawing.Point(116, 117); 42 | this.btnCancel.Name = "btnCancel"; 43 | this.btnCancel.Size = new System.Drawing.Size(80, 25); 44 | this.btnCancel.TabIndex = 0; 45 | this.btnCancel.Text = "Cancel"; 46 | this.btnCancel.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 47 | this.btnCancel.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 48 | this.btnCancel.UseVisualStyleBackColor = true; 49 | this.btnCancel.Click += new System.EventHandler(this.button1_Click); 50 | // 51 | // progressBar 52 | // 53 | this.progressBar.Location = new System.Drawing.Point(12, 57); 54 | this.progressBar.Name = "progressBar"; 55 | this.progressBar.Size = new System.Drawing.Size(287, 23); 56 | this.progressBar.TabIndex = 1; 57 | // 58 | // lblProgress 59 | // 60 | this.lblProgress.Location = new System.Drawing.Point(12, 32); 61 | this.lblProgress.Name = "lblProgress"; 62 | this.lblProgress.Size = new System.Drawing.Size(287, 19); 63 | this.lblProgress.TabIndex = 2; 64 | this.lblProgress.Text = ""; 65 | this.lblProgress.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 66 | // 67 | // btnClose 68 | // 69 | this.btnClose.DialogResult = System.Windows.Forms.DialogResult.OK; 70 | this.btnClose.Location = new System.Drawing.Point(116, 117); 71 | this.btnClose.Name = "btnClose"; 72 | this.btnClose.Size = new System.Drawing.Size(80, 25); 73 | this.btnClose.TabIndex = 3; 74 | this.btnClose.Text = "Close"; 75 | this.btnClose.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; 76 | this.btnClose.UseVisualStyleBackColor = true; 77 | this.btnClose.Visible = false; 78 | // 79 | // lblPercentage 80 | // 81 | this.lblPercentage.Location = new System.Drawing.Point(12, 83); 82 | this.lblPercentage.Name = "lblPercentage"; 83 | this.lblPercentage.Size = new System.Drawing.Size(287, 19); 84 | this.lblPercentage.TabIndex = 4; 85 | this.lblPercentage.Text = "0 %"; 86 | this.lblPercentage.TextAlign = System.Drawing.ContentAlignment.MiddleCenter; 87 | // 88 | // ProgressView 89 | // 90 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 91 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 92 | this.ClientSize = new System.Drawing.Size(311, 154); 93 | this.ControlBox = false; 94 | this.Controls.Add(this.lblPercentage); 95 | this.Controls.Add(this.lblProgress); 96 | this.Controls.Add(this.progressBar); 97 | this.Controls.Add(this.btnCancel); 98 | this.Controls.Add(this.btnClose); 99 | this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; 100 | this.MaximizeBox = false; 101 | this.MinimizeBox = false; 102 | this.Name = "ProgressView"; 103 | this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; 104 | this.Text = "Saving"; 105 | this.TopMost = true; 106 | this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ProgressView_FormClosed); 107 | this.Load += new System.EventHandler(this.ProgressView_Load); 108 | this.ResumeLayout(false); 109 | 110 | } 111 | 112 | #endregion 113 | 114 | private System.Windows.Forms.Button btnCancel; 115 | private System.Windows.Forms.ProgressBar progressBar; 116 | private System.Windows.Forms.Label lblProgress; 117 | private System.Windows.Forms.Button btnClose; 118 | private System.Windows.Forms.Label lblPercentage; 119 | } 120 | } -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ProgressView/ProgressView.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Threading; 3 | using System.Windows.Forms; 4 | 5 | namespace _3Commas.BulkEditor.Views.ProgressView 6 | { 7 | public partial class ProgressView : Form 8 | { 9 | private readonly CancellationTokenSource _cancellationToken; 10 | private readonly int _totalCount; 11 | 12 | public ProgressView(string text, CancellationTokenSource token, int totalCount) 13 | { 14 | _cancellationToken = token; 15 | _totalCount = totalCount; 16 | InitializeComponent(); 17 | lblProgress.Text = $@"{text}. Please wait ..."; 18 | progressBar.Maximum = totalCount; 19 | } 20 | 21 | public void SetProgress(int currentValue) 22 | { 23 | if (this.InvokeRequired) 24 | { 25 | Invoke(new MethodInvoker(() => 26 | { 27 | progressBar.Value = currentValue; 28 | decimal percentage = ((decimal)currentValue / _totalCount) * 100; 29 | lblPercentage.Text = $"{(int)percentage} %"; 30 | })); 31 | } 32 | } 33 | 34 | private void button1_Click(object sender, EventArgs e) 35 | { 36 | _cancellationToken.Cancel(); 37 | 38 | lblProgress.Text = @"Operation has been cancelled."; 39 | progressBar.Enabled = false; 40 | btnCancel.Visible = false; 41 | btnClose.Visible = true; 42 | } 43 | 44 | private void ProgressView_FormClosed(object sender, FormClosedEventArgs e) 45 | { 46 | if (this.Owner != null) 47 | { 48 | this.Owner.Enabled = true; 49 | } 50 | } 51 | 52 | private void ProgressView_Load(object sender, EventArgs e) 53 | { 54 | CenterToParent(); 55 | if (this.Owner != null) 56 | { 57 | this.Owner.Enabled = false; 58 | } 59 | } 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/ProgressView/ProgressView.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/Settings/AddAccountDialog.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using _3Commas.BulkEditor.Misc; 4 | 5 | namespace _3Commas.BulkEditor.Views.Settings 6 | { 7 | public partial class AddAccountDialog : Form 8 | { 9 | private readonly XCommasAccount _account; 10 | 11 | public AddAccountDialog(string title, string buttonAction, string permissionsNeeded, XCommasAccount account) 12 | { 13 | _account = account; 14 | InitializeComponent(); 15 | 16 | Text = title; 17 | btnApply.Text = buttonAction; 18 | lblPermissionsNeeded.Text = permissionsNeeded; 19 | 20 | txtDescription.Text = _account.Name; 21 | txtBinanceApiKey.Text = _account.ApiKey; 22 | txtBinanceSecret.Text = _account.Secret; 23 | } 24 | 25 | private void btnApply_Click(object sender, EventArgs e) 26 | { 27 | _account.Name = txtDescription.Text; 28 | _account.ApiKey = txtBinanceApiKey.Text; 29 | _account.Secret = txtBinanceSecret.Text; 30 | 31 | DialogResult = DialogResult.OK; 32 | } 33 | 34 | private void btnCancel_Click(object sender, EventArgs e) 35 | { 36 | this.Close(); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/Settings/AddAccountDialog.resx: -------------------------------------------------------------------------------- 1 |  2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/Settings/Settings.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.ComponentModel; 3 | using System.Configuration; 4 | using System.Linq; 5 | using System.Windows.Forms; 6 | using _3Commas.BulkEditor.Infrastructure; 7 | using _3Commas.BulkEditor.Misc; 8 | 9 | namespace _3Commas.BulkEditor.Views.Settings 10 | { 11 | public partial class Settings : Form 12 | { 13 | private bool _viewLoaded = false; 14 | 15 | public Settings(bool persistSettings, string title, XCommasAccounts accounts) 16 | { 17 | InitializeComponent(); 18 | chkPersist.Checked = persistSettings; 19 | Text = title; 20 | 21 | Accounts = new BindingList(accounts.Accounts); 22 | 23 | listBox.DataSource = Accounts; 24 | listBox.DisplayMember = nameof(XCommasAccount.Name); 25 | listBox.ValueMember = nameof(XCommasAccount.Id); 26 | 27 | _viewLoaded = true; 28 | } 29 | 30 | public BindingList Accounts { get; set; } 31 | 32 | public bool PersistKeys => chkPersist.Checked; 33 | 34 | private void btnApply_Click(object sender, EventArgs e) 35 | { 36 | if (PersistKeys) 37 | { 38 | ObjectContainer.KeyManager.Save(new XCommasAccounts() {Accounts = Accounts.ToList()}); 39 | } 40 | else 41 | { 42 | ObjectContainer.KeyManager.Clear(); 43 | } 44 | 45 | DialogResult = DialogResult.OK; 46 | this.Close(); 47 | } 48 | 49 | private void chkPersist_CheckedChanged(object sender, EventArgs e) 50 | { 51 | if (_viewLoaded && chkPersist.Checked) 52 | { 53 | MessageBox.Show("Your keys will be persisted in your user directory. Be aware that other programs may potentially have access to it. In addition, after an application update, the configuration files of previous versions may still exist. Only an uninstallation will delete all configuration data." + Environment.NewLine + Environment.NewLine + 54 | "Settings location: " + System.IO.Path.GetDirectoryName(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath), "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning); 55 | } 56 | } 57 | 58 | private void btnAdd_Click(object sender, EventArgs e) 59 | { 60 | var newAccount = new XCommasAccount(); 61 | var settings = new AddAccountDialog("Add 3Commas Account", "Add", "Permissions Needed: BotsRead, BotsWrite, AccountsRead", newAccount); 62 | var dr = settings.ShowDialog(); 63 | if (dr == DialogResult.OK) 64 | { 65 | Accounts.Add(newAccount); 66 | } 67 | } 68 | 69 | private void btnEdit_Click(object sender, EventArgs e) 70 | { 71 | if (listBox.SelectedItem == null) 72 | { 73 | ObjectContainer.MessageBoxService.ShowError("No Account selected."); 74 | return; 75 | } 76 | 77 | var account = listBox.SelectedItem as XCommasAccount; 78 | var settings = new AddAccountDialog("Edit 3Commas Account", "Apply", "Permissions Needed: BotsRead, BotsWrite, AccountsRead", account); 79 | var dr = settings.ShowDialog(); 80 | if (dr == DialogResult.OK) 81 | { 82 | listBox.DataSource = null; 83 | listBox.DataSource = Accounts; 84 | listBox.DisplayMember = nameof(XCommasAccount.Name); 85 | listBox.ValueMember = nameof(XCommasAccount.Id); 86 | } 87 | } 88 | 89 | private void btnDelete_Click(object sender, EventArgs e) 90 | { 91 | if (listBox.SelectedItem == null) 92 | { 93 | ObjectContainer.MessageBoxService.ShowError("No Account selected."); 94 | return; 95 | } 96 | 97 | var account = listBox.SelectedItem as XCommasAccount; 98 | var dr = ObjectContainer.MessageBoxService.ShowQuestion($"Are you sure to delete Account '{account.Name}' ?"); 99 | if (dr == DialogResult.Yes) 100 | { 101 | Accounts.Remove(account); 102 | } 103 | } 104 | 105 | private void btnCancel_Click(object sender, EventArgs e) 106 | { 107 | DialogResult = DialogResult.Cancel; 108 | Close(); 109 | } 110 | } 111 | } 112 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/Views/Settings/Settings.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /src/3Commas.BulkEditor/robot.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MarcDrexler/3Commas.BulkEditor/d0d5a21ec2602de22e050309b1e569420acb51ed/src/3Commas.BulkEditor/robot.ico --------------------------------------------------------------------------------