Skip to content

Instantly share code, notes, and snippets.

@Kikimora
Created September 20, 2017 16:06
Show Gist options
  • Save Kikimora/59abe12b1bb2a76e036e6537cdfb959f to your computer and use it in GitHub Desktop.
Save Kikimora/59abe12b1bb2a76e036e6537cdfb959f to your computer and use it in GitHub Desktop.
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