Exemple #1
0
        /// <inheritdoc />
        public IDeposit ExtractDepositFromTransaction(Transaction transaction, int blockHeight, uint256 blockHash)
        {
            // If there are no deposits to the multsig (i.e. cross chain transfers) do nothing.
            if (!DepositValidationHelper.TryGetDepositsToMultisig(this.network, transaction, FederatedPegSettings.CrossChainTransferMinimum, out List <TxOut> depositsToMultisig))
            {
                return(null);
            }

            // If there are deposits to the multsig (i.e. cross chain transfers), try and extract and validate the address by the specfied destination chain.
            if (!DepositValidationHelper.TryGetTarget(transaction, this.opReturnDataReader, out bool conversionTransaction, out string targetAddress, out int targetChain))
            {
                return(null);
            }

            Money amount = depositsToMultisig.Sum(o => o.Value);

            DepositRetrievalType depositRetrievalType;

            if (conversionTransaction)
            {
                if (amount < Money.Coins(ConversionTransactionMinimum))
                {
                    return(null);
                }

                if (amount > this.federatedPegSettings.NormalDepositThresholdAmount)
                {
                    depositRetrievalType = DepositRetrievalType.ConversionLarge;
                }
                else if (amount > this.federatedPegSettings.SmallDepositThresholdAmount)
                {
                    depositRetrievalType = DepositRetrievalType.ConversionNormal;
                }
                else
                {
                    depositRetrievalType = DepositRetrievalType.ConversionSmall;
                }
            }
            else
            {
                if (targetAddress == this.network.CirrusRewardDummyAddress)
                {
                    depositRetrievalType = DepositRetrievalType.Distribution;
                }
                else if (amount > this.federatedPegSettings.NormalDepositThresholdAmount)
                {
                    depositRetrievalType = DepositRetrievalType.Large;
                }
                else if (amount > this.federatedPegSettings.SmallDepositThresholdAmount)
                {
                    depositRetrievalType = DepositRetrievalType.Normal;
                }
                else
                {
                    depositRetrievalType = DepositRetrievalType.Small;
                }
            }


            return(new Deposit(transaction.GetHash(), depositRetrievalType, amount, targetAddress, (DestinationChain)targetChain, blockHeight, blockHash));
        }
        public BuildContractTransactionResult BuildTx(BuildContractTransactionRequest request)
        {
            Features.Wallet.Wallet wallet = this.walletManager.GetWallet(request.WalletName);

            HdAccount account = wallet.GetAccount(request.AccountName);

            if (account == null)
            {
                return(BuildContractTransactionResult.Failure(AccountNotInWalletError, $"No account with the name '{request.AccountName}' could be found."));
            }

            HdAddress senderAddress = account.GetCombinedAddresses().FirstOrDefault(x => x.Address == request.Sender);

            if (senderAddress == null)
            {
                return(BuildContractTransactionResult.Failure(SenderNotInWalletError, $"The given address {request.Sender} was not found in the wallet."));
            }

            if (!this.CheckBalance(senderAddress.Address))
            {
                return(BuildContractTransactionResult.Failure(InsufficientBalanceError, SenderNoBalanceError));
            }

            (List <OutPoint> selectedInputs, string message) = SelectInputs(request.WalletName, request.Sender, request.Outpoints);
            if (!string.IsNullOrEmpty(message))
            {
                return(BuildContractTransactionResult.Failure(InvalidOutpointsError, message));
            }

            var recipients = new List <Recipient>();

            foreach (RecipientModel recipientModel in request.Recipients)
            {
                var bitcoinAddress = BitcoinAddress.Create(recipientModel.DestinationAddress, this.network);

                // If it's a potential SC address, check if it's a contract.
                if (bitcoinAddress is BitcoinPubKeyAddress bitcoinPubKeyAddress)
                {
                    var address = new uint160(bitcoinPubKeyAddress.Hash.ToBytes());

                    if (this.stateRoot.IsExist(address))
                    {
                        return(BuildContractTransactionResult.Failure(TransferFundsToContractError,
                                                                      $"The recipient address {recipientModel.DestinationAddress} is a contract. Transferring funds directly to a contract is not supported."));
                    }
                }

                recipients.Add(new Recipient
                {
                    ScriptPubKey = bitcoinAddress.ScriptPubKey,
                    Amount       = recipientModel.Amount
                });
            }

            var context = new TransactionBuildContext(this.network)
            {
                AccountReference = new WalletAccountReference(request.WalletName, request.AccountName),
                TransactionFee   = string.IsNullOrEmpty(request.FeeAmount) ? null : Money.Parse(request.FeeAmount),
                MinConfirmations = MinConfirmationsAllChecks,
                Shuffle          = false,
                OpReturnData     = request.OpReturnData,
                OpReturnAmount   = string.IsNullOrEmpty(request.OpReturnAmount) ? null : Money.Parse(request.OpReturnAmount),
                WalletPassword   = request.Password,
                SelectedInputs   = selectedInputs,
                AllowOtherInputs = false,
                Recipients       = recipients,
                ChangeAddress    = senderAddress
            };

            Transaction transaction = this.walletTransactionHandler.BuildTransaction(context);

            DepositValidationHelper.ValidateCrossChainDeposit(this.network, transaction);

            var model = new WalletBuildTransactionModel
            {
                Hex           = transaction.ToHex(),
                Fee           = context.TransactionFee,
                TransactionId = transaction.GetHash()
            };

            return(BuildContractTransactionResult.Success(model));
        }