Eigenes NFT erstellen mit Truffle auf Klaytn

Tech at Klaytn
8 min readApr 28, 2021

--

Hier ist die komplette Liste aller Artikel.
Dieser Post ist auch verfügbar auf Englisch.

Hallo, liebe deutschsprachige Leserinnen und Leser! 🇩🇪🇦🇹🇱🇮🇨🇭🇧🇪

In diesem Beitrag zeigen wir Dir, wie Du mit Truffle auf der Klaytn-Blockchain Dein eigenes NFT erstellen kannst.

1. Klaytn?

Was ist Klaytn? Klaytn ist eine Blockchain-Platform, die von GroundX entwickelt wurde. GroundX ist eine Tochtergesellschaft von dem südkoreanischen Tech-Riese Kakao Corps. Mehr dazu findest Du auf Klaytn,com, Klaytn Docs und im Positionspapier information.

2. NFT?

NFT steht für Non-Fungible Token, also „nicht austauschbare Token“ auf Deutsch. NFTs nahmen ihren Anfang mit Ethereums ERC-721, wobei jedem Token einen einzigartigen Wert zugewiesen bekommt. Zum Beispiel könnten Sammelkarten mit Sportlern und Promis, oder ein Pokémon in ein solches Token verwandelt werden. Die auf Klaytn-basierten NFTs entsprechen dem KIP-17 Standard. Weitere Details finden sich hier: KIPs.

3. NFT-Contract bereitstellen? Ein Token senden?

Zu Beginn eine kleine technische Einführung in die NFTs. Wenn Du NFTs erstellen willst, muss im Voraus ein Smart-Contract im Klaytn-Netzwerk eingesetzt sein. Ein NFT-Smart-Contract ist, ganz einfach gesagt, eine Art ein Speicher, in dem NFTs gespeichert werden. Wenn Du einen solchen Speicher erstellt hast, kannst Du darin neue NFTs erstellen. Unten findest Du eine kurze Zusammenfassung der Begriffe:

  • NFT: Non-Fungible Token (nicht austauschbare Token)
  • NFT-Contract: Eine Art Speicher, in dem Du NFTs speichern kannst
  • NFT erstellen: ein neues NFT über einen NFT-Contract zu erstellen
  • NFT senden: jemandem ein bereits erstelltes NFT zu schicken
  • NFT verbrennen: ein bereits erstelltes NFT zu löschen

Jetzt hast Du eine Vorstellung davon, was Klaytn und NFTs sind. Aber in diesem Artikel beschäftigen wir uns nicht mit NFTs, sondern damit, wie man auf dem Klaytn-Blockchain NFTs erstellen kann. Wenn Du Dich jedoch für die näheren Einzelheiten des Themas NFT interessieren, gibt es viele Ressourcen auf dem Internet, die Dir helfen können.

4. NFT-Contract deployen

Du kannst einen Smart-Contract nach dem KIP-17-Standard selbst zusammenstellen und im Klaytn-Netzwerk deployen. Aber in diesem Artikel werden wir einen Beispielcode verwenden, den Du in diesem Link finden kannst.

4.1. Entwicklungsumgebung einrichten

Zum einfachsten Weg, einen NFT-Contract einzusetzen, verweisen wir auf klaytn-contracts, welches ein Git-Repository ist. In diesem Artikel, werden wir allerdings die Node API von KAS verwenden, um den KIP-17-Contract zu deployen. KAS ist der API-Service, der von GroundX angeboten wird, der eine entwicklerfreundliche Anwendung von verschiedenen KAS-Funktionalitäten ermöglicht. Du kannst täglich bis zu 10,000 APIs kostenlos aufrufen; also einfach anmelden und mal ausprobieren!

4.2. Truffle installieren

Truffle kannst Du herunterladen, indem Du den folgenden Befehl ausführst:

$ npm install -g truffle@v5.1.61

4.3. Code für klaytn-contract clonen

Mit dem folgenden Befehl kannst Du das klaytn-contract-Repository auf Ihren PC clonen:

$ git clone https://github.com/klaytn/klaytn-contracts.git

4.4. truffle-config.js updaten

Dann fügst Du den AccessKey (Zugriffsschlüssel) sowie den secretAccessKey (gemeinen Zugriffsschlüssel) von KAS dem unteren Code hinzu. Mehr zu AccessKey und secretAccessKey findest Du in KAS Docs.

