Skip to content
This repository has been archived by the owner on Jan 13, 2025. It is now read-only.

Commit

Permalink
Add RPC getStakeMinimumDelegation
Browse files Browse the repository at this point in the history
  • Loading branch information
brooksprumo committed Jul 15, 2022
1 parent 15d18a0 commit 4be5cb7
Show file tree
Hide file tree
Showing 7 changed files with 128 additions and 70 deletions.
1 change: 1 addition & 0 deletions client/src/mock_sender.rs
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,7 @@ impl RpcSender for MockSender {
active: 123,
inactive: 12,
}),
"getStakeMinimumDelegation" => Value::Number(Number::from(123_456_789)),
"getSupply" => json!(Response {
context: RpcResponseContext { slot: 1, api_version: None },
value: RpcSupply {
Expand Down
59 changes: 24 additions & 35 deletions client/src/nonblocking/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -4523,40 +4522,30 @@ 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)
self.send(RpcRequest::GetStakeMinimumDelegation, Value::Null)
.await
}

/// Request the transaction count.
Expand Down
57 changes: 22 additions & 35 deletions client/src/rpc_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Expand Down Expand Up @@ -4106,7 +4124,7 @@ mod tests {
system_transaction,
transaction::TransactionError,
},
std::{collections::HashMap, io, thread},
std::{io, thread},
};

#[test]
Expand Down Expand Up @@ -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);
}
}
2 changes: 2 additions & 0 deletions client/src/rpc_request.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ pub enum RpcRequest {
SendTransaction,
SimulateTransaction,
SignVote,
GetStakeMinimumDelegation,
}

#[allow(deprecated)]
Expand Down Expand Up @@ -184,6 +185,7 @@ impl fmt::Display for RpcRequest {
RpcRequest::SendTransaction => "sendTransaction",
RpcRequest::SimulateTransaction => "simulateTransaction",
RpcRequest::SignVote => "signVote",
RpcRequest::GetStakeMinimumDelegation => "getStakeMinimumDelegation",
};

write!(f, "{}", method)
Expand Down
29 changes: 29 additions & 0 deletions docs/src/developing/clients/jsonrpc-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -2451,6 +2452,34 @@ Result:
}
```

### getStakeMinimumDelegation

Returns the stake minimum delegation, in lamports.

#### Parameters:

None

#### Results:

- `<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": 1000000000, "id": 1 }
```

### getSupply

Returns information about the current supply.
Expand Down
1 change: 1 addition & 0 deletions rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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" }
Expand Down
49 changes: 49 additions & 0 deletions rpc/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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]) {
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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())
}
}
}

Expand Down Expand Up @@ -8358,4 +8382,29 @@ pub mod tests {
)
);
}

#[test]
fn test_rpc_get_stake_minimum_delegation() {
let rpc = RpcHandler::start();
let bank = rpc.working_bank();
let stake_minimum_delegation =
solana_stake_program::get_minimum_delegation(&bank.feature_set);
let RpcHandler { meta, io, .. } = rpc;

let req = r#"{"jsonrpc":"2.0","id":1,"method":"getStakeMinimumDelegation"}"#;
let res = io.handle_request_sync(req, meta);
let expected = json!({
"jsonrpc": "2.0",
"result": {
"context": {"slot": 0, "apiVersion": RpcApiVersion::default()},
"value": stake_minimum_delegation,
},
"id": 1
});
let expected: Response =
serde_json::from_value(expected).expect("expected response deserialization");
let result: Response = serde_json::from_str(&res.expect("actual response"))
.expect("actual response deserialization");
assert_eq!(result, expected);
}
}

0 comments on commit 4be5cb7

Please sign in to comment.