Skip to content
Open
Show file tree
Hide file tree
Changes from 47 commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
f335fe1
add the helper psbt method
mariocynicys Jun 26, 2025
8c43905
suppport deriving htlc pubkey for walletconnect for utxo coins
mariocynicys Jun 26, 2025
989bf74
let my_public_key work for walletconnect
mariocynicys Jun 27, 2025
a125ef5
add fixme labels for the minimum psbt code needed for swaps v1 to work
mariocynicys Jul 2, 2025
d3f4592
implement sign_p2sh_with_walletconnect utility method
mariocynicys Jul 7, 2025
51905d4
add rust-bitcoin (bitcoin) crate as a depenedency for wasm
mariocynicys Jul 31, 2025
d4ea665
implement sign_p2wpkh_with_walletconnect utility method
mariocynicys Jul 31, 2025
859e515
clean up the panics and unwraps in utxo walletconnect code
mariocynicys Aug 1, 2025
8ca78c0
fix the fixme in p2pkh walletconnect signing
mariocynicys Aug 1, 2025
c496af3
set the p2pkh signing code
mariocynicys Aug 2, 2025
dc2ec4c
refactor: let the chain_id be in UtxoCoinConf
mariocynicys Aug 2, 2025
6946fb5
embed walletconnect logic into p2sh htlc signing for swaps v1
mariocynicys Aug 2, 2025
9a1d80e
complete p2sh signing via walletconnect
mariocynicys Aug 2, 2025
27fd49c
fix: use htlc pubkey derivarion instead of keypair in multiple method…
mariocynicys Aug 4, 2025
c3e6b08
add a testing func for walletconnect swaps
mariocynicys Aug 4, 2025
efe59e9
tested the refund case
mariocynicys Aug 7, 2025
5bf8727
simplify watcher code in taker swap
mariocynicys Aug 7, 2025
e17f485
resolve fixme: disable watchers for walletconnect
mariocynicys Aug 7, 2025
d58d932
resolve fixme: fix not using the correct keypair for zcash
mariocynicys Aug 7, 2025
04c77d0
resolve fixme: query the rpc/cache for previous p2pkh txs before wall…
mariocynicys Aug 7, 2025
e51c24a
merge with origin/dev
mariocynicys Aug 11, 2025
419c825
review(shamardy): fix spelling mistakes and use better names
mariocynicys Aug 21, 2025
ff38b7d
Revert "simplify watcher code in taker swap"
mariocynicys Aug 21, 2025
6248a49
review(onur): use a permalink to the caip-4 ref instead of branch link
mariocynicys Sep 4, 2025
81ec311
review(onur): fix a typo (it -> is)
mariocynicys Sep 4, 2025
400f0e9
review(onur): less `map_err`s and more `try_tx_s`
mariocynicys Sep 4, 2025
446a903
review(onur): move detailed walletconnect logic away from signing fun…
mariocynicys Sep 4, 2025
402c2c6
merge with origin/dev
mariocynicys Sep 4, 2025
8922d98
fix a typo
mariocynicys Jul 30, 2025
86e3b2b
review(dimxy): make use of complete_tx() utility func
mariocynicys Sep 4, 2025
a387e05
review(shamardy): add a todo regarding fork_id
mariocynicys Sep 5, 2025
6d4e79c
review(shamardy): explicity type different privatekey policies
mariocynicys Sep 6, 2025
9df9abd
review(dimxy): deserialize the psbt via serde
mariocynicys Sep 8, 2025
16b9853
don't `.as_bytes()` the string
mariocynicys Sep 8, 2025
d01b12e
move derserialize_base64 to common crate
mariocynicys Sep 8, 2025
58a72a6
use DEFAULT_SWAP_VIN and DEFAULT_SWAP_VOUT properly
mariocynicys Sep 9, 2025
31cd36f
move secpv24 that's used in lightning activation to non-wasm deps
mariocynicys Sep 9, 2025
d2e889c
relax a couple of derive_htlc_key_pair to derive_htlc_pubkey used in …
mariocynicys Sep 6, 2025
74a54ce
simplify error handling by using try_tx_s!
mariocynicys Sep 6, 2025
ed6ffd1
put fixme lables and use P2SHSigner
mariocynicys Sep 10, 2025
5524164
return the bare p2sh signature from wallet connect and configure sigh…
mariocynicys Sep 10, 2025
7be460f
refactor and edit the visibility of utxo::wallet_connect methods
mariocynicys Sep 10, 2025
8ecd7b9
support walletconnect utxo signing for swaps v2
mariocynicys Sep 10, 2025
2393ee7
fix walletconnect malformed sig
mariocynicys Sep 10, 2025
1ecae08
fix walletconnect not signing sighash_single
mariocynicys Sep 10, 2025
51ac7e0
add a manual test for v2 swaps via walletconnect
mariocynicys Sep 10, 2025
45d8f17
remove leftover fixmes
mariocynicys Sep 10, 2025
5f5c1bc
merge with origin/dev
mariocynicys Jan 13, 2026
7db5720
fix wasm tests
mariocynicys Jan 15, 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
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 27 additions & 6 deletions mm2src/coins/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ async-std = { workspace = true, features = ["unstable"] }
async-trait.workspace = true
base64.workspace = true
bip32.workspace = true
bitcoin.workspace = true
bitcoin_hashes.workspace = true
bitcrypto = { path = "../mm2_bitcoin/crypto" }
blake2b_simd = { workspace = true, optional = true }
Expand Down Expand Up @@ -73,11 +74,11 @@ mm2_event_stream = { path = "../mm2_event_stream" }
mm2_io = { path = "../mm2_io" }
mm2_metrics = { path = "../mm2_metrics" }
mm2_net = { path = "../mm2_net" }
mm2_number = { path = "../mm2_number"}
mm2_number = { path = "../mm2_number" }
mm2_p2p = { path = "../mm2_p2p", default-features = false }
mm2_rpc = { path = "../mm2_rpc" }
mm2_state_machine = { path = "../mm2_state_machine" }
mocktopus = { workspace = true, optional = true }
mocktopus = { workspace = true, optional = true }
num-traits.workspace = true
parking_lot = { workspace = true }
primitives = { path = "../mm2_bitcoin/primitives" }
Expand Down Expand Up @@ -108,7 +109,9 @@ sha3.workspace = true
utxo_signer = { path = "utxo_signer" }
# using the same version as cosmrs
tendermint-rpc.workspace = true
tokio-tungstenite-wasm = { workspace = true, features = ["rustls-tls-native-roots"]}
tokio-tungstenite-wasm = { workspace = true, features = [
"rustls-tls-native-roots",
] }
url.workspace = true
uuid.workspace = true
# One of web3 dependencies is the old `tokio-uds 0.1.7` which fails cross-compiling to ARM.
Expand All @@ -130,12 +133,24 @@ mm2_metamask = { path = "../mm2_metamask" }
mm2_test_helpers = { path = "../mm2_test_helpers" }
time = { workspace = true, features = ["wasm-bindgen"] }
timed-map = { workspace = true, features = ["rustc-hash", "wasm"] }
tonic = { workspace = true, default-features = false, features = ["prost", "codegen", "gzip"] }
tonic = { workspace = true, default-features = false, features = [
"prost",
"codegen",
"gzip",
] }
tower-service.workspace = true
wasm-bindgen.workspace = true
wasm-bindgen-futures.workspace = true
wasm-bindgen-test.workspace = true
web-sys = { workspace = true, features = ["console", "Headers", "Request", "RequestInit", "RequestMode", "Response", "Window"] }
web-sys = { workspace = true, features = [
"console",
"Headers",
"Request",
"RequestInit",
"RequestMode",
"Response",
"Window",
] }
zcash_proofs = { workspace = true, features = ["local-prover"] }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
Expand All @@ -152,7 +167,13 @@ secp256k1v24.workspace = true
timed-map = { workspace = true, features = ["rustc-hash"] }
tokio.workspace = true
tokio-rustls.workspace = true
tonic = { workspace = true, features = ["codegen", "prost", "gzip", "tls", "tls-webpki-roots"] }
tonic = { workspace = true, features = [
"codegen",
"prost",
"gzip",
"tls",
"tls-webpki-roots",
] }
webpki-roots.workspace = true
zcash_client_sqlite.workspace = true
zcash_proofs = { workspace = true, features = ["local-prover", "multicore"] }
Expand Down
6 changes: 5 additions & 1 deletion mm2src/coins/lp_coins.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4484,6 +4484,10 @@ impl<T> PrivKeyPolicy<T> {
fn is_trezor(&self) -> bool {
matches!(self, PrivKeyPolicy::Trezor)
}

fn is_internal(&self) -> bool {
matches!(self, PrivKeyPolicy::Iguana(_) | PrivKeyPolicy::HDWallet { .. })
}
}