// klaytn-contracts/truffle-config.js:29
const accessKeyId = "ACCESS_KEY";
const secretAccessKey = "SECRET_KEY";

4.5. Paketabhängigkeiten installieren

Installierst Du die notwendigen Pakete mit npm install

klaytn-contracts$ npm install

4.6. migrations/2_contract_migration.js updaten

Den Contract, den Du mit Truffle bereitstellen willst, kannst Du dich mit 2_contract_migration.js wählen. Ändere das File wie im Folgenden dargestellt:

// migrations/2_contract_migration.js
var kip17 = artifacts.require(‘KIP17Token’);
module.exports = function(deployer) {
deployer.deploy(kip17, “Test NFT”, “TN”)
};

4.7. Im Testnetzwerk Baobab bereitstellen

Baobab ist das Testnetzwerk von Klaytn. Du kannst durch Baobab Faucet das Spielgeld, also Test-KLAY, kostenlos erhalten. Erstelle ein Konto für KlaytnWallet und bekomme Test-KLAY verschenkt. Dann füge den privateKey in truffle-config.js hinzu.

// klaytn-contracts/truffle-config.js:40
const privateKey = “0x123 …”;

Wenn Duden accessKey, secretKey und den privateKey in truffle-config.js eingefügt haben, ist der Contract nun bereit zum Einsatz! Führe einfach den unteren Befehl aus. Unten haben wir die gesamte Protokolldatei eingefügt; Du kannst anhand dessen vergleichen, ob Dein Contract korrekt eingesetzt wurde.

