/// Creates a new Did power up request for the given [pairwiseDid] and of the given [amount].
        /// Signs everything that needs to be signed (i.e. the signature JSON inside the payload) with the
        /// private key contained inside the given  [senderWallet] and the [privateKey].
        public static async Task <TransactionResult> requestDidPowerUp(
            Wallet senderWallet,
            String pairwiseDid,
            List <StdCoin> amount,
            RSAPrivateKey privateKey,
            StdFee fee            = null,
            BroadcastingMode mode = BroadcastingMode.SYNC
            )
        {
            RequestDidPowerUp requestDidPowerUp = await RequestDidPowerUpHelper.fromWallet(
                senderWallet,
                pairwiseDid,
                amount,
                privateKey
                );

            MsgRequestDidPowerUp msg = new MsgRequestDidPowerUp(requestDidPowerUp: requestDidPowerUp);

            // Careful here, Eugene: we are passing a list of BaseType containing the derived MsgSetDidDocument msg
            return(await TxHelper.createSignAndSendTx(new List <StdMsg> {
                msg
            }, senderWallet, fee : fee, mode : mode));
        }
        public static async Task <RequestDidPowerUp> fromWallet(Wallet senderWallet, String pairwiseDid, List <StdCoin> amount, RSAPrivateKey privateKey)
        {
            // Get the timestamp
            String timestamp = GenericUtils.getTimeStampEpoch(); // RC 20200913: Be careful, the Dart version uses a different timestamp format non ISO-8601 - Why?
            String senderDid = senderWallet.bech32Address;

            // Build and sign the signature
            byte[] signedSignatureHash = SignHelper.signPowerUpSignature(
                senderDid: senderDid,
                pairwiseDid: pairwiseDid,
                timestamp: timestamp,
                rsaPrivateKey: privateKey);

            // Build the payload -*
            DidPowerUpRequestPayload payload = new DidPowerUpRequestPayload(
                senderDid: senderDid,
                pairwiseDid: pairwiseDid,
                timeStamp: timestamp,
                signature: Convert.ToBase64String(signedSignatureHash)
                );

            // =============
            // Encrypt proof
            // =============

            // Generate an AES-256 key
            KeyParameter aesKey = KeysHelper.generateAesKey(); // await ?

            // Encrypt the payload
            byte[] encryptedProof = EncryptionHelper.encryptStringWithAesGCM(JsonConvert.SerializeObject(payload), aesKey);

            // =================
            // Encrypt proof key
            // =================

            // Encrypt the key using the Tumbler public RSA key
            RSAPublicKey rsaPubTkKey = await EncryptionHelper.getGovernmentRsaPubKey(senderWallet.networkInfo.lcdUrl);

            byte[] encryptedProofKey = EncryptionHelper.encryptBytesWithRsa(aesKey.GetKey(), rsaPubTkKey);

            // Build the message
            RequestDidPowerUp request = new RequestDidPowerUp(
                claimantDid: senderDid,
                amount: amount,
                powerUpProof: Convert.ToBase64String(encryptedProof),
                uuid: Guid.NewGuid().ToString(),
                encryptionKey: Convert.ToBase64String(encryptedProofKey)
                );

            return(request);
        }
        /// Takes [senderDid], [pairwiseDid], [timestamp] and:
        /// 1. Concatenate senderDid, pairwiseDid and timestamp as payload
        /// 2. Returns the RSA PKCS1v15 (the SHA256 digest is calculated inside the
        ///    signer) and sign using the [rsaPrivateKey]
        public static byte[] signPowerUpSignature(String senderDid, String pairwiseDid, String timestamp, RSAPrivateKey rsaPrivateKey)
        {
            String concat = senderDid + pairwiseDid + timestamp;

            ISigner sig = SignerUtilities.GetSigner("SHA256WithRSA");

            // Populate key
            sig.Init(true, rsaPrivateKey.secretKey);
            // Get the bytes to be signed from the string
            byte[] buffer = Encoding.UTF8.GetBytes(concat);
            // Calc the signature
            sig.BlockUpdate(buffer, 0, buffer.Length);
            byte[] signature = sig.GenerateSignature();
            return(signature);
        }