Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
66f8925
test: add TestContext::wallet_abi
KyrylR Apr 13, 2026
b5b7ec7
test: add WalletAbiHarness::fund_address
KyrylR Apr 13, 2026
eed64ff
test: add RuntimeFundingAsset::IssuedAsset
KyrylR Apr 13, 2026
b813ad9
test: add WalletAbiHarness::evaluate_request
KyrylR Apr 13, 2026
0d3ec40
test: add WalletAbiHarness::process_request
KyrylR Apr 13, 2026
5dfab6e
test: add WalletAbiHarness::current_height
KyrylR Apr 14, 2026
e920680
test: add WalletAbiHarness::mine_to_height
KyrylR Apr 14, 2026
22e96a8
test: add WalletAbiHarness::fund_and_sync
KyrylR Apr 14, 2026
82f86ad
test: wait for synced tip in WalletAbiHarness::mine_to_height
KyrylR Apr 14, 2026
8281215
test: add WalletAbiHarness::fund_signer_lbtc
KyrylR Apr 14, 2026
15e9006
test: add WalletAbiHarness::fund_signer_asset
KyrylR Apr 14, 2026
a08c083
test: add WalletAbiHarness::simf_finalizer
KyrylR Apr 14, 2026
3bb2ab1
test: add WalletAbiRequestBuilder::build_create
KyrylR Apr 14, 2026
bc7ae4e
test: add WalletAbiRequestBuilder::wallet_input_exact
KyrylR Apr 14, 2026
aba5fb2
test: add WalletAbiRequestBuilder::provided_input
KyrylR Apr 14, 2026
6667a9e
test: add WalletAbiRequestBuilder::new_issuance
KyrylR Apr 14, 2026
07f5d7d
test: add WalletAbiRequestBuilder::explicit_output
KyrylR Apr 14, 2026
0b38353
test: add WalletAbiRequestBuilder::new_issuance_asset_output
KyrylR Apr 14, 2026
d9cc4f4
test: add WalletAbiRequestBuilder::finalizer_output
KyrylR Apr 14, 2026
7467091
test: add WalletAbiRequestBuilder::lock_time_height
KyrylR Apr 14, 2026
553493c
test: rewrite wallet_abi_smoke with intent helpers
KyrylR Apr 14, 2026
b54129f
test: fix wallet_abi strict lint warnings
KyrylR Apr 14, 2026
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
1,947 changes: 1,915 additions & 32 deletions Cargo.lock

Large diffs are not rendered by default.

4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,7 @@ simplicityhl = { version = "0.5.0-rc.0" }

[patch.crates-io]
simplicity-sys = { git = "https://github.com/BlockstreamResearch/rust-simplicity", tag = "simplicity-sys-0.6.1" }
lwk_common = { git = "https://github.com/Blockstream/lwk", rev = "d384a20b8e2dde83ca0d733ba6c22dd3c5daac56" }
lwk_signer = { git = "https://github.com/Blockstream/lwk", rev = "d384a20b8e2dde83ca0d733ba6c22dd3c5daac56" }
lwk_simplicity = { git = "https://github.com/Blockstream/lwk", rev = "d384a20b8e2dde83ca0d733ba6c22dd3c5daac56" }
lwk_wollet = { git = "https://github.com/Blockstream/lwk", rev = "d384a20b8e2dde83ca0d733ba6c22dd3c5daac56" }
1 change: 1 addition & 0 deletions crates/simplex/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub use smplx_sdk::*;

pub use smplx_test::config::TestConfig;
pub use smplx_test::context::TestContext;
pub use smplx_test::wallet_abi;

pub use smplx_macros;
pub use smplx_macros::{include_simf, test};
150 changes: 150 additions & 0 deletions crates/simplex/tests/wallet_abi.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
use std::collections::HashMap;

use simplex::wallet_abi::{FinalizerSpec, RuntimeFundingAsset, TxEvaluateRequest};