/// 'CoinWithPrivKeyPolicy' trait is used to get the private key policy of a coin.
Expand Down Expand Up @@ -4722,7 +4726,7 @@ pub struct UtxoProtocolInfo {
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(tag = "type", content = "protocol_data")]
pub enum CoinProtocol {
// TODO: Nest this option deep into the innert struct fields when more fields are added to the UTXO protocol info.
// TODO: Nest this option deep into the inner struct fields when more fields are added to the UTXO protocol info.
UTXO(Option<UtxoProtocolInfo>),
QTUM,
QRC20 {
Expand Down
6 changes: 3 additions & 3 deletions mm2src/coins/qrc20.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ impl UtxoCommonOps for Qrc20Coin {
utxo_common::denominate_satoshis(&self.utxo, satoshi)
}

fn my_public_key(&self) -> Result<&Public, MmError<UnexpectedDerivationMethod>> {
fn my_public_key(&self) -> Result<Public, MmError<UnexpectedDerivationMethod>> {
utxo_common::my_public_key(self.as_ref())
}

Expand Down Expand Up @@ -754,7 +754,7 @@ impl UtxoCommonOps for Qrc20Coin {
utxo_common::get_mut_verbose_transaction_from_map_or_rpc(self, tx_hash, utxo_tx_map).await
}

async fn p2sh_spending_tx(&self, input: utxo_common::P2SHSpendingTxInput<'_>) -> Result<UtxoTx, String> {
async fn p2sh_spending_tx(&self, input: utxo_common::P2SHSpendingTxInput) -> Result<UtxoTx, String> {
utxo_common::p2sh_spending_tx(self, input).await
}

Expand Down Expand Up @@ -1073,7 +1073,7 @@ impl SwapOps for Qrc20Coin {
}

fn derive_htlc_pubkey(&self, swap_unique_data: &[u8]) -> [u8; 33] {
utxo_common::derive_htlc_pubkey(self, swap_unique_data)
utxo_common::derive_htlc_pubkey(self.as_ref(), swap_unique_data)
}

#[inline]
Expand Down
33 changes: 23 additions & 10 deletions mm2src/coins/utxo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ use futures::channel::mpsc::{Receiver as AsyncReceiver, Sender as AsyncSender};
use futures::compat::Future01CompatExt;
use futures::lock::{Mutex as AsyncMutex, MutexGuard as AsyncMutexGuard};
use futures01::Future;
use kdf_walletconnect::chain::WcChainId;
use keys::bytes::Bytes;
use keys::NetworkAddressPrefixes;
use keys::Signature;
Expand Down Expand Up @@ -600,6 +601,9 @@ pub struct UtxoCoinConf {
pub checksum_type: ChecksumType,
/// Fork id used in sighash
pub fork_id: u32,
/// A CAIP-2 compliant chain ID. This is used to identify the UTXO chain in WalletConnect and other cross-chain protocols.
/// https://github.com/ChainAgnostic/CAIPs/blob/9516a2c0b26223d98a342938bf6d9ee59517f190/CAIPs/caip-4.md
pub chain_id: Option<WcChainId>,
/// Signature version
pub signature_version: SignatureVersion,
pub required_confirmations: AtomicU64,
Expand Down Expand Up @@ -1056,7 +1060,7 @@ pub trait UtxoCommonOps:
/// The method is expected to fail if [`UtxoCoinFields::priv_key_policy`] is [`PrivKeyPolicy::HardwareWallet`].
/// It's worth adding a method like `my_public_key_der_path`
/// that takes a derivation path from which we derive the corresponding public key.
fn my_public_key(&self) -> Result<&Public, MmError<UnexpectedDerivationMethod>>;
fn my_public_key(&self) -> Result<Public, MmError<UnexpectedDerivationMethod>>;

/// Try to parse address from string using specified on asset enable format,
/// and if it failed inform user that he used a wrong format.
Expand All @@ -1083,7 +1087,7 @@ pub trait UtxoCommonOps:

/// Generates a transaction spending P2SH vout (typically, with 0 index [`utxo_common::DEFAULT_SWAP_VOUT`]) of input.prev_transaction
/// Works only if single signature is required!
async fn p2sh_spending_tx(&self, input: utxo_common::P2SHSpendingTxInput<'_>) -> Result<UtxoTx, String>;
async fn p2sh_spending_tx(&self, input: utxo_common::P2SHSpendingTxInput) -> Result<UtxoTx, String>;

/// Loads verbose transactions from cache or requests it using RPC client.
fn get_verbose_transactions_from_cache_or_rpc(
Expand Down Expand Up @@ -1877,7 +1881,6 @@ where
T: AsRef<UtxoCoinFields> + UtxoTxGenerationOps + UtxoTxBroadcastOps,
{
let my_address = try_tx_s!(coin.as_ref().derivation_method.single_addr_or_err().await);
let key_pair = try_tx_s!(coin.as_ref().priv_key_policy.activated_key_or_err());
let mut builder = UtxoTxBuilder::new(coin)
.await
.add_available_inputs(unspents)
Expand All @@ -1888,7 +1891,7 @@ where
}
let (unsigned, _) = try_tx_s!(builder.build().await);

let spent_unspents = unsigned
let spent_unspents: Vec<_> = unsigned
.inputs
.iter()
.map(|input| UnspentInfo {
Expand All @@ -1904,12 +1907,22 @@ where
_ => coin.as_ref().conf.signature_version,
};

let signed = try_tx_s!(sign_tx(
unsigned,
key_pair,
signature_version,
coin.as_ref().conf.fork_id
));
let signed = match coin.as_ref().priv_key_policy {
PrivKeyPolicy::Iguana(activated_key) | PrivKeyPolicy::HDWallet { activated_key, .. } => {
try_tx_s!(sign_tx(
unsigned,
&activated_key,
signature_version,
coin.as_ref().conf.fork_id
))
},
PrivKeyPolicy::WalletConnect { ref session_topic, .. } => {
try_tx_s!(wallet_connect::sign_p2pkh(coin, session_topic, &unsigned).await)
},
PrivKeyPolicy::Trezor => return Err(TransactionErr::Plain("Can't sign tx with trezor".to_string())),
#[cfg(target_arch = "wasm32")]
PrivKeyPolicy::Metamask { .. } => return Err(TransactionErr::Plain("Can't sign tx with metamask".to_string())),
};

Ok((signed, spent_unspents))
}
Expand Down
6 changes: 3 additions & 3 deletions mm2src/coins/utxo/bch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -809,7 +809,7 @@ impl UtxoCommonOps for BchCoin {
utxo_common::denominate_satoshis(&self.utxo_arc, satoshi)
}

fn my_public_key(&self) -> Result<&Public, MmError<UnexpectedDerivationMethod>> {
fn my_public_key(&self) -> Result<Public, MmError<UnexpectedDerivationMethod>> {
utxo_common::my_public_key(self.as_ref())
}

Expand Down Expand Up @@ -842,7 +842,7 @@ impl UtxoCommonOps for BchCoin {
utxo_common::get_mut_verbose_transaction_from_map_or_rpc(self, tx_hash, utxo_tx_map).await
}

async fn p2sh_spending_tx(&self, input: utxo_common::P2SHSpendingTxInput<'_>) -> Result<UtxoTx, String> {
async fn p2sh_spending_tx(&self, input: utxo_common::P2SHSpendingTxInput) -> Result<UtxoTx, String> {
utxo_common::p2sh_spending_tx(self, input).await
}

Expand Down Expand Up @@ -1046,7 +1046,7 @@ impl SwapOps for BchCoin {
}

fn derive_htlc_pubkey(&self, swap_unique_data: &[u8]) -> [u8; 33] {
utxo_common::derive_htlc_pubkey(self, swap_unique_data)
utxo_common::derive_htlc_pubkey(self.as_ref(), swap_unique_data)
}

#[inline]
Expand Down
6 changes: 3 additions & 3 deletions mm2src/coins/utxo/qtum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -422,7 +422,7 @@ impl UtxoCommonOps for QtumCoin {
utxo_common::denominate_satoshis(&self.utxo_arc, satoshi)
}

fn my_public_key(&self) -> Result<&Public, MmError<UnexpectedDerivationMethod>> {
fn my_public_key(&self) -> Result<Public, MmError<UnexpectedDerivationMethod>> {
utxo_common::my_public_key(self.as_ref())
}

Expand Down Expand Up @@ -460,7 +460,7 @@ impl UtxoCommonOps for QtumCoin {
utxo_common::get_mut_verbose_transaction_from_map_or_rpc(self, tx_hash, utxo_tx_map).await
}

async fn p2sh_spending_tx(&self, input: utxo_common::P2SHSpendingTxInput<'_>) -> Result<UtxoTx, String> {
async fn p2sh_spending_tx(&self, input: utxo_common::P2SHSpendingTxInput) -> Result<UtxoTx, String> {
utxo_common::p2sh_spending_tx(self, input).await
}

Expand Down Expand Up @@ -686,7 +686,7 @@ impl SwapOps for QtumCoin {
}

fn derive_htlc_pubkey(&self, swap_unique_data: &[u8]) -> [u8; 33] {
utxo_common::derive_htlc_pubkey(self, swap_unique_data)
utxo_common::derive_htlc_pubkey(self.as_ref(), swap_unique_data)
}

#[inline]
Expand Down
16 changes: 8 additions & 8 deletions mm2src/coins/utxo/slp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::tx_history_storage::{GetTxHistoryFilters, WalletId};
use crate::utxo::bch::BchCoin;
use crate::utxo::bchd_grpc::{check_slp_transaction, validate_slp_utxos, ValidateSlpUtxosErr};
use crate::utxo::rpc_clients::{UnspentInfo, UtxoRpcClientEnum, UtxoRpcError, UtxoRpcResult};
use crate::utxo::utxo_common::{self, big_decimal_from_sat_unsigned, payment_script, UtxoTxBuilder};
use crate::utxo::utxo_common::{self, big_decimal_from_sat_unsigned, payment_script, UtxoTxBuilder, DEFAULT_SWAP_VIN};
use crate::utxo::{
generate_and_send_tx, sat_from_big_decimal, ActualFeeRate, BroadcastTxErr, FeePolicy, GenerateTxError,
RecentlySpentOutPointsGuard, UtxoCoinConf, UtxoCoinFields, UtxoCommonOps, UtxoTx, UtxoTxBroadcastOps,
Expand Down Expand Up @@ -581,7 +581,7 @@ impl SlpToken {

let other_pub = Public::from_slice(other_pub)?;
let my_public_key = self.platform_coin.my_public_key().map_mm_err()?;
let redeem_script = payment_script(time_lock, secret_hash, my_public_key, &other_pub);
let redeem_script = payment_script(time_lock, secret_hash, &my_public_key, &other_pub);

let slp_amount = match slp_tx.transaction {
SlpTransaction::Send { token_id, amounts } => {
Expand Down Expand Up @@ -702,7 +702,7 @@ impl SlpToken {
.map_mm_err()?;

unsigned.lock_time = tx_locktime;
unsigned.inputs[0].sequence = input_sequence;
unsigned.inputs[DEFAULT_SWAP_VIN].sequence = input_sequence;

let my_key_pair = self
.platform_coin
Expand All @@ -712,7 +712,7 @@ impl SlpToken {
.map_mm_err()?;
let signed_p2sh_input = p2sh_spend(
&unsigned,
0,
DEFAULT_SWAP_VIN,
htlc_keypair,
script_data,
redeem_script,
Expand Down Expand Up @@ -1516,7 +1516,7 @@ impl SwapOps for SlpToken {
}

fn derive_htlc_pubkey(&self, swap_unique_data: &[u8]) -> [u8; 33] {
utxo_common::derive_htlc_pubkey(self, swap_unique_data)
utxo_common::derive_htlc_pubkey(self.as_ref(), swap_unique_data)
}

#[inline]
Expand Down Expand Up @@ -2162,7 +2162,7 @@ mod slp_tests {
let other_pub = Public::from_slice(&other_pub).unwrap();

let my_public_key = bch.my_public_key().unwrap();
let htlc_script = payment_script(1624547837, &secret_hash, &other_pub, my_public_key);
let htlc_script = payment_script(1624547837, &secret_hash, &other_pub, &my_public_key);

let slp_send_op_return_out = slp_send_output(&token_id, &[1000]);

Expand Down Expand Up @@ -2254,10 +2254,10 @@ mod slp_tests {

// standard BCH validation should pass as the output itself is correct
block_on(utxo_common::validate_payment(
bch.clone(),
bch,
&deserialize(payment_tx.as_slice()).unwrap(),
SLP_SWAP_VOUT,
my_pub,
&my_pub,
&other_pub,
SwapTxTypeWithSecretHash::TakerOrMakerPayment {
maker_secret_hash: &secret_hash,
Expand Down
Loading
Loading