diff --git a/src/Solnet.Examples/SolnetRpcTester.cs b/src/Solnet.Examples/SolnetRpcTester.cs index cf4bab02..c97613f8 100644 --- a/src/Solnet.Examples/SolnetRpcTester.cs +++ b/src/Solnet.Examples/SolnetRpcTester.cs @@ -33,6 +33,11 @@ static void Main(string[] args) //var inflationRate = c.GetInflationRate(); //Console.WriteLine(inflationRate.Result.Total); + //var perf = c.GetRecentPerformanceSamples(); + //Console.WriteLine($"Tx: {perf.Result[0].NumTransactions} Slot: {perf.Result[0].Slot }"); + + var signatures = c.GetSignaturesForAddress("4Rf9mGD7FeYknun5JczX5nGLTfQuS1GRjNVfkEMKE92b"); + var v = c.GetVersion(); Console.WriteLine(v.Result.SolanaCore); Console.WriteLine(v.Result.FeatureSet); diff --git a/src/Solnet.Rpc/IRpcClient.cs b/src/Solnet.Rpc/IRpcClient.cs index 7e15c431..592a2e0d 100644 --- a/src/Solnet.Rpc/IRpcClient.cs +++ b/src/Solnet.Rpc/IRpcClient.cs @@ -424,6 +424,51 @@ public interface IRpcClient /// RequestResult GetSnapshotSlot(); + + /// + /// Gets a list of recent performance samples. + /// + /// Unless searchTransactionHistory is included, this method only searches the recent status cache of signatures. + /// + /// + /// Maximum transaction signatures to return, between 1-720. Default is 720. + /// A task which may return a request result the signatures for the transactions. + Task> GetRecentPerformanceSamplesAsync(ulong limit = 720); + + /// + RequestResult GetRecentPerformanceSamples(ulong limit = 720); + + /// + /// Gets confirmed signatures for transactions involving the address. + /// + /// Unless searchTransactionHistory is included, this method only searches the recent status cache of signatures. + /// + /// + /// The account address as base-58 encoded string. + /// Maximum transaction signatures to return, between 1-1000. Default is 1000. + /// Start searching backwards from this transaction signature. + /// Search until this transaction signature, if found before limit is reached. + /// A task which may return a request result the signatures for the transactions. + Task> GetSignaturesForAddressAsync(string accountPubKey, ulong limit = 1000, string before = "", string until = ""); + + /// + RequestResult GetSignaturesForAddress(string accountPubKey, ulong limit = 1000, string before = "", string until = ""); + + /// + /// Gets the status of a list of signatures. + /// + /// Unless searchTransactionHistory is included, this method only searches the recent status cache of signatures. + /// + /// + /// The list of transactions to search status info for. + /// If the node should search for signatures in it's ledger cache. + /// A task which may return a request result the highest slot with a snapshot. + Task>> GetSignatureStatusesAsync(string[] transactionHashes, + bool searchTransactionHistory = false); + + /// + RequestResult> GetSignatureStatuses(string[] transactionHashes, + bool searchTransactionHistory = false); /// /// Gets the current slot the node is processing diff --git a/src/Solnet.Rpc/Models/Performance.cs b/src/Solnet.Rpc/Models/Performance.cs new file mode 100644 index 00000000..bd05ada7 --- /dev/null +++ b/src/Solnet.Rpc/Models/Performance.cs @@ -0,0 +1,28 @@ +namespace Solnet.Rpc.Models +{ + /// + /// Represents a performance sample. + /// + public class PerformanceSample + { + /// + /// Slot in which sample was taken at. + /// + public ulong Slot { get; set; } + + /// + /// Number of transactions in sample. + /// + public ulong NumTransactions { get; set; } + + /// + /// Number of slots in sample + /// + public ulong NumSlots { get; set; } + + /// + /// Number of seconds in a sample window. + /// + public int SamplePeriodSecs { get; set; } + } +} \ No newline at end of file diff --git a/src/Solnet.Rpc/Models/Signature.cs b/src/Solnet.Rpc/Models/Signature.cs new file mode 100644 index 00000000..e28ae070 --- /dev/null +++ b/src/Solnet.Rpc/Models/Signature.cs @@ -0,0 +1,46 @@ +using System.Text.Json.Serialization; + +namespace Solnet.Rpc.Models +{ + /// + /// Represents the signature status information. + /// + public class SignatureStatusInfo + { + /// + /// The slot the transaction was processed in. + /// + public ulong Slot { get; set; } + + /// + /// The number of blocks since signature confirmation. + /// + public ulong? Confirmations { get; set; } + + /// + /// The error if the transaction failed, null if it succeeded. + /// + [JsonPropertyName("err")] + public TransactionError Error { get; set; } + + /// + /// The transaction's cluster confirmation status, either "processed", "confirmed" or "finalized". + /// + public string ConfirmationStatus { get; set; } + + /// + /// Memo associated with the transaction, null if no memo is present. + /// + public string Memo { get; set; } + + /// + /// The transaction signature as base-58 encoded string. + /// + public string Signature { get; set; } + + /// + /// Estimated production time as Unix timestamp, null if not available. + /// + public ulong? BlockTime { get; set; } + } +} \ No newline at end of file diff --git a/src/Solnet.Rpc/SolanaRpcClient.cs b/src/Solnet.Rpc/SolanaRpcClient.cs index 05720c6e..249c7ffb 100644 --- a/src/Solnet.Rpc/SolanaRpcClient.cs +++ b/src/Solnet.Rpc/SolanaRpcClient.cs @@ -603,6 +603,78 @@ public async Task> GetSnapshotSlotAsync() /// public RequestResult GetSnapshotSlot() => GetSnapshotSlotAsync().Result; + /// + /// Gets a list of recent performance samples. + /// + /// Unless searchTransactionHistory is included, this method only searches the recent status cache of signatures. + /// + /// + /// Maximum transaction signatures to return, between 1-720. Default is 720. + /// A task which may return a request result the signatures for the transactions. + public async Task> GetRecentPerformanceSamplesAsync(ulong limit = 720) + { + return await SendRequestAsync("getRecentPerformanceSamples" , + new List{limit}); + } + + /// + public RequestResult GetRecentPerformanceSamples(ulong limit = 720) + => GetRecentPerformanceSamplesAsync(limit).Result; + + /// + /// Gets confirmed signatures for transactions involving the address. + /// + /// Unless searchTransactionHistory is included, this method only searches the recent status cache of signatures. + /// + /// + /// The account address as base-58 encoded string. + /// Maximum transaction signatures to return, between 1-1000. Default is 1000. + /// Start searching backwards from this transaction signature. + /// Search until this transaction signature, if found before limit is reached. + /// A task which may return a request result the signatures for the transactions. + public async Task> GetSignaturesForAddressAsync( + string accountPubKey, ulong limit = 1000, string before = "", string until = "") + { + var dictionary = new Dictionary {{"limit", limit}}; + + if (!string.IsNullOrWhiteSpace(before)) + dictionary.Add("before", before); + + if (!string.IsNullOrWhiteSpace(until)) + dictionary.Add("until", until); + + return await SendRequestAsync("getSignaturesForAddress" , + new List{accountPubKey, dictionary}); + } + + /// + public RequestResult GetSignaturesForAddress( + string accountPubKey, ulong limit = 1000, string before = "", string until = "") + => GetSignaturesForAddressAsync(accountPubKey, limit, before, until).Result; + + /// + /// Gets the status of a list of signatures. + /// + /// Unless searchTransactionHistory is included, this method only searches the recent status cache of signatures. + /// + /// + /// The list of transactions to search status info for. + /// If the node should search for signatures in it's ledger cache. + /// A task which may return a request result the highest slot with a snapshot. + public async Task>> GetSignatureStatusesAsync(string[] transactionHashes, bool searchTransactionHistory = false) + { + if (searchTransactionHistory) + return await SendRequestAsync>("getSignatureStatuses" , + new List{transactionHashes, new Dictionary{ { "searchTransactionHistory", true }}}); + return await SendRequestAsync>("getSignatureStatuses" , + new List{transactionHashes}); + } + + /// + public RequestResult> GetSignatureStatuses(string[] transactionHashes, + bool searchTransactionHistory = false) + => GetSignatureStatusesAsync(transactionHashes, searchTransactionHistory).Result; + /// /// Gets the current slot the node is processing /// diff --git a/test/Solnet.Rpc.Test/Resources/Http/GetRecentPerformanceSamplesRequest.json b/test/Solnet.Rpc.Test/Resources/Http/GetRecentPerformanceSamplesRequest.json new file mode 100644 index 00000000..7362f49d --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/GetRecentPerformanceSamplesRequest.json @@ -0,0 +1 @@ +{"method":"getRecentPerformanceSamples","params":[4],"jsonrpc":"2.0","id":0} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/GetRecentPerformanceSamplesResponse.json b/test/Solnet.Rpc.Test/Resources/Http/GetRecentPerformanceSamplesResponse.json new file mode 100644 index 00000000..d0183e08 --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/GetRecentPerformanceSamplesResponse.json @@ -0,0 +1,30 @@ +{ + "jsonrpc": "2.0", + "result": [ + { + "numSlots": 126, + "numTransactions": 126, + "samplePeriodSecs": 60, + "slot": 348125 + }, + { + "numSlots": 126, + "numTransactions": 126, + "samplePeriodSecs": 60, + "slot": 347999 + }, + { + "numSlots": 125, + "numTransactions": 125, + "samplePeriodSecs": 60, + "slot": 347873 + }, + { + "numSlots": 125, + "numTransactions": 125, + "samplePeriodSecs": 60, + "slot": 347748 + } + ], + "id": 1 +} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesRequest.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesRequest.json new file mode 100644 index 00000000..40227f6b --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesRequest.json @@ -0,0 +1 @@ +{"method":"getSignatureStatuses","params":[["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW","5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7"]],"jsonrpc":"2.0","id":0} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesResponse.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesResponse.json new file mode 100644 index 00000000..46dd9916 --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesResponse.json @@ -0,0 +1,21 @@ +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 82 + }, + "value": [ + { + "slot": 72, + "confirmations": 10, + "err": null, + "status": { + "Ok": null + }, + "confirmationStatus": "confirmed" + }, + null + ] + }, + "id": 0 +} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesWithHistoryRequest.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesWithHistoryRequest.json new file mode 100644 index 00000000..89f368cc --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesWithHistoryRequest.json @@ -0,0 +1 @@ +{"method":"getSignatureStatuses","params":[["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW","5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7"],{"searchTransactionHistory":true}],"jsonrpc":"2.0","id":0} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesWithHistoryResponse.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesWithHistoryResponse.json new file mode 100644 index 00000000..76614463 --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignatureStatusesWithHistoryResponse.json @@ -0,0 +1,21 @@ +{ + "jsonrpc": "2.0", + "result": { + "context": { + "slot": 82 + }, + "value": [ + { + "slot": 48, + "confirmations": null, + "err": null, + "status": { + "Ok": null + }, + "confirmationStatus": "finalized" + }, + null + ] + }, + "id": 0 +} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressBeforeRequest.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressBeforeRequest.json new file mode 100644 index 00000000..b8a81082 --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressBeforeRequest.json @@ -0,0 +1 @@ +{"method":"getSignaturesForAddress","params":["Vote111111111111111111111111111111111111111",{"limit":1,"before":"Vote111111111111111111111111111111111111111"}],"jsonrpc":"2.0","id":0} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressBeforeResponse.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressBeforeResponse.json new file mode 100644 index 00000000..c7f7ed4d --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressBeforeResponse.json @@ -0,0 +1,13 @@ +{ + "jsonrpc": "2.0", + "result": [ + { + "err": null, + "memo": null, + "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", + "slot": 114, + "blockTime": null + } + ], + "id": 1 +} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressRequest.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressRequest.json new file mode 100644 index 00000000..dff1663e --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressRequest.json @@ -0,0 +1 @@ +{"method":"getSignaturesForAddress","params":["4Rf9mGD7FeYknun5JczX5nGLTfQuS1GRjNVfkEMKE92b",{"limit":3}],"jsonrpc":"2.0","id":0} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressResponse.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressResponse.json new file mode 100644 index 00000000..f39aef69 --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressResponse.json @@ -0,0 +1,30 @@ +{ + "jsonrpc": "2.0", + "result": [ + { + "blockTime": 1616245823, + "confirmationStatus": "finalized", + "err": null, + "memo": null, + "signature": "5Jofwx5JcPT1dMsgo6DkyT6x61X5chS9K7hM7huGKAnUq8xxHwGKuDnnZmPGoapWVZcN4cPvQtGNCicnWZfPHowr", + "slot": 68710495 + }, + { + "blockTime": 1615234539, + "confirmationStatus": "finalized", + "err": null, + "memo": null, + "signature": "2Y8fUdkvA9WG7eBBjtPdTxhUhrGAGAPVZMgze4mrjWobJsM5varX1z42VrfvQDoMXhYstVyABfPSaWrPxPWMsMmA", + "slot": 66979017 + }, + { + "blockTime": 1612818924, + "confirmationStatus": "finalized", + "err": null, + "memo": null, + "signature": "3TVD8hze8GrGZRNEcqnh5WR45F2Wu2Xmxf2HAPwXaL5H5yrRhxAsbdKbUBSXHpPnXeGPq6HBwoa7ZUCegiM4hb3U", + "slot": 62482980 + } + ], + "id": 1 +} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressUntilRequest.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressUntilRequest.json new file mode 100644 index 00000000..ce6c8cf4 --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressUntilRequest.json @@ -0,0 +1 @@ +{"method":"getSignaturesForAddress","params":["Vote111111111111111111111111111111111111111",{"limit":1,"until":"Vote111111111111111111111111111111111111111"}],"jsonrpc":"2.0","id":0} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressUntilResponse.json b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressUntilResponse.json new file mode 100644 index 00000000..c7f7ed4d --- /dev/null +++ b/test/Solnet.Rpc.Test/Resources/Http/Signatures/GetSignaturesForAddressUntilResponse.json @@ -0,0 +1,13 @@ +{ + "jsonrpc": "2.0", + "result": [ + { + "err": null, + "memo": null, + "signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", + "slot": 114, + "blockTime": null + } + ], + "id": 1 +} \ No newline at end of file diff --git a/test/Solnet.Rpc.Test/SolanaRpcClientTest.cs b/test/Solnet.Rpc.Test/SolanaRpcClientTest.cs index d9cac91a..d7594cca 100644 --- a/test/Solnet.Rpc.Test/SolanaRpcClientTest.cs +++ b/test/Solnet.Rpc.Test/SolanaRpcClientTest.cs @@ -926,6 +926,200 @@ public void TestGetSlot() FinishTest(messageHandlerMock, TestnetUri); } + + [TestMethod] + public void TestGetRecentPerformanceSamples() + { + var responseData = File.ReadAllText("Resources/Http/GetRecentPerformanceSamplesResponse.json"); + var requestData = File.ReadAllText("Resources/Http/GetRecentPerformanceSamplesRequest.json"); + var sentMessage = string.Empty; + var messageHandlerMock = SetupTest( + (s => sentMessage = s), responseData); + + var httpClient = new HttpClient(messageHandlerMock.Object) + { + BaseAddress = TestnetUri, + }; + + var sut = new SolanaRpcClient(TestnetUrl, null, httpClient); + var result = sut.GetRecentPerformanceSamples(4); + + Assert.AreEqual(requestData, sentMessage); + Assert.IsNotNull(result.Result); + Assert.IsTrue(result.WasSuccessful); + Assert.AreEqual(4, result.Result.Length); + Assert.AreEqual(126UL, result.Result[0].NumSlots); + Assert.AreEqual(348125UL, result.Result[0].Slot); + Assert.AreEqual(126UL, result.Result[0].NumTransactions); + Assert.AreEqual(60, result.Result[0].SamplePeriodSecs); + + FinishTest(messageHandlerMock, TestnetUri); + } + + [TestMethod] + public void TestGetSignaturesForAddress() + { + var responseData = File.ReadAllText("Resources/Http/Signatures/GetSignaturesForAddressResponse.json"); + var requestData = File.ReadAllText("Resources/Http/Signatures/GetSignaturesForAddressRequest.json"); + var sentMessage = string.Empty; + var messageHandlerMock = SetupTest( + (s => sentMessage = s), responseData); + + var httpClient = new HttpClient(messageHandlerMock.Object) + { + BaseAddress = TestnetUri, + }; + + var sut = new SolanaRpcClient(TestnetUrl, null, httpClient); + var result = sut.GetSignaturesForAddress("4Rf9mGD7FeYknun5JczX5nGLTfQuS1GRjNVfkEMKE92b", limit: 3); + + Assert.AreEqual(requestData, sentMessage); + Assert.IsNotNull(result.Result); + Assert.IsTrue(result.WasSuccessful); + Assert.AreEqual(3, result.Result.Length); + Assert.AreEqual(1616245823UL, result.Result[0].BlockTime); + Assert.AreEqual(68710495UL, result.Result[0].Slot); + Assert.AreEqual("5Jofwx5JcPT1dMsgo6DkyT6x61X5chS9K7hM7huGKAnUq8xxHwGKuDnnZmPGoapWVZcN4cPvQtGNCicnWZfPHowr", result.Result[0].Signature); + Assert.AreEqual(null, result.Result[0].Memo); + Assert.AreEqual(null, result.Result[0].Error); + + FinishTest(messageHandlerMock, TestnetUri); + } + + [TestMethod] + public void TestGetSignaturesForAddressUntil() + { + var responseData = File.ReadAllText("Resources/Http/Signatures/GetSignaturesForAddressUntilResponse.json"); + var requestData = File.ReadAllText("Resources/Http/Signatures/GetSignaturesForAddressUntilRequest.json"); + var sentMessage = string.Empty; + var messageHandlerMock = SetupTest( + (s => sentMessage = s), responseData); + + var httpClient = new HttpClient(messageHandlerMock.Object) + { + BaseAddress = TestnetUri, + }; + + var sut = new SolanaRpcClient(TestnetUrl, null, httpClient); + var result = sut.GetSignaturesForAddress( + "Vote111111111111111111111111111111111111111", + 1, until: "Vote111111111111111111111111111111111111111"); + + Assert.AreEqual(requestData, sentMessage); + Assert.IsNotNull(result.Result); + Assert.IsTrue(result.WasSuccessful); + Assert.AreEqual(1, result.Result.Length); + Assert.AreEqual(null, result.Result[0].BlockTime); + Assert.AreEqual(114UL, result.Result[0].Slot); + Assert.AreEqual("5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", result.Result[0].Signature); + Assert.AreEqual(null, result.Result[0].Memo); + Assert.AreEqual(null, result.Result[0].Error); + + FinishTest(messageHandlerMock, TestnetUri); + } + + [TestMethod] + public void TestGetSignaturesForAddressBefore() + { + var responseData = File.ReadAllText("Resources/Http/Signatures/GetSignaturesForAddressBeforeResponse.json"); + var requestData = File.ReadAllText("Resources/Http/Signatures/GetSignaturesForAddressBeforeRequest.json"); + var sentMessage = string.Empty; + var messageHandlerMock = SetupTest( + (s => sentMessage = s), responseData); + + var httpClient = new HttpClient(messageHandlerMock.Object) + { + BaseAddress = TestnetUri, + }; + + var sut = new SolanaRpcClient(TestnetUrl, null, httpClient); + var result = sut.GetSignaturesForAddress( + "Vote111111111111111111111111111111111111111", + 1, before: "Vote111111111111111111111111111111111111111"); + + Assert.AreEqual(requestData, sentMessage); + Assert.IsNotNull(result.Result); + Assert.IsTrue(result.WasSuccessful); + Assert.AreEqual(1, result.Result.Length); + Assert.AreEqual(null, result.Result[0].BlockTime); + Assert.AreEqual(114UL, result.Result[0].Slot); + Assert.AreEqual("5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv", result.Result[0].Signature); + Assert.AreEqual(null, result.Result[0].Memo); + Assert.AreEqual(null, result.Result[0].Error); + + FinishTest(messageHandlerMock, TestnetUri); + } + + [TestMethod] + public void TestGetSignatureStatuses() + { + var responseData = File.ReadAllText("Resources/Http/Signatures/GetSignatureStatusesResponse.json"); + var requestData = File.ReadAllText("Resources/Http/Signatures/GetSignatureStatusesRequest.json"); + var sentMessage = string.Empty; + var messageHandlerMock = SetupTest( + (s => sentMessage = s), responseData); + + var httpClient = new HttpClient(messageHandlerMock.Object) + { + BaseAddress = TestnetUri, + }; + + var sut = new SolanaRpcClient(TestnetUrl, null, httpClient); + var result = sut.GetSignatureStatuses( + new [] + { + "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW", + "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7" + }); + + Assert.AreEqual(requestData, sentMessage); + Assert.IsNotNull(result.Result); + Assert.IsTrue(result.WasSuccessful); + Assert.AreEqual(82UL, result.Result.Context.Slot); + Assert.AreEqual(2, result.Result.Value.Length); + Assert.AreEqual(null, result.Result.Value[1]); + Assert.AreEqual(72UL, result.Result.Value[0].Slot); + Assert.AreEqual(10UL, result.Result.Value[0].Confirmations); + Assert.AreEqual("confirmed", result.Result.Value[0].ConfirmationStatus); + + FinishTest(messageHandlerMock, TestnetUri); + } + + + [TestMethod] + public void TestGetSignatureStatusesWithHistory() + { + var responseData = File.ReadAllText("Resources/Http/Signatures/GetSignatureStatusesWithHistoryResponse.json"); + var requestData = File.ReadAllText("Resources/Http/Signatures/GetSignatureStatusesWithHistoryRequest.json"); + var sentMessage = string.Empty; + var messageHandlerMock = SetupTest( + (s => sentMessage = s), responseData); + + var httpClient = new HttpClient(messageHandlerMock.Object) + { + BaseAddress = TestnetUri, + }; + + var sut = new SolanaRpcClient(TestnetUrl, null, httpClient); + var result = sut.GetSignatureStatuses( + new [] + { + "5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW", + "5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7" + }, true); + + Assert.AreEqual(requestData, sentMessage); + Assert.IsNotNull(result.Result); + Assert.IsTrue(result.WasSuccessful); + Assert.AreEqual(82UL, result.Result.Context.Slot); + Assert.AreEqual(2, result.Result.Value.Length); + Assert.AreEqual(null, result.Result.Value[1]); + Assert.AreEqual(48UL, result.Result.Value[0].Slot); + Assert.AreEqual(null, result.Result.Value[0].Confirmations); + Assert.AreEqual("finalized", result.Result.Value[0].ConfirmationStatus); + + FinishTest(messageHandlerMock, TestnetUri); + } [TestMethod] public void TestGetSnapshotSlot() @@ -951,7 +1145,7 @@ public void TestGetSnapshotSlot() FinishTest(messageHandlerMock, TestnetUri); } - + [TestMethod] public void TestGetSupply() { diff --git a/test/Solnet.Rpc.Test/Solnet.Rpc.Test.csproj b/test/Solnet.Rpc.Test/Solnet.Rpc.Test.csproj index 9a2343af..779ab8ac 100644 --- a/test/Solnet.Rpc.Test/Solnet.Rpc.Test.csproj +++ b/test/Solnet.Rpc.Test/Solnet.Rpc.Test.csproj @@ -426,6 +426,42 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest +