본문으로 건너뛰기

WalletKit 세션 메시지

세션 메시지 형식 — SessionWire

세션 연결과 요청 메시지를 생성·해석하는 API입니다. AppKit dApp SDK와 바이트 단위로 호환되며, 모든 페이로드는 UTF-8 JSON을 ChannelCrypto(ChaCha20-Poly1305)로 암호화해 전송합니다.

public object SessionWire {
public const val RELAY_PROTOCOL: String = "scr"
public const val SIGN_METHOD: String = "eth_signTypedData_v4"
}

relay-protocolscr은 WalletConnect의 irn과 호환되지 않습니다. eth_signTypedData_v4는 현재 세션 요청이 지원하는 유일한 RPC 메서드입니다.

태그별 메시지 생성·해석 함수

tag방향빌더파서
1100 proposedApp → 지갑propose(publicKeyRaw, dappName)proposePublicKey, requestedChains, dappName
1101 propose 응답지갑 → dAppproposeResponse(publicKeyRaw)responderPublicKey
1102 settle지갑 → dAppsettle(controllerPublicKeyRaw, chains, account)settledAddress
1103 settle ackdApp → 지갑settleAck()
1108 서명 요청dApp → 지갑signRequest(from, typedDataJson, chainId)signRequestTypedData
1109 서명 응답지갑 → dAppsignResponse(signatureHex), signRejection(code, message)signResponseSignature

생성 함수는 모두 암호화 전 UTF-8 JSON 바이트를 반환하고, 해석 함수는 복호화된 바이트를 받습니다. 지갑이 직접 호출하는 것은 1101·1102·1109 생성 함수와 1100·1108 해석 함수이며, 나머지는 dApp(AppKit)에서 사용합니다.

// 1100 scope_sessionPropose
fun propose(publicKeyRaw: ByteArray, dappName: String): ByteArray
fun proposePublicKey(bytes: ByteArray): ByteArray
fun requestedChains(bytes: ByteArray): List<String>
fun dappName(bytes: ByteArray): String

// 1101 propose 응답
fun proposeResponse(publicKeyRaw: ByteArray): ByteArray
fun responderPublicKey(bytes: ByteArray): ByteArray

// 1102 settle · 1103 ack
fun settle(controllerPublicKeyRaw: ByteArray, chains: List<String>, account: String): ByteArray
fun settledAddress(bytes: ByteArray): String
fun settleAck(): ByteArray

// 1108 서명 요청
fun signRequest(from: String, typedDataJson: String, chainId: String): ByteArray
fun signRequestTypedData(bytes: ByteArray): String

// 1109 서명 응답
fun signResponse(signatureHex: String): ByteArray
fun signRejection(code: Int, message: String): ByteArray
fun signResponseSignature(bytes: ByteArray): ByteArray
함수설명
proposepublicKeyRaw는 32바이트 X25519 공개키. eip155:1 체인과 eth_signTypedData_v4 메서드를 필수 네임스페이스에 포함합니다
proposePublicKeydApp의 32바이트 X25519 공개키. proposer·proposer.publicKey가 없거나 32바이트가 아니면 예외
requestedChainsrequired + optional namespace의 CAIP-2 체인을 중복 제거해 반환. 비어 있으면 ["eip155:1"]
dappNameproposer.metadata.name. 없으면 예외가 아니라 "Unknown dApp"을 반환하므로 표시 전 확인이 필요합니다
proposeResponse지갑의 32바이트 X25519 공개키를 responderPublicKey로 실어 보냅니다
responderPublicKey지갑의 32바이트 공개키. 필드 누락이나 길이 불일치 시 예외
settlechains를 CAIP-2 namespace 접두사로 묶어 각 체인에 {chain}:{account} CAIP-10 계정을 부여합니다. 이벤트는 accountsChanged
settledAddress지갑이 승인한 첫 번째 계정의 주소만 추출(eip155:1:0x…0x…). namespaces 누락 또는 계정 0건이면 예외
settleAck릴레이 프로토콜만 담은 dApp 측 확인 응답. 인자 없음
signRequestparams[from, typedDataJson] 순서. method는 항상 eth_signTypedData_v4
signRequestTypedDataparams[1]의 구조화 데이터 JSON. methodeth_signTypedData_v4가 아니거나 params가 2개 미만이면 예외
signResponse{"result": signatureHex}를 빌드합니다. signatureHex0x 접두사가 붙은 65바이트 서명 hex
signRejection{"error": {"code", "message"}} 응답을 만듭니다. 사용자 거절은 EIP-1193 4001을 사용하며, AppKit의 JSON-RPC 오류 응답 형식과 일치합니다
signResponseSignature{result}에서 65바이트(r‖s‖v) 서명을 반환. {error} 응답이거나 result 누락, 65바이트 불일치면 예외

signResponsesignRejection같은 태그 1109로 발행됩니다 — 성공과 거절을 태그가 아니라 본문(resulterror)으로 구분합니다. 지갑 흐름에서 두 함수가 호출되는 지점은 세션 연결의 시퀀스에 표시되어 있습니다.

EIP-3009 구조화 데이터

fun eip3009TypedData(
name: String,
version: String,
chainId: Long,
verifyingContract: String,
authz: TransferWithAuthorization,
): String

fun parseEip3009TypedData(typedDataJson: String): ParsedEip3009

data class ParsedEip3009(
val name: String,
val version: String,
val chainId: Long,
val verifyingContract: String,
val primaryType: String,
val authz: TransferWithAuthorization,
)

eth_signTypedData_v4params[1]에 들어가는 구조화 데이터 JSON을 생성·해석합니다. 지원하는 primaryTypeTransferWithAuthorization(가스리스 전송)과 ReceiveWithAuthorization(수신형 결제) 두 가지입니다.