Created
September 20, 2017 16:06
-
-
Save Kikimora/59abe12b1bb2a76e036e6537cdfb959f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public enum Network { Bitcoin, Ethereum } | |
public interface IWeakListener | |
{ | |
void OnMessage(Notification notification); | |
} | |
public interface ISendStrategy | |
{ | |
decimal AvailableFunds {get;} | |
Error ValidateRecipientAddress(string recipient); | |
void Send(string recipient, decimal amount, decimal fee); | |
} | |
public class SendModel : DataContext, IWeakListener | |
{ | |
ISendStrategy _sendStrategy; | |
public SendModel() | |
{ | |
SendCommand = new AsyncCommand(Send, _ => !_.IsRunning); | |
PropertyChanged += ValidateCalculatedProperties; | |
//Subscribe to events which comes not from UI but from our model. | |
//Subscriptions are implemented as weak references. | |
WalletContext.MessageHub.Subscribe("Bitcoin.AvailableFunds", this); | |
WalletContext.MessageHub.Subscribe("Ethereum.AvailableFunds", this); | |
} | |
void IWeakListener.OnMessage(Notification notification) | |
{ | |
RaisePropertyChanged(nameof(AvailableFunds)); | |
} | |
decimal _amount; | |
public decimal Amount | |
{ | |
get => _amount; | |
set | |
{ | |
//Amount cannot be less than 0 | |
Validator.CheckProperty(value).MoreOrEqThan(0); | |
if (value == _amount) | |
{ | |
_amount = value; | |
RaisePropertyChanged(nameof(Amount)); | |
OnTotalTransactionAmountChanged(); | |
} | |
} | |
} | |
//Only valid for bitcoin | |
decimal _fee; | |
public decimal Fee | |
{ | |
get => Network == Network.Bitcoin ? _fee : 0; | |
set | |
{ | |
//Fee cannot be less than 0 | |
Validator.CheckProperty(value).MoreOrEqThan(0).LessThan(); | |
if (value != _fee) | |
{ | |
_fee = value; | |
RaisePropertyChanged(nameof(Fee)); | |
OnTotalTransactionAmountChanged(); | |
} | |
} | |
} | |
public decimal TotalTransactionAmount | |
{ | |
get | |
{ | |
return Amount + Fee; | |
} | |
} | |
string _recipient; | |
public string Recipient | |
{ | |
get => _recipient; | |
set | |
{ | |
var checker = Validator.CheckProperty(value).NotEmpty(); | |
var error = _sendStrategy.ValidateRecipientAddress(value); | |
if (error != null) | |
{ | |
error.Key = nameof(Recipient); | |
Validator.Add(error); | |
} | |
if (value != _recipient) | |
{ | |
_recipient = value; | |
RaisePropertyChanged(nameof(Recipient)); | |
} | |
} | |
} | |
Network _network; | |
public Network Network | |
{ | |
get => _network; | |
set | |
{ | |
if (value != _network) | |
{ | |
_network = value; | |
_sendStrategy = _network == Network.Bitcoin ? new BitcoinSendStrategy() : EthereumSendStrategy(); | |
RaisePropertyChanged(nameof(Network)); | |
RaisePropertyChanged(nameof(Fee)); | |
OnAvailableFundsChanged(); | |
Validate(); | |
} | |
} | |
} | |
public decimal AvailableFunds | |
{ | |
get | |
{ | |
return _sendStrategy.AvailableFunds; | |
} | |
} | |
private void OnTotalTransactionAmountChanged() | |
{ | |
ValidateTotalAmount(); | |
RaisePropertyChanged(nameof(TotalTransactionAmount)); | |
} | |
private void ValidateTotalAmount() | |
{ | |
Validator.Check(TotalTransactionAmount, nameof(TotalTransactionAmount)) | |
.LessThan(AvailableFunds); | |
} | |
private void OnAvailableFundsChanged() | |
{ | |
RaisePropertyChanged(nameof(AvailableFunds)); | |
//TotalTransactionAmount depends on AvailableFunds; | |
OnTotalTransactionAmountChanged(); | |
} | |
private async Task Send(object arg, CancellationToken token) | |
{ | |
_sendStrategy.Send(Recipient, Amount, Fee); | |
} | |
} | |
public class BitcoinSendStrategy : ISendStrategy | |
{ | |
public decimal AvailableFunds | |
{ | |
get | |
{ | |
return WalletContext.User.Bitcoin.AvailableFunds; | |
} | |
} | |
public Error ValidateRecipientAddress(string recipient) | |
{ | |
if (BitcoinAddress.Parse(recipient) == null) | |
{ | |
return new Error() { Message = "Invalid Recipient", {{"Value", recipient}} }; | |
} | |
} | |
public void Send(string recipient, decimal amount, decimal fee) | |
{ | |
var address = BitcoinAddress.Parse(recipient); | |
var sender = WalletContext.User.Bitcoin.Address; | |
await WalletContext.BitcoinService.Send(sender, address, amount, fee); | |
} | |
} | |
public class EthereumSendStrategy : ISendStrategy | |
{ | |
public decimal AvailableFunds | |
{ | |
get | |
{ | |
return WalletContext.User.Ethereum.AvailableFunds; | |
} | |
} | |
public void ValidateRecipientAddress(Check<string> recipient) | |
{ | |
if (EthereumAddress.Parse(recipient) == null) | |
{ | |
return new Error() { Message = "Invalid Recipient", {{"Value", recipient}} }; | |
} | |
} | |
public void Send(string recipient, decimal amount, decimal fee) | |
{ | |
var address = EthereumAddress.Parse(recipient); | |
var sender = WalletContext.User.Ethereum.Address; | |
await WalletContext.EthereumService.Send(sender, address, amount); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment