mirror of
https://github.com/RoboSats/taptrade-core.git
synced 2025-12-22 21:15:32 +00:00
complete bond validation function
This commit is contained in:
@ -21,7 +21,7 @@ struct AwaitingBondOffer {
|
|||||||
bond_amount_sat: u64,
|
bond_amount_sat: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct AwaitinigTakerOffer {
|
struct AwaitingTakerOffer {
|
||||||
offer_id: String,
|
offer_id: String,
|
||||||
robohash_maker: Vec<u8>,
|
robohash_maker: Vec<u8>,
|
||||||
is_buy_order: bool,
|
is_buy_order: bool,
|
||||||
@ -160,7 +160,7 @@ impl CoordinatorDB {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fetch_and_delete_offer_from_bond_table(
|
async fn fetch_and_delete_offer_from_bond_table(
|
||||||
&self,
|
&self,
|
||||||
robohash_hex: &str,
|
robohash_hex: &str,
|
||||||
) -> Result<AwaitingBondOffer> {
|
) -> Result<AwaitingBondOffer> {
|
||||||
@ -271,10 +271,10 @@ impl CoordinatorDB {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn fetch_and_delete_offer_from_public_offers_table(
|
async fn fetch_and_delete_offer_from_public_offers_table(
|
||||||
&self,
|
&self,
|
||||||
offer_id_hex: &str,
|
offer_id_hex: &str,
|
||||||
) -> Result<AwaitinigTakerOffer> {
|
) -> Result<AwaitingTakerOffer> {
|
||||||
let fetched_values = sqlx::query_as::<_, (Vec<u8>, bool, i64, i32, i64, String, i64, String, String, String, String)> (
|
let fetched_values = sqlx::query_as::<_, (Vec<u8>, bool, i64, i32, i64, String, i64, String, String, String, String)> (
|
||||||
"SELECT robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address,
|
"SELECT robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address,
|
||||||
musig_pub_nonce_hex, musig_pubkey_hex FROM active_maker_offers WHERE <unique_identifier_column> = ?",
|
musig_pub_nonce_hex, musig_pubkey_hex FROM active_maker_offers WHERE <unique_identifier_column> = ?",
|
||||||
@ -289,7 +289,7 @@ impl CoordinatorDB {
|
|||||||
.execute(&*self.db_pool)
|
.execute(&*self.db_pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
Ok(AwaitinigTakerOffer {
|
Ok(AwaitingTakerOffer {
|
||||||
offer_id: offer_id_hex.to_string(),
|
offer_id: offer_id_hex.to_string(),
|
||||||
robohash_maker: fetched_values.0,
|
robohash_maker: fetched_values.0,
|
||||||
is_buy_order: fetched_values.1,
|
is_buy_order: fetched_values.1,
|
||||||
@ -443,21 +443,21 @@ mod tests {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_fetch_maker_request() -> Result<()> {
|
async fn test_fetch_maker_request() -> Result<()> {
|
||||||
let database = create_coordinator().await?;
|
let database = create_coordinator().await?;
|
||||||
|
|
||||||
// Create a sample order request and insert it into the database
|
// Create a sample order request and insert it into the database
|
||||||
let robohash_hex = "a3f1f1f0e2f3f4f5";
|
let robohash_hex = "a3f1f1f0e2f3f4f5";
|
||||||
let order_request = (
|
let order_request = (
|
||||||
hex::decode(robohash_hex).unwrap(),
|
hex::decode(robohash_hex).unwrap(),
|
||||||
true, // is_buy_order
|
true, // is_buy_order
|
||||||
1000, // amount_satoshi
|
1000, // amount_satoshi
|
||||||
50, // bond_ratio
|
50, // bond_ratio
|
||||||
1234567890, // offer_duration_ts
|
1234567890, // offer_duration_ts
|
||||||
"1BitcoinAddress".to_string(), // bond_address
|
"1BitcoinAddress".to_string(), // bond_address
|
||||||
500, // bond_amount_sat
|
500, // bond_amount_sat
|
||||||
);
|
);
|
||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
@ -475,33 +475,35 @@ mod tests {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Fetch and delete the order request
|
// Fetch and delete the order request
|
||||||
let fetched_offer = database.fetch_maker_request(&robohash_hex.to_string()).await?;
|
let fetched_offer = database
|
||||||
|
.fetch_maker_request(&robohash_hex.to_string())
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify the result
|
// Verify the result
|
||||||
let expected = BondRequirementResponse {
|
let expected = BondRequirementResponse {
|
||||||
bond_address: "1BitcoinAddress".to_string(),
|
bond_address: "1BitcoinAddress".to_string(),
|
||||||
locking_amount_sat: 500_u64,
|
locking_amount_sat: 500_u64,
|
||||||
};
|
};
|
||||||
assert_eq!(fetched_offer, expected);
|
assert_eq!(fetched_offer, expected);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_fetch_and_delete_offer_from_bond_table() -> Result<()> {
|
async fn test_fetch_and_delete_offer_from_bond_table() -> Result<()> {
|
||||||
// Set up the in-memory database
|
// Set up the in-memory database
|
||||||
let database = create_coordinator().await?;
|
let database = create_coordinator().await?;
|
||||||
|
|
||||||
// Create a sample order request and insert it into the database
|
// Create a sample order request and insert it into the database
|
||||||
let robohash_hex = "a3f1f1f0e2f3f4f5";
|
let robohash_hex = "a3f1f1f0e2f3f4f5";
|
||||||
let order_request = (
|
let order_request = (
|
||||||
hex::decode(robohash_hex).unwrap(),
|
hex::decode(robohash_hex).unwrap(),
|
||||||
true, // is_buy_order
|
true, // is_buy_order
|
||||||
1000, // amount_satoshi
|
1000, // amount_satoshi
|
||||||
50, // bond_ratio
|
50, // bond_ratio
|
||||||
1234567890, // offer_duration_ts
|
1234567890, // offer_duration_ts
|
||||||
"1BitcoinAddress".to_string(), // bond_address
|
"1BitcoinAddress".to_string(), // bond_address
|
||||||
500, // bond_amount_sat
|
500, // bond_amount_sat
|
||||||
);
|
);
|
||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
@ -519,7 +521,9 @@ mod tests {
|
|||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Fetch and delete the order request
|
// Fetch and delete the order request
|
||||||
let fetched_offer = database.fetch_and_delete_offer_from_bond_table(robohash_hex).await?;
|
let fetched_offer = database
|
||||||
|
.fetch_and_delete_offer_from_bond_table(robohash_hex)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify the fetched offer
|
// Verify the fetched offer
|
||||||
let expected_offer = AwaitingBondOffer {
|
let expected_offer = AwaitingBondOffer {
|
||||||
@ -544,24 +548,23 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_move_offer_to_active() -> Result<()> {
|
async fn test_move_offer_to_active() -> Result<()> {
|
||||||
// Create a temporary SQLite database
|
// Create a temporary SQLite database
|
||||||
let database = create_coordinator().await?;
|
let database = create_coordinator().await?;
|
||||||
|
|
||||||
|
// Insert a test entry into maker_requests
|
||||||
// Insert a test entry into maker_requests
|
let robohash_hex = "a3f1f1f0e2f3f4f5";
|
||||||
let robohash_hex = "a3f1f1f0e2f3f4f5";
|
let order_request = (
|
||||||
let order_request = (
|
hex::decode(robohash_hex).unwrap(),
|
||||||
hex::decode(robohash_hex).unwrap(),
|
true, // is_buy_order
|
||||||
true, // is_buy_order
|
1000, // amount_satoshi
|
||||||
1000, // amount_satoshi
|
50, // bond_ratio
|
||||||
50, // bond_ratio
|
1234567890, // offer_duration_ts
|
||||||
1234567890, // offer_duration_ts
|
"1BitcoinAddress".to_string(), // bond_address
|
||||||
"1BitcoinAddress".to_string(), // bond_address
|
500, // bond_amount_sat
|
||||||
500, // bond_amount_sat
|
);
|
||||||
);
|
|
||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"INSERT INTO maker_requests (robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat)
|
"INSERT INTO maker_requests (robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?)",
|
VALUES (?, ?, ?, ?, ?, ?, ?)",
|
||||||
)
|
)
|
||||||
@ -575,87 +578,87 @@ mod tests {
|
|||||||
.execute(&*database.db_pool)
|
.execute(&*database.db_pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Create a sample BondSubmissionRequest
|
// Create a sample BondSubmissionRequest
|
||||||
let bond_submission_request = BondSubmissionRequest {
|
let bond_submission_request = BondSubmissionRequest {
|
||||||
robohash_hex: robohash_hex.to_string(),
|
robohash_hex: robohash_hex.to_string(),
|
||||||
signed_bond_hex: "signedBondHex".to_string(),
|
signed_bond_hex: "signedBondHex".to_string(),
|
||||||
payout_address: "1PayoutAddress".to_string(),
|
payout_address: "1PayoutAddress".to_string(),
|
||||||
musig_pub_nonce_hex: "musigPubNonceHex".to_string(),
|
musig_pub_nonce_hex: "musigPubNonceHex".to_string(),
|
||||||
musig_pubkey_hex: "musigPubkeyHex".to_string(),
|
musig_pubkey_hex: "musigPubkeyHex".to_string(),
|
||||||
};
|
};
|
||||||
|
|
||||||
// Call the move_offer_to_active function
|
// Call the move_offer_to_active function
|
||||||
let offer_id = "sample_offer_id".to_string();
|
let offer_id = "sample_offer_id".to_string();
|
||||||
let taker_bond_address = "1TakerBondAddress".to_string();
|
let taker_bond_address = "1TakerBondAddress".to_string();
|
||||||
let result = database
|
let result = database
|
||||||
.move_offer_to_active(&bond_submission_request, &offer_id, taker_bond_address)
|
.move_offer_to_active(&bond_submission_request, &offer_id, taker_bond_address)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Verify the result
|
// Verify the result
|
||||||
assert_eq!(result, 1234567890); // Verify that the offer_duration_ts is correct
|
assert_eq!(result, 1234567890); // Verify that the offer_duration_ts is correct
|
||||||
|
|
||||||
// Verify that the entry was moved to active_maker_offers
|
// Verify that the entry was moved to active_maker_offers
|
||||||
let active_offer = sqlx::query_as::<_, (String, Vec<u8>, bool, i64, i64, i64, String, i64, String, String, String, String)> (
|
let active_offer = sqlx::query_as::<_, (String, Vec<u8>, bool, i64, i64, i64, String, i64, String, String, String, String)> (
|
||||||
"SELECT offer_id, robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address, musig_pub_nonce_hex, musig_pubkey_hex
|
"SELECT offer_id, robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address, musig_pub_nonce_hex, musig_pubkey_hex
|
||||||
FROM active_maker_offers WHERE offer_id = ?",
|
FROM active_maker_offers WHERE offer_id = ?",
|
||||||
)
|
)
|
||||||
.bind(offer_id)
|
.bind(offer_id)
|
||||||
.fetch_one(&*database.db_pool)
|
.fetch_one(&*database.db_pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
assert_eq!(active_offer.0, "sample_offer_id".to_string());
|
assert_eq!(active_offer.0, "sample_offer_id".to_string());
|
||||||
assert_eq!(hex::encode(active_offer.1), robohash_hex);
|
assert_eq!(hex::encode(active_offer.1), robohash_hex);
|
||||||
assert!(active_offer.2);
|
assert!(active_offer.2);
|
||||||
assert_eq!(active_offer.3, 1000);
|
assert_eq!(active_offer.3, 1000);
|
||||||
assert_eq!(active_offer.4, 50);
|
assert_eq!(active_offer.4, 50);
|
||||||
assert_eq!(active_offer.5, 1234567890);
|
assert_eq!(active_offer.5, 1234567890);
|
||||||
assert_eq!(active_offer.6, "1BitcoinAddress".to_string());
|
assert_eq!(active_offer.6, "1BitcoinAddress".to_string());
|
||||||
assert_eq!(active_offer.7, 500);
|
assert_eq!(active_offer.7, 500);
|
||||||
assert_eq!(active_offer.8, "signedBondHex".to_string());
|
assert_eq!(active_offer.8, "signedBondHex".to_string());
|
||||||
assert_eq!(active_offer.9, "1PayoutAddress".to_string());
|
assert_eq!(active_offer.9, "1PayoutAddress".to_string());
|
||||||
assert_eq!(active_offer.10, "musigPubNonceHex".to_string());
|
assert_eq!(active_offer.10, "musigPubNonceHex".to_string());
|
||||||
assert_eq!(active_offer.11, "musigPubkeyHex".to_string());
|
assert_eq!(active_offer.11, "musigPubkeyHex".to_string());
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_fetch_suitable_offers() -> Result<()> {
|
async fn test_fetch_suitable_offers() -> Result<()> {
|
||||||
let database = create_coordinator().await?;
|
let database = create_coordinator().await?;
|
||||||
// Insert test entries into active_maker_offers
|
// Insert test entries into active_maker_offers
|
||||||
let offers = vec![
|
let offers = vec![
|
||||||
(
|
(
|
||||||
"offer_id_1",
|
"offer_id_1",
|
||||||
true, // is_buy_order
|
true, // is_buy_order
|
||||||
15000, // amount_sat
|
15000, // amount_sat
|
||||||
100, // bond_ratio
|
100, // bond_ratio
|
||||||
1234567890, // offer_duration_ts
|
1234567890, // offer_duration_ts
|
||||||
"1BondAddress".to_string(), // bond_address
|
"1BondAddress".to_string(), // bond_address
|
||||||
50, // bond_amount_sat
|
50, // bond_amount_sat
|
||||||
"signedBondHex".to_string(),
|
"signedBondHex".to_string(),
|
||||||
"1PayoutAddress".to_string(),
|
"1PayoutAddress".to_string(),
|
||||||
"musigPubNonceHex".to_string(),
|
"musigPubNonceHex".to_string(),
|
||||||
"musigPubkeyHex".to_string(),
|
"musigPubkeyHex".to_string(),
|
||||||
"1TakerBondAddress".to_string(),
|
"1TakerBondAddress".to_string(),
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
"offer_id_2",
|
"offer_id_2",
|
||||||
true, // is_buy_order
|
true, // is_buy_order
|
||||||
1500, // amount_sat
|
1500, // amount_sat
|
||||||
200, // bond_ratio
|
200, // bond_ratio
|
||||||
1234567891, // offer_duration_ts
|
1234567891, // offer_duration_ts
|
||||||
"2BondAddress".to_string(), // bond_address
|
"2BondAddress".to_string(), // bond_address
|
||||||
100, // bond_amount_sat
|
100, // bond_amount_sat
|
||||||
"signedBondHex2".to_string(),
|
"signedBondHex2".to_string(),
|
||||||
"2PayoutAddress".to_string(),
|
"2PayoutAddress".to_string(),
|
||||||
"musigPubNonceHex2".to_string(),
|
"musigPubNonceHex2".to_string(),
|
||||||
"musigPubkeyHex2".to_string(),
|
"musigPubkeyHex2".to_string(),
|
||||||
"2TakerBondAddress".to_string(),
|
"2TakerBondAddress".to_string(),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
|
|
||||||
for offer in offers {
|
for offer in offers {
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"INSERT INTO active_maker_offers (offer_id, robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address, musig_pub_nonce_hex, musig_pubkey_hex, taker_bond_address)
|
"INSERT INTO active_maker_offers (offer_id, robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address, musig_pub_nonce_hex, musig_pubkey_hex, taker_bond_address)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
)
|
)
|
||||||
@ -674,43 +677,42 @@ mod tests {
|
|||||||
.bind(offer.11.clone())
|
.bind(offer.11.clone())
|
||||||
.execute(&*database.db_pool)
|
.execute(&*database.db_pool)
|
||||||
.await?;
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create a sample OffersRequest
|
||||||
|
let offers_request = OffersRequest {
|
||||||
|
buy_offers: true,
|
||||||
|
amount_min_sat: 1000,
|
||||||
|
amount_max_sat: 2000,
|
||||||
|
};
|
||||||
|
|
||||||
// Create a sample OffersRequest
|
// Call the fetch_suitable_offers function
|
||||||
let offers_request = OffersRequest {
|
let result = database.fetch_suitable_offers(&offers_request).await?;
|
||||||
buy_offers: true,
|
|
||||||
amount_min_sat: 1000,
|
|
||||||
amount_max_sat: 2000,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Call the fetch_suitable_offers function
|
|
||||||
let result = database.fetch_suitable_offers(&offers_request).await?;
|
|
||||||
|
|
||||||
println!("{:?}", result);
|
println!("{:?}", result);
|
||||||
// Verify the result
|
// Verify the result
|
||||||
assert!(result.is_some());
|
assert!(result.is_some());
|
||||||
let available_offers = result.unwrap();
|
let available_offers = result.unwrap();
|
||||||
assert_eq!(available_offers.len(), 1);
|
assert_eq!(available_offers.len(), 1);
|
||||||
let offer = &available_offers[0];
|
let offer = &available_offers[0];
|
||||||
assert_eq!(offer.offer_id_hex, "offer_id_2");
|
assert_eq!(offer.offer_id_hex, "offer_id_2");
|
||||||
assert_eq!(offer.amount_sat, 1500);
|
assert_eq!(offer.amount_sat, 1500);
|
||||||
assert_eq!(offer.required_bond_amount_sat, 100);
|
assert_eq!(offer.required_bond_amount_sat, 100);
|
||||||
assert_eq!(offer.bond_locking_address, "2TakerBondAddress");
|
assert_eq!(offer.bond_locking_address, "2TakerBondAddress");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_fetch_taker_bond_requirements() -> Result<()> {
|
async fn test_fetch_taker_bond_requirements() -> Result<()> {
|
||||||
let database = create_coordinator().await?;
|
let database = create_coordinator().await?;
|
||||||
|
|
||||||
// Insert a test entry into active_maker_offers
|
// Insert a test entry into active_maker_offers
|
||||||
let offer_id_hex = "offer_id_1";
|
let offer_id_hex = "offer_id_1";
|
||||||
let taker_bond_address = "1TakerBondAddress";
|
let taker_bond_address = "1TakerBondAddress";
|
||||||
let bond_amount_sat = 100;
|
let bond_amount_sat = 100;
|
||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"INSERT INTO active_maker_offers (offer_id, robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address, musig_pub_nonce_hex, musig_pubkey_hex, taker_bond_address)
|
"INSERT INTO active_maker_offers (offer_id, robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address, musig_pub_nonce_hex, musig_pubkey_hex, taker_bond_address)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
)
|
)
|
||||||
@ -730,35 +732,37 @@ mod tests {
|
|||||||
.execute(&*database.db_pool)
|
.execute(&*database.db_pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Call the fetch_taker_bond_requirements function
|
// Call the fetch_taker_bond_requirements function
|
||||||
let result = database.fetch_taker_bond_requirements(&offer_id_hex.to_string()).await?;
|
let result = database
|
||||||
|
.fetch_taker_bond_requirements(&offer_id_hex.to_string())
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify the result
|
// Verify the result
|
||||||
assert_eq!(result.bond_address, taker_bond_address);
|
assert_eq!(result.bond_address, taker_bond_address);
|
||||||
assert_eq!(result.locking_amount_sat, bond_amount_sat as u64);
|
assert_eq!(result.locking_amount_sat, bond_amount_sat as u64);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn test_fetch_and_delete_offer_from_public_offers_table() -> Result<()> {
|
async fn test_fetch_and_delete_offer_from_public_offers_table() -> Result<()> {
|
||||||
let database = create_coordinator().await?;
|
let database = create_coordinator().await?;
|
||||||
|
|
||||||
// Insert a test entry into active_maker_offers
|
// Insert a test entry into active_maker_offers
|
||||||
let offer_id_hex = "offer_id_1";
|
let offer_id_hex = "offer_id_1";
|
||||||
let robohash = hex::decode("a3f1f1f0e2f3f4f5").unwrap(); // Example robohash
|
let robohash = hex::decode("a3f1f1f0e2f3f4f5").unwrap(); // Example robohash
|
||||||
let is_buy_order = true;
|
let is_buy_order = true;
|
||||||
let amount_sat = 1000;
|
let amount_sat = 1000;
|
||||||
let bond_ratio = 50;
|
let bond_ratio = 50;
|
||||||
let offer_duration_ts = 1234567890;
|
let offer_duration_ts = 1234567890;
|
||||||
let bond_address = "1BondAddress".to_string();
|
let bond_address = "1BondAddress".to_string();
|
||||||
let bond_amount_sat = 500;
|
let bond_amount_sat = 500;
|
||||||
let bond_tx_hex = "signedBondHex".to_string();
|
let bond_tx_hex = "signedBondHex".to_string();
|
||||||
let payout_address = "1PayoutAddress".to_string();
|
let payout_address = "1PayoutAddress".to_string();
|
||||||
let musig_pub_nonce_hex = "musigPubNonceHex".to_string();
|
let musig_pub_nonce_hex = "musigPubNonceHex".to_string();
|
||||||
let musig_pubkey_hex = "musigPubkeyHex".to_string();
|
let musig_pubkey_hex = "musigPubkeyHex".to_string();
|
||||||
|
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"INSERT INTO active_maker_offers (offer_id, robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address, musig_pub_nonce_hex, musig_pubkey_hex)
|
"INSERT INTO active_maker_offers (offer_id, robohash, is_buy_order, amount_sat, bond_ratio, offer_duration_ts, bond_address, bond_amount_sat, bond_tx_hex, payout_address, musig_pub_nonce_hex, musig_pubkey_hex)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
|
||||||
)
|
)
|
||||||
@ -777,33 +781,35 @@ mod tests {
|
|||||||
.execute(&*database.db_pool)
|
.execute(&*database.db_pool)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// Call the fetch_and_delete_offer_from_public_offers_table function
|
// Call the fetch_and_delete_offer_from_public_offers_table function
|
||||||
let result = database.fetch_and_delete_offer_from_public_offers_table(offer_id_hex).await?;
|
let result = database
|
||||||
|
.fetch_and_delete_offer_from_public_offers_table(offer_id_hex)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify the result
|
// Verify the result
|
||||||
assert_eq!(result.offer_id, offer_id_hex);
|
assert_eq!(result.offer_id, offer_id_hex);
|
||||||
assert_eq!(result.robohash_maker, robohash);
|
assert_eq!(result.robohash_maker, robohash);
|
||||||
assert_eq!(result.is_buy_order, is_buy_order);
|
assert_eq!(result.is_buy_order, is_buy_order);
|
||||||
assert_eq!(result.amount_sat, amount_sat);
|
assert_eq!(result.amount_sat, amount_sat);
|
||||||
assert_eq!(result.bond_ratio, bond_ratio);
|
assert_eq!(result.bond_ratio, bond_ratio);
|
||||||
assert_eq!(result.offer_duration_ts, offer_duration_ts);
|
assert_eq!(result.offer_duration_ts, offer_duration_ts);
|
||||||
assert_eq!(result.bond_address_maker, bond_address);
|
assert_eq!(result.bond_address_maker, bond_address);
|
||||||
assert_eq!(result.bond_amount_sat, bond_amount_sat);
|
assert_eq!(result.bond_amount_sat, bond_amount_sat);
|
||||||
assert_eq!(result.bond_tx_hex_maker, bond_tx_hex);
|
assert_eq!(result.bond_tx_hex_maker, bond_tx_hex);
|
||||||
assert_eq!(result.payout_address_maker, payout_address);
|
assert_eq!(result.payout_address_maker, payout_address);
|
||||||
assert_eq!(result.musig_pub_nonce_hex_maker, musig_pub_nonce_hex);
|
assert_eq!(result.musig_pub_nonce_hex_maker, musig_pub_nonce_hex);
|
||||||
assert_eq!(result.musig_pubkey_hex_maker, musig_pubkey_hex);
|
assert_eq!(result.musig_pubkey_hex_maker, musig_pubkey_hex);
|
||||||
|
|
||||||
// Verify the deletion
|
// Verify the deletion
|
||||||
let remaining_offers = sqlx::query("SELECT COUNT(*) FROM active_maker_offers WHERE offer_id = ?")
|
let remaining_offers =
|
||||||
.bind(offer_id_hex)
|
sqlx::query("SELECT COUNT(*) FROM active_maker_offers WHERE offer_id = ?")
|
||||||
.fetch_one(&*database.db_pool)
|
.bind(offer_id_hex)
|
||||||
.await?;
|
.fetch_one(&*database.db_pool)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let remaining_offers_count: i64 = remaining_offers.try_get(0)?;
|
let remaining_offers_count: i64 = remaining_offers.try_get(0)?;
|
||||||
assert_eq!(remaining_offers_count, 0);
|
assert_eq!(remaining_offers_count, 0);
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,2 +0,0 @@
|
|||||||
use super::*;
|
|
||||||
use bdk::wallet::verify::verify_tx;
|
|
||||||
@ -64,30 +64,51 @@ impl CoordinatorWallet {
|
|||||||
&self,
|
&self,
|
||||||
bond: &String,
|
bond: &String,
|
||||||
requirements: BondRequirements,
|
requirements: BondRequirements,
|
||||||
) -> Result<bool> {
|
) -> Result<()> {
|
||||||
|
let input_sum: u64;
|
||||||
let tx: Transaction = deserialize(&hex::decode(bond)?)?;
|
let tx: Transaction = deserialize(&hex::decode(bond)?)?;
|
||||||
let wallet = self.wallet.lock().await;
|
{
|
||||||
let blockchain = ElectrumBlockchain::from(Client::new(
|
let blockchain = ElectrumBlockchain::from(Client::new(
|
||||||
&env::var("ELECTRUM_BACKEND")
|
&env::var("ELECTRUM_BACKEND")
|
||||||
.context("Parsing ELECTRUM_BACKEND from .env failed, is it set?")?,
|
.context("Parsing ELECTRUM_BACKEND from .env failed, is it set?")?,
|
||||||
)?);
|
)?);
|
||||||
|
let wallet = self.wallet.lock().await;
|
||||||
|
|
||||||
// we need to test this with signed and invalid/unsigned transactions
|
// we need to test this with signed and invalid/unsigned transactions
|
||||||
// checks signatures and inputs
|
// checks signatures and inputs
|
||||||
if let Err(e) = verify_tx(&tx, &*wallet.database(), &blockchain) {
|
if let Err(e) = verify_tx(&tx, &*wallet.database(), &blockchain) {
|
||||||
dbg!(e);
|
return Err(anyhow!(e));
|
||||||
return Ok(false);
|
}
|
||||||
|
|
||||||
|
// check if the tx has the correct input amounts (have to be >= trading amount)
|
||||||
|
input_sum = match tx.input_sum(&blockchain, &*wallet.database()) {
|
||||||
|
Ok(amount) => {
|
||||||
|
if amount < requirements.min_input_sum_sat {
|
||||||
|
return Err(anyhow!("Bond input sum too small"));
|
||||||
|
}
|
||||||
|
amount
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(anyhow!(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if the tx has the correct input amounts (have to be >= trading amount)
|
|
||||||
if tx.input_sum(&blockchain, &*wallet.database())? < requirements.min_input_sum_sat {
|
|
||||||
return Ok(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if bond output to us is big enough
|
// check if bond output to us is big enough
|
||||||
// trait bond_output_sum
|
let output_sum = match tx.bond_output_sum(&requirements.bond_address) {
|
||||||
|
Ok(amount) => {
|
||||||
|
if amount < requirements.locking_amount_sat {
|
||||||
|
return Err(anyhow!("Bond output sum too small"));
|
||||||
|
}
|
||||||
|
amount
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
return Err(anyhow!(e));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// let valid = tx.verify_tx();
|
if ((input_sum - output_sum) / tx.vsize() as u64) < 200 {
|
||||||
Ok(true)
|
return Err(anyhow!("Bond fee rate too low"));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use bdk::{blockchain::GetTx, database::Database};
|
use bdk::{
|
||||||
|
bitcoin::{Address, Network},
|
||||||
|
blockchain::GetTx,
|
||||||
|
database::Database,
|
||||||
|
};
|
||||||
|
|
||||||
pub trait BondTx {
|
pub trait BondTx {
|
||||||
fn input_sum<D: Database, B: GetTx>(&self, blockchain: &B, db: &D) -> Result<u64>;
|
fn input_sum<D: Database, B: GetTx>(&self, blockchain: &B, db: &D) -> Result<u64>;
|
||||||
@ -35,10 +39,15 @@ impl BondTx for Transaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn bond_output_sum(&self, bond_address: &str) -> Result<u64> {
|
fn bond_output_sum(&self, bond_address: &str) -> Result<u64> {
|
||||||
panic!("implement");
|
let bond_script = Address::from_str(bond_address)?
|
||||||
// let bond_script = ScriptBuf;
|
.require_network(Network::Testnet)?
|
||||||
|
.script_pubkey();
|
||||||
|
|
||||||
for output in self.output.iter() {}
|
for output in self.output.iter() {
|
||||||
Ok(0)
|
if output.script_pubkey == bond_script {
|
||||||
|
return Ok(output.value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(anyhow!("No output to bond address in transaction"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user