klaytn-contracts$ truffle deploy --network kasBaobabCompiling your contracts…
===========================
> Compiling ./contracts/GSN/Context.sol
> Compiling ./contracts/Migrations.sol
> Compiling ./contracts/access/Roles.sol
> Compiling ./contracts/access/roles/MinterRole.sol
> Compiling ./contracts/access/roles/PauserRole.sol
> Compiling ./contracts/drafts/Counters.sol
> Compiling ./contracts/introspection/IKIP13.sol
> Compiling ./contracts/introspection/KIP13.sol
> Compiling ./contracts/introspection/KIP13Checker.sol
> Compiling ./contracts/lifecycle/Pausable.sol
> Compiling ./contracts/math/SafeMath.sol
> Compiling ./contracts/mocks/ERC1155ReceiverMock.sol
> Compiling ./contracts/mocks/ERC721ReceiverMock.sol
> Compiling ./contracts/mocks/KIP13/KIP13InterfacesSupported.sol
> Compiling ./contracts/mocks/KIP13/KIP13NotSupported.sol
> Compiling ./contracts/mocks/KIP13CheckerMock.sol
> Compiling ./contracts/mocks/KIP13Mock.sol
> Compiling ./contracts/mocks/KIP17FullMock.sol
> Compiling ./contracts/mocks/KIP17MintableBurnableImpl.sol
> Compiling ./contracts/mocks/KIP17Mock.sol
> Compiling ./contracts/mocks/KIP17PausableMock.sol
> Compiling ./contracts/mocks/KIP17ReceiverMock.sol
> Compiling ./contracts/mocks/KIP37BurnableMock.sol
> Compiling ./contracts/mocks/KIP37Mock.sol
> Compiling ./contracts/mocks/KIP37PausableMock.sol
> Compiling ./contracts/mocks/KIP37ReceiverMock.sol
> Compiling ./contracts/mocks/KIP7BurnableMock.sol
> Compiling ./contracts/mocks/KIP7MetadataMock.sol
> Compiling ./contracts/mocks/KIP7MintableMock.sol
> Compiling ./contracts/mocks/KIP7Mock.sol
> Compiling ./contracts/mocks/KIP7PausableMock.sol
> Compiling ./contracts/mocks/MinterRoleMock.sol
> Compiling ./contracts/mocks/PauserRoleMock.sol
> Compiling ./contracts/token/KIP17/IERC721Receiver.sol
> Compiling ./contracts/token/KIP17/IKIP17.sol
> Compiling ./contracts/token/KIP17/IKIP17Enumerable.sol
> Compiling ./contracts/token/KIP17/IKIP17Full.sol
> Compiling ./contracts/token/KIP17/IKIP17Metadata.sol
> Compiling ./contracts/token/KIP17/IKIP17Receiver.sol
> Compiling ./contracts/token/KIP17/KIP17.sol
> Compiling ./contracts/token/KIP17/KIP17Burnable.sol
> Compiling ./contracts/token/KIP17/KIP17Enumerable.sol
> Compiling ./contracts/token/KIP17/KIP17Full.sol
> Compiling ./contracts/token/KIP17/KIP17Metadata.sol
> Compiling ./contracts/token/KIP17/KIP17MetadataMintable.sol
> Compiling ./contracts/token/KIP17/KIP17Mintable.sol
> Compiling ./contracts/token/KIP17/KIP17Pausable.sol
> Compiling ./contracts/token/KIP17/KIP17Token.sol
> Compiling ./contracts/token/KIP37/IERC1155Receiver.sol
> Compiling ./contracts/token/KIP37/IKIP37.sol
> Compiling ./contracts/token/KIP37/IKIP37MetadataURI.sol
> Compiling ./contracts/token/KIP37/IKIP37Receiver.sol
> Compiling ./contracts/token/KIP37/KIP37.sol
> Compiling ./contracts/token/KIP37/KIP37Burnable.sol
> Compiling ./contracts/token/KIP37/KIP37Holder.sol
> Compiling ./contracts/token/KIP37/KIP37Mintable.sol
> Compiling ./contracts/token/KIP37/KIP37Pausable.sol
> Compiling ./contracts/token/KIP37/KIP37Receiver.sol
> Compiling ./contracts/token/KIP37/KIP37Token.sol
> Compiling ./contracts/token/KIP7/IKIP7.sol
> Compiling ./contracts/token/KIP7/IKIP7Receiver.sol
> Compiling ./contracts/token/KIP7/KIP7.sol
> Compiling ./contracts/token/KIP7/KIP7Burnable.sol
> Compiling ./contracts/token/KIP7/KIP7Metadata.sol
> Compiling ./contracts/token/KIP7/KIP7Mintable.sol
> Compiling ./contracts/token/KIP7/KIP7Pausable.sol
> Compiling ./contracts/token/KIP7/KIP7Token.sol
> Compiling ./contracts/utils/Address.sol
> Compilation warnings encountered:
/Users/kjhman21/Sources/github.com/klaytn/klaytn-contracts/contracts/token/KIP37/KIP37Pausable.sol:79:9: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
address operator,
^ — — — — — — — ^
,/Users/kjhman21/Sources/github.com/klaytn/klaytn-contracts/contracts/token/KIP37/KIP37Pausable.sol:80:9: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
address from,
^ — — — — — ^
,/Users/kjhman21/Sources/github.com/klaytn/klaytn-contracts/contracts/token/KIP37/KIP37Pausable.sol:81:9: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
address to,
^ — — — — ^
,/Users/kjhman21/Sources/github.com/klaytn/klaytn-contracts/contracts/token/KIP37/KIP37Pausable.sol:83:9: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
uint256[] memory amounts,
^ — — — — — — — — — — — ^
,/Users/kjhman21/Sources/github.com/klaytn/klaytn-contracts/contracts/token/KIP37/KIP37Pausable.sol:84:9: Warning: Unused function parameter. Remove or comment out the variable name to silence this warning.
bytes memory data
^ — — — — — — — -^
> Artifacts written to /Users/kjhman21/Sources/github.com/klaytn/klaytn-contracts/build/contracts
> Compiled successfully using:
- solc: 0.5.6+commit.b259423e.Emscripten.clang
Starting migrations…
======================
> Network name: ‘kasBaobab’
> Network id: 1001
> Block gas limit: 0 (0x0)
1_initial_migration.js
======================
Deploying ‘Migrations’
— — — — — — — — — — —
> transaction hash: 0xb1c4474dd0819f0a92c7a2510acb76c45b704d56b536230ea9809be33a4b2602
> Blocks: 0 Seconds: 0
> contract address: 0x69E2622287EaBDF8FeDC6D1465626A55e9744777
> block number: 54229441
> block timestamp: 1615785044
> account: 0xEB5cCFa5C1750a2d075Df8F7a0f34490d4930b8b
> balance: 78.856641625
> gas used: 140894 (0x2265e)
> gas price: 25 gwei
> value sent: 0 ETH
> total cost: 0.00352235 ETH
> Saving migration to chain.
> Saving artifacts
— — — — — — — — — — — — — — — — — — -
> Total cost: 0.00352235 ETH
2_contract_migration.js
=======================
Deploying ‘KIP17Token’— — — — — — — — — — —> transaction hash: 0x55d5f332e7eb86e12d9688acb53fab8fe4c62c4e86eda7ea5ee46f6580b864d9
> Blocks: 0 Seconds: 0
> contract address: 0xc609eB0eE11D4246AC6d0c070c0D2374B53d7BA8
> block number: 54229446
> block timestamp: 1615785049
> account: 0xEB5cCFa5C1750a2d075Df8F7a0f34490d4930b8b
> balance: 78.780642175
> gas used: 2998052 (0x2dbf24)
> gas price: 25 gwei
> value sent: 0 ETH
> total cost: 0.0749513 ETH
> Saving migration to chain.
> Saving artifacts
— — — — — — — — — — — — — — — — — — -
> Total cost: 0.0749513 ETH
Summary
=======
> Total deployments: 2
> Final cost: 0.07847365 ETH

