본문으로 건너뛰기

2026-08-03

엔드포인트를 빌드 시점 값으로 고정 — 릴레이 WSS 주소와 Connect 백엔드 루트를 실행 시점 설정에서 제거하고 SDK 번들과 배포 파일에 포함했습니다. 두 값은 dApp·지갑별 설정이 아니라 배포 환경에 따라 결정됩니다. WalletKit은 스캔한 페어링 URI의 relay-url보다 빌드 값을 우선합니다. QR은 신뢰할 수 없는 입력이므로 지갑의 연결 대상을 바꿀 수 없어야 합니다.


주요 변경

백엔드 루트 (connectBaseUrl)

  • AppKitOptions.connectBaseUrl제거했습니다. 전달하던 dApp은 해당 옵션을 지우면 되며 백엔드 호출은 그대로 동작합니다.
  • @scope-connect/appkit-reactScopeAppKitConfig.connectBaseUrl 제거
  • AppKit.connectBaseUrl 속성은 남지만 항상 빌드 시점 값을 반환하며 실행 중에는 덮어쓸 수 없습니다.
  • @scope-connect/appkit-react의 백엔드 세션 활성화 조건 변경 — Phantom 모바일 백엔드 암호화 세션과 일반 지갑 세션은 이전에는 clientId와 명시적 connectBaseUrl이 모두 있을 때만 활성화되었습니다. 백엔드 루트가 항상 설정되므로 이제 clientId만 있으면 활성화됩니다(clientId는 필수이므로 사실상 항상 활성화). 이 기능을 끄려면 UI 없는 AppKit을 직접 구성합니다. genericWalletSession은 계속 명시적으로 켜야 합니다(기본값 off).

릴레이 (relayUrl)

  • AppKitOptions.relayUrl제거했습니다. 전달하던 dApp은 해당 옵션을 지우면 되며 릴레이 페어링은 그대로 동작합니다.
  • @scope-connect/appkit-reactScopeAppKitConfig.relayUrl 제거
  • pair()가 더 이상 릴레이 설정 누락으로 INVALID_CONFIG를 던지지 않는다 — 초기화된 AppKit은 언제나 페어링할 수 있다
  • WalletKit WalletKitConfig.relayUrl을 Kotlin·Swift에서 모두 제거했습니다. Swift는 기본 인자가 연결되지 않으므로 호출 코드에서 인자를 지워야 컴파일됩니다.
  • WalletKit은 페어링 URI의 relay-url연결 대상으로 사용하지 않습니다. dApp과 지갑이 서로 다른 릴레이로 빌드되면 페어링이 성립하지 않으며, 불일치는 WalletSessionResult.steps에 기록됩니다.

추가

  • @scope-connect/appkitDEFAULT_RELAY_URL 상수와 normalizeRelayUrl 함수를 공개 API로 제공 — CSP connect-src처럼 애플리케이션이 릴레이 origin을 알아야 하는 곳에서 사용한다 (DEFAULT_CONNECT_BASE_URL·normalizeConnectBaseUrl도 공개 API로 제공)
  • WalletKit RelayDefaults.DEFAULT_RELAY_URL — 빌드 시점에 생성되는 상수

변경

  • 빌드 시점 지정 방법
    • AppKit: 빌드 환경의 APPKIT_CONNECT_BASE_URLAPPKIT_RELAY_URL을 번들에 포함합니다. 데모 이미지는 docker build --build-arg APPKIT_CONNECT_BASE_URL=… --build-arg APPKIT_RELAY_URL=…로 지정합니다.
    • WalletKit: ./gradlew :walletkit:build -PscopeRelayUrl=… 또는 SCOPE_RELAY_URL=…
    • 지정하지 않으면 개발용 기본 엔드포인트 사용
  • 데모 dApp(connect/payment)에서 APPKIT_RELAY_URL·APPKIT_CONNECT_BASE_URL 런타임 주입 제거 — entrypoint.sh/__ENV.js/.env.example에서 빠졌다. 잔액 조회·스크리닝·CSP도 SDK의 빌드 시점 상수를 읽는다. 런타임 env로 남는 것은 APPKIT_CLIENT_ID(+데모 전용 키)뿐이다

