Skip to main content

WalletConnect and dApps

BitTool Signer never connects to a dApp: it has no network. Your wallet holds the WalletConnect session, and when a dApp asks for a signature from a BitTool Signer account, your wallet turns the request into a signing QR code, waits for the response, and answers the dApp. BitTool Wallet works this way.

Your walletHolds the WalletConnect session
BitTool SignerOffline
  1. 1Receives a session request from the dApp, e.g. personal_sign on eip155:1.
  2. 2Shows the request to the user, completes it if needed (nonce, gas, fees), freezes the exact bytes.
  3. ur:eth-sign-request · ur:sol-sign-request · ur:tron-sign-request ▶
  4. 3Decodes, reviews and signs after the user enters the wallet password.
  5. ◀ ur:eth-signature · ur:sol-signature · ur:tron-signature
  6. 4Verifies the signature, broadcasts if the method requires it, and returns the JSON-RPC result to the dApp.

WalletConnect sessions time out, and a dApp may give up waiting. Show the QR code promptly and let the user cancel; if the user cancels, reply to the dApp with a user-rejected error (4001 on EVM chains).

Method mapping​

NamespacedApp methodRequest to BitTool SignerResult to the dApp
eip155personal_sign [message, address]eth-sign-request, data-type 3, the message bytes0x signature, 65 bytes, v = 27/28
eip155eth_signTypedData_v4 [address, typedData]data-type 2, the typed-data JSON0x signature, 65 bytes, v = 27/28
eip155eth_sendTransaction [tx]Fill nonce, gas and fees; data-type 4 (EIP-1559) or 1 (legacy)Transaction hash, after you broadcast
eip155eth_signTransaction [tx]Same as aboveSigned raw transaction (not broadcast)
eip155eth_signNot supported: BitTool Signer never signs a raw 32-byte hashReject the request
solanasolana_signMessage {message, pubkey}sol-sign-request, sign-type 2, the decoded message bytes{ signature } in Base58
solanasolana_signTransaction {transaction}sign-type 1, the transaction's message bytes{ signature } in Base58
solanasolana_signAndSendTransaction {transaction}sign-type 1{ signature } after you broadcast
trontron_signMessage {address, message}tron-sign-request, data-type 2, the message bytes0x signature with v = 27/28
trontron_signTransaction {address, transaction}data-type 1, raw_data_hex bytesThe transaction object with signature added

Chain IDs to offer in the session (CAIP-2):

ChainCAIP-2
EVMeip155:1, eip155:56, eip155:42161, eip155:8453, eip155:10, eip155:137, eip155:100, eip155:43114
Solana mainnetsolana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
TRON mainnettron:0x2b6653dc

Offer only the accounts the user paired, and only networks BitTool Signer can sign for. An eth_sendTransaction on any other chain ID would be rejected by the signer.

Things that trip people up​

  • personal_sign parameter order. The spec is [message, address], but some dApps send [address, message]. Detect the 20-byte address. The message is hex (0x…) for bytes; pass the decoded bytes, never the hex text, as sign-data.
  • Typed data arrives as a string. eth_signTypedData_v4 usually sends the JSON as a string. Pass it through as UTF-8 bytes without re-serializing, so integer and address spellings stay exactly as the dApp wrote them. If you must re-serialize, keep large integers as strings.
  • Solana: send the message, not the transaction. solana_signTransaction gives you a Base64 serialized transaction with empty signature slots. Deserialize it and send only the message bytes. If the dApp built a v0 transaction with address lookup tables, BitTool Signer cannot sign it.
  • Solana message encoding. solana_signMessage sends the message as Base58. Decode it to bytes first.
  • TRON transaction shape. dApps wrap the transaction differently: params.transaction.transaction, params.transaction or params itself. Take the object that has raw_data_hex, check txID = SHA-256(raw_data), and sign the raw_data_hex bytes.
  • TRON message signatures. The signer returns the recovery byte as 0/1; dApps using TronWeb expect 27/28. Add 27 to the last byte.

Worked examples​

Each example shows the request your wallet receives from the dApp, the QR round trip with BitTool Signer, and the result you return. All use the test phrase; the full chain-specific details are on the EVM, Solana and TRON pages.

A Sign-In with Ethereum login.

dApp request (chainId eip155:1)
{
"method": "personal_sign",
"params": [
"0x6170702e6578616d706c652e6f72672077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078393835384566464432333242343033334534376439303030334434314543333445636145646139340a0a5369676e20696e20746f204578616d706c65204170702e0a0a5552493a2068747470733a2f2f6170702e6578616d706c652e6f72670a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a203866336b326d39710a4973737565642041743a20323032362d31302d31385430393a33303a30302e3030305a",
"0x9858EfFD232B4033E47d90003D41EC34EcaEda94"
]
}

Request (your wallet → BitTool Signer)

