Was ist eine Krypto-Wallet? Wie interagiert sie mit der Blockchain?
Was ist eine Krypto-Wallet? Wie interagiert sie mit der Blockchain?
Veröffentlicht die 2022-07-28
Veröffentlicht die 2022-07-28

Einführung zu WalletConnect

Wie kann WalletConnect Ihnen helfen? Wie funktioniert es?

Um diese Fragen zu beantworten, müssen wir verstehen, dass Blockchain-Technologien die Dezentralisierung von Daten und Ausführungslogik ermöglichen. Bei herkömmlichen Web 2.0-Anwendungen gibt es im Allgemeinen zwei Möglichkeiten zur Identifizierung eines Nutzers: die Erstellung eines Kontos, wo die Anwendung Daten wie E-Mail und Passwort speichert, oder die Anmeldung über eine Drittanbieterverbindung wie Konten in sozialen Medien wie Facebook, Twitter, … oder Ihren bevorzugter E-Mail-Anbieter wie Google, Microsoft, … Beides sind zentralisierte Systeme. 

Bei einem dezentralen System speichert der Nutzer selbst seine "Anmeldedaten" mit sogenannten "privaten Schlüsseln" in seiner eigenen Krypto-Brieftasche. Mit einem privaten Schlüssel kann man den Besitz einer Blockchain-Adresse nachweisen und Transaktionen unterzeichnen. Sie sind daher von grossem Wert und werden folglich in einer Software- oder Hardware-Wallet gespeichert, um sie zu sichern. Es gibt jedoch viele verschiedene Wallet-Anbieter (MetaMask, Trust Wallet, ...), und wenn Sie nur einige wenige unterstützen, wird die Nutzerbasis Ihrer DApp eingeschränkt. Andererseits wäre es mühsam und komplex, die Verbindung mit allen Anbietern zu implementieren. An dieser Stelle kommt WalletConnect ins Spiel.

WalletConnect logo
WalletConnect logo

WalletConnect hilft DApps, sich mit Wallets zu verbinden. Und wie? Indem es als Mittelsmann zwischen Ihrer Dapp und der Wallet Ihres Nutzers fungiert. Es erleichtert die Softwareentwicklung erheblich, da Sie nur einmal die Verbindung mit WalletConnect implementieren müssen, um mehr als 170 verschiedene Wallet-Anbieter zu unterstützen.

WalletConnect fungiert als Mittelsmann zwischen der D-App und der Geldbörse des Nutzers.
WalletConnect fungiert als Mittelsmann zwischen der D-App und der Geldbörse des Nutzers.

Um eine Verbindung zwischen allen Akteuren herzustellen, müssen Sie zunächst die DApp mit dem Middleman-Server verbinden. Bei WalletConnect V1 wird der Middleman-Server als "Bridge-Server" bezeichnet, seine Adresse lautet bridge.walletconnect.org. Bei WalletConnect V2 wird der Vermittler "Relay-Server" genannt, seine Adresse lautet relay.walletconnect.com. Der zweite Schritt besteht darin, die Wallet des Nutzers mit dem Bridge/Relay-Server zu verbinden, wobei die DApp auf einem Desktop oder einem mobilen Gerät läuft und die Wallet sich auf dem mobilen Gerät befindet. Es sind mehrere Kombinationen möglich, die in der Tabelle unten aufgeführt sind.

Kompatibilitätstabelle für Wallet-Verbindung zwischen einer DApp und einem Wallet.
Kompatibilitätstabelle für Wallet-Verbindung zwischen einer DApp und einem Wallet.

In diesem Artikel behandeln wir die Mobile-Mobile-Verbindung mit Android und iOS. Im nächsten Abschnitt wird dies anhand eines praktischen Beispiels erläutert. Der Verbindungsprozess zwischen Ihrer DApp und dem Relay/Bridge-Server wird von Ihrer DApp gestartet, indem sie einen QR-Code anzeigt oder einen Deep Link öffnet. Dann muss der Nutzer die Anfrage bearbeiten, indem er seine bevorzugte Wallet-Anwendung auswählt.

