본문으로 건너뛰기

WalletKit 오류 처리

WalletKit은 공통 오류 코드 enum을 제공하지 않고 표준 예외로 실패를 전달합니다. 지갑 앱은 예외 경로와 사용자 거부(approved = false)를 서로 다른 분기로 다룹니다.

dApp 쪽에서 던지는 AppError·AppResultCode와 릴레이·프로바이더 오류는 AppKit 오류 처리에서 다룹니다.

오류 유형

계층식별 방법대표 사용 위치
WalletKitRelayRpcException, TimeoutCancellationException 등 표준 예외지갑 앱의 페어링과 서명 응답
플랫폼그 밖의 ThrowableKtor, TLS, WebSocket, 주입한 의존성

Swift에서는 전파된 KMP 예외가 NSError로 감싸여 오므로 항상 catch 경로를 둡니다 — 감싸지 않으면 앱이 종료됩니다.

네트워크 작업은 Kotlin 비동기 작업의 취소를 삼키지 말고 호출자에게 전달하며, 자동 재연결 중에도 사용자 취소와 명시적 close()를 구분합니다.

WalletKit이 전달하는 예외

WalletKit(Kotlin Multiplatform)은 공통 오류 코드 enum 없이 표준 예외로 실패를 전달합니다. connect()@Throws(Throwable::class)로 선언되어 Swift에서 try/catch로 잡을 수 있습니다. 선언되지 않은 KMP 예외는 iOS 앱을 종료시키므로 지갑 앱은 항상 catch 경로를 둡니다.

RelayRpcException

AppKit RelayRpcError와 동일한 릴레이 JSON-RPC 코드 체계를 사용합니다.

필드타입설명
codeInt릴레이 JSON-RPC 코드
rpcMessageString릴레이가 반환한 메시지
isForbiddenTopicBoolean코드 2403 여부

상황별 예외

상황지갑 앱이 받는 오류기본 동작
잘못된 페어링 URIPairingUri.parse 예외
아직 생성되지 않은 토픽 구독RelayRpcException 2403SDK가 250ms 간격 최대 60회 재시도 후 실패 처리
세션 연결 제한 시간 초과TimeoutCancellationException기본 20초
서명 요청 제한 시간 초과TimeoutCancellationException기본 5분(signRequestTimeoutMs)
Signer 구현 실패구현이 던진 예외호출자에게 그대로 전달

사용자가 서명 요청을 거부하면 WalletKit은 dApp에 EIP-1193 4001 오류 응답을 보내고 WalletSessionResult(approved = false)를 반환합니다. 거부는 예외가 아니므로 approved 필드로 분기합니다.

지갑 앱에서 오류 처리

try {
val result = wallet.connect(uri, signer)
if (!result.approved) { /* 사용자 거부 */ }
} catch (e: RelayRpcException) {
if (e.isForbiddenTopic) { /* 2403 — 재시도는 SDK 내부에서 처리 */ }
else WalletKitLog.error("relay rpc ${e.code}", e)
} catch (e: Throwable) {
WalletKitLog.error("connect failed", e)
}

WalletKit 응답과 AppKit 오류 대응

지갑 측 응답과 dApp 측 오류는 다음과 같이 대응됩니다.

사용자 행동지갑(WalletKit) 응답dApp(AppKit)에서 받는 결과
서명 거부태그 1109 {error:{code:4001}}AppError(USER_REJECTED)
연결 거부응답 미전송, approved = false세션 Promise 대기 초과 시 SESSION_TIMEOUT
아직 생성되지 않은 토픽 구독RelayRpcException 2403 후 재시도없음. 토픽은 dApp이 생성
서명 거부는 오류 응답으로 전달됩니다

WalletKit은 서명 거부에만 릴레이 error 응답을 보내며, AppKit은 이를 성공 값이 아닌 USER_REJECTED 오류로 전달합니다. 연결 거부는 별도 응답을 보내지 않습니다.

제한 시간

경로현재 기본값공개 재정의
세션 연결 각 단계20초WalletKitConfig.handshakeTimeoutMs
settle 이후 서명 요청 대기5분WalletKitConfig.signRequestTimeoutMs
토픽 구독 재시도250ms 간격 최대 60회재정의 불가 — handshakeTimeoutMs와 별개로 동작

두 대기 모두 초과 시 TimeoutCancellationException을 던집니다. 이 예외는 CancellationException의 하위 타입이므로, 취소를 그대로 상위로 전달하는 코드가 타임아웃까지 사용자 취소로 오분류할 수 있습니다 — 타임아웃 실패 화면이 필요하면 타입을 먼저 확인합니다.

dApp 측 제한 시간(릴레이 제안·settle 각 300초)은 AppKit 오류 처리에서 확인합니다.

재시도 원칙

상황자동 재시도이유
사용자 거부아니요새 사용자 의도가 필요
잘못된 페어링 URI아니요동일 입력은 같은 결과
토픽 미생성(2403)SDK 내부에서 처리dApp이 토픽을 만드는 짧은 경쟁 상태
세션 연결·서명 요청 제한 시간새 세션만기존 세션 상태를 보장할 수 없음
소켓 단절전송이 자동 재연결대기 중 도착한 요청은 재연결 후 재생됨

오류 로그에는 페어링 URI, 채널 키, 서명 요청 원문, 서명과 개인키를 남기지 않습니다.