Update and normalize Coding Conventons with uncontroversial guidelines (for pull request reviewing.)
ADD
CodeMaid.config
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <configSections>
+ <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
+ <section name="SteveCadwallader.CodeMaid.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
+ </sectionGroup>
+ </configSections>
+ <userSettings>
+ <SteveCadwallader.CodeMaid.Properties.Settings>
+ <setting name="Cleaning_AutoCleanupOnFileSave" serializeAs="String">
+ <value>True</value>
+ </setting>
+ <setting name="Reorganizing_AlphabetizeMembersOfTheSameGroup"
+ serializeAs="String">
+ <value>False</value>
+ </setting>
+ <setting name="Cleaning_InsertEndOfFileTrailingNewLine" serializeAs="String">
+ <value>True</value>
+ </setting>
+ <setting name="Cleaning_RemoveEndOfFileTrailingNewLine" serializeAs="String">
+ <value>False</value>
+ </setting>
+ <setting name="Cleaning_RunVisualStudioRemoveAndSortUsingStatements"
+ serializeAs="String">
+ <value>False</value>
+ </setting>
+ <setting name="Cleaning_PerformPartialCleanupOnExternal" serializeAs="String">
+ <value>2</value>
+ </setting>
+ </SteveCadwallader.CodeMaid.Properties.Settings>
+ </userSettings>
+</configuration>
\ No newline at end of file

