paint-brush
Lassen Sie uns Ticketmaster revolutionieren, indem wir ein Web3-Ticketsystem aufbauenvon@MichaelB
2,225 Lesungen
2,225 Lesungen

Lassen Sie uns Ticketmaster revolutionieren, indem wir ein Web3-Ticketsystem aufbauen

von Michael17m2023/04/29
Read on Terminal Reader
Read this story w/o Javascript

Zu lang; Lesen

Ein beliebter und praktischer Anwendungsfall für NFTs ist die Generierung von Tickets für Live-Events. Wir werden einen Smart Contract einsetzen, der als Ticketing-Service fungiert und Tickets als ERC-20 Non-fungible Tokens (NFTs) erstellt. Die Verwendung von Smart Contracts und NFTs ermöglicht sogar neue Einnahmequellen wie Lizenzgebührenzahlungen und Umsatzbeteiligung.
featured image - Lassen Sie uns Ticketmaster revolutionieren, indem wir ein Web3-Ticketsystem aufbauen
Michael HackerNoon profile picture
0-item
1-item
2-item

Ein beliebter und praktischer Anwendungsfall für NFTs ist die Generierung von Tickets für Live-Events. Blockchains wie Ethereum können den Besitz, den Urheber und die Authentizität eines digitalen Gegenstands garantieren und so das Problem gefälschter Tickets effektiv lösen. Während große Player wie Ticketmaster darum kämpfen, Scalper (die verzweifelt kontrollieren wollen, wer Tickets wo und für wie viel weiterverkaufen darf) und Ticketbetrug einzudämmen, hat web3 bereits eine Lösung. Die Ticketing-Branche ist reif für Umwälzungen.


In diesem Tutorial schauen wir uns an, wie man eine solche Ticketing-Lösung mit ConsenSys Truffle , Infura und der Infura NFT API erstellt. Wir werden einen intelligenten Vertrag einsetzen, der als Ticketservice fungiert und Tickets als nicht fungible ERC-20-Token (NFTs) erstellt. Wir werden auch einige Architekturen potenzieller Frontends durchgehen, die mit dem Vertrag verbunden sein könnten und zusammen als integriertes, umfassendes Web3-Ticketsystem fungieren könnten.


Lasst uns bauen!

Erstellen Sie ein NFT-Ticketsystem auf Ethereum

Die Grundarchitektur unseres Systems zielt darauf ab, einen Smart Contract zu erstellen, der unsere Tickets als nicht fungible Token (NFTs) ausgibt. NFTs sind perfekt für das, was wir bauen wollen. Es handelt sich um nachweislich einzigartige digitale Token, mit denen wir sicherstellen können, dass jedes Ticket einzigartig ist und nicht kopiert oder gefälscht werden kann. Dies garantiert nicht nur ein sicheres Ticketerlebnis für Konzertbesucher, sondern ermöglicht Künstlern (und Veranstaltern) auch eine bessere Kontrolle über den Ticketvertrieb, die Preisgestaltung und den Weiterverkauf. Der Einsatz von Smart Contracts und NFTs ermöglicht sogar neue Einnahmequellen wie Lizenzzahlungen und Umsatzbeteiligung!


(Wenn Sie Hintergrundinformationen zu einem dieser Begriffe, der Blockchain-Technologie oder Web3 im Allgemeinen benötigen, lesen Sie diesen Artikel zum Thema „Lernen, ein Web3-Entwickler zu werden, indem Sie den Web3-Stack erkunden “).

Schritt 1: MetaMask installieren

Als Erstes richten wir ein MetaMask-Wallet ein und fügen das Sepolia-Testnetzwerk hinzu. MetaMask ist die weltweit beliebteste, sicherste und benutzerfreundlichste selbstverwaltete digitale Geldbörse.

Laden Sie zunächst die MetaMask-Erweiterung herunter . Nachdem Sie die Erweiterung installiert haben, richtet MetaMask das Wallet für Sie ein. Dabei erhalten Sie eine Geheimphrase. Bewahren Sie es sorgfältig auf und machen Sie es unter keinen Umständen öffentlich.


