public void TestDecodeTxNoTail() { var noTailTransactionXdr = "AAAAAEntn0+aXWXUuLtq9RDTOQHw6FKCz4YULdFpx6KrFLM2AAABLACOUUAAAAAEAAAAAQAAAABbFYjQAAAAAH////8AAAABAAAAFEVDTFlQU0VTQ09JTiBQYXltZW50AAAAAwAAAAAAAAABAAAAANqNgkK/Piz99iwrbp+Lr2LjwDKul8tgETQO2igoZaaNAAAAAkVDTFlQU0VTQ09JTgAAAABwYz2lcMDGOi6MU/sYdRuBye2KWD5aolXM/Yxdr8X9+AAAAAAF9eEAAAAAAAAAAAYAAAACRUNMWVBTRVNDT0lOAAAAAHBjPaVwwMY6LoxT+xh1G4HJ7YpYPlqiVcz9jF2vxf34AAAAAAAAAAAAAAABAAAAAEntn0+aXWXUuLtq9RDTOQHw6FKCz4YULdFpx6KrFLM2AAAACAAAAACxJkMYYoztLLzXom8YBWAqFrREfEt3DvmQepBBLNCzbQAAAAAAAAABLNCzbQAAAEDjlco8Cz8GnuFItJVUUEMPYizwC5LLTxueNI9KEf1fgyPZ0hYC5IQP5Augl/p78z5WpnHfFZXYz3vXMf6buhgN"; var bytes = noTailTransactionXdr.ToCharArray(); var xdrDataInputStream = new XdrDataInputStream(Convert.FromBase64CharArray(bytes, 0, bytes.Length)); var decodedTransaction = Transaction.Decode(xdrDataInputStream); var memo = decodedTransaction.Memo.Text; Assert.AreEqual("ECLYPSESCOIN Payment", memo); }
/// <summary> /// Generates Transaction XDR object. /// </summary> /// <returns></returns> public xdr.Transaction ToXdr() { // fee var fee = new Uint32 { InnerValue = Fee }; // sequenceNumber var sequenceNumberUint = new Uint64 { InnerValue = SequenceNumber }; var sequenceNumber = new SequenceNumber { InnerValue = sequenceNumberUint }; // sourceAccount var sourceAccount = new AccountID { InnerValue = SourceAccount.XdrPublicKey }; // operations var operations = new xdr.Operation[Operations.Length]; for (var i = 0; i < Operations.Length; i++) { operations[i] = Operations[i].ToXdr(); } // ext var ext = new xdr.Transaction.TransactionExt { Discriminant = 0 }; var transaction = new xdr.Transaction { Fee = fee, SeqNum = sequenceNumber, SourceAccount = sourceAccount, Operations = operations, Memo = Memo.ToXdr(), TimeBounds = TimeBounds?.ToXdr(), Ext = ext }; return(transaction); }
public void TestBuilderTimeBounds() { // GBPMKIRA2OQW2XZZQUCQILI5TMVZ6JNRKM423BSAISDM7ZFWQ6KWEBC4 var source = KeyPair.FromSecretSeed("SCH27VUZZ6UAKB67BDNF6FA42YMBMQCBKXWGMFD5TZ6S5ZZCZFLRXKHS"); var destination = KeyPair.FromAccountId("GDW6AUTBXTOC7FIKUO5BOO3OGLK4SF7ZPOBLMQHMZDI45J2Z6VXRB5NR"); var account = new Account(source, 2908908335136768L); var transaction = new Transaction.Builder(account) .AddOperation(new CreateAccountOperation.Builder(destination, "2000").Build()) .AddTimeBounds(new TimeBounds(42, 1337)) .Build(); transaction.Sign(source); // Convert transaction to binary XDR and back again to make sure timebounds are correctly de/serialized. var bytes = transaction.ToEnvelopeXdrBase64().ToCharArray(); var xdrDataInputStream = new XdrDataInputStream(Convert.FromBase64CharArray(bytes, 0, bytes.Length)); var decodedTransaction = XdrTransaction.Decode(xdrDataInputStream); Assert.AreEqual(decodedTransaction.TimeBounds.MinTime.InnerValue, 42); Assert.AreEqual(decodedTransaction.TimeBounds.MaxTime.InnerValue, 1337); }
public void TestBuilderFee() { // GBPMKIRA2OQW2XZZQUCQILI5TMVZ6JNRKM423BSAISDM7ZFWQ6KWEBC4 var source = KeyPair.FromSecretSeed("SCH27VUZZ6UAKB67BDNF6FA42YMBMQCBKXWGMFD5TZ6S5ZZCZFLRXKHS"); var destination = KeyPair.FromAccountId("GDW6AUTBXTOC7FIKUO5BOO3OGLK4SF7ZPOBLMQHMZDI45J2Z6VXRB5NR"); var account = new Account(source.AccountId, 2908908335136768L); var transaction = new TransactionBuilder(account) .AddOperation(new CreateAccountOperation.Builder(destination, "2000").Build()) .AddOperation(new CreateAccountOperation.Builder(destination, "2000").Build()) .SetFee(173) .Build(); // Convert transaction to binary XDR and back again to make sure fee is correctly de/serialized. var bytes = transaction.ToUnsignedEnvelopeXdrBase64().ToCharArray(); var xdrDataInputStream = new XdrDataInputStream(Convert.FromBase64CharArray(bytes, 0, bytes.Length)); var decodedTransaction = XdrTransaction.Decode(xdrDataInputStream); Assert.AreEqual(decodedTransaction.Fee.InnerValue, 173 * 2U); var transaction2 = Transaction.FromEnvelopeXdr(transaction.ToUnsignedEnvelopeXdr()); Assert.AreEqual(transaction.SourceAccount.AccountId, transaction2.SourceAccount.AccountId); Assert.AreEqual(transaction.SequenceNumber, transaction2.SequenceNumber); Assert.AreEqual(transaction.Memo, transaction2.Memo); Assert.AreEqual(transaction.TimeBounds, transaction2.TimeBounds); Assert.AreEqual(transaction.Fee, transaction2.Fee); Assert.AreEqual( ((CreateAccountOperation)transaction.Operations[0]).StartingBalance, ((CreateAccountOperation)transaction2.Operations[0]).StartingBalance ); Assert.AreEqual( ((CreateAccountOperation)transaction.Operations[1]).StartingBalance, ((CreateAccountOperation)transaction2.Operations[1]).StartingBalance ); }
public static Transaction FromEnvelopeXdr(TransactionEnvelope envelope) { xdr.Transaction transactionXdr = envelope.Tx; var fee = transactionXdr.Fee.InnerValue; KeyPair sourceAccount = KeyPair.FromXdrPublicKey(transactionXdr.SourceAccount.InnerValue); long sequenceNumber = transactionXdr.SeqNum.InnerValue.InnerValue; Memo memo = Memo.FromXdr(transactionXdr.Memo); TimeBounds timeBounds = TimeBounds.FromXdr(transactionXdr.TimeBounds); Operation[] operations = new Operation[transactionXdr.Operations.Length]; for (int i = 0; i < transactionXdr.Operations.Length; i++) { operations[i] = Operation.FromXdr(transactionXdr.Operations[i]); } Transaction transaction = new Transaction(sourceAccount, fee, sequenceNumber, operations, memo, timeBounds); foreach (var signature in envelope.Signatures) { transaction.Signatures.Add(signature); } return(transaction); }
private async Task <bool> ProcessDwToHwTransaction(Guid operationId, stellar_dotnet_sdk.xdr.Transaction tx) { var fromKeyPair = KeyPair.FromPublicKey(tx.SourceAccount.Ed25519.InnerValue); if (!_balanceService.IsDepositBaseAddress(fromKeyPair.Address) || tx.Operations.Length != 1 || tx.Operations[0].Body.PaymentOp == null || string.IsNullOrWhiteSpace(tx.Memo.Text)) { return(false); } var toKeyPair = KeyPair.FromPublicKey(tx.Operations[0].Body.PaymentOp.Destination.Ed25519.InnerValue); if (!_balanceService.IsDepositBaseAddress(toKeyPair.Address)) { return(false); } var fromAddress = $"{fromKeyPair.Address}{Constants.PublicAddressExtension.Separator}{tx.Memo.Text}"; var amount = tx.Operations[0].Body.PaymentOp.Amount.InnerValue; // Use our guid-ed OperationId as transaction hash, as it uniquely identifies the transaction, // just without dashes to look more hash-y. var hash = operationId.ToString("N"); // While we have only single action within DW->HW transaction, // we can use any value to identify action within transaction. // Use hashed operation ID to add more diversity. var opId = operationId.ToString("N").CalculateHash64(); var ledger = await _horizonService.GetLatestLedger(); var updateLedger = (ledger.Sequence * 10) + 1; var broadcast = new TxBroadcast { OperationId = operationId, Amount = amount, Fee = 0, Hash = hash, // ReSharper disable once ArrangeRedundantParentheses Ledger = updateLedger, CreatedAt = DateTime.UtcNow }; var assetId = _blockchainAssetsService.GetNativeAsset().Id; var balance = await _balanceRepository.GetAsync(assetId, fromAddress); if (balance.Balance < amount) { broadcast.State = TxBroadcastState.Failed; broadcast.Error = "Not enough balance!"; broadcast.ErrorCode = TxExecutionError.NotEnoughBalance; } else { await _balanceRepository.RecordOperationAsync(assetId, fromAddress, updateLedger, opId, hash, (-1) *amount); await _balanceRepository.RefreshBalance(assetId, fromAddress); broadcast.State = TxBroadcastState.Completed; } _chaos.Meow(nameof(ProcessDwToHwTransaction)); // update state await _broadcastRepository.InsertOrReplaceAsync(broadcast); return(true); }