#[simplex::test]
fn wallet_abi_smoke(context: simplex::TestContext) -> Result<(), Box<dyn std::error::Error>> {
let harness = context.wallet_abi()?;

let lbtc_funding = harness.fund_signer_lbtc(200_000)?;
let issued_funding = harness.fund_signer_asset(5_000)?;

let wallet_utxos = harness.wallet_utxos()?;
assert!(wallet_utxos.iter().any(|utxo| {
utxo.unblinded.asset == lbtc_funding.asset_id().expect("lbtc asset")
&& utxo.unblinded.value == lbtc_funding.value().expect("lbtc value")
}));
assert!(wallet_utxos.iter().any(|utxo| {
utxo.unblinded.asset == issued_funding.asset_id().expect("issued asset")
&& utxo.unblinded.value == issued_funding.value().expect("issued value")
}));

let recipient_script = harness.signer_script();
let policy_asset = harness.network().policy_asset();
let request = harness
.tx()
.wallet_input_exact("wallet-input", policy_asset, lbtc_funding.value()?)
.explicit_output("recipient", recipient_script.clone(), policy_asset, 50_000)
.build_create()?;
let request_id = request.request_id.to_string();

let preview = harness.evaluate_request(TxEvaluateRequest::from_parts(
request_id.as_str(),
request.network,
request.params.clone(),
)?)?;
assert!(preview.error.is_none());
assert!(preview.preview.is_some());

let tx = harness.process_request(request)?;
let recipient_output = harness.find_output(&tx, |tx_out| {
tx_out.script_pubkey == recipient_script
&& tx_out.asset.explicit() == Some(policy_asset)
&& tx_out.value.explicit() == Some(50_000)
})?;

assert_eq!(recipient_output.value()?, 50_000);
assert_eq!(recipient_output.asset_id()?, policy_asset);

Ok(())
}

#[simplex::test]
fn wallet_abi_current_height_matches_provider_tip(
context: simplex::TestContext,
) -> Result<(), Box<dyn std::error::Error>> {
let harness = context.wallet_abi()?;

assert_eq!(
harness.current_height()?,
context.get_default_provider().fetch_tip_height()?,
);

Ok(())
}

#[simplex::test]
fn wallet_abi_mine_to_height_reaches_target(context: simplex::TestContext) -> Result<(), Box<dyn std::error::Error>> {
let harness = context.wallet_abi()?;
let current_height = harness.current_height()?;
let target_height = current_height + 2;

harness.mine_to_height(target_height)?;
assert_eq!(harness.current_height()?, target_height);

harness.mine_to_height(target_height)?;
assert_eq!(harness.current_height()?, target_height);

Ok(())
}

#[simplex::test]
fn wallet_abi_fund_and_sync_returns_synced_utxo(
context: simplex::TestContext,
) -> Result<(), Box<dyn std::error::Error>> {
let harness = context.wallet_abi()?;
let funding = harness.fund_and_sync(harness.signer_address(), RuntimeFundingAsset::Lbtc, 200_000, 1)?;
let wallet_utxos = harness.wallet_utxos()?;

assert!(wallet_utxos.iter().any(|utxo| {
utxo.outpoint == funding.outpoint
&& utxo.unblinded.asset == funding.asset_id().expect("funding asset")
&& utxo.unblinded.value == funding.value().expect("funding value")
}));

Ok(())
}

#[simplex::test]
fn wallet_abi_fund_signer_lbtc_returns_policy_asset(
context: simplex::TestContext,
) -> Result<(), Box<dyn std::error::Error>> {
let harness = context.wallet_abi()?;
let funding = harness.fund_signer_lbtc(200_000)?;

assert_eq!(funding.asset_id()?, harness.network().policy_asset());
assert_eq!(funding.value()?, 200_000);

Ok(())
}

#[simplex::test]
fn wallet_abi_fund_signer_asset_returns_issued_asset(
context: simplex::TestContext,
) -> Result<(), Box<dyn std::error::Error>> {
let harness = context.wallet_abi()?;
let funding = harness.fund_signer_asset(5_000)?;

assert_ne!(funding.asset_id()?, harness.network().policy_asset());
assert_eq!(funding.value()?, 5_000);

Ok(())
}

