In this tutorial we will be creating a NFT contract on Stellar Soroban using the libraries from OpenZeppelin

To follow along you’ll need a couple of pieces of software:-
- Rust – https://rust-lang.org
- Stellar Cli – https://github.com/stellar/stellar-cli/
The full source code for this project is available on Github:
https://github.com/jamesbachini/OZ-Stellar-NFT
The code is based on the OpenZeppelin example for sequential minting which is available here: https://github.com/OpenZeppelin/stellar-contracts/tree/main/examples/nft-sequential-minting
There are however a couple of differences. In my version I want to set a maximum number of tokens that can ever be created.
We can see from the sequential_mint function in the library at the link below that it returns a u32 numerical token_id.
https://github.com/OpenZeppelin/stellar-contracts/blob/4f18e0cd0e1d49b2f27e30e8fa5206e95ea4c178/packages/tokens/non-fungible/src/storage.rs#L659
We can use this to throw a panic! error if someone tries to mint over the maximum mint threshold for our contract.
let token_id: TokenId = Base::sequential_mint(e, &to);
if token_id > 100 {
panic!("Maximum minted already");
}
I’m also editing the Metadata URI, Token Name and Ticker symbol in the constructor argument.
Base::set_metadata(
e,
String::from_str(e, "ipfs://bafkreigjf3tymofuq5vepmlijsglf65qprsiwykkkz6ipdgxv6fnxcje4e"),
String::from_str(e, "SoroKittens"),
String::from_str(e, "SKT"),
);
Before I do that I need to upload an image or images to IPFS and then create the metadata in JSON format.
For this I will use Pinata which is a useful IPFS management tool which has a generous free tier.

The metadata.json file includes an IPFS link to the image. Here is the full file:
{
"name": "SoroKittens",
"description": "Kittens on Stellar Soroban",
"url": "ipfs://bafybeie52o6v7t7p4ceeqmjipbub7hqo3xsdzcab3h3suiqt5pz7te6zeq",
"issuer": "GD6ERVU2XC35LUZQ57JKTRF6DMCNF2JI5TFL7COH5FSQ4TZ2IBA3H55C",
"code": "SKT"
}
Once we upload the metadata.json we will get an IFPS hash for that as well which we can use as the URI in the Soroban contract metadata.
Next let’s test, compile and build the contract.
cargo test
cargo build --target wasm32-unknown-unknown --release
stellar contract deploy --wasm target/wasm32-unknown-unknown/release/ozstellarnft.wasm --source james --network testnet

IF all goes well we should get a contract address which we can paste into Stellar Expert:

Congratulations, you just deployed your first NFT to Soroban ♥️
