13using System.Collections.Generic;
14using System.Diagnostics;
15using System.Threading.Tasks;
16using System.Windows.Controls;
17using System.Windows.Input;
40 private readonly List<AccountEventWrapper> events =
new();
42 private readonly
Command sendUri;
43 private readonly
Command transferEDaler;
44 private readonly
Command buyEDaler;
45 private readonly
Command sellEDaler;
52 private string optionsTransactionId =
null;
53 private string optionsContractId =
null;
73 this.sendUri =
new Command(this.CanExecuteSendUri, this.ExecuteSendUri);
74 this.transferEDaler =
new Command(this.CanTransferEDaler, this.ExecuteTransferEDaler);
75 this.buyEDaler =
new Command(this.CanBuyEDaler, this.ExecuteBuyEDaler);
76 this.sellEDaler =
new Command(this.CanSellEDaler, this.ExecuteSellEDaler);
78 this.contractsClient = Contracts;
79 this.networkModel = Network;
81 this.eDalerClient =
new EDalerClient(Client, Contracts, ComponentJid);
82 this.eDalerClient.BalanceUpdated += this.EDalerClient_BalanceUpdated;
83 this.eDalerClient.BuyEDalerClientUrlReceived += this.EDalerClient_BuyEDalerClientUrlReceived;
84 this.eDalerClient.BuyEDalerCompleted += this.EDalerClient_BuyEDalerCompleted;
85 this.eDalerClient.BuyEDalerError += this.EDalerClient_BuyEDalerError;
86 this.eDalerClient.BuyEDalerOptionsClientUrlReceived += this.EDalerClient_BuyEDalerOptionsClientUrlReceived;
87 this.eDalerClient.BuyEDalerOptionsCompleted += this.EDalerClient_BuyEDalerOptionsCompleted;
88 this.eDalerClient.BuyEDalerOptionsError += this.EDalerClient_BuyEDalerOptionsError;
89 this.eDalerClient.SellEDalerClientUrlReceived += this.EDalerClient_SellEDalerClientUrlReceived;
90 this.eDalerClient.SellEDalerCompleted += this.EDalerClient_SellEDalerCompleted;
91 this.eDalerClient.SellEDalerError += this.EDalerClient_SellEDalerError;
92 this.eDalerClient.SellEDalerOptionsClientUrlReceived += this.EDalerClient_SellEDalerOptionsClientUrlReceived;
93 this.eDalerClient.SellEDalerOptionsCompleted += this.EDalerClient_SellEDalerOptionsCompleted;
94 this.eDalerClient.SellEDalerOptionsError += this.EDalerClient_SellEDalerOptionsError;
97 private async Task EDalerClient_BalanceUpdated(
object Sender,
BalanceEventArgs e)
102 Item.Selected += this.Item_Selected;
103 Item.Deselected += this.Item_Deselected;
107 this.events.Insert(0, Item);
113 private void Item_Deselected(
object sender, EventArgs e)
115 if (this.selectedItem == sender)
117 this.selectedItem =
null;
122 private void Item_Selected(
object sender, EventArgs e)
124 this.selectedItem = sender as AccountEventWrapper;
131 this.eDalerClient.Dispose();
144 get => this.amount.Value;
145 set => this.amount.Value = value;
153 get => this.reserved.Value;
154 set => this.reserved.Value = value;
162 get => this.pending.Value;
163 set => this.pending.Value = value;
171 get => this.available.Value;
172 set => this.available.Value = value;
180 get => this.currency.Value;
181 set => this.currency.Value = value;
189 get => this.timestamp.Value;
190 set => this.timestamp.Value = value;
198 get => this.uri.Value;
201 this.uri.Value = value;
202 this.sendUri.RaiseCanExecuteChanged();
218 return this.UpdateAmounts();
221 private async Task UpdateAmounts()
223 this.Amount = this.balance.
Amount;
224 this.Reserved = this.balance.
Reserved;
225 this.Currency = this.balance.
Currency;
228 (decimal
Pending, _, _) = await this.eDalerClient.GetPendingPayments();
231 this.Available = this.Amount - this.Reserved - this.
Pending;
237 public IEnumerable<AccountEventWrapper>
Events
243 return this.events.ToArray();
253 get => this.selectedItem;
254 set => this.selectedItem = value;
262 private bool CanExecuteSendUri()
264 return this.eDalerClient.Client.State == XmppState.Connected && !
string.IsNullOrEmpty(this.
Uri);
267 private async Task ExecuteSendUri()
272 throw new Exception(
"Invalid eDaler® URI.");
276 this.Uri = await this.eDalerClient.CreateFullPaymentUri(
278 IncompleteUri.Amount,
279 IncompleteUri.AmountExtra,
280 IncompleteUri.Currency,
281 (
int)IncompleteUri.Expires.Subtract(DateTime.Today.AddDays(-1)).TotalDays);
284 await this.eDalerClient.SendEDalerUriAsync(this.Uri);
285 this.Uri =
string.Empty;
298 private bool CanTransferEDaler()
300 return this.eDalerClient.Client.State ==
XmppState.Connected;
303 private async Task ExecuteTransferEDaler()
314 TransferEDalerModel Model =
new(Dialog,
string.IsNullOrEmpty(this.currency.Value) ? DefaultArgs.Currency : this.currency.Value);
316 bool? Result = Dialog.ShowDialog();
317 if (!Result.HasValue || !Result.Value)
320 this.Uri = await this.eDalerClient.CreateFullPaymentUri(
Model.Recipient,
Model.Amount,
323 await this.UpdateAmounts();
336 private bool CanBuyEDaler()
338 return this.eDalerClient.Client.State ==
XmppState.Connected;
341 private async Task ExecuteBuyEDaler()
348 if (Providers.Length == 0)
349 throw new Exception(
"No providers available for buying eDaler®.");
356 BuyEDalerModel Model =
new(Dialog, Providers,
string.IsNullOrEmpty(this.currency.Value) ? DefaultArgs.Currency : this.currency.Value);
358 bool? Result = Dialog.ShowDialog();
359 if (!Result.HasValue || !Result.Value)
365 throw new Exception(
"Cannot buy eDaler® using that service provider.");
380 string Key =
"Contract.Template." + TemplateName;
387 throw new Exception(
"Contract referenced by service provider is not a template.");
390 this.networkModel.Legal.ContractTemplateAdded(TemplateName,
Contract);
393 Dictionary<CaseInsensitiveString, object> PresetValues =
new()
395 {
"Amount", Model.Amount },
396 {
"Currency", Model.Currency }
399 await this.networkModel.Legal.SetContractTemplateName(TemplateName, PresetValues);
401 foreach (TabItem Item
in MainWindow.currentInstance.TabControl.Items)
403 if (Item.Content ==
MainWindow.currentInstance.ContractsTab)
405 MainWindow.currentInstance.TabControl.SelectedItem = Item;
412 this.optionsTransactionId = Guid.NewGuid().ToString();
416 this.optionsTransactionId,
null,
null,
null);
428 return Task.CompletedTask;
431 private static void OpenUrl(
string Url)
433 ProcessStartInfo StartInfo =
new()
436 UseShellExecute =
true
439 Process.Start(StartInfo);
445 return Task.CompletedTask;
451 return Task.CompletedTask;
457 return Task.CompletedTask;
463 return Task.CompletedTask;
469 return Task.CompletedTask;
477 private bool CanSellEDaler()
479 return this.eDalerClient.Client.State ==
XmppState.Connected;
482 private async Task ExecuteSellEDaler()
489 if (Providers.Length == 0)
490 throw new Exception(
"No providers available for selling eDaler®.");
497 SellEDalerModel Model =
new(Dialog, Providers,
string.IsNullOrEmpty(this.currency.Value) ? DefaultArgs.Currency : this.currency.Value);
499 bool? Result = Dialog.ShowDialog();
500 if (!Result.HasValue || !Result.Value)
506 throw new Exception(
"Cannot sell eDaler® using that service provider.");
509 if (
string.IsNullOrEmpty(
ServiceProvider.SellEDalerTemplateContractId))
521 string Key =
"Contract.Template." + TemplateName;
528 throw new Exception(
"Contract referenced by service provider is not a template.");
531 this.networkModel.Legal.ContractTemplateAdded(TemplateName,
Contract);
534 Dictionary<CaseInsensitiveString, object> PresetValues =
new()
536 {
"Amount", Model.Amount },
537 {
"Currency", Model.Currency }
540 await this.networkModel.Legal.SetContractTemplateName(TemplateName, PresetValues);
542 foreach (TabItem Item
in MainWindow.currentInstance.TabControl.Items)
544 if (Item.Content ==
MainWindow.currentInstance.ContractsTab)
546 MainWindow.currentInstance.TabControl.SelectedItem = Item;
553 this.optionsTransactionId = Guid.NewGuid().ToString();
557 this.optionsTransactionId,
null,
null,
null);
569 return Task.CompletedTask;
575 return Task.CompletedTask;
581 return Task.CompletedTask;
587 return Task.CompletedTask;
593 return Task.CompletedTask;
599 return Task.CompletedTask;
607 MainWindow.currentInstance.WalletTab.DataContext =
this;
608 return Task.CompletedTask;
611 await this.
SetBalance(await this.eDalerClient.GetBalanceAsync());
613 (
AccountEvent[]
Events,
bool More) = await this.eDalerClient.GetAccountEventsAsync(50);
620 Item.Selected += this.Item_Selected;
621 Item.Deselected += this.Item_Deselected;
623 this.events.Add(Item);
632 private void ContractOptionsReceived(
string TransactionId, IDictionary<CaseInsensitiveString, object>[] Options)
634 if (this.optionsTransactionId != TransactionId ||
635 this.networkModel.Legal.CurrentContract.ContractId !=
this.optionsContractId)
640 MainWindow.
UpdateGui(async () => await this.networkModel.Legal.CurrentContract.ShowContractOptions(Options));
Contains information about a balance.
CaseInsensitiveString Currency
Currency of amount.
AccountEvent Event
Any account event associated to the balance message.
decimal Amount
Amount at given point in time.
decimal Reserved
Reserved amount, that the user cannot use directly.
DateTime Timestamp
Timestamp of balance.
Wallet balance event arguments.
Event arguments for events where a client URL needs to be displayed when buying eDaler.
string ClientUrl
URL client needs to open to complete the transaction of buying eDaler.
Event arguments for event signalling the completion of a payment operation.
decimal Amount
Amount paid
string Currency
Currency paid
Event arguments for event signalling an error of a payment operation.
new string Message
Error message.
Event arguments for operations returning payment options.
IDictionary< CaseInsensitiveString, object >[] Options
Payment options.
string TransactionId
Transaction ID, if available in the response.
Event arguments for events where a client URL needs to be displayed when selling eDaler.
string ClientUrl
URL client needs to open to complete the transaction of selling eDaler.
Abstract base class for eDaler URIs
static bool TryParse(string Uri, out EDalerUri Result)
Tries to parse an eDaler URI
Incomplete eDaler URI for simplifying payments to a predefined recipient.
Converts values to strings.
static string ToString(object Value)
Converts a monetary value to a string, removing any round-off errors.
Interaction logic for BuyEDalerDialog.xaml
View model for the buy eDaler® dialog.
View mode for service providers.
Waher.Networking.XMPP.Contracts.IServiceProvider ServiceProvider
Reference to service provider.
Interaction logic for SellEDalerDialog.xaml
View model for the sell eDaler® dialog.
Interaction logic for TransferEDalerDialog.xaml
View model for the Transfer eDaler® dialog.
Interaction logic for MainWindow.xaml
static void MouseHourglass()
Displays an hourglass cursor (or similar for waiting purposes).
static void ErrorBox(string ErrorMessage)
Displays an error message on the screen, on the main UI thread.
static void SuccessBox(string Message)
Displays a success message on the screen, on the main UI thread.
static void UpdateGui(GuiDelegate Method)
Calls a method from the Main UI thread.
static void MouseDefault()
Returns to default mouse pointer.
Defines a custom command.
Abstract base class for view models
virtual void RaisePropertyChanged(string PropertyName)
Raises the PropertyChanged event.
Abstract base class for persistant view models
Generic class for properties
WalletModel(XmppClient Client, ContractsClient Contracts, string ComponentJid, NetworkModel Network)
Wallet Model
override async Task Start()
Starts the model.
Task SetBalance(Balance Balance)
Sets the balance of the wallet.
decimal Pending
Pending amount
ICommand SellEDaler
Command for selling eDaler®.
ICommand BuyEDaler
Command for buying eDaler®.
IEnumerable< AccountEventWrapper > Events
Account events
decimal Available
Available amount
Balance Balance
Latest balance
decimal Amount
Balance amount
ICommand SendUri
Command for sending URI to server.
DateTime Timestamp
Balance timestamp
ICommand TransferEDaler
Command for transferring eDaler®.
AccountEventWrapper SelectedItem
Selected item
decimal Reserved
Reserved amount
string Currency
Balance currency
Event arguments for callback methods to token creation attributes queries.
Contains the definition of a contract
bool CanActAsTemplate
If the contract can act as a template for other contracts.
string ContractId
Contract identity
Adds support for legal identities, smart contracts and signatures to an XMPP client.
Contains information about a service provider.
string Type
Type of service provider.
string Id
ID of service provider.
string Name
Displayable name of service provider.
Manages an XMPP client connection. Implements XMPP, as defined in https://tools.ietf....
Static class managing persistent settings.
static async Task< string > GetAsync(string Key, string DefaultValue)
Gets a string-valued setting.
static async Task< bool > SetAsync(string Key, string Value)
Sets a string-valued setting.
Interface for information about a service provider that users can use to buy eDaler.
Interface for information about a service provider that users can use to sell eDaler.
XmppState
State of XMPP connection.