#[simplex::test]
fn simf_finalizer_uses_bip0341(context: simplex::TestContext) -> Result<(), Box<dyn std::error::Error>> {
let harness = context.wallet_abi()?;
let arguments = simplex::wallet_abi::SimfArguments::new(simplex::simplicityhl::Arguments::from(HashMap::new()));
let witness = simplex::wallet_abi::SimfWitness::new(simplex::simplicityhl::WitnessValues::from(HashMap::new()));
let expected_arguments = simplex::wallet_abi::serialize_arguments(&arguments)?;
let expected_witness = simplex::wallet_abi::serialize_witness(&witness)?;

let finalizer = harness.simf_finalizer("unit.simf", &arguments, &witness)?;

match finalizer {
FinalizerSpec::Simf {
source_simf,
internal_key,
arguments,
witness,
} => {
assert_eq!(source_simf, "unit.simf");
assert_eq!(internal_key, simplex::wallet_abi::InternalKeySource::Bip0341);
assert_eq!(arguments, expected_arguments);
assert_eq!(witness, expected_witness);
}
FinalizerSpec::Wallet => panic!("expected simf finalizer"),
}

Ok(())
}
7 changes: 7 additions & 0 deletions crates/test/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,13 @@ simplicityhl = { workspace = true }
electrsd = { workspace = true }
serde = { workspace = true }
toml = { workspace = true }
hex = { workspace = true }
serde_json = "1.0"
futures = "0.3"
lwk_common = { git = "https://github.com/Blockstream/lwk", rev = "d384a20b8e2dde83ca0d733ba6c22dd3c5daac56" }
lwk_signer = { git = "https://github.com/Blockstream/lwk", rev = "d384a20b8e2dde83ca0d733ba6c22dd3c5daac56", default-features = false }
lwk_simplicity = { git = "https://github.com/Blockstream/lwk", rev = "d384a20b8e2dde83ca0d733ba6c22dd3c5daac56" }
lwk_wollet = { git = "https://github.com/Blockstream/lwk", rev = "d384a20b8e2dde83ca0d733ba6c22dd3c5daac56", default-features = false, features = ["esplora", "electrum"] }

syn = { version = "2.0.114", default-features = false, features = ["proc-macro", "full", "parsing", "derive", "clone-impls", "extra-traits", "printing"] }
proc-macro2 = { version = "1.0.106", features = ["span-locations"] }
Expand Down
24 changes: 24 additions & 0 deletions crates/test/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use smplx_sdk::signer::Signer;

use crate::config::TestConfig;
use crate::error::TestError;
use crate::wallet_abi::WalletAbiHarness;

#[allow(dead_code)]
pub struct TestContext {
Expand Down Expand Up @@ -70,6 +71,29 @@ impl TestContext {
self.signer.get_provider().get_network()
}

pub fn wallet_abi(&self) -> Result<WalletAbiHarness, TestError> {
let network = match self.get_network() {
SimplicityNetwork::Liquid => lwk_wollet::ElementsNetwork::Liquid,
SimplicityNetwork::LiquidTestnet => lwk_wollet::ElementsNetwork::LiquidTestnet,
SimplicityNetwork::ElementsRegtest { policy_asset } => lwk_wollet::ElementsNetwork::ElementsRegtest {
policy_asset: policy_asset
.to_string()
.parse::<lwk_wollet::elements::AssetId>()
.map_err(|error| TestError::WalletAbiInvariant(error.to_string()))?,
},
};

WalletAbiHarness::new(
self.config.mnemonic.as_str(),
network,
self._provider_info.esplora_url.clone(),
self._provider_info
.elements_url
.clone()
.zip(self._provider_info.auth.clone()),
)
}

fn setup(config: &TestConfig) -> Result<(Signer, ProviderInfo, Option<RegtestClient>), TestError> {
let client: Option<RegtestClient>;
let provider_info: ProviderInfo;
Expand Down
31 changes: 31 additions & 0 deletions crates/test/src/error.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
use std::io;

use electrsd::bitcoind::bitcoincore_rpc::Error as RpcError;
use lwk_simplicity::error::WalletAbiError;
use smplx_sdk::provider::ProviderError;

use lwk_signer::NewError;
use lwk_wollet::Error as LwkWalletError;
use lwk_wollet::elements::UnblindError;
use smplx_regtest::error::RegtestError;

use crate::wallet_abi::WalletAbiAdapterError;

#[derive(thiserror::Error, Debug)]
pub enum TestError {
#[error(transparent)]
Expand All @@ -20,4 +27,28 @@ pub enum TestError {

#[error("Network name should either be `Liquid`, `LiquidTestnet` or `ElementsRegtest`, got: {0}")]
BadNetworkName(String),

#[error(transparent)]
LwkWallet(#[from] LwkWalletError),

#[error(transparent)]
LwkSignerNew(#[from] NewError),

#[error("wallet descriptor error: {0}")]
WalletDescriptor(String),

#[error("wallet-abi invariant violation: {0}")]
WalletAbiInvariant(String),

#[error(transparent)]
WalletAbi(#[from] WalletAbiError),

#[error(transparent)]
WalletAbiAdapter(#[from] WalletAbiAdapterError),

#[error(transparent)]
WalletAbiRpc(#[from] RpcError),

#[error(transparent)]
WalletAbiUnblind(#[from] UnblindError),
}
1 change: 1 addition & 0 deletions crates/test/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ pub mod config;
pub mod context;
pub mod error;
pub mod macros;
pub mod wallet_abi;

pub use config::{RpcConfig, TEST_ENV_NAME, TestConfig};
Loading
Loading