use koios_sdk::{
models::pool::{PoolStatus, SnapshotType, UpdateType},
types::{EpochNo, PoolBech32},
Client,
};
use pretty_assertions::assert_eq;
use serde_json::json;
use wiremock::{
matchers::{body_json, header, method, path, query_param},
Mock, MockServer, ResponseTemplate,
};
async fn setup_test_client() -> (MockServer, Client) {
let mock_server = MockServer::start().await;
let client = Client::builder()
.base_url(mock_server.uri())
.build()
.unwrap();
(mock_server, client)
}
#[tokio::test]
async fn test_get_pool_list() {
let (mock_server, client) = setup_test_client().await;
let mock_response = json!([{
"pool_id_bech32": "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy",
"pool_id_hex": "0f292fcaa02b8b2f9b3c8f9fd8e0bb21abedb692a6d5058df3ef2735",
"active_epoch_no": 321,
"margin": 0.015,
"fixed_cost": "340000000",
"pledge": "10000000000",
"reward_addr": "stake1uxkptsa4lkr55jleztw43t37vgdn88l6ghclfwuxld2eykq7dls9w",
"owners": ["stake1u98nnlkvkk23vtvf9273uq7cph5ww6u2yq2389psuqet90sv4xv9v"],
"relays": [],
"ticker": "TEST",
"meta_url": "https://example.com/metadata.json",
"meta_hash": "e394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"pool_status": "registered",
"active_stake": "23456789000",
"retiring_epoch": null
}]);
Mock::given(method("GET"))
.and(path("/pool_list"))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client.get_pool_list().await.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(
response[0].pool_id_bech32,
"pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy"
);
assert_eq!(response[0].margin.unwrap(), 0.015);
assert_eq!(response[0].fixed_cost.as_ref().unwrap(), "340000000");
assert_eq!(response[0].pledge.as_ref().unwrap(), "10000000000");
assert_eq!(response[0].pool_status, PoolStatus::Registered);
}
#[tokio::test]
async fn test_get_pool_info() {
let (mock_server, client) = setup_test_client().await;
let pool_ids = vec!["pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy".to_string()];
let mock_response = json!([{
"pool_id_bech32": "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy",
"pool_id_hex": "0f292fcaa02b8b2f9b3c8f9fd8e0bb21abedb692a6d5058df3ef2735",
"active_epoch_no": 321,
"vrf_key_hash": "e394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"margin": 0.015,
"fixed_cost": "340000000",
"pledge": "10000000000",
"reward_addr": "stake1uxkptsa4lkr55jleztw43t37vgdn88l6ghclfwuxld2eykq7dls9w",
"owners": ["stake1u98nnlkvkk23vtvf9273uq7cph5ww6u2yq2389psuqet90sv4xv9v"],
"relays": [{
"dns": "relay.example.com",
"srv": null,
"ipv4": "192.168.1.1",
"ipv6": null,
"port": 3001
}],
"meta_url": "https://example.com/metadata.json",
"meta_hash": "e394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"meta_json": {
"name": "Test Pool",
"description": "A test stake pool",
"ticker": "TEST",
"homepage": "https://example.com"
},
"pool_status": "registered",
"retiring_epoch": null,
"op_cert": "d05c10588ed1153be128c44d26241a229c5181c789067bf245e5ea7c28d5f05f",
"op_cert_counter": 5,
"active_stake": "23456789000",
"sigma": 0.002,
"block_count": 100,
"live_pledge": "10500000000",
"live_stake": "24000000000",
"live_delegators": 1000,
"live_saturation": 0.8
}]);
Mock::given(method("POST"))
.and(path("/pool_info"))
.and(header("Content-Type", "application/json"))
.and(body_json(json!({
"_pool_bech32_ids": pool_ids
})))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client.get_pool_info(&pool_ids).await.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(response[0].pool_id_bech32, pool_ids[0]);
assert_eq!(response[0].margin.unwrap(), 0.015);
assert!(response[0].relays.len() > 0);
assert_eq!(response[0].pool_status, PoolStatus::Registered);
assert_eq!(response[0].op_cert_counter.unwrap(), 5);
assert_eq!(response[0].block_count.unwrap(), 100);
assert_eq!(response[0].live_delegators, 1000);
}
#[tokio::test]
async fn test_get_pool_stake_snapshot() {
let (mock_server, client) = setup_test_client().await;
let pool_id = PoolBech32::new("pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy");
let mock_response = json!([
{
"snapshot": "mark",
"epoch_no": 321,
"nonce": "e394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"pool_stake": "23456789000",
"active_stake": "42000000000000"
},
{
"snapshot": "set",
"epoch_no": 321,
"nonce": "f394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"pool_stake": "23556789000",
"active_stake": "42100000000000"
}
]);
Mock::given(method("GET"))
.and(path("/pool_stake_snapshot"))
.and(query_param("_pool_bech32", pool_id.value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client.get_pool_stake_snapshot(&pool_id).await.unwrap();
assert_eq!(response.len(), 2);
assert_eq!(response[0].snapshot, SnapshotType::Mark);
assert_eq!(response[1].snapshot, SnapshotType::Set);
assert_eq!(response[0].epoch_no, 321);
assert_eq!(response[0].pool_stake, "23456789000");
}
#[tokio::test]
async fn test_get_pool_delegators() {
let (mock_server, client) = setup_test_client().await;
let pool_id = PoolBech32::new("pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy");
let mock_response = json!([{
"stake_address": "stake1u9ylzsgxaa6xctf4juup682ar3juj85n8tx3hthnljg47zctvm3rc",
"amount": "1000000000",
"active_epoch_no": 321,
"latest_delegation_tx_hash": "6ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6541"
}]);
Mock::given(method("GET"))
.and(path("/pool_delegators"))
.and(query_param("_pool_bech32", pool_id.value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client.get_pool_delegators(&pool_id).await.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(
response[0].stake_address,
"stake1u9ylzsgxaa6xctf4juup682ar3juj85n8tx3hthnljg47zctvm3rc"
);
assert_eq!(response[0].amount, "1000000000");
assert_eq!(response[0].active_epoch_no, 321);
}
#[tokio::test]
async fn test_get_pool_delegators_history() {
let (mock_server, client) = setup_test_client().await;
let pool_id = PoolBech32::new("pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy");
let epoch_no = EpochNo::new("321");
let mock_response = json!([{
"stake_address": "stake1u9ylzsgxaa6xctf4juup682ar3juj85n8tx3hthnljg47zctvm3rc",
"amount": "1000000000",
"epoch_no": 321
}]);
Mock::given(method("GET"))
.and(path("/pool_delegators_history"))
.and(query_param("_pool_bech32", pool_id.value()))
.and(query_param("_epoch_no", epoch_no.value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client
.get_pool_delegators_history(&pool_id, Some(epoch_no))
.await
.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(
response[0].stake_address,
"stake1u9ylzsgxaa6xctf4juup682ar3juj85n8tx3hthnljg47zctvm3rc"
);
assert_eq!(response[0].amount, "1000000000");
assert_eq!(response[0].epoch_no, 321);
}
#[tokio::test]
async fn test_get_pool_history() {
let (mock_server, client) = setup_test_client().await;
let pool_id = PoolBech32::new("pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy");
let epoch_no = EpochNo::new("321");
let mock_response = json!([{
"epoch_no": 321,
"active_stake": "23456789000",
"active_stake_pct": 0.02,
"saturation_pct": 0.8,
"block_cnt": 100,
"delegator_cnt": 1000,
"margin": 0.015,
"fixed_cost": "340000000",
"pool_fees": "500000000",
"deleg_rewards": "1000000000",
"member_rewards": "100000000",
"epoch_ros": 0.05
}]);
Mock::given(method("GET"))
.and(path("/pool_history"))
.and(query_param("_pool_bech32", pool_id.value()))
.and(query_param("_epoch_no", epoch_no.value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client
.get_pool_history(&pool_id, Some(epoch_no))
.await
.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(response[0].epoch_no, 321);
assert_eq!(response[0].active_stake.as_ref().unwrap(), "23456789000");
assert_eq!(response[0].block_cnt.unwrap(), 100);
assert_eq!(response[0].delegator_cnt, 1000);
assert_eq!(response[0].margin, 0.015);
assert_eq!(response[0].fixed_cost, "340000000");
assert_eq!(response[0].pool_fees, "500000000");
assert_eq!(response[0].epoch_ros, 0.05);
}
#[tokio::test]
async fn test_get_pool_updates() {
let (mock_server, client) = setup_test_client().await;
let pool_id = Some(PoolBech32::new(
"pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy",
));
let mock_response = json!([{
"tx_hash": "6ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6541",
"block_time": 1630106091,
"pool_id_bech32": "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy",
"pool_id_hex": "0f292fcaa02b8b2f9b3c8f9fd8e0bb21abedb692a6d5058df3ef2735",
"active_epoch_no": 321,
"vrf_key_hash": "e394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"margin": 0.015,
"fixed_cost": "340000000",
"pledge": "10000000000",
"reward_addr": "stake1uxkptsa4lkr55jleztw43t37vgdn88l6ghclfwuxld2eykq7dls9w",
"owners": ["stake1u98nnlkvkk23vtvf9273uq7cph5ww6u2yq2389psuqet90sv4xv9v"],
"relays": [],
"meta_url": "https://example.com/metadata.json",
"meta_hash": "e394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"meta_json": {
"name": "Test Pool",
"description": "A test stake pool",
"ticker": "TEST",
"homepage": "https://example.com"
},
"update_type": "registration",
"retiring_epoch": null
}]);
Mock::given(method("GET"))
.and(path("/pool_updates"))
.and(query_param(
"_pool_bech32",
pool_id.as_ref().unwrap().value(),
))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client.get_pool_updates(pool_id.as_ref()).await.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(response[0].pool_id_bech32, pool_id.unwrap().value());
assert_eq!(response[0].margin.unwrap(), 0.015);
assert_eq!(response[0].fixed_cost.as_ref().unwrap(), "340000000");
assert_eq!(response[0].update_type, UpdateType::Registration);
}
#[tokio::test]
async fn test_get_pool_registrations() {
let (mock_server, client) = setup_test_client().await;
let epoch_no = Some(EpochNo::new("321"));
let mock_response = json!([{
"pool_id_bech32": "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy",
"tx_hash": "6ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6541",
"block_hash": "f144a8264acf4bdfe2e1241170969c930d64ab6b0996a4a45237b623f1dd670e",
"block_height": 7017300,
"epoch_no": 321,
"epoch_slot": 85691,
"active_epoch_no": 323
}]);
Mock::given(method("GET"))
.and(path("/pool_registrations"))
.and(query_param("_epoch_no", epoch_no.as_ref().unwrap().value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client.get_pool_registrations(epoch_no).await.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(
response[0].pool_id_bech32,
"pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy"
);
assert_eq!(response[0].epoch_no, 321);
assert_eq!(response[0].active_epoch_no, 323);
}
#[tokio::test]
async fn test_get_pool_retirements() {
let (mock_server, client) = setup_test_client().await;
let epoch_no = Some(EpochNo::new("321"));
let mock_response = json!([{
"pool_id_bech32": "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy",
"tx_hash": "6ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6541",
"block_hash": "f144a8264acf4bdfe2e1241170969c930d64ab6b0996a4a45237b623f1dd670e",
"block_height": 7017300,
"epoch_no": 321,
"epoch_slot": 85691,
"active_epoch_no": 323
}]);
Mock::given(method("GET"))
.and(path("/pool_retirements"))
.and(query_param("_epoch_no", epoch_no.as_ref().unwrap().value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client.get_pool_retirements(epoch_no).await.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(
response[0].pool_id_bech32,
"pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy"
);
assert_eq!(response[0].epoch_no, 321);
assert_eq!(response[0].active_epoch_no, 323);
}
#[tokio::test]
async fn test_get_pool_relays() {
let (mock_server, client) = setup_test_client().await;
let mock_response = json!([{
"pool_id_bech32": "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy",
"relays": [{
"dns": "relay1.example.com",
"srv": null,
"ipv4": "192.168.1.1",
"ipv6": null,
"port": 3001
}, {
"dns": "relay2.example.com",
"srv": null,
"ipv4": "192.168.1.2",
"ipv6": null,
"port": 3001
}]
}]);
Mock::given(method("GET"))
.and(path("/pool_relays"))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client.get_pool_relays().await.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(
response[0].pool_id_bech32,
"pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy"
);
assert_eq!(response[0].relays.len(), 2);
assert_eq!(
response[0].relays[0].dns.as_ref().unwrap(),
"relay1.example.com"
);
assert_eq!(response[0].relays[0].ipv4.as_ref().unwrap(), "192.168.1.1");
assert_eq!(response[0].relays[0].port.unwrap(), 3001);
}
#[tokio::test]
async fn test_get_pool_metadata() {
let (mock_server, client) = setup_test_client().await;
let pool_ids = Some(vec![
"pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy".to_string(),
]);
let mock_response = json!([{
"pool_id_bech32": "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy",
"meta_url": "https://example.com/metadata.json",
"meta_hash": "e394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"meta_json": {
"name": "Test Pool",
"description": "A test stake pool",
"ticker": "TEST",
"homepage": "https://example.com"
}
}]);
Mock::given(method("POST"))
.and(path("/pool_metadata"))
.and(header("Content-Type", "application/json"))
.and(body_json(json!({
"_pool_bech32_ids": pool_ids.as_ref().unwrap()
})))
.respond_with(ResponseTemplate::new(200).set_body_json(&mock_response))
.mount(&mock_server)
.await;
let response = client.get_pool_metadata(pool_ids.as_deref()).await.unwrap();
assert_eq!(response.len(), 1);
assert_eq!(
response[0].pool_id_bech32,
"pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy"
);
assert_eq!(
response[0].meta_url.as_ref().unwrap(),
"https://example.com/metadata.json"
);
let meta_json = &response[0].meta_json.as_ref().unwrap();
assert_eq!(meta_json.name.as_str(), "Test Pool");
assert_eq!(meta_json.ticker.as_str(), "TEST");
}
#[tokio::test]
async fn test_invalid_pool_id() {
let (mock_server, client) = setup_test_client().await;
let pool_id = PoolBech32::new("invalid_pool_id");
Mock::given(method("GET"))
.and(path("/pool_stake_snapshot"))
.and(query_param("_pool_bech32", pool_id.value()))
.respond_with(ResponseTemplate::new(400).set_body_string("Invalid pool ID format"))
.mount(&mock_server)
.await;
let error = client.get_pool_stake_snapshot(&pool_id).await.unwrap_err();
match error {
koios_sdk::error::Error::Api { status, message } => {
assert_eq!(status, 400);
assert_eq!(message, "Invalid pool ID format");
}
_ => panic!("Expected API error"),
}
}
#[tokio::test]
async fn test_pool_not_found() {
let (mock_server, client) = setup_test_client().await;
let pool_ids = vec!["pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy".to_string()];
Mock::given(method("POST"))
.and(path("/pool_info"))
.and(body_json(json!({
"_pool_bech32_ids": pool_ids
})))
.respond_with(ResponseTemplate::new(404).set_body_string("Pool not found"))
.mount(&mock_server)
.await;
let error = client.get_pool_info(&pool_ids).await.unwrap_err();
match error {
koios_sdk::error::Error::Api { status, message } => {
assert_eq!(status, 404);
assert_eq!(message, "Pool not found");
}
_ => panic!("Expected API error"),
}
}
#[tokio::test]
async fn test_malformed_pool_response() {
let (mock_server, client) = setup_test_client().await;
Mock::given(method("GET"))
.and(path("/pool_list"))
.respond_with(ResponseTemplate::new(200).set_body_string("invalid json"))
.mount(&mock_server)
.await;
match client.get_pool_list().await {
Err(koios_sdk::error::Error::Json(_)) | Err(koios_sdk::error::Error::HttpClient(_)) => {}
other => panic!("Expected Json or HttpClient error, got {:?}", other),
}
}
#[tokio::test]
async fn test_pool_info_and_history_integration() {
let (mock_server, client) = setup_test_client().await;
let pool_ids = vec!["pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy".to_string()];
let pool_id = PoolBech32::new(&pool_ids[0]);
let epoch_no = EpochNo::new("321");
let info_response = json!([{
"pool_id_bech32": pool_ids[0],
"pool_id_hex": "0f292fcaa02b8b2f9b3c8f9fd8e0bb21abedb692a6d5058df3ef2735",
"active_epoch_no": 321,
"vrf_key_hash": "e394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"margin": 0.015,
"fixed_cost": "340000000",
"pledge": "10000000000",
"reward_addr": "stake1uxkptsa4lkr55jleztw43t37vgdn88l6ghclfwuxld2eykq7dls9w",
"owners": ["stake1u98nnlkvkk23vtvf9273uq7cph5ww6u2yq2389psuqet90sv4xv9v"],
"relays": [],
"pool_status": "registered",
"active_stake": "23456789000",
"live_delegators": 1000
}]);
Mock::given(method("POST"))
.and(path("/pool_info"))
.and(body_json(json!({
"_pool_bech32_ids": pool_ids
})))
.respond_with(ResponseTemplate::new(200).set_body_json(&info_response))
.mount(&mock_server)
.await;
let history_response = json!([{
"epoch_no": 321,
"active_stake": "23456789000",
"active_stake_pct": 0.02,
"saturation_pct": 0.8,
"block_cnt": 100,
"delegator_cnt": 1000,
"margin": 0.015,
"fixed_cost": "340000000",
"pool_fees": "500000000",
"deleg_rewards": "1000000000",
"epoch_ros": 0.05
}]);
Mock::given(method("GET"))
.and(path("/pool_history"))
.and(query_param("_pool_bech32", pool_id.value()))
.and(query_param("_epoch_no", epoch_no.value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&history_response))
.mount(&mock_server)
.await;
let (info, history) = tokio::join!(
client.get_pool_info(&pool_ids),
client.get_pool_history(&pool_id, Some(epoch_no))
);
let info = info.unwrap();
let history = history.unwrap();
assert_eq!(info[0].pool_id_bech32, pool_id.value());
assert_eq!(info[0].active_epoch_no, history[0].epoch_no);
assert_eq!(info[0].margin.unwrap(), history[0].margin);
assert_eq!(info[0].fixed_cost.as_ref().unwrap(), &history[0].fixed_cost);
assert_eq!(
info[0].active_stake.as_ref().unwrap(),
history[0].active_stake.as_ref().unwrap()
);
}
#[tokio::test]
async fn test_pool_lifecycle() {
let (mock_server, client) = setup_test_client().await;
let pool_id = "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy";
let epoch_no = 321;
let registration_response = json!([{
"pool_id_bech32": pool_id,
"tx_hash": "6ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6541",
"block_hash": "f144a8264acf4bdfe2e1241170969c930d64ab6b0996a4a45237b623f1dd670e",
"block_height": 7017300,
"epoch_no": epoch_no,
"epoch_slot": 85691,
"active_epoch_no": 323
}]);
Mock::given(method("GET"))
.and(path("/pool_registrations"))
.and(query_param("_epoch_no", epoch_no.to_string()))
.respond_with(ResponseTemplate::new(200).set_body_json(®istration_response))
.mount(&mock_server)
.await;
let updates_response = json!([{
"tx_hash": "6ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6541",
"block_time": 1630106091,
"pool_id_bech32": pool_id,
"pool_id_hex": "0f292fcaa02b8b2f9b3c8f9fd8e0bb21abedb692a6d5058df3ef2735",
"active_epoch_no": epoch_no,
"margin": 0.015,
"fixed_cost": "340000000",
"pledge": "10000000000",
"reward_addr": "stake1uxkptsa4lkr55jleztw43t37vgdn88l6ghclfwuxld2eykq7dls9w",
"owners": ["stake1u98nnlkvkk23vtvf9273uq7cph5ww6u2yq2389psuqet90sv4xv9v"],
"relays": [],
"meta_url": null,
"meta_hash": null,
"meta_json": null,
"update_type": "registration",
"retiring_epoch": null
}]);
Mock::given(method("GET"))
.and(path("/pool_updates"))
.and(query_param("_pool_bech32", pool_id))
.respond_with(ResponseTemplate::new(200).set_body_json(&updates_response))
.mount(&mock_server)
.await;
let retirement_response = json!([{
"pool_id_bech32": pool_id,
"tx_hash": "7ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6542",
"block_hash": "g144a8264acf4bdfe2e1241170969c930d64ab6b0996a4a45237b623f1dd670f",
"block_height": 7017400,
"epoch_no": epoch_no,
"epoch_slot": 85791,
"active_epoch_no": 325
}]);
Mock::given(method("GET"))
.and(path("/pool_retirements"))
.and(query_param("_epoch_no", epoch_no.to_string()))
.respond_with(ResponseTemplate::new(200).set_body_json(&retirement_response))
.mount(&mock_server)
.await;
let pool_bech32 = PoolBech32::new(pool_id);
let (registration, updates, retirement) = tokio::join!(
client.get_pool_registrations(Some(EpochNo::new(&epoch_no.to_string()))),
client.get_pool_updates(Some(&pool_bech32)),
client.get_pool_retirements(Some(EpochNo::new(&epoch_no.to_string())))
);
let registration = registration.unwrap();
let updates = updates.unwrap();
let retirement = retirement.unwrap();
assert_eq!(registration[0].pool_id_bech32, pool_id);
assert_eq!(registration[0].epoch_no, epoch_no);
assert_eq!(updates[0].pool_id_bech32, pool_id);
assert_eq!(updates[0].update_type, UpdateType::Registration);
assert_eq!(retirement[0].pool_id_bech32, pool_id);
assert_eq!(retirement[0].epoch_no, epoch_no);
assert!(registration[0].active_epoch_no < retirement[0].active_epoch_no);
}
#[tokio::test]
async fn test_pool_delegators_and_stakes() {
let (mock_server, client) = setup_test_client().await;
let pool_id = PoolBech32::new("pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy");
let epoch_no = EpochNo::new("321");
let delegators_response = json!([{
"stake_address": "stake1u9ylzsgxaa6xctf4juup682ar3juj85n8tx3hthnljg47zctvm3rc",
"amount": "1000000000",
"active_epoch_no": 321,
"latest_delegation_tx_hash": "6ed09ba58a56c6e946668038ba4d3cef8eb97a20cbf76c5970e1402e8a8d6541"
}]);
Mock::given(method("GET"))
.and(path("/pool_delegators"))
.and(query_param("_pool_bech32", pool_id.value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&delegators_response))
.mount(&mock_server)
.await;
let snapshot_response = json!([{
"snapshot": "mark",
"epoch_no": 321,
"nonce": "e394c39f06741ace92445d61d0853d8358fd49d1fd08a0b26599bda520",
"pool_stake": "23456789000",
"active_stake": "42000000000000"
}]);
Mock::given(method("GET"))
.and(path("/pool_stake_snapshot"))
.and(query_param("_pool_bech32", pool_id.value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&snapshot_response))
.mount(&mock_server)
.await;
let history_response = json!([{
"stake_address": "stake1u9ylzsgxaa6xctf4juup682ar3juj85n8tx3hthnljg47zctvm3rc",
"amount": "1000000000",
"epoch_no": 321
}]);
Mock::given(method("GET"))
.and(path("/pool_delegators_history"))
.and(query_param("_pool_bech32", pool_id.value()))
.and(query_param("_epoch_no", epoch_no.value()))
.respond_with(ResponseTemplate::new(200).set_body_json(&history_response))
.mount(&mock_server)
.await;
let (delegators, snapshot, history) = tokio::join!(
client.get_pool_delegators(&pool_id),
client.get_pool_stake_snapshot(&pool_id),
client.get_pool_delegators_history(&pool_id, Some(epoch_no))
);
let delegators = delegators.unwrap();
let snapshot = snapshot.unwrap();
let history = history.unwrap();
assert_eq!(delegators[0].stake_address, history[0].stake_address);
assert_eq!(delegators[0].amount, history[0].amount);
assert_eq!(delegators[0].active_epoch_no, history[0].epoch_no);
assert_eq!(snapshot[0].epoch_no, history[0].epoch_no);
assert_eq!(snapshot[0].snapshot, SnapshotType::Mark);
}