Wie man eine skalierbare dApp-Architektur entwickelt Von Smart Contracts bis zur Frontend-Integration
Grundlagen der dApp-Architektur
Das Internet, wie wir es kennen, ist kein lineares Gebilde, das einfach so entstanden ist, wie wir es heute kennen, und auch unsere heutige Nutzung wird sich in den nächsten Jahrzehnten nicht ändern. Das Web lässt sich in vier Hauptphasen unterteilen: Web 1, Web 2, Web 3 und Web 4. Diese existieren nebeneinander, jede mit ihren spezifischen Anwendungsbereichen und Anwendungsgebieten. Vereinfacht gesagt, war Web 1 von statischen Webseiten geprägt, der einfachsten Art von Website. Web 2 führte dynamische Webanwendungen ein und ermöglichte so die Entwicklung sozialer Medien und Netzwerke. Web 3 basiert auf der Erstellung dezentraler Anwendungen (dApps), Wallets, NFTs usw. mithilfe der Blockchain-Technologie. Web 4 ist noch weitgehend theoretisch, nutzt aber bereits KI in Arbeitsabläufen.
Da Web 4 noch nicht einmal ein klar definiertes Konzept ist, stellt Web 3 nach wie vor den modernsten und in der Regel fortschrittlichsten Ansatz für das Internet dar. Um damit erfolgreich zu sein, muss man die Architektur dezentraler Anwendungen verstehen, die im Wesentlichen aus Blockchain, Smart Contracts und Frontend-Integration besteht. In diesem Artikel geben wir eine Einführung in Web3 und dApps, den Aufbau skalierbarer Blockchain-Anwendungen sowie in diesen innovativen und teilweise noch geheimnisvollen Bereich der Softwareentwicklung.
Smart-Contract-Architektur: Entwicklung für Sicherheit und Skalierbarkeit
Man könnte sagen, dass Smart Contracts den kleinsten funktionalen Bestandteil der Architektur dezentraler Anwendungen (dApps) darstellen. Sie sind quasi das Backend der Anwendung: Der eigentliche Dienst, der die Logik ausführt und Vorgänge wie Zahlungen, Wallet-Verwaltung usw. abwickelt. Smart Contracts werden üblicherweise mit der Programmiersprache Solidity entwickelt, die JavaScript ähnelt, aber direkt in Binärcode kompiliert wird, um in der Blockchain ausgeführt werden zu können. Smart Contracts sind somit die absolute Wahrheitsquelle einer dApp und der Ort, an dem entscheidendes Vertrauen entsteht.
Smart Contracts werden üblicherweise mithilfe dreier zentraler Designmuster entwickelt: Proxy- oder Upgradefähigkeit, Factory Contracts und Zugriffskontrolle. Hier ein kurzer Überblick:
- Proxy (Aktualisierbarkeit): Sobald ein Smart Contract kompiliert und in der Blockchain, z. B. Ethereum, hinterlegt ist, erhält Ihre Anwendung eine Adresse, die nicht mehr geändert werden kann. Sie bleibt dauerhaft bestehen. Der Proxy ist daher notwendig, um die Weiterentwicklung und die Entwicklung neuer Funktionen für einen Dienst zu ermöglichen: Bei einem System-Upgrade erhalten Sie die Adresse des neuen Contracts und Ihre Anwendung verwendet diese. Dadurch wird der Contract aktualisierbar, ohne die Unveränderlichkeit der Blockchain zu beeinträchtigen.
- Factory Contracts: Das Factory-Pattern ist die optimale Lösung für Skalierung und Standardisierung. Anstatt neue Contracts manuell zu erstellen, erstellen Sie eine Vorlage und weisen einem Contract die Aufgabe zu, weitere Contracts zu generieren. Dies ist besonders nützlich, wenn ein Benutzer oder eine Organisation eigene Contract-Instanzen benötigt (z. B. Wallets, Pools, NFTs). Jeder Contract verwendet dasselbe Code-Muster und dieselbe Initialisierung und ist bis zum ursprünglichen Contract zurückverfolgbar.
- Zugriffskontrolle: Dieses Muster definiert, wer in einem Contract welche Aktionen ausführen darf. In dezentralen Systemen ist die Authentifizierung weitgehend identisch mit der traditionellen. Standardmäßig wird ein „Besitzer“-Flag verwendet, robustere Systeme können jedoch auch unterschiedliche Rollen zuweisen. Dieses Muster ist von entscheidender Bedeutung, da dApps üblicherweise mit realen Vermögenswerten in der Blockchain, wie beispielsweise Kryptowährungen, arbeiten. Jeder Fehler kann zu verheerenden finanziellen Verlusten führen, die in einer Blockchain-Umgebung nahezu unumkehrbar sind. Daher ist das Design sehr eindeutig: Jede Funktion muss klar definieren, wer sie ausführen darf und warum.
Bei der Erstellung von Smart Contracts gibt es einiges zu beachten: Die Ausführung von Code in der Blockchain ist nicht kostenlos. Die benötigte Rechenleistung wird durch eine Gebühr namens Gas bezahlt. Diese Gebühr muss üblicherweise in Ethereum entrichtet werden, und Ihre Software muss optimal darauf abgestimmt sein: Das Lesen von Variablen benötigt nur wenig Gas, das Schreiben im Speicher hingegen sehr viel, und die Kosten summieren sich schnell. Beachten Sie außerdem: Wenn Sie eine Transaktion starten, aber nicht genügend Gas haben, um sie abzuschließen, wird die Transaktion abgebrochen und Ihr Fortschritt geht verloren. Darüber hinaus ist höchste Aufmerksamkeit der Sicherheit geboten, insbesondere der Verhinderung von Angriffen wie Reentrancy und Overflow, wie wir später noch genauer erläutern werden.
Wie dezentrale Anwendungen miteinander kommunizieren
In der Architektur der dApp-Entwicklung kommunizieren verschiedene Anwendungen nicht direkt miteinander, wie es bei herkömmlichen REST-APIs der Fall ist. Stattdessen nutzen sie sogenannte Smart Contracts, die auf derselben Blockchain, beispielsweise Ethereum, ausgeführt werden. Dadurch entsteht ein Kompositionsmuster, bei dem ein Contract den anderen über die sogenannte Contract-to-Contract-Interaktion aufruft. Damit diese Interaktion reibungslos funktioniert, muss eine dApp öffentliche Funktionen bereitstellen, auf die andere dApps zugreifen können, ähnlich wie bei öffentlichen API-Endpunkten. So entsteht ein kompositionsfähiges Ökosystem, die sogenannten „Money Legos“, deren Architektur im folgenden Diagramm veranschaulicht wird:
Das Diagramm veranschaulicht diese Art der Interaktion: Der Einstiegspunkt ist der Proxy-Vertrag, der die Ausführung an die aktuellste Implementierung und deren interne Module weiterleitet. Die Interaktion kann sich dann auch nach außen richten, indem andere Verträge aufgerufen, bereits in der Blockchain gespeicherte gemeinsame Zustände genutzt oder Ereignisprotokolle ausgelöst werden usw.
Diese Architektur ermöglicht es mehreren verschiedenen dApps, gleichzeitig miteinander zu interagieren und zu kommunizieren. So entsteht ein Netzwerk von Smart Contracts, ähnlich wie bei traditionellen Microservices. Anwendungen können Logik, Liquidität oder Daten anderer Anwendungen wiederverwenden, indem sie mit deren Verträgen interagieren oder indizierte Ausgaben lesen. Das Ergebnis ist ein zusammensetzbares System, in dem unabhängige Anwendungen als Bausteine innerhalb einer großen und strukturierten Blockchain fungieren.
Frontend-Integration: Verbindung der Benutzeroberfläche mit Smart Contracts
Selbst die besten Smart Contracts der Welt machen Ihre dApp ohne ein Frontend für Ihre Nutzerbasis unvollständig. Die Integration von Smart Contract und Frontend erfolgt mithilfe spezialisierter Web3-JavaScript-Bibliotheken wie ethers.js oder web3.js. Sie dient als Brücke zwischen der Anwendungsoberfläche und dem auf der Blockchain veröffentlichten Vertrag und benötigt drei Hauptinformationen: die Vertragsadresse, die Vertrags-ABI und den Provider-RPC. Diese Informationen werden verwendet, um dem Frontend zu erklären, wie der Vertrag erstellt und koordiniert wird, welche Anfragen gesendet und welche Antworten erwartet werden usw.
Der Ablauf ist also folgendermaßen: Zuerst greift der Nutzer über eine Website oder eine mobile Anwendung auf das Frontend zu und verbindet sich mit einer Wallet (z. B. Metamask). Die Wallet stellt dann eine Verbindung zu einem RPC-Provider her, um Daten in einer Blockchain wie Ethereum zu lesen und zu schreiben. Anschließend ruft sie die eigentlichen Smart Contracts mit direktem Zugriff auf die Blockchain auf. Der Vorgang ist im Wesentlichen in dieser Infografik dargestellt:
Eine häufige Herausforderung bei solchen Integrationen besteht darin, die Benutzeroberfläche mit dem aktuellen Blockchain-Status zu synchronisieren, da die Blockchain Daten anders verarbeitet als herkömmliche APIs und jeder Lesevorgang zudem Gaskosten verursacht. Das Frontend muss ausstehende Transaktionen, Bestätigungen und Statusaktualisierungen verarbeiten und dabei oft direkt vom Smart Contract empfangene Daten mit indizierten Daten aus Tools wie The Graph verknüpfen. Ein gängiger Ansatz hierfür ist die Verwendung von Web3-Hooks und State-Management-Strategien, die sicherstellen, dass die Benutzeroberfläche Blockchain-Änderungen in Echtzeit widerspiegelt und die Benutzerfreundlichkeit nicht beeinträchtigt.
Schritt-für-Schritt-Anleitung zum Aufbau einer skalierbaren dApp-Architektur
Um die Architektur einer dApp mit Fokus auf Skalierbarkeit zu definieren, muss zunächst entschieden werden, welche Prozesse On-Chain und welche Off-Chain abgewickelt werden. Der On-Chain-Teil Ihrer Anwendung umfasst alle Vorgänge und Speicherorte innerhalb der Blockchain (z. B. Ausführung von Smart Contracts, Speichern permanenter Daten, Werttransfers usw.). On-Chain-Operationen sind langsam und teuer, da sie Gas verbrauchen und per Definition unveränderlich sind. Off-Chain hingegen umfasst alles, was außerhalb der Blockchain geschieht: Frontend, Indexer, APIs, Server, Cache usw. Off-Chain ist deutlich günstiger, schneller und flexibler und beinhaltet alles, was nicht direkt mit Geld zu tun hat.
Die Planung ist von entscheidender Bedeutung, da sie direkten Einfluss darauf hat, wie effizient und kostengünstig Ihre Anwendung funktioniert und wie nützlich Ihre dApp für Ihre Nutzerbasis ist. Anschließend befasst sich die Architektur mit der Ausführungsschicht: Smart Contracts, RPC-Infrastruktur, Layer 2, Indexierung und Frontend-Integration. Wie bereits erwähnt, führen Smart Contracts die Kernlogik aus und kommunizieren mit der Blockchain. Layer-2-Netzwerke tragen zur Senkung der Transaktionskosten bei, und Indexierungstools ermöglichen eine schnellere und kostengünstigere Navigation in der Blockchain sowie den Abruf von Daten.
Um Ihnen das praktische Verständnis zu erleichtern, finden Sie hier ein Beispiel, wie eine Anwendung mithilfe von ether.js über einen RPC-Provider eine Leseanfrage an die Blockchain senden kann:
import { ethers } from "ethers";
const RPC_URL = "https://eth-sepolia.g.alchemy.com/v2/YOUR_API_KEY";
const CONTRACT_ADDRESS = "0xYourContractAddress";
const ABI = [
"function balanceOf(address owner) view returns (uint256)",
"function totalSupply() view returns (uint256)",
];
async function readFromBlockchain() {
const provider = new ethers.JsonRpcProvider(RPC_URL);
const contract = new ethers.Contract(CONTRACT_ADDRESS, ABI, provider);
const userAddress = "0xUserWalletAddress";
const balance = await contract.balanceOf(userAddress);
const totalSupply = await contract.totalSupply();
console.log("User balance:", ethers.formatUnits(balance, 18));
console.log("Total supply:", ethers.formatUnits(totalSupply, 18));
}
readFromBlockchain();
Vor diesem Hintergrund können wir endlich mit der Entwicklung unserer dezentralen Anwendung beginnen und uns mit der Blockchain unserer Wahl verbinden – am häufigsten mit Ethereum. Bedenken Sie jedoch, dass jede Blockchain-Operation Kosten verursacht, die in Ethereum-Coins anfallen. Das bedeutet letztendlich, dass echtes Geld dafür ausgegeben wird. Entweder trägt der Kunde die Kosten oder Ihr Unternehmen – keine der beiden Alternativen ist wirklich optimal. Um Ihre App effizienter zu gestalten, gibt es verschiedene Alternativen, die Sie sorgfältig abwägen sollten.
Fazit: Web3-Architektur zukunftssicher gestalten
Das Web3-Ökosystem entwickelt sich rasant – in puncto Skalierbarkeit, Entwicklerwerkzeuge und Protokolldesign. All diese Aspekte verbessern sich stetig. Dank verbesserter RPC-Infrastruktur, effizienterer Indexierungssysteme und neuer Layer-2-Lösungen wandelt sich die Entwicklung und Skalierung von dApps hin zu mehr Zuverlässigkeit und einfacherer Skalierbarkeit. Modularität ist dabei ein wichtiges Architekturprinzip. Entwickler können neue Technologien implementieren, ohne das gesamte System neu schreiben zu müssen. Die Entkopplung von Smart Contracts von Infrastruktur und Frontend ermöglicht dies.
Die Entwicklung moderner dApp-Architekturen ist auf zukünftige Änderungen und Verbesserungen ausgelegt. Es geht darum, flexibel zwischen Layer-2-Netzwerken wechseln zu können, neue Protokoll-Upgrades zu unterstützen und die Performance zu steigern, wenn das Ökosystem wächst. Skalierbare dApp-Architekturen gewährleisten, dass Anwendungen sicher, effizient und zukunftssicher bleiben. So vermeiden Sie kostspielige Neuentwicklungen und können sich mit Web3 weiterentwickeln.