ADD
WalletWasabi.Documentation/CodingConventions.md
+# Wasabi Coding Conventions
+
+## CodeMaid
+
+**DO** use [CodeMaid](http://www.codemaid.net/) is a Visual Studio extension to automatically clean up your code on saving the file.
+
+CodeMaid is a non-intrusive code cleanup tool. Wasabi's CodeMaid settings [can be found in the root of the repository](https://github.com/zkSNACKs/WalletWasabi/blob/master/CodeMaid.config), and are automatically picked up by Visual Studio when you open the project. Assuming the CodeMaid extension is installed. Unfortunately CodeMaid has no Visual Studio Code extension yet. You can check out the progress on this [under this GitHub issue](https://github.com/codecadwallader/codemaid/issues/273).
+
+## Comments
+
+**DO** follow [Microsoft's C# commenting conventions](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions#commenting-conventions).
+
+- Place the comment on a separate line, not at the end of a line of code.
+- Begin comment text with an uppercase letter.
+- End comment text with a period.
+- Insert one space between the comment delimiter (`//`) and the comment text, as shown in the following example.
+- Do not create formatted blocks of asterisks around comments.
+
+```cs
+// The following declaration creates a query. It does not run
+// the query.
+```
+
+## Asynchronous Locking
+
+**DO NOT** use mix awaitable and non-awaitable locks.
+
+```cs
+// GOOD
+private AsyncLock AsyncLock { get; } = new AsyncLock();
+using (await AsyncLock.LockAsync())
+{
+ ...
+}
+
+// GOOD
+private object Lock { get; } = new object();
+lock (Lock)
+{
+ ...
+}
+
+// BAD
+using (AsyncLock.Lock())
+{
+ ...
+}
+```
+
+## Null Check
+
+**DO** use `is null` instead of `== null`. It was a performance consideration in the past but from C# 7.0 it does not matter anymore, today we use this convention to keep our code consisent.
+
+```cs
+ if (foo is null) return;
+```
+
+## Blocking
+
+**DO NOT** block with `.Result, .Wait(), .GetAwaiter().GetResult()`. Never.
+
+```cs
+// BAD
+IoHelpers.DeleteRecursivelyWithMagicDustAsync(Folder).GetAwaiter().GetResult();
+```
+
+## `async void`
+
+**DO NOT** `async void`, except for event subscriptions. `async Task` instead.
+**DO** `try catch` in `async void`, otherwise the software can crash.
+
+```cs
+{
+ MyClass.SomethingHappened += MyClass_OnSomethingHappenedAsync;
+}
+
+// GOOD
+private async void Synchronizer_ResponseArrivedAsync(object sender, EventArgs e)
+{
+ try
+ {
+ awat FooAsync();
+ }
+ catch (Exception ex)
+ {
+ Logger.LogError<MyClass2>(ex);
+ }
+}
+```
+
+## Disposing Subscriptions in ReactiveObjects
+
+**DO** follow [ReactiveUI's Subscription Disposing Conventions](https://reactiveui.net/docs/guidelines/framework/dispose-your-subscriptions).
+
+**DO** dispose your subscription if you are referencing another object. **DO** use the `.DisposeWith()` method.
+
+```cs
+Observable.FromEventPattern(...)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .Subscribe(...)
+ .DisposeWith(Disposables);
+```
+
+**DO NOT** dispose your subscription if a component exposes an event and also subscribes to it itself. That's because the subscription is manifested as the component having a reference to itself. Same is true with Rx. If you're a VM and you e.g. WhenAnyValue against your own property, there's no need to clean that up because that is manifested as the VM having a reference to itself.
+
+```cs
+this.WhenAnyValue(...)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .Subscribe(...);
+```
+
+## ObservableAsPropertyHelpers Over Properties
+
+**DO** follow [ReactiveUI's Oaph Over Properties Principle](https://reactiveui.net/docs/guidelines/framework/prefer-oaph-over-properties).
+
+**DO** use `ObservableAsPropertyHelper` with `WhenAny` when a property's value depends on another property, a set of properties, or an observable stream, rather than set the value explicitly.
+
+```cs
+public class RepositoryViewModel : ReactiveObject
+{
+ readonly ObservableAsPropertyHelper<bool> _canDoIt;
+
+ public RepositoryViewModel()
+ {
+ _canDoIt = this.WhenAny(...)
+ .ObserveOn(RxApp.MainThreadScheduler)
+ .ToProperty(this, x => x.CanDoIt);
+ }
+
+ public bool CanDoIt => _canDoIt?.Value ?? false;
+}
+```

DELETE
WalletWasabi.Documentation/Guides/WasabiCodingGuidelines.md
-# Wasabi Coding Guidelines for UI
-
-## Example ViewModel Class
-
-```c#
- public class MyViewModel : ReactiveObject, IDisposable
- {
- private CompositeDisposable Disposables { get; } = new CompositeDisposable();
- private string _myProperty;
- private bool _myConfirmed;
- private ObservableAsPropertyHelper<bool> _confirmed;
- private SmartCoin Model { get; }
-
- public string MyProperty
- {
- get => _myProperty;
- set => this.RaiseAndSetIfChanged(ref _myProperty, value);
- }
-
- public bool MyConfirmed
- {
- get => _myConfirmed;
- set => this.RaiseAndSetIfChanged(ref _myConfirmed, value);
- }
-
- public ReactiveCommand MyCommand { get; }
- public ReactiveCommand MySecondCommand { get; }
-
- public MyViewModel()
- {
-
- this.WhenAnyValue(x => x.MyProperty)
- .Subscribe(myProperty =>
- {
- });
-
- _confirmed = Model.WhenAnyValue(x => x.Confirmed)
- .ToProperty(this, x => x.MyConfirmed, scheduler: RxApp.MainThreadScheduler)
- .DisposeWith(Disposables);
-
- Model.WhenAnyValue(x => x.IsBanned, x => x.SpentAccordingToBackend)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(_ =>
- {
- })
- .DisposeWith(Disposables);
-
- Dispatcher.UIThread.PostLogException(() =>
- {
- // Do something on the UI thread. App-crash exception handler built-in.
- });
-
- Observable.FromEventPattern(
- Global.ChaumianClient,
- nameof(Global.ChaumianClient.StateUpdated))
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(_ =>
- {
- }).DisposeWith(Disposables);
-
- IObservable<bool> isCoinListItemSelected = this.WhenAnyValue(x => x.MyProperty).Select(myProperty => myProperty != null);
-
- MyCommand = ReactiveCommand.Create(() =>
- {
-
- }, isCoinListItemSelected);
-
- MyCommand.ThrownExceptions
- .Subscribe(ex => Logging.Logger.LogWarning<MyViewModel>(ex));
-
- MySecondCommand = ReactiveCommand.CreateFromTask(async () =>
- {
- await Task.Delay(100);
- }, isCoinListItemSelected);
-
- Observable.FromEventPattern(Global.WalletService.Coins, nameof(Global.WalletService.Coins.CollectionChanged))
- .Merge(Observable.FromEventPattern(Global.WalletService, nameof(Global.WalletService.NewBlockProcessed)))
- .Merge(Observable.FromEventPattern(Global.WalletService, nameof(Global.WalletService.CoinSpentOrSpenderConfirmed)))
- .Throttle(TimeSpan.FromSeconds(5))
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(_ =>
- {
-
- })
- .DisposeWith(Disposables);
-
-
- }
-
- #region IDisposable Support
-
- private volatile bool _disposedValue = false;
-
- protected virtual void Dispose(bool disposing)
- {
- if (!_disposedValue)
- {
- if (disposing)
- {
- Disposables?.Dispose();
- }
- Disposables = null;
-
- _disposedValue = true;
- }
- }
-
- ~MyViewModel()
- {
- Dispose(false);
- }
-
- public void Dispose()
- {
- Dispose(true);
- GC.SuppressFinalize(this);
- }
-
- #endregion IDisposable Support
- }
-```
-
-
-## Detecting the change of a Property
-
-You can put the following into the constructor of the ViewModel. `MyProperty` should use `this.RaiseAndSetIfChanged()` to notify the change. If you're a VM and you e.g. `WhenAnyValue` against your own property, there's [no need to clean that up because](https://reactiveui.net/docs/guidelines/framework/dispose-your-subscriptions) that is manifested as the VM having a reference to itself.
-
-```c#
- this.WhenAnyValue(x => x.MyProperty)
- .Subscribe(myProperty =>
- {
- });
-```
-
-If you are referencing other object you should dispose your subscription. Use `.DisposeWith()` method.
-
-```c#
- Model.WhenAnyValue(x => x.IsBanned, x => x.SpentAccordingToBackend)
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(_ =>
- {
- })
- .DisposeWith(Disposables);
-```
-
-## Event subscriptions
-
-Reactive generates an observable from the event and from then you can use all the toolset of Rx. Regarding the disposal it is pretty similar. If a component exposes an event and also subscribes to it itself, it doesn't need to unsubscribe. That's because the subscription is manifested as the component having a reference to itself.
-
-```c#
- Observable.FromEventPattern(CoinList, nameof(CoinList.SelectionChanged)).Subscribe(_ => SetFeesAndTexts());
-
- Observable.FromEventPattern(
- Global.ChaumianClient,
- nameof(Global.ChaumianClient.StateUpdated))
- .ObserveOn(RxApp.MainThreadScheduler)
- .Subscribe(_ =>
- {
- RefreshSmartCoinStatus();
- }).DisposeWith(Disposables);
-```
-
-[More examples](http://blog.functionalfun.net/2012/03/weak-events-in-net-easy-way.html)
-
-## Expose Model Property to View
-
-When a property's value depends on another property, a set of properties, or an observable stream, rather than set the value explicitly, [use `ObservableAsPropertyHelper` with `WhenAny` wherever possible](https://reactiveui.net/docs/guidelines/framework/prefer-oaph-over-properties).
-
-
-```c#
- //Define class members.
- private ObservableAsPropertyHelper<bool> _confirmed;
- public bool Confirmed => _confirmed?.Value ?? false;
-
- //Initialize PropertyHelper.
- _confirmed = Model.WhenAnyValue(x => x.Confirmed).ToProperty(this, x => x.Confirmed).DisposeWith(Disposables);
-
- //Initialize PropertyHelper if invoked from not UI thread
- _confirmed = Model.WhenAnyValue(x => x.Confirmed).ToProperty(this, x => x.Confirmed, scheduler:RxApp.MainThreadScheduler).DisposeWith(Disposables);
-```
-
-
-## ReactiveCommand
-
-Prefer binding user interactions to [commands](https://reactiveui.net/docs/guidelines/framework/commands) rather than methods.
-
-```c#
- //Create Observable<bool> on MyProperty for CanExecute. Null detection always tricky but following code will handle that.
- IObservable<bool> isCoinListItemSelected = this.WhenAnyValue(x => x.MyProperty).Select(myProperty => myProperty != null);
-
- //Define command with CanExecute.
- MyCommand = ReactiveCommand.Create(() =>
- {
-
- }, isCoinListItemSelected);
-
- //Define command from Task
- MySecondCommand = ReactiveCommand.CreateFromTask(async () =>
- {
- await Task.Delay(100);
- }, isCoinListItemSelected);
-```
-
-
-Reactive command doesn't have any unmanaged resources.
-Dispose in Reactive command doesn't mean release unmanaged resources, it simply means unsubscribe.
-Reactive command is on the same object that is subscribing, so GC will handle everything.
-So no memory leak here.
-[See this comment from the author of RxUI...](https://github.com/reactiveui/ReactiveUI/issues/20#issuecomment-1324201)
-
-## AsyncLock
-
-Use awaitable locks if possible. The library `Nito.AsyncEx` contains tools to do this.
-
-```c#
- private readonly AsyncLock _myLock = new AsyncLock();
-
- using (await _myLock.LockAsync())
- {
-
- }
-```
-
-## Null check
-
-```c#
- if (FeeService is null) return;
-```
-
-Use `is null` instead of `==null`. It was a performance consideration in the past but from C# 7.0 two operators behave the same. The Roslyn compiler has been updated to make the behavior of the two operator the same __when there is no overloaded equality operator__. [Please see the code in the current compiler results (M1 and M2 in the code)](http://tryroslyn.azurewebsites.net/#b:master/f:%3Eilr/K4Zwlgdg5gBAygTxAFwKYFsDcAoADsAIwBswBjGUogQxBBgGEYBvbGNmAge06JgFkAjAApOBAFapSyGAA8AlDAC8APlkwwdCMCJEcASC49+AJhHjJ0+UtUylimFp04AvkA==) that shows what happens when there is no overloaded equality comparer. They both now have the better performing == behavior. If there is an overloaded equality comparer, [the code still differs](https://stackoverflow.com/questions/40676426/what-is-the-difference-between-x-is-null-and-x-null).
-
-
-## !!!WANTED!!! 10000 Dollar Reward Dead or Alive!
-
-DO NOT use PropertyChanged.
-
-```c#
- private void Coin_PropertyChanged(object sender, PropertyChangedEventArgs e)
- {
- if (e.PropertyName == nameof(CoinViewModel.Unspent))
- {
- }
- }
-```
-
-DO NOT use event subscriptions.
-
-```c#
- Global.ChaumianClient.StateUpdated += ChaumianClient_StateUpdated;
-
- if (Global.ChaumianClient != null)
- {
- Global.ChaumianClient.StateUpdated -= ChaumianClient_StateUpdated;
- }
-```
-
-DO NOT do anything in set except `RaiseAndSetIfChanged()`.
-
-```c#
- public int FeeTarget
- {
- get => _feeTarget;
- set
- {
- this.RaiseAndSetIfChanged(ref _feeTarget, value);
- Global.UiConfig.FeeTarget = value;
- }
- }
-```
-
-DO NOT use [async void Method()](https://msdn.microsoft.com/en-us/magazine/jj991977.aspx).
-
-```c#
- async void DoSomething()
- {
-
- }
-```
-
-DO NOT block with `.Result, .Wait(), .GetAwaiter().GetResult()` unless they are absolutely necessary.
-
-```c#
- IoHelpers.DeleteRecursivelyWithMagicDustAsync(Folder).GetAwaiter().GetResult();
-```
-
-DO NOT use `==null`
-
-```c#
- if (FeeService == null) return;
-```
-
-DO NOT use local variables in `.Subscribe()`.
-
-```c#
-
- public MyConstructor(NodesCollection nodes)
- {
-
- Observable.FromEventPattern<NodeEventArgs>(myList, nameof(nodes.Removed))
- .Subscribe(x =>
- {
- Refresh(nodes.Count); //Bad code. Nodes should be a class member!
- }).DisposeWith(Disposables);
-
- }
-
-```

Update and normalize Coding Conventons with uncontroversial guidelines (for pull request reviewing.)