Die Wallet-Anwendung sollte den URI automatisch verarbeiten und mit dem Relay/Bridge-Server kommunizieren. Nachdem eine Verbindung zwischen der Wallet und dem Relay/Bridge-Server hergestellt wurde, sendet der Relay/Bridge-Server einen Callback, um die DApp zu informieren, dass die Verbindung hergestellt wurde. Ihre DAppp ist nun bereit, mit der Blockchain zu interagieren, Transaktionen zu verarbeiten, ... und zwar mit der Wallet des Nutzers. Die folgende Abbildung fasst alle erforderlichen Schritte zusammen, um Ihre DApp mit der Wallet des Nutzers zu verbinden.

Schliessen Sie den Verbindungsvorgang zwischen einer DApp und der Brieftasche eines Benutzers mit WalletConnect ab.
Schliessen Sie den Verbindungsvorgang zwischen einer DApp und der Brieftasche eines Benutzers mit WalletConnect ab.

Praktisches Beispiel

In diesem Abschnitt wird ein praktisches Beispiel mit konkreten Codebeispielen gezeigt. Das Ziel ist eine Mobile-Mobile-Verbindung für iOS- und Android-Anwendungen unter Verwendung von WalletConnect V1 (V2 befindet sich derzeit in der Beta-Phase). Der vollständige iOS und Android Code der beiden funktionierenden Anwendungen ist auf unseren GitHub-Repositories zu finden.

Hier finden Sie die Android-Anwendung und hier die iOS-Anwendung

Android

Konfigurieren des Projekts

 Fügen Sie in Ihrer settings.gradle das jitpack Repository hinzu.

//setting.gradle

dependencyResolutionManagement {

   …

   repositories {

       maven { url "https://jitpack.io" }

   }

}

 Fügen Sie dann die folgenden Abhängigkeiten zu Ihrer app/build.gradle hinzu.

 

// app/build.gradle

dependencies {

...

implementation 'com.github.WalletConnect:kotlin-walletconnect-lib:0.9.6'

implementation 'com.github.komputing:khex:1.1.2'

implementation 'org.java-websocket:Java-WebSocket:1.4.0'

implementation 'com.squareup.moshi:moshi-kotlin:1.13.0'

implementation 'com.squareup.moshi:moshi:1.13.0'

implementation 'com.squareup.okhttp3:okhttp:4.9.3'

}

 

Verbinden der DApp mit dem Bridge-Server

 Setzen Sie zunächst ein paar statische Konstanten, die Ihre DApp und die Bridge definieren, sowie ein paar Variablen, die für die Verbindung mit WalletConnect verwendet werden.

 

companion object {

       private lateinit var client: OkHttpClient

       private lateinit var moshi: Moshi

       private lateinit var storage: WCSessionStore

       private lateinit var config: Session.Config

       private lateinit var session: Session

       private val bridgeUrl = "https://bridge.walletconnect.org"

       private val metaData = Session.PeerMeta(

              name = "nfscene",

              url = "nfscene.com",

              description = "nfscene WalletConnect demo"

       )

}

 Dann müssen Sie den HTTP-Client (OkHttpClient), den JSON-Parser (Moshi) und den Speicher, der die WalletConnect-Sitzung speichert, initialisieren.

 

client = OkHttpClient.Builder().build()

moshi = Moshi.Builder().add(KotlinJsonAdapterFactory()).build()

storage = FileWCSessionStore(

       File(

           getContext().cacheDir,

           "session_store.json"

       ).apply { createNewFile() }, moshi

)

 

Sie sind nun bereit, eine Sitzung mit dem Bridge-Server zu eröffnen.

 

fun resetSession(callback: Session.Callback) {

   nullOnThrow { session }?.clearCallbacks()

   val key = ByteArray(32).also { Random().nextBytes(it) }.toNoPrefixHexString()

   config = Session.Config(UUID.randomUUID().toString(), bridgeUrl, key)

   session = WCSession(

       config,

       MoshiPayloadAdapter(moshi),

       storage,

       OkHttpTransport.Builder(client, moshi),

       metaData

   )

   session.addCallback(callback)

   session.offer()

}

 Das Callback-Argument ist eine Klasse, die die Schnittstelle Session.Callback implementieren muss. Es müssen zwei Signaturen implementiert werden. Der fun onStatus(status: Status) wird aufgerufen, wenn eine Verbindungsänderung stattfindet. Nachdem die Methode session.offer() aufgerufen wurde, versucht die DApp, eine Verbindung mit dem Relay-Server herzustellen. Wenn dies gelingt, wird der Callback ausgeführt und Sie erhalten den Status: Session.Status.Connected .

 Verbinden der Brieftasche mit dem Brückenserver

