/// <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)); }