diff --git a/src/lib.rs b/src/lib.rs index bf33897..863ee2a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1358,10 +1358,51 @@ impl WalletClient { } /// Create a new account - pub async fn create_account(&self, label: Option) -> anyhow::Result { + pub async fn create_account(&self, label: Option) -> anyhow::Result { let params = empty().chain(once(("label", label.into()))); self.inner - .request::("create_account", RpcParams::map(params)) + .request::("create_account", RpcParams::map(params)) + .await + } + + /// Create a transaction proof + pub async fn get_tx_proof( + &self, + txid: HashString>, + address: Address, + message: Option, + ) -> anyhow::Result { + let params = empty() + .chain(once(("txid", txid.to_string().into()))) + .chain(once(("address", address.to_string().into()))) + .chain(once(("message", message.into()))); + #[derive(Clone, Debug, Serialize, Deserialize)] + struct Rsp { + signature: String, + } + + Ok(self + .inner + .request::("get_tx_proof", RpcParams::map(params)) + .await? + .signature) + } + + /// Check a transaction proof + pub async fn check_tx_proof( + &self, + txid: HashString>, + address: Address, + message: Option, + signature: String, + ) -> anyhow::Result { + let params = empty() + .chain(once(("txid", txid.to_string().into()))) + .chain(once(("address", address.to_string().into()))) + .chain(once(("message", message.into()))) + .chain(once(("signature", signature.into()))); + self.inner + .request::("check_tx_proof", RpcParams::map(params)) .await } } diff --git a/src/models.rs b/src/models.rs index c9b0db4..de58bcf 100644 --- a/src/models.rs +++ b/src/models.rs @@ -559,15 +559,29 @@ pub struct KeyImageImportResponse { pub unspent: Amount, } -/// Return type of wallet `create_wallet`. +/// Return type of `create_wallet`. #[derive(Clone, Debug, Serialize, Deserialize)] -pub struct CreateWallet { +pub struct AccountCreation { /// Index of the new account. pub account_index: u32, /// Generated wallet address. pub address: Address, } +/// Return type of `check_tx_proof`. +#[derive(Clone, Debug, Deserialize)] +pub struct TxProofOutput { + /// Number of block mined after the one with the transaction. + pub confirmations: u32, + /// States if the inputs proves the transaction. + pub good: bool, + /// States if the transaction is still in pool or has been added to a block. + pub in_pool: bool, + /// Amount of the transaction. + #[serde(with = "amount::serde::as_pico")] + pub received: Amount, +} + #[cfg(test)] mod tests { use super::*; diff --git a/tests/clients_tests/all_clients_interaction.rs b/tests/clients_tests/all_clients_interaction.rs index 693961b..b7962df 100644 --- a/tests/clients_tests/all_clients_interaction.rs +++ b/tests/clients_tests/all_clients_interaction.rs @@ -447,7 +447,10 @@ pub async fn run() { subaddr_index: Index { major: 0, minor: 0 }, suggested_confirmations_threshold: 1, // this is any date, since it will not be tested against anything - timestamp: DateTime::::from_utc(NaiveDateTime::from_timestamp_opt(0, 0).unwrap(), Utc), + timestamp: DateTime::from_naive_utc_and_offset( + NaiveDateTime::from_timestamp_opt(0, 0).unwrap(), + Utc, + ), txid: HashString(transfer_1_data.tx_hash.0.as_ref().to_vec()), transfer_type: GetTransfersCategory::Pending, unlock_time: 0, @@ -874,4 +877,40 @@ pub async fn run() { }, ) .await; + + // Create tx proof and check tx proof test + //---------------------------------------------------------------------------------------// + let selector_data: HashMap = HashMap::from([ + (GetTransfersCategory::In, true), + (GetTransfersCategory::Out, true), + (GetTransfersCategory::Pending, false), + (GetTransfersCategory::Failed, false), + (GetTransfersCategory::Pool, false), + (GetTransfersCategory::Block, false), + ]); + let selector = GetTransfersSelector { + category_selector: selector_data, + account_index: None, + subaddr_indices: None, + block_height_filter: None, + }; + let res = wallet.get_transfers(selector).await; + assert!(res.is_ok()); + let res = res.unwrap(); + let transfers = res.get(&GetTransfersCategory::Out); + if transfers.is_some() { + let transfers = transfers.unwrap(); + let transfer = transfers[0].clone(); + + helpers::wallet::create_check_tx_proof_assert_ok( + &wallet, + transfer.txid, + transfer.address, + Some(String::from("Test")), + ) + .await; + } else { + panic!("No Transfers to Test for"); + } + //---------------------------------------------------------------------------------------// } diff --git a/tests/clients_tests/empty_blockchain.rs b/tests/clients_tests/empty_blockchain.rs index bef8812..7afdc54 100644 --- a/tests/clients_tests/empty_blockchain.rs +++ b/tests/clients_tests/empty_blockchain.rs @@ -62,7 +62,10 @@ pub async fn run() { // this **is** used inside the test functions, since this block header corresponds // to the genesis block; // note that in the `non_empty_blockchain`, this field is **not** tested. - timestamp: DateTime::::from_utc(NaiveDateTime::from_timestamp_opt(0, 0).unwrap(), Utc), + timestamp: DateTime::from_naive_utc_and_offset( + NaiveDateTime::from_timestamp_opt(0, 0).unwrap(), + Utc, + ), }; helpers::regtest::get_last_block_header_assert_block_header( diff --git a/tests/clients_tests/helpers/regtest.rs b/tests/clients_tests/helpers/regtest.rs index 69a89b9..0d72656 100644 --- a/tests/clients_tests/helpers/regtest.rs +++ b/tests/clients_tests/helpers/regtest.rs @@ -244,7 +244,7 @@ fn test_get_block_header_assert_block_header( .unwrap() .and_hms_opt(0, 0, 0) .unwrap(); - let start_2022_date = DateTime::::from_utc(start_2022_date, Utc); + let start_2022_date = DateTime::::from_naive_utc_and_offset(start_2022_date, Utc); assert!(block_header.timestamp >= start_2022_date); } diff --git a/tests/clients_tests/helpers/wallet.rs b/tests/clients_tests/helpers/wallet.rs index 95b139e..024d8d6 100644 --- a/tests/clients_tests/helpers/wallet.rs +++ b/tests/clients_tests/helpers/wallet.rs @@ -6,8 +6,8 @@ use monero::{ }; use monero_rpc::{ AddressData, BalanceData, GenerateFromKeysArgs, GetAccountsData, GetTransfersCategory, - GetTransfersSelector, GotTransfer, IncomingTransfers, KeyImageImportResponse, Payment, - PrivateKeyType, SignedKeyImage, SignedTransferOutput, SweepAllArgs, TransferData, + GetTransfersSelector, GotTransfer, HashString, IncomingTransfers, KeyImageImportResponse, + Payment, PrivateKeyType, SignedKeyImage, SignedTransferOutput, SweepAllArgs, TransferData, TransferOptions, TransferPriority, TransferType, WalletClient, WalletCreation, }; @@ -761,3 +761,23 @@ pub async fn create_account_assert_ok(wallet: &WalletClient, label: Option= 1); } + +pub async fn create_check_tx_proof_assert_ok( + wallet: &WalletClient, + txid: HashString>, + address: Address, + message: Option, +) { + let proof_res = wallet + .get_tx_proof(txid.clone(), address, message.clone()) + .await; + + assert!(proof_res.is_ok()); + + let check_res = wallet + .check_tx_proof(txid, address, message, proof_res.unwrap()) + .await; + + assert!(check_res.is_ok()); + assert!(check_res.unwrap().good); +} diff --git a/tests/clients_tests/non_empty_blockchain.rs b/tests/clients_tests/non_empty_blockchain.rs index 60f2d61..3f4d606 100644 --- a/tests/clients_tests/non_empty_blockchain.rs +++ b/tests/clients_tests/non_empty_blockchain.rs @@ -76,7 +76,10 @@ pub async fn run() { reward: Amount::from_pico(35180379334199), // this is not used inside the test functions below, since its value depend on when the // test was run, so use any date in this field since it is insignificant for testing. - timestamp: DateTime::::from_utc(NaiveDateTime::from_timestamp_opt(0, 0).unwrap(), Utc), + timestamp: DateTime::from_naive_utc_and_offset( + NaiveDateTime::from_timestamp_opt(0, 0).unwrap(), + Utc, + ), }; helpers::regtest::get_last_block_header_assert_block_header( ®test,