Jetzt können Sie die Wallet mit dem Relay-Server verbinden. Dazu verwenden wir einen mobilen Deeplink, um eine Anwendung aufzurufen, die die Anfrage bearbeiten kann. Der Deeplink ist im Config-Objekt zu finden. Hier ist die Methode zum Aufruf des Deeplinks: 

fun signIn() {

   val intent = Intent(Intent.ACTION_VIEW, Uri.parse(config.toWCUri()))

   intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)

   getContext().startActivity(intent)

}

 Der Nutzer wählt seine bevorzugte Walet-Anwendung aus, um die Anfrage zu bearbeiten. Es wird nicht funktionieren, wenn auf dem Gerät keine Wallet-Anwendungen installiert sind.

Bestätigungs-Popup, das von der Wallet-Anwendung geöffnet wird, ausgelöst durch das Öffnen des Deeplinks.
Bestätigungs-Popup, das von der Wallet-Anwendung geöffnet wird, ausgelöst durch das Öffnen des Deeplinks.

Hier sehen Sie ein Beispiel für einen Bestätigungsdialog, der von der MetaMask-Mobilanwendung generiert wird. Nachdem der Benutzer die Verbindung akzeptiert hat, wird die Wallet-Aktivität geschlossen und Ihre DApp-Aktivität kehrt zurück. Die Callback-Methode wird mit dem Status aufgerufen: Session.Status.Approved . 

Eine vollständige Verbindungspipeline ist nun erreicht, Ihre Anfragen können dann über die WalletConnect-Bridge verarbeitet werden. Wenn Sie die Konten abrufen möchten, können Sie die Methode session.approvedAccounts()aufrufen. Um die Sitzung zu schliessen, rufen Sie einfach die Methode session.kill() auf. 

Das vollständige Android DApp-Beispiel ist in diesem GitHub-Repository zu finden.

 

iOS

Konfigurieren des Projekts

Um das WalletConnect SDK in einer iOS Anwendung zu verwenden, müssen Sie das WalletConnectSwift Paket zu Ihrem XCode Projekt hinzufügen. Klicken Sie auf Datei > Pakete hinzufügen... dann fügen Sie die WalletConnectSwift GitHub Repository URL in die Suchleiste ein und klicken auf Paket hinzufügen.

Fügen Sie das WalletConnect Swift-Paket zum XCode-Projekt hinzu.
Fügen Sie das WalletConnect Swift-Paket zum XCode-Projekt hinzu.

Anschliessend muss dem XCode-Projekt eine bestimmte Berechtigung erteilt werden, damit die Demo-Anwendung mobile Deeplinks öffnen kann. Fügen Sie dazu die folgenden LSApplicationQueriesSchemes in die info.plist Ihres Projekts ein.

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">

<plist version="1.0">

<dict>

<key>LSApplicationQueriesSchemes</key>

<array>

<string>wc</string>

</array>

</dict>

</plist>

 

Verbinden der DApp mit dem Bridgeserver

 Zunächst müssen Sie einige statische Konstanten festlegen: Definieren Sie Ihre Client-Informationen mit einer Session.ClientMeta-Struktur und erzeugen Sie einen 32-Byte-Schlüssel. Beides ist erforderlich, um Ihre DApp-Informationen zu definieren (innerhalb einer Session.DAppInfo-Struktur). 

 Ausserdem benötigen Sie einen "Delegaten", der dem ClientDelegate-Protokoll folgt, um Callback-Aufrufe bezüglich des Verbindungsstatus’ zu erhalten. In unserem Fall implementiert die Klasse selbst das ClientDelegate-Protokoll.

let clientMeta = Session.ClientMeta(name: "WalletConnectDemo",

description: "A mobile application acting as a Dapp to connect to a crypto wallet using the WalletConnect SDK",

icons: [],

url: URL(string: "https://nfscene.com")!)

let dAppInfo = Session.DAppInfo(peerId: UUID().uuidString, peerMeta: clientMeta)

client = Client(delegate: self, dAppInfo: dAppInfo)

 Bevor Sie die Verbindung mit dem Bridgeserver herstellen, müssen Sie die URL des Bridgeservers, zu dem Sie eine Verbindung herstellen möchten, mit einer WCURL-Struktur definieren. Nun kann die Verbindung mit dem Bridge-Server mit der Methode connect(to url: WCURL) hergestellt werden.

