NFT Smart Contract erstellen und bereitstellen
In diesem Abschnitt erfahren Sie, wie Sie einen Smart Contract für NFT erstellen und bereitstellen, der zum Einrichten des NFT Marketplace erforderlich ist.
Mit Blockchain App Builder können Sie einen Smart Contract zum Verwalten von Minzen, Eigentümern und Transfer von NFTs erstellen. Der Kernfaktor dieser Lösung ist die Möglichkeit, NFTs mit Oracle Blockchain Platform zu mintieren und zu übertragen.
Zuerst erstellen Sie eine NFT-Spezifikationsdatei und stellen dann den Smart Contract in einer Oracle Blockchain Platform-Instanz bereit. Anschließend können Sie den Smart Contract testen.
Blockchain App Builder installieren
Nachdem Sie eine Oracle Blockchain Platform-Instanz bereitgestellt haben, führen Sie die folgenden Schritte aus:
- Öffnen Sie in der Oracle Blockchain Platform-Konsole die Registerkarte Entwicklertools, und wählen Sie dann den Bereich Blockchain App Builder aus.
- Laden Sie im Abschnitt Herunterladen das Befehlszeilenschnittstellenarchiv (CLI) oder die Visual Studio-(VS-)Codeerweiterung herunter, und richten Sie es dann lokal ein.
Anpassen der NFT-Beispielspezifikationsdatei
Eine NFT-Beispielspezifikationsdatei ist in Blockchain App Builder enthalten. Sie können es verwenden und an Ihre Bedürfnisse anpassen, wie im folgenden Beispiel dargestellt:
assets:
- name: ArtCollection
type: token
symbol: ART #mandatory
standard: erc721+
anatomy:
type: nonfungible
unit: whole
behavior:
- indivisible # mandatory
- singleton # mandatory
- mintable: # mandatory
max_min_quantity: 20000
- transferable
- burnable
- roles:
minter_role_name: minter
properties:
- name: price
type: number
- name: on_sale_flag
type: boolean
metadata:
- name: painting_name
type: string
- name: description
type: string
- name: image
type: string
- name: painter_name
type: string
customMethods:
- executeQuery
- "createAccountByConsumers(org_id: string, user_id: string, token_type: string)" # Create accounts for consumers while signing up
- "sell(token_id: string, selling_price: number)" # Post the token for selling in the marketplace
- "buyWithTokens(from_org_id: string, from_user_id: string, to_org_id: string, to_user_id: string, nonfungible_token_id: string, fungible_token_id: string, amount_paid: number)" # Buy the NFT after paying the using FT Tokens
- "buyWithDirectPayment(from_org_id: string, from_user_id: string, to_org_id: string, to_user_id: string, nonfungible_token_id: string, amount_paid: number)" # Buy the NFT after paying the amount using payment gateway
Sie können benutzerdefinierte Eigenschaften und Methoden hinzufügen, um diese Spezifikation für NFT-Chaincode zu erweitern. Von Blockchain App Builder generierte NFT-Chaincodes basieren auf dem Standard ERC-721
.
Führen Sie die folgenden Schritte aus, um den Chaincode (Smart Contract) mit der Visual Studio Code-Erweiterung zu generieren:
- Klicken Sie im Abschnitt Chaincodes auf das Symbol +. Der Bereich Chaincode-Details wird geöffnet.
- Füllen Sie die Felder aus, die zum Generieren des Chaincode-Projekts erforderlich sind:
- Geben Sie einen Namen für das Chaincode-Projekt ein.
- Wählen Sie
TypeScript
oderGo
als Sprache aus, in der die Chaincode-Methoden generiert werden sollen. - Wählen Sie die Eingabespezifikationsdatei aus, die Sie zuvor erstellt haben.
- Geben Sie den Standort ein, an dem das Projekt generiert werden soll.
- Klicken Sie auf Erstellen.
Im folgenden Screenshot der Benutzeroberfläche wird das Fenster Chaincode erstellen angezeigt.

