#![cfg(all(feature = "ctv", feature = "bip70-http"))]
use blvm_node::config::PaymentConfig;
use blvm_node::payment::processor::PaymentProcessor;
use blvm_node::payment::state_machine::PaymentStateMachine;
use blvm_node::rpc::payment::PaymentRpc;
use blvm_node::storage::Storage;
use serde_json::{json, Value};
use std::sync::Arc;
use tempfile::TempDir;
fn create_test_payment_rpc() -> PaymentRpc {
let config = PaymentConfig::default();
let processor =
Arc::new(PaymentProcessor::new(config).expect("Failed to create payment processor"));
let state_machine = Arc::new(PaymentStateMachine::new(processor).with_congestion_manager(
None, None, blvm_node::payment::congestion::BatchConfig::default(),
));
PaymentRpc::with_state_machine(state_machine)
}
fn create_test_payment_rpc_with_storage() -> (PaymentRpc, TempDir) {
let temp_dir = TempDir::new().unwrap();
let storage_path = temp_dir.path();
let storage = Storage::new(storage_path).expect("Failed to create storage");
let storage_arc = Arc::new(storage);
let config = PaymentConfig::default();
let processor =
Arc::new(PaymentProcessor::new(config).expect("Failed to create payment processor"));
let state_machine = Arc::new(
PaymentStateMachine::with_storage(processor, Some(storage_arc.clone()))
.with_congestion_manager(
None, Some(storage_arc), blvm_node::payment::congestion::BatchConfig::default(),
),
);
(PaymentRpc::with_state_machine(state_machine), temp_dir)
}
#[tokio::test]
async fn test_rpc_createvault() {
let rpc = create_test_payment_rpc();
let params = json!({
"vault_id": "test_vault_rpc_1",
"deposit_amount": 100000,
"withdrawal_script": "5176a914000000000000000000000000000000000000000087",
"config": {
"withdrawal_delay_blocks": 144,
"require_unvault": true
}
});
let result = rpc.create_vault(¶ms).await;
assert!(result.is_ok(), "createvault should succeed");
let response = result.unwrap();
assert_eq!(response["vault_id"], "test_vault_rpc_1");
assert!(response["vault_state"].is_object());
}
#[tokio::test]
async fn test_rpc_createvault_missing_params() {
let rpc = create_test_payment_rpc();
let params = json!({
"vault_id": "test_vault_rpc_2"
});
let result = rpc.create_vault(¶ms).await;
assert!(
result.is_err(),
"createvault should fail with missing params"
);
}
#[tokio::test]
async fn test_rpc_unvault() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let create_params = json!({
"vault_id": "test_vault_rpc_3",
"deposit_amount": 100000,
"withdrawal_script": "5176a914000000000000000000000000000000000000000087",
"config": {
"require_unvault": true
}
});
rpc.create_vault(&create_params).await.unwrap();
let unvault_params = json!({
"vault_id": "test_vault_rpc_3",
"unvault_script": "5276a914000000000000000000000000000000000000000087"
});
let result = rpc.unvault(&unvault_params).await;
assert!(result.is_ok(), "unvault should succeed");
let response = result.unwrap();
assert_eq!(response["vault_id"], "test_vault_rpc_3");
assert!(response["vault_state"].is_object());
}
#[tokio::test]
async fn test_rpc_unvault_nonexistent() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let params = json!({
"vault_id": "nonexistent_vault",
"unvault_script": "5276a914000000000000000000000000000000000000000087"
});
let result = rpc.unvault(¶ms).await;
assert!(result.is_err(), "unvault should fail for nonexistent vault");
}
#[tokio::test]
async fn test_rpc_withdrawfromvault() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let create_params = json!({
"vault_id": "test_vault_rpc_4",
"deposit_amount": 100000,
"withdrawal_script": "5176a914000000000000000000000000000000000000000087",
"config": {
"withdrawal_delay_blocks": 0, "require_unvault": false }
});
rpc.create_vault(&create_params).await.unwrap();
let withdraw_params = json!({
"vault_id": "test_vault_rpc_4",
"withdrawal_script": "5376a914000000000000000000000000000000000000000087",
"current_block_height": 1000 });
let result = rpc.withdraw_from_vault(&withdraw_params).await;
assert!(result.is_ok(), "withdrawfromvault should succeed");
let response = result.unwrap();
assert_eq!(response["vault_id"], "test_vault_rpc_4");
assert!(response["vault_state"].is_object());
}
#[tokio::test]
async fn test_rpc_getvaultstate() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let create_params = json!({
"vault_id": "test_vault_rpc_5",
"deposit_amount": 100000,
"withdrawal_script": "5176a914000000000000000000000000000000000000000087"
});
rpc.create_vault(&create_params).await.unwrap();
let get_params = json!({
"vault_id": "test_vault_rpc_5"
});
let result = rpc.get_vault_state(&get_params).await;
assert!(result.is_ok(), "getvaultstate should succeed");
let response = result.unwrap();
assert_eq!(response["vault_id"], "test_vault_rpc_5");
assert!(response["vault_state"].is_object());
}
#[tokio::test]
async fn test_rpc_createpool() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let params = json!({
"pool_id": "test_pool_rpc_1",
"initial_participants": [
["participant_1", 10000, "5176a914000000000000000000000000000000000000000087"],
["participant_2", 20000, "5276a914000000000000000000000000000000000000000087"]
],
"config": {
"min_contribution": 5000
}
});
let result = rpc.create_pool(¶ms).await;
assert!(result.is_ok(), "createpool should succeed");
let response = result.unwrap();
assert_eq!(response["pool_id"], "test_pool_rpc_1");
assert!(response["pool_state"].is_object());
}
#[tokio::test]
async fn test_rpc_joinpool() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let create_params = json!({
"pool_id": "test_pool_rpc_2",
"initial_participants": [
["participant_1", 10000, "5176a914000000000000000000000000000000000000000087"]
]
});
rpc.create_pool(&create_params).await.unwrap();
let join_params = json!({
"pool_id": "test_pool_rpc_2",
"participant_id": "participant_2",
"contribution": 20000,
"script_pubkey": "5276a914000000000000000000000000000000000000000087"
});
let result = rpc.join_pool(&join_params).await;
assert!(result.is_ok(), "joinpool should succeed");
let response = result.unwrap();
assert_eq!(response["pool_id"], "test_pool_rpc_2");
}
#[tokio::test]
async fn test_rpc_distributepool() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let create_params = json!({
"pool_id": "test_pool_rpc_3",
"initial_participants": [
["participant_1", 10000, "5176a914000000000000000000000000000000000000000087"],
["participant_2", 20000, "5276a914000000000000000000000000000000000000000087"]
]
});
rpc.create_pool(&create_params).await.unwrap();
let distribute_params = json!({
"pool_id": "test_pool_rpc_3",
"distribution": [
["participant_1", 5000],
["participant_2", 10000]
]
});
let result = rpc.distribute_pool(&distribute_params).await;
assert!(result.is_ok(), "distributepool should succeed");
let response = result.unwrap();
assert_eq!(response["pool_id"], "test_pool_rpc_3");
assert!(response["covenant_proof"].is_object());
}
#[tokio::test]
async fn test_rpc_getpoolstate() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let create_params = json!({
"pool_id": "test_pool_rpc_4",
"initial_participants": [
["participant_1", 10000, "5176a914000000000000000000000000000000000000000087"]
]
});
rpc.create_pool(&create_params).await.unwrap();
let get_params = json!({
"pool_id": "test_pool_rpc_4"
});
let result = rpc.get_pool_state(&get_params).await;
assert!(result.is_ok(), "getpoolstate should succeed");
let response = result.unwrap();
assert_eq!(response["pool_id"], "test_pool_rpc_4");
assert!(response["pool_state"].is_object());
}
#[tokio::test]
async fn test_rpc_createbatch() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let params = json!({
"batch_id": "test_batch_rpc_1",
"target_fee_rate": 10
});
let result = rpc.create_batch(¶ms).await;
assert!(result.is_ok(), "createbatch should succeed");
let response = result.unwrap();
assert_eq!(response["batch_id"], "test_batch_rpc_1");
}
#[tokio::test]
async fn test_rpc_createbatch_default_fee() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let params = json!({
"batch_id": "test_batch_rpc_2"
});
let result = rpc.create_batch(¶ms).await;
assert!(
result.is_ok(),
"createbatch should succeed with default fee"
);
let response = result.unwrap();
assert_eq!(response["batch_id"], "test_batch_rpc_2");
}
#[tokio::test]
async fn test_rpc_addtobatch() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let create_params = json!({
"batch_id": "test_batch_rpc_3"
});
rpc.create_batch(&create_params).await.unwrap();
let add_params = json!({
"batch_id": "test_batch_rpc_3",
"tx_id": "test_tx_1",
"outputs": [
{
"amount": 10000,
"script_pubkey": "5176a914000000000000000000000000000000000000000087"
}
],
"priority": "normal"
});
let result = rpc.add_to_batch(&add_params).await;
assert!(result.is_ok(), "addtobatch should succeed");
let response = result.unwrap();
assert_eq!(response["batch_id"], "test_batch_rpc_3");
assert!(response["batch_size"].as_u64().unwrap() > 0);
}
#[tokio::test]
async fn test_rpc_getcongestionmetrics() {
let rpc = create_test_payment_rpc();
let params = json!({});
let result = rpc.get_congestion_metrics(¶ms).await;
assert!(
result.is_err(),
"getcongestionmetrics should fail without mempool"
);
}
#[tokio::test]
async fn test_rpc_broadcastbatch() {
let (rpc, _temp_dir) = create_test_payment_rpc_with_storage();
let create_params = json!({
"batch_id": "test_batch_rpc_4"
});
rpc.create_batch(&create_params).await.unwrap();
let add_params = json!({
"batch_id": "test_batch_rpc_4",
"tx_id": "test_tx_2",
"outputs": [
{
"amount": 20000,
"script_pubkey": "5276a914000000000000000000000000000000000000000087"
}
],
"priority": "normal"
});
rpc.add_to_batch(&add_params).await.unwrap();
let broadcast_params = json!({
"batch_id": "test_batch_rpc_4"
});
let result = rpc.broadcast_batch(&broadcast_params).await;
assert!(result.is_ok(), "broadcastbatch should succeed");
let response = result.unwrap();
assert_eq!(response["batch_id"], "test_batch_rpc_4");
assert!(response["ready_to_broadcast"].as_bool().unwrap());
assert!(response["covenant_proof"].is_object());
}