Skip to main content

Modify

The following steps will guide you through a modification of the Kitty Items project. You will add a new NFT kind, representing an exclusive collection of rare NFTs of sunglasses:

sunglasses

Video Walkthrough

Start in emulator

In the last step, you started the project on the testnet. For local development, however, it is recommended to emulate the blockchain network locally using the Flow Emulator. Once changes are implemented and tested locally, you will deploy the updates to the testnet.

Let's start the project in the emulator by running the command below in the root project folder.

Important: You will notice that the previous script execution finished once all services successfully started. You do not need to stop the previous process. By running the next command, existing services will be configured to communicate with the emulator instead of the testnet.


_10
npm run dev:emulator

You should see similar logs as in the last step:


_29
✔ Emulator started
_29
ℹ Flow Emulator is running at: http://localhost:8080
_29
ℹ View log output: npx pm2 logs emulator
_29
_29
✔ Developer Wallet started
_29
ℹ FCL Dev Wallet running at: http://localhost:8701
_29
ℹ View log output: npx pm2 logs dev-wallet
_29
_29
✔ Contracts deployed
_29
ℹ Contracts were deployed to: 0xf8d6e0586b0a20c7 (emulator)
_29
_29
✔ Admin account initialized
_29
ℹ ./cadence/transactions/nftStorefront/setup_account.cdc was executed successfully.
_29
ℹ ./cadence/transactions/kittyItems/setup_account.cdc was executed successfully.
_29
_29
✔ API server started
_29
ℹ Kitty Items API is running at: http://localhost:3000
_29
ℹ View log output: npx pm2 logs api
_29
_29
✔ Storefront web app started
_29
ℹ Kitty Items Web App is running at: http://localhost:3001
_29
ℹ View log output: npx pm2 logs web
_29
_29
KITTY ITEMS HAS STARTED
_29
_29
_29
Visit: http://localhost:3001
_29
_29
? Would you like to view the logs for all processes? (Y/n)

Once again, you will be asked if you want to show all logs. You can enter n for now.

You may notice that you were not prompted for an account. This is because the local setup includes a developer wallet that simulates user accounts.

Add new NFT collection

To add the new NFT collection, we will have to make changes to several components of the project:

  • Backend API: Add the new collection to the list of available collections
  • Web application: Define the new collection name and add it to the map of available collections
  • Cadence: Define the new collection name, add it to the map of available collections, set the content hash for the images (stored on IPFS)

To start making your changes, it is recommended to open the project in a code editor like Visual Studio Code.

Recommended: Install the VSCode extension for Cadence to get syntax highlighting, type checking, and code completion support. If you have VSCode in your $PATH, you can use the CLI to install the extension: flow cadence install-vscode-extension.

Update the backend API

Open the file /api/src/services/kitty-items.ts and add new element (Shades) at the bottom of the Kind enum:

/api/src/services/kitty-items.ts

_10
enum Kind {
_10
Fishbowl = 0,
_10
Fishhat,
_10
Milkshake,
_10
TukTuk,
_10
Skateboard,
_10
Shades
_10
}

Update the web application

Open the file /web/src/global/constants.js and add a new item (Shades) to the ITEM_KIND_MAP constant:

/web/src/global/constants.js

_10
export const ITEM_KIND_MAP = {
_10
0: "Fishbowl",
_10
1: "Fish Hat",
_10
2: "Milkshake",
_10
3: "TukTuk",
_10
4: "Skateboard",
_10
5: "Shades",
_10
};

Note: To simplify this tutorial, we already added the images for the NFT collection to the project folder. If you were to add new NFTs on your own, you would also need to add images to the web/public/images/kitty-items folder.

Update the Cadence smart contract

Open the /cadence/contracts/KittyItems.cdc file and make the following changes.

Add a new kind

Locate the enum Kind object and add a new case (shades) to the bottom of the list:

/cadence/contracts/KittyItems.cdc

_10
pub enum Kind: UInt8 {
_10
pub case fishbowl
_10
pub case fishhat
_10
pub case milkshake
_10
pub case tuktuk
_10
pub case skateboard
_10
pub case shades
_10
}

Update the kindToString method

This method is used to set the name and description of a specified NFT. Locate the the kindToString method and add a new case (Kind.shades) to the bottom of the switch statement:

/cadence/contracts/KittyItems.cdc

_18
pub fun kindToString(_ kind: Kind): String {
_18
switch kind {
_18
case Kind.fishbowl:
_18
return "Fishbowl"
_18
case Kind.fishhat:
_18
return "Fish Hat"
_18
case Kind.milkshake:
_18
return "Milkshake"
_18
case Kind.tuktuk:
_18
return "Tuk-Tuk"
_18
case Kind.skateboard:
_18
return "Skateboard"
_18
case Kind.shades:
_18
return "Shades"
_18
}
_18
_18
return ""
_18
}

Create a transaction to update the list of images for your new kind

Next, you need to create a transaction to update the contract with new links to the images for the new NFT kind.

Note: You can't modify the list of images in the init() function directly because this function only runs the first time your contract is deployed - not on subsequent updates. You can read more about here.

In the root directory of the project, run the following commands to create a new file for the transaction:


_10
touch cadence/transactions/kittyItems/add_nft_images_for_new_kind.cdc