Beschreibung der Abbildung Blockchain_chaincode_details.png
src
in der Projekthierarchie prüfen.
- Die Modelldatei enthält alle generierten Datenstrukturen, die das Token, Accounts usw. darstellen.
- Die Controllerdatei enthält alle generierten NFT-Lebenszyklusmethoden und unterstützenden Funktionen mit erforderlicher Validierungslogik basierend auf der Spezifikation.
/**
*
* BDB sql rich queries can be executed in OBP CS/EE.
* This method can be invoked only when connected to remote OBP CS/EE network.
*
*/
@Validator(yup.string())
public async executeQuery(query: string) {
const result = await this.query(query);
return result;
}
@Validator(yup.string(), yup.string(), yup.string())
public async createAccountByConsumers(org_id: string, user_id: string, token_type: string) {
//await this.Ctx.ERC721Auth.checkAuthorization('ERC721ACCOUNT.createAccount', 'TOKEN');
return await this.Ctx.ERC721Account.createAccount(org_id, user_id, token_type);
}
@Validator(yup.string(), yup.number())
public async sell (token_id: string, selling_price: number) {
try {
const token = await this.Ctx.ERC721Token.get(token_id);
const t = new ArtCollection(token)
t.price = selling_price;
t.on_sale_flag = true;
//console.log(token);
await this.Ctx.ERC721Token.update(t);
return `Token ID : '${token_id}' has been posted for selling in the marketplace'`;
} catch(error) {
throw new Error(error.message);
}
}
@Validator(yup.string(), yup.string(), yup.string(), yup.string(), yup.string(), yup.string(), yup.number())
public async buyWithTokens(from_org_id: string, from_user_id: string, to_org_id: string, to_user_id: string, nonfungible_token_id: string, fungible_token_id: string, amount_paid: number) {
try {
const token = await this.Ctx.ERC721Token.get(nonfungible_token_id);
const t = new ArtCollection(token);
const oChainUtil = new OChainUtils(this.Ctx.Stub);
var msg = `Token ID : '${nonfungible_token_id}' had not been transferred'`;
if (t.on_sale_flag==true) {
if(t.price == amount_paid) {
// @ts-ignore
await oChainUtil.invokeChaincode("LoyaltyToken7", "transferTokens", [fungible_token_id, from_org_id, from_user_id, amount_paid], "marketplace");
const from_account_id = await this.Ctx.ERC721Account.generateAccountId(from_org_id, from_user_id);
const to_account_id = await this.Ctx.ERC721Account.generateAccountId(to_org_id, to_user_id);
await this.Ctx.ERC721Token.transferFrom(from_account_id, to_account_id, t);
msg = `Token ID : '${nonfungible_token_id}' has been successfully transferred to UserID : '${to_user_id}'`;
}
}
else {
msg = `Token ID : '${nonfungible_token_id}' has not been transferred to UserID : '${to_user_id}' as the amount was not fully paid'`;
}
return msg;
} catch(error)
{
throw new Error(error.message);
}
}
@Validator(yup.string(), yup.string(), yup.string(), yup.string(), yup.string(), yup.number())
public async buyWithDirectPayment(from_org_id: string, from_user_id: string, to_org_id: string, to_user_id: string, nonfungible_token_id: string, amount_paid: number) {
try {
const token = await this.Ctx.ERC721Token.get(nonfungible_token_id);
const t = new ArtCollection(token);
var msg = `Token ID : '${nonfungible_token_id}' had not been transferred'`;
if (t.on_sale_flag==true) {
if(t.price == amount_paid) {
const from_account_id = await this.Ctx.ERC721Account.generateAccountId(from_org_id, from_user_id);
const to_account_id = await this.Ctx.ERC721Account.generateAccountId(to_org_id, to_user_id);
await this.Ctx.ERC721Token.transferFrom(from_account_id, to_account_id, t);
msg = `Token ID : '${nonfungible_token_id}' has been successfully transferred to UserID : '${to_user_id}'`;
}
}
else {
msg = `Token ID : '${nonfungible_token_id}' has not been transferred to UserID : '${to_user_id}' as the amount was not fully paid'`;
}
return msg;
} catch(error) {
throw new Error(error.message);
}
}
}
Smart Contract bereitstellen
Nachdem Sie ein Chaincode-Projekt erstellt haben, können Sie es lokal bereitstellen.
Wählen Sie im Bereich Chaincode-Details die Option Bereitstellen, um den Deployment-Assistenten zu öffnen. Blockchain App Builder umfasst ein lokales Blockchain-Netzwerk, das in den Docker-Containern ausgeführt wird, das Sie zu Testzwecken verwenden können.
Sie können den Chaincode auch in einer Oracle Blockchain Platform-Instanz bereitstellen, indem Sie das Verbindungsprofil aus der Liste für die Zielumgebung auswählen. Sie müssen auch die Init-Parameter abschließen und speichern, da der generierte NFT-Chaincode die Parameter orgId
und userId
zur Initialisierung erfordert. Mit den Parametern orgId
und userId
wird angegeben, welche Benutzer über Tokenadministratorberechtigungen verfügen.
Smart Contract testen
Beim Deployment des Chaincodes stellt Oracle Blockchain Platform automatisch die REST-APIs für Tokeninitialisierung, Account- und Rollenverwaltung und NFT-Lebenszyklusmethoden (Erstellen, Transfer, Brennen) bereit.
Sie können den Test durchführen, indem Sie im Bereich Chaincode-Details in Blockchain App Builder die Option Ausführen auswählen oder einen REST-API-Client wie Postman verwenden.
Der folgende Screenshot der Benutzeroberfläche zeigt die Registerkarte Ausführen des Fensters Kettencode erstellen.

