From 7a4f08db323986a3f03152a52f63dbec6b7df658 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Thu, 9 Jan 2025 18:52:39 +0000 Subject: [PATCH 01/17] add transation_hex to create_deposit --- emily/handler/src/api/handlers/deposit.rs | 27 +- .../src/api/models/deposit/requests.rs | 231 ++++++++++++++++++ ...create-deposit-invalid-deposit-script.json | 7 + .../create-deposit-invalid-output-index.json | 7 + ...create-deposit-invalid-reclaim-script.json | 7 + ...reate-deposit-invalid-transaction-hex.json | 7 + .../fixtures/create-deposit-invalid-txid.json | 7 + ...reate-deposit-mismatch-deposit-script.json | 7 + ...reate-deposit-mismatch-reclaim-script.json | 7 + .../create-deposit-mismatch-txid.json | 7 + .../fixtures/create-deposit-valid-2.json | 7 + .../tests/fixtures/create-deposit-valid.json | 7 + 12 files changed, 320 insertions(+), 8 deletions(-) create mode 100644 emily/handler/tests/fixtures/create-deposit-invalid-deposit-script.json create mode 100644 emily/handler/tests/fixtures/create-deposit-invalid-output-index.json create mode 100644 emily/handler/tests/fixtures/create-deposit-invalid-reclaim-script.json create mode 100644 emily/handler/tests/fixtures/create-deposit-invalid-transaction-hex.json create mode 100644 emily/handler/tests/fixtures/create-deposit-invalid-txid.json create mode 100644 emily/handler/tests/fixtures/create-deposit-mismatch-deposit-script.json create mode 100644 emily/handler/tests/fixtures/create-deposit-mismatch-reclaim-script.json create mode 100644 emily/handler/tests/fixtures/create-deposit-mismatch-txid.json create mode 100644 emily/handler/tests/fixtures/create-deposit-valid-2.json create mode 100644 emily/handler/tests/fixtures/create-deposit-valid.json diff --git a/emily/handler/src/api/handlers/deposit.rs b/emily/handler/src/api/handlers/deposit.rs index c1cceb0cc..fe7442402 100644 --- a/emily/handler/src/api/handlers/deposit.rs +++ b/emily/handler/src/api/handlers/deposit.rs @@ -207,7 +207,10 @@ pub async fn create_deposit( context: EmilyContext, body: CreateDepositRequestBody, ) -> impl warp::reply::Reply { - debug!("In create deposit"); + debug!( + "Creating deposit with txid: {}, output index: {}", + body.bitcoin_txid, body.bitcoin_tx_output_index + ); // Internal handler so `?` can be used correctly while still returning a reply. async fn handler( context: EmilyContext, @@ -245,11 +248,19 @@ pub async fn create_deposit( Err(e) => return Err(e), } - let status = Status::Pending; + let tx = (&body).try_into()?; + let limits = accessors::get_limits(&context).await?; + body.validate(&tx, &limits)?; // Get parameters from scripts. - let script_parameters = - scripts_to_resource_parameters(&body.deposit_script, &body.reclaim_script)?; + let script_parameters = scripts_to_resource_parameters( + &body.deposit_script, + &body.reclaim_script, + tx.tx_out(body.bitcoin_tx_output_index as usize) + .unwrap() // Safe to unwrap. We have already validated the output index in the try_into. + .value + .to_sat(), + )?; // Make table entry. let deposit_entry: DepositEntry = DepositEntry { @@ -268,7 +279,7 @@ pub async fn create_deposit( stacks_block_hash: stacks_block_hash.clone(), stacks_block_height, }], - status, + status: Status::Pending, last_update_block_hash: stacks_block_hash, last_update_height: stacks_block_height, amount: script_parameters.amount, @@ -305,6 +316,7 @@ struct ScriptParameters { fn scripts_to_resource_parameters( deposit_script: &str, reclaim_script: &str, + amount: u64, ) -> Result { let deposit_script_buf = ScriptBuf::from_hex(deposit_script)?; let deposit_script_inputs = sbtc::deposits::DepositScriptInputs::parse(&deposit_script_buf)?; @@ -316,8 +328,7 @@ fn scripts_to_resource_parameters( let recipient_hex_string = hex::encode(&recipient_bytes); Ok(ScriptParameters { - // TODO(TBD): Get the amount from some script related data somehow. - amount: 0, + amount, max_fee: deposit_script_inputs.max_fee, recipient: recipient_hex_string, lock_time: reclaim_script_inputs.lock_time(), @@ -422,7 +433,7 @@ mod tests { let reclaim_script = setup.reclaim.reclaim_script().to_hex_string(); let script_parameters: ScriptParameters = - scripts_to_resource_parameters(&deposit_script, &reclaim_script).unwrap(); + scripts_to_resource_parameters(&deposit_script, &reclaim_script, amount_sats).unwrap(); assert_eq!(script_parameters.max_fee, max_fee); assert_eq!(script_parameters.lock_time, lock_time); diff --git a/emily/handler/src/api/models/deposit/requests.rs b/emily/handler/src/api/models/deposit/requests.rs index 676252b5e..812f7a009 100644 --- a/emily/handler/src/api/models/deposit/requests.rs +++ b/emily/handler/src/api/models/deposit/requests.rs @@ -1,9 +1,19 @@ //! Request structures for deposit api calls. +use std::str::FromStr; + +use bitcoin::blockdata::transaction::Transaction; +use bitcoin::consensus::encode; +use bitcoin::{Amount, OutPoint, ScriptBuf, Txid}; +use reqwest::StatusCode; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; +use sbtc::deposits::CreateDepositRequest; + use crate::api::models::common::{Fulfillment, Status}; +use crate::api::models::limits::Limits; +use crate::common::error::Error; /// Query structure for the GetDepositsQuery struct. #[derive(Clone, Default, Debug, PartialEq, Hash, Serialize, Deserialize, ToSchema)] @@ -43,8 +53,89 @@ pub struct CreateDepositRequestBody { pub reclaim_script: String, /// Deposit script. pub deposit_script: String, + /// The raw transaction hex. + pub transaction_hex: String, +} + +/// This is the dust limit for deposits in the sBTC smart contracts. +/// Deposit amounts that is less than this amount will be rejected by the +/// smart contract. +pub const DEPOSIT_DUST_LIMIT: u64 = 546; + +fn parse_hex(input: &str, error_msg: &str, parser: F) -> Result +where + F: Fn(&str) -> Result, +{ + parser(input).map_err(|_| Error::HttpRequest(StatusCode::BAD_REQUEST, error_msg.to_string())) +} + +impl CreateDepositRequestBody { + /// Validates that the deposit request is valid. + /// This includes validating the request fields, if their content matches the transaction + /// and if the amount is within the limits. + pub fn validate(&self, tx: &Transaction, limits: &Limits) -> Result<(), Error> { + let deposit_req = CreateDepositRequest { + outpoint: OutPoint { + txid: parse_hex(&self.bitcoin_txid, "invalid bitcoin_txid", Txid::from_str)?, + vout: self.bitcoin_tx_output_index, + }, + reclaim_script: parse_hex( + &self.reclaim_script, + "invalid reclaim_script", + ScriptBuf::from_hex, + )?, + deposit_script: parse_hex( + &self.deposit_script, + "invalid deposit_script", + ScriptBuf::from_hex, + )?, + }; + + let amount = tx + .tx_out(self.bitcoin_tx_output_index as usize) + .map_err(|_| { + Error::HttpRequest( + StatusCode::BAD_REQUEST, + "invalid bitcoin_output_index".to_string(), + ) + })? + .value + .to_sat(); + deposit_req + .validate_tx(tx) + .map_err(|e| Error::HttpRequest(StatusCode::BAD_REQUEST, e.to_string()))?; + + // Even if no limits are set, the deposit amount should be higher than the dust limit. + let min = limits.per_deposit_minimum.unwrap_or(DEPOSIT_DUST_LIMIT); + if amount < min { + return Err(Error::HttpRequest( + StatusCode::BAD_REQUEST, + format!("deposit amount below minimum ({})", min), + )); + } + + let cap = limits.per_deposit_cap.unwrap_or(Amount::MAX_MONEY.to_sat()); + if amount > cap { + return Err(Error::HttpRequest( + StatusCode::BAD_REQUEST, + format!("deposit amount exceeds cap ({})", cap), + )); + } + Ok(()) + } } +impl TryInto for &CreateDepositRequestBody { + type Error = Error; + + fn try_into(self) -> Result { + parse_hex( + &self.transaction_hex, + "invalid transaction_hex", + encode::deserialize_hex, + ) + } +} /// A singlular Deposit update that contains only the fields pertinent /// to updating the status of a deposit. This includes the key related /// data in addition to status history related data. @@ -79,3 +170,143 @@ pub struct UpdateDepositsRequestBody { /// Bitcoin transaction id. pub deposits: Vec, } + +#[cfg(test)] +mod tests { + use super::*; + use test_case::test_case; + + const CREATE_DEPOSIT_VALID: &str = + include_str!("../../../../tests/fixtures/create-deposit-valid.json"); + + const CREATE_DEPOSIT_INVALID_TXID: &str = + include_str!("../../../../tests/fixtures/create-deposit-invalid-txid.json"); + + const CREATE_DEPOSIT_INVALID_OUTPUT_INDEX: &str = + include_str!("../../../../tests/fixtures/create-deposit-invalid-output-index.json"); + + const CREATE_DEPOSIT_INVALID_RECLAIM_SCRIPT: &str = + include_str!("../../../../tests/fixtures/create-deposit-invalid-reclaim-script.json"); + + const CREATE_DEPOSIT_INVALID_DEPOSIT_SCRIPT: &str = + include_str!("../../../../tests/fixtures/create-deposit-invalid-deposit-script.json"); + + const CREATE_DEPOSIT_INVALID_TRANSACTION_HEX: &str = + include_str!("../../../../tests/fixtures/create-deposit-invalid-transaction-hex.json"); + + const CREATE_DEPOSIT_MISMATCH_TXID: &str = + include_str!("../../../../tests/fixtures/create-deposit-mismatch-txid.json"); + + const CREATE_DEPOSIT_MISMATCH_RECLAIM_SCRIPT: &str = + include_str!("../../../../tests/fixtures/create-deposit-mismatch-reclaim-script.json"); + + const CREATE_DEPOSIT_MISMATCH_DEPOSIT_SCRIPT: &str = + include_str!("../../../../tests/fixtures/create-deposit-mismatch-deposit-script.json"); + + mod helpers { + use super::*; + + pub fn create_test_limits(min: Option, max: Option) -> Limits { + Limits { + per_deposit_minimum: min, + per_deposit_cap: max, + ..Default::default() + } + } + + pub fn parse_request(json: &str) -> CreateDepositRequestBody { + serde_json::from_str(json).expect("failed to parse request") + } + + pub fn parse_transaction(request: &CreateDepositRequestBody) -> Transaction { + request.try_into().expect("failed to parse transaction") + } + } + + #[tokio::test] + async fn test_transaction_deserialization_valid() { + let deposit_request = helpers::parse_request(CREATE_DEPOSIT_VALID); + let result: Result = (&deposit_request).try_into(); + assert!(result.is_ok()); + } + + #[tokio::test] + async fn test_transaction_deserialization_invalid() { + let deposit_request = helpers::parse_request(CREATE_DEPOSIT_INVALID_TRANSACTION_HEX); + let result: Result = (&deposit_request).try_into(); + assert_eq!( + result.unwrap_err().to_string(), + "HTTP request failed with status code 400 Bad Request: invalid transaction_hex" + .to_string() + ); + } + + #[tokio::test] + async fn test_deposit_validate_happy_path() { + let deposit_request = helpers::parse_request(CREATE_DEPOSIT_VALID); + let tx = helpers::parse_transaction(&deposit_request); + let limits = helpers::create_test_limits(None, None); + assert!(deposit_request.validate(&tx, &limits).is_ok()); + } + + #[test_case(CREATE_DEPOSIT_INVALID_TXID, "invalid bitcoin_txid"; "invalid_txid")] + #[test_case(CREATE_DEPOSIT_INVALID_RECLAIM_SCRIPT, "invalid reclaim_script"; "invalid_reclaim_script")] + #[test_case(CREATE_DEPOSIT_INVALID_DEPOSIT_SCRIPT, "invalid deposit_script"; "invalid_deposit_script")] + #[test_case(CREATE_DEPOSIT_INVALID_OUTPUT_INDEX, "invalid bitcoin_output_index"; "invalid_output_index")] + #[test_case(CREATE_DEPOSIT_MISMATCH_TXID, "The txid of the transaction did not match the given txid"; "mismatch_txid")] + #[test_case( + CREATE_DEPOSIT_MISMATCH_RECLAIM_SCRIPT, + "mismatch in expected and actual ScriptPubKeys. outpoint: f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de:0"; + "mismatch_reclaim_script")] + #[test_case( + CREATE_DEPOSIT_MISMATCH_DEPOSIT_SCRIPT, + "mismatch in expected and actual ScriptPubKeys. outpoint: f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de:0"; + "mismatch_deposit_script")] + #[tokio::test] + async fn test_deposit_validate_errors(input: &str, expected_error: &str) { + let deposit_request = helpers::parse_request(input); + let tx = helpers::parse_transaction(&deposit_request); + let limits = helpers::create_test_limits(Some(DEPOSIT_DUST_LIMIT), None); + + let result = deposit_request.validate(&tx, &limits); + assert_eq!( + result.unwrap_err().to_string(), + format!("HTTP request failed with status code 400 Bad Request: {expected_error}") + ); + } + + // CREATE_DEPOSIT_VALID has a deposit amount of 1_000_000 satoshis. + #[test_case(CREATE_DEPOSIT_VALID, None, None; "no_limits")] + #[test_case(CREATE_DEPOSIT_VALID, Some(DEPOSIT_DUST_LIMIT), None; "min_limit")] + #[test_case(CREATE_DEPOSIT_VALID, None, Some(1_000_000_000); "max_limit")] + #[test_case(CREATE_DEPOSIT_VALID, Some(DEPOSIT_DUST_LIMIT), Some(1_000_000_000); "min_max_limit")] + #[tokio::test] + async fn test_deposit_validate_limits(input: &str, min: Option, max: Option) { + let deposit_request = helpers::parse_request(input); + let tx = helpers::parse_transaction(&deposit_request); + let limits = helpers::create_test_limits(min, max); + assert!(deposit_request.validate(&tx, &limits).is_ok()); + } + + #[test_case(CREATE_DEPOSIT_VALID, Some(1_000_000 + 1), None, "deposit amount below minimum (1000001)"; "below_min_limit")] + #[test_case(CREATE_DEPOSIT_VALID, None, Some(999_999), "deposit amount exceeds cap (999999)"; "above_max_limit")] + #[tokio::test] + async fn test_deposit_validate_limits_errors( + input: &str, + min: Option, + max: Option, + expected_error: &str, + ) { + let deposit_request = helpers::parse_request(input); + let tx = helpers::parse_transaction(&deposit_request); + let limits = helpers::create_test_limits(min, max); + + let result = deposit_request.validate(&tx, &limits); + + assert!(result.is_err()); + assert_eq!( + result.unwrap_err().to_string(), + format!("HTTP request failed with status code 400 Bad Request: {expected_error}") + ); + } +} diff --git a/emily/handler/tests/fixtures/create-deposit-invalid-deposit-script.json b/emily/handler/tests/fixtures/create-deposit-invalid-deposit-script.json new file mode 100644 index 000000000..5cadc6899 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-invalid-deposit-script.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "5cb275204384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54ac", + "depositScript": "abcdefg", + "transactionHex": "0200000000010989d51408bf1f885b50572654a2dd24c4bfd1a14d7c9b4f74de81ba1c616d4ea90000000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4f1654c4e614e915739b566ba6511a2e1610971b6ee239e4158e098a62320d690400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffc9ca41ed0e42e2b0e9897f159bdd20fb79341f3c3fdde0e83366e7bae45bf269e500000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff2f425f864d2dbaf31ba2f2b02658adbe5edab36aedc1fbd7d42a8d6681065ebdc400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff447410db5da41ec044732836cd1aaa37539ea262e095aa75675b9d961d7711778702000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4cbf9c604ddbdca9b9873167594f3da33b661d6c15757040f58e6a45446e821e5b01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffe305cb725943876e71c110c62ede7ad1a849eeadb29ece74ec9cfcd43527b64b3601000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff6182df4003982e0149a73ca1be71caf0f5a07a7f17b0a69884ca2e899d257a5e7100000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff7618f1e75775768841720503103aee291762cf06ed2d2d7e18419f9699307915ff01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff0240420f0000000000225120d58d5d38bb5a2813cecfeced939b190048527a2b249dbaf09c302bb636af0f1ebb6a00000000000017a91484c51a49c1a5591ffbd536dce0025c6fcacc46e087024730440220226a7cdecf9dab5d88f57dfb45e5e45e8b24e938c22e414b8c90ac64eea9d4410220534443a01bf0627911bfc92b35639657d30f4c963c60bacba09770b07b6a3c8d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210090c23fd06d5552f527547a2c17ae1decd7c58a8f7363fd59f2671bfb235d40960220567fd8c1af0eaa5c89dbfb80d3e6fbfbb493a4429fb28c54ca171e076e0baba30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54024730440220418fb80a6dae469a2ebc96fdcb0ff82c808545876d390afa66c726d80a3d070502204401e631625f8d83a6a7d0ccc5e2319240f75769a9a1835687d0d8eb62bdf5430121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5402483045022100f2cc528c7733daa602a970e40021f96cef87bc662f9f31621b32cf8ef51dce5402201260482c3a550ef20ed87bfd61299906d5e440e4feb78e8568381a536cfebb2e0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206185ddb641cd9d8d0e126724c91c522954ae775b90b74214651dc16a674b3022022016df2b9455b4518a7b85239e62440f40d81a59080e61b5cd00385de58facf0d30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402203c38a66e6f9f6d67f088b83ce33d0cc00e6d0068d5922e461356ccb23125f01e02204382f4d16842f633ceadf0a7dab70ae9d5691661dbe6ac7c09fc9ea7ab74249d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206ad85249b3d4c6ee1bb895697debd4fac89df6b15d4e93c16454852bbe3ffaf0022074ffd1a716c1b6b191bc3825f8061b27d7b63367c90e3b6633962b978099c3bd0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210094c0adcef4f4eb1e120f3235979a0caec457f0e5525185ef76d54ae668302d45022076b8e07f7968c1cf91d369dd6d92e951fe7b0ff1d3157dd0bbeaa682f2d820b00121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402205127cc30ed7ac63634d7290deda839d414b2f6d659ab4f1643b38bdcd289da6e022003d7bace557b438f0c9947b33765b662286aa6e7245863d0e16ec5e1a38d40de0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5400000000" +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-invalid-output-index.json b/emily/handler/tests/fixtures/create-deposit-invalid-output-index.json new file mode 100644 index 000000000..f91bbb192 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-invalid-output-index.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de", + "bitcoinTxOutputIndex": 10, + "reclaimScript": "5cb275204384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54ac", + "depositScript": "1e000000000001388005160bf8a0a80e3a205534977e0d9e00bcd8b9c1b3a17520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", + "transactionHex": "0200000000010989d51408bf1f885b50572654a2dd24c4bfd1a14d7c9b4f74de81ba1c616d4ea90000000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4f1654c4e614e915739b566ba6511a2e1610971b6ee239e4158e098a62320d690400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffc9ca41ed0e42e2b0e9897f159bdd20fb79341f3c3fdde0e83366e7bae45bf269e500000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff2f425f864d2dbaf31ba2f2b02658adbe5edab36aedc1fbd7d42a8d6681065ebdc400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff447410db5da41ec044732836cd1aaa37539ea262e095aa75675b9d961d7711778702000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4cbf9c604ddbdca9b9873167594f3da33b661d6c15757040f58e6a45446e821e5b01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffe305cb725943876e71c110c62ede7ad1a849eeadb29ece74ec9cfcd43527b64b3601000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff6182df4003982e0149a73ca1be71caf0f5a07a7f17b0a69884ca2e899d257a5e7100000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff7618f1e75775768841720503103aee291762cf06ed2d2d7e18419f9699307915ff01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff0240420f0000000000225120d58d5d38bb5a2813cecfeced939b190048527a2b249dbaf09c302bb636af0f1ebb6a00000000000017a91484c51a49c1a5591ffbd536dce0025c6fcacc46e087024730440220226a7cdecf9dab5d88f57dfb45e5e45e8b24e938c22e414b8c90ac64eea9d4410220534443a01bf0627911bfc92b35639657d30f4c963c60bacba09770b07b6a3c8d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210090c23fd06d5552f527547a2c17ae1decd7c58a8f7363fd59f2671bfb235d40960220567fd8c1af0eaa5c89dbfb80d3e6fbfbb493a4429fb28c54ca171e076e0baba30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54024730440220418fb80a6dae469a2ebc96fdcb0ff82c808545876d390afa66c726d80a3d070502204401e631625f8d83a6a7d0ccc5e2319240f75769a9a1835687d0d8eb62bdf5430121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5402483045022100f2cc528c7733daa602a970e40021f96cef87bc662f9f31621b32cf8ef51dce5402201260482c3a550ef20ed87bfd61299906d5e440e4feb78e8568381a536cfebb2e0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206185ddb641cd9d8d0e126724c91c522954ae775b90b74214651dc16a674b3022022016df2b9455b4518a7b85239e62440f40d81a59080e61b5cd00385de58facf0d30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402203c38a66e6f9f6d67f088b83ce33d0cc00e6d0068d5922e461356ccb23125f01e02204382f4d16842f633ceadf0a7dab70ae9d5691661dbe6ac7c09fc9ea7ab74249d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206ad85249b3d4c6ee1bb895697debd4fac89df6b15d4e93c16454852bbe3ffaf0022074ffd1a716c1b6b191bc3825f8061b27d7b63367c90e3b6633962b978099c3bd0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210094c0adcef4f4eb1e120f3235979a0caec457f0e5525185ef76d54ae668302d45022076b8e07f7968c1cf91d369dd6d92e951fe7b0ff1d3157dd0bbeaa682f2d820b00121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402205127cc30ed7ac63634d7290deda839d414b2f6d659ab4f1643b38bdcd289da6e022003d7bace557b438f0c9947b33765b662286aa6e7245863d0e16ec5e1a38d40de0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5400000000" +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-invalid-reclaim-script.json b/emily/handler/tests/fixtures/create-deposit-invalid-reclaim-script.json new file mode 100644 index 000000000..78e7fad95 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-invalid-reclaim-script.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "abcdefg", + "depositScript": "1e000000000001388005160bf8a0a80e3a205534977e0d9e00bcd8b9c1b3a17520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", + "transactionHex": "0200000000010989d51408bf1f885b50572654a2dd24c4bfd1a14d7c9b4f74de81ba1c616d4ea90000000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4f1654c4e614e915739b566ba6511a2e1610971b6ee239e4158e098a62320d690400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffc9ca41ed0e42e2b0e9897f159bdd20fb79341f3c3fdde0e83366e7bae45bf269e500000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff2f425f864d2dbaf31ba2f2b02658adbe5edab36aedc1fbd7d42a8d6681065ebdc400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff447410db5da41ec044732836cd1aaa37539ea262e095aa75675b9d961d7711778702000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4cbf9c604ddbdca9b9873167594f3da33b661d6c15757040f58e6a45446e821e5b01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffe305cb725943876e71c110c62ede7ad1a849eeadb29ece74ec9cfcd43527b64b3601000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff6182df4003982e0149a73ca1be71caf0f5a07a7f17b0a69884ca2e899d257a5e7100000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff7618f1e75775768841720503103aee291762cf06ed2d2d7e18419f9699307915ff01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff0240420f0000000000225120d58d5d38bb5a2813cecfeced939b190048527a2b249dbaf09c302bb636af0f1ebb6a00000000000017a91484c51a49c1a5591ffbd536dce0025c6fcacc46e087024730440220226a7cdecf9dab5d88f57dfb45e5e45e8b24e938c22e414b8c90ac64eea9d4410220534443a01bf0627911bfc92b35639657d30f4c963c60bacba09770b07b6a3c8d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210090c23fd06d5552f527547a2c17ae1decd7c58a8f7363fd59f2671bfb235d40960220567fd8c1af0eaa5c89dbfb80d3e6fbfbb493a4429fb28c54ca171e076e0baba30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54024730440220418fb80a6dae469a2ebc96fdcb0ff82c808545876d390afa66c726d80a3d070502204401e631625f8d83a6a7d0ccc5e2319240f75769a9a1835687d0d8eb62bdf5430121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5402483045022100f2cc528c7733daa602a970e40021f96cef87bc662f9f31621b32cf8ef51dce5402201260482c3a550ef20ed87bfd61299906d5e440e4feb78e8568381a536cfebb2e0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206185ddb641cd9d8d0e126724c91c522954ae775b90b74214651dc16a674b3022022016df2b9455b4518a7b85239e62440f40d81a59080e61b5cd00385de58facf0d30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402203c38a66e6f9f6d67f088b83ce33d0cc00e6d0068d5922e461356ccb23125f01e02204382f4d16842f633ceadf0a7dab70ae9d5691661dbe6ac7c09fc9ea7ab74249d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206ad85249b3d4c6ee1bb895697debd4fac89df6b15d4e93c16454852bbe3ffaf0022074ffd1a716c1b6b191bc3825f8061b27d7b63367c90e3b6633962b978099c3bd0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210094c0adcef4f4eb1e120f3235979a0caec457f0e5525185ef76d54ae668302d45022076b8e07f7968c1cf91d369dd6d92e951fe7b0ff1d3157dd0bbeaa682f2d820b00121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402205127cc30ed7ac63634d7290deda839d414b2f6d659ab4f1643b38bdcd289da6e022003d7bace557b438f0c9947b33765b662286aa6e7245863d0e16ec5e1a38d40de0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5400000000" +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-invalid-transaction-hex.json b/emily/handler/tests/fixtures/create-deposit-invalid-transaction-hex.json new file mode 100644 index 000000000..0bb609007 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-invalid-transaction-hex.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "5cb275204384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54ac", + "depositScript": "1e000000000001388005160bf8a0a80e3a205534977e0d9e00bcd8b9c1b3a17520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", + "transactionHex": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-invalid-txid.json b/emily/handler/tests/fixtures/create-deposit-invalid-txid.json new file mode 100644 index 000000000..537b55863 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-invalid-txid.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "abcde1234", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "5cb275204384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54ac", + "depositScript": "1e000000000001388005160bf8a0a80e3a205534977e0d9e00bcd8b9c1b3a17520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", + "transactionHex": "0200000000010989d51408bf1f885b50572654a2dd24c4bfd1a14d7c9b4f74de81ba1c616d4ea90000000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4f1654c4e614e915739b566ba6511a2e1610971b6ee239e4158e098a62320d690400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffc9ca41ed0e42e2b0e9897f159bdd20fb79341f3c3fdde0e83366e7bae45bf269e500000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff2f425f864d2dbaf31ba2f2b02658adbe5edab36aedc1fbd7d42a8d6681065ebdc400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff447410db5da41ec044732836cd1aaa37539ea262e095aa75675b9d961d7711778702000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4cbf9c604ddbdca9b9873167594f3da33b661d6c15757040f58e6a45446e821e5b01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffe305cb725943876e71c110c62ede7ad1a849eeadb29ece74ec9cfcd43527b64b3601000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff6182df4003982e0149a73ca1be71caf0f5a07a7f17b0a69884ca2e899d257a5e7100000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff7618f1e75775768841720503103aee291762cf06ed2d2d7e18419f9699307915ff01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff0240420f0000000000225120d58d5d38bb5a2813cecfeced939b190048527a2b249dbaf09c302bb636af0f1ebb6a00000000000017a91484c51a49c1a5591ffbd536dce0025c6fcacc46e087024730440220226a7cdecf9dab5d88f57dfb45e5e45e8b24e938c22e414b8c90ac64eea9d4410220534443a01bf0627911bfc92b35639657d30f4c963c60bacba09770b07b6a3c8d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210090c23fd06d5552f527547a2c17ae1decd7c58a8f7363fd59f2671bfb235d40960220567fd8c1af0eaa5c89dbfb80d3e6fbfbb493a4429fb28c54ca171e076e0baba30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54024730440220418fb80a6dae469a2ebc96fdcb0ff82c808545876d390afa66c726d80a3d070502204401e631625f8d83a6a7d0ccc5e2319240f75769a9a1835687d0d8eb62bdf5430121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5402483045022100f2cc528c7733daa602a970e40021f96cef87bc662f9f31621b32cf8ef51dce5402201260482c3a550ef20ed87bfd61299906d5e440e4feb78e8568381a536cfebb2e0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206185ddb641cd9d8d0e126724c91c522954ae775b90b74214651dc16a674b3022022016df2b9455b4518a7b85239e62440f40d81a59080e61b5cd00385de58facf0d30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402203c38a66e6f9f6d67f088b83ce33d0cc00e6d0068d5922e461356ccb23125f01e02204382f4d16842f633ceadf0a7dab70ae9d5691661dbe6ac7c09fc9ea7ab74249d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206ad85249b3d4c6ee1bb895697debd4fac89df6b15d4e93c16454852bbe3ffaf0022074ffd1a716c1b6b191bc3825f8061b27d7b63367c90e3b6633962b978099c3bd0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210094c0adcef4f4eb1e120f3235979a0caec457f0e5525185ef76d54ae668302d45022076b8e07f7968c1cf91d369dd6d92e951fe7b0ff1d3157dd0bbeaa682f2d820b00121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402205127cc30ed7ac63634d7290deda839d414b2f6d659ab4f1643b38bdcd289da6e022003d7bace557b438f0c9947b33765b662286aa6e7245863d0e16ec5e1a38d40de0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5400000000" +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-mismatch-deposit-script.json b/emily/handler/tests/fixtures/create-deposit-mismatch-deposit-script.json new file mode 100644 index 000000000..8b9f2a234 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-mismatch-deposit-script.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "5cb27520d48165cbd6639da14ff7e3c75a3d62d282552285180db996ac5a9c39f7ac85ccac", + "depositScript": "1e000000000001388005160bf8a0a80e3a205534977e0d9e00bcd8b9c1b3a17520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", + "transactionHex": "0200000000010989d51408bf1f885b50572654a2dd24c4bfd1a14d7c9b4f74de81ba1c616d4ea90000000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4f1654c4e614e915739b566ba6511a2e1610971b6ee239e4158e098a62320d690400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffc9ca41ed0e42e2b0e9897f159bdd20fb79341f3c3fdde0e83366e7bae45bf269e500000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff2f425f864d2dbaf31ba2f2b02658adbe5edab36aedc1fbd7d42a8d6681065ebdc400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff447410db5da41ec044732836cd1aaa37539ea262e095aa75675b9d961d7711778702000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4cbf9c604ddbdca9b9873167594f3da33b661d6c15757040f58e6a45446e821e5b01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffe305cb725943876e71c110c62ede7ad1a849eeadb29ece74ec9cfcd43527b64b3601000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff6182df4003982e0149a73ca1be71caf0f5a07a7f17b0a69884ca2e899d257a5e7100000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff7618f1e75775768841720503103aee291762cf06ed2d2d7e18419f9699307915ff01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff0240420f0000000000225120d58d5d38bb5a2813cecfeced939b190048527a2b249dbaf09c302bb636af0f1ebb6a00000000000017a91484c51a49c1a5591ffbd536dce0025c6fcacc46e087024730440220226a7cdecf9dab5d88f57dfb45e5e45e8b24e938c22e414b8c90ac64eea9d4410220534443a01bf0627911bfc92b35639657d30f4c963c60bacba09770b07b6a3c8d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210090c23fd06d5552f527547a2c17ae1decd7c58a8f7363fd59f2671bfb235d40960220567fd8c1af0eaa5c89dbfb80d3e6fbfbb493a4429fb28c54ca171e076e0baba30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54024730440220418fb80a6dae469a2ebc96fdcb0ff82c808545876d390afa66c726d80a3d070502204401e631625f8d83a6a7d0ccc5e2319240f75769a9a1835687d0d8eb62bdf5430121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5402483045022100f2cc528c7733daa602a970e40021f96cef87bc662f9f31621b32cf8ef51dce5402201260482c3a550ef20ed87bfd61299906d5e440e4feb78e8568381a536cfebb2e0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206185ddb641cd9d8d0e126724c91c522954ae775b90b74214651dc16a674b3022022016df2b9455b4518a7b85239e62440f40d81a59080e61b5cd00385de58facf0d30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402203c38a66e6f9f6d67f088b83ce33d0cc00e6d0068d5922e461356ccb23125f01e02204382f4d16842f633ceadf0a7dab70ae9d5691661dbe6ac7c09fc9ea7ab74249d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206ad85249b3d4c6ee1bb895697debd4fac89df6b15d4e93c16454852bbe3ffaf0022074ffd1a716c1b6b191bc3825f8061b27d7b63367c90e3b6633962b978099c3bd0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210094c0adcef4f4eb1e120f3235979a0caec457f0e5525185ef76d54ae668302d45022076b8e07f7968c1cf91d369dd6d92e951fe7b0ff1d3157dd0bbeaa682f2d820b00121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402205127cc30ed7ac63634d7290deda839d414b2f6d659ab4f1643b38bdcd289da6e022003d7bace557b438f0c9947b33765b662286aa6e7245863d0e16ec5e1a38d40de0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5400000000" +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-mismatch-reclaim-script.json b/emily/handler/tests/fixtures/create-deposit-mismatch-reclaim-script.json new file mode 100644 index 000000000..8b9f2a234 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-mismatch-reclaim-script.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "5cb27520d48165cbd6639da14ff7e3c75a3d62d282552285180db996ac5a9c39f7ac85ccac", + "depositScript": "1e000000000001388005160bf8a0a80e3a205534977e0d9e00bcd8b9c1b3a17520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", + "transactionHex": "0200000000010989d51408bf1f885b50572654a2dd24c4bfd1a14d7c9b4f74de81ba1c616d4ea90000000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4f1654c4e614e915739b566ba6511a2e1610971b6ee239e4158e098a62320d690400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffc9ca41ed0e42e2b0e9897f159bdd20fb79341f3c3fdde0e83366e7bae45bf269e500000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff2f425f864d2dbaf31ba2f2b02658adbe5edab36aedc1fbd7d42a8d6681065ebdc400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff447410db5da41ec044732836cd1aaa37539ea262e095aa75675b9d961d7711778702000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4cbf9c604ddbdca9b9873167594f3da33b661d6c15757040f58e6a45446e821e5b01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffe305cb725943876e71c110c62ede7ad1a849eeadb29ece74ec9cfcd43527b64b3601000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff6182df4003982e0149a73ca1be71caf0f5a07a7f17b0a69884ca2e899d257a5e7100000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff7618f1e75775768841720503103aee291762cf06ed2d2d7e18419f9699307915ff01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff0240420f0000000000225120d58d5d38bb5a2813cecfeced939b190048527a2b249dbaf09c302bb636af0f1ebb6a00000000000017a91484c51a49c1a5591ffbd536dce0025c6fcacc46e087024730440220226a7cdecf9dab5d88f57dfb45e5e45e8b24e938c22e414b8c90ac64eea9d4410220534443a01bf0627911bfc92b35639657d30f4c963c60bacba09770b07b6a3c8d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210090c23fd06d5552f527547a2c17ae1decd7c58a8f7363fd59f2671bfb235d40960220567fd8c1af0eaa5c89dbfb80d3e6fbfbb493a4429fb28c54ca171e076e0baba30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54024730440220418fb80a6dae469a2ebc96fdcb0ff82c808545876d390afa66c726d80a3d070502204401e631625f8d83a6a7d0ccc5e2319240f75769a9a1835687d0d8eb62bdf5430121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5402483045022100f2cc528c7733daa602a970e40021f96cef87bc662f9f31621b32cf8ef51dce5402201260482c3a550ef20ed87bfd61299906d5e440e4feb78e8568381a536cfebb2e0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206185ddb641cd9d8d0e126724c91c522954ae775b90b74214651dc16a674b3022022016df2b9455b4518a7b85239e62440f40d81a59080e61b5cd00385de58facf0d30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402203c38a66e6f9f6d67f088b83ce33d0cc00e6d0068d5922e461356ccb23125f01e02204382f4d16842f633ceadf0a7dab70ae9d5691661dbe6ac7c09fc9ea7ab74249d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206ad85249b3d4c6ee1bb895697debd4fac89df6b15d4e93c16454852bbe3ffaf0022074ffd1a716c1b6b191bc3825f8061b27d7b63367c90e3b6633962b978099c3bd0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210094c0adcef4f4eb1e120f3235979a0caec457f0e5525185ef76d54ae668302d45022076b8e07f7968c1cf91d369dd6d92e951fe7b0ff1d3157dd0bbeaa682f2d820b00121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402205127cc30ed7ac63634d7290deda839d414b2f6d659ab4f1643b38bdcd289da6e022003d7bace557b438f0c9947b33765b662286aa6e7245863d0e16ec5e1a38d40de0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5400000000" +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-mismatch-txid.json b/emily/handler/tests/fixtures/create-deposit-mismatch-txid.json new file mode 100644 index 000000000..9e05b30bc --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-mismatch-txid.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "8c1675cba126c57ae11dcda46dbedb06aa28d1583aff8801b2431b0b049ecdab", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "5cb275204384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54ac", + "depositScript": "1e000000000001388005160bf8a0a80e3a205534977e0d9e00bcd8b9c1b3a17520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", + "transactionHex": "0200000000010989d51408bf1f885b50572654a2dd24c4bfd1a14d7c9b4f74de81ba1c616d4ea90000000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4f1654c4e614e915739b566ba6511a2e1610971b6ee239e4158e098a62320d690400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffc9ca41ed0e42e2b0e9897f159bdd20fb79341f3c3fdde0e83366e7bae45bf269e500000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff2f425f864d2dbaf31ba2f2b02658adbe5edab36aedc1fbd7d42a8d6681065ebdc400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff447410db5da41ec044732836cd1aaa37539ea262e095aa75675b9d961d7711778702000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4cbf9c604ddbdca9b9873167594f3da33b661d6c15757040f58e6a45446e821e5b01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffe305cb725943876e71c110c62ede7ad1a849eeadb29ece74ec9cfcd43527b64b3601000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff6182df4003982e0149a73ca1be71caf0f5a07a7f17b0a69884ca2e899d257a5e7100000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff7618f1e75775768841720503103aee291762cf06ed2d2d7e18419f9699307915ff01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff0240420f0000000000225120d58d5d38bb5a2813cecfeced939b190048527a2b249dbaf09c302bb636af0f1ebb6a00000000000017a91484c51a49c1a5591ffbd536dce0025c6fcacc46e087024730440220226a7cdecf9dab5d88f57dfb45e5e45e8b24e938c22e414b8c90ac64eea9d4410220534443a01bf0627911bfc92b35639657d30f4c963c60bacba09770b07b6a3c8d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210090c23fd06d5552f527547a2c17ae1decd7c58a8f7363fd59f2671bfb235d40960220567fd8c1af0eaa5c89dbfb80d3e6fbfbb493a4429fb28c54ca171e076e0baba30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54024730440220418fb80a6dae469a2ebc96fdcb0ff82c808545876d390afa66c726d80a3d070502204401e631625f8d83a6a7d0ccc5e2319240f75769a9a1835687d0d8eb62bdf5430121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5402483045022100f2cc528c7733daa602a970e40021f96cef87bc662f9f31621b32cf8ef51dce5402201260482c3a550ef20ed87bfd61299906d5e440e4feb78e8568381a536cfebb2e0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206185ddb641cd9d8d0e126724c91c522954ae775b90b74214651dc16a674b3022022016df2b9455b4518a7b85239e62440f40d81a59080e61b5cd00385de58facf0d30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402203c38a66e6f9f6d67f088b83ce33d0cc00e6d0068d5922e461356ccb23125f01e02204382f4d16842f633ceadf0a7dab70ae9d5691661dbe6ac7c09fc9ea7ab74249d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206ad85249b3d4c6ee1bb895697debd4fac89df6b15d4e93c16454852bbe3ffaf0022074ffd1a716c1b6b191bc3825f8061b27d7b63367c90e3b6633962b978099c3bd0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210094c0adcef4f4eb1e120f3235979a0caec457f0e5525185ef76d54ae668302d45022076b8e07f7968c1cf91d369dd6d92e951fe7b0ff1d3157dd0bbeaa682f2d820b00121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402205127cc30ed7ac63634d7290deda839d414b2f6d659ab4f1643b38bdcd289da6e022003d7bace557b438f0c9947b33765b662286aa6e7245863d0e16ec5e1a38d40de0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5400000000" +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-valid-2.json b/emily/handler/tests/fixtures/create-deposit-valid-2.json new file mode 100644 index 000000000..e6886e8c8 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-valid-2.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "48ac9b013437e950ac6a90e0b0f205c40eead9df24c785cab4a88538d17a5e92", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "5cb2752080e5d9a5a66f464ffc7c58dcd7211b0d924cb44d3f391d9feca1f8ae81e6c3f7ac", + "depositScript": "1e00000000000138800516f1e0a0b10611aaf496863cff80ead8001a88750b7520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", + "transactionHex": "02000000000101e73f8303166d875e30c3be7e51e1d8c6c930233ad124b41116baedd67690e5320e00000000000000000240420f0000000000225120b7619d3399c7b00527411f617db7c14eb9b489795916bd3744f2f0a59f5563dd96572d020000000016001459d441589772f921f615ddc25fbf734e8b8a360802483045022100ed1f5e848b9676f3e53dd4d58682691b0b901f33d5d73b86d0fe2877172d7ece02205ec929ce064ec5366f740961ce684865575128f5a27f9a5ffd485058e4d51a6b01210380e5d9a5a66f464ffc7c58dcd7211b0d924cb44d3f391d9feca1f8ae81e6c3f700000000" +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-valid.json b/emily/handler/tests/fixtures/create-deposit-valid.json new file mode 100644 index 000000000..e909a5752 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-valid.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "f75cb869600c6a75ab90c872435da38d54d53c27afe5e03ac7dedae7822958de", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "5cb275204384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54ac", + "depositScript": "1e000000000001388005160bf8a0a80e3a205534977e0d9e00bcd8b9c1b3a17520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", + "transactionHex": "0200000000010989d51408bf1f885b50572654a2dd24c4bfd1a14d7c9b4f74de81ba1c616d4ea90000000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4f1654c4e614e915739b566ba6511a2e1610971b6ee239e4158e098a62320d690400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffc9ca41ed0e42e2b0e9897f159bdd20fb79341f3c3fdde0e83366e7bae45bf269e500000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff2f425f864d2dbaf31ba2f2b02658adbe5edab36aedc1fbd7d42a8d6681065ebdc400000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff447410db5da41ec044732836cd1aaa37539ea262e095aa75675b9d961d7711778702000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff4cbf9c604ddbdca9b9873167594f3da33b661d6c15757040f58e6a45446e821e5b01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffffe305cb725943876e71c110c62ede7ad1a849eeadb29ece74ec9cfcd43527b64b3601000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff6182df4003982e0149a73ca1be71caf0f5a07a7f17b0a69884ca2e899d257a5e7100000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff7618f1e75775768841720503103aee291762cf06ed2d2d7e18419f9699307915ff01000017160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259dfdffffff0240420f0000000000225120d58d5d38bb5a2813cecfeced939b190048527a2b249dbaf09c302bb636af0f1ebb6a00000000000017a91484c51a49c1a5591ffbd536dce0025c6fcacc46e087024730440220226a7cdecf9dab5d88f57dfb45e5e45e8b24e938c22e414b8c90ac64eea9d4410220534443a01bf0627911bfc92b35639657d30f4c963c60bacba09770b07b6a3c8d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210090c23fd06d5552f527547a2c17ae1decd7c58a8f7363fd59f2671bfb235d40960220567fd8c1af0eaa5c89dbfb80d3e6fbfbb493a4429fb28c54ca171e076e0baba30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d54024730440220418fb80a6dae469a2ebc96fdcb0ff82c808545876d390afa66c726d80a3d070502204401e631625f8d83a6a7d0ccc5e2319240f75769a9a1835687d0d8eb62bdf5430121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5402483045022100f2cc528c7733daa602a970e40021f96cef87bc662f9f31621b32cf8ef51dce5402201260482c3a550ef20ed87bfd61299906d5e440e4feb78e8568381a536cfebb2e0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206185ddb641cd9d8d0e126724c91c522954ae775b90b74214651dc16a674b3022022016df2b9455b4518a7b85239e62440f40d81a59080e61b5cd00385de58facf0d30121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402203c38a66e6f9f6d67f088b83ce33d0cc00e6d0068d5922e461356ccb23125f01e02204382f4d16842f633ceadf0a7dab70ae9d5691661dbe6ac7c09fc9ea7ab74249d0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402206ad85249b3d4c6ee1bb895697debd4fac89df6b15d4e93c16454852bbe3ffaf0022074ffd1a716c1b6b191bc3825f8061b27d7b63367c90e3b6633962b978099c3bd0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540248304502210094c0adcef4f4eb1e120f3235979a0caec457f0e5525185ef76d54ae668302d45022076b8e07f7968c1cf91d369dd6d92e951fe7b0ff1d3157dd0bbeaa682f2d820b00121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d540247304402205127cc30ed7ac63634d7290deda839d414b2f6d659ab4f1643b38bdcd289da6e022003d7bace557b438f0c9947b33765b662286aa6e7245863d0e16ec5e1a38d40de0121024384f64fdbe709bec8cbecdb1780258449313fb2c02801098bb56ef742308d5400000000" +} \ No newline at end of file From d0fb2885b757e5220e66ed85ff25e7f74f7c5b38 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Thu, 9 Jan 2025 18:52:56 +0000 Subject: [PATCH 02/17] add autogenerated code --- .../client/rust/private/docs/CreateDepositRequestBody.md | 1 + .../emily/client/rust/private/src/apis/deposit_api.rs | 1 + .../rust/private/src/models/create_deposit_request_body.rs | 5 +++++ .../client/rust/public/docs/CreateDepositRequestBody.md | 1 + .../emily/client/rust/public/src/apis/deposit_api.rs | 1 + .../rust/public/src/models/create_deposit_request_body.rs | 5 +++++ .../client/rust/testing/docs/CreateDepositRequestBody.md | 1 + .../emily/client/rust/testing/src/apis/deposit_api.rs | 1 + .../rust/testing/src/models/create_deposit_request_body.rs | 5 +++++ .../generated-specs/private-emily-openapi-spec.json | 7 ++++++- .../openapi/generated-specs/public-emily-openapi-spec.json | 7 ++++++- .../generated-specs/testing-emily-openapi-spec.json | 7 ++++++- 12 files changed, 39 insertions(+), 3 deletions(-) diff --git a/.generated-sources/emily/client/rust/private/docs/CreateDepositRequestBody.md b/.generated-sources/emily/client/rust/private/docs/CreateDepositRequestBody.md index fe6e83217..66f12b35e 100644 --- a/.generated-sources/emily/client/rust/private/docs/CreateDepositRequestBody.md +++ b/.generated-sources/emily/client/rust/private/docs/CreateDepositRequestBody.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **bitcoin_txid** | **String** | Bitcoin transaction id. | **deposit_script** | **String** | Deposit script. | **reclaim_script** | **String** | Reclaim script. | +**transaction_hex** | **String** | The raw transaction hex. | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs b/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs index ed7f027a9..439a89209 100644 --- a/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs +++ b/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs @@ -20,6 +20,7 @@ pub enum CreateDepositError { Status400(models::ErrorResponse), Status404(models::ErrorResponse), Status405(models::ErrorResponse), + Status409(models::ErrorResponse), Status500(models::ErrorResponse), UnknownValue(serde_json::Value), } diff --git a/.generated-sources/emily/client/rust/private/src/models/create_deposit_request_body.rs b/.generated-sources/emily/client/rust/private/src/models/create_deposit_request_body.rs index 8e53dc90e..3451a1585 100644 --- a/.generated-sources/emily/client/rust/private/src/models/create_deposit_request_body.rs +++ b/.generated-sources/emily/client/rust/private/src/models/create_deposit_request_body.rs @@ -26,6 +26,9 @@ pub struct CreateDepositRequestBody { /// Reclaim script. #[serde(rename = "reclaimScript")] pub reclaim_script: String, + /// The raw transaction hex. + #[serde(rename = "transactionHex")] + pub transaction_hex: String, } impl CreateDepositRequestBody { @@ -35,12 +38,14 @@ impl CreateDepositRequestBody { bitcoin_txid: String, deposit_script: String, reclaim_script: String, + transaction_hex: String, ) -> CreateDepositRequestBody { CreateDepositRequestBody { bitcoin_tx_output_index, bitcoin_txid, deposit_script, reclaim_script, + transaction_hex, } } } diff --git a/.generated-sources/emily/client/rust/public/docs/CreateDepositRequestBody.md b/.generated-sources/emily/client/rust/public/docs/CreateDepositRequestBody.md index fe6e83217..66f12b35e 100644 --- a/.generated-sources/emily/client/rust/public/docs/CreateDepositRequestBody.md +++ b/.generated-sources/emily/client/rust/public/docs/CreateDepositRequestBody.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **bitcoin_txid** | **String** | Bitcoin transaction id. | **deposit_script** | **String** | Deposit script. | **reclaim_script** | **String** | Reclaim script. | +**transaction_hex** | **String** | The raw transaction hex. | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs b/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs index ed7f027a9..439a89209 100644 --- a/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs +++ b/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs @@ -20,6 +20,7 @@ pub enum CreateDepositError { Status400(models::ErrorResponse), Status404(models::ErrorResponse), Status405(models::ErrorResponse), + Status409(models::ErrorResponse), Status500(models::ErrorResponse), UnknownValue(serde_json::Value), } diff --git a/.generated-sources/emily/client/rust/public/src/models/create_deposit_request_body.rs b/.generated-sources/emily/client/rust/public/src/models/create_deposit_request_body.rs index 8e53dc90e..3451a1585 100644 --- a/.generated-sources/emily/client/rust/public/src/models/create_deposit_request_body.rs +++ b/.generated-sources/emily/client/rust/public/src/models/create_deposit_request_body.rs @@ -26,6 +26,9 @@ pub struct CreateDepositRequestBody { /// Reclaim script. #[serde(rename = "reclaimScript")] pub reclaim_script: String, + /// The raw transaction hex. + #[serde(rename = "transactionHex")] + pub transaction_hex: String, } impl CreateDepositRequestBody { @@ -35,12 +38,14 @@ impl CreateDepositRequestBody { bitcoin_txid: String, deposit_script: String, reclaim_script: String, + transaction_hex: String, ) -> CreateDepositRequestBody { CreateDepositRequestBody { bitcoin_tx_output_index, bitcoin_txid, deposit_script, reclaim_script, + transaction_hex, } } } diff --git a/.generated-sources/emily/client/rust/testing/docs/CreateDepositRequestBody.md b/.generated-sources/emily/client/rust/testing/docs/CreateDepositRequestBody.md index fe6e83217..66f12b35e 100644 --- a/.generated-sources/emily/client/rust/testing/docs/CreateDepositRequestBody.md +++ b/.generated-sources/emily/client/rust/testing/docs/CreateDepositRequestBody.md @@ -8,6 +8,7 @@ Name | Type | Description | Notes **bitcoin_txid** | **String** | Bitcoin transaction id. | **deposit_script** | **String** | Deposit script. | **reclaim_script** | **String** | Reclaim script. | +**transaction_hex** | **String** | The raw transaction hex. | [[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md) diff --git a/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs b/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs index ed7f027a9..439a89209 100644 --- a/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs +++ b/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs @@ -20,6 +20,7 @@ pub enum CreateDepositError { Status400(models::ErrorResponse), Status404(models::ErrorResponse), Status405(models::ErrorResponse), + Status409(models::ErrorResponse), Status500(models::ErrorResponse), UnknownValue(serde_json::Value), } diff --git a/.generated-sources/emily/client/rust/testing/src/models/create_deposit_request_body.rs b/.generated-sources/emily/client/rust/testing/src/models/create_deposit_request_body.rs index 8e53dc90e..3451a1585 100644 --- a/.generated-sources/emily/client/rust/testing/src/models/create_deposit_request_body.rs +++ b/.generated-sources/emily/client/rust/testing/src/models/create_deposit_request_body.rs @@ -26,6 +26,9 @@ pub struct CreateDepositRequestBody { /// Reclaim script. #[serde(rename = "reclaimScript")] pub reclaim_script: String, + /// The raw transaction hex. + #[serde(rename = "transactionHex")] + pub transaction_hex: String, } impl CreateDepositRequestBody { @@ -35,12 +38,14 @@ impl CreateDepositRequestBody { bitcoin_txid: String, deposit_script: String, reclaim_script: String, + transaction_hex: String, ) -> CreateDepositRequestBody { CreateDepositRequestBody { bitcoin_tx_output_index, bitcoin_txid, deposit_script, reclaim_script, + transaction_hex, } } } diff --git a/.generated-sources/emily/openapi/generated-specs/private-emily-openapi-spec.json b/.generated-sources/emily/openapi/generated-specs/private-emily-openapi-spec.json index 617b36448..9b227e09c 100644 --- a/.generated-sources/emily/openapi/generated-specs/private-emily-openapi-spec.json +++ b/.generated-sources/emily/openapi/generated-specs/private-emily-openapi-spec.json @@ -1768,7 +1768,8 @@ "bitcoinTxid", "bitcoinTxOutputIndex", "reclaimScript", - "depositScript" + "depositScript", + "transactionHex" ], "properties": { "bitcoinTxOutputIndex": { @@ -1788,6 +1789,10 @@ "reclaimScript": { "type": "string", "description": "Reclaim script." + }, + "transactionHex": { + "type": "string", + "description": "The raw transaction hex." } } }, diff --git a/.generated-sources/emily/openapi/generated-specs/public-emily-openapi-spec.json b/.generated-sources/emily/openapi/generated-specs/public-emily-openapi-spec.json index 8435ed92f..25c229028 100644 --- a/.generated-sources/emily/openapi/generated-specs/public-emily-openapi-spec.json +++ b/.generated-sources/emily/openapi/generated-specs/public-emily-openapi-spec.json @@ -1568,7 +1568,8 @@ "bitcoinTxid", "bitcoinTxOutputIndex", "reclaimScript", - "depositScript" + "depositScript", + "transactionHex" ], "properties": { "bitcoinTxOutputIndex": { @@ -1588,6 +1589,10 @@ "reclaimScript": { "type": "string", "description": "Reclaim script." + }, + "transactionHex": { + "type": "string", + "description": "The raw transaction hex." } } }, diff --git a/.generated-sources/emily/openapi/generated-specs/testing-emily-openapi-spec.json b/.generated-sources/emily/openapi/generated-specs/testing-emily-openapi-spec.json index ce0758285..907fb54c1 100644 --- a/.generated-sources/emily/openapi/generated-specs/testing-emily-openapi-spec.json +++ b/.generated-sources/emily/openapi/generated-specs/testing-emily-openapi-spec.json @@ -1822,7 +1822,8 @@ "bitcoinTxid", "bitcoinTxOutputIndex", "reclaimScript", - "depositScript" + "depositScript", + "transactionHex" ], "properties": { "bitcoinTxOutputIndex": { @@ -1842,6 +1843,10 @@ "reclaimScript": { "type": "string", "description": "Reclaim script." + }, + "transactionHex": { + "type": "string", + "description": "The raw transaction hex." } } }, From 447d36a1c7ca0dcacf516dfce3fa0d1d3a7a6b98 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Fri, 10 Jan 2025 11:53:29 +0000 Subject: [PATCH 03/17] simplify deposit validation. save recipients as strings --- emily/handler/src/api/handlers/deposit.rs | 84 ++----------------- .../src/api/models/deposit/requests.rs | 65 ++++---------- 2 files changed, 22 insertions(+), 127 deletions(-) diff --git a/emily/handler/src/api/handlers/deposit.rs b/emily/handler/src/api/handlers/deposit.rs index fe7442402..ac5b57263 100644 --- a/emily/handler/src/api/handlers/deposit.rs +++ b/emily/handler/src/api/handlers/deposit.rs @@ -4,7 +4,6 @@ use crate::api::models::deposit::responses::{ GetDepositsForTransactionResponse, UpdateDepositsResponse, }; use crate::database::entries::StatusEntry; -use stacks_common::codec::StacksMessageCodec as _; use tracing::{debug, instrument}; use warp::reply::{json, with_status, Reply}; @@ -23,7 +22,6 @@ use crate::database::entries::deposit::{ DepositEntry, DepositEntryKey, DepositEvent, DepositParametersEntry, ValidatedUpdateDepositsRequest, }; -use bitcoin::ScriptBuf; use warp::http::StatusCode; /// Get deposit handler. @@ -248,19 +246,8 @@ pub async fn create_deposit( Err(e) => return Err(e), } - let tx = (&body).try_into()?; let limits = accessors::get_limits(&context).await?; - body.validate(&tx, &limits)?; - - // Get parameters from scripts. - let script_parameters = scripts_to_resource_parameters( - &body.deposit_script, - &body.reclaim_script, - tx.tx_out(body.bitcoin_tx_output_index as usize) - .unwrap() // Safe to unwrap. We have already validated the output index in the try_into. - .value - .to_sat(), - )?; + let deposit_info = body.validate(&limits)?; // Make table entry. let deposit_entry: DepositEntry = DepositEntry { @@ -268,10 +255,10 @@ pub async fn create_deposit( bitcoin_txid: body.bitcoin_txid, bitcoin_tx_output_index: body.bitcoin_tx_output_index, }, - recipient: script_parameters.recipient, + recipient: deposit_info.recipient.to_string(), parameters: DepositParametersEntry { - max_fee: script_parameters.max_fee, - lock_time: script_parameters.lock_time, + max_fee: deposit_info.max_fee, + lock_time: deposit_info.lock_time.to_consensus_u32(), }, history: vec![DepositEvent { status: StatusEntry::Pending, @@ -282,7 +269,7 @@ pub async fn create_deposit( status: Status::Pending, last_update_block_hash: stacks_block_hash, last_update_height: stacks_block_height, - amount: script_parameters.amount, + amount: deposit_info.amount, reclaim_script: body.reclaim_script, deposit_script: body.deposit_script, ..Default::default() @@ -301,40 +288,6 @@ pub async fn create_deposit( .map_or_else(Reply::into_response, Reply::into_response) } -/// Parameters from the deposit and reclaim scripts. -struct ScriptParameters { - amount: u64, - max_fee: u64, - recipient: String, - lock_time: u32, -} - -/// Convert scripts to resource parameters. -/// -/// This function is used to convert the deposit and reclaim scripts into the -/// parameters that are stored in the database. -fn scripts_to_resource_parameters( - deposit_script: &str, - reclaim_script: &str, - amount: u64, -) -> Result { - let deposit_script_buf = ScriptBuf::from_hex(deposit_script)?; - let deposit_script_inputs = sbtc::deposits::DepositScriptInputs::parse(&deposit_script_buf)?; - - let reclaim_script_buf = ScriptBuf::from_hex(reclaim_script)?; - let reclaim_script_inputs = sbtc::deposits::ReclaimScriptInputs::parse(&reclaim_script_buf)?; - - let recipient_bytes = deposit_script_inputs.recipient.serialize_to_vec(); - let recipient_hex_string = hex::encode(&recipient_bytes); - - Ok(ScriptParameters { - amount, - max_fee: deposit_script_inputs.max_fee, - recipient: recipient_hex_string, - lock_time: reclaim_script_inputs.lock_time(), - }) -} - /// Update deposits handler. #[utoipa::path( put, @@ -415,30 +368,3 @@ pub async fn update_deposits( } // TODO(393): Add handler unit tests. - -// Test module -#[cfg(test)] -mod tests { - - use super::*; - use sbtc::testing::{self, deposits::TxSetup}; - use test_case::test_case; - - #[test_case(15000, 500_000, 150; "All parameters are normal numbers")] - #[test_case(0, 0, 0; "All parameters are zeros")] - fn test_scripts_to_resource_parameters(max_fee: u64, amount_sats: u64, lock_time: u32) { - let setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, amount_sats); - - let deposit_script = setup.deposit.deposit_script().to_hex_string(); - let reclaim_script = setup.reclaim.reclaim_script().to_hex_string(); - - let script_parameters: ScriptParameters = - scripts_to_resource_parameters(&deposit_script, &reclaim_script, amount_sats).unwrap(); - - assert_eq!(script_parameters.max_fee, max_fee); - assert_eq!(script_parameters.lock_time, lock_time); - - // TODO: Test the recipient with an input value. - assert!(script_parameters.recipient.len() > 0); - } -} diff --git a/emily/handler/src/api/models/deposit/requests.rs b/emily/handler/src/api/models/deposit/requests.rs index 812f7a009..84f3cf04d 100644 --- a/emily/handler/src/api/models/deposit/requests.rs +++ b/emily/handler/src/api/models/deposit/requests.rs @@ -9,7 +9,7 @@ use reqwest::StatusCode; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; -use sbtc::deposits::CreateDepositRequest; +use sbtc::deposits::{CreateDepositRequest, DepositInfo}; use crate::api::models::common::{Fulfillment, Status}; use crate::api::models::limits::Limits; @@ -73,7 +73,7 @@ impl CreateDepositRequestBody { /// Validates that the deposit request is valid. /// This includes validating the request fields, if their content matches the transaction /// and if the amount is within the limits. - pub fn validate(&self, tx: &Transaction, limits: &Limits) -> Result<(), Error> { + pub fn validate(&self, limits: &Limits) -> Result { let deposit_req = CreateDepositRequest { outpoint: OutPoint { txid: parse_hex(&self.bitcoin_txid, "invalid bitcoin_txid", Txid::from_str)?, @@ -91,6 +91,12 @@ impl CreateDepositRequestBody { )?, }; + let tx: Transaction = parse_hex( + &self.transaction_hex, + "invalid transaction_hex", + encode::deserialize_hex, + )?; + let amount = tx .tx_out(self.bitcoin_tx_output_index as usize) .map_err(|_| { @@ -101,9 +107,6 @@ impl CreateDepositRequestBody { })? .value .to_sat(); - deposit_req - .validate_tx(tx) - .map_err(|e| Error::HttpRequest(StatusCode::BAD_REQUEST, e.to_string()))?; // Even if no limits are set, the deposit amount should be higher than the dust limit. let min = limits.per_deposit_minimum.unwrap_or(DEPOSIT_DUST_LIMIT); @@ -121,21 +124,13 @@ impl CreateDepositRequestBody { format!("deposit amount exceeds cap ({})", cap), )); } - Ok(()) - } -} -impl TryInto for &CreateDepositRequestBody { - type Error = Error; - - fn try_into(self) -> Result { - parse_hex( - &self.transaction_hex, - "invalid transaction_hex", - encode::deserialize_hex, - ) + deposit_req + .validate_tx(&tx) + .map_err(|e| Error::HttpRequest(StatusCode::BAD_REQUEST, e.to_string())) } } + /// A singlular Deposit update that contains only the fields pertinent /// to updating the status of a deposit. This includes the key related /// data in addition to status history related data. @@ -217,41 +212,19 @@ mod tests { pub fn parse_request(json: &str) -> CreateDepositRequestBody { serde_json::from_str(json).expect("failed to parse request") } - - pub fn parse_transaction(request: &CreateDepositRequestBody) -> Transaction { - request.try_into().expect("failed to parse transaction") - } - } - - #[tokio::test] - async fn test_transaction_deserialization_valid() { - let deposit_request = helpers::parse_request(CREATE_DEPOSIT_VALID); - let result: Result = (&deposit_request).try_into(); - assert!(result.is_ok()); - } - - #[tokio::test] - async fn test_transaction_deserialization_invalid() { - let deposit_request = helpers::parse_request(CREATE_DEPOSIT_INVALID_TRANSACTION_HEX); - let result: Result = (&deposit_request).try_into(); - assert_eq!( - result.unwrap_err().to_string(), - "HTTP request failed with status code 400 Bad Request: invalid transaction_hex" - .to_string() - ); } #[tokio::test] async fn test_deposit_validate_happy_path() { let deposit_request = helpers::parse_request(CREATE_DEPOSIT_VALID); - let tx = helpers::parse_transaction(&deposit_request); let limits = helpers::create_test_limits(None, None); - assert!(deposit_request.validate(&tx, &limits).is_ok()); + assert!(deposit_request.validate(&limits).is_ok()); } #[test_case(CREATE_DEPOSIT_INVALID_TXID, "invalid bitcoin_txid"; "invalid_txid")] #[test_case(CREATE_DEPOSIT_INVALID_RECLAIM_SCRIPT, "invalid reclaim_script"; "invalid_reclaim_script")] #[test_case(CREATE_DEPOSIT_INVALID_DEPOSIT_SCRIPT, "invalid deposit_script"; "invalid_deposit_script")] + #[test_case(CREATE_DEPOSIT_INVALID_TRANSACTION_HEX, "invalid transaction_hex"; "invalid_transaction_hex")] #[test_case(CREATE_DEPOSIT_INVALID_OUTPUT_INDEX, "invalid bitcoin_output_index"; "invalid_output_index")] #[test_case(CREATE_DEPOSIT_MISMATCH_TXID, "The txid of the transaction did not match the given txid"; "mismatch_txid")] #[test_case( @@ -265,10 +238,9 @@ mod tests { #[tokio::test] async fn test_deposit_validate_errors(input: &str, expected_error: &str) { let deposit_request = helpers::parse_request(input); - let tx = helpers::parse_transaction(&deposit_request); let limits = helpers::create_test_limits(Some(DEPOSIT_DUST_LIMIT), None); - let result = deposit_request.validate(&tx, &limits); + let result = deposit_request.validate(&limits); assert_eq!( result.unwrap_err().to_string(), format!("HTTP request failed with status code 400 Bad Request: {expected_error}") @@ -283,9 +255,8 @@ mod tests { #[tokio::test] async fn test_deposit_validate_limits(input: &str, min: Option, max: Option) { let deposit_request = helpers::parse_request(input); - let tx = helpers::parse_transaction(&deposit_request); let limits = helpers::create_test_limits(min, max); - assert!(deposit_request.validate(&tx, &limits).is_ok()); + assert!(deposit_request.validate(&limits).is_ok()); } #[test_case(CREATE_DEPOSIT_VALID, Some(1_000_000 + 1), None, "deposit amount below minimum (1000001)"; "below_min_limit")] @@ -298,12 +269,10 @@ mod tests { expected_error: &str, ) { let deposit_request = helpers::parse_request(input); - let tx = helpers::parse_transaction(&deposit_request); let limits = helpers::create_test_limits(min, max); - let result = deposit_request.validate(&tx, &limits); + let result = deposit_request.validate(&limits); - assert!(result.is_err()); assert_eq!( result.unwrap_err().to_string(), format!("HTTP request failed with status code 400 Bad Request: {expected_error}") From 9ed0ecbf9d8064e6aaec53e0168a87634f3d822c Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 13 Jan 2025 14:47:51 +0000 Subject: [PATCH 04/17] update integration tests --- emily/handler/tests/integration/deposit.rs | 244 +++++++++++------- sbtc/src/deposits.rs | 45 ++-- sbtc/src/testing/deposits.rs | 52 ++-- sbtc/tests/integration/validation.rs | 12 +- signer/src/bin/demo_cli.rs | 2 + signer/src/block_observer.rs | 26 +- .../fixtures/completed-deposit-event.json | 68 ++--- signer/tests/integration/block_observer.rs | 2 + signer/tests/integration/emily.rs | 15 +- signer/tests/integration/request_decider.rs | 2 + signer/tests/integration/setup.rs | 4 + .../integration/stacks_events_observer.rs | 15 +- .../integration/transaction_coordinator.rs | 2 + 13 files changed, 287 insertions(+), 202 deletions(-) diff --git a/emily/handler/tests/integration/deposit.rs b/emily/handler/tests/integration/deposit.rs index 7d9d92c6e..c32b3b846 100644 --- a/emily/handler/tests/integration/deposit.rs +++ b/emily/handler/tests/integration/deposit.rs @@ -1,9 +1,8 @@ use std::cmp::Ordering; use test_case::test_case; +use bitcoin::consensus::encode::serialize_hex; use sbtc::testing; -use sbtc::testing::deposits::TxSetup; -use stacks_common::codec::StacksMessageCodec as _; use testing_emily_client::models::{Fulfillment, Status, UpdateDepositsRequestBody}; use testing_emily_client::{ apis::{self, configuration::Configuration}, @@ -16,13 +15,9 @@ const BLOCK_HASH: &'static str = ""; const BLOCK_HEIGHT: u64 = 0; const INITIAL_DEPOSIT_STATUS_MESSAGE: &'static str = "Just received deposit"; -const DEPOSIT_LOCK_TIME: u32 = 12345; +const DEPOSIT_LOCK_TIME: u32 = 14; const DEPOSIT_MAX_FEE: u64 = 30; - -// TODO(TBD): This is the only value that will work at the moment because the -// API needs to take in more information in order to get the amount from the -// create deposit data. We need to fix this before launch. -const DEPOSIT_AMOUNT_SATS: u64 = 0; +const DEPOSIT_AMOUNT_SATS: u64 = 1_000_000; /// An arbitrary fully ordered partial cmp comparator for DepositInfos. /// This is useful for sorting vectors of deposit infos so that vectors with @@ -64,20 +59,34 @@ async fn batch_create_deposits( /// Test deposit txn information. This is useful for testing. struct DepositTxnData { - pub recipient: String, - pub reclaim_script: String, - pub deposit_script: String, + pub bitcoin_txid: String, + pub transaction_hex: String, + pub recipients: Vec, + pub reclaim_scripts: Vec, + pub deposit_scripts: Vec, } impl DepositTxnData { - pub fn new(lock_time: u32, max_fee: u64, amount_sats: u64) -> Self { - let test_deposit_tx: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, amount_sats); - let recipient_hex_string = - hex::encode(&test_deposit_tx.deposit.recipient.serialize_to_vec()); + pub fn new(lock_time: u32, max_fee: u64, amounts: &[u64]) -> Self { + let test_deposit_tx = testing::deposits::tx_setup(lock_time, max_fee, amounts); Self { - recipient: recipient_hex_string, - reclaim_script: test_deposit_tx.reclaim.reclaim_script().to_hex_string(), - deposit_script: test_deposit_tx.deposit.deposit_script().to_hex_string(), + bitcoin_txid: test_deposit_tx.tx.compute_txid().to_string(), + transaction_hex: serialize_hex(&test_deposit_tx.tx), + recipients: test_deposit_tx + .deposits + .iter() + .map(|d| d.recipient.to_string()) + .collect(), + reclaim_scripts: test_deposit_tx + .reclaims + .iter() + .map(|r| r.reclaim_script().to_hex_string()) + .collect(), + deposit_scripts: test_deposit_tx + .deposits + .iter() + .map(|d| d.deposit_script().to_hex_string()) + .collect(), } } } @@ -89,27 +98,33 @@ async fn create_and_get_deposit_happy_path() { // Arrange. // -------- - let bitcoin_txid: &str = "bitcoin_txid"; - let bitcoin_tx_output_index = 12; + let bitcoin_tx_output_index = 0; // Setup test deposit transaction. let DepositTxnData { - recipient: expected_recipient, - reclaim_script, - deposit_script, - } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, DEPOSIT_AMOUNT_SATS); + recipients, + reclaim_scripts, + deposit_scripts, + bitcoin_txid, + transaction_hex, + } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, &[DEPOSIT_AMOUNT_SATS]); + + let recipient = recipients.first().unwrap().clone(); + let reclaim_script = reclaim_scripts.first().unwrap().clone(); + let deposit_script = deposit_scripts.first().unwrap().clone(); let request = CreateDepositRequestBody { bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), reclaim_script: reclaim_script.clone(), deposit_script: deposit_script.clone(), + transaction_hex: transaction_hex.clone(), }; let expected_deposit = Deposit { amount: DEPOSIT_AMOUNT_SATS, bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), fulfillment: None, last_update_block_hash: BLOCK_HASH.into(), last_update_height: BLOCK_HEIGHT, @@ -119,7 +134,7 @@ async fn create_and_get_deposit_happy_path() { lock_time: DEPOSIT_LOCK_TIME, max_fee: DEPOSIT_MAX_FEE, }), - recipient: expected_recipient, + recipient, status: testing_emily_client::models::Status::Pending, status_message: INITIAL_DEPOSIT_STATUS_MESSAGE.into(), }; @@ -133,7 +148,7 @@ async fn create_and_get_deposit_happy_path() { let bitcoin_tx_output_index_string = bitcoin_tx_output_index.to_string(); let gotten_deposit = apis::deposit_api::get_deposit( &configuration, - bitcoin_txid, + &bitcoin_txid, &bitcoin_tx_output_index_string, ) .await @@ -152,21 +167,26 @@ async fn wipe_databases_test() { // Arrange. // -------- - let bitcoin_txid: &str = "bitcoin_txid"; - let bitcoin_tx_output_index = 12; + let bitcoin_tx_output_index = 0; // Setup test deposit transaction. let DepositTxnData { - recipient: _, - reclaim_script, - deposit_script, - } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, DEPOSIT_AMOUNT_SATS); + recipients: _, + reclaim_scripts, + deposit_scripts, + bitcoin_txid, + transaction_hex, + } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, &[DEPOSIT_AMOUNT_SATS]); + + let reclaim_script = reclaim_scripts.first().unwrap().clone(); + let deposit_script = deposit_scripts.first().unwrap().clone(); let request = CreateDepositRequestBody { bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), - reclaim_script: reclaim_script.clone(), - deposit_script: deposit_script.clone(), + transaction_hex, + reclaim_script, + deposit_script, + bitcoin_txid: bitcoin_txid.clone().into(), }; // Act. @@ -182,7 +202,7 @@ async fn wipe_databases_test() { let bitcoin_tx_output_index_string = bitcoin_tx_output_index.to_string(); let attempted_get: StandardError = apis::deposit_api::get_deposit( &configuration, - bitcoin_txid, + &bitcoin_txid, &bitcoin_tx_output_index_string, ) .await @@ -201,32 +221,39 @@ async fn get_deposits_for_transaction() { // Arrange. // -------- - let bitcoin_txid: &str = "bitcoin_txid"; - let bitcoin_tx_output_indices = vec![1, 3, 2, 4]; // unordered. - + let bitcoin_tx_output_indices: Vec = vec![0, 2, 1, 3]; // unordered. + let amounts = vec![DEPOSIT_AMOUNT_SATS; 4]; // Setup test deposit transaction. let DepositTxnData { - recipient: expected_recipient, - reclaim_script, - deposit_script, - } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, DEPOSIT_AMOUNT_SATS); + recipients, + reclaim_scripts, + deposit_scripts, + bitcoin_txid, + transaction_hex, + } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, &amounts); let mut create_requests: Vec = Vec::new(); let mut expected_deposits: Vec = Vec::new(); for bitcoin_tx_output_index in bitcoin_tx_output_indices { + let tx_output_index = bitcoin_tx_output_index as usize; + let recipient = recipients.get(tx_output_index).unwrap().clone(); + let reclaim_script = reclaim_scripts.get(tx_output_index).unwrap().clone(); + let deposit_script = deposit_scripts.get(tx_output_index).unwrap().clone(); + let request = CreateDepositRequestBody { bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), deposit_script: deposit_script.clone(), reclaim_script: reclaim_script.clone(), + transaction_hex: transaction_hex.clone(), }; create_requests.push(request); let expected_deposit = Deposit { amount: DEPOSIT_AMOUNT_SATS, bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), fulfillment: None, last_update_block_hash: BLOCK_HASH.into(), last_update_height: BLOCK_HEIGHT, @@ -236,7 +263,7 @@ async fn get_deposits_for_transaction() { lock_time: DEPOSIT_LOCK_TIME, max_fee: DEPOSIT_MAX_FEE, }), - recipient: expected_recipient.clone(), + recipient: recipient.clone(), status: testing_emily_client::models::Status::Pending, status_message: INITIAL_DEPOSIT_STATUS_MESSAGE.into(), }; @@ -248,7 +275,7 @@ async fn get_deposits_for_transaction() { batch_create_deposits(&configuration, create_requests).await; let gotten_deposits = - apis::deposit_api::get_deposits_for_transaction(&configuration, bitcoin_txid, None, None) + apis::deposit_api::get_deposits_for_transaction(&configuration, &bitcoin_txid, None, None) .await .expect( "Received an error after making a valid get deposits for transaction api call.", @@ -273,36 +300,46 @@ async fn get_deposits() { // Arrange. // -------- - let bitcoin_txids: Vec<&str> = vec!["bitcoin_txid_1", "bitcoin_txid_2"]; - let bitcoin_tx_output_indices = vec![1, 3, 2, 4]; // unordered. + let bitcoin_tx_output_indices: Vec = vec![0, 2, 1, 3]; // unordered. + let amounts = vec![DEPOSIT_AMOUNT_SATS; 4]; // Setup test deposit transaction. - let DepositTxnData { - recipient: expected_recipient, - reclaim_script, - deposit_script, - } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, DEPOSIT_AMOUNT_SATS); + let deposit_txn_data = + (0..2).map(|_| DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, &amounts)); let mut create_requests: Vec = Vec::new(); let mut expected_deposit_infos: Vec = Vec::new(); - for bitcoin_txid in bitcoin_txids { + for deposit_tx in deposit_txn_data { + let DepositTxnData { + recipients, + reclaim_scripts, + deposit_scripts, + bitcoin_txid, + transaction_hex, + } = deposit_tx; for &bitcoin_tx_output_index in bitcoin_tx_output_indices.iter() { + let tx_output_index = bitcoin_tx_output_index as usize; + let recipient = recipients.get(tx_output_index).unwrap().clone(); + let reclaim_script = reclaim_scripts.get(tx_output_index).unwrap().clone(); + let deposit_script = deposit_scripts.get(tx_output_index).unwrap().clone(); + let request = CreateDepositRequestBody { bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), deposit_script: deposit_script.clone(), reclaim_script: reclaim_script.clone(), + transaction_hex: transaction_hex.clone(), }; create_requests.push(request); let expected_deposit_info = DepositInfo { amount: DEPOSIT_AMOUNT_SATS, bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), last_update_block_hash: BLOCK_HASH.into(), last_update_height: BLOCK_HEIGHT, - recipient: expected_recipient.clone(), + recipient: recipient.clone(), status: testing_emily_client::models::Status::Pending, reclaim_script: reclaim_script.clone(), deposit_script: deposit_script.clone(), @@ -365,18 +402,12 @@ async fn get_deposits() { #[tokio::test] async fn update_deposits() { let configuration = clean_setup().await; - // Arrange. // -------- - let bitcoin_txids: Vec<&str> = vec!["bitcoin_txid_1", "bitcoin_txid_2"]; - let bitcoin_tx_output_indices = vec![1, 2]; - + let amounts = vec![DEPOSIT_AMOUNT_SATS; 2]; // Setup test deposit transaction. - let DepositTxnData { - recipient: expected_recipient, - reclaim_script, - deposit_script, - } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, DEPOSIT_AMOUNT_SATS); + let deposits_txs = + (0..2).map(|_| DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, &amounts)); let update_status_message: &str = "test_status_message"; let update_block_hash: &str = "update_block_hash"; @@ -392,23 +423,36 @@ async fn update_deposits() { stacks_txid: "test_fulfillment_stacks_txid".to_string(), }; - let num_deposits = bitcoin_tx_output_indices.len() * bitcoin_txids.len(); + let num_deposits = amounts.len() * deposits_txs.len(); let mut create_requests: Vec = Vec::with_capacity(num_deposits); let mut deposit_updates: Vec = Vec::with_capacity(num_deposits); let mut expected_deposits: Vec = Vec::with_capacity(num_deposits); - for bitcoin_txid in bitcoin_txids { - for &bitcoin_tx_output_index in bitcoin_tx_output_indices.iter() { + for tx in deposits_txs { + let DepositTxnData { + recipients, + reclaim_scripts, + deposit_scripts, + bitcoin_txid, + transaction_hex, + } = tx; + for (i, ((recipient, reclaim_script), deposit_script)) in recipients + .iter() + .zip(reclaim_scripts.iter()) + .zip(deposit_scripts.iter()) + .enumerate() + { let create_request = CreateDepositRequestBody { - bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_tx_output_index: i as u32, + bitcoin_txid: bitcoin_txid.clone().into(), deposit_script: deposit_script.clone(), reclaim_script: reclaim_script.clone(), + transaction_hex: transaction_hex.clone(), }; create_requests.push(create_request); let deposit_update = DepositUpdate { - bitcoin_tx_output_index: bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_tx_output_index: i as u32, + bitcoin_txid: bitcoin_txid.clone().into(), fulfillment: Some(Some(Box::new(update_fulfillment.clone()))), last_update_block_hash: update_block_hash.into(), last_update_height: update_block_height, @@ -419,8 +463,8 @@ async fn update_deposits() { let expected_deposit = Deposit { amount: DEPOSIT_AMOUNT_SATS, - bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_tx_output_index: i as u32, + bitcoin_txid: bitcoin_txid.clone().into(), fulfillment: Some(Some(Box::new(update_fulfillment.clone()))), last_update_block_hash: update_block_hash.into(), last_update_height: update_block_height, @@ -430,7 +474,7 @@ async fn update_deposits() { lock_time: DEPOSIT_LOCK_TIME, max_fee: DEPOSIT_MAX_FEE, }), - recipient: expected_recipient.clone(), + recipient: recipient.clone(), status: update_status.clone(), status_message: update_status_message.into(), }; @@ -464,21 +508,25 @@ async fn update_deposits_updates_chainstate() { // Arrange. // -------- - let bitcoin_txid = "bitcoin_txid_1"; - let bitcoin_tx_output_index = 1; + let bitcoin_tx_output_index = 0; // Setup test deposit transaction. let DepositTxnData { - recipient: _, - reclaim_script, - deposit_script, - } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, DEPOSIT_AMOUNT_SATS); + recipients: _, + reclaim_scripts, + deposit_scripts, + bitcoin_txid, + transaction_hex, + } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, &[DEPOSIT_AMOUNT_SATS]); + let reclaim_script = reclaim_scripts.first().unwrap().clone(); + let deposit_script = deposit_scripts.first().unwrap().clone(); let create_request = CreateDepositRequestBody { bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), deposit_script: deposit_script.clone(), reclaim_script: reclaim_script.clone(), + transaction_hex: transaction_hex.clone(), }; // It's okay to say it's accepted over and over. @@ -493,7 +541,7 @@ async fn update_deposits_updates_chainstate() { for update_block_height in range.clone() { let deposit_update = DepositUpdate { bitcoin_tx_output_index: bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), fulfillment: None, last_update_block_hash: format!("hash_{}", update_block_height), last_update_height: update_block_height as u64, @@ -561,19 +609,25 @@ async fn overwrite_deposit(status: Status, should_reject: bool) { let configuration = clean_setup().await; // Arrange. // -------- - let bitcoin_txid: &str = "bitcoin_txid_overwrite_deposit"; let bitcoin_tx_output_index = 0; // Setup test deposit transaction. let DepositTxnData { - reclaim_script, deposit_script, .. - } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, DEPOSIT_AMOUNT_SATS); + reclaim_scripts, + deposit_scripts, + bitcoin_txid, + transaction_hex, + .. + } = DepositTxnData::new(DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, &[DEPOSIT_AMOUNT_SATS]); + let reclaim_script = reclaim_scripts.first().unwrap().clone(); + let deposit_script = deposit_scripts.first().unwrap().clone(); let create_deposit_body = CreateDepositRequestBody { bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), deposit_script: deposit_script.clone(), reclaim_script: reclaim_script.clone(), + transaction_hex: transaction_hex.clone(), }; apis::deposit_api::create_deposit(&configuration, create_deposit_body.clone()) @@ -582,7 +636,7 @@ async fn overwrite_deposit(status: Status, should_reject: bool) { let response = apis::deposit_api::get_deposit( &configuration, - bitcoin_txid, + &bitcoin_txid, &bitcoin_tx_output_index.to_string(), ) .await @@ -608,7 +662,7 @@ async fn overwrite_deposit(status: Status, should_reject: bool) { UpdateDepositsRequestBody { deposits: vec![DepositUpdate { bitcoin_tx_output_index: bitcoin_tx_output_index, - bitcoin_txid: bitcoin_txid.into(), + bitcoin_txid: bitcoin_txid.clone().into(), fulfillment, last_update_block_hash: "update_block_hash".into(), last_update_height: 34, @@ -622,7 +676,7 @@ async fn overwrite_deposit(status: Status, should_reject: bool) { let response = apis::deposit_api::get_deposit( &configuration, - bitcoin_txid, + &bitcoin_txid, &bitcoin_tx_output_index.to_string(), ) .await @@ -639,7 +693,7 @@ async fn overwrite_deposit(status: Status, should_reject: bool) { let response = apis::deposit_api::get_deposit( &configuration, - bitcoin_txid, + &bitcoin_txid, &bitcoin_tx_output_index.to_string(), ) .await diff --git a/sbtc/src/deposits.rs b/sbtc/src/deposits.rs index 4f48465e1..c2869b9b8 100644 --- a/sbtc/src/deposits.rs +++ b/sbtc/src/deposits.rs @@ -814,12 +814,12 @@ mod tests { let amount_sats = 500_000; let lock_time = 150; - let setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, amount_sats); + let setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, &[amount_sats]); let request = CreateDepositRequest { outpoint: OutPoint::new(setup.tx.compute_txid(), 0), - reclaim_script: setup.reclaim.reclaim_script(), - deposit_script: setup.deposit.deposit_script(), + reclaim_script: setup.reclaims.first().unwrap().reclaim_script(), + deposit_script: setup.deposits.first().unwrap().deposit_script(), }; let parsed = request.validate_tx(&setup.tx).unwrap(); @@ -828,9 +828,12 @@ mod tests { assert_eq!(parsed.deposit_script, request.deposit_script); assert_eq!(parsed.reclaim_script, request.reclaim_script); assert_eq!(parsed.amount, amount_sats); - assert_eq!(parsed.signers_public_key, setup.deposit.signers_public_key); + assert_eq!( + parsed.signers_public_key, + setup.deposits.first().unwrap().signers_public_key + ); assert_eq!(parsed.lock_time, LockTime::from_height(lock_time as u16)); - assert_eq!(parsed.recipient, setup.deposit.recipient); + assert_eq!(parsed.recipient, setup.deposits.first().unwrap().recipient); } #[test] @@ -839,16 +842,16 @@ mod tests { let amount_sats = 500_000; let lock_time = 150; - let mut setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, amount_sats); + let mut setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, &[amount_sats]); // Let's modify the max_fee of the deposit script and send that in // the request. - setup.deposit.max_fee = 3000; + setup.deposits.first_mut().unwrap().max_fee = 3000; let request = CreateDepositRequest { outpoint: OutPoint::new(setup.tx.compute_txid(), 0), - deposit_script: setup.deposit.deposit_script(), - reclaim_script: setup.reclaim.reclaim_script(), + deposit_script: setup.deposits.first().unwrap().deposit_script(), + reclaim_script: setup.reclaims.first().unwrap().reclaim_script(), }; let error = request.validate_tx(&setup.tx).unwrap_err(); @@ -861,16 +864,16 @@ mod tests { let amount_sats = 500_000; let lock_time = 0; - let mut setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, amount_sats); + let mut setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, &[amount_sats]); // Let's modify the lock time of the reclaim script to look more // reasonable in the request. - setup.reclaim.lock_time = LockTime::from_height(150); + setup.reclaims.first_mut().unwrap().lock_time = LockTime::from_height(150); let request = CreateDepositRequest { outpoint: OutPoint::new(setup.tx.compute_txid(), 0), - deposit_script: setup.deposit.deposit_script(), - reclaim_script: setup.reclaim.reclaim_script(), + deposit_script: setup.deposits.first().unwrap().deposit_script(), + reclaim_script: setup.reclaims.first().unwrap().reclaim_script(), }; let error = request.validate_tx(&setup.tx).unwrap_err(); @@ -883,13 +886,13 @@ mod tests { let amount_sats = 500_000; let lock_time = 150; - let setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, amount_sats); + let setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, &[amount_sats]); let request = CreateDepositRequest { // This output index is guaranteed to always be incorrect. outpoint: OutPoint::new(setup.tx.compute_txid(), setup.tx.output.len() as u32), - deposit_script: setup.deposit.deposit_script(), - reclaim_script: setup.reclaim.reclaim_script(), + deposit_script: setup.deposits.first().unwrap().deposit_script(), + reclaim_script: setup.reclaims.first().unwrap().reclaim_script(), }; let error = request.validate_tx(&setup.tx).unwrap_err(); @@ -898,8 +901,8 @@ mod tests { let request = CreateDepositRequest { // This txid is almost certainly incorrect. outpoint: OutPoint::new(Txid::all_zeros(), 0), - deposit_script: setup.deposit.deposit_script(), - reclaim_script: setup.reclaim.reclaim_script(), + deposit_script: setup.deposits.first().unwrap().deposit_script(), + reclaim_script: setup.reclaims.first().unwrap().reclaim_script(), }; let error = request.validate_tx(&setup.tx).unwrap_err(); @@ -912,7 +915,7 @@ mod tests { let amount_sats = 500_000; let lock_time = 150; - let setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, amount_sats); + let setup: TxSetup = testing::deposits::tx_setup(lock_time, max_fee, &[amount_sats]); let request = CreateDepositRequest { outpoint: OutPoint::new(setup.tx.compute_txid(), 0), @@ -920,7 +923,7 @@ mod tests { // they told us a lie and sent us an invalid deposit script in // their request. deposit_script: ScriptBuf::new(), - reclaim_script: setup.reclaim.reclaim_script(), + reclaim_script: setup.reclaims.first().unwrap().reclaim_script(), }; let error = request.validate_tx(&setup.tx).unwrap_err(); @@ -928,7 +931,7 @@ mod tests { let request = CreateDepositRequest { outpoint: OutPoint::new(setup.tx.compute_txid(), 0), - deposit_script: setup.deposit.deposit_script(), + deposit_script: setup.deposits.first().unwrap().deposit_script(), // The actual reclaim script in the transaction is fine, but // they told us a lie, and sent us an invalid reclaim script in // their request. diff --git a/sbtc/src/testing/deposits.rs b/sbtc/src/testing/deposits.rs index 0e6c121a1..6b2420090 100644 --- a/sbtc/src/testing/deposits.rs +++ b/sbtc/src/testing/deposits.rs @@ -20,39 +20,47 @@ use crate::deposits::ReclaimScriptInputs; /// A properly formated transaction and the corresponding deposit and /// reclaim inputs. pub struct TxSetup { - /// The transaction + /// The transaction pub tx: Transaction, - /// The deposit script and its variable inputs - pub deposit: DepositScriptInputs, - /// The reclaim script and its variable inputs - pub reclaim: ReclaimScriptInputs, + /// The deposit scripts and their variable inputs + pub deposits: Vec, + /// The reclaim scripts and their variable inputs + pub reclaims: Vec, } /// The BTC transaction that is in this TxSetup is consistent with /// the deposit and reclaim scripts. -pub fn tx_setup(lock_time: u32, max_fee: u64, amount: u64) -> TxSetup { - let secret_key = SecretKey::new(&mut OsRng); +pub fn tx_setup(lock_time: u32, max_fee: u64, amounts: &[u64]) -> TxSetup { + let mut tx_outs = Vec::with_capacity(amounts.len()); + let mut deposits = Vec::with_capacity(amounts.len()); + let mut reclaims = Vec::with_capacity(amounts.len()); - let deposit = DepositScriptInputs { - signers_public_key: secret_key.x_only_public_key(SECP256K1).0, - recipient: PrincipalData::from(StacksAddress::burn_address(false)), - max_fee, - }; - let reclaim = ReclaimScriptInputs::try_new(lock_time, ScriptBuf::new()).unwrap(); + for &amount in amounts { + let secret_key = SecretKey::new(&mut OsRng); + let deposit = DepositScriptInputs { + signers_public_key: secret_key.x_only_public_key(SECP256K1).0, + recipient: PrincipalData::from(StacksAddress::burn_address(false)), + max_fee, + }; + let reclaim = ReclaimScriptInputs::try_new(lock_time, ScriptBuf::new()).unwrap(); + + let deposit_script = deposit.deposit_script(); + let reclaim_script = reclaim.reclaim_script(); + + tx_outs.push(TxOut { + value: Amount::from_sat(amount), + script_pubkey: deposits::to_script_pubkey(deposit_script, reclaim_script), + }); + deposits.push(deposit); + reclaims.push(reclaim); + } - let deposit_script = deposit.deposit_script(); - let reclaim_script = reclaim.reclaim_script(); - // This transaction is kinda invalid because it doesn't have any - // inputs. But it is fine for our purposes. let tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, input: Vec::new(), - output: vec![TxOut { - value: Amount::from_sat(amount), - script_pubkey: deposits::to_script_pubkey(deposit_script, reclaim_script), - }], + output: tx_outs, }; - TxSetup { tx, reclaim, deposit } + TxSetup { tx, reclaims, deposits } } diff --git a/sbtc/tests/integration/validation.rs b/sbtc/tests/integration/validation.rs index 8f30dc245..a7c1659e1 100644 --- a/sbtc/tests/integration/validation.rs +++ b/sbtc/tests/integration/validation.rs @@ -49,7 +49,7 @@ fn tx_validation_from_mempool() { let amount_sats = 49_900_000; let lock_time = 150; - let mut setup: TxSetup = sbtc::testing::deposits::tx_setup(lock_time, max_fee, amount_sats); + let mut setup: TxSetup = sbtc::testing::deposits::tx_setup(lock_time, max_fee, &[amount_sats]); let (rpc, faucet) = regtest::initialize_blockchain(); let depositor = Recipient::new(AddressType::P2tr); @@ -67,11 +67,11 @@ fn tx_validation_from_mempool() { script_sig: ScriptBuf::new(), witness: Witness::new(), }]; - + let deposit = setup.deposits.first().unwrap(); let request = CreateDepositRequest { outpoint: OutPoint::new(setup.tx.compute_txid(), 0), - reclaim_script: setup.reclaim.reclaim_script(), - deposit_script: setup.deposit.deposit_script(), + reclaim_script: setup.reclaims.first().unwrap().reclaim_script(), + deposit_script: deposit.deposit_script(), }; regtest::p2tr_sign_transaction(&mut setup.tx, 0, &utxos, &depositor.keypair); @@ -83,8 +83,8 @@ fn tx_validation_from_mempool() { assert_eq!(parsed.deposit_script, request.deposit_script); assert_eq!(parsed.reclaim_script, request.reclaim_script); assert_eq!(parsed.amount, amount_sats); - assert_eq!(parsed.signers_public_key, setup.deposit.signers_public_key); - assert_eq!(parsed.recipient, setup.deposit.recipient); + assert_eq!(parsed.signers_public_key, deposit.signers_public_key); + assert_eq!(parsed.recipient, deposit.recipient); let lock_time_height = bitcoin::relative::LockTime::from_height(lock_time as u16); assert_eq!(parsed.lock_time, lock_time_height); diff --git a/signer/src/bin/demo_cli.rs b/signer/src/bin/demo_cli.rs index 73c4df021..201b6c4f9 100644 --- a/signer/src/bin/demo_cli.rs +++ b/signer/src/bin/demo_cli.rs @@ -1,5 +1,6 @@ use std::str::FromStr; +use bitcoin::consensus::encode::serialize_hex; use bitcoin::hex::DisplayHex; use bitcoin::{ absolute, transaction::Version, Amount, Network, OutPoint, ScriptBuf, Sequence, Transaction, @@ -185,6 +186,7 @@ async fn exec_deposit( bitcoin_txid: txid.to_string(), deposit_script: deposit_script.deposit_script().to_hex_string(), reclaim_script: reclaim_script.reclaim_script().to_hex_string(), + transaction_hex: serialize_hex(&unsigned_tx), }, ) .await?; diff --git a/signer/src/block_observer.rs b/signer/src/block_observer.rs index 66553b54b..92d709500 100644 --- a/signer/src/block_observer.rs +++ b/signer/src/block_observer.rs @@ -667,14 +667,14 @@ mod tests { // invalid requests (even though it should've validated them) and // BitcoinClient will return the right transaction for both of // them. - let tx_setup0 = sbtc::testing::deposits::tx_setup(lock_time, max_fee, amount); + let tx_setup0 = sbtc::testing::deposits::tx_setup(lock_time, max_fee, &[amount]); let deposit_request0 = CreateDepositRequest { outpoint: bitcoin::OutPoint { txid: tx_setup0.tx.compute_txid(), vout: 0, }, - deposit_script: tx_setup0.deposit.deposit_script(), - reclaim_script: tx_setup0.reclaim.reclaim_script(), + deposit_script: tx_setup0.deposits.first().unwrap().deposit_script(), + reclaim_script: tx_setup0.reclaims.first().unwrap().reclaim_script(), }; let req0 = deposit_request0.clone(); // When we validate the deposit request, we fetch the transaction @@ -686,7 +686,7 @@ mod tests { block_time: None, }; - let tx_setup1 = sbtc::testing::deposits::tx_setup(300, 2000, amount); + let tx_setup1 = sbtc::testing::deposits::tx_setup(300, 2000, &[amount]); // This one is an invalid deposit request because the deposit // script is wrong let deposit_request1 = CreateDepositRequest { @@ -695,7 +695,7 @@ mod tests { vout: 0, }, deposit_script: bitcoin::ScriptBuf::new(), - reclaim_script: tx_setup1.reclaim.reclaim_script(), + reclaim_script: tx_setup1.reclaims.first().unwrap().reclaim_script(), }; // The transaction is also in the mempool, even though it is an // invalid deposit. @@ -708,7 +708,7 @@ mod tests { // This deposit transaction is a fine deposit, it just hasn't been // confirmed yet. - let tx_setup2 = sbtc::testing::deposits::tx_setup(400, 3000, amount); + let tx_setup2 = sbtc::testing::deposits::tx_setup(400, 3000, &[amount]); let get_tx_resp2 = GetTxResponse { tx: tx_setup2.tx.clone(), block_hash: None, @@ -721,8 +721,8 @@ mod tests { txid: tx_setup2.tx.compute_txid(), vout: 0, }, - deposit_script: tx_setup2.deposit.deposit_script(), - reclaim_script: tx_setup2.reclaim.reclaim_script(), + deposit_script: tx_setup2.deposits.first().unwrap().deposit_script(), + reclaim_script: tx_setup2.reclaims.first().unwrap().reclaim_script(), }; // Let's add the "responses" to the field that feeds the @@ -796,14 +796,14 @@ mod tests { // invalid requests (even though it should've validated them) and // BitcoinClient will return the right transaction for both of // them. - let tx_setup0 = sbtc::testing::deposits::tx_setup(lock_time, max_fee, amount); + let tx_setup0 = sbtc::testing::deposits::tx_setup(lock_time, max_fee, &[amount]); let deposit_request0 = CreateDepositRequest { outpoint: bitcoin::OutPoint { txid: tx_setup0.tx.compute_txid(), vout: 0, }, - deposit_script: tx_setup0.deposit.deposit_script(), - reclaim_script: tx_setup0.reclaim.reclaim_script(), + deposit_script: tx_setup0.deposits.first().unwrap().deposit_script(), + reclaim_script: tx_setup0.reclaims.first().unwrap().reclaim_script(), }; // When we validate the deposit request, we fetch the transaction // from bitcoin-core's blockchain. The stubs out that @@ -901,14 +901,14 @@ mod tests { // sbtc::testing::deposits::tx_setup just to quickly create a // transaction; any one will do since we will be adding the UTXO // that spends to the signer afterward. - let mut tx_setup0 = sbtc::testing::deposits::tx_setup(0, 0, 100); + let mut tx_setup0 = sbtc::testing::deposits::tx_setup(0, 0, &[100]); tx_setup0.tx.output.push(TxOut { value: Amount::ONE_BTC, script_pubkey: signers_script_pubkey.into(), }); // This one does not spend to the signers :( - let tx_setup1 = sbtc::testing::deposits::tx_setup(1, 10, 2000); + let tx_setup1 = sbtc::testing::deposits::tx_setup(1, 10, &[2000]); let txid0 = tx_setup0.tx.compute_txid(); let txid1 = tx_setup1.tx.compute_txid(); diff --git a/signer/tests/fixtures/completed-deposit-event.json b/signer/tests/fixtures/completed-deposit-event.json index 10041b665..417d25c0b 100644 --- a/signer/tests/fixtures/completed-deposit-event.json +++ b/signer/tests/fixtures/completed-deposit-event.json @@ -30,50 +30,50 @@ "Tuple": { "data_map": { "amount": { - "UInt": 123654789 + "UInt": 1000000 }, "bitcoin-txid": { "Sequence": { "Buffer": { "data": [ - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0 + 247, + 92, + 184, + 105, + 96, + 12, + 106, + 117, + 171, + 144, + 200, + 114, + 67, + 93, + 163, + 141, + 84, + 213, + 60, + 39, + 175, + 229, + 224, + 58, + 199, + 222, + 218, + 231, + 130, + 41, + 88, + 222 ] } } }, "output-index": { - "UInt": 4294967295 + "UInt": 0 }, "burn-hash": { "Sequence": { diff --git a/signer/tests/integration/block_observer.rs b/signer/tests/integration/block_observer.rs index 44024e718..d428cbe0e 100644 --- a/signer/tests/integration/block_observer.rs +++ b/signer/tests/integration/block_observer.rs @@ -5,6 +5,7 @@ use std::sync::atomic::Ordering; use std::sync::Arc; use std::time::Duration; +use bitcoin::consensus::encode::serialize_hex; use bitcoin::Address; use bitcoin::AddressType; use bitcoin::Amount; @@ -604,6 +605,7 @@ async fn block_observer_stores_donation_and_sbtc_utxos() { bitcoin_txid: deposit_request.outpoint.txid.to_string(), deposit_script: deposit_request.deposit_script.to_hex_string(), reclaim_script: deposit_request.reclaim_script.to_hex_string(), + transaction_hex: serialize_hex(&deposit_tx), }; deposit_api::create_deposit(emily_client.config(), body) .await diff --git a/signer/tests/integration/emily.rs b/signer/tests/integration/emily.rs index e8187ca59..b6afd9292 100644 --- a/signer/tests/integration/emily.rs +++ b/signer/tests/integration/emily.rs @@ -3,6 +3,7 @@ use std::time::Duration; use bitcoin::block::Header; use bitcoin::block::Version; +use bitcoin::consensus::encode::serialize_hex; use bitcoin::hashes::Hash as _; use bitcoin::AddressType; use bitcoin::Amount; @@ -219,6 +220,7 @@ async fn deposit_flow() { bitcoin_txid: deposit_request.outpoint.txid.to_string(), deposit_script: deposit_request.deposit_script.to_hex_string(), reclaim_script: deposit_request.reclaim_script.to_hex_string(), + transaction_hex: serialize_hex(&deposit_tx), }; // Create a fresh block for the block observer to process @@ -575,13 +577,16 @@ async fn get_deposit_request_works() { .await .expect("Wiping Emily database in test setup failed."); - let setup = sbtc::testing::deposits::tx_setup(lock_time, max_fee, amount_sats); + let setup = sbtc::testing::deposits::tx_setup(lock_time, max_fee, &[amount_sats]); + let deposit = setup.deposits.first().unwrap(); + let reclaim = setup.reclaims.first().unwrap(); let emily_request = CreateDepositRequestBody { bitcoin_tx_output_index: 0, bitcoin_txid: setup.tx.compute_txid().to_string(), - deposit_script: setup.deposit.deposit_script().to_hex_string(), - reclaim_script: setup.reclaim.reclaim_script().to_hex_string(), + deposit_script: deposit.deposit_script().to_hex_string(), + reclaim_script: reclaim.reclaim_script().to_hex_string(), + transaction_hex: serialize_hex(&setup.tx), }; deposit_api::create_deposit(emily_client.config(), emily_request.clone()) @@ -591,8 +596,8 @@ async fn get_deposit_request_works() { let txid = setup.tx.compute_txid().into(); let request = emily_client.get_deposit(&txid, 0).await.unwrap().unwrap(); - assert_eq!(request.deposit_script, setup.deposit.deposit_script()); - assert_eq!(request.reclaim_script, setup.reclaim.reclaim_script()); + assert_eq!(request.deposit_script, deposit.deposit_script()); + assert_eq!(request.reclaim_script, reclaim.reclaim_script()); assert_eq!(request.outpoint.txid, setup.tx.compute_txid()); assert_eq!(request.outpoint.vout, 0); diff --git a/signer/tests/integration/request_decider.rs b/signer/tests/integration/request_decider.rs index 47fc60c8b..28f238b75 100644 --- a/signer/tests/integration/request_decider.rs +++ b/signer/tests/integration/request_decider.rs @@ -1,5 +1,6 @@ use std::sync::atomic::Ordering; +use bitcoin::consensus::encode::serialize_hex; use emily_client::apis::deposit_api; use emily_client::apis::testing_api; use emily_client::models::CreateDepositRequestBody; @@ -374,6 +375,7 @@ async fn persist_received_deposit_decision_fetches_missing_deposit_requests() { bitcoin_txid: setup.deposit_request.outpoint.txid.to_string(), deposit_script: setup.deposit_request.deposit_script.to_hex_string(), reclaim_script: setup.deposit_request.reclaim_script.to_hex_string(), + transaction_hex: serialize_hex(&setup.deposit_tx), }; let _ = deposit_api::create_deposit(emily_client.config(), body) .await diff --git a/signer/tests/integration/setup.rs b/signer/tests/integration/setup.rs index befbb7ed1..b2b268595 100644 --- a/signer/tests/integration/setup.rs +++ b/signer/tests/integration/setup.rs @@ -4,6 +4,7 @@ use bitcoin::consensus::Encodable as _; use bitcoin::hashes::Hash as _; use bitcoin::AddressType; use bitcoin::OutPoint; +use bitcoin::Transaction; use bitcoincore_rpc::Client; use bitcoincore_rpc::RpcApi as _; use blockstack_lib::types::chainstate::StacksAddress; @@ -86,6 +87,8 @@ pub struct TestSweepSetup { /// threshold is the bitcoin signature threshold, which for v1 matches /// the signatures required on stacks. pub signatures_required: u16, + /// The deposit transaction + pub deposit_tx: Transaction, } impl TestSweepSetup { @@ -202,6 +205,7 @@ impl TestSweepSetup { withdrawal_request: requests.withdrawals.pop().unwrap(), withdrawal_sender: PrincipalData::from(StacksAddress::burn_address(false)), signatures_required: 2, + deposit_tx, } } diff --git a/signer/tests/integration/stacks_events_observer.rs b/signer/tests/integration/stacks_events_observer.rs index 5cf82ba68..1e614d62c 100644 --- a/signer/tests/integration/stacks_events_observer.rs +++ b/signer/tests/integration/stacks_events_observer.rs @@ -17,7 +17,6 @@ use fake::Fake; use rand::rngs::OsRng; use sbtc::events::RegistryEvent; use sbtc::events::TxInfo; -use sbtc::testing::deposits::TxSetup; use sbtc::webhooks::NewBlockEvent; use signer::api::new_block_handler; use signer::api::ApiState; @@ -56,6 +55,9 @@ async fn test_context() -> TestContext< .build() } +const CREATE_DEPOSIT_VALID: &str = + include_str!("../../../emily/handler/tests/fixtures/create-deposit-valid.json"); + const COMPLETED_DEPOSIT_WEBHOOK: &str = include_str!("../../tests/fixtures/completed-deposit-event.json"); @@ -113,13 +115,12 @@ async fn test_new_blocks_sends_update_deposits_to_emily() { RegistryEvent::CompletedDeposit(event) => Some(event), _ => panic!("Expected CompletedDeposit event"), }); - let bitcoin_txid = deposit_completed_event.outpoint.txid.to_string(); // Insert a dummy deposit request into the database. This will be retrieved by // handle_completed_deposit to compute the fee paid. let mut deposit: DepositRequest = fake::Faker.fake_with_rng(&mut OsRng); - deposit.amount = deposit_completed_event.amount + 100; + deposit.amount = deposit_completed_event.amount; deposit.txid = deposit_completed_event.outpoint.txid.into(); deposit.output_index = deposit_completed_event.outpoint.vout; @@ -130,12 +131,14 @@ async fn test_new_blocks_sends_update_deposits_to_emily() { .expect("failed to insert dummy deposit request"); // Add the deposit request to Emily - let tx_setup: TxSetup = sbtc::testing::deposits::tx_setup(15_000, 500_000, 150); + let request: CreateDepositRequestBody = + serde_json::from_str(CREATE_DEPOSIT_VALID).expect("failed to parse request"); let create_deposity_req = CreateDepositRequestBody { bitcoin_tx_output_index: deposit_completed_event.outpoint.vout as u32, bitcoin_txid: bitcoin_txid.clone(), - deposit_script: tx_setup.deposit.deposit_script().to_hex_string(), - reclaim_script: tx_setup.reclaim.reclaim_script().to_hex_string(), + deposit_script: request.deposit_script, + reclaim_script: request.reclaim_script, + transaction_hex: request.transaction_hex, }; let resp = create_deposit(&emily_context, create_deposity_req).await; assert!(resp.is_ok()); diff --git a/signer/tests/integration/transaction_coordinator.rs b/signer/tests/integration/transaction_coordinator.rs index 0242fb6c1..63d0f35ae 100644 --- a/signer/tests/integration/transaction_coordinator.rs +++ b/signer/tests/integration/transaction_coordinator.rs @@ -5,6 +5,7 @@ use std::sync::atomic::Ordering; use std::sync::Arc; use std::time::Duration; +use bitcoin::consensus::encode::serialize_hex; use bitcoin::consensus::Encodable as _; use bitcoin::hashes::Hash as _; use bitcoin::Address; @@ -1456,6 +1457,7 @@ async fn sign_bitcoin_transaction() { bitcoin_txid: deposit_request.outpoint.txid.to_string(), deposit_script: deposit_request.deposit_script.to_hex_string(), reclaim_script: deposit_request.reclaim_script.to_hex_string(), + transaction_hex: serialize_hex(&deposit_tx), }; let _ = deposit_api::create_deposit(emily_client.config(), body) .await From 4156052502d71baace2ac92a90c4a7e0dc3bbf84 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 13 Jan 2025 17:55:43 +0000 Subject: [PATCH 05/17] fix test_events unit test --- .../completed-valid-deposit-event.json | 288 ++++++++++++++++++ .../fixtures/create-deposit-valid-2.json | 7 - .../fixtures/completed-deposit-event.json | 68 ++--- .../integration/stacks_events_observer.rs | 6 +- 4 files changed, 325 insertions(+), 44 deletions(-) create mode 100644 emily/handler/tests/fixtures/completed-valid-deposit-event.json delete mode 100644 emily/handler/tests/fixtures/create-deposit-valid-2.json diff --git a/emily/handler/tests/fixtures/completed-valid-deposit-event.json b/emily/handler/tests/fixtures/completed-valid-deposit-event.json new file mode 100644 index 000000000..417d25c0b --- /dev/null +++ b/emily/handler/tests/fixtures/completed-valid-deposit-event.json @@ -0,0 +1,288 @@ +{ + "anchored_cost": { + "read_count": 28, + "read_length": 42790, + "runtime": 80123, + "write_count": 3, + "write_length": 139 + }, + "block_hash": "0x6bf165f5a1930cca370cf28158d6d86c9ed8103a6066de6138f5fff0c7835590", + "block_height": 227, + "burn_block_hash": "0x15e7d138f2b0b155418f588b7c193eae38f7943a83b4aa1af17aebec6f0e364f", + "burn_block_height": 136, + "burn_block_time": 1725050720, + "confirmed_microblocks_cost": { + "read_count": 0, + "read_length": 0, + "runtime": 0, + "write_count": 0, + "write_length": 0 + }, + "cycle_number": null, + "events": [ + { + "committed": true, + "contract_event": { + "contract_identifier": "SN3R84XZYA63QS28932XQF3G1J8R9PC3W76P9CSQS.sbtc-registry", + "raw_value": "0x0c0000000406616d6f756e7401000000000000000000000000075ed2850c626974636f696e2d74786964020000002000000000000000000000000000000000000000000000000000000000000000000c6f75747075742d696e64657801000000000000000000000000ffffffff05746f7069630d00000011636f6d706c657465642d6465706f736974", + "topic": "print", + "value": { + "Tuple": { + "data_map": { + "amount": { + "UInt": 1000000 + }, + "bitcoin-txid": { + "Sequence": { + "Buffer": { + "data": [ + 247, + 92, + 184, + 105, + 96, + 12, + 106, + 117, + 171, + 144, + 200, + 114, + 67, + 93, + 163, + 141, + 84, + 213, + 60, + 39, + 175, + 229, + 224, + 58, + 199, + 222, + 218, + 231, + 130, + 41, + 88, + 222 + ] + } + } + }, + "output-index": { + "UInt": 0 + }, + "burn-hash": { + "Sequence": { + "Buffer": { + "data": [ + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1, + 1 + ] + } + } + }, + "burn-height": { + "UInt": 42 + }, + "sweep-txid": { + "Sequence": { + "Buffer": { + "data": [ + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2, + 2 + ] + } + } + }, + "topic": { + "Sequence": { + "String": { + "ASCII": { + "data": [ + 99, + 111, + 109, + 112, + 108, + 101, + 116, + 101, + 100, + 45, + 100, + 101, + 112, + 111, + 115, + 105, + 116 + ] + } + } + } + } + }, + "type_signature": { + "type_map": { + "amount": "UIntType", + "bitcoin-txid": { + "SequenceType": { + "BufferType": 32 + } + }, + "output-index": "UIntType", + "burn-hash": { + "SequenceType": { + "BufferType": 32 + } + }, + "burn-height": "UIntType", + "sweep-txid": { + "SequenceType": { + "BufferType": 32 + } + }, + "topic": { + "SequenceType": { + "StringType": { + "ASCII": 17 + } + } + } + } + } + } + } + }, + "event_index": 1, + "txid": "0x58a9074c3299c2f627829b7e5ecf8b7136e380cbce3900461c679939925f77bc", + "type": "contract_event" + } + ], + "index_block_hash": "0xacf821a2df6700046a2e2cd8042b394bcae4d62aadd3e940597658ece9852c30", + "matured_miner_rewards": [], + "miner_signature": "0x01b2d4622b2e17c65e93c232f8009af1b143ceac0d7746a76db252db7fe8618c1d59fc3d24285aaf3360e207b498749e70d86a2df6146a3dd96a204ca7fa388a78", + "miner_txid": "0x5349bb3131e563b1daae3f5abadcb250d5f1a985177ebf11068d5e1dc8266629", + "parent_block_hash": "0x9d1dc0ff0fae7648ddaa0fdd30fcf5e4f5c587f172959a2e602d678e6f08cae0", + "parent_burn_block_hash": "0x15e7d138f2b0b155418f588b7c193eae38f7943a83b4aa1af17aebec6f0e364f", + "parent_burn_block_height": 136, + "parent_burn_block_timestamp": 1725050720, + "parent_index_block_hash": "0x1d8063dcc9061138bbcd89f5eab10dedf970526af50bedef542bba592228db74", + "parent_microblock": "0x0000000000000000000000000000000000000000000000000000000000000000", + "parent_microblock_sequence": 0, + "pox_v1_unlock_height": 104, + "pox_v2_unlock_height": 106, + "pox_v3_unlock_height": 109, + "reward_set": null, + "signer_bitvec": "000800000001ff", + "signer_signature": [ + "0075708c545456ad085204a87ae0b22229c53aaf325e84e1e52e99bed4c74b727a540dbafecbec69179af3201a881d250bd45b67bc8ada7b008f50e811d49159d4", + "01d620ebcfc4a18b781369ad9f996e87ecaa617852a3b92c420c633627c88da9e97058e896290df6ddd0070f8838970c39e46d756690017fe24545252cf7078b28", + "002cee5b1219127b8784d2c973ffa6de044bd5636c1b3a3db08b701c17ab6875ad394e3ea55e37d46db5292fb61e52744d1420c38ac910b6b92691c0091c2adbf2" + ], + "signer_signature_hash": "0x6bf165f5a1930cca370cf28158d6d86c9ed8103a6066de6138f5fff0c7835590", + "transactions": [ + { + "burnchain_op": null, + "contract_abi": null, + "execution_cost": { + "read_count": 28, + "read_length": 42790, + "runtime": 80123, + "write_count": 3, + "write_length": 139 + }, + "microblock_hash": null, + "microblock_parent_hash": null, + "microblock_sequence": null, + "raw_result": "0x070703", + "raw_tx": "0x80800000000405b67e6a475c7001d2d1f8589527f8357f0c1394440000000000000005000000000001e07800000003020005426366ae35702fbe63153afa0548b74b67ec94b8c356ed603bccc5e83a05445bd1bbb13703fad948f16443ca2a5c632ac642713f4d15d3964a230118701b38020144f48d62736cbe730394468f8f9ad1e482d5e4f091b98b581a88d1163b3ed8c02f2ae726627c5c8f090e3ac7eaa86d38df46d5891eef92449ddff22dfb2bb97b0200652613e261d9be17a6c690c53cf90a81d005eff00c46f43c07bd6806723d45ed4a258f4eab6393f5136c789d96864875f28e8dbeadf6db2446587648f1b7b0f400020301000000000215b67e6a475c7001d2d1f8589527f8357f0c1394440c736274632d6465706f73697418636f6d706c6574652d6465706f7369742d77726170706572000000040200000020000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000ffffffff01000000000000000000000000075ed2850515b67e6a475c7001d2d1f8589527f8357f0c139444", + "status": "success", + "tx_index": 0, + "txid": "0x58a9074c3299c2f627829b7e5ecf8b7136e380cbce3900461c679939925f77bc" + }, + { + "burnchain_op": null, + "contract_abi": null, + "execution_cost": { + "read_count": 0, + "read_length": 0, + "runtime": 0, + "write_count": 0, + "write_length": 0 + }, + "microblock_hash": null, + "microblock_parent_hash": null, + "microblock_sequence": null, + "raw_result": "0x0703", + "raw_tx": "0x8080000000040062b0e91cc557e583c3d1f9dfe468ace76d2f03740000000000000041000000000000012c0001f85034c2bf767a4211b295c864527c380b1260741d5368baf8abbf4b4ad8c0c15433af07aa4b24adfca8525fb2ffacfa596eb380e5db4f30d36a417a984da96703020000000000051a93b082ee51d78faf5cc3d84a1c1591246c4965b000000000000003e800000000000000000000000000000000000000000000000000000000000000000000", + "status": "success", + "tx_index": 1, + "txid": "0xf7dea34b0473d7cbb3aebae49a93507dda58e18435e8c496e90253bf07fda3a8" + } + ] +} \ No newline at end of file diff --git a/emily/handler/tests/fixtures/create-deposit-valid-2.json b/emily/handler/tests/fixtures/create-deposit-valid-2.json deleted file mode 100644 index e6886e8c8..000000000 --- a/emily/handler/tests/fixtures/create-deposit-valid-2.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "bitcoinTxid": "48ac9b013437e950ac6a90e0b0f205c40eead9df24c785cab4a88538d17a5e92", - "bitcoinTxOutputIndex": 0, - "reclaimScript": "5cb2752080e5d9a5a66f464ffc7c58dcd7211b0d924cb44d3f391d9feca1f8ae81e6c3f7ac", - "depositScript": "1e00000000000138800516f1e0a0b10611aaf496863cff80ead8001a88750b7520f898f8a6ddb86dd4608dd168355ec6135fe2839222240c01942e8e7e50dd4c89ac", - "transactionHex": "02000000000101e73f8303166d875e30c3be7e51e1d8c6c930233ad124b41116baedd67690e5320e00000000000000000240420f0000000000225120b7619d3399c7b00527411f617db7c14eb9b489795916bd3744f2f0a59f5563dd96572d020000000016001459d441589772f921f615ddc25fbf734e8b8a360802483045022100ed1f5e848b9676f3e53dd4d58682691b0b901f33d5d73b86d0fe2877172d7ece02205ec929ce064ec5366f740961ce684865575128f5a27f9a5ffd485058e4d51a6b01210380e5d9a5a66f464ffc7c58dcd7211b0d924cb44d3f391d9feca1f8ae81e6c3f700000000" -} \ No newline at end of file diff --git a/signer/tests/fixtures/completed-deposit-event.json b/signer/tests/fixtures/completed-deposit-event.json index 417d25c0b..10041b665 100644 --- a/signer/tests/fixtures/completed-deposit-event.json +++ b/signer/tests/fixtures/completed-deposit-event.json @@ -30,50 +30,50 @@ "Tuple": { "data_map": { "amount": { - "UInt": 1000000 + "UInt": 123654789 }, "bitcoin-txid": { "Sequence": { "Buffer": { "data": [ - 247, - 92, - 184, - 105, - 96, - 12, - 106, - 117, - 171, - 144, - 200, - 114, - 67, - 93, - 163, - 141, - 84, - 213, - 60, - 39, - 175, - 229, - 224, - 58, - 199, - 222, - 218, - 231, - 130, - 41, - 88, - 222 + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 ] } } }, "output-index": { - "UInt": 0 + "UInt": 4294967295 }, "burn-hash": { "Sequence": { diff --git a/signer/tests/integration/stacks_events_observer.rs b/signer/tests/integration/stacks_events_observer.rs index 1e614d62c..d764aa36a 100644 --- a/signer/tests/integration/stacks_events_observer.rs +++ b/signer/tests/integration/stacks_events_observer.rs @@ -58,8 +58,8 @@ async fn test_context() -> TestContext< const CREATE_DEPOSIT_VALID: &str = include_str!("../../../emily/handler/tests/fixtures/create-deposit-valid.json"); -const COMPLETED_DEPOSIT_WEBHOOK: &str = - include_str!("../../tests/fixtures/completed-deposit-event.json"); +const COMPLETED_VALID_DEPOSIT_WEBHOOK: &str = + include_str!("../../../emily/handler/tests/fixtures/completed-valid-deposit-event.json"); const WITHDRAWAL_ACCEPT_WEBHOOK: &str = include_str!("../../tests/fixtures/withdrawal-accept-event.json"); @@ -110,7 +110,7 @@ async fn test_new_blocks_sends_update_deposits_to_emily() { .await .expect("Wiping Emily database in test setup failed."); - let body = COMPLETED_DEPOSIT_WEBHOOK.to_string(); + let body = COMPLETED_VALID_DEPOSIT_WEBHOOK.to_string(); let deposit_completed_event = get_registry_event_from_webhook(&body, |event| match event { RegistryEvent::CompletedDeposit(event) => Some(event), _ => panic!("Expected CompletedDeposit event"), From e5fccfa950d6e1bc94c9509f7bccd8b86848da53 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 20 Jan 2025 15:49:52 +0000 Subject: [PATCH 06/17] update as_emily_request to serialize raw tx --- signer/src/testing/btc.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/signer/src/testing/btc.rs b/signer/src/testing/btc.rs index 5d00ed3e8..003860a46 100644 --- a/signer/src/testing/btc.rs +++ b/signer/src/testing/btc.rs @@ -1,5 +1,6 @@ //! Helper functions for the bitcoin module //! +use bitcoin::consensus::encode::serialize_hex; use bitcoin::Amount; use bitcoin::OutPoint; use bitcoin::ScriptBuf; @@ -47,12 +48,13 @@ pub fn base_signer_transaction() -> Transaction { impl utxo::DepositRequest { /// Transform this deposit request into the body that Emily expects. - pub fn as_emily_request(&self) -> CreateDepositRequestBody { + pub fn as_emily_request(&self, tx: &Transaction) -> CreateDepositRequestBody { CreateDepositRequestBody { bitcoin_tx_output_index: self.outpoint.vout, bitcoin_txid: self.outpoint.txid.to_string(), deposit_script: self.deposit_script.to_hex_string(), reclaim_script: self.reclaim_script.to_hex_string(), + transaction_hex: serialize_hex(tx), } } } From 514ec6dc673f5f48f5bf0097f72c4a349c62a93e Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 20 Jan 2025 17:16:03 +0000 Subject: [PATCH 07/17] add is_mainnet param --- emily/README.md | 1 + emily/cdk/lib/emily-stack.ts | 15 ++--- emily/cdk/test/emily-stack.test.ts | 3 +- emily/handler/src/api/handlers/deposit.rs | 2 +- .../src/api/models/deposit/requests.rs | 12 ++-- emily/handler/src/context.rs | 4 ++ ...n => completed-deposit-testnet-event.json} | 60 +++++++++---------- .../create-deposit-valid-testnet.json | 7 +++ sbtc/src/deposits.rs | 6 +- .../integration/stacks_events_observer.rs | 4 +- .../integration/transaction_coordinator.rs | 2 +- 11 files changed, 65 insertions(+), 51 deletions(-) rename emily/handler/tests/fixtures/{completed-valid-deposit-event.json => completed-deposit-testnet-event.json} (90%) create mode 100644 emily/handler/tests/fixtures/create-deposit-valid-testnet.json diff --git a/emily/README.md b/emily/README.md index 222c3eb27..41f30bb51 100644 --- a/emily/README.md +++ b/emily/README.md @@ -38,6 +38,7 @@ environment: { LIMIT_TABLE_NAME: limitTableName, IS_LOCAL: "true" | "false", TRUSTED_REORG_API_KEY: trustedReorgApiKey, + IS_MAINNET: "true" | "false", }, ``` diff --git a/emily/cdk/lib/emily-stack.ts b/emily/cdk/lib/emily-stack.ts index 7d3963e68..d9d52a15f 100644 --- a/emily/cdk/lib/emily-stack.ts +++ b/emily/cdk/lib/emily-stack.ts @@ -140,11 +140,11 @@ export class EmilyStack extends cdk.Stack { indexName: byStatusIndexName, partitionKey: { name: 'OpStatus', - type: dynamodb.AttributeType.STRING + type: dynamodb.AttributeType.STRING }, sortKey: { name: 'LastUpdateHeight', - type: dynamodb.AttributeType.NUMBER + type: dynamodb.AttributeType.NUMBER }, projectionType: dynamodb.ProjectionType.INCLUDE, nonKeyAttributes: [ @@ -163,11 +163,11 @@ export class EmilyStack extends cdk.Stack { indexName: byRecipientIndexName, partitionKey: { name: 'Recipient', - type: dynamodb.AttributeType.STRING + type: dynamodb.AttributeType.STRING }, sortKey: { name: 'LastUpdateHeight', - type: dynamodb.AttributeType.NUMBER + type: dynamodb.AttributeType.NUMBER }, projectionType: dynamodb.ProjectionType.INCLUDE, nonKeyAttributes: [ @@ -220,11 +220,11 @@ export class EmilyStack extends cdk.Stack { indexName: indexName, partitionKey: { name: 'OpStatus', - type: dynamodb.AttributeType.STRING + type: dynamodb.AttributeType.STRING }, sortKey: { name: 'LastUpdateHeight', - type: dynamodb.AttributeType.NUMBER + type: dynamodb.AttributeType.NUMBER }, projectionType: dynamodb.ProjectionType.INCLUDE, nonKeyAttributes: [ @@ -316,7 +316,7 @@ export class EmilyStack extends cdk.Stack { chainstateTableName: string, limitTableName: string, removalPolicy: cdk.RemovalPolicy, - props: EmilyStackProps + props: EmilyStackProps, ): lambda.Function { const operationLambdaId: string = "OperationLambda"; @@ -343,6 +343,7 @@ export class EmilyStack extends cdk.Stack { // already expected to be present in the lambda. IS_LOCAL: "false", TRUSTED_REORG_API_KEY: props.trustedReorgApiKey, + IS_MAINNET: props.stageName == Constants.PROD_STAGE_NAME ? "true" : "false", }, description: `Emily Api Handler. ${EmilyStackUtils.getLambdaGitIdentifier()}`, currentVersionOptions: { diff --git a/emily/cdk/test/emily-stack.test.ts b/emily/cdk/test/emily-stack.test.ts index a36a6a957..eb1716486 100644 --- a/emily/cdk/test/emily-stack.test.ts +++ b/emily/cdk/test/emily-stack.test.ts @@ -49,7 +49,7 @@ describe('EmilyStack Test', () => { // TODO(TBD): Add check for properties linking resources created during cdk build. Handler: "main", Runtime: "provided.al2023", - Architectures: [ "x86_64" ], + Architectures: ["x86_64"], Timeout: 5, }); @@ -64,6 +64,7 @@ describe('EmilyStack Test', () => { expect(environment.LIMIT_TABLE_NAME).toMatch(`LimitTable-account-region-${Constants.UNIT_TEST_STAGE_NAME}`); expect(environment.TRUSTED_REORG_API_KEY).toEqual("testApiKey"); expect(environment.IS_LOCAL).toEqual("false"); + expect(environment.IS_MAINNET).toEqual("false"); }); }); diff --git a/emily/handler/src/api/handlers/deposit.rs b/emily/handler/src/api/handlers/deposit.rs index 8eb467cf1..c956136a8 100644 --- a/emily/handler/src/api/handlers/deposit.rs +++ b/emily/handler/src/api/handlers/deposit.rs @@ -300,7 +300,7 @@ pub async fn create_deposit( } let limits = accessors::get_limits(&context).await?; - let deposit_info = body.validate(&limits)?; + let deposit_info = body.validate(&limits, context.settings.is_mainnet)?; // Make table entry. let deposit_entry: DepositEntry = DepositEntry { diff --git a/emily/handler/src/api/models/deposit/requests.rs b/emily/handler/src/api/models/deposit/requests.rs index d14116451..9bf4b9edc 100644 --- a/emily/handler/src/api/models/deposit/requests.rs +++ b/emily/handler/src/api/models/deposit/requests.rs @@ -85,7 +85,7 @@ impl CreateDepositRequestBody { /// Validates that the deposit request is valid. /// This includes validating the request fields, if their content matches the transaction /// and if the amount is within the limits. - pub fn validate(&self, limits: &Limits) -> Result { + pub fn validate(&self, limits: &Limits, is_mainnet: bool) -> Result { let deposit_req = CreateDepositRequest { outpoint: OutPoint { txid: parse_hex(&self.bitcoin_txid, "invalid bitcoin_txid", Txid::from_str)?, @@ -138,7 +138,7 @@ impl CreateDepositRequestBody { } deposit_req - .validate_tx(&tx) + .validate_tx(&tx, is_mainnet) .map_err(|e| Error::HttpRequest(StatusCode::BAD_REQUEST, e.to_string())) } } @@ -230,7 +230,7 @@ mod tests { async fn test_deposit_validate_happy_path() { let deposit_request = helpers::parse_request(CREATE_DEPOSIT_VALID); let limits = helpers::create_test_limits(None, None); - assert!(deposit_request.validate(&limits).is_ok()); + assert!(deposit_request.validate(&limits, true).is_ok()); } #[test_case(CREATE_DEPOSIT_INVALID_TXID, "invalid bitcoin_txid"; "invalid_txid")] @@ -252,7 +252,7 @@ mod tests { let deposit_request = helpers::parse_request(input); let limits = helpers::create_test_limits(Some(DEPOSIT_DUST_LIMIT), None); - let result = deposit_request.validate(&limits); + let result = deposit_request.validate(&limits, true); assert_eq!( result.unwrap_err().to_string(), format!("HTTP request failed with status code 400 Bad Request: {expected_error}") @@ -268,7 +268,7 @@ mod tests { async fn test_deposit_validate_limits(input: &str, min: Option, max: Option) { let deposit_request = helpers::parse_request(input); let limits = helpers::create_test_limits(min, max); - assert!(deposit_request.validate(&limits).is_ok()); + assert!(deposit_request.validate(&limits, true).is_ok()); } #[test_case(CREATE_DEPOSIT_VALID, Some(1_000_000 + 1), None, "deposit amount below minimum (1000001)"; "below_min_limit")] @@ -283,7 +283,7 @@ mod tests { let deposit_request = helpers::parse_request(input); let limits = helpers::create_test_limits(min, max); - let result = deposit_request.validate(&limits); + let result = deposit_request.validate(&limits, true); assert_eq!( result.unwrap_err().to_string(), diff --git a/emily/handler/src/context.rs b/emily/handler/src/context.rs index 120f3de63..8ea591238 100644 --- a/emily/handler/src/context.rs +++ b/emily/handler/src/context.rs @@ -33,6 +33,8 @@ pub struct Settings { pub default_limits: AccountLimits, /// The API key for the Bitcoin Layer 2 API. pub trusted_reorg_api_key: String, + /// Whether the lambda is expecting transactions on mainnet. + pub is_mainnet: bool, } /// Emily Context @@ -88,6 +90,7 @@ impl Settings { .transpose()?, }, trusted_reorg_api_key: env::var("TRUSTED_REORG_API_KEY")?, + is_mainnet: env::var("IS_MAINNET")?.to_lowercase() == "true", }) } } @@ -174,6 +177,7 @@ impl EmilyContext { .to_string(), default_limits: AccountLimits::default(), trusted_reorg_api_key: "testApiKey".to_string(), + is_mainnet: false, }, dynamodb_client, }) diff --git a/emily/handler/tests/fixtures/completed-valid-deposit-event.json b/emily/handler/tests/fixtures/completed-deposit-testnet-event.json similarity index 90% rename from emily/handler/tests/fixtures/completed-valid-deposit-event.json rename to emily/handler/tests/fixtures/completed-deposit-testnet-event.json index 417d25c0b..a27fe89b5 100644 --- a/emily/handler/tests/fixtures/completed-valid-deposit-event.json +++ b/emily/handler/tests/fixtures/completed-deposit-testnet-event.json @@ -36,38 +36,38 @@ "Sequence": { "Buffer": { "data": [ - 247, - 92, - 184, - 105, - 96, - 12, - 106, - 117, - 171, - 144, - 200, - 114, - 67, - 93, - 163, - 141, + 88, + 100, + 97, + 211, + 237, + 87, + 228, + 73, + 185, + 232, + 170, + 196, + 209, + 202, + 38, + 203, + 139, + 170, + 151, 84, - 213, - 60, - 39, - 175, + 79, + 129, + 255, 229, - 224, - 58, - 199, - 222, - 218, - 231, - 130, - 41, - 88, - 222 + 255, + 0, + 64, + 1, + 98, + 119, + 38, + 178 ] } } diff --git a/emily/handler/tests/fixtures/create-deposit-valid-testnet.json b/emily/handler/tests/fixtures/create-deposit-valid-testnet.json new file mode 100644 index 000000000..e61f26433 --- /dev/null +++ b/emily/handler/tests/fixtures/create-deposit-valid-testnet.json @@ -0,0 +1,7 @@ +{ + "bitcoinTxid": "586461d3ed57e449b9e8aac4d1ca26cb8baa97544f81ffe5ff004001627726b2", + "bitcoinTxOutputIndex": 0, + "reclaimScript": "5eb2", + "depositScript": "1e000000000000001e051a00000000000000000000000000000000000000007520a963eee67c254e482624e75538514111313356345d6c755973591f9e362a41acac", + "transactionHex": "020000000001000140420f0000000000225120b8319ec4b8a7609bbd47aef73fffe797c40468db652d2a32a52b145decfba37100000000" +} \ No newline at end of file diff --git a/sbtc/src/deposits.rs b/sbtc/src/deposits.rs index 592b475c7..2baf63cfb 100644 --- a/sbtc/src/deposits.rs +++ b/sbtc/src/deposits.rs @@ -863,12 +863,12 @@ mod tests { fn tx_validation_network(is_mainnet: bool) { let recipient = StacksAddress::burn_address(is_mainnet); let setup: TxSetup = - testing::deposits::tx_setup_with_recipient(150, 2500, 35000, recipient); + testing::deposits::tx_setup_with_recipient(150, 2500, &[35000], recipient); let request = CreateDepositRequest { outpoint: OutPoint::new(setup.tx.compute_txid(), 0), - reclaim_script: setup.reclaim.reclaim_script(), - deposit_script: setup.deposit.deposit_script(), + reclaim_script: setup.reclaims.first().unwrap().reclaim_script(), + deposit_script: setup.deposits.first().unwrap().deposit_script(), }; assert!(request.validate_tx(&setup.tx, is_mainnet).is_ok()); diff --git a/signer/tests/integration/stacks_events_observer.rs b/signer/tests/integration/stacks_events_observer.rs index d764aa36a..3be55a796 100644 --- a/signer/tests/integration/stacks_events_observer.rs +++ b/signer/tests/integration/stacks_events_observer.rs @@ -56,10 +56,10 @@ async fn test_context() -> TestContext< } const CREATE_DEPOSIT_VALID: &str = - include_str!("../../../emily/handler/tests/fixtures/create-deposit-valid.json"); + include_str!("../../../emily/handler/tests/fixtures/create-deposit-valid-testnet.json"); const COMPLETED_VALID_DEPOSIT_WEBHOOK: &str = - include_str!("../../../emily/handler/tests/fixtures/completed-valid-deposit-event.json"); + include_str!("../../../emily/handler/tests/fixtures/completed-deposit-testnet-event.json"); const WITHDRAWAL_ACCEPT_WEBHOOK: &str = include_str!("../../tests/fixtures/withdrawal-accept-event.json"); diff --git a/signer/tests/integration/transaction_coordinator.rs b/signer/tests/integration/transaction_coordinator.rs index 4b5193f02..3f8452687 100644 --- a/signer/tests/integration/transaction_coordinator.rs +++ b/signer/tests/integration/transaction_coordinator.rs @@ -1823,7 +1823,7 @@ async fn sign_bitcoin_transaction() { async fn sign_bitcoin_transaction_multiple_locking_keys() { let (_, signer_key_pairs): (_, [Keypair; 3]) = testing::wallet::regtest_bootstrap_wallet(); let (rpc, faucet) = regtest::initialize_blockchain(); - signer::logging::setup_logging("info,signer=debug", false); + // signer::logging::setup_logging("info,signer=debug", false); // We need to populate our databases, so let's fetch the data. let emily_client = From eaf8882d4458b66534ca7888402991dcee26264f Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 27 Jan 2025 13:10:15 +0000 Subject: [PATCH 08/17] encode recipient in hex --- emily/handler/src/api/handlers/deposit.rs | 3 ++- emily/handler/src/database/entries/deposit.rs | 6 +++--- emily/handler/tests/integration/deposit.rs | 5 ++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/emily/handler/src/api/handlers/deposit.rs b/emily/handler/src/api/handlers/deposit.rs index c956136a8..2e22a010f 100644 --- a/emily/handler/src/api/handlers/deposit.rs +++ b/emily/handler/src/api/handlers/deposit.rs @@ -23,6 +23,7 @@ use crate::database::entries::deposit::{ DepositEntry, DepositEntryKey, DepositEvent, DepositParametersEntry, ValidatedUpdateDepositsRequest, }; +use stacks_common::codec::StacksMessageCodec as _; use warp::http::StatusCode; /// Get deposit handler. @@ -308,7 +309,7 @@ pub async fn create_deposit( bitcoin_txid: body.bitcoin_txid, bitcoin_tx_output_index: body.bitcoin_tx_output_index, }, - recipient: deposit_info.recipient.to_string(), + recipient: hex::encode(deposit_info.recipient.serialize_to_vec()), parameters: DepositParametersEntry { max_fee: deposit_info.max_fee, lock_time: deposit_info.lock_time.to_consensus_u32(), diff --git a/emily/handler/src/database/entries/deposit.rs b/emily/handler/src/database/entries/deposit.rs index 8cfbe910a..3ea347dc0 100644 --- a/emily/handler/src/database/entries/deposit.rs +++ b/emily/handler/src/database/entries/deposit.rs @@ -42,7 +42,7 @@ pub struct DepositEntry { pub key: DepositEntryKey, /// Table entry version. Updated on each alteration. pub version: u64, - /// Stacks address to received the deposited sBTC. + /// Stacks address to received the deposited sBTC encoded in hex. pub recipient: String, /// Amount of BTC being deposited in satoshis. pub amount: u64, @@ -351,7 +351,7 @@ pub struct DepositInfoEntry { /// Primary index key data. #[serde(flatten)] pub primary_index_key: DepositEntryKey, - /// Stacks address to received the deposited sBTC. + /// Stacks address to received the deposited sBTC encoded in hex. pub recipient: String, /// Amount of BTC being deposited in satoshis. pub amount: u64, @@ -436,7 +436,7 @@ pub struct DepositInfoByRecipientEntrySearchToken { #[derive(Clone, Default, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] pub struct DepositInfoByRecipientEntryKey { - /// The recipient of the deposit. + /// The recipient of the deposit encoded in hex. pub recipient: String, /// The most recent Stacks block height the API was aware of when the deposit was last /// updated. If the most recent update is tied to an artifact on the Stacks blockchain diff --git a/emily/handler/tests/integration/deposit.rs b/emily/handler/tests/integration/deposit.rs index 527077ab3..7dda7be98 100644 --- a/emily/handler/tests/integration/deposit.rs +++ b/emily/handler/tests/integration/deposit.rs @@ -1,10 +1,9 @@ -use std::cmp::Ordering; -use std::collections::HashMap; - use bitcoin::consensus::encode::serialize_hex; use sbtc::testing; use sbtc::testing::deposits::TxSetup; use stacks_common::types::chainstate::StacksAddress; +use std::cmp::Ordering; +use std::collections::HashMap; use test_case::test_case; use testing_emily_client::models::{Fulfillment, Status, UpdateDepositsRequestBody}; use testing_emily_client::{ From 97948f90f396fc544e6e01228792a438c49d96c7 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 27 Jan 2025 16:29:42 +0000 Subject: [PATCH 09/17] fix recipient serialization --- emily/handler/tests/integration/deposit.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/emily/handler/tests/integration/deposit.rs b/emily/handler/tests/integration/deposit.rs index 7dda7be98..dab46645e 100644 --- a/emily/handler/tests/integration/deposit.rs +++ b/emily/handler/tests/integration/deposit.rs @@ -1,6 +1,7 @@ use bitcoin::consensus::encode::serialize_hex; use sbtc::testing; use sbtc::testing::deposits::TxSetup; +use stacks_common::codec::StacksMessageCodec as _; use stacks_common::types::chainstate::StacksAddress; use std::cmp::Ordering; use std::collections::HashMap; @@ -76,7 +77,7 @@ impl DepositTxnData { recipients: test_deposit_tx .deposits .iter() - .map(|d| hex::encode(d.recipient.to_string())) + .map(|d| hex::encode(d.recipient.serialize_to_vec())) .collect(), reclaim_scripts: test_deposit_tx .reclaims From 26a5f1164d1f049cf63e8ce6bbddff04b3b9edae Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Fri, 31 Jan 2025 15:09:04 +0000 Subject: [PATCH 10/17] add get_deposits_by_input_address endpoint --- .../emily/client/rust/private/README.md | 2 + .../emily/client/rust/private/docs/CorsApi.md | 33 +++- .../client/rust/private/docs/DepositApi.md | 33 +++- .../client/rust/private/src/apis/cors_api.rs | 49 ++++++ .../rust/private/src/apis/deposit_api.rs | 62 ++++++++ .../emily/client/rust/public/README.md | 2 + .../emily/client/rust/public/docs/CorsApi.md | 33 +++- .../client/rust/public/docs/DepositApi.md | 33 +++- .../client/rust/public/src/apis/cors_api.rs | 49 ++++++ .../rust/public/src/apis/deposit_api.rs | 62 ++++++++ .../emily/client/rust/testing/README.md | 2 + .../emily/client/rust/testing/docs/CorsApi.md | 33 +++- .../client/rust/testing/docs/DepositApi.md | 33 +++- .../client/rust/testing/src/apis/cors_api.rs | 49 ++++++ .../rust/testing/src/apis/deposit_api.rs | 62 ++++++++ emily/cdk/lib/emily-stack.ts | 24 +++ emily/handler/src/api/handlers/deposit.rs | 68 +++++++- .../src/api/models/deposit/requests.rs | 44 +++++- emily/handler/src/api/routes/deposit.rs | 15 +- emily/handler/src/database/accessors.rs | 21 ++- emily/handler/src/database/entries/deposit.rs | 110 +++++++++++++ emily/handler/tests/integration/deposit.rs | 146 ++++++++++++++++++ emily/openapi-gen/generators/private.rs | 1 + emily/openapi-gen/generators/public.rs | 1 + emily/openapi-gen/generators/testing.rs | 1 + sbtc/src/testing/deposits.rs | 43 +++++- 26 files changed, 989 insertions(+), 22 deletions(-) diff --git a/.generated-sources/emily/client/rust/private/README.md b/.generated-sources/emily/client/rust/private/README.md index 2a7f6ec1c..648cdb8a0 100644 --- a/.generated-sources/emily/client/rust/private/README.md +++ b/.generated-sources/emily/client/rust/private/README.md @@ -28,6 +28,7 @@ Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- *CorsApi* | [**chainstate_height_options**](docs/CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support *CorsApi* | [**chainstate_options**](docs/CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support +*CorsApi* | [**deposit_input_address_input_address_options**](docs/CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support *CorsApi* | [**deposit_options**](docs/CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support *CorsApi* | [**deposit_recipient_recipient_options**](docs/CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support *CorsApi* | [**deposit_txid_index_options**](docs/CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support @@ -44,6 +45,7 @@ Class | Method | HTTP request | Description *DepositApi* | [**create_deposit**](docs/DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. *DepositApi* | [**get_deposit**](docs/DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. *DepositApi* | [**get_deposits**](docs/DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. +*DepositApi* | [**get_deposits_for_input_address**](docs/DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_recipient**](docs/DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_transaction**](docs/DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. *DepositApi* | [**update_deposits**](docs/DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. diff --git a/.generated-sources/emily/client/rust/private/docs/CorsApi.md b/.generated-sources/emily/client/rust/private/docs/CorsApi.md index e7827a2e5..fe889844a 100644 --- a/.generated-sources/emily/client/rust/private/docs/CorsApi.md +++ b/.generated-sources/emily/client/rust/private/docs/CorsApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**chainstate_height_options**](CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support [**chainstate_options**](CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support +[**deposit_input_address_input_address_options**](CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support [**deposit_options**](CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support [**deposit_recipient_recipient_options**](CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support [**deposit_txid_index_options**](CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support @@ -75,6 +76,36 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +## deposit_input_address_input_address_options + +> deposit_input_address_input_address_options(input_address) +CORS support + +Handles CORS preflight requests + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**input_address** | **String** | the address from which the deposit was made. | [required] | + +### Return type + + (empty response body) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: Not defined + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + ## deposit_options > deposit_options() @@ -114,7 +145,7 @@ Handles CORS preflight requests Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the status to search by when getting all deposits. | [required] | +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | ### Return type diff --git a/.generated-sources/emily/client/rust/private/docs/DepositApi.md b/.generated-sources/emily/client/rust/private/docs/DepositApi.md index 7fede5df3..3c14b1d89 100644 --- a/.generated-sources/emily/client/rust/private/docs/DepositApi.md +++ b/.generated-sources/emily/client/rust/private/docs/DepositApi.md @@ -7,6 +7,7 @@ Method | HTTP request | Description [**create_deposit**](DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. [**get_deposit**](DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. [**get_deposits**](DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. +[**get_deposits_for_input_address**](DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. [**get_deposits_for_recipient**](DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. [**get_deposits_for_transaction**](DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. [**update_deposits**](DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. @@ -100,6 +101,36 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +## get_deposits_for_input_address + +> models::GetDepositsResponse get_deposits_for_input_address(input_address, next_token, page_size) +Get deposits by recipient handler. + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**input_address** | **String** | the address from which the deposit was made. | [required] | +**next_token** | Option<**String**> | the next token value from the previous return of this api call. | | +**page_size** | Option<**i32**> | the maximum number of items in the response list. | | + +### Return type + +[**models::GetDepositsResponse**](GetDepositsResponse.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + ## get_deposits_for_recipient > models::GetDepositsResponse get_deposits_for_recipient(recipient, next_token, page_size) @@ -110,7 +141,7 @@ Get deposits by recipient handler. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the status to search by when getting all deposits. | [required] | +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | **next_token** | Option<**String**> | the next token value from the previous return of this api call. | | **page_size** | Option<**i32**> | the maximum number of items in the response list. | | diff --git a/.generated-sources/emily/client/rust/private/src/apis/cors_api.rs b/.generated-sources/emily/client/rust/private/src/apis/cors_api.rs index 007940c22..b7fd9e8e6 100644 --- a/.generated-sources/emily/client/rust/private/src/apis/cors_api.rs +++ b/.generated-sources/emily/client/rust/private/src/apis/cors_api.rs @@ -27,6 +27,13 @@ pub enum ChainstateOptionsError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`deposit_input_address_input_address_options`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DepositInputAddressInputAddressOptionsError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`deposit_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -169,6 +176,48 @@ pub async fn chainstate_options( } } +/// Handles CORS preflight requests +pub async fn deposit_input_address_input_address_options( + configuration: &configuration::Configuration, + input_address: &str, +) -> Result<(), Error> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/deposit/input-address/{inputAddress}", + local_var_configuration.base_path, + inputAddress = crate::apis::urlencode(input_address) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + Ok(()) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + /// Handles CORS preflight requests pub async fn deposit_options( configuration: &configuration::Configuration, diff --git a/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs b/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs index 0d0f65e54..10af926cd 100644 --- a/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs +++ b/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs @@ -47,6 +47,17 @@ pub enum GetDepositsError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`get_deposits_for_input_address`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GetDepositsForInputAddressError { + Status400(models::ErrorResponse), + Status404(models::ErrorResponse), + Status405(models::ErrorResponse), + Status500(models::ErrorResponse), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`get_deposits_for_recipient`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -209,6 +220,57 @@ pub async fn get_deposits( } } +pub async fn get_deposits_for_input_address( + configuration: &configuration::Configuration, + input_address: &str, + next_token: Option<&str>, + page_size: Option, +) -> Result> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/deposit/input-address/{inputAddress}", + local_var_configuration.base_path, + inputAddress = crate::apis::urlencode(input_address) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_str) = next_token { + local_var_req_builder = + local_var_req_builder.query(&[("nextToken", &local_var_str.to_string())]); + } + if let Some(ref local_var_str) = page_size { + local_var_req_builder = + local_var_req_builder.query(&[("pageSize", &local_var_str.to_string())]); + } + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn get_deposits_for_recipient( configuration: &configuration::Configuration, recipient: &str, diff --git a/.generated-sources/emily/client/rust/public/README.md b/.generated-sources/emily/client/rust/public/README.md index 4c618e0de..458843628 100644 --- a/.generated-sources/emily/client/rust/public/README.md +++ b/.generated-sources/emily/client/rust/public/README.md @@ -28,6 +28,7 @@ Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- *CorsApi* | [**chainstate_height_options**](docs/CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support *CorsApi* | [**chainstate_options**](docs/CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support +*CorsApi* | [**deposit_input_address_input_address_options**](docs/CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support *CorsApi* | [**deposit_options**](docs/CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support *CorsApi* | [**deposit_recipient_recipient_options**](docs/CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support *CorsApi* | [**deposit_txid_index_options**](docs/CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support @@ -44,6 +45,7 @@ Class | Method | HTTP request | Description *DepositApi* | [**create_deposit**](docs/DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. *DepositApi* | [**get_deposit**](docs/DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. *DepositApi* | [**get_deposits**](docs/DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. +*DepositApi* | [**get_deposits_for_input_address**](docs/DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_recipient**](docs/DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_transaction**](docs/DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. *DepositApi* | [**update_deposits**](docs/DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. diff --git a/.generated-sources/emily/client/rust/public/docs/CorsApi.md b/.generated-sources/emily/client/rust/public/docs/CorsApi.md index 08b3f86ce..a9303a3e3 100644 --- a/.generated-sources/emily/client/rust/public/docs/CorsApi.md +++ b/.generated-sources/emily/client/rust/public/docs/CorsApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**chainstate_height_options**](CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support [**chainstate_options**](CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support +[**deposit_input_address_input_address_options**](CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support [**deposit_options**](CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support [**deposit_recipient_recipient_options**](CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support [**deposit_txid_index_options**](CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support @@ -76,6 +77,36 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +## deposit_input_address_input_address_options + +> deposit_input_address_input_address_options(input_address) +CORS support + +Handles CORS preflight requests + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**input_address** | **String** | the address from which the deposit was made. | [required] | + +### Return type + + (empty response body) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: Not defined + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + ## deposit_options > deposit_options() @@ -115,7 +146,7 @@ Handles CORS preflight requests Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the status to search by when getting all deposits. | [required] | +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | ### Return type diff --git a/.generated-sources/emily/client/rust/public/docs/DepositApi.md b/.generated-sources/emily/client/rust/public/docs/DepositApi.md index 7fede5df3..3c14b1d89 100644 --- a/.generated-sources/emily/client/rust/public/docs/DepositApi.md +++ b/.generated-sources/emily/client/rust/public/docs/DepositApi.md @@ -7,6 +7,7 @@ Method | HTTP request | Description [**create_deposit**](DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. [**get_deposit**](DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. [**get_deposits**](DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. +[**get_deposits_for_input_address**](DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. [**get_deposits_for_recipient**](DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. [**get_deposits_for_transaction**](DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. [**update_deposits**](DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. @@ -100,6 +101,36 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +## get_deposits_for_input_address + +> models::GetDepositsResponse get_deposits_for_input_address(input_address, next_token, page_size) +Get deposits by recipient handler. + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**input_address** | **String** | the address from which the deposit was made. | [required] | +**next_token** | Option<**String**> | the next token value from the previous return of this api call. | | +**page_size** | Option<**i32**> | the maximum number of items in the response list. | | + +### Return type + +[**models::GetDepositsResponse**](GetDepositsResponse.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + ## get_deposits_for_recipient > models::GetDepositsResponse get_deposits_for_recipient(recipient, next_token, page_size) @@ -110,7 +141,7 @@ Get deposits by recipient handler. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the status to search by when getting all deposits. | [required] | +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | **next_token** | Option<**String**> | the next token value from the previous return of this api call. | | **page_size** | Option<**i32**> | the maximum number of items in the response list. | | diff --git a/.generated-sources/emily/client/rust/public/src/apis/cors_api.rs b/.generated-sources/emily/client/rust/public/src/apis/cors_api.rs index f3ce0bacd..5515494c7 100644 --- a/.generated-sources/emily/client/rust/public/src/apis/cors_api.rs +++ b/.generated-sources/emily/client/rust/public/src/apis/cors_api.rs @@ -27,6 +27,13 @@ pub enum ChainstateOptionsError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`deposit_input_address_input_address_options`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DepositInputAddressInputAddressOptionsError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`deposit_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -176,6 +183,48 @@ pub async fn chainstate_options( } } +/// Handles CORS preflight requests +pub async fn deposit_input_address_input_address_options( + configuration: &configuration::Configuration, + input_address: &str, +) -> Result<(), Error> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/deposit/input-address/{inputAddress}", + local_var_configuration.base_path, + inputAddress = crate::apis::urlencode(input_address) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + Ok(()) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + /// Handles CORS preflight requests pub async fn deposit_options( configuration: &configuration::Configuration, diff --git a/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs b/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs index 0d0f65e54..10af926cd 100644 --- a/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs +++ b/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs @@ -47,6 +47,17 @@ pub enum GetDepositsError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`get_deposits_for_input_address`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GetDepositsForInputAddressError { + Status400(models::ErrorResponse), + Status404(models::ErrorResponse), + Status405(models::ErrorResponse), + Status500(models::ErrorResponse), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`get_deposits_for_recipient`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -209,6 +220,57 @@ pub async fn get_deposits( } } +pub async fn get_deposits_for_input_address( + configuration: &configuration::Configuration, + input_address: &str, + next_token: Option<&str>, + page_size: Option, +) -> Result> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/deposit/input-address/{inputAddress}", + local_var_configuration.base_path, + inputAddress = crate::apis::urlencode(input_address) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_str) = next_token { + local_var_req_builder = + local_var_req_builder.query(&[("nextToken", &local_var_str.to_string())]); + } + if let Some(ref local_var_str) = page_size { + local_var_req_builder = + local_var_req_builder.query(&[("pageSize", &local_var_str.to_string())]); + } + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn get_deposits_for_recipient( configuration: &configuration::Configuration, recipient: &str, diff --git a/.generated-sources/emily/client/rust/testing/README.md b/.generated-sources/emily/client/rust/testing/README.md index a36a365a2..11e9d04f6 100644 --- a/.generated-sources/emily/client/rust/testing/README.md +++ b/.generated-sources/emily/client/rust/testing/README.md @@ -28,6 +28,7 @@ Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- *CorsApi* | [**chainstate_height_options**](docs/CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support *CorsApi* | [**chainstate_options**](docs/CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support +*CorsApi* | [**deposit_input_address_input_address_options**](docs/CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support *CorsApi* | [**deposit_options**](docs/CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support *CorsApi* | [**deposit_recipient_recipient_options**](docs/CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support *CorsApi* | [**deposit_txid_index_options**](docs/CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support @@ -45,6 +46,7 @@ Class | Method | HTTP request | Description *DepositApi* | [**create_deposit**](docs/DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. *DepositApi* | [**get_deposit**](docs/DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. *DepositApi* | [**get_deposits**](docs/DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. +*DepositApi* | [**get_deposits_for_input_address**](docs/DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_recipient**](docs/DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_transaction**](docs/DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. *DepositApi* | [**update_deposits**](docs/DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. diff --git a/.generated-sources/emily/client/rust/testing/docs/CorsApi.md b/.generated-sources/emily/client/rust/testing/docs/CorsApi.md index 08b3f86ce..a9303a3e3 100644 --- a/.generated-sources/emily/client/rust/testing/docs/CorsApi.md +++ b/.generated-sources/emily/client/rust/testing/docs/CorsApi.md @@ -6,6 +6,7 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**chainstate_height_options**](CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support [**chainstate_options**](CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support +[**deposit_input_address_input_address_options**](CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support [**deposit_options**](CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support [**deposit_recipient_recipient_options**](CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support [**deposit_txid_index_options**](CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support @@ -76,6 +77,36 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +## deposit_input_address_input_address_options + +> deposit_input_address_input_address_options(input_address) +CORS support + +Handles CORS preflight requests + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**input_address** | **String** | the address from which the deposit was made. | [required] | + +### Return type + + (empty response body) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: Not defined + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + ## deposit_options > deposit_options() @@ -115,7 +146,7 @@ Handles CORS preflight requests Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the status to search by when getting all deposits. | [required] | +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | ### Return type diff --git a/.generated-sources/emily/client/rust/testing/docs/DepositApi.md b/.generated-sources/emily/client/rust/testing/docs/DepositApi.md index 7fede5df3..3c14b1d89 100644 --- a/.generated-sources/emily/client/rust/testing/docs/DepositApi.md +++ b/.generated-sources/emily/client/rust/testing/docs/DepositApi.md @@ -7,6 +7,7 @@ Method | HTTP request | Description [**create_deposit**](DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. [**get_deposit**](DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. [**get_deposits**](DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. +[**get_deposits_for_input_address**](DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. [**get_deposits_for_recipient**](DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. [**get_deposits_for_transaction**](DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. [**update_deposits**](DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. @@ -100,6 +101,36 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) +## get_deposits_for_input_address + +> models::GetDepositsResponse get_deposits_for_input_address(input_address, next_token, page_size) +Get deposits by recipient handler. + +### Parameters + + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**input_address** | **String** | the address from which the deposit was made. | [required] | +**next_token** | Option<**String**> | the next token value from the previous return of this api call. | | +**page_size** | Option<**i32**> | the maximum number of items in the response list. | | + +### Return type + +[**models::GetDepositsResponse**](GetDepositsResponse.md) + +### Authorization + +No authorization required + +### HTTP request headers + +- **Content-Type**: Not defined +- **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + + ## get_deposits_for_recipient > models::GetDepositsResponse get_deposits_for_recipient(recipient, next_token, page_size) @@ -110,7 +141,7 @@ Get deposits by recipient handler. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the status to search by when getting all deposits. | [required] | +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | **next_token** | Option<**String**> | the next token value from the previous return of this api call. | | **page_size** | Option<**i32**> | the maximum number of items in the response list. | | diff --git a/.generated-sources/emily/client/rust/testing/src/apis/cors_api.rs b/.generated-sources/emily/client/rust/testing/src/apis/cors_api.rs index f3ce0bacd..5515494c7 100644 --- a/.generated-sources/emily/client/rust/testing/src/apis/cors_api.rs +++ b/.generated-sources/emily/client/rust/testing/src/apis/cors_api.rs @@ -27,6 +27,13 @@ pub enum ChainstateOptionsError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`deposit_input_address_input_address_options`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum DepositInputAddressInputAddressOptionsError { + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`deposit_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -176,6 +183,48 @@ pub async fn chainstate_options( } } +/// Handles CORS preflight requests +pub async fn deposit_input_address_input_address_options( + configuration: &configuration::Configuration, + input_address: &str, +) -> Result<(), Error> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/deposit/input-address/{inputAddress}", + local_var_configuration.base_path, + inputAddress = crate::apis::urlencode(input_address) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); + + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + Ok(()) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + /// Handles CORS preflight requests pub async fn deposit_options( configuration: &configuration::Configuration, diff --git a/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs b/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs index 0d0f65e54..10af926cd 100644 --- a/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs +++ b/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs @@ -47,6 +47,17 @@ pub enum GetDepositsError { UnknownValue(serde_json::Value), } +/// struct for typed errors of method [`get_deposits_for_input_address`] +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(untagged)] +pub enum GetDepositsForInputAddressError { + Status400(models::ErrorResponse), + Status404(models::ErrorResponse), + Status405(models::ErrorResponse), + Status500(models::ErrorResponse), + UnknownValue(serde_json::Value), +} + /// struct for typed errors of method [`get_deposits_for_recipient`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] @@ -209,6 +220,57 @@ pub async fn get_deposits( } } +pub async fn get_deposits_for_input_address( + configuration: &configuration::Configuration, + input_address: &str, + next_token: Option<&str>, + page_size: Option, +) -> Result> { + let local_var_configuration = configuration; + + let local_var_client = &local_var_configuration.client; + + let local_var_uri_str = format!( + "{}/deposit/input-address/{inputAddress}", + local_var_configuration.base_path, + inputAddress = crate::apis::urlencode(input_address) + ); + let mut local_var_req_builder = + local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); + + if let Some(ref local_var_str) = next_token { + local_var_req_builder = + local_var_req_builder.query(&[("nextToken", &local_var_str.to_string())]); + } + if let Some(ref local_var_str) = page_size { + local_var_req_builder = + local_var_req_builder.query(&[("pageSize", &local_var_str.to_string())]); + } + if let Some(ref local_var_user_agent) = local_var_configuration.user_agent { + local_var_req_builder = + local_var_req_builder.header(reqwest::header::USER_AGENT, local_var_user_agent.clone()); + } + + let local_var_req = local_var_req_builder.build()?; + let local_var_resp = local_var_client.execute(local_var_req).await?; + + let local_var_status = local_var_resp.status(); + let local_var_content = local_var_resp.text().await?; + + if !local_var_status.is_client_error() && !local_var_status.is_server_error() { + serde_json::from_str(&local_var_content).map_err(Error::from) + } else { + let local_var_entity: Option = + serde_json::from_str(&local_var_content).ok(); + let local_var_error = ResponseContent { + status: local_var_status, + content: local_var_content, + entity: local_var_entity, + }; + Err(Error::ResponseError(local_var_error)) + } +} + pub async fn get_deposits_for_recipient( configuration: &configuration::Configuration, recipient: &str, diff --git a/emily/cdk/lib/emily-stack.ts b/emily/cdk/lib/emily-stack.ts index 23e12d29e..167de251c 100644 --- a/emily/cdk/lib/emily-stack.ts +++ b/emily/cdk/lib/emily-stack.ts @@ -181,6 +181,30 @@ export class EmilyStack extends cdk.Stack { ] }); + // Index to efficiently query deposits that comes from a specific address + const byAddressIndexName: string = "DepositInputAddressIndex"; + table.addGlobalSecondaryIndex({ + indexName: byAddressIndexName, + partitionKey: { + name: 'InputAddress', + type: dynamodb.AttributeType.STRING + }, + sortKey: { + name: 'LastUpdateHeight', + type: dynamodb.AttributeType.NUMBER + }, + projectionType: dynamodb.ProjectionType.INCLUDE, + nonKeyAttributes: [ + "BitcoinTxid", + "BitcoinTxOutputIndex", + "Recipient", + "OpStatus", + "Amount", + "LastUpdateBlockHash", + "ReclaimScript", + "DepositScript", + ] + }); // TODO(388): Add an additional GSI for querying by user; not required for MVP. return table; } diff --git a/emily/handler/src/api/handlers/deposit.rs b/emily/handler/src/api/handlers/deposit.rs index 2e22a010f..ad65d9a6e 100644 --- a/emily/handler/src/api/handlers/deposit.rs +++ b/emily/handler/src/api/handlers/deposit.rs @@ -192,7 +192,7 @@ pub async fn get_deposits( operation_id = "getDepositsForRecipient", path = "/deposit/recipient/{recipient}", params( - ("recipient" = String, Path, description = "the status to search by when getting all deposits."), + ("recipient" = String, Path, description = "the recipient to search by when getting all deposits."), ("nextToken" = Option, Query, description = "the next token value from the previous return of this api call."), ("pageSize" = Option, Query, description = "the maximum number of items in the response list.") ), @@ -211,7 +211,7 @@ pub async fn get_deposits_for_recipient( recipient: String, query: BasicPaginationQuery, ) -> impl warp::reply::Reply { - debug!("In get deposits for recipient"); + debug!("in get deposits for recipient: {recipient}"); // Internal handler so `?` can be used correctly while still returning a reply. async fn handler( context: EmilyContext, @@ -238,6 +238,58 @@ pub async fn get_deposits_for_recipient( .map_or_else(Reply::into_response, Reply::into_response) } +/// Get deposits by recipient handler. +#[utoipa::path( + get, + operation_id = "getDepositsForInputAddress", + path = "/deposit/input-address/{inputAddress}", + params( + ("inputAddress" = String, Path, description = "the address from which the deposit was made."), + ("nextToken" = Option, Query, description = "the next token value from the previous return of this api call."), + ("pageSize" = Option, Query, description = "the maximum number of items in the response list.") + ), + tag = "deposit", + responses( + (status = 200, description = "Deposits retrieved successfully", body = GetDepositsResponse), + (status = 400, description = "Invalid request body", body = ErrorResponse), + (status = 404, description = "Address not found", body = ErrorResponse), + (status = 405, description = "Method not allowed", body = ErrorResponse), + (status = 500, description = "Internal server error", body = ErrorResponse) + ) +)] +#[instrument(skip(context))] +pub async fn get_deposits_for_input_address( + context: EmilyContext, + input_address: String, + query: BasicPaginationQuery, +) -> impl warp::reply::Reply { + debug!("in get deposits for input address: {input_address}"); + // Internal handler so `?` can be used correctly while still returning a reply. + async fn handler( + context: EmilyContext, + input_address: String, + query: BasicPaginationQuery, + ) -> Result { + let (entries, next_token) = accessors::get_deposit_entries_by_input_address( + &context, + &input_address, + query.next_token, + query.page_size, + ) + .await?; + // Convert data into resource types. + let deposits: Vec = entries.into_iter().map(|entry| entry.into()).collect(); + // Create response. + let response = GetDepositsResponse { deposits, next_token }; + // Respond. + Ok(with_status(json(&response), StatusCode::OK)) + } + // Handle and respond. + handler(context, input_address, query) + .await + .map_or_else(Reply::into_response, Reply::into_response) +} + /// Create deposit handler. #[utoipa::path( post, @@ -301,18 +353,17 @@ pub async fn create_deposit( } let limits = accessors::get_limits(&context).await?; - let deposit_info = body.validate(&limits, context.settings.is_mainnet)?; - + let deposit_data = body.validate(&limits, context.settings.is_mainnet)?; // Make table entry. let deposit_entry: DepositEntry = DepositEntry { key: DepositEntryKey { bitcoin_txid: body.bitcoin_txid, bitcoin_tx_output_index: body.bitcoin_tx_output_index, }, - recipient: hex::encode(deposit_info.recipient.serialize_to_vec()), + recipient: hex::encode(deposit_data.deposit_info.recipient.serialize_to_vec()), parameters: DepositParametersEntry { - max_fee: deposit_info.max_fee, - lock_time: deposit_info.lock_time.to_consensus_u32(), + max_fee: deposit_data.deposit_info.max_fee, + lock_time: deposit_data.deposit_info.lock_time.to_consensus_u32(), }, history: vec![DepositEvent { status: StatusEntry::Pending, @@ -323,9 +374,10 @@ pub async fn create_deposit( status: Status::Pending, last_update_block_hash: stacks_block_hash, last_update_height: stacks_block_height, - amount: deposit_info.amount, + amount: deposit_data.deposit_info.amount, reclaim_script: body.reclaim_script, deposit_script: body.deposit_script, + input_address: deposit_data.input_address.to_string(), ..Default::default() }; // Validate deposit entry. diff --git a/emily/handler/src/api/models/deposit/requests.rs b/emily/handler/src/api/models/deposit/requests.rs index 9bf4b9edc..a634ea60b 100644 --- a/emily/handler/src/api/models/deposit/requests.rs +++ b/emily/handler/src/api/models/deposit/requests.rs @@ -4,7 +4,8 @@ use std::str::FromStr; use bitcoin::blockdata::transaction::Transaction; use bitcoin::consensus::encode; -use bitcoin::{Amount, OutPoint, ScriptBuf, Txid}; +use bitcoin::params::Params; +use bitcoin::{Address, Amount, OutPoint, ScriptBuf, Txid}; use reqwest::StatusCode; use serde::{Deserialize, Serialize}; use utoipa::ToSchema; @@ -85,7 +86,11 @@ impl CreateDepositRequestBody { /// Validates that the deposit request is valid. /// This includes validating the request fields, if their content matches the transaction /// and if the amount is within the limits. - pub fn validate(&self, limits: &Limits, is_mainnet: bool) -> Result { + pub fn validate( + &self, + limits: &Limits, + is_mainnet: bool, + ) -> Result { let deposit_req = CreateDepositRequest { outpoint: OutPoint { txid: parse_hex(&self.bitcoin_txid, "invalid bitcoin_txid", Txid::from_str)?, @@ -137,12 +142,43 @@ impl CreateDepositRequestBody { )); } - deposit_req + let deposit_info = deposit_req .validate_tx(&tx, is_mainnet) - .map_err(|e| Error::HttpRequest(StatusCode::BAD_REQUEST, e.to_string())) + .map_err(|e| Error::HttpRequest(StatusCode::BAD_REQUEST, e.to_string()))?; + + let txin = tx.tx_in(0).map_err(|_| { + Error::HttpRequest( + StatusCode::BAD_REQUEST, + "invalid transaction input".to_string(), + ) + })?; + let input_address = { + let params = if is_mainnet { + Params::MAINNET + } else { + Params::REGTEST + }; + Address::from_script(&txin.script_sig, params.clone()).map_err(|e| { + Error::HttpRequest( + StatusCode::BAD_REQUEST, + "invalid transaction input address".to_string(), + ) + })? + }; + + Ok(ValidatedCreateDepositRequestData { deposit_info, input_address }) } } +/// Validated deposit request data. +#[derive(Debug)] +pub struct ValidatedCreateDepositRequestData { + /// Deposit information. + pub deposit_info: DepositInfo, + /// Input address of the first input in the transaction. + pub input_address: Address, +} + /// A singlular Deposit update that contains only the fields pertinent /// to updating the status of a deposit. This includes the key related /// data in addition to status history related data. diff --git a/emily/handler/src/api/routes/deposit.rs b/emily/handler/src/api/routes/deposit.rs index 856e1327a..754dcb5f4 100644 --- a/emily/handler/src/api/routes/deposit.rs +++ b/emily/handler/src/api/routes/deposit.rs @@ -13,6 +13,7 @@ pub fn routes( .or(get_deposits_for_transaction(context.clone())) .or(get_deposits(context.clone())) .or(get_deposits_for_recipient(context.clone())) + .or(get_deposits_for_input_address(context.clone())) .or(create_deposit(context.clone())) .or(update_deposits(context)) } @@ -52,7 +53,7 @@ fn get_deposits( .then(handlers::deposit::get_deposits) } -/// Get deposits endpoint. +/// Get deposits for recipient endpoint. fn get_deposits_for_recipient( context: EmilyContext, ) -> impl Filter + Clone { @@ -64,6 +65,18 @@ fn get_deposits_for_recipient( .then(handlers::deposit::get_deposits_for_recipient) } +/// Get deposits for input address endpoint. +fn get_deposits_for_input_address( + context: EmilyContext, +) -> impl Filter + Clone { + warp::any() + .map(move || context.clone()) + .and(warp::path!("deposit" / "input-address" / String)) + .and(warp::get()) + .and(warp::query()) + .then(handlers::deposit::get_deposits_for_input_address) +} + /// Create deposit endpoint. fn create_deposit( context: EmilyContext, diff --git a/emily/handler/src/database/accessors.rs b/emily/handler/src/database/accessors.rs index 2f626f532..27581b4c2 100644 --- a/emily/handler/src/database/accessors.rs +++ b/emily/handler/src/database/accessors.rs @@ -13,7 +13,9 @@ use crate::common::error::{Error, Inconsistency}; use crate::{api::models::common::Status, context::EmilyContext}; use super::entries::deposit::{ - DepositInfoByRecipientEntry, DepositTableByRecipientSecondaryIndex, ValidatedDepositUpdate, + DepositInfoByInputAddressEntry, DepositInfoByRecipientEntry, + DepositTableByInputAddressSecondaryIndex, DepositTableByRecipientSecondaryIndex, + ValidatedDepositUpdate, }; use super::entries::limits::{ LimitEntry, LimitEntryKey, LimitTablePrimaryIndex, GLOBAL_CAP_ACCOUNT, @@ -96,6 +98,23 @@ pub async fn get_deposit_entries_by_recipient( .await } +/// Get deposit entries by input address. +#[allow(clippy::ptr_arg)] +pub async fn get_deposit_entries_by_input_address( + context: &EmilyContext, + input_address: &String, + maybe_next_token: Option, + maybe_page_size: Option, +) -> Result<(Vec, Option), Error> { + query_with_partition_key::( + context, + input_address, + maybe_next_token, + maybe_page_size, + ) + .await +} + /// Hacky exhasutive list of all statuses that we will iterate over in order to /// get every deposit present. const ALL_STATUSES: &[Status] = &[ diff --git a/emily/handler/src/database/entries/deposit.rs b/emily/handler/src/database/entries/deposit.rs index 3ea347dc0..3fbe8689a 100644 --- a/emily/handler/src/database/entries/deposit.rs +++ b/emily/handler/src/database/entries/deposit.rs @@ -69,6 +69,8 @@ pub struct DepositEntry { pub fulfillment: Option, /// History of this deposit transaction. pub history: Vec, + /// Input address from which the deposit was made. + pub input_address: String, } /// Implements versioned entry trait for the deposit entry. @@ -523,6 +525,111 @@ impl From for DepositInfo { } } +/// Search token for input address GSI. +#[derive(Clone, Default, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct DepositInfoByInputAddressEntrySearchToken { + /// Primary index key. + #[serde(flatten)] + pub primary_index_key: DepositEntryKey, + /// Global secondary index key. + #[serde(flatten)] + pub secondary_index_key: DepositInfoByInputAddressEntryKey, +} + +/// Key for deposit info entry that's indexed by input_address. +#[derive(Clone, Default, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct DepositInfoByInputAddressEntryKey { + /// The input_address of the deposit encoded in hex. + pub input_address: String, + /// The most recent Stacks block height the API was aware of when the deposit was last + /// updated. If the most recent update is tied to an artifact on the Stacks blockchain + /// then this height is the Stacks block height that contains that artifact. + pub last_update_height: u64, +} + +/// Reduced version of the deposit data that is indexed by input_address. +#[derive(Clone, Default, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct DepositInfoByInputAddressEntry { + /// Gsi key data. + #[serde(flatten)] + pub key: DepositInfoByInputAddressEntryKey, + /// Primary index key data. + #[serde(flatten)] + pub primary_index_key: DepositEntryKey, + /// The status of the entry. + #[serde(rename = "OpStatus")] + pub status: Status, + /// The recipient of the deposit encoded in hex. + pub recipient: String, + /// Amount of BTC being deposited in satoshis. + pub amount: u64, + /// The raw reclaim script. + pub reclaim_script: String, + /// The raw deposit script. + pub deposit_script: String, + /// The most recent Stacks block hash the API was aware of when the deposit was last + /// updated. If the most recent update is tied to an artifact on the Stacks blockchain + /// then this hash is the Stacks block hash that contains that artifact. + pub last_update_block_hash: String, +} + +/// Implements the key trait for the deposit entry key. +impl KeyTrait for DepositInfoByInputAddressEntryKey { + /// The type of the partition key. + type PartitionKey = String; + /// the type of the sort key. + type SortKey = u64; + /// The table field name of the partition key. + const PARTITION_KEY_NAME: &'static str = "InputAddress"; + /// The table field name of the sort key. + const SORT_KEY_NAME: &'static str = "LastUpdateHeight"; +} + +/// Implements the entry trait for the deposit entry. +impl EntryTrait for DepositInfoByInputAddressEntry { + /// The type of the key for this entry type. + type Key = DepositInfoByInputAddressEntryKey; + /// Extract the key from the deposit info entry. + fn key(&self) -> Self::Key { + DepositInfoByInputAddressEntryKey { + input_address: self.key.input_address.clone(), + last_update_height: self.key.last_update_height, + } + } +} + +/// Primary index struct. +pub struct DepositTableByInputAddressSecondaryIndexInner; +/// Deposit table primary index type. +pub type DepositTableByInputAddressSecondaryIndex = + SecondaryIndex; +/// Definition of Primary index trait. +impl SecondaryIndexTrait for DepositTableByInputAddressSecondaryIndexInner { + type PrimaryIndex = DepositTablePrimaryIndex; + type Entry = DepositInfoByInputAddressEntry; + const INDEX_NAME: &'static str = "DepositInputAddressIndex"; +} + +impl From for DepositInfo { + fn from(deposit_info_entry: DepositInfoByInputAddressEntry) -> Self { + // Create deposit info resource from deposit info table entry. + DepositInfo { + bitcoin_txid: deposit_info_entry.primary_index_key.bitcoin_txid, + bitcoin_tx_output_index: deposit_info_entry.primary_index_key.bitcoin_tx_output_index, + recipient: deposit_info_entry.recipient, + amount: deposit_info_entry.amount, + last_update_height: deposit_info_entry.key.last_update_height, + last_update_block_hash: deposit_info_entry.last_update_block_hash, + status: deposit_info_entry.status, + reclaim_script: deposit_info_entry.reclaim_script, + deposit_script: deposit_info_entry.deposit_script, + } + } +} + // ----------------------------------------------------------------------------- /// Validated version of the update deposit request. @@ -706,6 +813,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending, accepted.clone()], + input_address: "".to_string(), }; let update = ValidatedDepositUpdate { @@ -745,6 +853,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending.clone()], + input_address: "".to_string(), }; let update = ValidatedDepositUpdate { @@ -802,6 +911,7 @@ mod tests { last_update_block_hash: "hash6".to_string(), fulfillment: Some(fulfillment.clone()), history: vec![pending.clone(), accepted.clone(), confirmed.clone()], + input_address: "test-input-address".to_string(), }; // Ensure the deposit is valid. diff --git a/emily/handler/tests/integration/deposit.rs b/emily/handler/tests/integration/deposit.rs index dab46645e..1d9eb37ba 100644 --- a/emily/handler/tests/integration/deposit.rs +++ b/emily/handler/tests/integration/deposit.rs @@ -1,4 +1,7 @@ use bitcoin::consensus::encode::serialize_hex; +use bitcoin::hashes::Hash as _; +use bitcoin::params::Params; +use bitcoin::{Address, PubkeyHash, ScriptBuf, WPubkeyHash, WScriptHash}; use sbtc::testing; use sbtc::testing::deposits::TxSetup; use stacks_common::codec::StacksMessageCodec as _; @@ -110,6 +113,21 @@ impl DepositTxnData { Self::from_tx_setup(tx_setup) } + pub fn new_with_input_sigscript( + lock_time: u32, + max_fee: u64, + amounts: &[u64], + input_pubscript: ScriptBuf, + ) -> Self { + let tx_setup = testing::deposits::tx_setup_with_input_sigscript( + lock_time, + max_fee, + amounts, + input_pubscript, + ); + Self::from_tx_setup(tx_setup) + } + pub fn new(lock_time: u32, max_fee: u64, amounts: &[u64]) -> Self { let tx_setup = testing::deposits::tx_setup(lock_time, max_fee, amounts); Self::from_tx_setup(tx_setup) @@ -532,6 +550,134 @@ async fn get_deposits_for_recipient() { } } +#[tokio::test] +async fn get_deposits_for_input_address() { + let configuration = clean_setup().await; + + // Arrange. + // -------- + + // Setup the test information that we'll use to arrange the test. + let deposits_per_transaction = vec![3, 4, 0]; + let script_bufs = vec![ + ScriptBuf::new_p2pkh(&PubkeyHash::from_byte_array([0u8; 20])), + ScriptBuf::new_p2wpkh(&WPubkeyHash::from_byte_array([1u8; 20])), + ScriptBuf::new_p2wsh(&WScriptHash::from_byte_array([2u8; 32])), + ]; + let addresses = script_bufs + .iter() + .map(|script| { + Address::from_script(&script, Params::REGTEST) + .unwrap() + .to_string() + }) + .collect::>(); + + let mut expected_address_data: HashMap> = HashMap::new(); + let mut create_requests: Vec = Vec::new(); + for (address, input_pubscript) in addresses.iter().zip(script_bufs.iter()) { + // Make create requests. + let mut expected_deposit_infos: Vec = Vec::new(); + for num_deposits in deposits_per_transaction.iter() { + let amounts = vec![DEPOSIT_AMOUNT_SATS; *num_deposits as usize]; + // Setup test deposit transaction. + let DepositTxnData { + recipients, + reclaim_scripts, + deposit_scripts, + bitcoin_txid, + transaction_hex, + } = DepositTxnData::new_with_input_sigscript( + DEPOSIT_LOCK_TIME, + DEPOSIT_MAX_FEE, + &amounts, + input_pubscript.clone(), + ); + + for bitcoin_tx_output_index in 0..*num_deposits { + let tx_output_index = bitcoin_tx_output_index as usize; + let recipient = recipients[tx_output_index].clone(); + let reclaim_script = reclaim_scripts[tx_output_index].clone(); + let deposit_script = deposit_scripts[tx_output_index].clone(); + // Make the create request. + let request = CreateDepositRequestBody { + bitcoin_tx_output_index, + bitcoin_txid: bitcoin_txid.clone(), + deposit_script: deposit_script.clone(), + reclaim_script: reclaim_script.clone(), + transaction_hex: transaction_hex.clone(), + }; + create_requests.push(request); + // Store the expected deposit info that should come from it. + let expected_deposit_info = DepositInfo { + amount: DEPOSIT_AMOUNT_SATS, + bitcoin_tx_output_index, + bitcoin_txid: bitcoin_txid.clone(), + last_update_block_hash: BLOCK_HASH.into(), + last_update_height: BLOCK_HEIGHT, + recipient: recipient.clone(), + status: testing_emily_client::models::Status::Pending, + reclaim_script: reclaim_script, + deposit_script: deposit_script, + }; + expected_deposit_infos.push(expected_deposit_info); + } + } + // Add the address data to the address data hashmap that stores what + // we expect to see from the address. + expected_address_data.insert(address.clone(), expected_deposit_infos.clone()); + } + + // The size of the chunks to grab from the api. + let chunksize: u16 = 2; + + // Act. + // ---- + batch_create_deposits(&configuration, create_requests).await; + + let mut actual_address_data: HashMap> = HashMap::new(); + for address in expected_address_data.keys() { + // Loop over the api calls to get all the deposits for the address. + let mut gotten_deposit_info_chunks: Vec> = Vec::new(); + let mut next_token: Option> = None; + loop { + let response = apis::deposit_api::get_deposits_for_input_address( + &configuration, + address, + next_token.as_ref().and_then(|o| o.as_deref()), + Some(chunksize as i32), + ) + .await + .expect("Received an error after making a valid get deposits for address api call."); + gotten_deposit_info_chunks.push(response.deposits); + next_token = response.next_token; + if !next_token.as_ref().is_some_and(|inner| inner.is_some()) { + break; + } + } + // Store the actual data received from the api. + actual_address_data.insert( + address.clone(), + gotten_deposit_info_chunks + .into_iter() + .flatten() + .collect::>(), + ); + } + + // Assert. + // ------- + for address in expected_address_data.keys() { + let mut expected_deposit_infos = expected_address_data.get(address).unwrap().clone(); + expected_deposit_infos.sort_by(arbitrary_deposit_info_partial_cmp); + let mut actual_deposit_infos = actual_address_data.get(address).unwrap().clone(); + actual_deposit_infos.sort_by(arbitrary_deposit_info_partial_cmp); + // Assert that the expected and actual deposit infos are the same. + assert_eq!(expected_deposit_infos.len(), actual_deposit_infos.len()); + assert_eq!(expected_deposit_infos, actual_deposit_infos); + } +} + #[tokio::test] async fn update_deposits() { let configuration = clean_setup().await; diff --git a/emily/openapi-gen/generators/private.rs b/emily/openapi-gen/generators/private.rs index 0131eeaf2..fbb60a062 100644 --- a/emily/openapi-gen/generators/private.rs +++ b/emily/openapi-gen/generators/private.rs @@ -17,6 +17,7 @@ use super::CorsSupport; api::handlers::deposit::get_deposit, api::handlers::deposit::get_deposits_for_transaction, api::handlers::deposit::get_deposits_for_recipient, + api::handlers::deposit::get_deposits_for_input_address, api::handlers::deposit::get_deposits, api::handlers::deposit::create_deposit, api::handlers::deposit::update_deposits, diff --git a/emily/openapi-gen/generators/public.rs b/emily/openapi-gen/generators/public.rs index 3924f871a..9ef45f775 100644 --- a/emily/openapi-gen/generators/public.rs +++ b/emily/openapi-gen/generators/public.rs @@ -17,6 +17,7 @@ use super::CorsSupport; api::handlers::deposit::get_deposit, api::handlers::deposit::get_deposits_for_transaction, api::handlers::deposit::get_deposits_for_recipient, + api::handlers::deposit::get_deposits_for_input_address, api::handlers::deposit::get_deposits, api::handlers::deposit::create_deposit, api::handlers::deposit::update_deposits, diff --git a/emily/openapi-gen/generators/testing.rs b/emily/openapi-gen/generators/testing.rs index ce473c1d0..7a4416f76 100644 --- a/emily/openapi-gen/generators/testing.rs +++ b/emily/openapi-gen/generators/testing.rs @@ -17,6 +17,7 @@ use super::CorsSupport; api::handlers::deposit::get_deposit, api::handlers::deposit::get_deposits_for_transaction, api::handlers::deposit::get_deposits_for_recipient, + api::handlers::deposit::get_deposits_for_input_address, api::handlers::deposit::get_deposits, api::handlers::deposit::create_deposit, api::handlers::deposit::update_deposits, diff --git a/sbtc/src/testing/deposits.rs b/sbtc/src/testing/deposits.rs index 9d027c914..28aa3789b 100644 --- a/sbtc/src/testing/deposits.rs +++ b/sbtc/src/testing/deposits.rs @@ -2,13 +2,21 @@ //! use bitcoin::absolute::LockTime; +use bitcoin::hashes::Hash as _; use bitcoin::transaction::Version; use bitcoin::Amount; +use bitcoin::OutPoint; use bitcoin::ScriptBuf; +use bitcoin::Sequence; use bitcoin::Transaction; +use bitcoin::TxIn; use bitcoin::TxOut; +use bitcoin::WPubkeyHash; +use bitcoin::Witness; use clarity::vm::types::PrincipalData; use rand::rngs::OsRng; +use rand::thread_rng; +use rand::RngCore as _; use secp256k1::SecretKey; use secp256k1::SECP256K1; use stacks_common::types::chainstate::StacksAddress; @@ -27,6 +35,18 @@ pub struct TxSetup { /// The reclaim scripts and their variable inputs pub reclaims: Vec, } +fn build_txin(script_sig: Option) -> TxIn { + TxIn { + previous_output: OutPoint::null(), + sequence: Sequence::ZERO, + script_sig: script_sig.unwrap_or_else(|| { + let mut bytes = [0u8; 20]; + thread_rng().fill_bytes(&mut bytes); + ScriptBuf::new_p2wpkh(&WPubkeyHash::from_byte_array(bytes)) + }), + witness: Witness::new(), + } +} fn build_deposit_reclaim_outputs( lock_time: u32, @@ -73,7 +93,7 @@ pub fn tx_setup(lock_time: u32, max_fee: u64, amounts: &[u64]) -> TxSetup { let tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, - input: Vec::new(), + input: vec![build_txin(None)], output: tx_outs, }; TxSetup { tx, reclaims, deposits } @@ -92,7 +112,26 @@ pub fn tx_setup_with_recipient( let tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, - input: Vec::new(), + input: vec![build_txin(None)], + output: tx_outs, + }; + TxSetup { tx, reclaims, deposits } +} + +/// The BTC transaction that is in this TxSetup is consistent with the deposit and +/// reclaim scripts with a specific input sigscript. +pub fn tx_setup_with_input_sigscript( + lock_time: u32, + max_fee: u64, + amounts: &[u64], + input_sigscript: ScriptBuf, +) -> TxSetup { + let (tx_outs, deposits, reclaims) = + build_deposit_reclaim_outputs(lock_time, max_fee, amounts, None); + let tx = Transaction { + version: Version::TWO, + lock_time: LockTime::ZERO, + input: vec![build_txin(Some(input_sigscript))], output: tx_outs, }; TxSetup { tx, reclaims, deposits } From 3ddd48c6dc915426a1c55814e23494c1b807c375 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Fri, 31 Jan 2025 15:09:46 +0000 Subject: [PATCH 11/17] add autogen openapi specs --- .../private-emily-openapi-spec.json | 130 +++++++++++++++++- .../public-emily-openapi-spec.json | 130 +++++++++++++++++- .../testing-emily-openapi-spec.json | 130 +++++++++++++++++- 3 files changed, 384 insertions(+), 6 deletions(-) diff --git a/emily/openapi-gen/generated-specs/private-emily-openapi-spec.json b/emily/openapi-gen/generated-specs/private-emily-openapi-spec.json index 0c667dcec..33b836a25 100644 --- a/emily/openapi-gen/generated-specs/private-emily-openapi-spec.json +++ b/emily/openapi-gen/generated-specs/private-emily-openapi-spec.json @@ -637,6 +637,132 @@ } } }, + "/deposit/input-address/{inputAddress}": { + "get": { + "tags": [ + "deposit" + ], + "summary": "Get deposits by recipient handler.", + "operationId": "getDepositsForInputAddress", + "parameters": [ + { + "name": "inputAddress", + "in": "path", + "description": "the address from which the deposit was made.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "nextToken", + "in": "query", + "description": "the next token value from the previous return of this api call.", + "required": false, + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "pageSize", + "in": "query", + "description": "the maximum number of items in the response list.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "nullable": true + } + } + ], + "responses": { + "200": { + "description": "Deposits retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetDepositsResponse" + } + } + } + }, + "400": { + "description": "Invalid request body", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Address not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "405": { + "description": "Method not allowed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OperationLambda}/invocations" + } + } + }, + "options": { + "tags": [ + "CORS" + ], + "summary": "CORS support", + "description": "Handles CORS preflight requests", + "parameters": [ + { + "name": "inputAddress", + "in": "path", + "description": "the address from which the deposit was made.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": {}, + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OperationLambda}/invocations" + } + } + } + }, "/deposit/recipient/{recipient}": { "get": { "tags": [ @@ -648,7 +774,7 @@ { "name": "recipient", "in": "path", - "description": "the status to search by when getting all deposits.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -746,7 +872,7 @@ { "name": "recipient", "in": "path", - "description": "the status to search by when getting all deposits.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" diff --git a/emily/openapi-gen/generated-specs/public-emily-openapi-spec.json b/emily/openapi-gen/generated-specs/public-emily-openapi-spec.json index 6b12b6acd..246c92026 100644 --- a/emily/openapi-gen/generated-specs/public-emily-openapi-spec.json +++ b/emily/openapi-gen/generated-specs/public-emily-openapi-spec.json @@ -556,6 +556,132 @@ } } }, + "/deposit/input-address/{inputAddress}": { + "get": { + "tags": [ + "deposit" + ], + "summary": "Get deposits by recipient handler.", + "operationId": "getDepositsForInputAddress", + "parameters": [ + { + "name": "inputAddress", + "in": "path", + "description": "the address from which the deposit was made.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "nextToken", + "in": "query", + "description": "the next token value from the previous return of this api call.", + "required": false, + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "pageSize", + "in": "query", + "description": "the maximum number of items in the response list.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "nullable": true + } + } + ], + "responses": { + "200": { + "description": "Deposits retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetDepositsResponse" + } + } + } + }, + "400": { + "description": "Invalid request body", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Address not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "405": { + "description": "Method not allowed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OperationLambda}/invocations" + } + } + }, + "options": { + "tags": [ + "CORS" + ], + "summary": "CORS support", + "description": "Handles CORS preflight requests", + "parameters": [ + { + "name": "inputAddress", + "in": "path", + "description": "the address from which the deposit was made.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": {}, + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OperationLambda}/invocations" + } + } + } + }, "/deposit/recipient/{recipient}": { "get": { "tags": [ @@ -567,7 +693,7 @@ { "name": "recipient", "in": "path", - "description": "the status to search by when getting all deposits.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -665,7 +791,7 @@ { "name": "recipient", "in": "path", - "description": "the status to search by when getting all deposits.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" diff --git a/emily/openapi-gen/generated-specs/testing-emily-openapi-spec.json b/emily/openapi-gen/generated-specs/testing-emily-openapi-spec.json index 31b6a3e61..86743d9d4 100644 --- a/emily/openapi-gen/generated-specs/testing-emily-openapi-spec.json +++ b/emily/openapi-gen/generated-specs/testing-emily-openapi-spec.json @@ -637,6 +637,132 @@ } } }, + "/deposit/input-address/{inputAddress}": { + "get": { + "tags": [ + "deposit" + ], + "summary": "Get deposits by recipient handler.", + "operationId": "getDepositsForInputAddress", + "parameters": [ + { + "name": "inputAddress", + "in": "path", + "description": "the address from which the deposit was made.", + "required": true, + "schema": { + "type": "string" + } + }, + { + "name": "nextToken", + "in": "query", + "description": "the next token value from the previous return of this api call.", + "required": false, + "schema": { + "type": "string", + "nullable": true + } + }, + { + "name": "pageSize", + "in": "query", + "description": "the maximum number of items in the response list.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "nullable": true + } + } + ], + "responses": { + "200": { + "description": "Deposits retrieved successfully", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GetDepositsResponse" + } + } + } + }, + "400": { + "description": "Invalid request body", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "404": { + "description": "Address not found", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "405": { + "description": "Method not allowed", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + }, + "500": { + "description": "Internal server error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ErrorResponse" + } + } + } + } + }, + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OperationLambda}/invocations" + } + } + }, + "options": { + "tags": [ + "CORS" + ], + "summary": "CORS support", + "description": "Handles CORS preflight requests", + "parameters": [ + { + "name": "inputAddress", + "in": "path", + "description": "the address from which the deposit was made.", + "required": true, + "schema": { + "type": "string" + } + } + ], + "responses": {}, + "x-amazon-apigateway-integration": { + "httpMethod": "POST", + "type": "aws_proxy", + "uri": { + "Fn::Sub": "arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${OperationLambda}/invocations" + } + } + } + }, "/deposit/recipient/{recipient}": { "get": { "tags": [ @@ -648,7 +774,7 @@ { "name": "recipient", "in": "path", - "description": "the status to search by when getting all deposits.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -746,7 +872,7 @@ { "name": "recipient", "in": "path", - "description": "the status to search by when getting all deposits.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" From ad8cfac297c3ca8f394227d0b32de56f5e84bbd8 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Fri, 31 Jan 2025 15:10:44 +0000 Subject: [PATCH 12/17] clippy --- emily/handler/src/api/models/deposit/requests.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/emily/handler/src/api/models/deposit/requests.rs b/emily/handler/src/api/models/deposit/requests.rs index a634ea60b..01ef6b570 100644 --- a/emily/handler/src/api/models/deposit/requests.rs +++ b/emily/handler/src/api/models/deposit/requests.rs @@ -158,7 +158,7 @@ impl CreateDepositRequestBody { } else { Params::REGTEST }; - Address::from_script(&txin.script_sig, params.clone()).map_err(|e| { + Address::from_script(&txin.script_sig, params.clone()).map_err(|_| { Error::HttpRequest( StatusCode::BAD_REQUEST, "invalid transaction input address".to_string(), From 679249efdd96300ef747f4a1951ecc95b92e8084 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 3 Feb 2025 13:39:51 +0000 Subject: [PATCH 13/17] make input_address optional. add tests --- emily/handler/src/api/handlers/deposit.rs | 2 +- .../src/api/models/deposit/requests.rs | 86 +++++++++++++++++-- emily/handler/src/database/entries/deposit.rs | 8 +- emily/handler/tests/integration/deposit.rs | 1 + sbtc/src/testing/deposits.rs | 10 ++- 5 files changed, 91 insertions(+), 16 deletions(-) diff --git a/emily/handler/src/api/handlers/deposit.rs b/emily/handler/src/api/handlers/deposit.rs index 5c79c0862..17d47c0ae 100644 --- a/emily/handler/src/api/handlers/deposit.rs +++ b/emily/handler/src/api/handlers/deposit.rs @@ -376,7 +376,7 @@ pub async fn create_deposit( amount: deposit_data.deposit_info.amount, reclaim_script: body.reclaim_script, deposit_script: body.deposit_script, - input_address: deposit_data.input_address.to_string(), + input_address: deposit_data.input_address.map(|addr| addr.to_string()), ..Default::default() }; // Validate deposit entry. diff --git a/emily/handler/src/api/models/deposit/requests.rs b/emily/handler/src/api/models/deposit/requests.rs index 555d7edfd..ae8adaa65 100644 --- a/emily/handler/src/api/models/deposit/requests.rs +++ b/emily/handler/src/api/models/deposit/requests.rs @@ -8,6 +8,7 @@ use bitcoin::params::Params; use bitcoin::{Address, Amount, OutPoint, ScriptBuf, Txid}; use reqwest::StatusCode; use serde::{Deserialize, Serialize}; +use tracing; use utoipa::ToSchema; use sbtc::deposits::{CreateDepositRequest, DepositInfo}; @@ -158,12 +159,14 @@ impl CreateDepositRequestBody { } else { Params::REGTEST }; - Address::from_script(&txin.script_sig, params.clone()).map_err(|_| { - Error::HttpRequest( - StatusCode::BAD_REQUEST, - "invalid transaction input address".to_string(), - ) - })? + Address::from_script(&txin.script_sig, params.clone()) + .inspect_err(|_| { + tracing::debug!( + "unrecognized ScriptBuf format for txid: {}", + self.bitcoin_txid + ); + }) + .ok() }; Ok(ValidatedCreateDepositRequestData { deposit_info, input_address }) @@ -176,7 +179,7 @@ pub struct ValidatedCreateDepositRequestData { /// Deposit information. pub deposit_info: DepositInfo, /// Input address of the first input in the transaction. - pub input_address: Address, + pub input_address: Option
, } /// A singular Deposit update that contains only the fields pertinent @@ -217,6 +220,8 @@ pub struct UpdateDepositsRequestBody { #[cfg(test)] mod tests { use super::*; + use bitcoin::{AddressType, Network}; + use sbtc::testing; use test_case::test_case; const CREATE_DEPOSIT_VALID: &str = @@ -294,6 +299,73 @@ mod tests { format!("HTTP request failed with status code 400 Bad Request: {expected_error}") ); } + #[test_case("002065f91a53cb7120057db3d378bd0f7d944167d43a7dcbff15d6afc4823f1d3ed3", "bc1qvhu3557twysq2ldn6dut6rmaj3qk04p60h9l79wk4lzgy0ca8mfsnffz65", AddressType::P2wsh; "p2wsh")] + #[test_case("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac", "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM", AddressType::P2pkh; "p2pkh")] + #[test_case("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087", "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k", AddressType::P2sh; "p2sh")] + #[test_case("0014841b80d2cc75f5345c482af96294d04fdd66b2b7", "bc1qssdcp5kvwh6nghzg9tuk99xsflwkdv4hgvq58q", AddressType::P2wpkh; "p2wpkh")] + #[test_case("5120f3778defe5173a9bf7169575116224f961c03c725c0e98b8da8f15df29194b80", "bc1p7dmcmml9zuafhackj463zc3yl9suq0rjts8f3wx63u2a72gefwqqku46c7", AddressType::P2tr; "p2tr")] + #[tokio::test] + async fn test_deposit_validate_extracts_address( + scriptbuf_hex: &str, + address: &str, + address_type: AddressType, + ) { + let input_sigscript = ScriptBuf::from_hex(scriptbuf_hex).unwrap(); + let mainnet = true; + let deposit = testing::deposits::tx_setup_with_input_sigscript( + 14, + 8000, + &[10000], + input_sigscript, + mainnet, + ); + let deposit_request = CreateDepositRequestBody { + bitcoin_txid: deposit.tx.compute_txid().to_string(), + bitcoin_tx_output_index: 0, + reclaim_script: deposit.reclaims[0].reclaim_script().to_hex_string(), + deposit_script: deposit.deposits[0].deposit_script().to_hex_string(), + transaction_hex: encode::serialize_hex(&deposit.tx), + }; + let limits = helpers::create_test_limits(None, None); + let result = deposit_request.validate(&limits, mainnet).unwrap(); + + assert_eq!( + result.input_address.unwrap().to_string(), + address.to_string() + ); + let address = Address::from_str(address).unwrap(); + assert!(address.is_valid_for_network(Network::Bitcoin)); + assert_eq!( + address.assume_checked().address_type().unwrap(), + address_type + ); + } + + #[test_case("524104d81fd577272bbe73308c93009eec5dc9fc319fc1ee2e7066e17220a5d47a18314578be2faea34b9f1f8ca078f8621acd4bc22897b03daa422b9bf56646b342a24104ec3afff0b2b66e8152e9018fe3be3fc92b30bf886b3487a525997d00fd9da2d012dce5d5275854adc3106572a5d1e12d4211b228429f5a7b2f7ba92eb0475bb14104b49b496684b02855bc32f5daefa2e2e406db4418f3b86bca5195600951c7d918cdbe5e6d3736ec2abf2dd7610995c3086976b2c0c7b4e459d10b34a316d5a5e753ae"; "p2ms")] + #[test_case("160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259d"; "nested-p2wpkh")] + #[tokio::test] + async fn test_deposit_validate_for_unsupported_pubscript(scriptbuf_hex: &str) { + let input_sigscript = ScriptBuf::from_hex(scriptbuf_hex).unwrap(); + let mainnet = true; + let deposit = testing::deposits::tx_setup_with_input_sigscript( + 14, + 8000, + &[10000], + input_sigscript, + mainnet, + ); + let deposit_request = CreateDepositRequestBody { + bitcoin_txid: deposit.tx.compute_txid().to_string(), + bitcoin_tx_output_index: 0, + reclaim_script: deposit.reclaims[0].reclaim_script().to_hex_string(), + deposit_script: deposit.deposits[0].deposit_script().to_hex_string(), + transaction_hex: encode::serialize_hex(&deposit.tx), + }; + let limits = helpers::create_test_limits(None, None); + let result = deposit_request.validate(&limits, mainnet).unwrap(); + + assert_eq!(result.input_address, None); + } // CREATE_DEPOSIT_VALID has a deposit amount of 1_000_000 satoshis. #[test_case(CREATE_DEPOSIT_VALID, None, None; "no_limits")] diff --git a/emily/handler/src/database/entries/deposit.rs b/emily/handler/src/database/entries/deposit.rs index c6ab849a9..f324fc0c4 100644 --- a/emily/handler/src/database/entries/deposit.rs +++ b/emily/handler/src/database/entries/deposit.rs @@ -70,7 +70,7 @@ pub struct DepositEntry { /// History of this deposit transaction. pub history: Vec, /// Input address from which the deposit was made. - pub input_address: String, + pub input_address: Option, } /// Implements versioned entry trait for the deposit entry. @@ -813,7 +813,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending, accepted.clone()], - input_address: "".to_string(), + input_address: None, }; let update = ValidatedDepositUpdate { @@ -853,7 +853,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending.clone()], - input_address: "".to_string(), + input_address: None, }; let update = ValidatedDepositUpdate { @@ -911,7 +911,7 @@ mod tests { last_update_block_hash: "hash6".to_string(), fulfillment: Some(fulfillment.clone()), history: vec![pending.clone(), accepted.clone(), confirmed.clone()], - input_address: "test-input-address".to_string(), + input_address: Some("test-input-address".to_string()), }; // Ensure the deposit is valid. diff --git a/emily/handler/tests/integration/deposit.rs b/emily/handler/tests/integration/deposit.rs index 1d9eb37ba..1eb69ff26 100644 --- a/emily/handler/tests/integration/deposit.rs +++ b/emily/handler/tests/integration/deposit.rs @@ -124,6 +124,7 @@ impl DepositTxnData { max_fee, amounts, input_pubscript, + false, ); Self::from_tx_setup(tx_setup) } diff --git a/sbtc/src/testing/deposits.rs b/sbtc/src/testing/deposits.rs index 28aa3789b..83701c610 100644 --- a/sbtc/src/testing/deposits.rs +++ b/sbtc/src/testing/deposits.rs @@ -53,6 +53,7 @@ fn build_deposit_reclaim_outputs( max_fee: u64, amounts: &[u64], recipient: Option, + mainnet: bool, ) -> ( Vec, Vec, @@ -64,7 +65,7 @@ fn build_deposit_reclaim_outputs( for &amount in amounts { let secret_key = SecretKey::new(&mut OsRng); - let actual_recipient = recipient.unwrap_or(StacksAddress::burn_address(false)); + let actual_recipient = recipient.unwrap_or(StacksAddress::burn_address(mainnet)); let deposit = DepositScriptInputs { signers_public_key: secret_key.x_only_public_key(SECP256K1).0, recipient: PrincipalData::from(actual_recipient), @@ -89,7 +90,7 @@ fn build_deposit_reclaim_outputs( /// the deposit and reclaim scripts. pub fn tx_setup(lock_time: u32, max_fee: u64, amounts: &[u64]) -> TxSetup { let (tx_outs, deposits, reclaims) = - build_deposit_reclaim_outputs(lock_time, max_fee, amounts, None); + build_deposit_reclaim_outputs(lock_time, max_fee, amounts, None, false); let tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, @@ -108,7 +109,7 @@ pub fn tx_setup_with_recipient( recipient: StacksAddress, ) -> TxSetup { let (tx_outs, deposits, reclaims) = - build_deposit_reclaim_outputs(lock_time, max_fee, amounts, Some(recipient)); + build_deposit_reclaim_outputs(lock_time, max_fee, amounts, Some(recipient), false); let tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, @@ -125,9 +126,10 @@ pub fn tx_setup_with_input_sigscript( max_fee: u64, amounts: &[u64], input_sigscript: ScriptBuf, + mainnet: bool, ) -> TxSetup { let (tx_outs, deposits, reclaims) = - build_deposit_reclaim_outputs(lock_time, max_fee, amounts, None); + build_deposit_reclaim_outputs(lock_time, max_fee, amounts, None, mainnet); let tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, From 4eba369ccbf63e25654380c8c05f0732f2e52c29 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 3 Feb 2025 18:10:26 +0000 Subject: [PATCH 14/17] save None address for unknown pubkey_scripts. update integration-tests --- emily/handler/src/api/handlers/deposit.rs | 5 +- emily/handler/src/database/entries/deposit.rs | 8 +-- .../completed-deposit-testnet-event.json | 60 +++++++++---------- .../create-deposit-valid-testnet.json | 6 +- 4 files changed, 41 insertions(+), 38 deletions(-) diff --git a/emily/handler/src/api/handlers/deposit.rs b/emily/handler/src/api/handlers/deposit.rs index 17d47c0ae..4b92e4c47 100644 --- a/emily/handler/src/api/handlers/deposit.rs +++ b/emily/handler/src/api/handlers/deposit.rs @@ -376,7 +376,10 @@ pub async fn create_deposit( amount: deposit_data.deposit_info.amount, reclaim_script: body.reclaim_script, deposit_script: body.deposit_script, - input_address: deposit_data.input_address.map(|addr| addr.to_string()), + input_address: deposit_data + .input_address + .map(|addr| addr.to_string()) + .unwrap_or_else(|| "None".to_string()), ..Default::default() }; // Validate deposit entry. diff --git a/emily/handler/src/database/entries/deposit.rs b/emily/handler/src/database/entries/deposit.rs index f324fc0c4..c6ab849a9 100644 --- a/emily/handler/src/database/entries/deposit.rs +++ b/emily/handler/src/database/entries/deposit.rs @@ -70,7 +70,7 @@ pub struct DepositEntry { /// History of this deposit transaction. pub history: Vec, /// Input address from which the deposit was made. - pub input_address: Option, + pub input_address: String, } /// Implements versioned entry trait for the deposit entry. @@ -813,7 +813,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending, accepted.clone()], - input_address: None, + input_address: "".to_string(), }; let update = ValidatedDepositUpdate { @@ -853,7 +853,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending.clone()], - input_address: None, + input_address: "".to_string(), }; let update = ValidatedDepositUpdate { @@ -911,7 +911,7 @@ mod tests { last_update_block_hash: "hash6".to_string(), fulfillment: Some(fulfillment.clone()), history: vec![pending.clone(), accepted.clone(), confirmed.clone()], - input_address: Some("test-input-address".to_string()), + input_address: "test-input-address".to_string(), }; // Ensure the deposit is valid. diff --git a/emily/handler/tests/fixtures/completed-deposit-testnet-event.json b/emily/handler/tests/fixtures/completed-deposit-testnet-event.json index a27fe89b5..47b044651 100644 --- a/emily/handler/tests/fixtures/completed-deposit-testnet-event.json +++ b/emily/handler/tests/fixtures/completed-deposit-testnet-event.json @@ -36,38 +36,38 @@ "Sequence": { "Buffer": { "data": [ - 88, - 100, - 97, - 211, - 237, - 87, - 228, - 73, - 185, - 232, - 170, + 103, + 47, + 119, + 206, + 60, + 22, + 179, + 110, + 198, 196, - 209, - 202, - 38, - 203, - 139, - 170, - 151, + 67, + 245, + 184, + 160, + 169, + 104, + 77, + 2, + 3, + 72, + 42, + 48, + 104, + 86, + 126, + 121, + 47, + 226, + 85, + 157, 84, - 79, - 129, - 255, - 229, - 255, - 0, - 64, - 1, - 98, - 119, - 38, - 178 + 207 ] } } diff --git a/emily/handler/tests/fixtures/create-deposit-valid-testnet.json b/emily/handler/tests/fixtures/create-deposit-valid-testnet.json index e61f26433..a9adca6ca 100644 --- a/emily/handler/tests/fixtures/create-deposit-valid-testnet.json +++ b/emily/handler/tests/fixtures/create-deposit-valid-testnet.json @@ -1,7 +1,7 @@ { - "bitcoinTxid": "586461d3ed57e449b9e8aac4d1ca26cb8baa97544f81ffe5ff004001627726b2", + "bitcoinTxid": "672f77ce3c16b36ec6c443f5b8a0a9684d0203482a3068567e792fe2559d54cf", "bitcoinTxOutputIndex": 0, "reclaimScript": "5eb2", - "depositScript": "1e000000000000001e051a00000000000000000000000000000000000000007520a963eee67c254e482624e75538514111313356345d6c755973591f9e362a41acac", - "transactionHex": "020000000001000140420f0000000000225120b8319ec4b8a7609bbd47aef73fffe797c40468db652d2a32a52b145decfba37100000000" + "depositScript": "1e0000000000001f40051a00000000000000000000000000000000000000007520567467ad8005b9a240160b3c8f6cbd229f3e52f100004c138054d4dbae363e5eac", + "transactionHex": "02000000010000000000000000000000000000000000000000000000000000000000000000ffffffff1600148d7300197c1f4d143e7b4eff42628014a5b1c820000000000110270000000000002251202cb104bacca5e17ec44e60efe7381a21bfb718525111f6b5e38d7866795f09bf00000000" } \ No newline at end of file From cd689384fd2cde5ab6407a35fd41bf43f366318e Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Mon, 3 Feb 2025 19:09:38 +0000 Subject: [PATCH 15/17] avoid saving the address to dynamo if empty --- emily/handler/src/api/handlers/deposit.rs | 5 +---- emily/handler/src/database/entries/deposit.rs | 9 +++++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/emily/handler/src/api/handlers/deposit.rs b/emily/handler/src/api/handlers/deposit.rs index 4b92e4c47..17d47c0ae 100644 --- a/emily/handler/src/api/handlers/deposit.rs +++ b/emily/handler/src/api/handlers/deposit.rs @@ -376,10 +376,7 @@ pub async fn create_deposit( amount: deposit_data.deposit_info.amount, reclaim_script: body.reclaim_script, deposit_script: body.deposit_script, - input_address: deposit_data - .input_address - .map(|addr| addr.to_string()) - .unwrap_or_else(|| "None".to_string()), + input_address: deposit_data.input_address.map(|addr| addr.to_string()), ..Default::default() }; // Validate deposit entry. diff --git a/emily/handler/src/database/entries/deposit.rs b/emily/handler/src/database/entries/deposit.rs index c6ab849a9..7a41b8fb1 100644 --- a/emily/handler/src/database/entries/deposit.rs +++ b/emily/handler/src/database/entries/deposit.rs @@ -70,7 +70,8 @@ pub struct DepositEntry { /// History of this deposit transaction. pub history: Vec, /// Input address from which the deposit was made. - pub input_address: String, + #[serde(skip_serializing_if = "Option::is_none")] + pub input_address: Option, } /// Implements versioned entry trait for the deposit entry. @@ -813,7 +814,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending, accepted.clone()], - input_address: "".to_string(), + input_address: None, }; let update = ValidatedDepositUpdate { @@ -853,7 +854,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending.clone()], - input_address: "".to_string(), + input_address: None, }; let update = ValidatedDepositUpdate { @@ -911,7 +912,7 @@ mod tests { last_update_block_hash: "hash6".to_string(), fulfillment: Some(fulfillment.clone()), history: vec![pending.clone(), accepted.clone(), confirmed.clone()], - input_address: "test-input-address".to_string(), + input_address: Some("test-input-address".to_string()), }; // Ensure the deposit is valid. From d55e3a690c4be79ab833c56964a64f6b2d2c2f30 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Wed, 5 Feb 2025 18:43:19 +0000 Subject: [PATCH 16/17] convert deposit/input-address -> deposit/reclaim-pubkey --- emily/cdk/lib/emily-stack.ts | 4 +- emily/handler/src/api/handlers/deposit.rs | 75 ++++++++--- .../src/api/models/deposit/requests.rs | 116 +----------------- emily/handler/src/api/routes/deposit.rs | 10 +- emily/handler/src/database/accessors.rs | 16 +-- emily/handler/src/database/entries/deposit.rs | 58 ++++----- emily/handler/tests/integration/deposit.rs | 73 +++++------ .../private-emily-openapi-spec.json | 24 ++-- .../public-emily-openapi-spec.json | 24 ++-- .../testing-emily-openapi-spec.json | 24 ++-- emily/openapi-gen/generators/private.rs | 2 +- emily/openapi-gen/generators/public.rs | 2 +- emily/openapi-gen/generators/testing.rs | 2 +- sbtc/src/testing/deposits.rs | 49 +++----- 14 files changed, 194 insertions(+), 285 deletions(-) diff --git a/emily/cdk/lib/emily-stack.ts b/emily/cdk/lib/emily-stack.ts index fdcc99167..6a2c5b1d7 100644 --- a/emily/cdk/lib/emily-stack.ts +++ b/emily/cdk/lib/emily-stack.ts @@ -182,11 +182,11 @@ export class EmilyStack extends cdk.Stack { }); // Index to efficiently query deposits that comes from a specific address - const byAddressIndexName: string = "DepositInputAddressIndex"; + const byAddressIndexName: string = "DepositReclaimPubkeyIndex"; table.addGlobalSecondaryIndex({ indexName: byAddressIndexName, partitionKey: { - name: 'InputAddress', + name: 'ReclaimPubkey', type: dynamodb.AttributeType.STRING }, sortKey: { diff --git a/emily/handler/src/api/handlers/deposit.rs b/emily/handler/src/api/handlers/deposit.rs index 17d47c0ae..b4afceace 100644 --- a/emily/handler/src/api/handlers/deposit.rs +++ b/emily/handler/src/api/handlers/deposit.rs @@ -5,6 +5,9 @@ use crate::api::models::deposit::responses::{ GetDepositsForTransactionResponse, UpdateDepositsResponse, }; use crate::database::entries::StatusEntry; +use bitcoin::opcodes::all as opcodes; +use bitcoin::ScriptBuf; +use sbtc::deposits::ReclaimScriptInputs; use tracing::{debug, instrument}; use warp::reply::{json, with_status, Reply}; @@ -240,10 +243,10 @@ pub async fn get_deposits_for_recipient( /// Get deposits by recipient handler. #[utoipa::path( get, - operation_id = "getDepositsForInputAddress", - path = "/deposit/input-address/{inputAddress}", + operation_id = "getDepositsForReclaimPubkey", + path = "/deposit/reclaim-pubkey/{reclaimPubkey}", params( - ("inputAddress" = String, Path, description = "the address from which the deposit was made."), + ("reclaimPubkey" = String, Path, description = "the reclaim schnorr public key to search by when getting all deposits."), ("nextToken" = Option, Query, description = "the next token value from the previous return of this api call."), ("pageSize" = Option, Query, description = "the maximum number of items in the response list.") ), @@ -257,21 +260,21 @@ pub async fn get_deposits_for_recipient( ) )] #[instrument(skip(context))] -pub async fn get_deposits_for_input_address( +pub async fn get_deposits_for_reclaim_pubkey( context: EmilyContext, - input_address: String, + reclaim_pubkey: String, query: BasicPaginationQuery, ) -> impl warp::reply::Reply { - debug!("in get deposits for input address: {input_address}"); + debug!("in get deposits for reclaim pubkey: {reclaim_pubkey}"); // Internal handler so `?` can be used correctly while still returning a reply. async fn handler( context: EmilyContext, - input_address: String, + reclaim_pubkey: String, query: BasicPaginationQuery, ) -> Result { - let (entries, next_token) = accessors::get_deposit_entries_by_input_address( + let (entries, next_token) = accessors::get_deposit_entries_by_reclaim_pubkey( &context, - &input_address, + &reclaim_pubkey, query.next_token, query.page_size, ) @@ -284,7 +287,7 @@ pub async fn get_deposits_for_input_address( Ok(with_status(json(&response), StatusCode::OK)) } // Handle and respond. - handler(context, input_address, query) + handler(context, reclaim_pubkey, query) .await .map_or_else(Reply::into_response, Reply::into_response) } @@ -352,17 +355,18 @@ pub async fn create_deposit( } let limits = accessors::get_limits(&context).await?; - let deposit_data = body.validate(&limits, context.settings.is_mainnet)?; + let deposit_info = body.validate(&limits, context.settings.is_mainnet)?; + // Make table entry. let deposit_entry: DepositEntry = DepositEntry { key: DepositEntryKey { bitcoin_txid: body.bitcoin_txid, bitcoin_tx_output_index: body.bitcoin_tx_output_index, }, - recipient: hex::encode(deposit_data.deposit_info.recipient.serialize_to_vec()), + recipient: hex::encode(deposit_info.recipient.serialize_to_vec()), parameters: DepositParametersEntry { - max_fee: deposit_data.deposit_info.max_fee, - lock_time: deposit_data.deposit_info.lock_time.to_consensus_u32(), + max_fee: deposit_info.max_fee, + lock_time: deposit_info.lock_time.to_consensus_u32(), }, history: vec![DepositEvent { status: StatusEntry::Pending, @@ -373,10 +377,10 @@ pub async fn create_deposit( status: Status::Pending, last_update_block_hash: stacks_block_hash, last_update_height: stacks_block_height, - amount: deposit_data.deposit_info.amount, + amount: deposit_info.amount, reclaim_script: body.reclaim_script, deposit_script: body.deposit_script, - input_address: deposit_data.input_address.map(|addr| addr.to_string()), + reclaim_pubkey: parse_reclaim_pubkey(&deposit_info.reclaim_script), ..Default::default() }; // Validate deposit entry. @@ -472,4 +476,43 @@ pub async fn update_deposits( .map_or_else(Reply::into_response, Reply::into_response) } +const OP_DROP: u8 = opcodes::OP_DROP.to_u8(); +const OP_CHECKSIG: u8 = opcodes::OP_CHECKSIG.to_u8(); + +/// Parse the reclaim script to extract the pubkey. +/// Currently only supports the sBTC Bridge and Leather Wallet reclaim scripts. +fn parse_reclaim_pubkey(reclaim_script: &ScriptBuf) -> Option { + let reclaim = ReclaimScriptInputs::parse(reclaim_script).ok()?; + + match reclaim.user_script().as_bytes() { + [OP_DROP, _key_len, pubkey @ .., OP_CHECKSIG] => Some(hex::encode(pubkey)), + _ => None, + } +} + +#[cfg(test)] +mod tests { + use super::*; + use bitcoin::{ + key::rand::rngs::OsRng, + secp256k1::{SecretKey, SECP256K1}, + }; + + #[tokio::test] + async fn test_parse_reclaim_pubkey_two_ways() { + let secret_key = SecretKey::new(&mut OsRng); + let pubkey = secret_key.x_only_public_key(SECP256K1).0.serialize(); + let user_script = ScriptBuf::builder() + .push_opcode(opcodes::OP_DROP) + .push_slice(pubkey) + .push_opcode(opcodes::OP_CHECKSIG) + .into_script(); + let reclaim_script = ReclaimScriptInputs::try_new(14, user_script) + .unwrap() + .reclaim_script(); + let pubkey_from_script = parse_reclaim_pubkey(&reclaim_script).unwrap(); + assert_eq!(pubkey_from_script, hex::encode(pubkey)); + } +} + // TODO(393): Add handler unit tests. diff --git a/emily/handler/src/api/models/deposit/requests.rs b/emily/handler/src/api/models/deposit/requests.rs index ae8adaa65..5b8fac8ac 100644 --- a/emily/handler/src/api/models/deposit/requests.rs +++ b/emily/handler/src/api/models/deposit/requests.rs @@ -4,11 +4,9 @@ use std::str::FromStr; use bitcoin::blockdata::transaction::Transaction; use bitcoin::consensus::encode; -use bitcoin::params::Params; -use bitcoin::{Address, Amount, OutPoint, ScriptBuf, Txid}; +use bitcoin::{Amount, OutPoint, ScriptBuf, Txid}; use reqwest::StatusCode; use serde::{Deserialize, Serialize}; -use tracing; use utoipa::ToSchema; use sbtc::deposits::{CreateDepositRequest, DepositInfo}; @@ -87,11 +85,7 @@ impl CreateDepositRequestBody { /// Validates that the deposit request is valid. /// This includes validating the request fields, if their content matches the transaction /// and if the amount is within the limits. - pub fn validate( - &self, - limits: &Limits, - is_mainnet: bool, - ) -> Result { + pub fn validate(&self, limits: &Limits, is_mainnet: bool) -> Result { let deposit_req = CreateDepositRequest { outpoint: OutPoint { txid: parse_hex(&self.bitcoin_txid, "invalid bitcoin_txid", Txid::from_str)?, @@ -143,45 +137,12 @@ impl CreateDepositRequestBody { )); } - let deposit_info = deposit_req + deposit_req .validate_tx(&tx, is_mainnet) - .map_err(|e| Error::HttpRequest(StatusCode::BAD_REQUEST, e.to_string()))?; - - let txin = tx.tx_in(0).map_err(|_| { - Error::HttpRequest( - StatusCode::BAD_REQUEST, - "invalid transaction input".to_string(), - ) - })?; - let input_address = { - let params = if is_mainnet { - Params::MAINNET - } else { - Params::REGTEST - }; - Address::from_script(&txin.script_sig, params.clone()) - .inspect_err(|_| { - tracing::debug!( - "unrecognized ScriptBuf format for txid: {}", - self.bitcoin_txid - ); - }) - .ok() - }; - - Ok(ValidatedCreateDepositRequestData { deposit_info, input_address }) + .map_err(|e| Error::HttpRequest(StatusCode::BAD_REQUEST, e.to_string())) } } -/// Validated deposit request data. -#[derive(Debug)] -pub struct ValidatedCreateDepositRequestData { - /// Deposit information. - pub deposit_info: DepositInfo, - /// Input address of the first input in the transaction. - pub input_address: Option
, -} - /// A singular Deposit update that contains only the fields pertinent /// to updating the status of a deposit. This includes the key related /// data in addition to status history related data. @@ -220,8 +181,6 @@ pub struct UpdateDepositsRequestBody { #[cfg(test)] mod tests { use super::*; - use bitcoin::{AddressType, Network}; - use sbtc::testing; use test_case::test_case; const CREATE_DEPOSIT_VALID: &str = @@ -299,73 +258,6 @@ mod tests { format!("HTTP request failed with status code 400 Bad Request: {expected_error}") ); } - #[test_case("002065f91a53cb7120057db3d378bd0f7d944167d43a7dcbff15d6afc4823f1d3ed3", "bc1qvhu3557twysq2ldn6dut6rmaj3qk04p60h9l79wk4lzgy0ca8mfsnffz65", AddressType::P2wsh; "p2wsh")] - #[test_case("76a914162c5ea71c0b23f5b9022ef047c4a86470a5b07088ac", "132F25rTsvBdp9JzLLBHP5mvGY66i1xdiM", AddressType::P2pkh; "p2pkh")] - #[test_case("a914162c5ea71c0b23f5b9022ef047c4a86470a5b07087", "33iFwdLuRpW1uK1RTRqsoi8rR4NpDzk66k", AddressType::P2sh; "p2sh")] - #[test_case("0014841b80d2cc75f5345c482af96294d04fdd66b2b7", "bc1qssdcp5kvwh6nghzg9tuk99xsflwkdv4hgvq58q", AddressType::P2wpkh; "p2wpkh")] - #[test_case("5120f3778defe5173a9bf7169575116224f961c03c725c0e98b8da8f15df29194b80", "bc1p7dmcmml9zuafhackj463zc3yl9suq0rjts8f3wx63u2a72gefwqqku46c7", AddressType::P2tr; "p2tr")] - #[tokio::test] - async fn test_deposit_validate_extracts_address( - scriptbuf_hex: &str, - address: &str, - address_type: AddressType, - ) { - let input_sigscript = ScriptBuf::from_hex(scriptbuf_hex).unwrap(); - let mainnet = true; - let deposit = testing::deposits::tx_setup_with_input_sigscript( - 14, - 8000, - &[10000], - input_sigscript, - mainnet, - ); - let deposit_request = CreateDepositRequestBody { - bitcoin_txid: deposit.tx.compute_txid().to_string(), - bitcoin_tx_output_index: 0, - reclaim_script: deposit.reclaims[0].reclaim_script().to_hex_string(), - deposit_script: deposit.deposits[0].deposit_script().to_hex_string(), - transaction_hex: encode::serialize_hex(&deposit.tx), - }; - let limits = helpers::create_test_limits(None, None); - let result = deposit_request.validate(&limits, mainnet).unwrap(); - - assert_eq!( - result.input_address.unwrap().to_string(), - address.to_string() - ); - let address = Address::from_str(address).unwrap(); - assert!(address.is_valid_for_network(Network::Bitcoin)); - assert_eq!( - address.assume_checked().address_type().unwrap(), - address_type - ); - } - - #[test_case("524104d81fd577272bbe73308c93009eec5dc9fc319fc1ee2e7066e17220a5d47a18314578be2faea34b9f1f8ca078f8621acd4bc22897b03daa422b9bf56646b342a24104ec3afff0b2b66e8152e9018fe3be3fc92b30bf886b3487a525997d00fd9da2d012dce5d5275854adc3106572a5d1e12d4211b228429f5a7b2f7ba92eb0475bb14104b49b496684b02855bc32f5daefa2e2e406db4418f3b86bca5195600951c7d918cdbe5e6d3736ec2abf2dd7610995c3086976b2c0c7b4e459d10b34a316d5a5e753ae"; "p2ms")] - #[test_case("160014ea940f42d06dfe7ffffd0f8270bf83f3b3d2259d"; "nested-p2wpkh")] - #[tokio::test] - async fn test_deposit_validate_for_unsupported_pubscript(scriptbuf_hex: &str) { - let input_sigscript = ScriptBuf::from_hex(scriptbuf_hex).unwrap(); - let mainnet = true; - let deposit = testing::deposits::tx_setup_with_input_sigscript( - 14, - 8000, - &[10000], - input_sigscript, - mainnet, - ); - let deposit_request = CreateDepositRequestBody { - bitcoin_txid: deposit.tx.compute_txid().to_string(), - bitcoin_tx_output_index: 0, - reclaim_script: deposit.reclaims[0].reclaim_script().to_hex_string(), - deposit_script: deposit.deposits[0].deposit_script().to_hex_string(), - transaction_hex: encode::serialize_hex(&deposit.tx), - }; - let limits = helpers::create_test_limits(None, None); - let result = deposit_request.validate(&limits, mainnet).unwrap(); - - assert_eq!(result.input_address, None); - } // CREATE_DEPOSIT_VALID has a deposit amount of 1_000_000 satoshis. #[test_case(CREATE_DEPOSIT_VALID, None, None; "no_limits")] diff --git a/emily/handler/src/api/routes/deposit.rs b/emily/handler/src/api/routes/deposit.rs index 754dcb5f4..462864c97 100644 --- a/emily/handler/src/api/routes/deposit.rs +++ b/emily/handler/src/api/routes/deposit.rs @@ -13,7 +13,7 @@ pub fn routes( .or(get_deposits_for_transaction(context.clone())) .or(get_deposits(context.clone())) .or(get_deposits_for_recipient(context.clone())) - .or(get_deposits_for_input_address(context.clone())) + .or(get_deposits_for_reclaim_pubkey(context.clone())) .or(create_deposit(context.clone())) .or(update_deposits(context)) } @@ -65,16 +65,16 @@ fn get_deposits_for_recipient( .then(handlers::deposit::get_deposits_for_recipient) } -/// Get deposits for input address endpoint. -fn get_deposits_for_input_address( +/// Get deposits for reclaim pubkey endpoint. +fn get_deposits_for_reclaim_pubkey( context: EmilyContext, ) -> impl Filter + Clone { warp::any() .map(move || context.clone()) - .and(warp::path!("deposit" / "input-address" / String)) + .and(warp::path!("deposit" / "reclaim-pubkey" / String)) .and(warp::get()) .and(warp::query()) - .then(handlers::deposit::get_deposits_for_input_address) + .then(handlers::deposit::get_deposits_for_reclaim_pubkey) } /// Create deposit endpoint. diff --git a/emily/handler/src/database/accessors.rs b/emily/handler/src/database/accessors.rs index 1c55f6d25..7417125e2 100644 --- a/emily/handler/src/database/accessors.rs +++ b/emily/handler/src/database/accessors.rs @@ -13,8 +13,8 @@ use crate::common::error::{Error, Inconsistency}; use crate::{api::models::common::Status, context::EmilyContext}; use super::entries::deposit::{ - DepositInfoByInputAddressEntry, DepositInfoByRecipientEntry, - DepositTableByInputAddressSecondaryIndex, DepositTableByRecipientSecondaryIndex, + DepositInfoByRecipientEntry, DepositInfoByReclaimPubkeyEntry, + DepositTableByRecipientSecondaryIndex, DepositTableByReclaimPubkeySecondaryIndex, ValidatedDepositUpdate, }; use super::entries::limits::{ @@ -98,17 +98,17 @@ pub async fn get_deposit_entries_by_recipient( .await } -/// Get deposit entries by input address. +/// Get deposit entries by reclaim pubkey. #[allow(clippy::ptr_arg)] -pub async fn get_deposit_entries_by_input_address( +pub async fn get_deposit_entries_by_reclaim_pubkey( context: &EmilyContext, - input_address: &String, + reclaim_pubkey: &String, maybe_next_token: Option, maybe_page_size: Option, -) -> Result<(Vec, Option), Error> { - query_with_partition_key::( +) -> Result<(Vec, Option), Error> { + query_with_partition_key::( context, - input_address, + reclaim_pubkey, maybe_next_token, maybe_page_size, ) diff --git a/emily/handler/src/database/entries/deposit.rs b/emily/handler/src/database/entries/deposit.rs index 7a41b8fb1..76cb7c4a0 100644 --- a/emily/handler/src/database/entries/deposit.rs +++ b/emily/handler/src/database/entries/deposit.rs @@ -69,9 +69,9 @@ pub struct DepositEntry { pub fulfillment: Option, /// History of this deposit transaction. pub history: Vec, - /// Input address from which the deposit was made. + /// schnorr reclaim pubkey from which the deposit was made. #[serde(skip_serializing_if = "Option::is_none")] - pub input_address: Option, + pub reclaim_pubkey: Option, } /// Implements versioned entry trait for the deposit entry. @@ -526,37 +526,37 @@ impl From for DepositInfo { } } -/// Search token for input address GSI. +/// Search token for schnorr reclaim pubkey GSI. #[derive(Clone, Default, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] -pub struct DepositInfoByInputAddressEntrySearchToken { +pub struct DepositInfoByReclaimPubkeyEntrySearchToken { /// Primary index key. #[serde(flatten)] pub primary_index_key: DepositEntryKey, /// Global secondary index key. #[serde(flatten)] - pub secondary_index_key: DepositInfoByInputAddressEntryKey, + pub secondary_index_key: DepositInfoByReclaimPubkeyEntryKey, } -/// Key for deposit info entry that's indexed by input_address. +/// Key for deposit info entry that's indexed by reclaim_pubkey. #[derive(Clone, Default, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] -pub struct DepositInfoByInputAddressEntryKey { - /// The input_address of the deposit encoded in hex. - pub input_address: String, +pub struct DepositInfoByReclaimPubkeyEntryKey { + /// The reclaim_pubkey of the deposit encoded in hex. + pub reclaim_pubkey: String, /// The most recent Stacks block height the API was aware of when the deposit was last /// updated. If the most recent update is tied to an artifact on the Stacks blockchain /// then this height is the Stacks block height that contains that artifact. pub last_update_height: u64, } -/// Reduced version of the deposit data that is indexed by input_address. +/// Reduced version of the deposit data that is indexed by reclaim_pubkey. #[derive(Clone, Default, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)] #[serde(rename_all = "PascalCase")] -pub struct DepositInfoByInputAddressEntry { +pub struct DepositInfoByReclaimPubkeyEntry { /// Gsi key data. #[serde(flatten)] - pub key: DepositInfoByInputAddressEntryKey, + pub key: DepositInfoByReclaimPubkeyEntryKey, /// Primary index key data. #[serde(flatten)] pub primary_index_key: DepositEntryKey, @@ -578,44 +578,44 @@ pub struct DepositInfoByInputAddressEntry { } /// Implements the key trait for the deposit entry key. -impl KeyTrait for DepositInfoByInputAddressEntryKey { +impl KeyTrait for DepositInfoByReclaimPubkeyEntryKey { /// The type of the partition key. type PartitionKey = String; /// the type of the sort key. type SortKey = u64; /// The table field name of the partition key. - const PARTITION_KEY_NAME: &'static str = "InputAddress"; + const PARTITION_KEY_NAME: &'static str = "ReclaimPubkey"; /// The table field name of the sort key. const SORT_KEY_NAME: &'static str = "LastUpdateHeight"; } /// Implements the entry trait for the deposit entry. -impl EntryTrait for DepositInfoByInputAddressEntry { +impl EntryTrait for DepositInfoByReclaimPubkeyEntry { /// The type of the key for this entry type. - type Key = DepositInfoByInputAddressEntryKey; + type Key = DepositInfoByReclaimPubkeyEntryKey; /// Extract the key from the deposit info entry. fn key(&self) -> Self::Key { - DepositInfoByInputAddressEntryKey { - input_address: self.key.input_address.clone(), + DepositInfoByReclaimPubkeyEntryKey { + reclaim_pubkey: self.key.reclaim_pubkey.clone(), last_update_height: self.key.last_update_height, } } } /// Primary index struct. -pub struct DepositTableByInputAddressSecondaryIndexInner; +pub struct DepositTableByReclaimPubkeySecondaryIndexInner; /// Deposit table primary index type. -pub type DepositTableByInputAddressSecondaryIndex = - SecondaryIndex; +pub type DepositTableByReclaimPubkeySecondaryIndex = + SecondaryIndex; /// Definition of Primary index trait. -impl SecondaryIndexTrait for DepositTableByInputAddressSecondaryIndexInner { +impl SecondaryIndexTrait for DepositTableByReclaimPubkeySecondaryIndexInner { type PrimaryIndex = DepositTablePrimaryIndex; - type Entry = DepositInfoByInputAddressEntry; - const INDEX_NAME: &'static str = "DepositInputAddressIndex"; + type Entry = DepositInfoByReclaimPubkeyEntry; + const INDEX_NAME: &'static str = "DepositReclaimPubkeyIndex"; } -impl From for DepositInfo { - fn from(deposit_info_entry: DepositInfoByInputAddressEntry) -> Self { +impl From for DepositInfo { + fn from(deposit_info_entry: DepositInfoByReclaimPubkeyEntry) -> Self { // Create deposit info resource from deposit info table entry. DepositInfo { bitcoin_txid: deposit_info_entry.primary_index_key.bitcoin_txid, @@ -814,7 +814,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending, accepted.clone()], - input_address: None, + reclaim_pubkey: None, }; let update = ValidatedDepositUpdate { @@ -854,7 +854,7 @@ mod tests { last_update_block_hash: "".to_string(), fulfillment: None, history: vec![pending.clone()], - input_address: None, + reclaim_pubkey: None, }; let update = ValidatedDepositUpdate { @@ -912,7 +912,7 @@ mod tests { last_update_block_hash: "hash6".to_string(), fulfillment: Some(fulfillment.clone()), history: vec![pending.clone(), accepted.clone(), confirmed.clone()], - input_address: Some("test-input-address".to_string()), + reclaim_pubkey: Some("test-reclaim-pubkey".to_string()), }; // Ensure the deposit is valid. diff --git a/emily/handler/tests/integration/deposit.rs b/emily/handler/tests/integration/deposit.rs index 1eb69ff26..01fa5a7c6 100644 --- a/emily/handler/tests/integration/deposit.rs +++ b/emily/handler/tests/integration/deposit.rs @@ -1,7 +1,6 @@ use bitcoin::consensus::encode::serialize_hex; -use bitcoin::hashes::Hash as _; -use bitcoin::params::Params; -use bitcoin::{Address, PubkeyHash, ScriptBuf, WPubkeyHash, WScriptHash}; +use bitcoin::opcodes::all as opcodes; +use bitcoin::ScriptBuf; use sbtc::testing; use sbtc::testing::deposits::TxSetup; use stacks_common::codec::StacksMessageCodec as _; @@ -113,22 +112,20 @@ impl DepositTxnData { Self::from_tx_setup(tx_setup) } - pub fn new_with_input_sigscript( + pub fn new_with_reclaim_user_script( lock_time: u32, max_fee: u64, amounts: &[u64], - input_pubscript: ScriptBuf, + reclaim_user_script: &ScriptBuf, ) -> Self { - let tx_setup = testing::deposits::tx_setup_with_input_sigscript( + let tx_setup = testing::deposits::tx_setup_with_reclaim_user_script( lock_time, max_fee, amounts, - input_pubscript, - false, + reclaim_user_script, ); Self::from_tx_setup(tx_setup) } - pub fn new(lock_time: u32, max_fee: u64, amounts: &[u64]) -> Self { let tx_setup = testing::deposits::tx_setup(lock_time, max_fee, amounts); Self::from_tx_setup(tx_setup) @@ -552,7 +549,7 @@ async fn get_deposits_for_recipient() { } #[tokio::test] -async fn get_deposits_for_input_address() { +async fn get_deposits_for_reclaim_pubkey() { let configuration = clean_setup().await; // Arrange. @@ -560,23 +557,17 @@ async fn get_deposits_for_input_address() { // Setup the test information that we'll use to arrange the test. let deposits_per_transaction = vec![3, 4, 0]; - let script_bufs = vec![ - ScriptBuf::new_p2pkh(&PubkeyHash::from_byte_array([0u8; 20])), - ScriptBuf::new_p2wpkh(&WPubkeyHash::from_byte_array([1u8; 20])), - ScriptBuf::new_p2wsh(&WScriptHash::from_byte_array([2u8; 32])), - ]; - let addresses = script_bufs - .iter() - .map(|script| { - Address::from_script(&script, Params::REGTEST) - .unwrap() - .to_string() - }) - .collect::>(); + let reclaim_pubkeys = vec![[1u8; 32], [2u8; 32], [3u8; 32]]; - let mut expected_address_data: HashMap> = HashMap::new(); + let mut expected_pubkey_data: HashMap> = HashMap::new(); let mut create_requests: Vec = Vec::new(); - for (address, input_pubscript) in addresses.iter().zip(script_bufs.iter()) { + for pubkey in reclaim_pubkeys.iter() { + let reclaim_user_script = ScriptBuf::builder() + .push_opcode(opcodes::OP_DROP) + .push_slice(pubkey) + .push_opcode(opcodes::OP_CHECKSIG) + .into_script(); + // Make create requests. let mut expected_deposit_infos: Vec = Vec::new(); for num_deposits in deposits_per_transaction.iter() { @@ -588,11 +579,11 @@ async fn get_deposits_for_input_address() { deposit_scripts, bitcoin_txid, transaction_hex, - } = DepositTxnData::new_with_input_sigscript( + } = DepositTxnData::new_with_reclaim_user_script( DEPOSIT_LOCK_TIME, DEPOSIT_MAX_FEE, &amounts, - input_pubscript.clone(), + &reclaim_user_script, ); for bitcoin_tx_output_index in 0..*num_deposits { @@ -624,9 +615,9 @@ async fn get_deposits_for_input_address() { expected_deposit_infos.push(expected_deposit_info); } } - // Add the address data to the address data hashmap that stores what - // we expect to see from the address. - expected_address_data.insert(address.clone(), expected_deposit_infos.clone()); + // Add the pubkey data to the pubkey data hashmap that stores what + // we expect to see from the pubkey. + expected_pubkey_data.insert(serialize_hex(pubkey), expected_deposit_infos.clone()); } // The size of the chunks to grab from the api. @@ -636,20 +627,20 @@ async fn get_deposits_for_input_address() { // ---- batch_create_deposits(&configuration, create_requests).await; - let mut actual_address_data: HashMap> = HashMap::new(); - for address in expected_address_data.keys() { - // Loop over the api calls to get all the deposits for the address. + let mut actual_pubkey_data: HashMap> = HashMap::new(); + for pubkey in expected_pubkey_data.keys() { + // Loop over the api calls to get all the deposits for the pubkey. let mut gotten_deposit_info_chunks: Vec> = Vec::new(); let mut next_token: Option> = None; loop { - let response = apis::deposit_api::get_deposits_for_input_address( + let response = apis::deposit_api::get_deposits_for_reclaim_pubkey( &configuration, - address, + pubkey, next_token.as_ref().and_then(|o| o.as_deref()), Some(chunksize as i32), ) .await - .expect("Received an error after making a valid get deposits for address api call."); + .expect("Received an error after making a valid get deposits for pubkey api call."); gotten_deposit_info_chunks.push(response.deposits); next_token = response.next_token; if !next_token.as_ref().is_some_and(|inner| inner.is_some()) { @@ -657,8 +648,8 @@ async fn get_deposits_for_input_address() { } } // Store the actual data received from the api. - actual_address_data.insert( - address.clone(), + actual_pubkey_data.insert( + pubkey.clone(), gotten_deposit_info_chunks .into_iter() .flatten() @@ -668,10 +659,10 @@ async fn get_deposits_for_input_address() { // Assert. // ------- - for address in expected_address_data.keys() { - let mut expected_deposit_infos = expected_address_data.get(address).unwrap().clone(); + for pubkey in expected_pubkey_data.keys() { + let mut expected_deposit_infos = expected_pubkey_data.get(pubkey).unwrap().clone(); expected_deposit_infos.sort_by(arbitrary_deposit_info_partial_cmp); - let mut actual_deposit_infos = actual_address_data.get(address).unwrap().clone(); + let mut actual_deposit_infos = actual_pubkey_data.get(pubkey).unwrap().clone(); actual_deposit_infos.sort_by(arbitrary_deposit_info_partial_cmp); // Assert that the expected and actual deposit infos are the same. assert_eq!(expected_deposit_infos.len(), actual_deposit_infos.len()); diff --git a/emily/openapi-gen/generated-specs/private-emily-openapi-spec.json b/emily/openapi-gen/generated-specs/private-emily-openapi-spec.json index 3f5931af8..321c4dfda 100644 --- a/emily/openapi-gen/generated-specs/private-emily-openapi-spec.json +++ b/emily/openapi-gen/generated-specs/private-emily-openapi-spec.json @@ -637,18 +637,18 @@ } } }, - "/deposit/input-address/{inputAddress}": { + "/deposit/recipient/{recipient}": { "get": { "tags": [ "deposit" ], "summary": "Get deposits by recipient handler.", - "operationId": "getDepositsForInputAddress", + "operationId": "getDepositsForRecipient", "parameters": [ { - "name": "inputAddress", + "name": "recipient", "in": "path", - "description": "the address from which the deposit was made.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -744,9 +744,9 @@ "description": "Handles CORS preflight requests", "parameters": [ { - "name": "inputAddress", + "name": "recipient", "in": "path", - "description": "the address from which the deposit was made.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -763,18 +763,18 @@ } } }, - "/deposit/recipient/{recipient}": { + "/deposit/reclaim-pubkey/{reclaimPubkey}": { "get": { "tags": [ "deposit" ], "summary": "Get deposits by recipient handler.", - "operationId": "getDepositsForRecipient", + "operationId": "getDepositsForReclaimPubkey", "parameters": [ { - "name": "recipient", + "name": "reclaimPubkey", "in": "path", - "description": "the recipient to search by when getting all deposits.", + "description": "the reclaim schnorr public key to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -870,9 +870,9 @@ "description": "Handles CORS preflight requests", "parameters": [ { - "name": "recipient", + "name": "reclaimPubkey", "in": "path", - "description": "the recipient to search by when getting all deposits.", + "description": "the reclaim schnorr public key to search by when getting all deposits.", "required": true, "schema": { "type": "string" diff --git a/emily/openapi-gen/generated-specs/public-emily-openapi-spec.json b/emily/openapi-gen/generated-specs/public-emily-openapi-spec.json index 23a612ba5..4ff0a670e 100644 --- a/emily/openapi-gen/generated-specs/public-emily-openapi-spec.json +++ b/emily/openapi-gen/generated-specs/public-emily-openapi-spec.json @@ -556,18 +556,18 @@ } } }, - "/deposit/input-address/{inputAddress}": { + "/deposit/recipient/{recipient}": { "get": { "tags": [ "deposit" ], "summary": "Get deposits by recipient handler.", - "operationId": "getDepositsForInputAddress", + "operationId": "getDepositsForRecipient", "parameters": [ { - "name": "inputAddress", + "name": "recipient", "in": "path", - "description": "the address from which the deposit was made.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -663,9 +663,9 @@ "description": "Handles CORS preflight requests", "parameters": [ { - "name": "inputAddress", + "name": "recipient", "in": "path", - "description": "the address from which the deposit was made.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -682,18 +682,18 @@ } } }, - "/deposit/recipient/{recipient}": { + "/deposit/reclaim-pubkey/{reclaimPubkey}": { "get": { "tags": [ "deposit" ], "summary": "Get deposits by recipient handler.", - "operationId": "getDepositsForRecipient", + "operationId": "getDepositsForReclaimPubkey", "parameters": [ { - "name": "recipient", + "name": "reclaimPubkey", "in": "path", - "description": "the recipient to search by when getting all deposits.", + "description": "the reclaim schnorr public key to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -789,9 +789,9 @@ "description": "Handles CORS preflight requests", "parameters": [ { - "name": "recipient", + "name": "reclaimPubkey", "in": "path", - "description": "the recipient to search by when getting all deposits.", + "description": "the reclaim schnorr public key to search by when getting all deposits.", "required": true, "schema": { "type": "string" diff --git a/emily/openapi-gen/generated-specs/testing-emily-openapi-spec.json b/emily/openapi-gen/generated-specs/testing-emily-openapi-spec.json index 7639606e5..cbefd6404 100644 --- a/emily/openapi-gen/generated-specs/testing-emily-openapi-spec.json +++ b/emily/openapi-gen/generated-specs/testing-emily-openapi-spec.json @@ -637,18 +637,18 @@ } } }, - "/deposit/input-address/{inputAddress}": { + "/deposit/recipient/{recipient}": { "get": { "tags": [ "deposit" ], "summary": "Get deposits by recipient handler.", - "operationId": "getDepositsForInputAddress", + "operationId": "getDepositsForRecipient", "parameters": [ { - "name": "inputAddress", + "name": "recipient", "in": "path", - "description": "the address from which the deposit was made.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -744,9 +744,9 @@ "description": "Handles CORS preflight requests", "parameters": [ { - "name": "inputAddress", + "name": "recipient", "in": "path", - "description": "the address from which the deposit was made.", + "description": "the recipient to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -763,18 +763,18 @@ } } }, - "/deposit/recipient/{recipient}": { + "/deposit/reclaim-pubkey/{reclaimPubkey}": { "get": { "tags": [ "deposit" ], "summary": "Get deposits by recipient handler.", - "operationId": "getDepositsForRecipient", + "operationId": "getDepositsForReclaimPubkey", "parameters": [ { - "name": "recipient", + "name": "reclaimPubkey", "in": "path", - "description": "the recipient to search by when getting all deposits.", + "description": "the reclaim schnorr public key to search by when getting all deposits.", "required": true, "schema": { "type": "string" @@ -870,9 +870,9 @@ "description": "Handles CORS preflight requests", "parameters": [ { - "name": "recipient", + "name": "reclaimPubkey", "in": "path", - "description": "the recipient to search by when getting all deposits.", + "description": "the reclaim schnorr public key to search by when getting all deposits.", "required": true, "schema": { "type": "string" diff --git a/emily/openapi-gen/generators/private.rs b/emily/openapi-gen/generators/private.rs index fbb60a062..ccffcea09 100644 --- a/emily/openapi-gen/generators/private.rs +++ b/emily/openapi-gen/generators/private.rs @@ -17,7 +17,7 @@ use super::CorsSupport; api::handlers::deposit::get_deposit, api::handlers::deposit::get_deposits_for_transaction, api::handlers::deposit::get_deposits_for_recipient, - api::handlers::deposit::get_deposits_for_input_address, + api::handlers::deposit::get_deposits_for_reclaim_pubkey, api::handlers::deposit::get_deposits, api::handlers::deposit::create_deposit, api::handlers::deposit::update_deposits, diff --git a/emily/openapi-gen/generators/public.rs b/emily/openapi-gen/generators/public.rs index 9ef45f775..3b5cddcf4 100644 --- a/emily/openapi-gen/generators/public.rs +++ b/emily/openapi-gen/generators/public.rs @@ -17,7 +17,7 @@ use super::CorsSupport; api::handlers::deposit::get_deposit, api::handlers::deposit::get_deposits_for_transaction, api::handlers::deposit::get_deposits_for_recipient, - api::handlers::deposit::get_deposits_for_input_address, + api::handlers::deposit::get_deposits_for_reclaim_pubkey, api::handlers::deposit::get_deposits, api::handlers::deposit::create_deposit, api::handlers::deposit::update_deposits, diff --git a/emily/openapi-gen/generators/testing.rs b/emily/openapi-gen/generators/testing.rs index 7a4416f76..fe1f92798 100644 --- a/emily/openapi-gen/generators/testing.rs +++ b/emily/openapi-gen/generators/testing.rs @@ -17,7 +17,7 @@ use super::CorsSupport; api::handlers::deposit::get_deposit, api::handlers::deposit::get_deposits_for_transaction, api::handlers::deposit::get_deposits_for_recipient, - api::handlers::deposit::get_deposits_for_input_address, + api::handlers::deposit::get_deposits_for_reclaim_pubkey, api::handlers::deposit::get_deposits, api::handlers::deposit::create_deposit, api::handlers::deposit::update_deposits, diff --git a/sbtc/src/testing/deposits.rs b/sbtc/src/testing/deposits.rs index 83701c610..2f36379cc 100644 --- a/sbtc/src/testing/deposits.rs +++ b/sbtc/src/testing/deposits.rs @@ -2,21 +2,13 @@ //! use bitcoin::absolute::LockTime; -use bitcoin::hashes::Hash as _; use bitcoin::transaction::Version; use bitcoin::Amount; -use bitcoin::OutPoint; use bitcoin::ScriptBuf; -use bitcoin::Sequence; use bitcoin::Transaction; -use bitcoin::TxIn; use bitcoin::TxOut; -use bitcoin::WPubkeyHash; -use bitcoin::Witness; use clarity::vm::types::PrincipalData; use rand::rngs::OsRng; -use rand::thread_rng; -use rand::RngCore as _; use secp256k1::SecretKey; use secp256k1::SECP256K1; use stacks_common::types::chainstate::StacksAddress; @@ -35,25 +27,13 @@ pub struct TxSetup { /// The reclaim scripts and their variable inputs pub reclaims: Vec, } -fn build_txin(script_sig: Option) -> TxIn { - TxIn { - previous_output: OutPoint::null(), - sequence: Sequence::ZERO, - script_sig: script_sig.unwrap_or_else(|| { - let mut bytes = [0u8; 20]; - thread_rng().fill_bytes(&mut bytes); - ScriptBuf::new_p2wpkh(&WPubkeyHash::from_byte_array(bytes)) - }), - witness: Witness::new(), - } -} fn build_deposit_reclaim_outputs( lock_time: u32, max_fee: u64, amounts: &[u64], recipient: Option, - mainnet: bool, + reclaim_user_script: Option<&ScriptBuf>, ) -> ( Vec, Vec, @@ -65,13 +45,17 @@ fn build_deposit_reclaim_outputs( for &amount in amounts { let secret_key = SecretKey::new(&mut OsRng); - let actual_recipient = recipient.unwrap_or(StacksAddress::burn_address(mainnet)); + let actual_recipient = recipient.unwrap_or(StacksAddress::burn_address(false)); let deposit = DepositScriptInputs { signers_public_key: secret_key.x_only_public_key(SECP256K1).0, recipient: PrincipalData::from(actual_recipient), max_fee, }; - let reclaim = ReclaimScriptInputs::try_new(lock_time, ScriptBuf::new()).unwrap(); + let reclaim = ReclaimScriptInputs::try_new( + lock_time, + reclaim_user_script.map_or_else(ScriptBuf::new, |s| s.clone()), + ) + .unwrap(); let deposit_script = deposit.deposit_script(); let reclaim_script = reclaim.reclaim_script(); @@ -90,11 +74,11 @@ fn build_deposit_reclaim_outputs( /// the deposit and reclaim scripts. pub fn tx_setup(lock_time: u32, max_fee: u64, amounts: &[u64]) -> TxSetup { let (tx_outs, deposits, reclaims) = - build_deposit_reclaim_outputs(lock_time, max_fee, amounts, None, false); + build_deposit_reclaim_outputs(lock_time, max_fee, amounts, None, None); let tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, - input: vec![build_txin(None)], + input: Vec::new(), output: tx_outs, }; TxSetup { tx, reclaims, deposits } @@ -109,31 +93,30 @@ pub fn tx_setup_with_recipient( recipient: StacksAddress, ) -> TxSetup { let (tx_outs, deposits, reclaims) = - build_deposit_reclaim_outputs(lock_time, max_fee, amounts, Some(recipient), false); + build_deposit_reclaim_outputs(lock_time, max_fee, amounts, Some(recipient), None); let tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, - input: vec![build_txin(None)], + input: Vec::new(), output: tx_outs, }; TxSetup { tx, reclaims, deposits } } /// The BTC transaction that is in this TxSetup is consistent with the deposit and -/// reclaim scripts with a specific input sigscript. -pub fn tx_setup_with_input_sigscript( +/// reclaim scripts with a specific user script. +pub fn tx_setup_with_reclaim_user_script( lock_time: u32, max_fee: u64, amounts: &[u64], - input_sigscript: ScriptBuf, - mainnet: bool, + reclaim_user_script: &ScriptBuf, ) -> TxSetup { let (tx_outs, deposits, reclaims) = - build_deposit_reclaim_outputs(lock_time, max_fee, amounts, None, mainnet); + build_deposit_reclaim_outputs(lock_time, max_fee, amounts, None, Some(reclaim_user_script)); let tx = Transaction { version: Version::TWO, lock_time: LockTime::ZERO, - input: vec![build_txin(Some(input_sigscript))], + input: Vec::new(), output: tx_outs, }; TxSetup { tx, reclaims, deposits } From 0af53d12d0268dfc0799a842a5a0827e9533d5b8 Mon Sep 17 00:00:00 2001 From: Francesco Leacche Date: Wed, 5 Feb 2025 18:43:32 +0000 Subject: [PATCH 17/17] add autogenerated files --- .../emily/client/rust/private/README.md | 4 +- .../emily/client/rust/private/docs/CorsApi.md | 26 +++++----- .../client/rust/private/docs/DepositApi.md | 14 +++--- .../client/rust/private/src/apis/cors_api.rs | 50 +++++++++---------- .../rust/private/src/apis/deposit_api.rs | 32 ++++++------ .../emily/client/rust/public/README.md | 4 +- .../emily/client/rust/public/docs/CorsApi.md | 26 +++++----- .../client/rust/public/docs/DepositApi.md | 14 +++--- .../client/rust/public/src/apis/cors_api.rs | 50 +++++++++---------- .../rust/public/src/apis/deposit_api.rs | 32 ++++++------ .../emily/client/rust/testing/README.md | 4 +- .../emily/client/rust/testing/docs/CorsApi.md | 26 +++++----- .../client/rust/testing/docs/DepositApi.md | 14 +++--- .../client/rust/testing/src/apis/cors_api.rs | 50 +++++++++---------- .../rust/testing/src/apis/deposit_api.rs | 32 ++++++------ 15 files changed, 189 insertions(+), 189 deletions(-) diff --git a/.generated-sources/emily/client/rust/private/README.md b/.generated-sources/emily/client/rust/private/README.md index 648cdb8a0..66e45161f 100644 --- a/.generated-sources/emily/client/rust/private/README.md +++ b/.generated-sources/emily/client/rust/private/README.md @@ -28,9 +28,9 @@ Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- *CorsApi* | [**chainstate_height_options**](docs/CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support *CorsApi* | [**chainstate_options**](docs/CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support -*CorsApi* | [**deposit_input_address_input_address_options**](docs/CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support *CorsApi* | [**deposit_options**](docs/CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support *CorsApi* | [**deposit_recipient_recipient_options**](docs/CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support +*CorsApi* | [**deposit_reclaim_pubkey_reclaim_pubkey_options**](docs/CorsApi.md#deposit_reclaim_pubkey_reclaim_pubkey_options) | **OPTIONS** /deposit/reclaim-pubkey/{reclaimPubkey} | CORS support *CorsApi* | [**deposit_txid_index_options**](docs/CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support *CorsApi* | [**deposit_txid_options**](docs/CorsApi.md#deposit_txid_options) | **OPTIONS** /deposit/{txid} | CORS support *CorsApi* | [**health_options**](docs/CorsApi.md#health_options) | **OPTIONS** /health | CORS support @@ -45,8 +45,8 @@ Class | Method | HTTP request | Description *DepositApi* | [**create_deposit**](docs/DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. *DepositApi* | [**get_deposit**](docs/DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. *DepositApi* | [**get_deposits**](docs/DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. -*DepositApi* | [**get_deposits_for_input_address**](docs/DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_recipient**](docs/DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. +*DepositApi* | [**get_deposits_for_reclaim_pubkey**](docs/DepositApi.md#get_deposits_for_reclaim_pubkey) | **GET** /deposit/reclaim-pubkey/{reclaimPubkey} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_transaction**](docs/DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. *DepositApi* | [**update_deposits**](docs/DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. *HealthApi* | [**check_health**](docs/HealthApi.md#check_health) | **GET** /health | Get health handler. diff --git a/.generated-sources/emily/client/rust/private/docs/CorsApi.md b/.generated-sources/emily/client/rust/private/docs/CorsApi.md index fe889844a..cfa218685 100644 --- a/.generated-sources/emily/client/rust/private/docs/CorsApi.md +++ b/.generated-sources/emily/client/rust/private/docs/CorsApi.md @@ -6,9 +6,9 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**chainstate_height_options**](CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support [**chainstate_options**](CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support -[**deposit_input_address_input_address_options**](CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support [**deposit_options**](CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support [**deposit_recipient_recipient_options**](CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support +[**deposit_reclaim_pubkey_reclaim_pubkey_options**](CorsApi.md#deposit_reclaim_pubkey_reclaim_pubkey_options) | **OPTIONS** /deposit/reclaim-pubkey/{reclaimPubkey} | CORS support [**deposit_txid_index_options**](CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support [**deposit_txid_options**](CorsApi.md#deposit_txid_options) | **OPTIONS** /deposit/{txid} | CORS support [**health_options**](CorsApi.md#health_options) | **OPTIONS** /health | CORS support @@ -76,19 +76,16 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## deposit_input_address_input_address_options +## deposit_options -> deposit_input_address_input_address_options(input_address) +> deposit_options() CORS support Handles CORS preflight requests ### Parameters - -Name | Type | Description | Required | Notes -------------- | ------------- | ------------- | ------------- | ------------- -**input_address** | **String** | the address from which the deposit was made. | [required] | +This endpoint does not need any parameter. ### Return type @@ -106,16 +103,19 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## deposit_options +## deposit_recipient_recipient_options -> deposit_options() +> deposit_recipient_recipient_options(recipient) CORS support Handles CORS preflight requests ### Parameters -This endpoint does not need any parameter. + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | ### Return type @@ -133,9 +133,9 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## deposit_recipient_recipient_options +## deposit_reclaim_pubkey_reclaim_pubkey_options -> deposit_recipient_recipient_options(recipient) +> deposit_reclaim_pubkey_reclaim_pubkey_options(reclaim_pubkey) CORS support Handles CORS preflight requests @@ -145,7 +145,7 @@ Handles CORS preflight requests Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | +**reclaim_pubkey** | **String** | the reclaim schnorr public key to search by when getting all deposits. | [required] | ### Return type diff --git a/.generated-sources/emily/client/rust/private/docs/DepositApi.md b/.generated-sources/emily/client/rust/private/docs/DepositApi.md index 3c14b1d89..ee6001127 100644 --- a/.generated-sources/emily/client/rust/private/docs/DepositApi.md +++ b/.generated-sources/emily/client/rust/private/docs/DepositApi.md @@ -7,8 +7,8 @@ Method | HTTP request | Description [**create_deposit**](DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. [**get_deposit**](DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. [**get_deposits**](DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. -[**get_deposits_for_input_address**](DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. [**get_deposits_for_recipient**](DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. +[**get_deposits_for_reclaim_pubkey**](DepositApi.md#get_deposits_for_reclaim_pubkey) | **GET** /deposit/reclaim-pubkey/{reclaimPubkey} | Get deposits by recipient handler. [**get_deposits_for_transaction**](DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. [**update_deposits**](DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. @@ -101,9 +101,9 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## get_deposits_for_input_address +## get_deposits_for_recipient -> models::GetDepositsResponse get_deposits_for_input_address(input_address, next_token, page_size) +> models::GetDepositsResponse get_deposits_for_recipient(recipient, next_token, page_size) Get deposits by recipient handler. ### Parameters @@ -111,7 +111,7 @@ Get deposits by recipient handler. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**input_address** | **String** | the address from which the deposit was made. | [required] | +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | **next_token** | Option<**String**> | the next token value from the previous return of this api call. | | **page_size** | Option<**i32**> | the maximum number of items in the response list. | | @@ -131,9 +131,9 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## get_deposits_for_recipient +## get_deposits_for_reclaim_pubkey -> models::GetDepositsResponse get_deposits_for_recipient(recipient, next_token, page_size) +> models::GetDepositsResponse get_deposits_for_reclaim_pubkey(reclaim_pubkey, next_token, page_size) Get deposits by recipient handler. ### Parameters @@ -141,7 +141,7 @@ Get deposits by recipient handler. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | +**reclaim_pubkey** | **String** | the reclaim schnorr public key to search by when getting all deposits. | [required] | **next_token** | Option<**String**> | the next token value from the previous return of this api call. | | **page_size** | Option<**i32**> | the maximum number of items in the response list. | | diff --git a/.generated-sources/emily/client/rust/private/src/apis/cors_api.rs b/.generated-sources/emily/client/rust/private/src/apis/cors_api.rs index b7fd9e8e6..4ea292f62 100644 --- a/.generated-sources/emily/client/rust/private/src/apis/cors_api.rs +++ b/.generated-sources/emily/client/rust/private/src/apis/cors_api.rs @@ -27,24 +27,24 @@ pub enum ChainstateOptionsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`deposit_input_address_input_address_options`] +/// struct for typed errors of method [`deposit_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum DepositInputAddressInputAddressOptionsError { +pub enum DepositOptionsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`deposit_options`] +/// struct for typed errors of method [`deposit_recipient_recipient_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum DepositOptionsError { +pub enum DepositRecipientRecipientOptionsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`deposit_recipient_recipient_options`] +/// struct for typed errors of method [`deposit_reclaim_pubkey_reclaim_pubkey_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum DepositRecipientRecipientOptionsError { +pub enum DepositReclaimPubkeyReclaimPubkeyOptionsError { UnknownValue(serde_json::Value), } @@ -177,19 +177,14 @@ pub async fn chainstate_options( } /// Handles CORS preflight requests -pub async fn deposit_input_address_input_address_options( +pub async fn deposit_options( configuration: &configuration::Configuration, - input_address: &str, -) -> Result<(), Error> { +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; - let local_var_uri_str = format!( - "{}/deposit/input-address/{inputAddress}", - local_var_configuration.base_path, - inputAddress = crate::apis::urlencode(input_address) - ); + let local_var_uri_str = format!("{}/deposit", local_var_configuration.base_path); let mut local_var_req_builder = local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); @@ -207,7 +202,7 @@ pub async fn deposit_input_address_input_address_options( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { Ok(()) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -219,14 +214,19 @@ pub async fn deposit_input_address_input_address_options( } /// Handles CORS preflight requests -pub async fn deposit_options( +pub async fn deposit_recipient_recipient_options( configuration: &configuration::Configuration, -) -> Result<(), Error> { + recipient: &str, +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; - let local_var_uri_str = format!("{}/deposit", local_var_configuration.base_path); + let local_var_uri_str = format!( + "{}/deposit/recipient/{recipient}", + local_var_configuration.base_path, + recipient = crate::apis::urlencode(recipient) + ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); @@ -244,7 +244,7 @@ pub async fn deposit_options( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { Ok(()) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -256,18 +256,18 @@ pub async fn deposit_options( } /// Handles CORS preflight requests -pub async fn deposit_recipient_recipient_options( +pub async fn deposit_reclaim_pubkey_reclaim_pubkey_options( configuration: &configuration::Configuration, - recipient: &str, -) -> Result<(), Error> { + reclaim_pubkey: &str, +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/deposit/recipient/{recipient}", + "{}/deposit/reclaim-pubkey/{reclaimPubkey}", local_var_configuration.base_path, - recipient = crate::apis::urlencode(recipient) + reclaimPubkey = crate::apis::urlencode(reclaim_pubkey) ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); @@ -286,7 +286,7 @@ pub async fn deposit_recipient_recipient_options( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { Ok(()) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, diff --git a/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs b/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs index 10af926cd..b4cf15725 100644 --- a/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs +++ b/.generated-sources/emily/client/rust/private/src/apis/deposit_api.rs @@ -47,10 +47,10 @@ pub enum GetDepositsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`get_deposits_for_input_address`] +/// struct for typed errors of method [`get_deposits_for_recipient`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum GetDepositsForInputAddressError { +pub enum GetDepositsForRecipientError { Status400(models::ErrorResponse), Status404(models::ErrorResponse), Status405(models::ErrorResponse), @@ -58,10 +58,10 @@ pub enum GetDepositsForInputAddressError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`get_deposits_for_recipient`] +/// struct for typed errors of method [`get_deposits_for_reclaim_pubkey`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum GetDepositsForRecipientError { +pub enum GetDepositsForReclaimPubkeyError { Status400(models::ErrorResponse), Status404(models::ErrorResponse), Status405(models::ErrorResponse), @@ -220,20 +220,20 @@ pub async fn get_deposits( } } -pub async fn get_deposits_for_input_address( +pub async fn get_deposits_for_recipient( configuration: &configuration::Configuration, - input_address: &str, + recipient: &str, next_token: Option<&str>, page_size: Option, -) -> Result> { +) -> Result> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/deposit/input-address/{inputAddress}", + "{}/deposit/recipient/{recipient}", local_var_configuration.base_path, - inputAddress = crate::apis::urlencode(input_address) + recipient = crate::apis::urlencode(recipient) ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); @@ -260,7 +260,7 @@ pub async fn get_deposits_for_input_address( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { serde_json::from_str(&local_var_content).map_err(Error::from) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -271,20 +271,20 @@ pub async fn get_deposits_for_input_address( } } -pub async fn get_deposits_for_recipient( +pub async fn get_deposits_for_reclaim_pubkey( configuration: &configuration::Configuration, - recipient: &str, + reclaim_pubkey: &str, next_token: Option<&str>, page_size: Option, -) -> Result> { +) -> Result> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/deposit/recipient/{recipient}", + "{}/deposit/reclaim-pubkey/{reclaimPubkey}", local_var_configuration.base_path, - recipient = crate::apis::urlencode(recipient) + reclaimPubkey = crate::apis::urlencode(reclaim_pubkey) ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); @@ -311,7 +311,7 @@ pub async fn get_deposits_for_recipient( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { serde_json::from_str(&local_var_content).map_err(Error::from) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, diff --git a/.generated-sources/emily/client/rust/public/README.md b/.generated-sources/emily/client/rust/public/README.md index 458843628..23f913d9e 100644 --- a/.generated-sources/emily/client/rust/public/README.md +++ b/.generated-sources/emily/client/rust/public/README.md @@ -28,9 +28,9 @@ Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- *CorsApi* | [**chainstate_height_options**](docs/CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support *CorsApi* | [**chainstate_options**](docs/CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support -*CorsApi* | [**deposit_input_address_input_address_options**](docs/CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support *CorsApi* | [**deposit_options**](docs/CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support *CorsApi* | [**deposit_recipient_recipient_options**](docs/CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support +*CorsApi* | [**deposit_reclaim_pubkey_reclaim_pubkey_options**](docs/CorsApi.md#deposit_reclaim_pubkey_reclaim_pubkey_options) | **OPTIONS** /deposit/reclaim-pubkey/{reclaimPubkey} | CORS support *CorsApi* | [**deposit_txid_index_options**](docs/CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support *CorsApi* | [**deposit_txid_options**](docs/CorsApi.md#deposit_txid_options) | **OPTIONS** /deposit/{txid} | CORS support *CorsApi* | [**health_options**](docs/CorsApi.md#health_options) | **OPTIONS** /health | CORS support @@ -45,8 +45,8 @@ Class | Method | HTTP request | Description *DepositApi* | [**create_deposit**](docs/DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. *DepositApi* | [**get_deposit**](docs/DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. *DepositApi* | [**get_deposits**](docs/DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. -*DepositApi* | [**get_deposits_for_input_address**](docs/DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_recipient**](docs/DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. +*DepositApi* | [**get_deposits_for_reclaim_pubkey**](docs/DepositApi.md#get_deposits_for_reclaim_pubkey) | **GET** /deposit/reclaim-pubkey/{reclaimPubkey} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_transaction**](docs/DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. *DepositApi* | [**update_deposits**](docs/DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. *HealthApi* | [**check_health**](docs/HealthApi.md#check_health) | **GET** /health | Get health handler. diff --git a/.generated-sources/emily/client/rust/public/docs/CorsApi.md b/.generated-sources/emily/client/rust/public/docs/CorsApi.md index a9303a3e3..a0292ac98 100644 --- a/.generated-sources/emily/client/rust/public/docs/CorsApi.md +++ b/.generated-sources/emily/client/rust/public/docs/CorsApi.md @@ -6,9 +6,9 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**chainstate_height_options**](CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support [**chainstate_options**](CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support -[**deposit_input_address_input_address_options**](CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support [**deposit_options**](CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support [**deposit_recipient_recipient_options**](CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support +[**deposit_reclaim_pubkey_reclaim_pubkey_options**](CorsApi.md#deposit_reclaim_pubkey_reclaim_pubkey_options) | **OPTIONS** /deposit/reclaim-pubkey/{reclaimPubkey} | CORS support [**deposit_txid_index_options**](CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support [**deposit_txid_options**](CorsApi.md#deposit_txid_options) | **OPTIONS** /deposit/{txid} | CORS support [**health_options**](CorsApi.md#health_options) | **OPTIONS** /health | CORS support @@ -77,19 +77,16 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## deposit_input_address_input_address_options +## deposit_options -> deposit_input_address_input_address_options(input_address) +> deposit_options() CORS support Handles CORS preflight requests ### Parameters - -Name | Type | Description | Required | Notes -------------- | ------------- | ------------- | ------------- | ------------- -**input_address** | **String** | the address from which the deposit was made. | [required] | +This endpoint does not need any parameter. ### Return type @@ -107,16 +104,19 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## deposit_options +## deposit_recipient_recipient_options -> deposit_options() +> deposit_recipient_recipient_options(recipient) CORS support Handles CORS preflight requests ### Parameters -This endpoint does not need any parameter. + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | ### Return type @@ -134,9 +134,9 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## deposit_recipient_recipient_options +## deposit_reclaim_pubkey_reclaim_pubkey_options -> deposit_recipient_recipient_options(recipient) +> deposit_reclaim_pubkey_reclaim_pubkey_options(reclaim_pubkey) CORS support Handles CORS preflight requests @@ -146,7 +146,7 @@ Handles CORS preflight requests Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | +**reclaim_pubkey** | **String** | the reclaim schnorr public key to search by when getting all deposits. | [required] | ### Return type diff --git a/.generated-sources/emily/client/rust/public/docs/DepositApi.md b/.generated-sources/emily/client/rust/public/docs/DepositApi.md index 3c14b1d89..ee6001127 100644 --- a/.generated-sources/emily/client/rust/public/docs/DepositApi.md +++ b/.generated-sources/emily/client/rust/public/docs/DepositApi.md @@ -7,8 +7,8 @@ Method | HTTP request | Description [**create_deposit**](DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. [**get_deposit**](DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. [**get_deposits**](DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. -[**get_deposits_for_input_address**](DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. [**get_deposits_for_recipient**](DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. +[**get_deposits_for_reclaim_pubkey**](DepositApi.md#get_deposits_for_reclaim_pubkey) | **GET** /deposit/reclaim-pubkey/{reclaimPubkey} | Get deposits by recipient handler. [**get_deposits_for_transaction**](DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. [**update_deposits**](DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. @@ -101,9 +101,9 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## get_deposits_for_input_address +## get_deposits_for_recipient -> models::GetDepositsResponse get_deposits_for_input_address(input_address, next_token, page_size) +> models::GetDepositsResponse get_deposits_for_recipient(recipient, next_token, page_size) Get deposits by recipient handler. ### Parameters @@ -111,7 +111,7 @@ Get deposits by recipient handler. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**input_address** | **String** | the address from which the deposit was made. | [required] | +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | **next_token** | Option<**String**> | the next token value from the previous return of this api call. | | **page_size** | Option<**i32**> | the maximum number of items in the response list. | | @@ -131,9 +131,9 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## get_deposits_for_recipient +## get_deposits_for_reclaim_pubkey -> models::GetDepositsResponse get_deposits_for_recipient(recipient, next_token, page_size) +> models::GetDepositsResponse get_deposits_for_reclaim_pubkey(reclaim_pubkey, next_token, page_size) Get deposits by recipient handler. ### Parameters @@ -141,7 +141,7 @@ Get deposits by recipient handler. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | +**reclaim_pubkey** | **String** | the reclaim schnorr public key to search by when getting all deposits. | [required] | **next_token** | Option<**String**> | the next token value from the previous return of this api call. | | **page_size** | Option<**i32**> | the maximum number of items in the response list. | | diff --git a/.generated-sources/emily/client/rust/public/src/apis/cors_api.rs b/.generated-sources/emily/client/rust/public/src/apis/cors_api.rs index 5515494c7..8783c7a28 100644 --- a/.generated-sources/emily/client/rust/public/src/apis/cors_api.rs +++ b/.generated-sources/emily/client/rust/public/src/apis/cors_api.rs @@ -27,24 +27,24 @@ pub enum ChainstateOptionsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`deposit_input_address_input_address_options`] +/// struct for typed errors of method [`deposit_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum DepositInputAddressInputAddressOptionsError { +pub enum DepositOptionsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`deposit_options`] +/// struct for typed errors of method [`deposit_recipient_recipient_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum DepositOptionsError { +pub enum DepositRecipientRecipientOptionsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`deposit_recipient_recipient_options`] +/// struct for typed errors of method [`deposit_reclaim_pubkey_reclaim_pubkey_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum DepositRecipientRecipientOptionsError { +pub enum DepositReclaimPubkeyReclaimPubkeyOptionsError { UnknownValue(serde_json::Value), } @@ -184,19 +184,14 @@ pub async fn chainstate_options( } /// Handles CORS preflight requests -pub async fn deposit_input_address_input_address_options( +pub async fn deposit_options( configuration: &configuration::Configuration, - input_address: &str, -) -> Result<(), Error> { +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; - let local_var_uri_str = format!( - "{}/deposit/input-address/{inputAddress}", - local_var_configuration.base_path, - inputAddress = crate::apis::urlencode(input_address) - ); + let local_var_uri_str = format!("{}/deposit", local_var_configuration.base_path); let mut local_var_req_builder = local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); @@ -214,7 +209,7 @@ pub async fn deposit_input_address_input_address_options( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { Ok(()) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -226,14 +221,19 @@ pub async fn deposit_input_address_input_address_options( } /// Handles CORS preflight requests -pub async fn deposit_options( +pub async fn deposit_recipient_recipient_options( configuration: &configuration::Configuration, -) -> Result<(), Error> { + recipient: &str, +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; - let local_var_uri_str = format!("{}/deposit", local_var_configuration.base_path); + let local_var_uri_str = format!( + "{}/deposit/recipient/{recipient}", + local_var_configuration.base_path, + recipient = crate::apis::urlencode(recipient) + ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); @@ -251,7 +251,7 @@ pub async fn deposit_options( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { Ok(()) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -263,18 +263,18 @@ pub async fn deposit_options( } /// Handles CORS preflight requests -pub async fn deposit_recipient_recipient_options( +pub async fn deposit_reclaim_pubkey_reclaim_pubkey_options( configuration: &configuration::Configuration, - recipient: &str, -) -> Result<(), Error> { + reclaim_pubkey: &str, +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/deposit/recipient/{recipient}", + "{}/deposit/reclaim-pubkey/{reclaimPubkey}", local_var_configuration.base_path, - recipient = crate::apis::urlencode(recipient) + reclaimPubkey = crate::apis::urlencode(reclaim_pubkey) ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); @@ -293,7 +293,7 @@ pub async fn deposit_recipient_recipient_options( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { Ok(()) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, diff --git a/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs b/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs index 10af926cd..b4cf15725 100644 --- a/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs +++ b/.generated-sources/emily/client/rust/public/src/apis/deposit_api.rs @@ -47,10 +47,10 @@ pub enum GetDepositsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`get_deposits_for_input_address`] +/// struct for typed errors of method [`get_deposits_for_recipient`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum GetDepositsForInputAddressError { +pub enum GetDepositsForRecipientError { Status400(models::ErrorResponse), Status404(models::ErrorResponse), Status405(models::ErrorResponse), @@ -58,10 +58,10 @@ pub enum GetDepositsForInputAddressError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`get_deposits_for_recipient`] +/// struct for typed errors of method [`get_deposits_for_reclaim_pubkey`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum GetDepositsForRecipientError { +pub enum GetDepositsForReclaimPubkeyError { Status400(models::ErrorResponse), Status404(models::ErrorResponse), Status405(models::ErrorResponse), @@ -220,20 +220,20 @@ pub async fn get_deposits( } } -pub async fn get_deposits_for_input_address( +pub async fn get_deposits_for_recipient( configuration: &configuration::Configuration, - input_address: &str, + recipient: &str, next_token: Option<&str>, page_size: Option, -) -> Result> { +) -> Result> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/deposit/input-address/{inputAddress}", + "{}/deposit/recipient/{recipient}", local_var_configuration.base_path, - inputAddress = crate::apis::urlencode(input_address) + recipient = crate::apis::urlencode(recipient) ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); @@ -260,7 +260,7 @@ pub async fn get_deposits_for_input_address( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { serde_json::from_str(&local_var_content).map_err(Error::from) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -271,20 +271,20 @@ pub async fn get_deposits_for_input_address( } } -pub async fn get_deposits_for_recipient( +pub async fn get_deposits_for_reclaim_pubkey( configuration: &configuration::Configuration, - recipient: &str, + reclaim_pubkey: &str, next_token: Option<&str>, page_size: Option, -) -> Result> { +) -> Result> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/deposit/recipient/{recipient}", + "{}/deposit/reclaim-pubkey/{reclaimPubkey}", local_var_configuration.base_path, - recipient = crate::apis::urlencode(recipient) + reclaimPubkey = crate::apis::urlencode(reclaim_pubkey) ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); @@ -311,7 +311,7 @@ pub async fn get_deposits_for_recipient( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { serde_json::from_str(&local_var_content).map_err(Error::from) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, diff --git a/.generated-sources/emily/client/rust/testing/README.md b/.generated-sources/emily/client/rust/testing/README.md index 11e9d04f6..407f9f369 100644 --- a/.generated-sources/emily/client/rust/testing/README.md +++ b/.generated-sources/emily/client/rust/testing/README.md @@ -28,9 +28,9 @@ Class | Method | HTTP request | Description ------------ | ------------- | ------------- | ------------- *CorsApi* | [**chainstate_height_options**](docs/CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support *CorsApi* | [**chainstate_options**](docs/CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support -*CorsApi* | [**deposit_input_address_input_address_options**](docs/CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support *CorsApi* | [**deposit_options**](docs/CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support *CorsApi* | [**deposit_recipient_recipient_options**](docs/CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support +*CorsApi* | [**deposit_reclaim_pubkey_reclaim_pubkey_options**](docs/CorsApi.md#deposit_reclaim_pubkey_reclaim_pubkey_options) | **OPTIONS** /deposit/reclaim-pubkey/{reclaimPubkey} | CORS support *CorsApi* | [**deposit_txid_index_options**](docs/CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support *CorsApi* | [**deposit_txid_options**](docs/CorsApi.md#deposit_txid_options) | **OPTIONS** /deposit/{txid} | CORS support *CorsApi* | [**health_options**](docs/CorsApi.md#health_options) | **OPTIONS** /health | CORS support @@ -46,8 +46,8 @@ Class | Method | HTTP request | Description *DepositApi* | [**create_deposit**](docs/DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. *DepositApi* | [**get_deposit**](docs/DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. *DepositApi* | [**get_deposits**](docs/DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. -*DepositApi* | [**get_deposits_for_input_address**](docs/DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_recipient**](docs/DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. +*DepositApi* | [**get_deposits_for_reclaim_pubkey**](docs/DepositApi.md#get_deposits_for_reclaim_pubkey) | **GET** /deposit/reclaim-pubkey/{reclaimPubkey} | Get deposits by recipient handler. *DepositApi* | [**get_deposits_for_transaction**](docs/DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. *DepositApi* | [**update_deposits**](docs/DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. *HealthApi* | [**check_health**](docs/HealthApi.md#check_health) | **GET** /health | Get health handler. diff --git a/.generated-sources/emily/client/rust/testing/docs/CorsApi.md b/.generated-sources/emily/client/rust/testing/docs/CorsApi.md index a9303a3e3..a0292ac98 100644 --- a/.generated-sources/emily/client/rust/testing/docs/CorsApi.md +++ b/.generated-sources/emily/client/rust/testing/docs/CorsApi.md @@ -6,9 +6,9 @@ Method | HTTP request | Description ------------- | ------------- | ------------- [**chainstate_height_options**](CorsApi.md#chainstate_height_options) | **OPTIONS** /chainstate/{height} | CORS support [**chainstate_options**](CorsApi.md#chainstate_options) | **OPTIONS** /chainstate | CORS support -[**deposit_input_address_input_address_options**](CorsApi.md#deposit_input_address_input_address_options) | **OPTIONS** /deposit/input-address/{inputAddress} | CORS support [**deposit_options**](CorsApi.md#deposit_options) | **OPTIONS** /deposit | CORS support [**deposit_recipient_recipient_options**](CorsApi.md#deposit_recipient_recipient_options) | **OPTIONS** /deposit/recipient/{recipient} | CORS support +[**deposit_reclaim_pubkey_reclaim_pubkey_options**](CorsApi.md#deposit_reclaim_pubkey_reclaim_pubkey_options) | **OPTIONS** /deposit/reclaim-pubkey/{reclaimPubkey} | CORS support [**deposit_txid_index_options**](CorsApi.md#deposit_txid_index_options) | **OPTIONS** /deposit/{txid}/{index} | CORS support [**deposit_txid_options**](CorsApi.md#deposit_txid_options) | **OPTIONS** /deposit/{txid} | CORS support [**health_options**](CorsApi.md#health_options) | **OPTIONS** /health | CORS support @@ -77,19 +77,16 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## deposit_input_address_input_address_options +## deposit_options -> deposit_input_address_input_address_options(input_address) +> deposit_options() CORS support Handles CORS preflight requests ### Parameters - -Name | Type | Description | Required | Notes -------------- | ------------- | ------------- | ------------- | ------------- -**input_address** | **String** | the address from which the deposit was made. | [required] | +This endpoint does not need any parameter. ### Return type @@ -107,16 +104,19 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## deposit_options +## deposit_recipient_recipient_options -> deposit_options() +> deposit_recipient_recipient_options(recipient) CORS support Handles CORS preflight requests ### Parameters -This endpoint does not need any parameter. + +Name | Type | Description | Required | Notes +------------- | ------------- | ------------- | ------------- | ------------- +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | ### Return type @@ -134,9 +134,9 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## deposit_recipient_recipient_options +## deposit_reclaim_pubkey_reclaim_pubkey_options -> deposit_recipient_recipient_options(recipient) +> deposit_reclaim_pubkey_reclaim_pubkey_options(reclaim_pubkey) CORS support Handles CORS preflight requests @@ -146,7 +146,7 @@ Handles CORS preflight requests Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | +**reclaim_pubkey** | **String** | the reclaim schnorr public key to search by when getting all deposits. | [required] | ### Return type diff --git a/.generated-sources/emily/client/rust/testing/docs/DepositApi.md b/.generated-sources/emily/client/rust/testing/docs/DepositApi.md index 3c14b1d89..ee6001127 100644 --- a/.generated-sources/emily/client/rust/testing/docs/DepositApi.md +++ b/.generated-sources/emily/client/rust/testing/docs/DepositApi.md @@ -7,8 +7,8 @@ Method | HTTP request | Description [**create_deposit**](DepositApi.md#create_deposit) | **POST** /deposit | Create deposit handler. [**get_deposit**](DepositApi.md#get_deposit) | **GET** /deposit/{txid}/{index} | Get deposit handler. [**get_deposits**](DepositApi.md#get_deposits) | **GET** /deposit | Get deposits handler. -[**get_deposits_for_input_address**](DepositApi.md#get_deposits_for_input_address) | **GET** /deposit/input-address/{inputAddress} | Get deposits by recipient handler. [**get_deposits_for_recipient**](DepositApi.md#get_deposits_for_recipient) | **GET** /deposit/recipient/{recipient} | Get deposits by recipient handler. +[**get_deposits_for_reclaim_pubkey**](DepositApi.md#get_deposits_for_reclaim_pubkey) | **GET** /deposit/reclaim-pubkey/{reclaimPubkey} | Get deposits by recipient handler. [**get_deposits_for_transaction**](DepositApi.md#get_deposits_for_transaction) | **GET** /deposit/{txid} | Get deposits for transaction handler. [**update_deposits**](DepositApi.md#update_deposits) | **PUT** /deposit | Update deposits handler. @@ -101,9 +101,9 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## get_deposits_for_input_address +## get_deposits_for_recipient -> models::GetDepositsResponse get_deposits_for_input_address(input_address, next_token, page_size) +> models::GetDepositsResponse get_deposits_for_recipient(recipient, next_token, page_size) Get deposits by recipient handler. ### Parameters @@ -111,7 +111,7 @@ Get deposits by recipient handler. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**input_address** | **String** | the address from which the deposit was made. | [required] | +**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | **next_token** | Option<**String**> | the next token value from the previous return of this api call. | | **page_size** | Option<**i32**> | the maximum number of items in the response list. | | @@ -131,9 +131,9 @@ No authorization required [[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) -## get_deposits_for_recipient +## get_deposits_for_reclaim_pubkey -> models::GetDepositsResponse get_deposits_for_recipient(recipient, next_token, page_size) +> models::GetDepositsResponse get_deposits_for_reclaim_pubkey(reclaim_pubkey, next_token, page_size) Get deposits by recipient handler. ### Parameters @@ -141,7 +141,7 @@ Get deposits by recipient handler. Name | Type | Description | Required | Notes ------------- | ------------- | ------------- | ------------- | ------------- -**recipient** | **String** | the recipient to search by when getting all deposits. | [required] | +**reclaim_pubkey** | **String** | the reclaim schnorr public key to search by when getting all deposits. | [required] | **next_token** | Option<**String**> | the next token value from the previous return of this api call. | | **page_size** | Option<**i32**> | the maximum number of items in the response list. | | diff --git a/.generated-sources/emily/client/rust/testing/src/apis/cors_api.rs b/.generated-sources/emily/client/rust/testing/src/apis/cors_api.rs index 5515494c7..8783c7a28 100644 --- a/.generated-sources/emily/client/rust/testing/src/apis/cors_api.rs +++ b/.generated-sources/emily/client/rust/testing/src/apis/cors_api.rs @@ -27,24 +27,24 @@ pub enum ChainstateOptionsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`deposit_input_address_input_address_options`] +/// struct for typed errors of method [`deposit_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum DepositInputAddressInputAddressOptionsError { +pub enum DepositOptionsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`deposit_options`] +/// struct for typed errors of method [`deposit_recipient_recipient_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum DepositOptionsError { +pub enum DepositRecipientRecipientOptionsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`deposit_recipient_recipient_options`] +/// struct for typed errors of method [`deposit_reclaim_pubkey_reclaim_pubkey_options`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum DepositRecipientRecipientOptionsError { +pub enum DepositReclaimPubkeyReclaimPubkeyOptionsError { UnknownValue(serde_json::Value), } @@ -184,19 +184,14 @@ pub async fn chainstate_options( } /// Handles CORS preflight requests -pub async fn deposit_input_address_input_address_options( +pub async fn deposit_options( configuration: &configuration::Configuration, - input_address: &str, -) -> Result<(), Error> { +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; - let local_var_uri_str = format!( - "{}/deposit/input-address/{inputAddress}", - local_var_configuration.base_path, - inputAddress = crate::apis::urlencode(input_address) - ); + let local_var_uri_str = format!("{}/deposit", local_var_configuration.base_path); let mut local_var_req_builder = local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); @@ -214,7 +209,7 @@ pub async fn deposit_input_address_input_address_options( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { Ok(()) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -226,14 +221,19 @@ pub async fn deposit_input_address_input_address_options( } /// Handles CORS preflight requests -pub async fn deposit_options( +pub async fn deposit_recipient_recipient_options( configuration: &configuration::Configuration, -) -> Result<(), Error> { + recipient: &str, +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; - let local_var_uri_str = format!("{}/deposit", local_var_configuration.base_path); + let local_var_uri_str = format!( + "{}/deposit/recipient/{recipient}", + local_var_configuration.base_path, + recipient = crate::apis::urlencode(recipient) + ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); @@ -251,7 +251,7 @@ pub async fn deposit_options( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { Ok(()) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -263,18 +263,18 @@ pub async fn deposit_options( } /// Handles CORS preflight requests -pub async fn deposit_recipient_recipient_options( +pub async fn deposit_reclaim_pubkey_reclaim_pubkey_options( configuration: &configuration::Configuration, - recipient: &str, -) -> Result<(), Error> { + reclaim_pubkey: &str, +) -> Result<(), Error> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/deposit/recipient/{recipient}", + "{}/deposit/reclaim-pubkey/{reclaimPubkey}", local_var_configuration.base_path, - recipient = crate::apis::urlencode(recipient) + reclaimPubkey = crate::apis::urlencode(reclaim_pubkey) ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::OPTIONS, local_var_uri_str.as_str()); @@ -293,7 +293,7 @@ pub async fn deposit_recipient_recipient_options( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { Ok(()) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, diff --git a/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs b/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs index 10af926cd..b4cf15725 100644 --- a/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs +++ b/.generated-sources/emily/client/rust/testing/src/apis/deposit_api.rs @@ -47,10 +47,10 @@ pub enum GetDepositsError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`get_deposits_for_input_address`] +/// struct for typed errors of method [`get_deposits_for_recipient`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum GetDepositsForInputAddressError { +pub enum GetDepositsForRecipientError { Status400(models::ErrorResponse), Status404(models::ErrorResponse), Status405(models::ErrorResponse), @@ -58,10 +58,10 @@ pub enum GetDepositsForInputAddressError { UnknownValue(serde_json::Value), } -/// struct for typed errors of method [`get_deposits_for_recipient`] +/// struct for typed errors of method [`get_deposits_for_reclaim_pubkey`] #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(untagged)] -pub enum GetDepositsForRecipientError { +pub enum GetDepositsForReclaimPubkeyError { Status400(models::ErrorResponse), Status404(models::ErrorResponse), Status405(models::ErrorResponse), @@ -220,20 +220,20 @@ pub async fn get_deposits( } } -pub async fn get_deposits_for_input_address( +pub async fn get_deposits_for_recipient( configuration: &configuration::Configuration, - input_address: &str, + recipient: &str, next_token: Option<&str>, page_size: Option, -) -> Result> { +) -> Result> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/deposit/input-address/{inputAddress}", + "{}/deposit/recipient/{recipient}", local_var_configuration.base_path, - inputAddress = crate::apis::urlencode(input_address) + recipient = crate::apis::urlencode(recipient) ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); @@ -260,7 +260,7 @@ pub async fn get_deposits_for_input_address( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { serde_json::from_str(&local_var_content).map_err(Error::from) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status, @@ -271,20 +271,20 @@ pub async fn get_deposits_for_input_address( } } -pub async fn get_deposits_for_recipient( +pub async fn get_deposits_for_reclaim_pubkey( configuration: &configuration::Configuration, - recipient: &str, + reclaim_pubkey: &str, next_token: Option<&str>, page_size: Option, -) -> Result> { +) -> Result> { let local_var_configuration = configuration; let local_var_client = &local_var_configuration.client; let local_var_uri_str = format!( - "{}/deposit/recipient/{recipient}", + "{}/deposit/reclaim-pubkey/{reclaimPubkey}", local_var_configuration.base_path, - recipient = crate::apis::urlencode(recipient) + reclaimPubkey = crate::apis::urlencode(reclaim_pubkey) ); let mut local_var_req_builder = local_var_client.request(reqwest::Method::GET, local_var_uri_str.as_str()); @@ -311,7 +311,7 @@ pub async fn get_deposits_for_recipient( if !local_var_status.is_client_error() && !local_var_status.is_server_error() { serde_json::from_str(&local_var_content).map_err(Error::from) } else { - let local_var_entity: Option = + let local_var_entity: Option = serde_json::from_str(&local_var_content).ok(); let local_var_error = ResponseContent { status: local_var_status,