적용 방법

  • dApp: 설정에서 relayUrl·connectBaseUrl 두 줄만 삭제합니다. 표준 배포에는 그 밖의 조치가 필요 없습니다.
  • 비표준 엔드포인트를 쓰던 dApp: 실행 시점에 주입하는 대신 빌드할 때 APPKIT_CONNECT_BASE_URLAPPKIT_RELAY_URL을 지정합니다.
  • @scope-connect/appkit-react를 쓰면서 일반 지갑 세션 기록을 원하지 않는 dApp: 이전에는 connectBaseUrl을 생략해 우회했지만 이제는 불가능합니다. UI 없는 AppKit을 직접 구성하고 genericWalletSession을 생략합니다.
  • 지갑(WalletKit): WalletKitConfig(...)에서 relayUrl 인자를 삭제합니다. 다른 릴레이가 필요하면 -PscopeRelayUrl로 다시 빌드합니다.

참고

  • 릴레이 주소에 잘못된 값(ws(s)://가 아닌 문자열)이 들어오면 내장 기본값을 사용한다 — QR을 띄운 뒤에야 지갑 쪽에서 거부당하는 상황을 막기 위해서다
  • 두 값이 빌드에 고정되면서 신뢰 경계가 실행 시점 설정에서 빌드 과정으로 이동합니다. 운영 번들이 운영 엔드포인트를 사용하도록 빌드되었는지 릴리스 체크리스트에서 확인합니다.

연결·서명 결과값 보강 — dApp이 반환값만으로 어떤 지갑에 연결되었고 다음에 무엇을 해야 하는지 알 수 있도록 SDK 결과 타입에 필드를 추가했습니다. 기존 필드는 바꾸지 않아 기존 dApp 코드도 그대로 동작합니다.

연결·서명 결과 추가

  • WalletConnection.walletId — 연결에 사용한 지갑 ID입니다. selectWallet()은 선택한 ID를 항상 기록하고, connect()는 새 공개 함수 walletIdForConnectorId로 커넥터 ID에 대응하는 지갑 ID를 확인할 수 있을 때 채웁니다. 릴레이 연결은 세션 승인 응답에 지갑 ID가 없어 설정되지 않습니다.
  • WalletConnection.transport — 모든 내장 커넥터가 값을 설정합니다. EIP-1193 계열(주입형/EIP-6963/MetaMask SDK)은 injected, Phantom 모바일은 connect-service입니다. 직접 구현한 외부 커넥터에서만 이 값이 없을 수 있습니다.
  • WalletConnection.expiry — 릴레이 세션의 settle이 만료(epoch 초)를 실은 경우 노출
  • PairResult.topic / timeoutMs / cancel() — 페어링 토픽과 QR 유효 시간, 진행 중인 페어링을 중단하는 함수를 추가했습니다. cancel()을 호출하면 session Promise가 거부됩니다.
  • SolanaSignedTransaction.userSignature — 연결된 지갑의 서명입니다. 서명자 키를 연결 계정과 대조해 찾고, 확인할 수 없으면 마지막으로 값이 있는 슬롯을 사용합니다. 데스크톱·모바일 모두 같은 필드를 사용하므로 dApp에서 슬롯 규칙을 따로 처리할 필요가 없습니다.
  • @scope-connect/appkit-react: useWalletConnection·세션 훅 3종에 lastError { code, message } — 연결 실패 원인을 AppResultCode(예: USER_REJECTED vs WALLET_NOT_FOUND)로 분기해 안내할 수 있다. 재시도 시 초기화

수정

  • 페어링 진행 중 소켓이 닫히면(취소 포함) 연결 과정의 대기 Promise에서 처리되지 않은 거부 오류가 남던 문제를 수정했습니다.