Nachdem Sie MetaMask eingerichtet haben, klicken Sie oben rechts auf die Registerkarte „Netzwerk“. Sie sehen eine Option zum Ein-/Ausblenden von Testnetzwerken.


Sobald Sie Testnetzwerke aktivieren, sollten Sie das Sepolia-Testnetzwerk im Dropdown-Menü sehen können. Wir möchten das Sepolia-Netzwerk nutzen, damit wir unser System bereitstellen und testen können, ohne echtes Geld auszugeben.

Schritt 2: Holen Sie sich eine Test-ETH

Um unseren Smart Contract einzusetzen und mit ihm zu interagieren, benötigen wir eine kostenlose Test-ETH. Sie können kostenlose Sepolia ETH über den Sepolia-Faucet erhalten.


Sobald Sie Ihr Guthaben aufgeladen haben, sollte beim Wechsel zum Sepolia-Testnetzwerk auf MetaMask ein Guthaben ungleich Null angezeigt werden.



Schritt 3: Installieren Sie NPM und Node

Wie alle Ethereum-Dapps werden wir unser Projekt mit Node und NPM erstellen. Falls Sie diese nicht auf Ihrem lokalen Computer installiert haben, können Sie dies hier tun.


Um sicherzustellen, dass alles ordnungsgemäß funktioniert, führen Sie den folgenden Befehl aus:

 $ node -v


Wenn alles gut geht, sollten Sie eine Versionsnummer für Node sehen.

Schritt 4: Registrieren Sie sich für ein Infura-Konto

Um unseren Vertrag im Sepolia-Netzwerk bereitzustellen, benötigen wir ein Infura-Konto. Infura ermöglicht uns den Zugriff auf RPC-Endpunkte, die einen schnellen, zuverlässigen und einfachen Zugriff auf die Blockchain unserer Wahl ermöglichen.


Eröffnen Sie ein kostenloses Konto . Sobald Sie Ihr Konto erstellt haben, navigieren Sie zum Dashboard und wählen Sie „Neuen Schlüssel erstellen“ aus.



Wählen Sie als Netzwerk die Web3-API und nennen Sie sie „Ticketing System“ oder einen Namen Ihrer Wahl.


Sobald Sie auf „Erstellen“ klicken, generiert Infura einen API-Schlüssel für Sie und stellt Ihnen automatisch RPC-Endpunkte für Ethereum, Goerli, Sepolia, L2s und Nicht-EVM-L1s (und ihre entsprechenden Testnetze) zur Verfügung.

Für dieses Tutorial interessieren wir uns nur für den Sepolia RPC-Endpunkt. Diese URL hat die Form https://sepolia.infura.io/v3/←API KEY→

Schritt 5: Erstellen Sie ein Node-Projekt und installieren Sie die erforderlichen Pakete

Lassen Sie uns ein leeres Projekt-Repository einrichten, indem wir die folgenden Befehle ausführen:

 $ mkdir nft-ticketing && cd nft-ticketing $ npm init -y


Wir werden Truffle verwenden, eine erstklassige Entwicklungsumgebung und ein Testframework für EVM-Smart Contracts, um unseren Kryptowährungs-Smart Contract zu erstellen und bereitzustellen. Installieren Sie Truffle, indem Sie Folgendes ausführen:

 $ npm install —save truffle


Wir können jetzt ein Barebone-Truffle-Projekt erstellen, indem wir den folgenden Befehl ausführen:

 $ npx truffle init


Um zu überprüfen, ob alles ordnungsgemäß funktioniert, führen Sie Folgendes aus:

 $ npx truffle test


Wir haben Truffle jetzt erfolgreich konfiguriert. Als nächstes installieren wir das OpenZeppelin- Vertragspaket. Mit diesem Paket erhalten wir Zugriff auf die ERC-721-Basisimplementierung (den Standard für nicht fungible Token) sowie auf einige hilfreiche Zusatzfunktionen.

 $ npm install @openzeppelin/contracts


