Add RPC getStakeMinimumDelegation (#26638)
* Add RPC getStakeMinimumDelegation * fixup! rpc * fixup rpc * fixup rpc client mock sender * fixup docs * pr: sort
This commit is contained in:
parent
0d7d2090a2
commit
a8be960e05
|
@ -288,6 +288,10 @@ impl RpcSender for MockSender {
|
|||
active: 123,
|
||||
inactive: 12,
|
||||
}),
|
||||
"getStakeMinimumDelegation" => json!(Response {
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: 123_456_789,
|
||||
}),
|
||||
"getSupply" => json!(Response {
|
||||
context: RpcResponseContext { slot: 1, api_version: None },
|
||||
value: RpcSupply {
|
||||
|
|
|
@ -40,11 +40,10 @@ use {
|
|||
epoch_schedule::EpochSchedule,
|
||||
fee_calculator::{FeeCalculator, FeeRateGovernor},
|
||||
hash::Hash,
|
||||
instruction::InstructionError,
|
||||
message::Message,
|
||||
pubkey::Pubkey,
|
||||
signature::Signature,
|
||||
transaction::{self, uses_durable_nonce, Transaction, TransactionError},
|
||||
transaction::{self, uses_durable_nonce, Transaction},
|
||||
},
|
||||
solana_transaction_status::{
|
||||
EncodedConfirmedBlock, EncodedConfirmedTransactionWithStatusMeta, TransactionStatus,
|
||||
|
@ -4523,40 +4522,32 @@ impl RpcClient {
|
|||
}
|
||||
|
||||
/// Returns the stake minimum delegation, in lamports.
|
||||
///
|
||||
/// # RPC Reference
|
||||
///
|
||||
/// This method corresponds directly to the [`getStakeMinimumDelegation`] RPC method.
|
||||
///
|
||||
/// [`getStakeMinimumDelegation`]: https://docs.solana.com/developing/clients/jsonrpc-api#getstakeminimumdelegation
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use solana_client::{
|
||||
/// # nonblocking::rpc_client::RpcClient,
|
||||
/// # client_error::ClientError,
|
||||
/// # };
|
||||
/// # futures::executor::block_on(async {
|
||||
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||
/// let stake_minimum_delegation = rpc_client.get_stake_minimum_delegation().await?;
|
||||
/// # Ok::<(), ClientError>(())
|
||||
/// # })?;
|
||||
/// # Ok::<(), ClientError>(())
|
||||
/// ```
|
||||
pub async fn get_stake_minimum_delegation(&self) -> ClientResult<u64> {
|
||||
let instruction = solana_sdk::stake::instruction::get_minimum_delegation();
|
||||
let transaction = Transaction::new_with_payer(&[instruction], None);
|
||||
let response = self.simulate_transaction(&transaction).await?;
|
||||
let RpcTransactionReturnData {
|
||||
program_id,
|
||||
data: (data, encoding),
|
||||
} = response
|
||||
.value
|
||||
.return_data
|
||||
.ok_or_else(|| ClientErrorKind::Custom("return data was empty".to_string()))?;
|
||||
if Pubkey::from_str(&program_id) != Ok(solana_sdk::stake::program::id()) {
|
||||
return Err(TransactionError::InstructionError(
|
||||
0,
|
||||
InstructionError::IncorrectProgramId,
|
||||
)
|
||||
.into());
|
||||
}
|
||||
if encoding != ReturnDataEncoding::Base64 {
|
||||
return Err(
|
||||
ClientErrorKind::Custom("return data encoding is invalid".to_string()).into(),
|
||||
);
|
||||
}
|
||||
let data = base64::decode(data).map_err(|err| {
|
||||
ClientErrorKind::Custom(format!("failed to decode return data: {}", err))
|
||||
})?;
|
||||
let minimum_delegation = u64::from_le_bytes(data.try_into().map_err(|data: Vec<u8>| {
|
||||
ClientErrorKind::Custom(format!(
|
||||
"return data cannot be represented as a u64: expected size: {}, actual size: {}",
|
||||
std::mem::size_of::<u64>(),
|
||||
data.len()
|
||||
))
|
||||
})?);
|
||||
Ok(minimum_delegation)
|
||||
Ok(self
|
||||
.send::<Response<u64>>(RpcRequest::GetStakeMinimumDelegation, Value::Null)
|
||||
.await?
|
||||
.value)
|
||||
}
|
||||
|
||||
/// Request the transaction count.
|
||||
|
|
|
@ -3713,6 +3713,24 @@ impl RpcClient {
|
|||
}
|
||||
|
||||
/// Returns the stake minimum delegation, in lamports.
|
||||
///
|
||||
/// # RPC Reference
|
||||
///
|
||||
/// This method corresponds directly to the [`getStakeMinimumDelegation`] RPC method.
|
||||
///
|
||||
/// [`getStakeMinimumDelegation`]: https://docs.solana.com/developing/clients/jsonrpc-api#getstakeminimumdelegation
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// # use solana_client::{
|
||||
/// # rpc_client::RpcClient,
|
||||
/// # client_error::ClientError,
|
||||
/// # };
|
||||
/// # let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||
/// let stake_minimum_delegation = rpc_client.get_stake_minimum_delegation()?;
|
||||
/// # Ok::<(), ClientError>(())
|
||||
/// ```
|
||||
pub fn get_stake_minimum_delegation(&self) -> ClientResult<u64> {
|
||||
self.invoke(self.rpc_client.get_stake_minimum_delegation())
|
||||
}
|
||||
|
@ -4106,7 +4124,7 @@ mod tests {
|
|||
system_transaction,
|
||||
transaction::TransactionError,
|
||||
},
|
||||
std::{collections::HashMap, io, thread},
|
||||
std::{io, thread},
|
||||
};
|
||||
|
||||
#[test]
|
||||
|
@ -4326,39 +4344,8 @@ mod tests {
|
|||
#[test]
|
||||
fn test_get_stake_minimum_delegation() {
|
||||
let expected_minimum_delegation: u64 = 123_456_789;
|
||||
let rpc_client = {
|
||||
let mocks = {
|
||||
let rpc_response = {
|
||||
let program_id = solana_sdk::stake::program::id().to_string();
|
||||
let data = (
|
||||
base64::encode(expected_minimum_delegation.to_le_bytes()),
|
||||
ReturnDataEncoding::Base64,
|
||||
);
|
||||
serde_json::to_value(Response {
|
||||
context: RpcResponseContext {
|
||||
slot: 1,
|
||||
api_version: None,
|
||||
},
|
||||
value: RpcSimulateTransactionResult {
|
||||
err: None,
|
||||
logs: None,
|
||||
accounts: None,
|
||||
units_consumed: None,
|
||||
return_data: Some(RpcTransactionReturnData { program_id, data }),
|
||||
},
|
||||
})
|
||||
.unwrap()
|
||||
};
|
||||
let mut mocks = HashMap::new();
|
||||
mocks.insert(RpcRequest::SimulateTransaction, rpc_response);
|
||||
mocks
|
||||
};
|
||||
RpcClient::new_mock_with_mocks("succeeds".to_string(), mocks)
|
||||
};
|
||||
|
||||
let client_result = rpc_client.get_stake_minimum_delegation();
|
||||
assert!(client_result.is_ok());
|
||||
let actual_minimum_delegation = client_result.unwrap();
|
||||
assert_eq!(actual_minimum_delegation, expected_minimum_delegation);
|
||||
let rpc_client = RpcClient::new_mock("succeeds".to_string());
|
||||
let actual_minimum_delegation = rpc_client.get_stake_minimum_delegation().unwrap();
|
||||
assert_eq!(expected_minimum_delegation, actual_minimum_delegation);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ pub enum RpcRequest {
|
|||
GetStorageTurnRate,
|
||||
GetSlotsPerSegment,
|
||||
GetStakeActivation,
|
||||
GetStakeMinimumDelegation,
|
||||
GetStoragePubkeysForSlot,
|
||||
GetSupply,
|
||||
GetTokenAccountBalance,
|
||||
|
@ -164,6 +165,7 @@ impl fmt::Display for RpcRequest {
|
|||
RpcRequest::GetSlotLeader => "getSlotLeader",
|
||||
RpcRequest::GetSlotLeaders => "getSlotLeaders",
|
||||
RpcRequest::GetStakeActivation => "getStakeActivation",
|
||||
RpcRequest::GetStakeMinimumDelegation => "getStakeMinimumDelegation",
|
||||
RpcRequest::GetStorageTurn => "getStorageTurn",
|
||||
RpcRequest::GetStorageTurnRate => "getStorageTurnRate",
|
||||
RpcRequest::GetSlotsPerSegment => "getSlotsPerSegment",
|
||||
|
|
|
@ -54,6 +54,7 @@ gives a convenient interface for the RPC methods.
|
|||
- [getSlotLeader](jsonrpc-api.md#getslotleader)
|
||||
- [getSlotLeaders](jsonrpc-api.md#getslotleaders)
|
||||
- [getStakeActivation](jsonrpc-api.md#getstakeactivation)
|
||||
- [getStakeMinimumDelegation](jsonrpc-api.md#getstakeminimumdelegation)
|
||||
- [getSupply](jsonrpc-api.md#getsupply)
|
||||
- [getTokenAccountBalance](jsonrpc-api.md#gettokenaccountbalance)
|
||||
- [getTokenAccountsByDelegate](jsonrpc-api.md#gettokenaccountsbydelegate)
|
||||
|
@ -2451,6 +2452,45 @@ Result:
|
|||
}
|
||||
```
|
||||
|
||||
### getStakeMinimumDelegation
|
||||
|
||||
Returns the stake minimum delegation, in lamports.
|
||||
|
||||
#### Parameters:
|
||||
|
||||
None
|
||||
|
||||
#### Results:
|
||||
|
||||
The result will be an RpcResponse JSON object with `value` equal to:
|
||||
|
||||
- `<u64>` - The stake minimum delegation, in lamports
|
||||
|
||||
#### Example:
|
||||
|
||||
Request:
|
||||
|
||||
```bash
|
||||
curl http://localhost:8899 -X POST -H "Content-Type: application/json" -d '
|
||||
{"jsonrpc":"2.0","id":1,"method":"getStakeMinimumDelegation"}
|
||||
'
|
||||
```
|
||||
|
||||
Result:
|
||||
|
||||
```json
|
||||
{
|
||||
"jsonrpc": "2.0",
|
||||
"result": {
|
||||
"context": {
|
||||
"slot": 501
|
||||
},
|
||||
"value": 1000000000
|
||||
},
|
||||
"id": 1
|
||||
}
|
||||
```
|
||||
|
||||
### getSupply
|
||||
|
||||
Returns information about the current supply.
|
||||
|
|
|
@ -5278,6 +5278,7 @@ dependencies = [
|
|||
"solana-runtime",
|
||||
"solana-sdk 1.11.4",
|
||||
"solana-send-transaction-service",
|
||||
"solana-stake-program",
|
||||
"solana-storage-bigtable",
|
||||
"solana-streamer",
|
||||
"solana-transaction-status",
|
||||
|
|
|
@ -43,6 +43,7 @@ solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "=1.11.4"
|
|||
solana-runtime = { path = "../runtime", version = "=1.11.4" }
|
||||
solana-sdk = { path = "../sdk", version = "=1.11.4" }
|
||||
solana-send-transaction-service = { path = "../send-transaction-service", version = "=1.11.4" }
|
||||
solana-stake-program = { path = "../programs/stake", version = "=1.11.4" }
|
||||
solana-storage-bigtable = { path = "../storage-bigtable", version = "=1.11.4" }
|
||||
solana-streamer = { path = "../streamer", version = "=1.11.4" }
|
||||
solana-transaction-status = { path = "../transaction-status", version = "=1.11.4" }
|
||||
|
|
|
@ -80,6 +80,7 @@ use {
|
|||
send_transaction_service::{SendTransactionService, TransactionInfo},
|
||||
tpu_info::NullTpuInfo,
|
||||
},
|
||||
solana_stake_program,
|
||||
solana_storage_bigtable::Error as StorageError,
|
||||
solana_streamer::socket::SocketAddrSpace,
|
||||
solana_transaction_status::{
|
||||
|
@ -2169,6 +2170,13 @@ impl JsonRpcRequestProcessor {
|
|||
let fee = bank.get_fee_for_message(message);
|
||||
Ok(new_response(&bank, fee))
|
||||
}
|
||||
|
||||
fn get_stake_minimum_delegation(&self, config: RpcContextConfig) -> Result<RpcResponse<u64>> {
|
||||
let bank = self.get_bank_with_config(config)?;
|
||||
let stake_minimum_delegation =
|
||||
solana_stake_program::get_minimum_delegation(&bank.feature_set);
|
||||
Ok(new_response(&bank, stake_minimum_delegation))
|
||||
}
|
||||
}
|
||||
|
||||
fn optimize_filters(filters: &mut [RpcFilterType]) {
|
||||
|
@ -3401,6 +3409,13 @@ pub mod rpc_full {
|
|||
data: String,
|
||||
config: Option<RpcContextConfig>,
|
||||
) -> Result<RpcResponse<Option<u64>>>;
|
||||
|
||||
#[rpc(meta, name = "getStakeMinimumDelegation")]
|
||||
fn get_stake_minimum_delegation(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
config: Option<RpcContextConfig>,
|
||||
) -> Result<RpcResponse<u64>>;
|
||||
}
|
||||
|
||||
pub struct FullImpl;
|
||||
|
@ -3970,6 +3985,15 @@ pub mod rpc_full {
|
|||
})?;
|
||||
meta.get_fee_for_message(&sanitized_message, config.unwrap_or_default())
|
||||
}
|
||||
|
||||
fn get_stake_minimum_delegation(
|
||||
&self,
|
||||
meta: Self::Metadata,
|
||||
config: Option<RpcContextConfig>,
|
||||
) -> Result<RpcResponse<u64>> {
|
||||
debug!("get_stake_minimum_delegation rpc request received");
|
||||
meta.get_stake_minimum_delegation(config.unwrap_or_default())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8358,4 +8382,21 @@ pub mod tests {
|
|||
)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rpc_get_stake_minimum_delegation() {
|
||||
let rpc = RpcHandler::start();
|
||||
let bank = rpc.working_bank();
|
||||
let expected_stake_minimum_delegation =
|
||||
solana_stake_program::get_minimum_delegation(&bank.feature_set);
|
||||
|
||||
let request = create_test_request("getStakeMinimumDelegation", None);
|
||||
let response: RpcResponse<u64> = parse_success_result(rpc.handle_request_sync(request));
|
||||
let actual_stake_minimum_delegation = response.value;
|
||||
|
||||
assert_eq!(
|
||||
actual_stake_minimum_delegation,
|
||||
expected_stake_minimum_delegation
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue