JEP's Diary

WalletConnect(2) 본문

Development/iOS

WalletConnect(2)

지으니88 2023. 4. 14. 17:35

Networking Configuration

네트워킹 클라이언트는 Sign, Auth 및 Chat SDK에 대한 전송 계층을 제공합니다. 한 번 구성하면 모든 SDK가 동일한 네트워킹 클라이언트 인스턴스를 통해 전송 프로토콜 메시지를 전송하며, 하나의 WebSocket 연결만 열리게 됩니다.

Sign 또는 Auth SDK를 사용하기 전에는, WalletConnect Cloud에서 프로젝트를 시작할 때 생성된 프로젝트 ID와 SocketFactory 인스턴스를 구성하는 것이 필요합니다.

 

Networking.configure(projectId: <String>, socketFactory: SocketFactory())

Pair Configuration

페어링 API 피어간 암호화된, 프로토콜에 중립적인 통신 계층을 설정하기 위한 경량 API입니다. 목적은 dapp 지갑간에 프로토콜 제안이나 요청을 보낼 있는 안전한 채널을 제공하는 것입니다.

WalletConnect Sign, Auth Push 프로토콜을 제공합니다. 페어링 API 표준 인터페이스를 노출하며 여러 프로토콜 요청을 단일 페어링에서 보내고 받을 있도록하므로 피어 재사용 가능한 통신 채널을 가능하게 합니다.

AppMetadata 객체를 생성하세요. 객체는 애플리케이션을 설명하고 브라우저에서의 표시 방법을 정의합니다. 다음, 생성한 메타데이터 객체로 Pair 인스턴스를 구성하세요.

let metadata = AppMetadata(name: <String>,
                           description: <String>,
                           url: <String>,
                           icons: <[String]>)

Pair.configure(metadata: metadata)
let uri WalletConnectURI(string: <String>)
try! await Pair.instance.pair(uri: uri)

Sign

Sign API 를 통해서 DAppDMS 사용자에게 거래나 메시지에 서명해달라고 요청할 수 있습니다. Sign 인스턴스가 피어로부터 요청을 받으면 관련 이벤트를 발행합니다. 그 이벤트를 처리하기 위해 구독을 설정하세요.

세션 제안(Session Proposal)은 DApp이 보내는 핸드셰이크(Handshake)로, 세션 규칙을 정의하는 것이 목적입니다. 핸드셰이크 절차는 CAIP-25에 의해 정의됩니다. Session.Proposal 객체는 필요한 ProposalNamespaces 집합을 전달하며, 이는 필요한 블록체인 메서드와 이벤트를 포함합니다. DApp은 네임스페이스에 정의된 메서드와 지갑으로 이벤트를 요청합니다.

Session 객체는 DApp과의 활성 세션 연결을 나타낸다. 이 객체에는 DApp의 메타데이터(사용자에게 활성 세션을 표시하는 데 사용할 수 있음), 네임스페이스 및 만료 날짜가 포함됩니다. 또한 관련된 세션과의 요청을 연결하기 위해 사용할 주제(topic) 속성도 있습니다.

좋은 사용자 경험을 위해 지갑은 사용자가 원하지 않는 세션을 해제할 수 있도록 허용해야 합니다. 세션을 종료하기 위해 해제(disconnect) 메서드를 사용하세요.

Session의 만료기간은 7일이다.

Sign.instance.sessionsPublisher
    .receive(on: DispatchQueue.main)
    .sink { [unowned self] (sessions: [Session]) in
        // reload UI
    }.store(in: &publishers)
    public var sessionsPublisher: AnyPublisher<[Session], Never>
    public var sessionProposalPublisher: AnyPublisher<Session.Proposal, Never> 
    public var sessionRequestPublisher: AnyPublisher<Request, Never> 
    public var socketConnectionStatusPublisher: AnyPublisher<SocketConnectionStatus, Never> 
    public var sessionSettlePublisher: AnyPublisher<Session, Never> 
    public var sessionDeletePublisher: AnyPublisher<(String, Reason), Never> 
    public var sessionResponsePublisher: AnyPublisher<Response, Never> 
    public var sessionRejectionPublisher: AnyPublisher<(Session.Proposal, Reason), Never> 
    public var sessionUpdatePublisher: AnyPublisher<(sessionTopic: String, namespaces: [String : SessionNamespace]), Never>
    public var sessionEventPublisher: AnyPublisher<(event: Session.Event, sessionTopic: String, chainId: Blockchain?), Never> 
    public var sessionUpdateExpiryPublisher: AnyPublisher<(sessionTopic: String, expiry: Date), Never>
try await Pair.instance.pair(uri: uri)

 

Auth

Account 객체와 자체적으로 구현한 SignerFactory 사용하여 Auth 인스턴스를 구성하세요.

Auth.configure(
    account: Account("eip155:56:0xe5EeF1368781911d265fDB6946613dA61915a501")!,
    signerFactory: <SignerFactory>
)