Damit Truffle unser MetaMask-Wallet nutzen, Transaktionen signieren und in unserem Namen Benzin bezahlen kann, benötigen wir ein weiteres Paket namens hdwalletprovider . Installieren Sie es mit dem folgenden Befehl:

 $ npm install @truffle/hdwallet-provider


Um unsere sensiblen Wallet-Informationen zu schützen, verwenden wir schließlich das Paket dotenv .

 $ npm install dotenv

Schritt 6: Erstellen Sie den Ticketing-Smart-Vertrag für den NFT

Öffnen Sie das Projekt-Repository in einem Code-Editor (z. B. VS Code). Erstellen Sie im contracts eine neue Datei mit dem Namen NftTicketing.sol .


Unser Ticketing-Vertrag übernimmt alle Funktionen, die von der ERC721Enumerable -Implementierung von OpenZeppelin angeboten werden. Dazu gehören Übertragungen, Metadatenverfolgung, Eigentumsdaten usw.


Wir werden die folgenden Funktionen von Grund auf implementieren:

  1. Öffentlicher Hauptverkauf : Unser Vertrag gibt seinem Eigentümer die Befugnis, Tickets zu einem bestimmten Preis zu verkaufen. Der Eigentümer hat die Befugnis, den Verkauf zu eröffnen und zu schließen, die Ticketpreise zu aktualisieren und alle an den Vertrag für den Ticketkauf gezahlten Beträge abzuheben. Die Öffentlichkeit hat die Möglichkeit, Tickets zum Verkaufspreis zu prägen, solange der Verkauf geöffnet ist und noch Tickets im Angebot sind.
  2. Airdropping : Der Eigentümer kann Tickets per Airdrop an eine Liste von Wallet-Adressen senden.
  3. Reservierung : Der Eigentümer hat auch die Möglichkeit, Tickets für sich selbst zu reservieren, ohne den öffentlichen Verkaufspreis zahlen zu müssen.


