private void ProcessNodeLogs(BlockchainNode node, string logFileFullName) { try { string deploymentKey = node.NodeEndpoint.FullNodeName + logFileFullName; NodeLogObject logFile; if (openFiles.ContainsKey(deploymentKey)) { logFile = openFiles[deploymentKey]; } else { logFile = new NodeLogObject(node, logFileFullName); openFiles.Add(deploymentKey, logFile); } logFile.ReadLogFile(); if (logFile.IsClosed) { openFiles.Remove(deploymentKey); } } catch (Exception ex) { logger.Error(ex, $"{node.NodeEndpoint.FullNodeName} Cannot read log file"); } }
public void UpdateDataTable(DatabaseConnection database, BlockchainNode node) { List <ConnectionPeer> peers = node.NodeState.NodeOperationState.Peers; if (peers == null || !peers.Any()) { return; } if (!int.TryParse(node.NodeState.NodeLogState.HeadersHeight, out int nodeHight)) { nodeHight = 0; } int maxTip = Math.Max(peers.Max(p => p.TipHeight), nodeHight); foreach (ConnectionPeer connectionPeer in peers) { foreach (DataRow dataRow in DataTable.Rows) { if (((ConnectionPeer)dataRow["Address"]).RemoteSocketEndpoint == connectionPeer.RemoteSocketEndpoint) { dataRow[DataTable.Columns.IndexOf("Type")] = connectionPeer.PeerType; dataRow["Address"] = connectionPeer; CreateColumnIfNotExist("TipHeight", "TipHeight", typeof(string), 50); dataRow["TipHeight"] = $"{connectionPeer.TipHeight} ({connectionPeer.TipHeight - maxTip})"; CreateColumnIfNotExist("Version", "Agent", typeof(string), 80); dataRow["Version"] = connectionPeer.Version; } } } }
private void StartNode() { string compilerSwitches = ClientAction.Parameters[ActionParameters.CompilerSwitches]; string runtimeSwitches = ClientAction.Parameters[ActionParameters.RuntimeSwitches]; NetworkType network; NetworkType.TryParse(ClientAction.Parameters[ActionParameters.Network], out network); string dataDir = ClientAction.Parameters[ActionParameters.DataDir]; string workingDirectory = ClientAction.Parameters[ActionParameters.WorkingDirectory]; string networkSwitch = $"-{network}"; ProcessStartInfo startInfo = new ProcessStartInfo("dotnet", $"run {compilerSwitches}{networkSwitch} -datadir={dataDir}{runtimeSwitches}"); startInfo.WorkingDirectory = workingDirectory; startInfo.RedirectStandardError = false; startInfo.RedirectStandardOutput = false; Process process = new Process(); process.StartInfo = startInfo; process.Start(); BlockchainNode node = Client.Session.ManagedNodes.GetNode(ClientAction.FullNodeName); string pidFilePath = Path.Combine(node.NodeConfig.NetworkDirectory, "PID"); if (File.Exists(pidFilePath)) { File.Delete(pidFilePath); } File.WriteAllText(pidFilePath, process.Id.ToString()); }
public override void SendData() { logger.Debug($"Updating node measures"); List <Task> updateTasks = new List <Task>(); foreach (String nodeName in Session.ManagedNodes.Nodes.Keys.ToList()) { BlockchainNode node = Session.ManagedNodes.Nodes[nodeName]; updateTasks.AddRange(UpdateNodeData(node)); node.NodeState.Initialized = true; } Task.WaitAll(updateTasks.ToArray()); LastUpdateTimestamp = DateTime.Now; UpdateCount++; BlockchainNodeState[] nodesStatistics = (from n in Session.ManagedNodes.Nodes select n.Value.NodeState).ToArray(); BlockchainNodeStateMessage blockchainNodeStateMessage = new BlockchainNodeStateMessage(); blockchainNodeStateMessage.NodesStatistics = nodesStatistics; UpdateEventArgs args = new UpdateEventArgs() { MessageType = MessageType.NodeStatistics, Scope = ResourceScope.Global, CorrelationId = blockchainNodeStateMessage.CorrelationId, Data = blockchainNodeStateMessage }; OnUpdate(this, args); }
public void StopNode(BlockchainNode node, ResponseHandler.DispatherCallback dispatherCallback) { ActionRequest action = new ActionRequest(ActionType.StopNode); action.FullNodeName = node.NodeEndpoint.FullNodeName; actionQueue.Enqueue(action); }
public void StopNode(BlockchainNode node) { ActionRequest action = new ActionRequest(ActionType.StopNode); action.FullNodeName = node.NodeEndpoint.FullNodeName; actionQueue.Enqueue(action); }
private void dataGridViewNodes_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e) { if (e.StateChanged != DataGridViewElementStates.Selected && e.StateChanged != DataGridViewElementStates.None) { return; } if (dataGridViewNodes.SelectedRows.Count == 0) { return; } BlockchainNode node = (BlockchainNode)dataGridViewNodes.SelectedRows[0].Cells["Node"].Value; if (node == null) { return; } if (!node.NodeState.Initialized) { tabPageOverview.Enabled = false; } else { tabPageOverview.Enabled = true; } linkLabelRepositoryUrl.Text = node.GitRepositoryInfo.RepositoryUrl; labelCurrentBranch.Text = node.GitRepositoryInfo.CurrentBranchName; labelNumberOfCommitsBehind.Text = node.GitRepositoryInfo.CommitDifference; labelLastUpdateDate.Text = node.GitRepositoryInfo.LatestLocalCommitDateTime.ToString("dd MMM yyyy"); labelLastUpdateTime.Text = node.GitRepositoryInfo.LatestLocalCommitDateTime.ToString("HH:mm"); labelLastUpdateTimeAgo.Text = "(" + (DateTime.Now - node.GitRepositoryInfo.LatestLocalCommitDateTime).ToHumanReadable() + ")"; labelLastUpdateAuthor.Text = node.GitRepositoryInfo.LatestLocalCommitAuthor; labelLastUpdateMessage.Text = node.GitRepositoryInfo.LatestLocalCommitMessage; toolTipHelp.SetToolTip(this.labelLastUpdateMessage, node.GitRepositoryInfo.LatestLocalCommitMessage); labelDaemonName.Text = node.NodeConfig.DaemonName; labelStartupOptions.Text = node.NodeConfig.StartupSwitches; labelBlockchainName.Text = node.NodeEndpoint.NodeNetworkName; labelNetworkName.Text = node.NodeEndpoint.NodeBlockchainName; labelDataDir.Text = node.NodeConfig.DataDir; labelDataDirSize.Text = "(" + node.NodeState.NodeDeploymentState.DataDirSize + ")"; labelHeaderHeight.Text = node.NodeState.NodeLogState.HeadersHeight; labelConsensusHeight.Text = node.NodeState.NodeLogState.ConsensusHeight; labelBlockHeight.Text = node.NodeState.NodeLogState.BlockStoreHeight; labelWalletHeight.Text = node.NodeState.NodeLogState.WalletHeight; labelNetworkHeight.Text = node.NodeState.NodeOperationState.NetworkHeight.ToString(); labelOutboundPeers.Text = node.NodeState.NodeOperationState.OutboundPeersCount.ToString(); labelInboundPeers.Text = node.NodeState.NodeOperationState.InboundPeersCount.ToString(); labelBannedPeers.Text = node.NodeState.NodeOperationState.BannedPeersCount.ToString(); textBoxCodeDirectory.Text = node.NodeConfig.CodeDirectory; textBoxNetworkDirectory.Text = node.NodeConfig.NetworkDirectory; List <NodeLogMessage> logMessages = clientConnectionManager.Session.Database.GetLogMessages(node.NodeEndpoint.FullNodeName); dataGridViewNodeExceptions.UpdateNodes(logMessages, e.StateChanged == DataGridViewElementStates.None); dataGridViewPeers.UpdateNodes(node, clientConnectionManager.Session.Database); }
public void RemoveResource(BlockchainNode node, NodeResourceType resourceType, ResponseHandler.DispatherCallback dispatherCallback) { ActionRequest action = new ActionRequest(ActionType.DeleteFile); action.FullNodeName = node.NodeEndpoint.FullNodeName; NodeResource nodeResource = NodeResourceLocator.NodeResources[resourceType]; action.Parameters.Add(ActionParameters.Path, ClientConfigReader.Evaluate(nodeResource.ResourceLocation, node.NodeConfig)); actionQueue.Enqueue(action); }
public void GitPull(BlockchainNode node, ResponseHandler.DispatherCallback dispatherCallback) { ActionRequest action = new ActionRequest(ActionType.GitPull); action.FullNodeName = node.NodeEndpoint.FullNodeName; action.Parameters.Add(ActionParameters.WorkingDirectory, Path.Combine(node.NodeConfig.CodeDirectory, node.NodeConfig.ProjectDirectory)); actionQueue.Enqueue(action); }
private void GetBlockCount(BlockchainNode node) { if (node.NodeState.NodeOperationState.State != ProcessState.Running) { return; } BlockchainNodeConfig config = BlockchainConfig.GetNodeConfig(node.NodeConfig.NodeConfigFullName); int apiPort = config.GetApiPort(); node.NodeState.NodeOperationState.BlockHeight = BufferedRequestCaller.GetRpcResult <int>(RequestType.RpcGetBlockCount, node.NodeEndpoint.FullNodeName, apiPort); }
public void StartNode(BlockchainNode node) { ActionRequest action = new ActionRequest(ActionType.StartNode); action.FullNodeName = node.NodeEndpoint.FullNodeName; action.Parameters.Add(ActionParameters.CompilerSwitches, "--no-build"); action.Parameters.Add(ActionParameters.RuntimeSwitches, ""); action.Parameters.Add(ActionParameters.IsTestNet, node.NodeEndpoint.IsTestnet.ToString()); action.Parameters.Add(ActionParameters.DataDir, node.NodeConfig.DataDir); action.Parameters.Add(ActionParameters.WorkingDirectory, Path.Combine(node.NodeConfig.CodeDirectory, node.NodeConfig.ProjectDirectory)); actionQueue.Enqueue(action); }
public override List <Task> UpdateJob(BlockchainNode node) { List <Task> tasks = new List <Task>(); if (node.NodeState.NodeProcessState == null) { node.NodeState.NodeProcessState = new NodeProcessState(); } Task checkNodeFilesTask = Task.Run(() => CheckNodeProcessState(node)); tasks.Add(checkNodeFilesTask); return(tasks); }
private void StopNode() { BlockchainNode node = Client.Session.ManagedNodes.GetNode(ClientAction.FullNodeName); if (node == null) { logger.Error($"Cannot find node {ClientAction.FullNodeName}"); return; } BlockchainNodeConfig config = BlockchainConfig.GetNodeConfig(node.NodeConfig.NodeConfigFullName); int apiPort = config.GetApiPort(); BufferedRequestCaller.GetApiResult <string>(RequestType.ApiNodeShutdown, ClientAction.FullNodeName, apiPort); }
public override List <Task> UpdateJob(BlockchainNode node) { List <Task> tasks = new List <Task>(); if (node.NodeState.NodeOperationState == null) { node.NodeState.NodeOperationState = new NodeOperationState(); } tasks.Add(Task.Run(() => GetNodeStatus(node))); tasks.Add(Task.Run(() => GetBlockCount(node))); tasks.Add(Task.Run(() => GetMemoryPoolTransactions(node))); return(tasks); }
private void GetNodeStatus(BlockchainNode node) { BlockchainNodeConfig config = BlockchainConfig.GetNodeConfig(node.NodeConfig.NodeConfigFullName); int apiPort = config.GetApiPort(); NodeStatus nodeStatus = BufferedRequestCaller.GetApiResult <NodeStatus>(RequestType.ApiNodeStatus, node.NodeEndpoint.FullNodeName, apiPort); if (nodeStatus == null) { node.NodeState.NodeOperationState.State = ProcessState.Stopped; return; } node.NodeState.NodeOperationState.State = ProcessState.Running; node.NodeState.NodeOperationState.AgentName = nodeStatus.Agent; node.NodeState.NodeOperationState.Version = nodeStatus.Version; node.NodeState.NodeOperationState.Network = nodeStatus.Network; node.NodeState.NodeOperationState.ConsensusHeight = nodeStatus.ConsensusHeight; node.NodeState.NodeOperationState.Peers.Clear(); foreach (Peer inboundPeer in nodeStatus.InboundPeers) { ConnectionPeer peer = new ConnectionPeer(); peer.PeerType = PeerType.Inbound; peer.RemoteSocketEndpoint = inboundPeer.RemoteSocketEndpoint; peer.TipHeight = inboundPeer.TipHeight; peer.Version = inboundPeer.Version; node.NodeState.NodeOperationState.Peers.Add(peer); } foreach (Peer outboundPeer in nodeStatus.OutboundPeers) { ConnectionPeer peer = new ConnectionPeer(); peer.PeerType = PeerType.Inbound; peer.RemoteSocketEndpoint = outboundPeer.RemoteSocketEndpoint; peer.TipHeight = outboundPeer.TipHeight; peer.Version = outboundPeer.Version; node.NodeState.NodeOperationState.Peers.Add(peer); } node.NodeState.NodeOperationState.DataDirectory = nodeStatus.DataDirectoryPath; node.NodeState.NodeOperationState.Uptime = nodeStatus.RunningTime; int maxInboundTipHeight = nodeStatus.InboundPeers.Any() ? nodeStatus.InboundPeers.Max(p => p.TipHeight) : 0; int maxOutboundTipHeight = nodeStatus.OutboundPeers.Any() ? nodeStatus.OutboundPeers.Max(p => p.TipHeight) : 0; node.NodeState.NodeOperationState.NetworkHeight = Math.Max(maxInboundTipHeight, maxOutboundTipHeight); }
public CoinMasterForm() { InitializeComponent(); buttonEditNodeProfile_Click(null, EventArgs.Empty); ReadNodeProfiles(); //Create pop-up notifier = new Tulpep.NotificationWindow.PopupNotifier(); notifier.Delay = 10000; notifier.Click += (sender, eventArgs) => { Visible = true; BringToFront(); }; //Create workers cryptoIdWorker = new CryptoIdWorker(60000, new NodeEndpointName("Stratis", "StratisTest")); cryptoIdWorker.StateChange += DashboardWorkerStateChanged; cryptoIdWorker.DataUpdate += (source, args) => Invoke(new Action <object, CryptoIdDataUpdateEventArgs>(CryptoIdUpdated), source, args); _workers.Add(cryptoIdWorker); //Start all workers foreach (BaseWorker worker in _workers) { worker.Start(); } ClientConfigReader reader = new ClientConfigReader(); clientConfig = reader.ReadConfig(); List <String> agentList = clientConfig.GetAgentList(); this.managedNodes = new NodeNetwork(); foreach (string fullNodeName in clientConfig.NodeItems.Keys) { BlockchainNode blockchainNode = new BlockchainNode(clientConfig.NodeItems[fullNodeName]); this.managedNodes.Nodes.Add(fullNodeName, blockchainNode); } clientConnectionManager = new AgentConnectionManager(managedNodes); clientConnectionManager.Session.AgentHealthcheckStatsUpdated += (agentConnection, state, message) => Invoke(new Action <AgentConnection, AgentHealthState, String>(AgentDataTableUpdated), agentConnection, state, message); clientConnectionManager.Session.NodesUpdated += (agentConnection, updatedNodes) => Invoke(new Action <AgentConnection, NodeNetwork>(NodeDataUpdated), agentConnection, updatedNodes); clientConnectionManager.Session.AgentRegistrationUpdated += (agentConnection, agentRegistration) => Invoke(new Action <AgentConnection, AgentRegistration>(AgentRegistrationUpdated), agentConnection, agentRegistration); clientConnectionManager.ConnectToAgents(agentList); }
public void StartNode(BlockchainNode node, ResponseHandler.DispatherCallback dispatherCallback) { ActionRequest action = new ActionRequest(ActionType.StartNode); action.DispatherResponseReceived += dispatherCallback; action.FullNodeName = node.NodeEndpoint.FullNodeName; action.Parameters.Add(ActionParameters.CompilerSwitches, node.NodeConfig.CompilerSwitches); action.Parameters.Add(ActionParameters.RuntimeSwitches, node.NodeConfig.StartupSwitches); action.Parameters.Add(ActionParameters.Network, node.NodeEndpoint.Network.ToString()); action.Parameters.Add(ActionParameters.DataDir, node.NodeConfig.DataDir); action.Parameters.Add(ActionParameters.WorkingDirectory, Path.Combine(node.NodeConfig.CodeDirectory, node.NodeConfig.ProjectDirectory)); actionQueue.Enqueue(action); }
private void SendAction(Action <NodeActionDispatcher, BlockchainNode> action) { if (dataGridViewNodes.SelectedRows.Count == 0) { return; } foreach (DataGridViewRow row in dataGridViewNodes.SelectedRows) { BlockchainNode node = (BlockchainNode)row.Cells["Node"].Value; var agent = clientConnectionManager.GetAgent(node.NodeConfig.Agent); NodeActionDispatcher dispatcher = (NodeActionDispatcher)agent.Dispatchers[MessageType.ActionRequest]; action.Invoke(dispatcher, node); } }
public override List <Task> UpdateJob(BlockchainNode node) { List <Task> tasks = new List <Task>(); if (node.NodeState.NodeLogState == null) { node.NodeState.NodeLogState = new NodeLogState(); } string logFileFullName = Path.Combine(node.NodeConfig.NetworkDirectory, "Logs", "node.txt"); Task checkNodeFilesTask = Task.Run(() => ProcessNodeLogs(node, logFileFullName)); tasks.Add(checkNodeFilesTask); return(tasks); }
public void UpdateNodes(BlockchainNode node, DatabaseConnection database) { Mapper.MergeDataRows(node.NodeState.NodeOperationState.Peers); Mapper.UpdateDataTable(database, node); if (this.DataSource == null) { ConfigureDataGridView(); } if (SelectedRows.Count > 0) { DataGridViewRow selectedRow = SelectedRows[0]; DataGridViewRowStateChangedEventArgs e = new DataGridViewRowStateChangedEventArgs(selectedRow, DataGridViewElementStates.None); this.OnRowStateChanged(selectedRow.Index, e); } }
private void RemoveResourceForSelectedNodes(NodeResourceType resourceType) { if (dataGridViewNodes.SelectedRows.Count == 0) { return; } foreach (DataGridViewRow row in dataGridViewNodes.SelectedRows) { BlockchainNode node = (BlockchainNode)row.Cells["Node"].Value; var agent = clientConnectionManager.GetAgent(node.NodeConfig.Agent); NodeActionDispatcher dispatcher = (NodeActionDispatcher)agent.Dispatchers[MessageType.ActionRequest]; dispatcher.RemoveResource(node, resourceType); } }
private void buttonDeployFiles_Click(object sender, EventArgs e) { if (dataGridViewNodes.SelectedRows.Count == 0) { return; } foreach (DataGridViewRow row in dataGridViewNodes.SelectedRows) { BlockchainNode node = (BlockchainNode)row.Cells["Node"].Value; var agent = clientConnectionManager.GetAgent(node.NodeConfig.Agent); ResourceFromClientDispatcher dispatcher = (ResourceFromClientDispatcher)agent.Dispatchers[MessageType.ResourceFromClient]; dispatcher.DeployFile(clientConfig, ResourceScope.Node, node.NodeEndpoint.FullNodeName); } }
private void linkLabelSwitchBranch_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) { if (dataGridViewNodes.SelectedRows.Count == 0) { return; } if (dataGridViewNodes.SelectedRows.Count > 1) { MessageBox.Show("No more than 1 node can be celected for this operation", "Bulk Operation", MessageBoxButtons.OK, MessageBoxIcon.Information); } DataGridViewRow row = dataGridViewNodes.SelectedRows[0]; BlockchainNode node = (BlockchainNode)row.Cells["Node"].Value; //ToDo: Create pop-up to select branch and send command to agent }
public BlockchainNodeTests() { _receiver = A.Fake <IReceiver>(); _parameters = new StaticNetworkParameters() { BlockTime = TimeSpan.FromSeconds(1) }; _loggerFactory = A.Fake <ILoggerFactory>(); _blockRepository = A.Fake <IBlockRepository>(); _blockVerifier = A.Fake <IBlockVerifier>(); _forkRebaser = A.Fake <IForkRebaser>(); _peerNetwork = A.Fake <IPeerNetwork>(); _unconfirmedTransactionPool = A.Fake <IUnconfirmedTransactionPool>(); _difficultyCalculator = A.Fake <IDifficultyCalculator>(); _subject = new BlockchainNode(_blockRepository, _blockVerifier, _receiver, _loggerFactory, _forkRebaser, _parameters, _unconfirmedTransactionPool, _peerNetwork, _difficultyCalculator); _subject.PollTimer.Dispose(); }
private List <Task> UpdateNodeData(BlockchainNode node) { List <Task> updateTasks = new List <Task>(); foreach (StatusProbeBase statusProbe in statusProbes) { try { List <Task> tasks = statusProbe.UpdateJob(node); updateTasks.AddRange(tasks); } catch (Exception ex) { logger.Error(ex, $"Cannot get NodeDeploymentState"); } } return(updateTasks); }
private void GetMemoryPoolTransactions(BlockchainNode node) { if (node.NodeState.NodeOperationState.State != ProcessState.Running) { return; } BlockchainNodeConfig config = BlockchainConfig.GetNodeConfig(node.NodeConfig.NodeConfigFullName); int apiPort = config.GetApiPort(); string[] mempoolTransactions = BufferedRequestCaller.GetRpcResult <string[]>(RequestType.RpcGetRawMempool, node.NodeEndpoint.FullNodeName, apiPort); if (mempoolTransactions == null) { node.NodeState.NodeOperationState.MempoolTransactionCount = 0; return; } node.NodeState.NodeOperationState.MempoolTransactionCount = mempoolTransactions != null ? mempoolTransactions.Length : 0; }
public void MergeDataRows(NodeNetwork managedNodes) { //Remove nodes not managed by agent List <DataRow> rowsToDelete = new List <DataRow>(); foreach (DataRow row in DataTable.Rows) { BlockchainNode node = (BlockchainNode)row["Node"]; if (!managedNodes.Nodes.ContainsKey(node.NodeEndpoint.FullNodeName)) { rowsToDelete.Add(row); } } foreach (DataRow row in rowsToDelete) { DataTable.Rows.Remove(row); } //Add and update nodes foreach (string nodeName in managedNodes.Nodes.Keys) { BlockchainNode node = managedNodes.Nodes[nodeName]; var matchingNodes = from DataRow r in DataTable.Rows let nodeInDataTable = (BlockchainNode)r["Node"] where nodeInDataTable.NodeEndpoint.FullNodeName == node.NodeEndpoint.FullNodeName select r; if (!matchingNodes.Any()) { object[] rowData = new object[2]; CreateColumnIfNotExist("Status", "", typeof(Bitmap), 16); rowData[DataTable.Columns.IndexOf("Status")] = StatusIconProvider.GrayCircle; CreateColumnIfNotExist("Node", "Node", typeof(BlockchainNode), 130); rowData[DataTable.Columns.IndexOf("Node")] = node; DataTable.Rows.Add(rowData); } } }
private void GitPull() { BlockchainNode node = Client.Session.ManagedNodes.GetNode(ClientAction.FullNodeName); if (node == null) { logger.Error($"Cannot find node {ClientAction.FullNodeName}"); return; } if (!Client.Session.GitRepositoryMonitor.GitRepositories.ContainsKey(node.NodeConfig.CodeDirectory)) { logger.Warn($"Cannot find code repository \"{node.NodeConfig.CodeDirectory}\""); return; } GitRepository gitRepository = Client.Session.GitRepositoryMonitor.GitRepositories[node.NodeConfig.CodeDirectory]; gitRepository.Pull(); }
static void Main(string[] args) { AssertionHandler.CatchAssertions(); PrivateLock.OnDeadLock += () => Console.WriteLine("!!!!!!!!!!!!! DEADLOCK !!!!!!!!!!!!"); var services = new ServiceManager(); var node = new BlockchainNode(services); var explorer = new BlockchainExplorer(services); Console.WriteLine("Initializing..."); services.Initialize(); Console.WriteLine("Starting..."); services.Start(); Console.WriteLine("Running..."); var console = new ConsoleCommandProcessor(typeof(Program).Assembly); console.Initialize(); console.Run(); }
private static void Main(string[] args) { AssertionHandler.CatchAssertions(); PrivateLock.OnDeadLock += () => Console.WriteLine("!!!!!!!!!!!!! DEADLOCK !!!!!!!!!!!!"); var services = new ServiceManager(); var node = new BlockchainNode(services); var wallet = (IWalletService) new WalletService(); services.Add(wallet); wallet.AddressListener.RegisterWalletUpdated(input => { var verb = input.IsInput ? "Sent" : "Received"; var amount = Amount.ToWholeDecimal(input.Amount); var currency = Currency.ToSymbol(input.Currency); Console.WriteLine($"{verb} {input.Address.Encoded} {amount} {currency}"); }); wallet.TransactionSubmissionListener.OnSuccess += (transaction, elapsed) => { Console.WriteLine($"Transaction Included ! Elapsed Time {elapsed.TotalSeconds}s"); }; Console.WriteLine("Initializing..."); services.Initialize(); Console.WriteLine("Starting..."); services.Start(); Console.WriteLine("Running..."); var console = new ConsoleCommandProcessor(typeof(SetActiveKeyCommand).Assembly); console.Initialize(); console.RunCommand("loadinstructions", new [] { Configuration.InstructionsFile }); if (!wallet.GetPrivateKeys().Any()) { console.RunCommand("initializewallet", new string[0]); } console.Run(); }