public async Task <IActionResult> ProcessSessionOnCounterChain([FromBody] CreateCounterChainSessionRequest createCounterChainSessionRequest)
        {
            Guard.NotNull(createCounterChainSessionRequest, nameof(createCounterChainSessionRequest));

            this.logger.LogTrace("({0}:'{1}',{2}:'{3}')", nameof(createCounterChainSessionRequest.BlockHeight), createCounterChainSessionRequest.BlockHeight, "Transactions Count", createCounterChainSessionRequest.CounterChainTransactionInfos.Count);

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                return(BuildErrorResponse(this.ModelState));
            }

            try
            {
                var result = await this.counterChainSessionManager.ProcessCounterChainSession(createCounterChainSessionRequest.BlockHeight);

                return(this.Json(result));
            }
            catch (InvalidOperationException e)
            {
                this.logger.LogError("Exception thrown calling /api/FederationGateway/process-session-oncounterchain: {0}.", e.Message);
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.NotFound, $"Could not create partial transaction session: {e.Message}", e.ToString()));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception thrown calling /api/FederationGateway/process-session-oncounterchain: {0}.", e.Message);
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, $"Could not create partial transaction session: {e.Message}", e.ToString()));
            }
        }
        // Calls into the counter chain and sets off the process to build the multi-sig transaction.
        private async Task <uint256> ProcessSessionOnCounterChain(int apiPortForSidechain, MonitorChainSession monitorChainSession)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}',{4}:'{5}')", nameof(apiPortForSidechain), apiPortForSidechain, nameof(monitorChainSession.BlockNumber), monitorChainSession.BlockNumber, "Transactions Count", monitorChainSession.CrossChainTransactions.Count);

            var createCounterChainSessionRequest = new CreateCounterChainSessionRequest
            {
                BlockHeight = monitorChainSession.BlockNumber,
                CounterChainTransactionInfos = monitorChainSession.CrossChainTransactions.Select(t => new CounterChainTransactionInfoRequest
                {
                    TransactionHash    = t.TransactionHash,
                    DestinationAddress = t.DestinationAddress,
                    Amount             = t.Amount.ToString()
                }).ToList()
            };

            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                var uri     = new Uri($"http://localhost:{apiPortForSidechain}/api/FederationGateway/process-session-oncounterchain");
                var request = new JsonContent(createCounterChainSessionRequest);

                try
                {
                    var httpResponseMessage = await client.PostAsync(uri, request);

                    this.logger.LogInformation("Response: {0}", await httpResponseMessage.Content.ReadAsStringAsync());

                    if (httpResponseMessage.StatusCode == System.Net.HttpStatusCode.NotFound)
                    {
                        return(uint256.One);
                    }

                    if (httpResponseMessage.StatusCode != System.Net.HttpStatusCode.OK)
                    {
                        this.logger.LogError("Error occurred when calling /api/FederationGateway/process-session-oncounterchain: {0}-{1}", httpResponseMessage.StatusCode, httpResponseMessage.ToString());
                        return(uint256.Zero);
                    }

                    string json = await httpResponseMessage.Content.ReadAsStringAsync();

                    return(JsonConvert.DeserializeObject <uint256>(json, new UInt256JsonConverter()));
                }
                catch (Exception e)
                {
                    this.logger.LogError(e, "Error occurred when calling /api/FederationGateway/process-session-oncounterchain: {0}", e.Message);
                    return(uint256.Zero);
                }
            }
        }
        public IActionResult CreateSessionOnCounterChain([FromBody] CreateCounterChainSessionRequest createCounterChainSessionRequest)
        {
            Guard.NotNull(createCounterChainSessionRequest, nameof(createCounterChainSessionRequest));

            this.logger.LogTrace("({0}:'{1}',{2}:'{3}')", nameof(createCounterChainSessionRequest.BlockHeight), createCounterChainSessionRequest.BlockHeight, "Transactions Count", createCounterChainSessionRequest.CounterChainTransactionInfos.Count);

            // checks the request is valid
            if (!this.ModelState.IsValid)
            {
                return(BuildErrorResponse(this.ModelState));
            }

            try
            {
                this.counterChainSessionManager.CreateSessionOnCounterChain(createCounterChainSessionRequest.BlockHeight, createCounterChainSessionRequest.CounterChainTransactionInfos);
                return(this.Ok());
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception thrown calling /api/FederationGateway/create-session-oncounterchain: {0}.", e.Message);
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, $"Could not create session on counter chain: {e.Message}", e.ToString()));
            }
        }
        // Calls into the counter chain and registers the session there.
        public void CreateSessionOnCounterChain(int apiPortForSidechain, MonitorChainSession monitorChainSession)
        {
            this.logger.LogTrace("({0}:'{1}',{2}:'{3}',{4}:'{5}')", nameof(apiPortForSidechain), apiPortForSidechain, nameof(monitorChainSession.BlockNumber), monitorChainSession.BlockNumber, "Transactions Count", monitorChainSession.CrossChainTransactions.Count);

            var createCounterChainSessionRequest = new CreateCounterChainSessionRequest
            {
                BlockHeight = monitorChainSession.BlockNumber,
                CounterChainTransactionInfos = monitorChainSession.CrossChainTransactions.Select(t => new CounterChainTransactionInfoRequest
                {
                    TransactionHash    = t.TransactionHash,
                    DestinationAddress = t.DestinationAddress,
                    Amount             = t.Amount.ToString()
                }).ToList()
            };

            using (var client = new HttpClient())
            {
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                var uri     = new Uri($"http://localhost:{apiPortForSidechain}/api/FederationGateway/create-session-oncounterchain");
                var request = new JsonContent(createCounterChainSessionRequest);

                try
                {
                    var    httpResponseMessage = client.PostAsync(uri, request).ConfigureAwait(false).GetAwaiter().GetResult();
                    string json = httpResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(false).GetAwaiter().GetResult();
                }
                catch (Exception e)
                {
                    this.logger.LogError(e, "Error occurred when calling /api/FederationGateway/create-session-oncounterchain: {0}", e.Message);
                }
            }

            this.logger.LogTrace("(-)");
        }