Fügen Sie den folgenden Code zu NftTicketing.sol hinzu.

 //SPDX-License-Identifier: MIT pragma solidity ^0.8.19; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; import "@openzeppelin/contracts/utils/Counters.sol"; import "@openzeppelin/contracts/utils/Base64.sol"; import "@openzeppelin/contracts/utils/Strings.sol"; contract NftTicketing is ERC721, ERC721Enumerable, ERC721URIStorage, Ownable { using Counters for Counters.Counter; Counters.Counter private _tokenIds; // Total number of tickets available for the event uint public constant MAX_SUPPLY = 10000; // Number of tickets you can book at a time; prevents spamming uint public constant MAX_PER_MINT = 5; string public baseTokenURI; // Price of a single ticket uint public price = 0.05 ether; // Flag to turn sales on and off bool public saleIsActive = false; // Give collection a name and a ticker constructor() ERC721("My NFT Tickets", "MNT") {} // Generate NFT metadata function generateMetadata(uint tokenId) public pure returns (string memory) { string memory svg = string(abi.encodePacked( "<svg xmlns='http://www.w3.org/2000/svg' preserveAspectRatio='xMinyMin meet' viewBox='0 0 350 350'>", "<style>.base { fill: white; font-family: serif; font-size: 25px; }</style>", "<rect width='100%' height='100%' fill='red' />", "<text x='50%' y='40%' class='base' dominant-baseline='middle' text-anchor='middle'>", "<tspan y='50%' x='50%'>NFT Ticket #", Strings.toString(tokenId), "</tspan></text></svg>" )); string memory json = Base64.encode( bytes( string( abi.encodePacked( '{"name": "NFT Ticket #', Strings.toString(tokenId), '", "description": "A ticket that gives you access to a cool event!", "image": "data:image/svg+xml;base64,', Base64.encode(bytes(svg)), '", "attributes": [{"trait_type": "Type", "value": "Base Ticket"}]}' ) ) ) ); string memory metadata = string( abi.encodePacked("data:application/json;base64,", json) ); return metadata; } // Reserve tickets to creator wallet function reserveNfts(uint _count) public onlyOwner { uint nextId = _tokenIds.current(); require(nextId + _count < MAX_SUPPLY, "Not enough NFTs left to reserve"); for (uint i = 0; i < _count; i++) { string memory metadata = generateMetadata(nextId + i); _mintSingleNft(msg.sender, metadata); } } // Airdrop NFTs function airDropNfts(address[] calldata _wAddresses) public onlyOwner { uint nextId = _tokenIds.current(); uint count = _wAddresses.length; require(nextId + count < MAX_SUPPLY, "Not enough NFTs left to reserve"); for (uint i = 0; i < count; i++) { string memory metadata = generateMetadata(nextId + i); _mintSingleNft(_wAddresses[i], metadata); } } // Set Sale state function setSaleState(bool _activeState) public onlyOwner { saleIsActive = _activeState; } // Allow public to mint NFTs function mintNfts(uint _count) public payable { uint nextId = _tokenIds.current(); require(nextId + _count < MAX_SUPPLY, "Not enough NFT tickets left!"); require(_count > 0 && _count <= MAX_PER_MINT, "Cannot mint specified number of NFT tickets."); require(saleIsActive, "Sale is not currently active!"); require(msg.value >= price * _count, "Not enough ether to purchase NFTs."); for (uint i = 0; i < _count; i++) { string memory metadata = generateMetadata(nextId + i); _mintSingleNft(msg.sender, metadata); } } // Mint a single NFT ticket function _mintSingleNft(address _wAddress, string memory _tokenURI) private { // Sanity check for absolute worst case scenario require(totalSupply() == _tokenIds.current(), "Indexing has broken down!"); uint newTokenID = _tokenIds.current(); _safeMint(_wAddress, newTokenID); _setTokenURI(newTokenID, _tokenURI); _tokenIds.increment(); } // Update price function updatePrice(uint _newPrice) public onlyOwner { price = _newPrice; } // Withdraw ether function withdraw() public payable onlyOwner { uint balance = address(this).balance; require(balance > 0, "No ether left to withdraw"); (bool success, ) = (msg.sender).call{value: balance}(""); require(success, "Transfer failed."); } // Get tokens of an owner function tokensOfOwner(address _owner) external view returns (uint[] memory) { uint tokenCount = balanceOf(_owner); uint[] memory tokensId = new uint256[](tokenCount); for (uint i = 0; i < tokenCount; i++) { tokensId[i] = tokenOfOwnerByIndex(_owner, i); } return tokensId; } // The following functions are overrides required by Solidity. function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) internal override(ERC721, ERC721Enumerable) { super._beforeTokenTransfer(from, to, tokenId, batchSize); } function _burn(uint256 tokenId) internal override(ERC721, ERC721URIStorage) { super._burn(tokenId); } function tokenURI(uint256 tokenId) public view override(ERC721, ERC721URIStorage) returns (string memory) { return super.tokenURI(tokenId); } function supportsInterface(bytes4 interfaceId) public view override(ERC721, ERC721Enumerable) returns (bool) { return super.supportsInterface(interfaceId); } }


Stellen Sie sicher, dass der Vertrag korrekt kompiliert wird, indem Sie Folgendes ausführen:

 npx truffle compile


Unser Vertrag ist bereits ziemlich komplex, aber es ist möglich, nach Belieben einige zusätzliche Funktionen hinzuzufügen.


Sie können beispielsweise einen Anti-Scalping-Mechanismus in Ihren Vertrag integrieren. Die Schritte dazu wären wie folgt:


  1. Definieren Sie eine Solidity-Zuordnung, die als Zulassungsliste für Wallets fungiert, die mehr als ein Ticket enthalten können.
  2. Erstellen Sie eine Funktion, die es dem Eigentümer ermöglicht, dieser Zulassungsliste Adressen hinzuzufügen.
  3. Führen Sie einen Check-in _ beforeTokenTransfer ein, der die Prägung oder Übertragung auf eine Wallet, die bereits ein Ticket enthält, nur dann ermöglicht, wenn es auf der Zulassungsliste steht.


