본문으로 건너뛰기

WalletConnect와 dApp

BitTool Signer는 네트워크가 없으므로 dApp에 직접 연결하지 않습니다. WalletConnect 세션은 지갑이 유지하며, dApp이 BitTool Signer 계정의 서명을 요청하면 지갑이 그 요청을 서명 QR 코드로 바꾸고, 응답을 기다린 뒤 dApp에 답합니다. BitTool Wallet이 이렇게 동작합니다.

내 지갑WalletConnect 세션 유지
BitTool Signer오프라인
  1. 1dApp에서 세션 요청을 받습니다(예: eip155:1의 personal_sign).
  2. 2요청을 사용자에게 보여 주고, 필요하면 nonce, 가스, 수수료를 채운 뒤 정확한 바이트를 확정합니다.
  3. ur:eth-sign-request · ur:sol-sign-request · ur:tron-sign-request ▶
  4. 3요청을 디코딩하고 검토한 뒤, 사용자가 지갑 비밀번호를 입력하면 서명합니다.
  5. ◀ ur:eth-signature · ur:sol-signature · ur:tron-signature
  6. 4서명을 검증하고, 메서드에 필요하면 브로드캐스트한 뒤 JSON-RPC 결과를 dApp에 반환합니다.

WalletConnect 세션에는 시간 제한이 있고, dApp이 기다리다 포기할 수도 있습니다. QR 코드를 즉시 보여 주고 사용자가 취소할 수 있게 하세요. 사용자가 취소하면 dApp에 사용자 거부 오류(EVM 체인에서는 4001)로 응답하세요.

메서드 대응표​

네임스페이스dApp 메서드BitTool Signer로 보내는 요청dApp에 반환하는 결과
eip155personal_sign [message, address]eth-sign-request, data-type 3, 메시지 바이트0x 서명, 65바이트, v = 27/28
eip155eth_signTypedData_v4 [address, typedData]data-type 2, 타입 데이터 JSON0x 서명, 65바이트, v = 27/28
eip155eth_sendTransaction [tx]nonce, 가스, 수수료를 채운 뒤 data-type 4(EIP-1559) 또는 1(legacy)브로드캐스트 후 트랜잭션 해시
eip155eth_signTransaction [tx]위와 동일서명된 원시 트랜잭션(브로드캐스트하지 않음)
eip155eth_sign지원하지 않음: BitTool Signer는 원시 32바이트 해시에 서명하지 않습니다요청 거부
solanasolana_signMessage {message, pubkey}sol-sign-request, sign-type 2, 디코딩한 메시지 바이트Base58 { signature }
solanasolana_signTransaction {transaction}sign-type 1, 트랜잭션의 메시지 바이트Base58 { signature }
solanasolana_signAndSendTransaction {transaction}sign-type 1브로드캐스트 후 { signature }
trontron_signMessage {address, message}tron-sign-request, data-type 2, 메시지 바이트v = 27/28인 0x 서명
trontron_signTransaction {address, transaction}data-type 1, raw_data_hex 바이트signature를 추가한 트랜잭션 객체

세션에서 제공할 체인 ID(CAIP-2):

체인CAIP-2
EVMeip155:1, eip155:56, eip155:42161, eip155:8453, eip155:10, eip155:137, eip155:100, eip155:43114
Solana 메인넷solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp
TRON 메인넷tron:0x2b6653dc

사용자가 페어링한 계정과 BitTool Signer가 서명할 수 있는 네트워크만 제공하세요. 다른 체인 ID의 eth_sendTransaction은 서명 기기에서 거부됩니다.

