Skip to content
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@ CARBONADO_ENDPOINT=http://localhost:7070/carbonado
UDAS_UTXO=3b367e1facc3174e97658295961faf6a4ed889129c881b7a73db1f074b49bd8a:
MARKETPLACE_SEED="lion bronze dumb tuna perfect fantasy wall orphan improve business harbor sadness"
MARKETPLACE_NOSTR=cd591c134a0d88991326b1619953d0eae2287d315a7c4a93c1e4883a8c26c464

# 1..100
MARKETPLACE_FEE_PERC=
# xpub..
MARKETPLACE_FEE_XPUB=

# :: Coordinator ::
COORDINATOR_NOSTR=9e8294eb38ba77c0fba982da8fbd370b8868c6dbfc9ca414aff4863c15dfbcff

# :: RGB PROXY ::
RGB_PROXY_ENDPOINT=http://localhost:3001
80 changes: 70 additions & 10 deletions lib/web/rgb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -432,15 +432,15 @@ export interface InvoiceResponse {

export interface PsbtRequest {
/// Asset UTXOs
asset_inputs: PsbtInputRequest[];
assetInputs: PsbtInputRequest[];
/// Asset Descriptor Change
asset_descriptor_change: string;
assetDescriptorChange: string;
/// Asset Terminal Change (default: /10/0)
asset_terminal_change: string;
assetTerminalChange: string;
/// Bitcoin UTXOs
bitcoin_inputs: PsbtInputRequest[];
bitcoinInputs: PsbtInputRequest[];
/// Bitcoin Change Addresses (format: {address}:{amount})
bitcoin_changes: string[];
bitcoinChanges: string[];
/// Bitcoin Fee
fee: PsbtFeeRequest;
/// Allow RBF
Expand All @@ -453,11 +453,11 @@ interface PsbtInputRequest {
/// Asset or Bitcoin UTXO
utxo: string;
/// Asset or Bitcoin UTXO Terminal (ex. /0/0)
utxo_terminal: string;
utxoTerminal: string;
/// Asset or Bitcoin Tweak
tapret?: string;
/// Asset or Bitcoin Tweak
sigh_hash?: PsbtSigHashRequest;
sighHash?: PsbtSigHashRequest;
}

interface PsbtSigHashRequest {
Expand Down Expand Up @@ -748,7 +748,7 @@ export interface RgbTransferDetail {
}

export interface TxStatus {
not_found?: any;
notFound?: any;
error?: string;
mempool?: any;
block?: number;
Expand Down Expand Up @@ -793,8 +793,66 @@ export interface RgbOfferRequest {
changeTerminal: string;
/// Bitcoin Change Addresses (format: {address}:{amount})
bitcoinChanges: string[];
presig: boolean;
expire_at?: number;
strategy: RgbSwapStrategy;
expireAt?: number;
}

export interface RgbSwapStrategy {
auction?: string,
p2p?: string,
hotswap?: string,
}
export interface RgbAuctionOfferRequest {
signKeys: string[],

/// List of Offers
offers: RgbOfferRequest[],
}

export interface RgbAuctionBidRequest {
/// The Offer ID
offerId: string,
/// Asset Amount
assetAmount: string,
/// Universal Descriptor
descriptor: string,
/// Bitcoin Terminal Change
changeTerminal: string,
/// Descriptors to Sign
signKeys: string[],
/// Bitcoin Fee
fee: PsbtFeeRequest,
}

export interface RgbAuctionBidResponse {
/// The Bid ID
bidId: string,
/// The Offer ID
offerId: string,
/// Fee Value
feeValue: number,
}

export interface RgbMatchResponse {
/// Transfer ID
consigId: string,
/// Offer ID
offerId: string,
/// Bid ID
bidId: string,
}

export interface RgbAuctionOfferResponse {
/// Offer ID
offerId: string,
/// Contract ID
contractId: string,
/// Asset/Contract Amount
assetAmount: number,
/// Bitcoin Price
bitcoinPrice: number,
/// Bundle ID
bundleId: string,
}

export interface RgbOfferResponse {
Expand All @@ -810,6 +868,8 @@ export interface RgbOfferResponse {
sellerAddress: string;
/// Seller PSBT (encoded in base64)
sellerPsbt: string;
/// Bundle ID (collection)
bundleId?: string,
}

export interface RgbBidRequest {
Expand Down
70 changes: 66 additions & 4 deletions src/bin/bitmaskd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use axum::{
use bitcoin_30::secp256k1::{ecdh::SharedSecret, PublicKey, SecretKey};
use bitmask_core::{
bitcoin::{save_mnemonic, sign_and_publish_psbt_file},
carbonado::{handle_file, metrics, server_retrieve, server_store, store},
carbonado::{handle_file, marketplace_retrieve, marketplace_store, metrics, store},
constants::{
get_marketplace_nostr_key, get_marketplace_seed, get_network, get_udas_utxo, switch_network,
},
Expand Down Expand Up @@ -474,7 +474,7 @@ async fn co_store(
},
}

metrics::update(&filepath).await?;
// metrics::update(&filepath).await?;

Ok((StatusCode::OK, TypedHeader(cc), "Success"))
}
Expand Down Expand Up @@ -527,7 +527,7 @@ async fn co_server_store(
body: Bytes,
) -> Result<impl IntoResponse, AppError> {
info!("POST /carbonado/server/{name}, {} bytes", body.len());
let (filepath, encoded) = server_store(&name, &body, None).await?;
let (filepath, encoded) = marketplace_store(&name, &body, None).await?;

match OpenOptions::new()
.read(true)
Expand Down Expand Up @@ -627,7 +627,7 @@ async fn co_metadata(
async fn co_server_retrieve(Path(name): Path<String>) -> Result<impl IntoResponse, AppError> {
info!("GET /server/{name}");

let result = server_retrieve(&name).await;
let result = marketplace_retrieve(&name).await;
let cc = CacheControl::new().with_no_cache();

match result {
Expand Down Expand Up @@ -687,6 +687,56 @@ async fn rgb_proxy_media_data_save(
Ok((StatusCode::OK, Json(resp)))
}

async fn rgb_auction_get_offer(
Path(offer_id): Path<String>,
Json(_request): Json<String>,
) -> Result<impl IntoResponse, AppError> {
info!("GET /auction/{offer_id}");
Ok((StatusCode::OK, Json("")))
}

async fn rgb_auction_create_offer(
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
Path(offer_id): Path<String>,
Json(_request): Json<String>,
) -> Result<impl IntoResponse, AppError> {
info!("POST /auction/{offer_id}");
Ok((StatusCode::OK, Json("")))
}

async fn rgb_auction_destroy_offer(
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
Path(offer_id): Path<String>,
) -> Result<impl IntoResponse, AppError> {
info!("DELETE /auction/{offer_id}");
Ok((StatusCode::OK, Json("")))
}

async fn rgb_auction_get_bid(
Path((offer_id, bid_id)): Path<(String, String)>,
Json(_request): Json<String>,
) -> Result<impl IntoResponse, AppError> {
info!("GET /auction/{offer_id}/{bid_id}");
Ok((StatusCode::OK, Json("")))
}

async fn rgb_auction_create_bid(
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
Path((offer_id, bid_id)): Path<(String, String)>,
Json(_request): Json<String>,
) -> Result<impl IntoResponse, AppError> {
info!("POST /auction/{offer_id}/{bid_id}");
Ok((StatusCode::OK, Json("")))
}

async fn rgb_auction_destroy_bid(
TypedHeader(_auth): TypedHeader<Authorization<Bearer>>,
Path((offer_id, bid_id)): Path<(String, String)>,
) -> Result<impl IntoResponse, AppError> {
info!("DELETE /auction/{offer_id}/{bid_id}");
Ok((StatusCode::OK, Json("")))
}

const BMC_VERSION: &str = env!("CARGO_PKG_VERSION");

async fn status() -> Result<impl IntoResponse, AppError> {
Expand Down Expand Up @@ -809,6 +859,18 @@ async fn main() -> Result<()> {
.route("/proxy/media-metadata", post(rgb_proxy_media_data_save))
.route("/proxy/media-metadata/:id", get(rgb_proxy_media_retrieve))
.route("/proxy/media/:id", get(rgb_proxy_metadata_retrieve))
.route("/auctions/:offer_id", get(rgb_auction_get_offer))
.route("/auctions/:offer_id", post(rgb_auction_create_offer))
.route("/auctions/:offer_id", delete(rgb_auction_destroy_offer))
.route("/auctions/:offer_id/bid/:bid_id", get(rgb_auction_get_bid))
.route(
"/auctions/:offer_id/bid/:bid_id",
post(rgb_auction_create_bid),
)
.route(
"/auction/:offer_id/bid/:bid_id",
delete(rgb_auction_destroy_bid),
)
.route("/metrics.json", get(json_metrics))
.route("/metrics.csv", get(csv_metrics));

Expand Down
15 changes: 12 additions & 3 deletions src/bitcoin/psbt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ use crate::{

#[derive(Error, Debug)]
pub enum BitcoinPsbtError {
/// Could not broadcast PSBT
#[error("Could not broadcast PSBT")]
CouldNotBroadcastPsbt(String),
/// Could not finalize when signing PSBT
#[error("Could not finalize when signing PSBT")]
CouldNotFinalizePsbt,
Expand Down Expand Up @@ -46,7 +49,7 @@ pub async fn multi_sign_psbt(

let mut sign_count = 0;
for wallet in wallets {
wallet.lock().await.sign(
let sign = wallet.lock().await.sign(
&mut psbt,
SignOptions {
allow_all_sighashes: true,
Expand All @@ -55,7 +58,10 @@ pub async fn multi_sign_psbt(
},
)?;

sign_count += 1;
if sign {
sign_count += 1;
}

debug!(format!("PSBT Sign: ({sign_count}/{total_wallets})"));
}

Expand All @@ -70,7 +76,10 @@ pub async fn publish_psbt(
let tx = psbt.extract_tx();
debug!("tx:", &serialize(&tx.clone()).to_hex());
let blockchain = get_blockchain().await;
blockchain.broadcast(&tx).await?;
blockchain
.broadcast(&tx)
.await
.map_err(|op| BitcoinPsbtError::CouldNotBroadcastPsbt(op.to_string()))?;

let txid = tx.txid();
let tx = blockchain.get_tx(&txid).await?;
Expand Down
Loading