Fügen Sie den folgenden Ausschnitt unter dem Konstruktor des Vertrags hinzu:

 mapping(address => bool) canMintMultiple; // Function that allowlists addresses to hold multiple NFTs. function addToAllowlist(address[] calldata _wAddresses) public onlyOwner { for (uint i = 0; i < _wAddresses.length; i++) { canMintMultiple[_wAddresses[i]] = true; } }


Ändern Sie abschließend die Funktion _ beforeTokenTranfer wie folgt:

 // The following functions are overrides required by Solidity. function _beforeTokenTransfer(address from, address to, uint256 tokenId, uint256 batchSize) internal override(ERC721, ERC721Enumerable) { if (balanceOf(to) > 0) { require(to == owner() || canMintMultiple[to], "Not authorized to hold more than one ticket"); } super._beforeTokenTransfer(from, to, tokenId, batchSize); }


Kompilieren Sie den Vertrag noch einmal mit dem obigen Truffle-Befehl.

Schritt 7: Aktualisieren Sie die Truffle-Konfiguration und erstellen Sie eine .env-Datei

Erstellen Sie im Stammverzeichnis des Projekts eine neue Datei mit dem Namen .env und fügen Sie den folgenden Inhalt hinzu:

 INFURA_API_KEY = "https://sepolia.infura.io/v3/<Your-API-Key>" MNEMONIC = "<Your-MetaMask-Secret-Recovery-Phrase>"


Als Nächstes fügen wir unserer Truffle-Konfigurationsdatei Informationen über unser Wallet, den Infura RPC-Endpunkt und das Sepolia-Netzwerk hinzu. Ersetzen Sie den Inhalt von truffle.config.js durch Folgendes:

 require('dotenv').config(); const HDWalletProvider = require('@truffle/hdwallet-provider'); const { INFURA_API_KEY, MNEMONIC } = process.env; module.exports = { networks: { development: { host: "127.0.0.1", port: 8545, network_id: "*" }, sepolia: { provider: () => new HDWalletProvider(MNEMONIC, INFURA_API_KEY), network_id: '5', } } };

Schritt 8: Stellen Sie den NFT Smart Contract bereit

Lassen Sie uns nun ein Skript schreiben, um unseren Vertrag in der Sepolia-Blockchain bereitzustellen.


Erstellen Sie im migrations eine neue Datei mit dem Namen 1_deploy_contract.js und fügen Sie den folgenden Code hinzu:

 // Get instance of the NFT contract const nftContract = artifacts.require("NftTicketing"); module.exports = async function (deployer) { // Deploy the contract await deployer.deploy(nftContract); const contract = await nftContract.deployed(); // Mint 5 tickets await contract.reserveNfts(5); console.log("5 NFT Tickets have been minted!") };


Wir sind bereit! Stellen Sie den Vertrag bereit, indem Sie den folgenden Befehl ausführen:

 truffle migrate --network sepolia


Wenn alles gut geht, sollten Sie eine Ausgabe (mit der Vertragsadresse) sehen, die etwa so aussieht:

 Starting migrations... ====================== > Network name: 'sepolia' > Network id: 5 > Block gas limit: 30000000 (0x1c9c380) 1_deploy_contract.js ==================== Deploying 'NftTicketing' ----------------------- > transaction hash: … > Blocks: 2 Seconds: 23 … > Saving artifacts ------------------------------------- > Total cost: 0.1201 ETH Summary ======= > Total deployments: 1 > Final cost: 0.1201 ETH


Sie können auf Sepolia etherscan nach Ihrer Vertragsadresse suchen und diese live sehen.

Glückwunsch! Sie haben den Vertrag erfolgreich für Sepolia bereitgestellt.


Schritt 9: Schnittstelle zum Smart Contract


Wir haben unseren Smart Contract! Der nächste Schritt besteht darin, Frontends bereitzustellen, die mit dem Vertrag interagieren und es jedem ermöglichen, die Mint-Funktion aufzurufen, um eine Spende zu tätigen und ein Ticket für sich selbst zu prägen.