자주 겪는 함정​

  • personal_sign 파라미터 순서. 명세는 [message, address]이지만 일부 dApp은 [address, message]로 보냅니다. 20바이트 주소를 감지해 구분하세요. 메시지가 바이트라면 hex(0x…)로 전달됩니다. sign-data에는 hex 텍스트가 아니라 디코딩한 바이트를 넣으세요.
  • 타입 데이터는 문자열로 도착합니다. eth_signTypedData_v4는 보통 JSON을 문자열로 보냅니다. 다시 직렬화하지 말고 UTF-8 바이트로 그대로 전달해야 정수와 주소 표기가 dApp이 쓴 그대로 유지됩니다. 꼭 다시 직렬화해야 한다면 큰 정수는 문자열로 유지하세요.
  • Solana: 트랜잭션이 아니라 메시지를 보내세요. solana_signTransaction은 서명 슬롯이 비어 있는 Base64 직렬화 트랜잭션을 전달합니다. 이를 역직렬화해 메시지 바이트만 보내세요. dApp이 주소 조회 테이블을 사용하는 v0 트랜잭션을 만들었다면 BitTool Signer는 서명할 수 없습니다.
  • Solana 메시지 인코딩. solana_signMessage는 메시지를 Base58로 보냅니다. 먼저 바이트로 디코딩하세요.
  • TRON 트랜잭션 구조. dApp마다 트랜잭션을 감싸는 방식이 params.transaction.transaction, params.transaction, params 자체 등으로 다릅니다. raw_data_hex가 있는 객체를 골라 txID = SHA-256(raw_data)를 확인하고, raw_data_hex 바이트에 서명하세요.
  • TRON 메시지 서명. 서명 기기는 복구 바이트를 0/1로 반환하지만, TronWeb을 쓰는 dApp은 27/28을 기대합니다. 마지막 바이트에 27을 더하세요.

예제​

각 예제는 지갑이 dApp에서 받는 요청, BitTool Signer와의 QR 왕복, 그리고 반환할 결과를 보여 줍니다. 모두 테스트 문구를 사용하며, 체인별 세부 사항은 EVM, Solana, TRON 페이지에 있습니다.

Sign-In with Ethereum 로그인입니다.

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

요청 (내 지갑 → BitTool Signer)

eth-sign-request2 프레임
UR:ETH-SIGN-REQUEST/1-2/LPADAOCFADFDCYCMDSCMFHHDOXOSADTPDAGDHECKNDDWKIFTGLJLLEBDCEDPFMGWHTAMAOHDWEHSJOJODMIHKSHSJNJOJZIHDMJLJPIOCXKTHSJTJYJKCXKKJLKPCXJYJLCXJKINIOJTCXINJTCXKTINJYISCXKKJLKPJPCXFEJYISIHJPIHKPJNCXHSIAIAJLKPJTJYFTBKDYKSESETECETFEIYFGFYEYEOEYFWEEDYEOEOFEEEEMIEESDYDYDYEOFYEEEHFEFXEOEEFEIAHSFEIEHSESEEBKBKGUINIOJTCXINJTCXJYJLCXFEKSHSJNJOJZIHCXFPJOJODMBKBKGOGMGAFTCXISCPDEGMOY
1 / 2
CBOR 필드
{
"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"
}
QR 텍스트와 원본 CBOR 보기
QR 텍스트 · ur:eth-sign-request
UR:ETH-SIGN-REQUEST/1-2/LPADAOCFADFDCYCMDSCMFHHDOXOSADTPDAGDHECKNDDWKIFTGLJLLEBDCEDPFMGWHTAMAOHDWEHSJOJODMIHKSHSJNJOJZIHDMJLJPIOCXKTHSJTJYJKCXKKJLKPCXJYJLCXJKINIOJTCXINJTCXKTINJYISCXKKJLKPJPCXFEJYISIHJPIHKPJNCXHSIAIAJLKPJTJYFTBKDYKSESETECETFEIYFGFYEYEOEYFWEEDYEOEOFEEEEMIEESDYDYDYEOFYEEEHFEFXEOEEFEIAHSFEIEHSESEEBKBKGUINIOJTCXINJTCXJYJLCXFEKSHSJNJOJZIHCXFPJOJODMBKBKGOGMGAFTCXISCPDEGMOY
UR:ETH-SIGN-REQUEST/2-2/LPAOAOCFADFDCYCMDSCMFHHDOXJYJYJOJKFTDLDLHSJOJODMIHKSHSJNJOJZIHDMJLJPIOBKHFIHJPJKINJLJTFTCXEHBKFXISHSINJTCXGAFYFTCXEHBKGLJLJTIAIHFTCXETIYEOJEEYJNESJSBKGAJKJKKPIHIECXFPJYFTCXEYDYEYENDPEHDYDPEHETGHDYESFTEODYFTDYDYDMDYDYDYHTAXAXAAADAHTAADDYOEADLECSDWYKCSFNYKAEYKAEWKAEWKAOCYJKSKTNBKAMGHMKHDWSZCCNDNFZEOVEKIMHAEFSFPWPEEWPPLTNMWATJTFWINJYGHJLJLJZCXHGHSJZJZIHJYCWTTFYJT
UR CBOR (hex)
a701d825505f1e9b2c7d3a4e6f8a0b1c2d3e4f5a060258ed6170702e6578616d706c652e6f72672077616e747320796f7520746f207369676e20696e207769746820796f757220457468657265756d206163636f756e743a0a3078393835384566464432333242343033334534376439303030334434314543333445636145646139340a0a5369676e20696e20746f204578616d706c65204170702e0a0a5552493a2068747470733a2f2f6170702e6578616d706c652e6f72670a56657273696f6e3a20310a436861696e2049443a20310a4e6f6e63653a203866336b326d39710a4973737565642041743a20323032362d31302d31385430393a33303a30302e3030305a0303040105d90130a2018a182cf5183cf500f500f400f4021a73c5da0a06549858effd232b4033e47d90003d41ec34ecaeda94076e426974546f6f6c2057616c6c6574