Auth 인스턴스가 피어 클라이언트로부터 요청이나 응답을 받으면 관련 이벤트를 발행합니다. 따라서 이를 처리하기 위해 구독을 설정해야 합니다.

Auth.instance.authRequestPublisher
    .receive(on: DispatchQueue.main)
    .sink { [unowned self] _ in
        //handle event
    }.store(in: &publishers)

dapp과 페어링한 후, 당신의 지갑은 인증 요청을 구독합니다. 요청은 authRequestPublisher에 의해 발행됩니다. 지갑이 요청을 받으면 사용자에게 보여주고 서명을 요청해야 합니다. 사용자가 인증 메시지에 서명한 후, 지갑은 dapp에 응답해야 합니다.

Type 매개변수는 DApp 측에서 사용될 서명 검증 방법을 나타냅니다. 지원되는 서명 검증 방법은 EIP191 EIP1271입니다. 경우 모두 메시지가 EIP191 표준으로 서명됩니다.

 

Push

Push dapp 인스턴스가 피어 클라이언트로부터 푸시 요청이나 메시지를 받으면 관련 이벤트를 발행합니다. 요청을 받으려면 해당 publisher 구독하세요.

Push.wallet.responsePublisher
    .receive(on: DispatchQueue.main)
    .sink { [unowned self] id, result in
        //handle event
    }.store(in: &publishers)

 

Echo

구성된 Echo SDK 사용하면 사용자가 중요 이벤트(: 인증 요청 또는 서명 세션 요청) 대한 푸시 알림을 장치에서 받을 있습니다.

Echo.configure(clientId: clientId, environment: .production)
try await Echo.instance.register(deviceToken: deviceToken)

연결 흐름(DApp-WalletApp)

  1. DApp은 New Pairing 을 위한 QR 코드를 생성한다.
  2. WalletApp 은 QR을 스캔하여 읽은 Uri로 페어링을 한다.
  3. 페어링이 성공하면 DApp 으로부터 Session Proposal이 온다.
  4. WalletApp은 Session.Proposal으로 전달된 requiredNamespaces(optionalNamespaces)을 확인하고 필요한 처리한 후 Session Proposal을 승인하거나 거절을 한다.
  5. Session Proposal을 승인하면 sessionsPublisher, sessionSettlePublisher 콜백을 통해 Session이 전달된다.
// 2.페어링 
Pair.instance.pair(uri: uri)
// 4.Proposal안에 있는 ProposalNamespace
public struct ProposalNamespace: Equatable, Codable {
    public let chains: Set<Blockchain>?
    public let methods: Set<String>
    public let events: Set<String>
}
// 4.Session Proposal 승인
Sign.instance.approve(proposalId: sessionProposal.id, namespaces: sessionNamespaces)

Disconnect 관리

Pair와 Session의 Disconnect는 독립적이다. 즉 Session만 Disconnect하면 Pair는 connected 상태이고, Pair만 Disconnect하면 Session은 connected 상태이며 Session 요청을 받을 수 있다.

Session은 사용자가 명시적으로 Disconnect 하는 기능을 제공해야 할 것 같으나, Pair에 대한 Disconnect는 좀더 고민이 필요하다.

테스트 DApp과의 테스트할때는 Session을 끊어야 DApp에서도 화면이 연결 끊김 상태로 전환된다.

Pair, Session 모두 Disconnect 해도 WebSocket은 연결된 상태이다. (ping 이벤트를 계속 받고 있다.) WebSocket의 연결 상태는 앱 생명주기를 따르며 SDK 내부에서 관리해준다.

 

Session과 Pairing의 차이 

세션은 사용자의 지갑과 dApp 사이의 실시간 연결을 가리키며, 페어링은 지갑과 dApp 사이의 안전한 연결을 수립하는 초기 과정을 의미합니다.

사용자가 WalletConnect를 지원하는 dApp을 열면, dApp은 사용자가 지갑 앱에서 스캔해야 하는 고유한 페어링 코드를 생성합니다. 페어링 과정을 시작하기 위해 사용자는 해당 코드를 스캔해야 합니다. 페어링이 완료되면 세션이 수립되어, dApp이 인터넷을 통해 지갑 앱과 안전하게 통신할 수 있게 됩니다.

세션 동안 dApp 지갑 앱에게 거래나 메시지 서명 등의 요청을 보낼 있고, 지갑 앱은 이에 대한 응답을 dApp에게 다시 보낼 있습니다. 세션은 사용자가 dApp 종료하거나 지갑을 연결 해제할 때까지 활성 상태를 유지합니다.

'Development > iOS' 카테고리의 다른 글

Concurrency(1)  (0) 2023.04.18
WalletConnect (1)  (0) 2023.04.14
Combine  (0) 2022.10.27
SwiftUI Custom Alert  (0) 2022.08.04
SwiftUI 투명 fullScreenCover  (0) 2022.08.04