public void Setup()
        {
            Credential = TestEnvironment.Credential;
            var httpHandler = new HttpClientHandler();

            httpHandler.ServerCertificateCustomValidationCallback = (_, _, _, _) => true;
            Options = new ConfidentialLedgerClientOptions {
                Transport = new HttpClientTransport(httpHandler)
            };
            Client = InstrumentClient(
                new ConfidentialLedgerClient(
                    TestEnvironment.ConfidentialLedgerUrl,
                    Credential,
                    InstrumentClientOptions(Options)));

            IdentityClient = InstrumentClient(
                new ConfidentialLedgerIdentityServiceClient(
                    TestEnvironment.ConfidentialLedgerIdentityUrl,
                    Credential,
                    InstrumentClientOptions(Options)));
        }
        public void HelloWorld()
        {
            #region Snippet:GetIdentity

#if SNIPPET
            Uri identityServiceUri = "<the identity service uri>";
#else
            Uri identityServiceUri = TestEnvironment.ConfidentialLedgerIdentityUrl;
#endif
            var identityClient = new ConfidentialLedgerIdentityServiceClient(identityServiceUri, new Identity.DefaultAzureCredential());

            // Get the ledger's  TLS certificate for our ledger.
#if SNIPPET
            string ledgerId = "<the ledger id>"; // ex. "my-ledger" from "https://my-ledger.eastus.cloudapp.azure.com"
#else
            var ledgerId = TestEnvironment.ConfidentialLedgerUrl.Host;
            ledgerId = ledgerId.Substring(0, ledgerId.IndexOf('.'));
#endif
            Response response = identityClient.GetLedgerIdentity(ledgerId);

            // extract the ECC PEM value from the response.
            var eccPem = JsonDocument.Parse(response.Content)
                         .RootElement
                         .GetProperty("ledgerTlsCertificate")
                         .GetString();

            // construct an X509Certificate2 with the ECC PEM value.
            X509Certificate2 ledgerTlsCert = new X509Certificate2(Encoding.UTF8.GetBytes(eccPem));

            #endregion

            #region Snippet:CreateClient

            // Create a certificate chain rooted with our TLS cert.
            X509Chain certificateChain = new();
            certificateChain.ChainPolicy.RevocationMode      = X509RevocationMode.NoCheck;
            certificateChain.ChainPolicy.RevocationFlag      = X509RevocationFlag.ExcludeRoot;
            certificateChain.ChainPolicy.VerificationFlags   = X509VerificationFlags.AllowUnknownCertificateAuthority;
            certificateChain.ChainPolicy.VerificationTime    = DateTime.Now;
            certificateChain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 0, 0);
            certificateChain.ChainPolicy.ExtraStore.Add(ledgerTlsCert);

            // Define a validation function to ensure that the ledger certificate is trusted by the ledger identity TLS certificate.
            bool CertValidationCheck(HttpRequestMessage httpRequestMessage, X509Certificate2 cert, X509Chain x509Chain, SslPolicyErrors sslPolicyErrors)
            {
                bool isChainValid = certificateChain.Build(cert);

                if (!isChainValid)
                {
                    return(false);
                }

                var isCertSignedByTheTlsCert = certificateChain.ChainElements.Cast <X509ChainElement>()
                                               .Any(x => x.Certificate.Thumbprint == ledgerTlsCert.Thumbprint);

                return(isCertSignedByTheTlsCert);
            }

            // Create an HttpClientHandler to use our certValidationCheck function.
            var httpHandler = new HttpClientHandler();
            httpHandler.ServerCertificateCustomValidationCallback = CertValidationCheck;

            // Create the ledger client using a transport that uses our custom ServerCertificateCustomValidationCallback.
            var options = new ConfidentialLedgerClientOptions {
                Transport = new HttpClientTransport(httpHandler)
            };
            var ledgerClient = new ConfidentialLedgerClient(TestEnvironment.ConfidentialLedgerUrl, new DefaultAzureCredential(), options);

            #endregion

            #region Snippet:AppendToLedger

            Response postResponse = ledgerClient.PostLedgerEntry(
                RequestContent.Create(
                    new { contents = "Hello world!" }));

            postResponse.Headers.TryGetValue(ConfidentialLedgerConstants.TransactionIdHeaderName, out string transactionId);
            Console.WriteLine($"Appended transaction with Id: {transactionId}");

            #endregion

            #region Snippet:GetStatus

            Response statusResponse = ledgerClient.GetTransactionStatus(transactionId);

            string status = JsonDocument.Parse(statusResponse.Content)
                            .RootElement
                            .GetProperty("state")
                            .GetString();

            Console.WriteLine($"Transaction status: {status}");

            #endregion

            #region Snippet:GetReceipt

            Response receiptResponse = ledgerClient.GetReceipt(transactionId);
            string   receiptJson     = new StreamReader(receiptResponse.ContentStream).ReadToEnd();

            Console.WriteLine(receiptJson);

            #endregion

            #region Snippet:SubLedger

            ledgerClient.PostLedgerEntry(
                RequestContent.Create(
                    new { contents = "Hello from Chris!", subLedgerId = "Chris' messages" }));

            ledgerClient.PostLedgerEntry(
                RequestContent.Create(
                    new { contents = "Hello from Allison!", subLedgerId = "Allison's messages" }));

            #endregion

            #region Snippet:NoSubLedgerId

