Beispiel #1
0
        private async Task SignTransactionWithPassphrase(string passphrase, Transaction.Output[] outputs, bool publishImmediately)
        {
            var walletClient          = App.Current.Synchronizer.WalletRpcClient;
            var requiredConfirmations = 1;           // TODO: Don't hardcode confs.
            var targetAmount          = outputs.Sum(o => o.Amount);
            var targetFee             = (Amount)1e6; // TODO: Don't hardcode fee/kB.
            var funding = await walletClient.FundTransactionAsync(SelectedAccount.Account, targetAmount + targetFee, requiredConfirmations);

            var fundingAmount = funding.Item2;

            if (fundingAmount < targetAmount + targetFee)
            {
                MessageBox.Show($"Transaction requires {(Amount)(targetAmount + targetFee)} input value but only {fundingAmount} is spendable.",
                                "Insufficient funds to create transaction.");
                return;
            }

            var selectedOutputs = funding.Item1;
            var inputs          = selectedOutputs
                                  .Select(o =>
            {
                var prevOutPoint = new Transaction.OutPoint(o.TransactionHash, o.OutputIndex, 0);
                return(Transaction.Input.CreateFromPrefix(prevOutPoint, TransactionRules.MaxInputSequence));
            })
                                  .ToArray();

            // TODO: Port the fee estimation logic from btcwallet.  Using a hardcoded fee is unacceptable.
            var estimatedFee = targetFee;

            var changePkScript = funding.Item3;

            if (changePkScript != null)
            {
                // Change output amount is calculated by solving for changeAmount with the equation:
                //   estimatedFee = fundingAmount - (targetAmount + changeAmount)
                var changeOutput = new Transaction.Output(fundingAmount - targetAmount - estimatedFee,
                                                          Transaction.Output.LatestPkScriptVersion, changePkScript.Script);
                var outputsList = outputs.ToList();
                // TODO: Randomize change output position.
                outputsList.Add(changeOutput);
                outputs = outputsList.ToArray();
            }

            // TODO: User may want to set the locktime.
            var unsignedTransaction = new Transaction(Transaction.SupportedVersion, inputs, outputs, 0, 0);

            var signingResponse = await walletClient.SignTransactionAsync(passphrase, unsignedTransaction);

            var complete = signingResponse.Item2;

            if (!complete)
            {
                MessageBox.Show("Failed to create transaction input signatures.");
                return;
            }
            var signedTransaction = signingResponse.Item1;

            MessageBox.Show($"Created tx with {estimatedFee} fee.");

            if (!publishImmediately)
            {
                MessageBox.Show("Reviewing signed transaction before publishing is not implemented yet.");
                return;
            }

            // TODO: The client just deserialized the transaction, so serializing it is a
            // little silly.  This could be optimized.
            await walletClient.PublishTransactionAsync(signedTransaction.Serialize());

            MessageBox.Show("Published transaction.");
        }
Beispiel #2
0
 private async Task <bool> IsBroadcastedUtxo(Transaction.OutPoint outpoint)
 {
     return(await _broadcastedOutpointRepo.GetAsync(outpoint.ToString()) != null);
 }