public IWithdrawal ExtractWithdrawalFromTransaction(Transaction transaction, uint256 blockHash, int blockHeight)
        {
            if (transaction.Outputs.Count(this.IsTargetAddressCandidate) != 1)
            {
                return(null);
            }
            if (!this.IsOnlyFromMultisig(transaction))
            {
                return(null);
            }

            if (!this.opReturnDataReader.TryGetTransactionId(transaction, out string depositId))
            {
                return(null);
            }

            this.logger.LogDebug(
                "Processing received transaction with source deposit id: {0}. Transaction hash: {1}.",
                depositId,
                transaction.GetHash());

            TxOut targetAddressOutput = transaction.Outputs.Single(this.IsTargetAddressCandidate);
            var   withdrawal          = new Withdrawal(
                uint256.Parse(depositId),
                transaction.GetHash(),
                targetAddressOutput.Value,
                targetAddressOutput.ScriptPubKey.GetDestinationAddress(this.network).ToString(),
                blockHeight,
                blockHash);

            return(withdrawal);
        }
        public IWithdrawal ExtractWithdrawalFromTransaction(Transaction transaction, uint256 blockHash, int blockHeight)
        {
            // Coinbase can't contain withdrawals.
            if (transaction.IsCoinBase)
            {
                return(null);
            }

            if (!this.IsOnlyFromMultisig(transaction))
            {
                return(null);
            }

            if (!this.opReturnDataReader.TryGetTransactionId(transaction, out string depositId))
            {
                return(null);
            }

            // This is not a withdrawal transaction.
            if (transaction.Outputs.Count < ExpectedNumberOfOutputsNoChange)
            {
                return(null);
            }

            Money  withdrawalAmount = null;
            string targetAddress    = null;

            // Cross chain transfers either have 2 or 3 outputs.
            if (transaction.Outputs.Count == ExpectedNumberOfOutputsNoChange || transaction.Outputs.Count == ExpectedNumberOfOutputsChange)
            {
                TxOut targetAddressOutput = transaction.Outputs.SingleOrDefault(this.IsTargetAddressCandidate);
                if (targetAddressOutput == null)
                {
                    return(null);
                }

                withdrawalAmount = targetAddressOutput.Value;
                targetAddress    = targetAddressOutput.ScriptPubKey.GetDestinationAddress(this.network).ToString();
            }
            else
            {
                // Reward distribution transactions will have more than 3 outputs.
                IEnumerable <TxOut> txOuts = transaction.Outputs.Where(output => output.ScriptPubKey != this.multisigAddress.ScriptPubKey && !output.ScriptPubKey.IsUnspendable);
                if (!txOuts.Any())
                {
                    return(null);
                }

                withdrawalAmount = txOuts.Sum(t => t.Value);
                targetAddress    = this.network.CirrusRewardDummyAddress;
            }

            var withdrawal = new Withdrawal(uint256.Parse(depositId), transaction.GetHash(), withdrawalAmount, targetAddress, blockHeight, blockHash);

            return(withdrawal);
        }
        public IWithdrawal ExtractWithdrawalFromTransaction(Transaction transaction, uint256 blockHash, int blockHeight)
        {
            // Coinbase can't contain withdrawals.
            if (transaction.IsCoinBase)
            {
                return(null);
            }

            // Withdrawal has a specific structure.
            if (transaction.Outputs.Count != ExpectedNumberOfOutputsNoChange &&
                transaction.Outputs.Count != ExpectedNumberOfOutputsChange)
            {
                return(null);
            }

            if (!this.IsOnlyFromMultisig(transaction))
            {
                return(null);
            }

            if (!this.opReturnDataReader.TryGetTransactionId(transaction, out string depositId))
            {
                return(null);
            }

            TxOut targetAddressOutput = transaction.Outputs.SingleOrDefault(this.IsTargetAddressCandidate);

            if (targetAddressOutput == null)
            {
                return(null);
            }

            var withdrawal = new Withdrawal(
                uint256.Parse(depositId),
                transaction.GetHash(),
                targetAddressOutput.Value,
                targetAddressOutput.ScriptPubKey.GetDestinationAddress(this.network).ToString(),
                blockHeight,
                blockHash);

            return(withdrawal);
        }