Skip to content

Conversation

@mariocynicys
Copy link
Collaborator

@mariocynicys mariocynicys commented Jun 23, 2025

This PR implements BTC (generic UTxO, but gotta be supported by the wallet) activation via WalletConnect.
Activation flow is exactly the same as #2223. You initiate a session with the required properties/permissions and then use that session id/topic to activate the coin (examples to be added).
Q: In such activation flow, how do we know which session topic to grab and use for activation of the coin? pragmatically?

To test this, you need to add chain_id field in the coins file for the select UTxO coins to be tested. And use a wallet that supports WalletConnect UTxO integration (ledger mobile, and this example web wallet by reown).
These are the caip compliant chain_ids for some utxo coins:

btc = bip122:000000000019d6689c085ae165831e93
tbtc = bip122:000000000933ea01ad0ee984209779ba
ltc = bip122:12a765e31ffd4059bada1e25190f6e98
doge = bip122:82bc68038f6034c0596b6e313729793a
kmd = bip122:027e3758c3a65b12aa1046462b486d0a

The example wallet by reown supports only btc & tbtc. Ledger mobile supports btc, tbtc, ltc, doge. No wallet support KMD as of now.
Activation via Ledger mobile will fail because it doesn't implement GetAccountAdderesses method as of now. With reown web example it should work fine.

Suggested to review this commit by commit (only 14, and coherent).


For Testing

Sample new_connection request:

{
        "method": "wc_new_connection",
	"userpass": "{{userpass}}",
	"mmrpc": "2.0",
	"params": {
		"required_namespaces": {
			"bip122": {
				"chains": [
                                     "bip122:000000000019d6689c085ae165831e93"
                                     //"bip122:4966625a4b2851d9fdee139e56211a0d"
                                ],
				"methods": [
					"getAccountAddresses"
                                        //,"signPsbt"
                                        ,"signMessage"
				],
                                "events": []
			}
		}
                //,"optional_namespaces": {}
	}
}

trustwallet is the one having limited methods support and doesn't support eth_signTransaction. Metamask supports nearly all methods
not relevant for now till KDF could be used as a wallet
…terpart might be fallible

we assumed it's infallible yet we used try_from in eth_coin_from_conf_and_request :/

anyway, we want this to be fallible since we will later add WalletConnect to PrivKeyBuildPolicy and the conversion in this case might not always succeed
even tho this struct is intertwined with eth and tendermint code. it's actually never utilized there :/
having these weird one func trait made a messy trace all over. coins who don't even support hw wallet had to implement the trait for hw wallet builder and not use it.
not btc, but rather any utxo that has a caip bip122 chain_id and is supported by the wallet side
@shamardy
Copy link
Collaborator

@mariocynicys please don't forget to fix fmt and clippy errors

@shamardy shamardy self-requested a review June 24, 2025 08:31
Copy link
Collaborator

@onur-ozkan onur-ozkan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just some nits from my end.

I will give a final look once conflicts are resolved.

and fix some conflicts
Comment on lines 253 to 260
// Get and parse the chain_id of the coin.
let chain_id = builder.conf()["chain_id"].as_str().ok_or_else(|| {
WalletConnectError::InvalidChainId(format!(
"coin={} doesn't have chain_id (bip122 standard) set in coin config which is required for WalletConnect",
builder.ticker()
))
})?;
let chain_id = WcChainId::try_from_str(chain_id).map_mm_err()?;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chain_id is being prepared way too early as used much later after many fallible calls. This makes its preparation potentially wasteful. I would move it closer to where it's actually used (right above get_walletconnect_address call).

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

chain_id is also a fallible call.
p.s. and it's not a heavy computation or something.

async fn build_utxo_fields_with_walletconnect<Builder>(
builder: &Builder,
session_topic: &str,
) -> UtxoCoinBuildResult<UtxoCoinFields>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 questions.

  1. Can we have a stricter type on session topic? Right now this function can be called with any value that isn't related with wallet connect at all.
  2. Can you split this into some smaller functions? It's nearly impossible to add test coverage on its current form.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agreed. will put some code in class methods.