Wenn Du die “Summary” siehst wie oben, bedeutet das, dass Dein Contract erfolgreich deployt wurde. Wichtig ist, dass Du dich die Adresse gut merkst! In diesem Tutorial lautet die Adresse zum Beispiel `0xc609eB0eE11D4246AC6d0c070c0D2374B53d7BA8`. Dies ist die Adresse, wo sich Dein NFT-Contract nun befindet.

4.8. Deployen im Hauptnetzwerk Cypress

Nun um den Contract im Cypress-Netzwerk bereitzustellen, bedarf es einer Klaytn-Wallet, die mindestens einen Kontostand von über 0.07847365 KLAY besitzt, welches übrigens die Summe ist, die im oberen Beispiel für die Transaktion ausgegeben wurde. Du kannst anKLAY an einer Kryptobörse oder mit einer Wallet-Applikation, die den Kauf von KLAY unterstützt, gelangen.

Gib deinen privateKey für den Account ein im Parameter private key von truffle-config.js, der KLAY beinhaltet, und dann führe es aus!

klaytn-contracts$ truffle deploy -- network kasCypress

Wenn Du einen Teil des Contracts etwas ändern möchtest bevor Deployment, darfst Du auch gerne auf klaytn-contracts/contracts/token/KIP17.

4.9. Tokens erstellen, senden und verbrennen mit caver

Zwar eignet sich Truffle sehr gut zum Deployment, aber es ist ein bisschen zu umständlich, um einen Smart Contract auszuführen. Wir werden anhand “caver” demonstrieren, wie man mit Tokens umgeht.

4.9.1. Tokens erstellen, senden und verbrennen mit caver-js-ext-kas

Du kannst sehr einfach Tokens erstellen, senden und verbrennen, indem Du caver-js-ext-kas verwendest. Probiere es selbst mal aus mit dem Beispielcode:

const CaverExtKAS = require('caver-js-ext-kas')// Configuration Part
// Set your KAS access key and secretAccessKey.
const accessKeyId = '{your_accessKeyId}'
const secretAccessKey = '{your_secretAccessKey}'
// const CHAIN_ID_BAOBOB = '1001'
// const CHAIN_ID_CYPRESS = '8217'
const chainId = '1001'
const contractAddress = '{contractAddress}'const caver = new CaverExtKAS(chainId, accessKeyId, secretAccessKey)test()async function test () {
const privateKey = '0x{private key}'
// Create a KeyringContainer instance
const keyringContainer = new caver.keyringContainer()
// Add keyring to in-memory wallet
const keyring = keyringContainer.keyring.createFromPrivateKey(privateKey)
keyringContainer.add(keyring)
// Create a KIP17 instance
const kip17 = new caver.kct.kip17(contractAddress)

// Call `kip17.setWallet(keyringContainer)` to use KeyringContainer instead of KAS Wallet API
kip17.setWallet(keyringContainer)
const tokenId = '1'
const uri = 'http://test.url'
const mintReceipt = await kip17.mintWithTokenURI(keyring.address, tokenId, uri, { from:keyring.address })
console.log(`mint receipt: `)
console.log(mintReceipt)
const transferReceipt = await kip17.transferFrom(keyring.address, keyring.address, tokenId, { from:keyring.address })
console.log(`transfer receipt: `)
console.log(transferReceipt)
const burnReceipt = await kip17.burn(tokenId, { from:keyring.address })
console.log(`burn receipt: `)
console.log(burnReceipt)
}

4.9.2. Tokens erstellen, senden und verbrennen mit caver-java-ext-kas

