Skip to content

Commit

Permalink
Implement signatures and performance methods (#64)
Browse files Browse the repository at this point in the history
* Implements signature methods and performance samples.
  • Loading branch information
hoakbuilds committed Jun 5, 2021
1 parent 3db161a commit a81d695
Show file tree
Hide file tree
Showing 19 changed files with 561 additions and 1 deletion.
5 changes: 5 additions & 0 deletions src/Solnet.Examples/SolnetRpcTester.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
45 changes: 45 additions & 0 deletions src/Solnet.Rpc/IRpcClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -424,6 +424,51 @@ public interface IRpcClient

/// <inheritdoc cref="SolanaRpcClient.GetSnapshotSlotAsync"/>
RequestResult<ulong> GetSnapshotSlot();

/// <summary>
/// Gets a list of recent performance samples.
/// <remarks>
/// Unless <c>searchTransactionHistory</c> is included, this method only searches the recent status cache of signatures.
/// </remarks>
/// </summary>
/// <param name="limit">Maximum transaction signatures to return, between 1-720. Default is 720.</param>
/// <returns>A task which may return a request result the signatures for the transactions.</returns>
Task<RequestResult<PerformanceSample[]>> GetRecentPerformanceSamplesAsync(ulong limit = 720);

/// <inheritdoc cref="SolanaRpcClient.GetRecentPerformanceSamplesAsync"/>
RequestResult<PerformanceSample[]> GetRecentPerformanceSamples(ulong limit = 720);

/// <summary>
/// Gets confirmed signatures for transactions involving the address.
/// <remarks>
/// Unless <c>searchTransactionHistory</c> is included, this method only searches the recent status cache of signatures.
/// </remarks>
/// </summary>
/// <param name="accountPubKey">The account address as base-58 encoded string.</param>
/// <param name="limit">Maximum transaction signatures to return, between 1-1000. Default is 1000.</param>
/// <param name="before">Start searching backwards from this transaction signature.</param>
/// <param name="until">Search until this transaction signature, if found before limit is reached.</param>
/// <returns>A task which may return a request result the signatures for the transactions.</returns>
Task<RequestResult<SignatureStatusInfo[]>> GetSignaturesForAddressAsync(string accountPubKey, ulong limit = 1000, string before = "", string until = "");

/// <inheritdoc cref="IRpcClient.GetSignaturesForAddressAsync"/>
RequestResult<SignatureStatusInfo[]> GetSignaturesForAddress(string accountPubKey, ulong limit = 1000, string before = "", string until = "");

/// <summary>
/// Gets the status of a list of signatures.
/// <remarks>
/// Unless <c>searchTransactionHistory</c> is included, this method only searches the recent status cache of signatures.
/// </remarks>
/// </summary>
/// <param name="transactionHashes">The list of transactions to search status info for.</param>
/// <param name="searchTransactionHistory">If the node should search for signatures in it's ledger cache.</param>
/// <returns>A task which may return a request result the highest slot with a snapshot.</returns>
Task<RequestResult<ResponseValue<SignatureStatusInfo[]>>> GetSignatureStatusesAsync(string[] transactionHashes,
bool searchTransactionHistory = false);

/// <inheritdoc cref="SolanaRpcClient.GetSignatureStatusesAsync"/>
RequestResult<ResponseValue<SignatureStatusInfo[]>> GetSignatureStatuses(string[] transactionHashes,
bool searchTransactionHistory = false);

/// <summary>
/// Gets the current slot the node is processing
Expand Down
28 changes: 28 additions & 0 deletions src/Solnet.Rpc/Models/Performance.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace Solnet.Rpc.Models
{
/// <summary>
/// Represents a performance sample.
/// </summary>
public class PerformanceSample
{
/// <summary>
/// Slot in which sample was taken at.
/// </summary>
public ulong Slot { get; set; }

/// <summary>
/// Number of transactions in sample.
/// </summary>
public ulong NumTransactions { get; set; }

/// <summary>
/// Number of slots in sample
/// </summary>
public ulong NumSlots { get; set; }

/// <summary>
/// Number of seconds in a sample window.
/// </summary>
public int SamplePeriodSecs { get; set; }
}
}
46 changes: 46 additions & 0 deletions src/Solnet.Rpc/Models/Signature.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.Text.Json.Serialization;

namespace Solnet.Rpc.Models
{
/// <summary>
/// Represents the signature status information.
/// </summary>
public class SignatureStatusInfo
{
/// <summary>
/// The slot the transaction was processed in.
/// </summary>
public ulong Slot { get; set; }

/// <summary>
/// The number of blocks since signature confirmation.
/// </summary>
public ulong? Confirmations { get; set; }

/// <summary>
/// The error if the transaction failed, null if it succeeded.
/// </summary>
[JsonPropertyName("err")]
public TransactionError Error { get; set; }

/// <summary>
/// The transaction's cluster confirmation status, either "processed", "confirmed" or "finalized".
/// </summary>
public string ConfirmationStatus { get; set; }

/// <summary>
/// Memo associated with the transaction, null if no memo is present.
/// </summary>
public string Memo { get; set; }

/// <summary>
/// The transaction signature as base-58 encoded string.
/// </summary>
public string Signature { get; set; }

/// <summary>
/// Estimated production time as Unix timestamp, null if not available.
/// </summary>
public ulong? BlockTime { get; set; }
}
}
72 changes: 72 additions & 0 deletions src/Solnet.Rpc/SolanaRpcClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,78 @@ public async Task<RequestResult<ulong>> GetSnapshotSlotAsync()
/// <inheritdoc cref="GetSnapshotSlotAsync"/>
public RequestResult<ulong> GetSnapshotSlot() => GetSnapshotSlotAsync().Result;

/// <summary>
/// Gets a list of recent performance samples.
/// <remarks>
/// Unless <c>searchTransactionHistory</c> is included, this method only searches the recent status cache of signatures.
/// </remarks>
/// </summary>
/// <param name="limit">Maximum transaction signatures to return, between 1-720. Default is 720.</param>
/// <returns>A task which may return a request result the signatures for the transactions.</returns>
public async Task<RequestResult<PerformanceSample[]>> GetRecentPerformanceSamplesAsync(ulong limit = 720)
{
return await SendRequestAsync<PerformanceSample[]>("getRecentPerformanceSamples" ,
new List<object>{limit});
}

/// <inheritdoc cref="GetRecentPerformanceSamplesAsync"/>
public RequestResult<PerformanceSample[]> GetRecentPerformanceSamples(ulong limit = 720)
=> GetRecentPerformanceSamplesAsync(limit).Result;

/// <summary>
/// Gets confirmed signatures for transactions involving the address.
/// <remarks>
/// Unless <c>searchTransactionHistory</c> is included, this method only searches the recent status cache of signatures.
/// </remarks>
/// </summary>
/// <param name="accountPubKey">The account address as base-58 encoded string.</param>
/// <param name="limit">Maximum transaction signatures to return, between 1-1000. Default is 1000.</param>
/// <param name="before">Start searching backwards from this transaction signature.</param>
/// <param name="until">Search until this transaction signature, if found before limit is reached.</param>
/// <returns>A task which may return a request result the signatures for the transactions.</returns>
public async Task<RequestResult<SignatureStatusInfo[]>> GetSignaturesForAddressAsync(
string accountPubKey, ulong limit = 1000, string before = "", string until = "")
{
var dictionary = new Dictionary<string, object> {{"limit", limit}};

if (!string.IsNullOrWhiteSpace(before))
dictionary.Add("before", before);

if (!string.IsNullOrWhiteSpace(until))
dictionary.Add("until", until);

return await SendRequestAsync<SignatureStatusInfo[]>("getSignaturesForAddress" ,
new List<object>{accountPubKey, dictionary});
}

/// <inheritdoc cref="GetSignaturesForAddressAsync"/>
public RequestResult<SignatureStatusInfo[]> GetSignaturesForAddress(
string accountPubKey, ulong limit = 1000, string before = "", string until = "")
=> GetSignaturesForAddressAsync(accountPubKey, limit, before, until).Result;

/// <summary>
/// Gets the status of a list of signatures.
/// <remarks>
/// Unless <c>searchTransactionHistory</c> is included, this method only searches the recent status cache of signatures.
/// </remarks>
/// </summary>
/// <param name="transactionHashes">The list of transactions to search status info for.</param>
/// <param name="searchTransactionHistory">If the node should search for signatures in it's ledger cache.</param>
/// <returns>A task which may return a request result the highest slot with a snapshot.</returns>
public async Task<RequestResult<ResponseValue<SignatureStatusInfo[]>>> GetSignatureStatusesAsync(string[] transactionHashes, bool searchTransactionHistory = false)
{
if (searchTransactionHistory)
return await SendRequestAsync<ResponseValue<SignatureStatusInfo[]>>("getSignatureStatuses" ,
new List<object>{transactionHashes, new Dictionary<string, bool>{ { "searchTransactionHistory", true }}});
return await SendRequestAsync<ResponseValue<SignatureStatusInfo[]>>("getSignatureStatuses" ,
new List<object>{transactionHashes});
}

/// <inheritdoc cref="GetSignatureStatusesAsync"/>
public RequestResult<ResponseValue<SignatureStatusInfo[]>> GetSignatureStatuses(string[] transactionHashes,
bool searchTransactionHistory = false)
=> GetSignatureStatusesAsync(transactionHashes, searchTransactionHistory).Result;

/// <summary>
/// Gets the current slot the node is processing
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"method":"getRecentPerformanceSamples","params":[4],"jsonrpc":"2.0","id":0}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"method":"getSignatureStatuses","params":[["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW","5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7"]],"jsonrpc":"2.0","id":0}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"method":"getSignatureStatuses","params":[["5VERv8NMvzbJMEkV8xnrLkEaWRtSz9CosKDYjCJjBRnbJLgp8uirBgmQpjKhoR4tjF3ZpRzrFmBV6UjKdiSZkQUW","5j7s6NiJS3JAkvgkoc18WVAsiSaci2pxB2A6ueCJP4tprA2TFg9wSyTLeYouxPBJEMzJinENTkpA52YStRW5Dia7"],{"searchTransactionHistory":true}],"jsonrpc":"2.0","id":0}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"method":"getSignaturesForAddress","params":["Vote111111111111111111111111111111111111111",{"limit":1,"before":"Vote111111111111111111111111111111111111111"}],"jsonrpc":"2.0","id":0}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"jsonrpc": "2.0",
"result": [
{
"err": null,
"memo": null,
"signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv",
"slot": 114,
"blockTime": null
}
],
"id": 1
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"method":"getSignaturesForAddress","params":["4Rf9mGD7FeYknun5JczX5nGLTfQuS1GRjNVfkEMKE92b",{"limit":3}],"jsonrpc":"2.0","id":0}
Original file line number Diff line number Diff line change
@@ -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
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{"method":"getSignaturesForAddress","params":["Vote111111111111111111111111111111111111111",{"limit":1,"until":"Vote111111111111111111111111111111111111111"}],"jsonrpc":"2.0","id":0}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"jsonrpc": "2.0",
"result": [
{
"err": null,
"memo": null,
"signature": "5h6xBEauJ3PK6SWCZ1PGjBvj8vDdWG3KpwATGy1ARAXFSDwt8GFXM7W5Ncn16wmqokgpiKRLuS83KUxyZyv2sUYv",
"slot": 114,
"blockTime": null
}
],
"id": 1
}
Loading

0 comments on commit a81d695

Please sign in to comment.