for the string thing, there is a Topic struct provided by walletconnect-rust. it's a weird arc thing, but might make sense here in this situation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2- 9bf308a addresses the second point.

a side note regarding testing: we really don't have a way to test these walletconnect connections programmatically as of now. we need a walletconnect wallet client run within our test suite for us to accomplish this.
we currently rely on already implemented mobile wallets and demo impls to test our implementation.

addressing point 1 next.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed here 4149627 and a22b14b.

doesn't do validation, but uses the type that's used by walletconnect-rust. we can later add a validation to that type and we get it in both places for free.

…activation

we used to convert it using `priv_key_policy.into()` and then do a check to rule out the bad activation policies not accepted by legacy activation.
changing it now to just do the conversion inline and reject bad activation policies from the beginning. this way we don't accidently add a new activation policty but forget to rule it out in legacy activation
Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more comments. Please merge with dev to fix conflicts.

Comment on lines 844 to 847
let chain_id = chain_spec
.ok_or(EthActivationV2Error::ChainIdNotSet)?
.chain_id()
.ok_or(EthActivationV2Error::ChainIdNotSet)?;
Copy link
Collaborator

@shamardy shamardy Jul 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, we only use it for wallet connect activation, got it, it's a bit confusing though. Will resolve the 2 comments above it for now

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

updating to the latest toolchain
@mariocynicys
Copy link
Collaborator Author

mariocynicys commented Jul 28, 2025

blocking this PR since there is something wrong with pubkey recovery. It doesn't work with all signatures (some yes and some not).
still investigating...

upd: the problem seem to be bifrost only. bifrosts signature seem to hard code the recovery id to 1 which isn't correct sometimes and makes us recover a different (incorrect) public key.

shamardy
shamardy previously approved these changes Jul 30, 2025
Copy link
Collaborator

@shamardy shamardy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please merge with dev again for latest toolchain, also the comment below is for next PRs. After fixing the chain_id thing, we can merge this.