응답 (BitTool Signer → 내 지갑)

디코딩된 응답 · ur:eth-signature
{
"request-id": {
"uuid": "5f1e9b2c7d3a4e6f8a0b1c2d3e4f5a06"
},
"signature": "23c5ba3f5d247b4c81d55b7c44a3951a14c82e70f17ef2c19abea893c4e5bef05795a7261ac2bd9da29be2dfef529327e1b0724580fccac106bed3d007854f6b1b"
}
QR 텍스트와 원본 CBOR 보기
QR 텍스트 · ur:eth-signature
UR:ETH-SIGNATURE/OEADTPDAGDHECKNDDWKIFTGLJLLEBDCEDPFMGWHTAMAOHDFPCNSKRDFHHLDKKGGSLYTLHPKEFYOTMDCYBBSPDMJOWNKBWZSENYRNPDMUSSVWRNWTHGMDOSDSCYSARYNTOENDVOURWSGMMUDIVYPFJPFELAZTSGSEAMRNTETIATLPGWJECWWNKEFGEH
UR CBOR (hex)
a201d825505f1e9b2c7d3a4e6f8a0b1c2d3e4f5a0602584123c5ba3f5d247b4c81d55b7c44a3951a14c82e70f17ef2c19abea893c4e5bef05795a7261ac2bd9da29be2dfef529327e1b0724580fccac106bed3d007854f6b1b

지갑이 조립한 결과

walletConnectResult
0x23c5ba3f5d247b4c81d55b7c44a3951a14c82e70f17ef2c19abea893c4e5bef05795a7261ac2bd9da29be2dfef529327e1b0724580fccac106bed3d007854f6b1b
dApp에 반환하는 JSON-RPC 결과
0x23c5ba3f5d247b4c81d55b7c44a3951a14c82e70f17ef2c19abea893c4e5bef05795a7261ac2bd9da29be2dfef529327e1b0724580fccac106bed3d007854f6b1b

요청 표시​

사용자는 지갑에서 한 번, BitTool Signer에서 한 번, 이렇게 두 번 승인합니다. 두 화면의 내용이 일치하도록 하세요. dApp의 이름과 URL, 네트워크, 그리고 BitTool Signer가 보여 줄 것과 같은 해석 내용(금액, 수신자, spender, 메시지라면 전체 텍스트)을 표시하세요. 알 수 없는 컨트랙트 호출은 추측하지 말고 알 수 없음으로 표시하세요. BitTool Signer도 이를 해석되지 않은 호출로 표시합니다.