Beschreibung der Abbildung Blockchain_chaincode_execute.png
Um Oracle Blockchain Platform-Smart Contract-Methoden mit REST-API aufzurufen, verwenden Sie die Methode POST
, und geben Sie die URL an, die aus zwei Teilen besteht, die zusammen verkettet sind. Der erste Teil ist der REST-Proxyendpunkt in Oracle Blockchain Platform, den Sie über die Registerkarte Knoten der Oracle Blockchain Platform-Konsole abrufen können.
Der zweite Teil ist die spezifische URI, mit der die Transaktion mit der Transaction-API aufgerufen wird. Informationen zum Senden einer POST
-Anforderung finden Sie in der Dokumentation. Die beiden Teile bilden eine vollständige URL ähnlich der hier.
https://oabcs1-iad.blockchain.ocp.oraclecloud.com:7443/restproxy/api/v2/channels/{channelName}/transactions
Ersetzen Sie {channelName}
durch den Namen des Kanals, den Sie beim Deployment Ihres Chaincodes angegeben haben, wie marketplace. Führen Sie beim Erstellen der API-Anforderung die folgenden Schritte aus:
- Legen Sie die Autorisierung so fest, dass
Basic Auth
mit der angegebenenuserid and password
verwendet wird, die der RolleREST_Client
zugeordnet ist. Sie können auchOAuth2
-Token verwenden. Weitere Informationen finden Sie unter Zugriffstokenbasierte Authentifizierung für OAuth 2.0 verwenden in der REST-API-Dokumentation. - Setzen Sie den
Content-Type
-Header aufapplication/json
. - Nehmen Sie im Body der Anforderung die für den Transaktionsaufruf erforderlichen Parameter auf, einschließlich des Chaincode-Namens und der Methode
create<TokenName>Token
sowie die erforderlichen Argumente.
Basierend auf dem aus der Vorlage yaml
generierten Chaincode zeigt der folgende Text einen Musteranforderungsbody und die zugehörige Antwort an.
Anforderung
{
"chaincode": "{{NFTChaincode}}",
"args": [
"createArtCollectionToken",
"{\"token_id\":\"{{NFTTokenID}}\",\"token_uri\":\"https://ipfs.io/ipfs/QmV68aiT7xw2WX8pmDbeTWpGP2or35NUFan9RagymsLpgV?filename=ArtCollection_NFT1.json\",\"metadata\":{\"painting_name\":\"Oracle - Red Bull Partnership\",\"image\":\"https://ipfs.io/ipfs/QmVap6Gkh3Cp9DiLLWvkvJHpuXpFmYB2GzU1caM57gNcAa?filename=Oracle_RedBull_NFT1.jpeg\",\"painter\":\"Alex\"},\"price\":200,\"on_sale_flag\":false}"
],
"timeout": 0,
"sync": true
}
Antwort
{
"returnCode": "Success",
"error": "",
"result": {
"txid": "c999922f04c3011bf25ca43624e4bb23e8900634f8e23a1648170a90274a9733",
"payload": {
"metadata": {
"painter": "Alex",
"painting_name": "Oracle - Red Bull Partnership",
"image": "https://ipfs.io/ipfs/QmVap6Gkh3Cp9DiLLWvkvJHpuXpFmYB2GzU1caM57gNcAa?filename=Oracle_RedBull_NFT1.jpeg"
},
"assetType": "otoken",
"created_by": "oaccount~eadf1b0ae857164f8681d1742b6328089a7d33ebec76d8248cb909da7a84f42a",
"creation_date": "2022-04-28T12:08:38.000Z",
"owner": "oaccount~eadf1b0ae857164f8681d1742b6328089a7d33ebec76d8248cb909da7a84f42a",
"uri": "https://ipfs.io/ipfs/QmV68aiT7xw2WX8pmDbeTWpGP2or35NUFan9RagymsLpgV?filename=ArtCollection_NFT1.json",
"is_burned": false,
"token_id": "NFT17",
"token_name": "artcollection",
"symbol": "ART",
"token_standard": "erc721+",
"token_type": "nonfungible",
"token_unit": "whole",
"behaviors": [
"indivisible",
"singleton",
"mintable",
"transferable",
"burnable",
"roles"
],
"roles": {
"minter_role_name": "minter"
},
"mintable": {
"max_mint_quantity": 20000
},
"token_uri": "https://ipfs.io/ipfs/QmV68aiT7xw2WX8pmDbeTWpGP2or35NUFan9RagymsLpgV?filename=ArtCollection_NFT1.json",
"price": 200,
"on_sale_flag": false
},
Weitere Informationen zu den Methoden zur Verwaltung von NFT-Chaincodes finden Sie im Abschnitt Weitere Informationen anzeigen, einschließlich der Methoden Golang
oder TypeScript
und Platform REST API
.
Sie können die APIs direkt aus dem Oracle Content Management-Webhook und der auf Visual Builder Cloud Service (VBCS) erstellten Webanwendung aufrufen oder sie erneut mit dem API-Gateway zur Verwendung durch eine extern gehostete Marketplace-Webanwendung mappen und umschließen. Beachten Sie, dass Sie beim Erstellen (Mint) eines NFT einen der Parameter token_uri
angeben müssen. Dabei kann es sich um eine IPFS URI
handeln, die auf eine JSON
-Datei verweist, die das digitale Objekt darstellt.
https://ipfs.io/ipfs/QmV68aiT7xw2WX8pmDbeTWpGP2or35NUFan9RagymsLpgV?filename=ArtCollection_NFT1.json
In den folgenden Schritten wird ein Beispiel zum Generieren der Token-URI mit IPFS-Desktop beschrieben:
- Laden Sie eine Bilddatei auf
IPFS
hoch, und speichern Sie die URI des Images. - Erstellen und laden Sie die Datei
JSON
hoch, die die Image-URI zusammen mit relevanten Metadatenfeldern enthält. - Teilen und kopieren Sie den Link in die Datei
JSON
unter ... Liste "Mehr".
{
"painting_name": "Oracle - Red Bull Partnership",
"description": "Cloud Partnership",
"image": "https://ipfs.io/ipfs/QmVap6Gkh3Cp9DiLLWvkvJHpuXpFmYB2GzU1caM57gNcAa?filename=Oracle_RedBull.jpeg",
"painter_name": "Alex"
}
Verwenden Sie die URI, die auf die Datei JSON
für den Parameter token_uri
verweist.
Sie können auch relevante Metadaten in die Attribute aufnehmen, die an die Methode create<Token-Name>Token
übergeben werden. Dadurch werden die Metadaten im Oracle Blockchain Platform-Ledger für einen einfachen Abruf verwaltet.
Verwenden Sie für NFTs, die mit Oracle Content Management (OCM) erstellt wurden, den OCM-Webhook, um Oracle Functions mit einem API-Gateway aufzurufen und den REST-API-Aufruf wie im Architekturdiagramm dargestellt in Oracle Functions zu platzieren. Sie können Blockchain-REST-APIs auch direkt von der Marketplace-Webanwendung aus oder über eine API-Gatewayzuordnung aufrufen, um vom Benutzer generierte Inhalte zu unterstützen. Die Funktion des Marketplace-Handels kann die benutzerdefinierten Methoden zur Verarbeitung der Zahlung aufrufen und dann eine Übertragung des NFT-Eigentums auslösen, wie die Beispielmethoden buyWithTokens
und buyWithDirectPayment
.