address: &str,
sign_message_prefix: &str,
) -> MmResult<String, WalletConnectError> {
const AUTH_MSG: &str = "Authenticate with KDF";
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For both UTXO and ETH (and other coins of course), there are some formats that such message should follow (e.g. https://github.com/ethereum/ercs/blob/master/ERCS/erc-4361.md) and for UTXO it can be something like the below

Komodo DeFi Framework requests your signature. (or komodo wallet, the app should be specified in the activation request)

Purpose: This signature is required to securely derive the public key for your trading address. This is not a transaction and will not spend any funds.

Address: bc1q...
Issued At: 2025-07-30T10:00:00Z
Expires At: 2025-07-30T10:05:00Z
Session: wc:a286b...

Please research this more to see if there is a standard or we should create one / follow the ethereum one.

and resolve a todo that was blocked on this PR
@shamardy
Copy link
Collaborator

lots of failing tests @mariocynicys please fix them

looks like serde won't regonize an object that has no protocol_data when the enum content is inlined as struct representation in the enum.
to curcumvent this without forcing us to use protocol_data everywhere, we let the enum hold its content in a tuple representation and let that tuple hold a struct that has the needed content.
the optional tagging should be at the enum level. this is how it masks protocol_data to make it optional as well.
structurally, this doesn't look right. but it keeps backward compatability with coins file and only coins that add chain_id need to play with protocol_data field.
Comment on lines +4690 to +4698
#[display(fmt = "No such coin {coin}")]
NoSuchCoin { coin: String },
#[display(fmt = "Invalid hash: {_0}")]
InvalidHashError(String),
#[from_stringify("web3::Error")]
#[display(fmt = "Transport error: {_0}")]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should start adding this to coins configs and docs @mariocynicys please open an issue in coins repo and in docs repo. c.c. @cipig @smk762

@shamardy shamardy merged commit 68bc4eb into dev Jul 31, 2025
18 of 24 checks passed
@shamardy shamardy deleted the btc-walletconnect branch July 31, 2025 00:48
dimxy pushed a commit that referenced this pull request Aug 1, 2025
* dev: (21 commits)
  feat(wallet-connect): impl BTC (UTxO) activation via WalletConnect (#2499)
  feat(utxo): add new fixed txfee option for DINGO-like coins (#2454)
  ci(pull-requests): review notification bot (#2468)
  improvement(walletconnect): return the `pairing_topic` in `new_connection` response (#2538)
  bless clippy (#2560)
  refactor(toolchain): use latest available stable compiler (#2557)
  feat(wallet): implement unified offline private key export API (#2542)
  improve note for docker test start failure (#2550)
  fix(DOCS): add note for macos to fix docker containers startup failure (#2544)
  refactor(toolchain): general stabilization for stable rust (#2528)
  fix(ci): adds nodejs 20 to ci-container (#2536)
  fix(WASM and Debian): fix build failures (#2534)
  improvement(event-streaming): impl DeriveStreamerId trait for all streamers (#2489)
  fix(eth): Propagate structured EIP-1559 fee errors (#2532)
  fix(eth): Correctly implement ETH max withdrawal logic (#2531)
  feat(use-clap-for-cli): use clap to parse CLI-Args #2215 (#2510)
  feat(orderbook): expirable maker orders (#2516)
  improvement(eth): drop parity support (#2527)
  chore(release): finalize changelog for v2.5.0-beta (#2524)
  chore(toolchain): upgrade toolchain to nightly 1.86.0 (#2444)
  ...

# Conflicts:
#	mm2src/coins/lp_coins.rs
#	mm2src/coins/rpc_command/get_new_address.rs
#	mm2src/trezor/src/eth/eth_command.rs
dimxy pushed a commit that referenced this pull request Aug 1, 2025
* dev:
  feat(wallet-connect): impl BTC (UTxO) activation via WalletConnect (#2499)
  feat(utxo): add new fixed txfee option for DINGO-like coins (#2454)
  ci(pull-requests): review notification bot (#2468)
  improvement(walletconnect): return the `pairing_topic` in `new_connection` response (#2538)
  bless clippy (#2560)
  refactor(toolchain): use latest available stable compiler (#2557)
  feat(wallet): implement unified offline private key export API (#2542)
  improve note for docker test start failure (#2550)
  fix(DOCS): add note for macos to fix docker containers startup failure (#2544)
  refactor(toolchain): general stabilization for stable rust (#2528)
  fix(ci): adds nodejs 20 to ci-container (#2536)
  fix(WASM and Debian): fix build failures (#2534)
  improvement(event-streaming): impl DeriveStreamerId trait for all streamers (#2489)
  chore(release): v2.3.0-beta (#2284)

# Conflicts:
#	mm2src/coins/eth.rs
#	mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs
#	mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs
#	mm2src/coins/eth/eth_tests.rs
#	mm2src/coins/eth/eth_withdraw.rs
#	mm2src/coins/eth/v2_activation.rs
#	mm2src/coins/nft.rs
#	mm2src/coins/qrc20.rs
#	mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs
#	mm2src/mm2_main/src/rpc/lp_commands/one_inch/rpcs.rs
#	mm2src/mm2_main/src/rpc/lp_commands/tokens.rs
#	mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs
dimxy pushed a commit that referenced this pull request Aug 15, 2025
* dev: (24 commits)
  fix(ordermatch): ignore loop-back; clear on null root; reject stale keep-alives (#2580)
  fix(clippy): fix clippy warnings for #2565 (#2589)
  fix(Trezor): fix utxo and eth calls due to firmware changes (#2565)
  fix(utxo): calculate min_trading_vol based on fixed tx fees (#2564)
  feat(protocol): [0] solana support (#2586)
  fix(utxo): fix header deserialization; guard AuxPoW (#2583)
  chore(rust 1.89): make CI clippy/fmt pass (wasm32, all-targets) (#2581)
  fix(utxo): deserialize sapling root for PIVX block headers (#2572)
  improvement(dep-stack): security bumps (#2562)
  fix(utxo): correct block header deserialization for AuxPow and KAWPOW coins (#2563)
  feat(wallet-connect): impl BTC (UTxO) activation via WalletConnect (#2499)
  feat(utxo): add new fixed txfee option for DINGO-like coins (#2454)
  ci(pull-requests): review notification bot (#2468)
  improvement(walletconnect): return the `pairing_topic` in `new_connection` response (#2538)
  bless clippy (#2560)
  refactor(toolchain): use latest available stable compiler (#2557)
  feat(wallet): implement unified offline private key export API (#2542)
  improve note for docker test start failure (#2550)
  fix(DOCS): add note for macos to fix docker containers startup failure (#2544)
  refactor(toolchain): general stabilization for stable rust (#2528)
  ...

# Conflicts:
#	mm2src/coins/eth.rs
#	mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs
#	mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs
#	mm2src/coins/eth/eth_tests.rs
#	mm2src/coins/eth/eth_withdraw.rs
#	mm2src/coins/eth/v2_activation.rs
#	mm2src/coins/nft.rs
#	mm2src/coins/qrc20.rs
#	mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs
#	mm2src/mm2_main/src/rpc/lp_commands/one_inch/rpcs.rs
#	mm2src/mm2_main/src/rpc/lp_commands/tokens.rs
#	mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs
dimxy pushed a commit that referenced this pull request Aug 19, 2025
* dev:
  improvement(`static mut`s): `static mut` removal (#2590)
  fix(orders): set subscription on kickstart and skip GC of own pubkeys (#2597)
  fix(ordermatch): ignore loop-back; clear on null root; reject stale keep-alives (#2580)
  fix(clippy): fix clippy warnings for #2565 (#2589)
  fix(Trezor): fix utxo and eth calls due to firmware changes (#2565)
  fix(utxo): calculate min_trading_vol based on fixed tx fees (#2564)
  feat(protocol): [0] solana support (#2586)
  fix(utxo): fix header deserialization; guard AuxPoW (#2583)
  chore(rust 1.89): make CI clippy/fmt pass (wasm32, all-targets) (#2581)
  fix(utxo): deserialize sapling root for PIVX block headers (#2572)
  improvement(dep-stack): security bumps (#2562)
  fix(utxo): correct block header deserialization for AuxPow and KAWPOW coins (#2563)
  feat(wallet-connect): impl BTC (UTxO) activation via WalletConnect (#2499)
  feat(utxo): add new fixed txfee option for DINGO-like coins (#2454)
  ci(pull-requests): review notification bot (#2468)
  improvement(walletconnect): return the `pairing_topic` in `new_connection` response (#2538)
  bless clippy (#2560)
  refactor(toolchain): use latest available stable compiler (#2557)
  feat(wallet): implement unified offline private key export API (#2542)
  chore(release): v2.3.0-beta (#2284)

# Conflicts:
#	mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs
dimxy pushed a commit to dimxy/komodo-defi-framework that referenced this pull request Aug 21, 2025
* dev: (28 commits)
  fix build script failing to find .git/HEAD (GLEECBTC#2601)
  refactor(EVM): rename fn, fix timeouts, add activation req validation (GLEECBTC#2543)
  improvement(`static mut`s): `static mut` removal (GLEECBTC#2590)
  fix(orders): set subscription on kickstart and skip GC of own pubkeys (GLEECBTC#2597)
  fix(ordermatch): ignore loop-back; clear on null root; reject stale keep-alives (GLEECBTC#2580)
  fix(clippy): fix clippy warnings for GLEECBTC#2565 (GLEECBTC#2589)
  fix(Trezor): fix utxo and eth calls due to firmware changes (GLEECBTC#2565)
  fix(utxo): calculate min_trading_vol based on fixed tx fees (GLEECBTC#2564)
  feat(protocol): [0] solana support (GLEECBTC#2586)
  fix(utxo): fix header deserialization; guard AuxPoW (GLEECBTC#2583)
  chore(rust 1.89): make CI clippy/fmt pass (wasm32, all-targets) (GLEECBTC#2581)
  fix(utxo): deserialize sapling root for PIVX block headers (GLEECBTC#2572)
  improvement(dep-stack): security bumps (GLEECBTC#2562)
  fix(utxo): correct block header deserialization for AuxPow and KAWPOW coins (GLEECBTC#2563)
  feat(wallet-connect): impl BTC (UTxO) activation via WalletConnect (GLEECBTC#2499)
  feat(utxo): add new fixed txfee option for DINGO-like coins (GLEECBTC#2454)
  ci(pull-requests): review notification bot (GLEECBTC#2468)
  improvement(walletconnect): return the `pairing_topic` in `new_connection` response (GLEECBTC#2538)
  bless clippy (GLEECBTC#2560)
  refactor(toolchain): use latest available stable compiler (GLEECBTC#2557)
  ...

# Conflicts:
#	mm2src/coins/eth.rs
#	mm2src/coins/eth/eth_rpc.rs
#	mm2src/coins/eth/eth_swap_v2/eth_maker_swap_v2.rs
#	mm2src/coins/eth/eth_swap_v2/eth_taker_swap_v2.rs
#	mm2src/coins/eth/eth_withdraw.rs
#	mm2src/coins/eth/v2_activation.rs
#	mm2src/coins/lightning.rs
#	mm2src/coins/lp_coins.rs
#	mm2src/coins/nft.rs
#	mm2src/coins/qrc20.rs
#	mm2src/coins/siacoin.rs
#	mm2src/coins/tendermint/tendermint_token.rs
#	mm2src/coins/test_coin.rs
#	mm2src/coins/utxo/bch.rs
#	mm2src/coins/utxo/qtum.rs
#	mm2src/coins/utxo/slp.rs
#	mm2src/coins/utxo/utxo_standard.rs
#	mm2src/coins/z_coin.rs
#	mm2src/coins_activation/src/bch_with_tokens_activation.rs
#	mm2src/coins_activation/src/erc20_token_activation.rs
#	mm2src/coins_activation/src/eth_with_token_activation.rs
#	mm2src/coins_activation/src/init_erc20_token_activation.rs
#	mm2src/coins_activation/src/init_token.rs
#	mm2src/coins_activation/src/platform_coin_with_tokens.rs
#	mm2src/coins_activation/src/slp_token_activation.rs
#	mm2src/coins_activation/src/tendermint_with_assets_activation.rs
#	mm2src/coins_activation/src/token.rs
#	mm2src/mm2_main/src/lp_swap.rs
#	mm2src/mm2_main/src/lp_swap/check_balance.rs
#	mm2src/mm2_main/src/lp_swap/maker_swap.rs
#	mm2src/mm2_main/src/lp_swap/max_maker_vol_rpc.rs
#	mm2src/mm2_main/src/lp_swap/swap_v2_rpcs.rs
#	mm2src/mm2_main/src/lp_swap/taker_swap.rs
#	mm2src/mm2_main/src/lp_swap/trade_preimage.rs
#	mm2src/mm2_main/src/rpc/dispatcher/dispatcher.rs
#	mm2src/mm2_main/src/rpc/lp_commands/legacy.rs
#	mm2src/mm2_main/src/rpc/lp_commands/lr_swap.rs
#	mm2src/mm2_main/src/rpc/lp_commands/lr_swap/lr_impl.rs
#	mm2src/mm2_main/src/rpc/lp_commands/one_inch/errors.rs
#	mm2src/mm2_main/src/rpc/lp_commands/one_inch/rpcs.rs
#	mm2src/mm2_main/src/rpc/lp_commands/tokens.rs
#	mm2src/mm2_main/tests/docker_tests/docker_tests_common.rs
#	mm2src/mm2_main/tests/docker_tests/docker_tests_inner.rs
#	mm2src/mm2_main/tests/docker_tests/eth_docker_tests.rs
#	mm2src/mm2_main/tests/integration_tests_common/mod.rs
#	mm2src/trading_api/src/one_inch_api/client.rs
dimxy pushed a commit that referenced this pull request Oct 15, 2025
…2499)

This implements activation only, full WalletConnect implementation for UTXO coins will follow.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants