Skip to content

Commit

Permalink
feat: add auction tests
Browse files Browse the repository at this point in the history
  • Loading branch information
crisdut committed Dec 8, 2023
1 parent 04c6957 commit e36e6cd
Show file tree
Hide file tree
Showing 3 changed files with 220 additions and 20 deletions.
40 changes: 26 additions & 14 deletions src/rgb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,16 +68,16 @@ use crate::{
MediaView, NextAddressResponse, NextUtxoResponse, NextUtxosResponse, PsbtFeeRequest,
PsbtRequest, PsbtResponse, PublicRgbBidResponse, PublicRgbOfferResponse,
PublicRgbOffersResponse, PublishPsbtRequest, ReIssueRequest, ReIssueResponse,
RgbAuctionBidRequest, RgbAuctionBidResponse, RgbBidDetail, RgbBidRequest, RgbBidResponse,
RgbBidsResponse, RgbInternalSaveTransferRequest, RgbInternalTransferResponse,
RgbInvoiceResponse, RgbOfferBidsResponse, RgbOfferDetail, RgbOfferRequest,
RgbOfferResponse, RgbOfferUpdateRequest, RgbOfferUpdateResponse, RgbOffersResponse,
RgbRemoveTransferRequest, RgbReplaceResponse, RgbSaveTransferRequest, RgbSwapRequest,
RgbSwapResponse, RgbSwapStatusResponse, RgbTransferDetail, RgbTransferRequest,
RgbTransferResponse, RgbTransferStatusResponse, RgbTransfersResponse, SchemaDetail,
SchemasResponse, SignPsbtRequest, SignedPsbtResponse, SimpleContractResponse, TransferType,
TxStatus, UtxoResponse, WatcherDetailResponse, WatcherRequest, WatcherResponse,
WatcherUtxoResponse,
RgbAuctionBidRequest, RgbAuctionBidResponse, RgbAuctionOfferRequest, RgbBidDetail,
RgbBidRequest, RgbBidResponse, RgbBidsResponse, RgbInternalSaveTransferRequest,
RgbInternalTransferResponse, RgbInvoiceResponse, RgbOfferBidsResponse, RgbOfferDetail,
RgbOfferRequest, RgbOfferResponse, RgbOfferUpdateRequest, RgbOfferUpdateResponse,
RgbOffersResponse, RgbRemoveTransferRequest, RgbReplaceResponse, RgbSaveTransferRequest,
RgbSwapRequest, RgbSwapResponse, RgbSwapStatusResponse, RgbTransferDetail,
RgbTransferRequest, RgbTransferResponse, RgbTransferStatusResponse, RgbTransfersResponse,
SchemaDetail, SchemasResponse, SignPsbtRequest, SignedPsbtResponse, SimpleContractResponse,
TransferType, TxStatus, UtxoResponse, WatcherDetailResponse, WatcherRequest,
WatcherResponse, WatcherUtxoResponse,
},
validators::RGBContext,
};
Expand Down Expand Up @@ -989,7 +989,7 @@ pub async fn create_seller_offer(

pub async fn create_auction_offers(
sk: &str,
request: Vec<RgbOfferRequest>,
request: RgbAuctionOfferRequest,
) -> Result<Vec<RgbOfferResponse>, RgbSwapError> {
if let Err(err) = request.validate(&RGBContext::default()) {
let errors = err
Expand All @@ -1012,8 +1012,8 @@ pub async fn create_auction_offers(
let mut resp = vec![];
let mut collection = vec![];
let options = RgbOfferOptions::with_bundle_id(sk.to_owned());
for item in request {
let new_offer = internal_create_seller_offer(
for item in request.offers.clone() {
let mut new_offer = internal_create_seller_offer(
sk,
item,
options.clone(),
Expand Down Expand Up @@ -1042,6 +1042,18 @@ pub async fn create_auction_offers(
let contract_amount =
f64::from_str(&contract_amount).expect("Invalid Contract Amount Value");

let request = SignPsbtRequest {
psbt: seller_psbt,
descriptors: request.sign_keys.clone(),
};

let SignedPsbtResponse {
psbt: final_psbt, ..
} = sign_psbt_file(request)
.await
.map_err(|op| RgbSwapError::WrongPsbtFinal(op.to_string()))?;
new_offer.seller_psbt = final_psbt.clone();

my_offers = my_offers.save_offer(contract_id.clone(), new_offer.clone());
collection.push(RgbOfferSwap::from(new_offer.clone()));

Expand All @@ -1051,7 +1063,7 @@ pub async fn create_auction_offers(
contract_amount,
bitcoin_price,
seller_address: seller_address.to_string(),
seller_psbt: seller_psbt.clone(),
seller_psbt: final_psbt,
});
}

Expand Down
13 changes: 13 additions & 0 deletions src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1309,6 +1309,19 @@ impl UtxoSpentStatus {
}
}

#[derive(Clone, Serialize, Deserialize, Debug, Display, Default, Validate)]
#[garde(context(RGBContext))]
#[serde(rename_all = "camelCase")]
#[display(doc_comments)]
pub struct RgbAuctionOfferRequest {
#[garde(skip)]
pub sign_keys: Vec<SecretString>,

/// List of Offers
#[garde(dive)]
pub offers: Vec<RgbOfferRequest>,
}

#[derive(Clone, Serialize, Deserialize, Debug, Display, Default, Validate)]
#[garde(context(RGBContext))]
#[serde(rename_all = "camelCase")]
Expand Down
187 changes: 181 additions & 6 deletions tests/rgb/integration/swaps.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ use bitmask_core::{
sign_and_publish_psbt_file, sign_psbt_file, sync_wallet,
},
rgb::{
accept_transfer, create_buyer_bid, create_seller_offer, create_swap_transfer,
create_watcher, get_contract, import as import_contract, structs::ContractAmount,
swap::RgbSwapStrategy, update_seller_offer, verify_transfers,
accept_transfer, create_auction_bid, create_auction_offers, create_buyer_bid,
create_seller_offer, create_swap_transfer, create_watcher, get_contract,
import as import_contract, structs::ContractAmount, swap::RgbSwapStrategy,
update_seller_offer, verify_transfers,
},
structs::{
AcceptRequest, AssetType, ImportRequest, IssueResponse, PsbtFeeRequest, PublishPsbtRequest,
RgbBidRequest, RgbBidResponse, RgbOfferRequest, RgbOfferResponse, RgbOfferUpdateRequest,
RgbSwapRequest, RgbSwapResponse, SecretString, SignPsbtRequest, SignedPsbtResponse,
WatcherRequest,
RgbAuctionBidRequest, RgbAuctionOfferRequest, RgbBidRequest, RgbBidResponse,
RgbOfferRequest, RgbOfferResponse, RgbOfferUpdateRequest, RgbSwapRequest, RgbSwapResponse,
SecretString, SignPsbtRequest, SignedPsbtResponse, WatcherRequest,
},
};

Expand Down Expand Up @@ -717,3 +718,177 @@ async fn create_p2p_swap() -> anyhow::Result<()> {

Ok(())
}

#[tokio::test]
async fn create_auction_swap() -> anyhow::Result<()> {
// 1. Initial Setup
let seller_keys = new_mnemonic(&SecretString("".to_string())).await?;
let buyer_keys = new_mnemonic(&SecretString("".to_string())).await?;

let watcher_name = "default";
let seller_sk = seller_keys.private.nostr_prv.clone();
let create_watch_req = WatcherRequest {
name: watcher_name.to_string(),
xpub: seller_keys.public.watcher_xpub.clone(),
force: true,
};
create_watcher(&seller_sk, create_watch_req.clone()).await?;

let buyer_sk = buyer_keys.private.nostr_prv.clone();
let create_watch_req = WatcherRequest {
name: watcher_name.to_string(),
xpub: buyer_keys.public.watcher_xpub.clone(),
force: true,
};
create_watcher(&buyer_sk, create_watch_req.clone()).await?;

// 2. Setup Wallets (Seller)
let btc_address_1 = get_new_address(
&SecretString(seller_keys.public.btc_descriptor_xpub.clone()),
None,
)
.await?;

let default_coins = "0.001";
send_some_coins(&btc_address_1, default_coins).await;

let btc_descriptor_xprv = SecretString(seller_keys.private.btc_descriptor_xprv.clone());
let btc_change_descriptor_xprv =
SecretString(seller_keys.private.btc_change_descriptor_xprv.clone());

let assets_address_1 = get_new_address(
&SecretString(seller_keys.public.rgb_assets_descriptor_xpub.clone()),
None,
)
.await?;

let uda_address_1 = get_new_address(
&SecretString(seller_keys.public.rgb_udas_descriptor_xpub.clone()),
None,
)
.await?;

let btc_wallet = get_wallet(&btc_descriptor_xprv, Some(&btc_change_descriptor_xprv)).await?;
sync_wallet(&btc_wallet).await?;

let fund_vault = fund_vault(
&btc_descriptor_xprv,
&btc_change_descriptor_xprv,
&assets_address_1,
&uda_address_1,
Some(1.1),
)
.await?;

// 3. Send some coins (Buyer)
let btc_address_1 = get_new_address(
&SecretString(buyer_keys.public.btc_descriptor_xpub.clone()),
None,
)
.await?;
let asset_address_1 = get_new_address(
&SecretString(buyer_keys.public.rgb_assets_descriptor_xpub.clone()),
None,
)
.await?;

let default_coins = "0.1";
send_some_coins(&btc_address_1, default_coins).await;
send_some_coins(&asset_address_1, default_coins).await;

// 4. Issue Contract (Seller)
let issuer_resp = issuer_issue_contract_v2(
5,
"RGB20",
ContractAmount::with(1, 0, 2).to_value(),
false,
false,
None,
None,
Some(UtxoFilter::with_outpoint(
fund_vault.assets_output.unwrap_or_default(),
)),
Some(seller_keys.clone()),
)
.await?;

for contract in issuer_resp.clone() {
let buyer_import_req = ImportRequest {
import: AssetType::RGB20,
data: contract.contract.strict,
};
let buyer_import_resp = import_contract(&buyer_sk, buyer_import_req).await;
assert!(buyer_import_resp.is_ok());
}

// 5. Create Collection (Seller)
let contract_amount = "1.00".to_string();
let mut offers_collection = vec![];
for contract in issuer_resp.clone() {
let IssueResponse {
contract_id, iface, ..
} = contract.clone();

let expire_at = (chrono::Local::now() + chrono::Duration::seconds(10))
.naive_utc()
.timestamp();

let desc = SecretString(seller_keys.public.rgb_assets_descriptor_xpub.clone());
let req = RgbOfferRequest {
contract_id,
iface,
contract_amount: contract_amount.clone(),
bitcoin_price: 1_000,
descriptor: desc,
change_terminal: "/20/1".to_string(),
bitcoin_changes: vec![],
strategy: RgbSwapStrategy::Auction,
expire_at: Some(expire_at),
};

offers_collection.push(req);
}

let offer_auction_req = RgbAuctionOfferRequest {
offers: offers_collection,
sign_keys: vec![
SecretString(seller_keys.private.btc_descriptor_xprv.clone()),
SecretString(seller_keys.private.btc_change_descriptor_xprv.clone()),
SecretString(seller_keys.private.rgb_assets_descriptor_xprv.clone()),
],
};

let resp = create_auction_offers(&seller_sk, offer_auction_req).await;
assert!(resp.is_ok());

let RgbOfferResponse { offer_id, .. } = resp?[0].clone();

// 6. Create Bid
let buyer_btc_desc = buyer_keys.public.btc_descriptor_xpub.clone();
let bid_auction_req = RgbAuctionBidRequest {
offer_id: offer_id.clone(),
asset_amount: contract_amount,
descriptor: SecretString(buyer_btc_desc),
change_terminal: "/1/0".to_string(),
fee: PsbtFeeRequest::Value(1000),
sign_keys: vec![
SecretString(buyer_keys.private.btc_descriptor_xprv.clone()),
SecretString(buyer_keys.private.btc_change_descriptor_xprv.clone()),
],
};

let resp = create_auction_bid(&buyer_sk, bid_auction_req).await;
assert!(resp.is_ok());

// 7. Finish Offer

// 8. Mine Some Blocks

// 9. Verify Auctions

// 10. Verify Transfers

// 11. Check Balances

Ok(())
}

0 comments on commit e36e6cd

Please sign in to comment.