Für einen voll funktionsfähigen Ticketservice benötigen Sie normalerweise die folgenden Frontends:

  1. Eine Website (mit einem großartigen Benutzererlebnis), auf der öffentliche Benutzer ihre Tickets bezahlen und prägen können.
  2. Ein Admin-Portal, über das der Besitzer Tickets reservieren und per Airdrop abgeben, Preise aktualisieren, die Admin-Rolle auf ein anderes Wallet übertragen, Verkaufserlöse abheben, Verkäufe eröffnen und abschließen kann usw.
  3. Ein Tool, das überprüft, ob eine Person sowohl online als auch im IRL über ein bestimmtes Ticket verfügt.


Der Aufbau dieser Systeme von Grund auf ist nicht Teil dieses Tutorials, aber wir geben Ihnen ein paar Ressourcen und Tipps.

  1. Schauen Sie sich für die Frontend-Minting-Website das Frontend an, das ich im Thank You NFT- Tutorial als Ausgangspunkt erstellt habe.

  2. Wenn Sie Ihren Vertrag auf Etherscan verifizieren, erhalten Sie automatisch ein Admin-Portal, über das Sie jede Funktion Ihres Vertrags aufrufen können. Dies ist ein guter erster Schritt, bevor Sie sich für den Aufbau einer individuellen Lösung entscheiden.

  3. Mit der balanceOf Funktion können Sie ganz einfach überprüfen, ob ein Wallet ein Ticket aus Ihrer Sammlung enthält. Wenn jemand nachweisen kann, dass er eine Brieftasche mit einem unserer Tickets besitzt, ist das im Grunde ein Beweis dafür, dass er ein Ticket hat. Dies kann mithilfe digitaler Signaturen erreicht werden.


Verifizierung mit der Infura NFT API

Noch ein Hinweis: Sobald Sie Ihren Smart Contract und Ihr Frontend haben (oder sogar bevor Ihr Frontend fertig ist und Sie beweisen möchten, dass alles funktioniert), können Sie die Infura NFT API verwenden, um zu überprüfen, ob Ihr neues NFT existiert. Die Infura NFT API ist eine schnelle Möglichkeit, eine Menge NFT-bezogenen Code mit einem einzigen API-Aufruf zu ersetzen.


Beispielsweise stehen uns die Informationen, die wir zum Nachweis des Eigentums an unserem NFT benötigen, über die API problemlos zur Verfügung. Wir müssen lediglich die Wallet-Adresse angeben. Der Code würde etwa so aussehen:

 const walletAddress = <your wallet address> const chainId = "1" const baseUrl = "https://nft.api.infura.io" const url = `${baseUrl}/networks/${chainId}/accounts/${walletAddress}/assets/nfts` // API request const config = { method: 'get', url: url, auth: { username: '<-- INFURA_API_KEY –>', password: '<-- INFURA_API_SECRET –>', } }; // API Request axios(config) .then(response => { console.log(response['data']) }) .catch(error => console.log('error', error));


Starte es …

 $ node <filename>.js


Und Sie sollten etwa Folgendes sehen:

 { total: 1, pageNumber: 1, pageSize: 100, network: 'ETHEREUM', account: <account address>, cursor: null, assets: [ { contract: <NFT contract address>, tokenId: '0', supply: '1', type: 'ERC20', metadata: [Object] }, … ] }

Abschluss

In diesem Tutorial haben wir einen voll funktionsfähigen NFT-Ticketing-Service mit Truffle , Infura und der Infura NFT API bereitgestellt.


Es ist natürlich nicht alles , was Sie brauchen, um Ticketmaster zu revolutionieren – aber es ist ein solider Anfang und ein großartiger Proof of Concept! Auch wenn Sie diesen Code nicht verwenden und Ihre eigene NFT-Ticketing-Plattform starten, haben Sie dabei hoffentlich etwas über web3 gelernt.


Das Hauptbild für diesen Artikel wurde vomAI Image Generator von HackerNoon über die Eingabeaufforderung „ein Rockkonzert in einem großen Stadion“ generiert.