Navigate to the new file, open it, and paste the following code:

cadence/transactions/kittyItems/add_nft_images_for_new_kind.cdc

_33
import KittyItems from "../../contracts/KittyItems.cdc"
_33
_33
// This transction uses the NFTMinter resource to add new image URIs for a new Kind of KittyItems NFT.
_33
_33
transaction {
_33
_33
let minter: &KittyItems.NFTMinter
_33
_33
prepare(signer: AuthAccount) {
_33
_33
self.minter = signer.borrow<&KittyItems.NFTMinter>(from: KittyItems.MinterStoragePath)
_33
?? panic("Only authorized KittyItems NFT Minter can update KittyItems NFT...")
_33
_33
let NewImages: { KittyItems.Kind: {KittyItems.Rarity: String}} = {
_33
_33
// The image URIs are hardcoded here for demonstration,
_33
// but could also be passed in to the transaction as arguments.
_33
_33
KittyItems.Kind.shades: {
_33
KittyItems.Rarity.blue: "bafybeibtxvitlnvksnzwrwmsqdgnoznosknr3fx5jxjazjcerpa2qo4jy4",
_33
KittyItems.Rarity.green: "bafybeicp5bagsziwkyarey76m5jkr6i3a5yrgr7r435qyuutbtlqxcdbwu",
_33
KittyItems.Rarity.purple: "bafybeidjigkvt67dtuwrgrpdt2z4dojq2efpbw66ndnffkb6eyr4baml2i",
_33
KittyItems.Rarity.gold: "bafybeibtxvitlnvksnzwrwmsqdgnoznosknr3fx5jxjazjcerpa2qo4jy4"
_33
}
_33
}
_33
_33
self.minter.addNewImagesForKind(from: signer, newImages: NewImages);
_33
_33
}
_33
_33
// the FLOAT NFT secret code is: witty-kitty
_33
execute {}
_33
}

This transaction borrows the minter Resource from the signing account and calls the addNewImagesForKind method on the minter Resource. It passes a struct containing the links to the new images for the shades kind.

Note: If the signing account does not have the minter Resource, this transaction will fail. This is good, because we only want the account that mints NFTs to be able to modify the contract. Also keep in mind, that if you were to add your own NFT, you would have to upload images to IPFS and store the new hashes instead.

Make sure you saved the file before proceeding to the next step.

Update contract on the emulator

Because you changed the smart contract for Kitty Items, you have to redeploy it to the emulator. Run the following command in your terminal, inside the root folder.

Note: You will notice that the previous script execution finished once all services successfully started. You do not need to stop the previous process. You can run the next command in the same terminal without impact on the services running in the background.


_10
npm run update:emulator

The script will update all contracts included in the project. The last one is the one you changed.


_10
Deploying 4 contracts for accounts: emulator-account
_10
_10
NonFungibleToken -> 0xf8d6e0586b0a20c7 (3346...6218)
_10
NFTStorefront -> 0xf8d6e0586b0a20c7 (c0e6...662b)
_10
MetadataViews -> 0xf8d6e0586b0a20c7 (e6c2...ef11)
_10
KittyItems -> 0xf8d6e0586b0a20c7 (3612...dcdb)
_10
_10
✨ All contracts deployed successfully

Run the new transaction to update the KittyItems contract

Run the following command to send the transaction to update the contract with the new shades images.


_10
flow transactions send ./cadence/transactions/kittyItems/add_nft_images_for_new_kind.cdc -n emulator

You should see the following response. Take note of the Status - it should be ✅ SEALED.


_23
Transaction ID: af76f20581a3923375fd52428cef078670673295c9d786a8ac9e616661a7f88e
_23
_23
Status ✅ SEALED
_23
ID af76f20581a3923375fd52428cef078670673295c9d786a8ac9e616661a7f88e
_23
Payer f8d6e0586b0a20c7
_23
Authorizers [f8d6e0586b0a20c7]
_23
_23
Proposal Key:
_23
Address f8d6e0586b0a20c7
_23
Index 0
_23
Sequence 15
_23
_23
No Payload Signatures
_23
_23
Envelope Signature 0: f8d6e0586b0a20c7
_23
Signatures (minimized, use --include signatures)
_23
_23
Events:
_23
Index 0
_23
Type A.f8d6e0586b0a20c7.KittyItems.ImagesAddedForNewKind
_23
Tx ID af76f20581a3923375fd52428cef078670673295c9d786a8ac9e616661a7f88e
_23
Values
_23
- kind (UInt8): 5

As indicated, the transaction was sealed and you are ready to mint your new KittyItems NFT.

Congratulations! You have completed all changes and your project now includes a new NFT collection for sunglasses.

Mint new sunglasses NFT

To mint one of the new NFTs in your local environment, you have to repeat the minting steps from the last page.

First, open the Kitty Items admin dashboard. Keep in mind that the password is KittyItems.

admin-ui

Now, hit the "Mint Item" button and see a new NFT being generated. The generation of new NFTs is randomized, so you will have to mint a few new NFTs until you will see an NFT from your new sunglasses collection.

During the minting process, you should see the sunglasses flash in the preview pane on the left side of the screen.

Note: It is best to hit the back button in your browser to get back to the "Mint a New Item" screen. You can jump to this screen by opening the admin dashboard directly.