/// <summary> /// Handle a fatal exception by calling our logger and then informing the user if possible. /// </summary> /// <param name="ex"> /// The exception that triggered this. /// </param> private static void HandleFatalException(Exception ex) { try { Logger.ApplicationInstance.Error("Fatal error within Sift.", ex); } catch { // Intentionally swallowed } string msg = "There was a fatal error within SIFT, please contact support with this message." + Environment.NewLine + ex; try { SiftDialog.ShowDialog("Fatal Error", msg); } catch { try { MessageBox.Show(msg); } catch { // Intentionally swallowed } } }
/// <summary> /// Shows a SIFT dialog with the specified parameters as a dialog. /// </summary> /// <param name="title"> /// The title of the message. /// </param> /// <param name="message"> /// The message to show. /// </param> /// <param name="isYesNo"> /// If this is a yes/no dialog (true) or a single button dialog (false). /// </param> /// <param name="isEthereum"> /// If this dialog is related to the ethereum network (true) and as such the ethereum logo should be displayed, otherwise false. /// </param> /// <returns> /// Null if return was pressed, false if No was pressed, true if Yes was pressed. /// </returns> public static bool?ShowDialog(string title, string message, bool isYesNo = false, bool isEthereum = false) { Func <bool?> uiCallback = () => { SiftDialogViewModel viewModel = new SiftDialogViewModel { Title = title, Message = message, IsEthereumAnimatedLogoVisible = isEthereum, IsSiftLogoVisible = !isEthereum, IsLogButtonVisible = true, IsNoButtonVisible = isYesNo, IsReturnButtonVisible = !isYesNo, IsYesButtonVisible = isYesNo }; SiftDialog dialog = new SiftDialog { DataContext = viewModel, Owner = Application.Current.MainWindow }; viewModel.CloseRequested += (s, e) => dialog.Close(); dialog.ShowDialog(); return(!isYesNo ? null : (bool?)viewModel.WasYesPressed); }; if (Application.Current.Dispatcher.CheckAccess()) { return(uiCallback()); } else { return(Application.Current.Dispatcher.Invoke(uiCallback)); } }
/// <summary> /// Perform an investment in SIFT using the current UI settings. /// </summary> private async Task Invest() { // Disable UI SiftInvestIsEnabled = false; // Check times if (DateTime.UtcNow < _ethereumManager.IcoStartDate) { SiftDialog.ShowDialog("ICO Not Open", "The ICO for SIFT does not open until " + _ethereumManager.IcoStartDate.ToShortDateString() + " (00:00 GMT). Please wait until this time to invest in SIFT."); return; } else if (DateTime.UtcNow > _ethereumManager.IcoEndDate) { SiftDialog.ShowDialog("ICO Not Open", "The ICO for SIFT finished at " + _ethereumManager.IcoStartDate.ToShortDateString() + " (00:00 GMT). As soon as the ICO has been closed you will be able to purchase SIFT via an open marketplace."); return; } // Perform the purchase SiftPurchaseResponse response = await _ethereumManager.PurchaseSift(SelectedAccount.Address, SiftAmountToPurchase); if (!response.WasSuccessful) { SiftDialog.ShowDialog("SIFT Investment Problem", "Sorry, there was a problem processing your transaction. Your SIFT could not be purchased at this time." + Environment.NewLine + Environment.NewLine + response.FailureReason); } else { TransactionToMine = _ethereumManager.EnqueueTransactionPendingReceipt(response.TransactionHash); if (TransactionToMine == null) { SiftDialog.ShowDialog("SIFT Delayed Investment", "Your transaction to buy SIFT was successfully sent with hash " + response.TransactionHash + ", but we could not validate the transaction. Your balance should update shortly, but if not please retry the transaction after checking your Ethereum wallet."); } else { // Hookup to wait to hear the status, or process it immediately if we have it Action act = () => { TransactionToMine.PropertyChanged += OnTransactionToMinePropertyChanged; _miningTransactionDialogViewModel = new SiftDialogViewModel { IsEthereumAnimatedLogoVisible = true, IsLogButtonVisible = true, Title = "Confirming SIFT Investment", Message = "Your transaction to invest in SIFT has been sent to the Ethereum network. Depending on the current network congestion it may take anywhere between a few seconds and minutes for the transaction to confirm. If the transaction does not confirm within a few minutes you can check your Ethereum wallet for more information." + Environment.NewLine + Environment.NewLine + "Please wait..." }; _miningTransactionDialog = new SiftDialog { DataContext = _miningTransactionDialogViewModel, Owner = Application.Current.MainWindow }; _miningTransactionDialogViewModel.CloseRequested += (s, e) => { _miningTransactionDialog.Close(); _miningTransactionDialog = null; _miningTransactionDialogViewModel = null; }; _miningTransactionDialog.ShowDialog(); }; if (Application.Current.Dispatcher.CheckAccess()) { act(); } else { Application.Current.Dispatcher.Invoke(act); } } } // Update the UI UpdateSiftPurchaseSettings(); }
/// <summary> /// This method is the main entry point for the ethereum checks and it is responsible for changing message content. /// </summary> private void ThreadEntry() { // Always check for updates first StatusText = "Checking for updates to sift-win..."; StatusHeader = "Please Wait..."; try { // Login to update API Logger.ApplicationInstance.Debug("Checking for updated version of SIFT"); AuthenticationClient authClient = new AuthenticationClient(); AuthenticateUserResponse authResponse = authClient.AuthenticateJwtAsync(new AuthenticateUserRequest { Username = "******", Password = "******" }).Result; if (authResponse == null) { throw new Exception("Null response when checking authentication details"); } // Call to get latest summary information ProductClient client = new ProductClient(); ProductSummaryResponse response = client.ProductSummaryGetAsync("D7682386-897C-4798-84B3-911EDEB8BD44", "BEARER " + authResponse?.JsonWebToken).Result; if (response == null) { throw new Exception("Null response when checking product details"); } // Determine any changes to state an update UI accordingly Logger.ApplicationInstance.Debug("Latest version is " + response.LatestVersion + " from " + response.LatestDownloadUrl); if (!string.IsNullOrEmpty(response.LatestVersion)) { Logger.ApplicationInstance.Info("A new version of SIFT - version " + response.LatestVersion + " is available from " + response.LatestDownloadUrl); Version version = Version.Parse(response.LatestVersion); if (!System.Diagnostics.Debugger.IsAttached) { if (Assembly.GetEntryAssembly().GetName().Version < version && SiftDialog.ShowDialog("SIFT Upgrade Available", "A new version of SIFT is available (" + version + "). Would you like to download it now?", true).Value) { System.Diagnostics.Process.Start(string.IsNullOrWhiteSpace(response.LatestDownloadUrl) ? "http://smartift.com/sift-win/latest" : response.LatestDownloadUrl); } } } } catch (Exception ex) { Logger.ApplicationInstance.Error("Failed to check for latest version", ex); } finally { } DateTime started = DateTime.UtcNow; StatusText = MessageConnecting; while (_isAlive) { // Break out of loop if we know what we're doing if (_ethereumManager.ContractPhase != ContractPhase.Unknown && !_ethereumManager.IsSyncing && _ethereumManager.LastChecksSuccessful && _ethereumManager.BlockNumber > 0 && _ethereumManager.Accounts.Count > 0) { break; } // If we've just gone over 5 seconds display a "this may be broken" message and enable exit button if (DateTime.UtcNow > started.AddSeconds(5) || _ethereumManager.LastChecksSuccessful) { StatusHeader = "Error!"; if (!_ethereumManager.LastChecksSuccessful || _ethereumManager.BlockNumber < 1) { StatusText = MessageDelayedStart; } else if (_ethereumManager.Accounts.Count < 1) { StatusText = MessageNoAddresses; } else if (_ethereumManager.IsSyncing) { StatusText = MessageSyncing; } else { StatusText = MessageUnknownContractState; } IsErrorState = true; } // Wait to retry Thread.Sleep(100); } // If we're still alive show appropriate window if (_isAlive) { // Show correct window and close the splash screen Action act = () => { Window mainWindow = Application.Current.MainWindow; Window newWindow; if (_ethereumManager.ContractPhase == ContractPhase.Ico) { newWindow = new IcoWindow { DataContext = new IcoViewModel(_ethereumManager) } } ; else { newWindow = new PostIcoWindow { DataContext = new PostIcoViewModel(_ethereumManager) } }; newWindow.Show(); Application.Current.MainWindow = newWindow; mainWindow.Close(); }; Application.Current.Dispatcher.BeginInvoke(act); } }