diff --git a/stellar-dotnet-sdk-test/ServerTest.cs b/stellar-dotnet-sdk-test/ServerTest.cs index 720fbd567..af666644a 100644 --- a/stellar-dotnet-sdk-test/ServerTest.cs +++ b/stellar-dotnet-sdk-test/ServerTest.cs @@ -1,16 +1,15 @@ -using System; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using Moq; +using Moq.Language; +using stellar_dotnet_sdk; +using stellar_dotnet_sdk.responses; +using System; using System.IO; using System.Linq; using System.Net; using System.Net.Http; using System.Threading; using System.Threading.Tasks; -using Castle.DynamicProxy.Generators; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using Moq; -using Moq.Language; -using stellar_dotnet_sdk; -using stellar_dotnet_sdk.responses; namespace stellar_dotnet_sdk_test { @@ -75,6 +74,19 @@ public Transaction BuildTransaction() return transaction; } + public FeeBumpTransaction BuildFeeBumpTransaction() + { + var source = KeyPair.FromSecretSeed("SB7ZMPZB3YMMK5CUWENXVLZWBK4KYX4YU5JBXQNZSK2DP2Q7V3LVTO5V"); + + var accountId = "GAYHAAKPAQLMGIJYMIWPDWCGUCQ5LAWY4Q7Q3IKSP57O7GUPD3NEOSEA"; + var innerTx = BuildTransaction(); + var feeSource = KeyPair.FromAccountId("GD7HCWFO77E76G6BKJLRHRFRLE6I7BMPJQZQKGNYTT3SPE6BA4DHJAQY"); + + var tx = TransactionBuilder.BuildFeeBumpTransaction(feeSource, innerTx, 200); + tx.Sign(source); + return tx; + } + [TestMethod] public async Task TestSubmitTransactionSuccess() { @@ -144,7 +156,7 @@ public async Task TestSubmitTransactionFail() } [TestMethod] - public async Task TestNoSkipMemoRequiredCheck() + public async Task TestNoSkipMemoRequiredCheck() { var json = File.ReadAllText(Path.Combine("testdata", "serverSuccess.json")); When().Returns(ResponseMessage(HttpOk, json)); @@ -155,10 +167,10 @@ public async Task TestNoSkipMemoRequiredCheck() Assert.AreEqual(response.Ledger, (uint)826150); Assert.AreEqual(response.Hash, "2634d2cf5adcbd3487d1df042166eef53830115844fdde1588828667bf93ff42"); Assert.IsNull(response.SubmitTransactionResponseExtras); - } - + } + [TestMethod] - public async Task TestSubmitTransactionEnvelopeBase64() + public async Task TestSubmitTransactionEnvelopeBase64() { var json = File.ReadAllText(Path.Combine("testdata", "serverSuccess.json")); When().Returns(ResponseMessage(HttpOk, json)); @@ -169,10 +181,51 @@ public async Task TestSubmitTransactionEnvelopeBase64() Assert.AreEqual(response.Ledger, (uint)826150); Assert.AreEqual(response.Hash, "2634d2cf5adcbd3487d1df042166eef53830115844fdde1588828667bf93ff42"); Assert.IsNull(response.SubmitTransactionResponseExtras); - } - + } + + [TestMethod] + public async Task TestSubmitFeeBumpTransactionEnvelopeBase64() + { + var json = File.ReadAllText(Path.Combine("testdata", "serverSuccess.json")); + When().Returns(ResponseMessage(HttpOk, json)); + + var response = await _server.SubmitTransaction( + BuildFeeBumpTransaction().ToEnvelopeXdrBase64(), new SubmitTransactionOptions { SkipMemoRequiredCheck = false, FeeBumpTransaction = true }); + Assert.IsTrue(response.IsSuccess()); + Assert.AreEqual(response.Ledger, (uint)826150); + Assert.AreEqual(response.Hash, "2634d2cf5adcbd3487d1df042166eef53830115844fdde1588828667bf93ff42"); + Assert.IsNull(response.SubmitTransactionResponseExtras); + } + + [TestMethod] + public async Task TestSubmitFeeBumpTransactionWithoutOptions() + { + var json = File.ReadAllText(Path.Combine("testdata", "serverSuccess.json")); + When().Returns(ResponseMessage(HttpOk, json)); + + var response = await _server.SubmitTransaction(BuildFeeBumpTransaction()); + Assert.IsTrue(response.IsSuccess()); + Assert.AreEqual(response.Ledger, (uint)826150); + Assert.AreEqual(response.Hash, "2634d2cf5adcbd3487d1df042166eef53830115844fdde1588828667bf93ff42"); + Assert.IsNull(response.SubmitTransactionResponseExtras); + } + [TestMethod] - public async Task TestSubmitTransactionWithoutOptions() + public async Task TestSubmitFeeBumpTransactionWithOptions() + { + var json = File.ReadAllText(Path.Combine("testdata", "serverSuccess.json")); + When().Returns(ResponseMessage(HttpOk, json)); + + var response = await _server.SubmitTransaction( + BuildFeeBumpTransaction(), new SubmitTransactionOptions { SkipMemoRequiredCheck = false }); + Assert.IsTrue(response.IsSuccess()); + Assert.AreEqual(response.Ledger, (uint)826150); + Assert.AreEqual(response.Hash, "2634d2cf5adcbd3487d1df042166eef53830115844fdde1588828667bf93ff42"); + Assert.IsNull(response.SubmitTransactionResponseExtras); + } + + [TestMethod] + public async Task TestSubmitTransactionWithoutOptions() { var json = File.ReadAllText(Path.Combine("testdata", "serverSuccess.json")); When().Returns(ResponseMessage(HttpOk, json)); @@ -183,10 +236,10 @@ public async Task TestSubmitTransactionWithoutOptions() Assert.AreEqual(response.Ledger, (uint)826150); Assert.AreEqual(response.Hash, "2634d2cf5adcbd3487d1df042166eef53830115844fdde1588828667bf93ff42"); Assert.IsNull(response.SubmitTransactionResponseExtras); - } - + } + [TestMethod] - public async Task TestSubmitTransactionEnvelopeBase64WithoutOptions() + public async Task TestSubmitTransactionEnvelopeBase64WithoutOptions() { var json = File.ReadAllText(Path.Combine("testdata", "serverSuccess.json")); When().Returns(ResponseMessage(HttpOk, json)); @@ -197,22 +250,22 @@ public async Task TestSubmitTransactionEnvelopeBase64WithoutOptions() Assert.AreEqual(response.Ledger, (uint)826150); Assert.AreEqual(response.Hash, "2634d2cf5adcbd3487d1df042166eef53830115844fdde1588828667bf93ff42"); Assert.IsNull(response.SubmitTransactionResponseExtras); - } - - public class FakeHttpMessageHandler : HttpMessageHandler - { - public Uri RequestUri { get; private set; } - - public virtual HttpResponseMessage Send(HttpRequestMessage request) - { - throw new NotImplementedException(); - } - - protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) - { - RequestUri = request.RequestUri; - return await Task.FromResult(Send(request)); - } - } + } + + public class FakeHttpMessageHandler : HttpMessageHandler + { + public Uri RequestUri { get; private set; } + + public virtual HttpResponseMessage Send(HttpRequestMessage request) + { + throw new NotImplementedException(); + } + + protected override async Task SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) + { + RequestUri = request.RequestUri; + return await Task.FromResult(Send(request)); + } + } } -} \ No newline at end of file +} diff --git a/stellar-dotnet-sdk/FeeBumpTransaction.cs b/stellar-dotnet-sdk/FeeBumpTransaction.cs index 80621a560..5b61398e5 100644 --- a/stellar-dotnet-sdk/FeeBumpTransaction.cs +++ b/stellar-dotnet-sdk/FeeBumpTransaction.cs @@ -1,5 +1,5 @@ +using stellar_dotnet_sdk.xdr; using System; -using stellar_dotnet_sdk.xdr; using Int64 = stellar_dotnet_sdk.xdr.Int64; namespace stellar_dotnet_sdk @@ -25,7 +25,7 @@ public override byte[] SignatureBase(Network network) throw new NoNetworkSelectedException(); // Hashed NetworkID - var networkHash = new Hash {InnerValue = network.NetworkId}; + var networkHash = new Hash { InnerValue = network.NetworkId }; var taggedTransaction = new TransactionSignaturePayload.TransactionSignaturePayloadTaggedTransaction { Discriminant = EnvelopeType.Create(EnvelopeType.EnvelopeTypeEnum.ENVELOPE_TYPE_TX_FEE_BUMP), @@ -45,12 +45,12 @@ public override byte[] SignatureBase(Network network) public xdr.FeeBumpTransaction ToXdr() { - var fee = new Int64 {InnerValue = Fee}; + var fee = new Int64 { InnerValue = Fee }; var feeSource = FeeSource.MuxedAccount; var inner = new xdr.FeeBumpTransaction.FeeBumpTransactionInnerTx { - Discriminant = new EnvelopeType {InnerValue = EnvelopeType.EnvelopeTypeEnum.ENVELOPE_TYPE_TX}, + Discriminant = new EnvelopeType { InnerValue = EnvelopeType.EnvelopeTypeEnum.ENVELOPE_TYPE_TX }, V1 = new TransactionV1Envelope { Tx = InnerTransaction.ToXdrV1(), @@ -58,7 +58,7 @@ public xdr.FeeBumpTransaction ToXdr() } }; - var ext = new xdr.FeeBumpTransaction.FeeBumpTransactionExt {Discriminant = 0}; + var ext = new xdr.FeeBumpTransaction.FeeBumpTransactionExt { Discriminant = 0 }; var transaction = new xdr.FeeBumpTransaction { @@ -90,10 +90,19 @@ private TransactionEnvelope ToEnvelopeXdr(TransactionXdrVersion version, Decorat return new TransactionEnvelope { Discriminant = - new EnvelopeType {InnerValue = EnvelopeType.EnvelopeTypeEnum.ENVELOPE_TYPE_TX_FEE_BUMP}, - FeeBump = new FeeBumpTransactionEnvelope {Tx = ToXdr(), Signatures = signatures} + new EnvelopeType { InnerValue = EnvelopeType.EnvelopeTypeEnum.ENVELOPE_TYPE_TX_FEE_BUMP }, + FeeBump = new FeeBumpTransactionEnvelope { Tx = ToXdr(), Signatures = signatures } }; } + + public static FeeBumpTransaction FromEnvelopeXdr(string envelope) + { + byte[] bytes = Convert.FromBase64String(envelope); + + TransactionEnvelope transactionEnvelope = TransactionEnvelope.Decode(new XdrDataInputStream(bytes)); + return FromEnvelopeXdr(transactionEnvelope); + } + public static FeeBumpTransaction FromEnvelopeXdr(TransactionEnvelope envelope) { { @@ -119,4 +128,4 @@ public static FeeBumpTransaction FromEnvelopeXdr(TransactionEnvelope envelope) } } -} \ No newline at end of file +} diff --git a/stellar-dotnet-sdk/Server.cs b/stellar-dotnet-sdk/Server.cs index f49595a26..82f4f18af 100644 --- a/stellar-dotnet-sdk/Server.cs +++ b/stellar-dotnet-sdk/Server.cs @@ -1,11 +1,10 @@ -using System; +using stellar_dotnet_sdk.requests; +using stellar_dotnet_sdk.responses; +using System; using System.Collections.Generic; -using System.Linq; using System.Net.Http; using System.Reflection; using System.Threading.Tasks; -using stellar_dotnet_sdk.requests; -using stellar_dotnet_sdk.responses; namespace stellar_dotnet_sdk { @@ -93,7 +92,7 @@ public RootResponse Root() /// public Task SubmitTransaction(Transaction transaction) { - var options = new SubmitTransactionOptions {SkipMemoRequiredCheck = false}; + var options = new SubmitTransactionOptions { SkipMemoRequiredCheck = false }; return SubmitTransaction(transaction.ToEnvelopeXdrBase64(), options); } @@ -120,10 +119,22 @@ public Task SubmitTransaction(Transaction transaction /// public Task SubmitTransaction(string transactionEnvelopeBase64) { - var options = new SubmitTransactionOptions {SkipMemoRequiredCheck = false}; + var options = new SubmitTransactionOptions { SkipMemoRequiredCheck = false }; return SubmitTransaction(transactionEnvelopeBase64, options); } + public Task SubmitTransaction(FeeBumpTransaction feeBump) + { + var options = new SubmitTransactionOptions { FeeBumpTransaction = true }; + return SubmitTransaction(feeBump.ToEnvelopeXdrBase64(), options); + } + + public Task SubmitTransaction(FeeBumpTransaction feeBump, SubmitTransactionOptions options) + { + options.FeeBumpTransaction = true; + return SubmitTransaction(feeBump.ToEnvelopeXdrBase64(), options); + } + /// /// Submit a transaction to the network. /// @@ -137,7 +148,17 @@ public async Task SubmitTransaction(string transactio { if (!options.SkipMemoRequiredCheck) { - var tx = Transaction.FromEnvelopeXdr(transactionEnvelopeBase64); + TransactionBase tx; + + if (options.FeeBumpTransaction) + { + tx = FeeBumpTransaction.FromEnvelopeXdr(transactionEnvelopeBase64); + } + else + { + tx = Transaction.FromEnvelopeXdr(transactionEnvelopeBase64); + } + await CheckMemoRequired(tx); } @@ -284,4 +305,4 @@ private IAccountId PaymentOperationDestination(Operation op) } } -} \ No newline at end of file +} diff --git a/stellar-dotnet-sdk/SubmitTransactionOptions.cs b/stellar-dotnet-sdk/SubmitTransactionOptions.cs index cbe286a69..acd81dbd5 100644 --- a/stellar-dotnet-sdk/SubmitTransactionOptions.cs +++ b/stellar-dotnet-sdk/SubmitTransactionOptions.cs @@ -1,7 +1,8 @@ -namespace stellar_dotnet_sdk +namespace stellar_dotnet_sdk { public class SubmitTransactionOptions { public bool SkipMemoRequiredCheck { get; set; } + public bool FeeBumpTransaction { get; set; } } -} \ No newline at end of file +}