Skip to content
Open
Show file tree
Hide file tree
Changes from all 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: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ authors = ["Santiago Carmuega <santiago@carmuega.me>"]

[dependencies]
bytes = "1.10.1"
thiserror = "2.0.12"
thiserror = "2.0.17"
tokio = "1.46.1"
tonic = { version = "0.12.3", features = ["tls-roots"] }
utxorpc-spec = { version = "0.17.0" }
utxorpc-spec = { version = "0.18.1" }
# utxorpc-spec = { path = "../spec/gen/rust" }

[dev-dependencies]
Expand Down
24 changes: 12 additions & 12 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,22 +555,16 @@ impl_grpc_client!(
);

impl<C: Chain> SubmitClient<C> {
pub async fn submit_tx<B: Into<NativeBytes>>(
&mut self,
txs: Vec<B>,
) -> Result<Vec<NativeBytes>> {
let tx = txs
.into_iter()
.map(|bytes| spec::submit::AnyChainTx {
r#type: Some(spec::submit::any_chain_tx::Type::Raw(bytes.into())),
})
.collect();
pub async fn submit_tx<B: Into<NativeBytes>>(&mut self, tx: B) -> Result<NativeBytes> {
let tx = Some(spec::submit::AnyChainTx {
r#type: Some(spec::submit::any_chain_tx::Type::Raw(tx.into())),
});

let req = spec::submit::SubmitTxRequest { tx };

let res = self.inner.submit_tx(req).await?;
let refs = res.into_inner().r#ref;
Ok(refs)
let tx_ref = res.into_inner().r#ref;
Ok(tx_ref)
}

pub async fn wait_for_tx<B: Into<NativeBytes>>(
Expand Down Expand Up @@ -617,6 +611,9 @@ where
tx: ChainTx<C::ParsedTx>,
block: ChainBlock<C::ParsedBlock>,
},
Idle {
block_ref: spec::watch::BlockRef,
},
}

pub struct WatchedTxStream<C: Chain>(Streaming<spec::watch::WatchTxResponse>, PhantomData<C>);
Expand All @@ -639,6 +636,9 @@ impl<C: Chain> WatchedTxStream<C> {
block: chain_tx.1,
}))
}
Some(spec::watch::watch_tx_response::Action::Idle(block_ref)) => {
Ok(Some(WatchedTx::Idle { block_ref }))
}
None => Ok(None),
},
None => Ok(None),
Expand Down
2 changes: 1 addition & 1 deletion utxorpc-tests/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1 +1 @@
// This crate contains all integration tests for the utxorpc library
// This crate contains all integration tests for the utxorpc library
14 changes: 12 additions & 2 deletions utxorpc-tests/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,14 +129,17 @@ pub async fn fetch_utxos_from_utxorpc(
let tx_hash = hex::encode(&tx_ref.hash);
let output_index = tx_ref.index;

let lovelace_amount = parsed.coin;
let lovelace_amount = parsed.coin.and_then(unwrap_bigint).unwrap_or_default();

let mut assets = Vec::new();
for asset_group in parsed.assets {
let policy_id = hex::encode(&asset_group.policy_id);
for asset in asset_group.assets {
let asset_name = hex::encode(&asset.name);
let asset_amount = asset.output_coin;
let asset_amount = match asset.quantity {
Some(spec::cardano::asset::Quantity::OutputCoin(int)) => unwrap_bigint(int).unwrap_or_default(),
_ => 0,
};
assets.push((policy_id.clone(), asset_name, asset_amount));
}
}
Expand Down Expand Up @@ -417,4 +420,11 @@ pub async fn build_transaction(
asset_name,
asset_amount,
).await
}

fn unwrap_bigint(value: spec::cardano::BigInt) -> Option<u64> {
match value.big_int {
Some(spec::cardano::big_int::BigInt::Int(inner)) => Some(inner as u64),
_ => None
}
}
18 changes: 6 additions & 12 deletions utxorpc-tests/tests/submit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,16 +34,12 @@ async fn submit_and_wait_for_tx() {
}
};

let refs = match submit_client.submit_tx(vec![tx_bytes]).await {
Ok(refs) => refs,
Err(_) => {
eprintln!("Transaction submission failed - skipping test");
return;
}
let Ok(tx_ref) = submit_client.submit_tx(tx_bytes).await else {
eprintln!("Transaction submission failed - skipping test");
return;
};
assert!(!refs.is_empty());

let mut stream = submit_client.wait_for_tx(refs).await.unwrap();
let mut stream = submit_client.wait_for_tx(vec![tx_ref]).await.unwrap();

match tokio::time::timeout(
std::time::Duration::from_secs(5),
Expand Down Expand Up @@ -180,10 +176,8 @@ async fn watch_mempool_all_patterns() {
}
};

let submitted_tx_id = match submit_client.submit_tx(vec![tx_bytes]).await {
Ok(refs) => refs.first()
.map(|tx_ref| hex::encode(tx_ref))
.expect("No transaction ref returned from submit"),
let submitted_tx_id = match submit_client.submit_tx(tx_bytes).await {
Ok(tx_ref) => hex::encode(tx_ref),
Err(_) => {
eprintln!("Transaction submission failed - skipping test");
return;
Expand Down
11 changes: 7 additions & 4 deletions utxorpc-tests/tests/sync.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
mod common;

use utxorpc::{*, spec};
use utxorpc::{spec, *};

#[tokio::test]
async fn client_build() {
Expand All @@ -25,6 +25,7 @@ async fn follow_tip() {
.unwrap()
.into(),
height: 3399486,
timestamp: 1768682099000,
}];

let mut tip = client.follow_tip(intersect).await.unwrap();
Expand Down Expand Up @@ -84,12 +85,13 @@ async fn fetch_block() {
.unwrap()
.into(),
height: 3399486,
timestamp: 1768682099000,
};

let blocks = client.fetch_block(vec![block_ref]).await.unwrap();

assert_eq!(blocks.len(), 1, "Should fetch exactly one block");

if let Some(parsed) = &blocks[0].parsed {
if let Some(header) = &parsed.header {
assert_eq!(header.slot, 85213090);
Expand All @@ -112,17 +114,18 @@ async fn dump_history() {
.unwrap()
.into(),
height: 3399486,
timestamp: 1768682099000,
};

let history = client.dump_history(Some(start_ref), 1).await.unwrap();

assert!(!history.items.is_empty(), "Should have at least one block");

let first_block = &history.items[0];
if let Some(parsed) = &first_block.parsed {
if let Some(header) = &parsed.header {
assert_eq!(header.slot, 85213090);
assert_eq!(header.height, 3399486);
}
}
}
}
7 changes: 3 additions & 4 deletions utxorpc-tests/tests/watch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ async fn watch_for_tx(
}
}
WatchedTx::Undo { .. } => {}
WatchedTx::Idle { .. } => {}
}
}
None
Expand Down Expand Up @@ -149,10 +150,8 @@ async fn watch_tx_all_patterns() {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;

// Submit transaction
let submitted_tx_id = match submit_client.submit_tx(vec![tx_bytes]).await {
Ok(refs) => refs.first()
.map(|tx_ref| hex::encode(tx_ref))
.expect("No transaction ref returned from submit"),
let submitted_tx_id = match submit_client.submit_tx(tx_bytes).await {
Ok(tx_ref) => hex::encode(tx_ref),
Err(_) => {
eprintln!("Transaction submission failed - skipping test");
return;
Expand Down