Du kannst sehr einfach Tokens erstellen, senden und verbrennen, indem Du caver-java-ext-kas verwendest. Probiere es selbstmal aus mit dem Beispielcode:

package com.klaytn.caver.boilerplate;import com.klaytn.caver.Caver;import com.klaytn.caver.account.Account;
import com.klaytn.caver.contract.SendOptions;
import com.klaytn.caver.kct.kip17.KIP17;
import com.klaytn.caver.kct.kip7.KIP7;
import com.klaytn.caver.methods.response.AccountKey;
import com.klaytn.caver.methods.response.Bytes32;
import com.klaytn.caver.methods.response.TransactionReceipt;
import com.klaytn.caver.transaction.response.PollingTransactionReceiptProcessor;
import com.klaytn.caver.transaction.response.TransactionReceiptProcessor;
import com.klaytn.caver.transaction.type.AccountUpdate;
import com.klaytn.caver.transaction.type.ValueTransfer;
import com.klaytn.caver.wallet.keyring.KeyringFactory;
import com.klaytn.caver.wallet.keyring.SingleKeyring;
import okhttp3.Credentials;
import org.web3j.protocol.exceptions.TransactionException;
import org.web3j.protocol.http.HttpService;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
public class BoilerPlate {
private static final String URL_NODE_API = "https://node-api.klaytnapi.com/v1/klaytn";
// Configuration Part
// Set your KAS access key and secretAccessKey.
static String accessKey = "{your_accessKeyId}";
static String secretAccessKey = "{your_secretAccessKey}";
// static String CHAIN_ID_BAOBOB = "1001";
// static String CHAIN_ID_CYPRESS = "8217";
static String chainId = "1001";
static String contractAddress = "{contractAddress}";
public static void main(String[] args) {
// Build a Caver instance.
Caver caver = setCaver(accessKey, secretAccessKey, chainId);
// Run a test.
test(caver);
}
public static void test(Caver caver) {
String testPrivateKey = "0x{private key}";
SingleKeyring deployerKeyring = KeyringFactory.createFromPrivateKey(testPrivateKey);
caver.wallet.add(deployerKeyring);
try {
// Create a KIP17 instance
KIP17 kip17 = new KIP17(caver, contractAddress);
//Mint a NFT token
BigInteger tokenId = BigInteger.ONE;
String uri = "http://test.url";
TransactionReceipt.TransactionReceiptData mintReceiptData = kip17.mintWithTokenURI(deployerKeyring.getAddress(), tokenId, uri, new SendOptions(deployerKeyring.getAddress()));
System.out.println("NFT mint transaction hash : " + mintReceiptData.getTransactionHash());
//Transfer a NFT token
TransactionReceipt.TransactionReceiptData transferReceiptData = kip17.transferFrom(deployerKeyring.getAddress(), deployerKeyring.getAddress(), tokenId, new SendOptions(deployerKeyring.getAddress()));
System.out.println("NFT transfer transaction hash : " + transferReceiptData.getTransactionHash());
//Burn a NFT token
TransactionReceipt.TransactionReceiptData burnReceiptData = kip17.burn(tokenId, new SendOptions(deployerKeyring.getAddress()));
System.out.println("NFT burn transaction hash : " + burnReceiptData.getTransactionHash());
} catch (NoSuchMethodException | IOException | InstantiationException | ClassNotFoundException | IllegalAccessException | InvocationTargetException | TransactionException e) {
e.printStackTrace();
}
}

private static Caver setCaver(String accessKey, String secretAccessKey, String chainID) {
HttpService httpService = new HttpService(URL_NODE_API);
httpService.addHeader("Authorization", Credentials.basic(accessKey, secretAccessKey));
httpService.addHeader("x-chain-id", chainID);
return new Caver(httpService);
}
}

In diesem Artikel haben wir Dir gezeigt, wie man mit Truffle auf der Klaytn-Blockchain einen KIP-17-Contract deployen kann. Probiere es mal selbst, Dein eigenes NFT zu erstellen und Deinen Freunden zu schicken, mit der schnellen und benutzerfreundlichen Blockchain Klaytn.

Bei Fragen, schreibe sie gerne in die Kommentare oder in unserem Developers Forum. Da kannst Du auch ruhig auf Deutsch schreiben. 😉

--

--

Tech at Klaytn
Tech at Klaytn

No responses yet