Add wallet Sign Message flow for CEX ownership verification#6065
Conversation
97138ed to
7624da7
Compare
7624da7 to
d59ad8d
Compare
📸 Test evidence (followup: user-selectable signing address, Ravencoin UTXO wallet on iOS sim)agent proof 1209296431612665 01 signmsg default address agent proof 1209296431612665 02 signature default address agent proof 1209296431612665 03 address edited signature cleared agent proof 1209296431612665 04 signature after reset Captured by the agent's in-app test run (build-and-test). |
📸 Test evidence: BIP-137 signature formatagent proof 1209296431612665 01 format selector default agent proof 1209296431612665 02 standard signature agent proof 1209296431612665 03 bip137 signature agent proof 1209296431612665 04 non segwit hidden Captured by the agent's in-app test run (build-and-test). |
bb08a13 to
8870e5a
Compare
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 8870e5a. Configure here.
📸 Test evidence (after Bugbot fixes): BIP-137 on HEAD + Taproot guardagent proof 1209296431612665 01 format selector default agent proof 1209296431612665 03 bip137 signature agent proof 1209296431612665 04 non segwit hidden agent proof 1209296431612665 05 taproot rejected Captured by the agent's in-app test run (build-and-test). |
8870e5a to
4b7a06e
Compare
Adds a Sign Message option to the wallet list menu for Bitcoin-family (UTXO) wallets. The new scene shows the wallet's receive address, lets the user paste an exchange-provided message, signs it with the wallet key, and returns a copyable signature. This lets users prove control of a self-hosted wallet for CEX/CASP withdrawal checks (EU Travel Rule) without manual ID/selfie verification.
Add signMessageInput and signMessageButton testIDs to the Sign Message scene so UI automation can drive the message field and sign action by a stable selector.
The Sign Message scene now shows the wallet's receive address in an editable field instead of a read-only row. Exchanges typically ask a user to prove control of the specific address they already provided (often a previously-used one), so the user can replace the default with that address. The wallet must control whichever address is entered; the plugin signs with the key derived from that address's stored derivation path and rejects any address it does not own, surfaced as a clear error. Editing the address clears any prior signature, and a Use default address link restores the auto-detected receive address.
Let users on SegWit chains (Bitcoin, Litecoin, DigiByte) choose between the Standard (Electrum) and BIP-137 signature formats. BIP-137 re-encodes the signature header byte by address script type (native SegWit 39-42, nested SegWit 35-38) so strict external verifiers recognize the address type. The option is hidden on non-SegWit UTXO chains, and legacy addresses are never remapped.
4b7a06e to
752e288
Compare


















CHANGELOG
Does this branch warrant an entry to the CHANGELOG?
Dependencies
none
Requirements
If you have made any visual changes to the GUI. Make sure you have:
Description
Adds an in-app Sign Message flow so a user can prove ownership of a self-hosted wallet by signing an exchange-provided message. This addresses EU Travel Rule / TFR withdrawal checks where CEXs/CASPs (Kraken, Coinbase, Bitvavo, Bitpanda, OKX, Bringin, NiceHash, etc.) require a signed message from the destination wallet instead of a manual ID/selfie proof.
BTC-first, per the task scope.
What it does
SignMessageScenethat shows the wallet's receive address (copyable, so the user can hand it to the exchange), a multiline message input, and a Sign Message button.wallet.signMessage(message, { otherParams: { publicAddress } })and displays the resulting base64 signature in a copyable card.Implementation notes
signMessageis used rather thansignBytesbecause for BitcoinsignBytesbase64-re-encodes the bytes before signing, which would produce a signature over the wrong data.signMessagesigns the literal UTF-8 message the exchange verifies (same pattern already used bybityProviderandEdgeProviderServer).wallet.getAddresses), because the UTXO plugin requires the address to be in its data layer.Files
SignMessageScene.tsx(new scene)routerTypes.tsx,Main.tsx(route + scene registration)WalletListMenuActions.tsx,WalletListMenuModal.tsx(menu entry, UTXO-scoped)en_US.ts(strings)Asana: https://app.asana.com/0/1215088146871429/1209296431612665
Testing
Verified end-to-end on the iOS simulator (edge-funds, My Bitcoin wallet): opened the wallet menu, tapped Sign Message, entered a message, and confirmed a valid base64 signature was produced and displayed. Proof screenshots attached below.
Note
Medium Risk
Touches wallet signing and key-derived signatures for user-supplied messages; logic is scoped to owned addresses and includes BIP-137 edge-case handling, but phishing/mis-signing risk remains user-dependent.
Overview
Adds Sign Message to the wallet list menu for Bitcoin-family UTXO wallets, opening a new scene where users paste an exchange message, choose a signing address (default receive address or a specific owned address), and copy the resulting signature.
On SegWit chains (Bitcoin, Litecoin, DigiByte), users can pick Standard (Electrum) or BIP-137; new
bitcoinMessageSignaturehelpers classify addresses, remap signature header bytes for native/nested SegWit, and block Taproot/P2WSH when BIP-137 is selected. Signing useswallet.signMessagewithpublicAddressinotherParams, with UX guards (stale signature clearing, address-not-owned errors, safety copy).Navigation, menu actions, locales, and unit tests for the BIP-137 utilities are included.
Reviewed by Cursor Bugbot for commit 752e288. Bugbot is set up for automated code reviews on this repo. Configure here.