let wcUrl = WCURL(topic: UUID().uuidString,

bridgeURL: URL(string: "https://bridge.walletconnect.org/")!,

key: try! generateRandomKey())

try! client.connect(to: wcUrl)

 Wenn die Verbindung zwischen der DApp und dem Bridgeserver erfolgreich ist, erhält der zuvor definierte Delegat einen Aufruf der Methode client(_ client: Client, didConnect url: WCURL) .

Verbindung der Wallet mit dem Bridgeserver

 Nach erfolgreicher Verbindung zwischen der DApp und dem Bridgeserver besteht der nächste Schritt darin, die Wallet des Nutzers mit dem Bridgeserver zu verbinden. Dazu erstellen Sie einen mobilen Deeplink unter Verwendung der zuvor erstellten connectino-URL. Öffnen Sie dann den mobilen Deeplink mit Hilfe des UIApplication Frameworks.

 

let connectionUrl = wcUrl.absoluteString

let deepLinkUrl = "wc://wc?uri=\(connectionUrl)"

DispatchQueue.main.asyncAfter(deadline: .now() + 1) {

if let url = URL(string: deepLinkUrl), UIApplication.shared.canOpenURL(url) {

UIApplication.shared.open(url, options: [:], completionHandler: nil)

} else {

print("Failed to open deepLinkUrl \(deepLinkUrl)")

}

}

 Hinweis: Im Gegensatz zu Android kann unter iOS nur eine einzige Anwendung Deeplinks eines bestimmten Schemas öffnen. Dies bedeutet leider, dass der Nutzer nicht wählen kann, welche Wallet er öffnen möchte. Die zuletzt installierte Wallet-Anwendung, die das Schema unterstützt, wird geöffnet. Für die Zwecke dieser Demo empfehlen wir die auf dem Gerät installierte MetaMask-Wallet. Wir werden in einem zukünftigen Artikel erläutern, wie dieses Problem entschärft werden kann und wie der Nutzer wählen kann, welche Wallet er öffnen möchte.

 Abhängig von der Wallet-Anwendung des Nutzers wird ein Bestätigungsdialog geöffnet und der Nutzer wird um eine Bestätigung gebeten. Hier ist ein Beispiel für den MetaMask-Bestätigungsdialog auf einem iOS-Gerät.

Bestätigungs-Popup, das von der Wallet-Anwendung geöffnet wird, ausgelöst durch das Öffnen des Deeplinks.
Bestätigungs-Popup, das von der Wallet-Anwendung geöffnet wird, ausgelöst durch das Öffnen des Deeplinks.

Nachdem der Nutzer die Verbindung bestätigt hat, wird die DApp erneut geöffnet, und der zuvor definierte Delegat erhält einen Aufruf der Rückrufmethode client(_ client: Client, didConnect session: Session) .

Die Wallet-Informationen des Nutzers werden in der session.walletInfo-Struktur enthalten sein. Um die Sitzung zu schliessen, sollte die Methode disconnect(from session: Session) auf dem zuvor definierten Client aufgerufen werden.

Nun ist eine vollständige Verbindungspipeline zwischen Ihrer DApp und der Wallet des Nutzers hergestellt. Anfragen können nun über die WalletConnect-Bridge verarbeitet werden.

Das vollständige iOS DApp Beispiel kann in diesem GitHub Repository gefunden werden.

Zusammenfassung

Es werden immer mehr verschiedene Wallet-Anbieter geschaffen, und es wird für Sie als DApp-Entwickler eine Herausforderung sein, mit den Hauptakteuren auf dem Markt Schritt zu halten. WalletConnect löst dieses Problem mit einer sauberen, einfachen und effektiven Lösung, indem es als Mittelsmann zwischen Ihrer DApp und jedem Wallet-Anbieter fungiert. 

Bei nfscene schätzen wir diese Lösung sehr, da sie die Unterstützung von mehr Wallets ermöglicht und den Entwicklungsprozess vereinfacht. WalletConnect ist ein perfektes Technologiebeispiel für das, wofür wir stehen: die Demokratisierung der Blockchain. 

Allerdings gibt es immer auch Nachteile und Kompromisse. Die Verwendung eines Bridgeservers eines Drittanbieters könnte aus Sicherheitsgründen ein Problem darstellen, weshalb wir empfehlen, nur lesbare Transaktionen zu verwenden. Dieser kritische Punkt kann auch durch die Erstellung eines eigenen Bridgeservers gelöst werden.