eth-sign-request2 frames
UR:ETH-SIGN-REQUEST/1-2/LPADAOCFADFDCYCMDSCMFHHDOXOSADTPDAGDHECKNDDWKIFTGLJLLEBDCEDPFMGWHTAMAOHDWEHSJOJODMIHKSHSJNJOJZIHDMJLJPIOCXKTHSJTJYJKCXKKJLKPCXJYJLCXJKINIOJTCXINJTCXKTINJYISCXKKJLKPJPCXFEJYISIHJPIHKPJNCXHSIAIAJLKPJTJYFTBKDYKSESETECETFEIYFGFYEYEOEYFWEEDYEOEOFEEEEMIEESDYDYDYEOFYEEEHFEFXEOEEFEIAHSFEIEHSESEEBKBKGUINIOJTCXINJTCXJYJLCXFEKSHSJNJOJZIHCXFPJOJODMBKBKGOGMGAFTCXISCPDEGMOY
1 / 2
CBOR fields
{
"1 request-id": {
"uuid (tag 37)": "5f1e9b2c7d3a4e6f8a0b1c2d3e4f5a06"
},
"2 sign-data": "6170702e6578616d706c652e6f72672077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078393835384566464432333242343033334534376439303030334434314543333445636145646139340a0a5369676e20696e20746f204578616d706c65204170702e0a0a5552493a2068747470733a2f2f6170702e6578616d706c652e6f72670a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a203866336b326d39710a4973737565642041743a20323032362d31302d31385430393a33303a30302e3030305a",
"3 data-type": 3,
"4 chain-id": 1,
"5 derivation-path": {
"crypto-keypath (tag 304)": {
"1 components": [
44,
true,
60,
true,
0,
true,
0,
false,
0,
false
],
"2 source-fingerprint": 1942346250
}
},
"6 address": "9858effd232b4033e47d90003d41ec34ecaeda94",
"7 origin": "BitTool Wallet"
}
Show the QR text and raw CBOR
QR text · ur:eth-sign-request
UR:ETH-SIGN-REQUEST/1-2/LPADAOCFADFDCYCMDSCMFHHDOXOSADTPDAGDHECKNDDWKIFTGLJLLEBDCEDPFMGWHTAMAOHDWEHSJOJODMIHKSHSJNJOJZIHDMJLJPIOCXKTHSJTJYJKCXKKJLKPCXJYJLCXJKINIOJTCXINJTCXKTINJYISCXKKJLKPJPCXFEJYISIHJPIHKPJNCXHSIAIAJLKPJTJYFTBKDYKSESETECETFEIYFGFYEYEOEYFWEEDYEOEOFEEEEMIEESDYDYDYEOFYEEEHFEFXEOEEFEIAHSFEIEHSESEEBKBKGUINIOJTCXINJTCXJYJLCXFEKSHSJNJOJZIHCXFPJOJODMBKBKGOGMGAFTCXISCPDEGMOY
UR:ETH-SIGN-REQUEST/2-2/LPAOAOCFADFDCYCMDSCMFHHDOXJYJYJOJKFTDLDLHSJOJODMIHKSHSJNJOJZIHDMJLJPIOBKHFIHJPJKINJLJTFTCXEHBKFXISHSINJTCXGAFYFTCXEHBKGLJLJTIAIHFTCXETIYEOJEEYJNESJSBKGAJKJKKPIHIECXFPJYFTCXEYDYEYENDPEHDYDPEHETGHDYESFTEODYFTDYDYDMDYDYDYHTAXAXAAADAHTAADDYOEADLECSDWYKCSFNYKAEYKAEWKAEWKAOCYJKSKTNBKAMGHMKHDWSZCCNDNFZEOVEKIMHAEFSFPWPEEWPPLTNMWATJTFWINJYGHJLJLJZCXHGHSJZJZIHJYCWTTFYJT
UR CBOR (hex)
a701d825505f1e9b2c7d3a4e6f8a0b1c2d3e4f5a060258ed6170702e6578616d706c652e6f72672077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078393835384566464432333242343033334534376439303030334434314543333445636145646139340a0a5369676e20696e20746f204578616d706c65204170702e0a0a5552493a2068747470733a2f2f6170702e6578616d706c652e6f72670a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a203866336b326d39710a4973737565642041743a20323032362d31302d31385430393a33303a30302e3030305a0303040105d90130a2018a182cf5183cf500f500f400f4021a73c5da0a06549858effd232b4033e47d90003d41ec34ecaeda94076e426974546f6f6c2057616c6c6574

Response (BitTool Signer → your wallet)

Decoded response · ur:eth-signature
{
"request-id": {
"uuid": "5f1e9b2c7d3a4e6f8a0b1c2d3e4f5a06"
},
"signature": "23c5ba3f5d247b4c81d55b7c44a3951a14c82e70f17ef2c19abea893c4e5bef05795a7261ac2bd9da29be2dfef529327e1b0724580fccac106bed3d007854f6b1b"
}
Show the QR text and raw CBOR
QR text · ur:eth-signature
UR:ETH-SIGNATURE/OEADTPDAGDHECKNDDWKIFTGLJLLEBDCEDPFMGWHTAMAOHDFPCNSKRDFHHLDKKGGSLYTLHPKEFYOTMDCYBBSPDMJOWNKBWZSENYRNPDMUSSVWRNWTHGMDOSDSCYSARYNTOENDVOURWSGMMUDIVYPFJPFELAZTSGSEAMRNTETIATLPGWJECWWNKEFGEH
UR CBOR (hex)
a201d825505f1e9b2c7d3a4e6f8a0b1c2d3e4f5a0602584123c5ba3f5d247b4c81d55b7c44a3951a14c82e70f17ef2c19abea893c4e5bef05795a7261ac2bd9da29be2dfef529327e1b0724580fccac106bed3d007854f6b1b

Assembled by your wallet

walletConnectResult
0x23c5ba3f5d247b4c81d55b7c44a3951a14c82e70f17ef2c19abea893c4e5bef05795a7261ac2bd9da29be2dfef529327e1b0724580fccac106bed3d007854f6b1b
JSON-RPC result to the dApp
0x23c5ba3f5d247b4c81d55b7c44a3951a14c82e70f17ef2c19abea893c4e5bef05795a7261ac2bd9da29be2dfef529327e1b0724580fccac106bed3d007854f6b1b

Showing the request​

The user approves twice: once in your wallet, once in BitTool Signer. Make the two screens agree. Show the dApp's name and URL, the network, and the same decoded content BitTool Signer will show: amounts, recipients, spender, and for messages the full text. Mark unknown contract calls as unknown rather than guessing; BitTool Signer will label them as not decoded too.