#if SNIPPET
            Response postResponse = ledgerClient.PostLedgerEntry(
#else
            postResponse = ledgerClient.PostLedgerEntry(
#endif
                RequestContent.Create(
                    new { contents = "Hello world!" }));
#if SNIPPET
            postResponse.Headers.TryGetValue(ConfidentialLedgerConstants.Headers.TransactionId, out string transactionId);
#else
            postResponse.Headers.TryGetValue(ConfidentialLedgerConstants.TransactionIdHeaderName, out transactionId);
#endif
            string subLedgerId = JsonDocument.Parse(statusResponse.Content)
                                 .RootElement
                                 .GetProperty("subLedgerId")
                                 .GetString();

            // Provide both the transactionId and subLedgerId.
            Response getBySubledgerResponse = ledgerClient.GetLedgerEntry(transactionId, subLedgerId);

            string contents = JsonDocument.Parse(getBySubledgerResponse.Content)
                              .RootElement
                              .GetProperty("contents")
                              .GetString();

            Console.WriteLine(contents); // "Hello world!"

            // Now just provide the transactionId.
            getBySubledgerResponse = ledgerClient.GetLedgerEntry(transactionId);

            string subLedgerId2 = JsonDocument.Parse(getBySubledgerResponse.Content)
                                  .RootElement
                                  .GetProperty("subLedgerId")
                                  .GetString();

            Console.WriteLine($"{subLedgerId} == {subLedgerId2}");

            #endregion

            #region Snippet:GetEnteryWithNoTransactionId

            Response firstPostResponse = ledgerClient.PostLedgerEntry(
                RequestContent.Create(new { contents = "Hello world 0" }));
            ledgerClient.PostLedgerEntry(
                RequestContent.Create(new { contents = "Hello world 1" }));
            Response subLedgerPostResponse = ledgerClient.PostLedgerEntry(
                RequestContent.Create(new { contents = "Hello world sub-ledger 0" }),
                "my sub-ledger");
            ledgerClient.PostLedgerEntry(
                RequestContent.Create(new { contents = "Hello world sub-ledger 1" }),
                "my sub-ledger");

#if SNIPPET
            firstPostResponse.Headers.TryGetValue(ConfidentialLedgerConstants.Headers.TransactionId, out string transactionId);
#else
            firstPostResponse.Headers.TryGetValue(ConfidentialLedgerConstants.TransactionIdHeaderName, out transactionId);
#endif

            // The ledger entry written at the transactionId in firstResponse is retrieved from the default sub-ledger.
            Response getResponse        = ledgerClient.GetLedgerEntry(transactionId);
            string   firstEntryContents = JsonDocument.Parse(getResponse.Content)
                                          .RootElement
                                          .GetProperty("contents")
                                          .GetString();

            Console.WriteLine(firstEntryContents); // "Hello world 0"

            // This will return the latest entry available in the default sub-ledger.
            getResponse = ledgerClient.GetCurrentLedgerEntry();
            string latestDefaultSubLedger = JsonDocument.Parse(getResponse.Content)
                                            .RootElement
                                            .GetProperty("contents")
                                            .GetString();

            Console.WriteLine($"The latest ledger entry from the default sub-ledger is {latestDefaultSubLedger}"); //"Hello world 1"

            // The ledger entry written at subLedgerTransactionId is retrieved from the sub-ledger 'sub-ledger'.
            subLedgerPostResponse.Headers.TryGetValue(ConfidentialLedgerConstants.TransactionIdHeaderName, out string subLedgerTransactionId);
            getResponse           = ledgerClient.GetLedgerEntry(subLedgerTransactionId, "my sub-ledger");
            string subLedgerEntry = JsonDocument.Parse(getResponse.Content)
                                    .RootElement
                                    .GetProperty("contents")
                                    .GetString();

            Console.WriteLine(subLedgerEntry); // "Hello world sub-ledger 0"

            // This will return the latest entry available in the sub-ledger.
            getResponse            = ledgerClient.GetCurrentLedgerEntry("my sub-ledger");
            string latestSubLedger = JsonDocument.Parse(getResponse.Content)
                                     .RootElement
                                     .GetProperty("contents")
                                     .GetString();

            Console.WriteLine($"The latest ledger entry from the sub-ledger is {latestSubLedger}"); // "Hello world sub-ledger 1"

            #endregion

            #region Snippet:RangedQuery

            ledgerClient.GetLedgerEntries(fromTransactionId: "2.1", toTransactionId: "4.5");

            #endregion

            #region Snippet:NewUser

            string newUserAadObjectId = "<some AAD user or service princpal object Id>";
            ledgerClient.CreateOrUpdateUser(
                newUserAadObjectId,
                RequestContent.Create(new { assignedRole = "Reader" }));

            #endregion

            #region Snippet:Consortium

            Response consortiumResponse = ledgerClient.GetConsortiumMembers();
            string   membersJson        = new StreamReader(consortiumResponse.ContentStream).ReadToEnd();

            // Consortium members can manage and alter the Confidential Ledger, such as by replacing unhealthy nodes.
            Console.WriteLine(membersJson);

            // The constitution is a collection of JavaScript code that defines actions available to members,
            // and vets proposals by members to execute those actions.
            Response constitutionResponse = ledgerClient.GetConstitution();
            string   constitutionJson     = new StreamReader(constitutionResponse.ContentStream).ReadToEnd();

            Console.WriteLine(constitutionJson);

            // Enclave quotes contain material that can be used to cryptographically verify the validity and contents of an enclave.
            Response enclavesResponse = ledgerClient.GetEnclaveQuotes();
            string   enclavesJson     = new StreamReader(enclavesResponse.ContentStream).ReadToEnd();

            Console.WriteLine(enclavesJson);

                              #endregion
        }