/// <summary> /// Buy the NFT based on the NFT and Neblio Address /// </summary> /// <param name="neblioAddress"></param> /// <param name="receiver"></param> /// <param name="nft"></param> /// <returns></returns> public async Task <(bool, string)> BuyNFT(string neblioAddress, string receiver, INFT nft) { if (!nft.PriceActive) { return(false, "NFT does not have setted up the price. It is not sellable NFT."); } if (IsLocked()) { await InvokeAccountLockedEvent(); return(false, "Account is locked."); } var res = await CheckSpendableDoge(nft.Price); if (res.Item2 == null) { await InvokeErrorDuringSendEvent(res.Item1, "Not enough spendable inputs"); return(false, res.Item1); } var nftid = nft.Utxo + ":" + nft.UtxoIndex.ToString(); var msg = neblioAddress + "=" + String.Format("{0:X}", nftid.GetHashCode()); // fill input data for sending tx var dto = new SendTxData() // please check SendTxData for another properties such as specify source UTXOs { Amount = nft.Price, SenderAddress = Address, ReceiverAddress = receiver, CustomMessage = msg }; try { // send tx var transaction = DogeTransactionHelpers.GetDogeTransactionWithMessageAsync(dto, BAddress, res.Item2); var result = await SignBroadcastAndInvokeSucessEvent(transaction, Secret, res.Item2, "Doge Payment Sent"); if (result.Item1) { return(true, result.Item2); } } catch (Exception ex) { await InvokeErrorDuringSendEvent(ex.Message, "Unknown Error"); return(false, ex.Message); } await InvokeErrorDuringSendEvent("Unknown Error", "Unknown Error"); return(false, "Unexpected error during send."); }
/// <summary> /// Function will send standard Neblio transaction with included message. /// </summary> /// <param name="data">Send data, please see SendTxData class for the details - this include field for custom message</param> /// <param name="ekey">Input EncryptionKey of the account</param> /// <param name="utxos">Optional input neblio utxo</param> /// <returns>New Transaction Hash - TxId</returns> public static Transaction GetDogeTransactionWithMessageAsync(SendTxData data, BitcoinAddress addressForTx, ICollection <Utxo> utxos) { return(GetTransactionObject(data, addressForTx, utxos, withMessage: true)); }
/// <summary> /// Send Doge payment with multiple inputs /// </summary> /// <param name="receiver">Receiver Doge Address</param> /// <param name="amount">Ammount in Doge</param> /// <param name="utxos"></param> /// <param name="message"></param> /// <param name="fee"></param> /// <returns></returns> public async Task <(bool, string)> SendMultipleInputPayment(string receiver, double amount, List <Utxo> utxos, string message = "", UInt64 fee = 100000000) { if (IsLocked()) { await InvokeAccountLockedEvent(); return(false, "Account is locked."); } var res = await CheckSpendableDoge(amount + 5); if (res.Item2 == null) { await InvokeErrorDuringSendEvent(res.Item1, "Not enough spendable inputs"); return(false, res.Item1); } if (utxos.Count > 0) { res.Item2 = utxos; } // fill input data for sending tx var dto = new SendTxData() // please check SendTxData for another properties such as specify source UTXOs { Amount = amount, SenderAddress = Address, ReceiverAddress = receiver, CustomMessage = message }; try { // send tx var rtxid = string.Empty; Transaction transaction; if (string.IsNullOrEmpty(message)) { transaction = DogeTransactionHelpers.GetDogeTransactionAsync(dto, BAddress, res.Item2); } else { transaction = DogeTransactionHelpers.GetDogeTransactionWithMessageAsync(dto, BAddress, res.Item2); } var result = await SignBroadcastAndInvokeSucessEvent(transaction, Secret, res.Item2, "Doge Payment Sent"); if (result.Item1) { return(true, result.Item2); } } catch (Exception ex) { await InvokeErrorDuringSendEvent(ex.Message, "Unknown Error"); return(false, ex.Message); } await InvokeErrorDuringSendEvent("Unknown Error", "Unknown Error"); return(false, "Unexpected error during send."); }
private static Transaction GetTransactionObject(SendTxData data, BitcoinAddress addressForTx, ICollection <Utxo> utxos, bool withMessage = false) { if (data == null) { throw new Exception("Data cannot be null!"); } if (addressForTx == null) { throw new Exception("BitcoinAddress object cannot be null!"); } // create receiver address BitcoinAddress recaddr; try { recaddr = BitcoinAddress.Create(data.ReceiverAddress, Network); } catch (Exception) { throw new Exception("Cannot send transaction. cannot create receiver address!"); } // create template for new tx from last one var tx = GetTransactionWithDogecoinInputs(utxos, addressForTx); if (tx.Item1 == null) { throw new Exception("Cannot create the transaction object."); } var transaction = tx.Item1; var allDogelCoins = tx.Item2; try { var fee = CalcFee(transaction.Inputs.Count, 1, data.CustomMessage, false); if (allDogelCoins < (data.Amount)) { throw new Exception("Not enough Doge to spend."); } var amountinSat = Convert.ToUInt64(data.Amount * FromSatToMainRatio); var diffinSat = (Convert.ToUInt64(allDogelCoins) * FromSatToMainRatio) - amountinSat - Convert.ToUInt64(fee); // create outputs transaction.Outputs.Add(new Money(amountinSat), recaddr.ScriptPubKey); // send to receiver required amount if (withMessage) { var bytes = Encoding.UTF8.GetBytes(data.CustomMessage); transaction.Outputs.Add(new TxOut() { Value = (long)0, ScriptPubKey = TxNullDataTemplate.Instance.GenerateScriptPubKey(bytes) }); } if (diffinSat > 0) { transaction.Outputs.Add(new Money(Convert.ToUInt64(diffinSat)), addressForTx.ScriptPubKey); // get diff back to sender address } } catch (Exception ex) { throw new Exception("Exception during creating outputs. " + ex.Message); } return(transaction); }