Part 3: Sending transactions
To send a transaction to Tezos, a dApp creates the transaction, including its parameters. Then it sends the transaction to the user's wallet application. With the user's approval, the wallet encrypts ("signs") the transaction with the user's private key and sends it to Tezos.
In this section, you add functions to the application that send a transaction that creates ("mints") an NFT on Tezos. The transaction calls a pre-deployed smart contract that manages NFTs. In a later section, you will deploy your own contract to manage your NFTs, but for now you can use the pre-deployed contract to learn about how it works.
The pre-deployed contract
You can see the pre-deployed contract by looking up its address KT1SRdvmiXjQxtY78sefFY2qrCHNpNttWZXq
on a block explorer such as these:
- https://ghostnet.tzkt.io/KT1SRdvmiXjQxtY78sefFY2qrCHNpNttWZXq
- https://better-call.dev/ghostnet/KT1SRdvmiXjQxtY78sefFY2qrCHNpNttWZXq
The block explorer shows the transactions that the contract has received and information about the tokens that it manages. Usually the block explorer has a Tokens tab for contracts that manage tokens. For example, Better Call Dev shows the tokens like this:
Most tokens have metadata that describes what the token represents. For example, the first token on the pre-deployed contract has this metadata:
Normally, contracts that manage tokens have restrictions on who can mint tokens, but for the purposes of the tutorial, this contract allows any account to mint NFTs.
Minting NFTs
To call a smart contract, you need the address of the contract, the name of the entrypoint to call, and a properly formatted parameter.
-
In the
App.svelte
file, in the<script>
section, add a constant with the address of the pre-deployed contract:const nftContractAddress = "KT1Lr8m7HgfY5UF6nXDDcXDxDgEmKyMeds1b";
-
Add a constant with a pre-deployed image. The application will use this image to represent the NFT in wallet applications.
const defaultImage = "https://gateway.pinata.cloud/ipfs/QmRCp4Qc8afPrEqtM1YdRvNagWCsFGXHgGjbBYrmNsBkcE";
-
Add a function that creates an NFT, first checking if the button is active because the wallet is connected:
if (!buttonActive) {
return;
}
buttonActive = false;
statusMessage = "Minting NFT; please wait..."; -
Inside the function, create the metadata for the token:
// Create token metadata
const metadata = new MichelsonMap();
metadata.set("name", stringToBytes("My Token"));
metadata.set("symbol", stringToBytes("Tok"));
metadata.set("decimals", stringToBytes("0"));
metadata.set("artifactUri", stringToBytes(defaultImage));
metadata.set("displayUri", stringToBytes(defaultImage));
metadata.set("thumbnailUri", stringToBytes(defaultImage));These are the metadata fields that the pre-deployed contract expects for new tokens. When you create your own contract you can define the fields, but these fields are commonly used for Tezos FA2 tokens, including NFTs.
Note that the value of the
decimals
field is set to zero because the token cannot be divided like a fungible token can.Also note that each field is converted from a string to bytes because token metadata is stored as a key-value map with string keys and byte values.
-
Create the parameter for the transaction:
const mintItem = {
to_: address,
metadata: metadata,
};
const mintParameter = [mintItem];There is no standard way that FA2 contracts mint tokens; in fact, FA2 contracts are not required to have a
mint
entrypoint. In this case, the mint entrypoint accepts a list of tokens to create, with each list item including the address of the token owner and the metadata for the new token. You can set up your contract to mint tokens in any way. -
Within a
try/catch
block, create an object that represents the contract and call itsmint
entrypoint by adding this code:try {
Tezos.setWalletProvider(wallet);
console.log("getting contract");
const nftContract = await Tezos.wallet.at(nftContractAddress);
console.log("minting");
const op = await nftContract.methodsObject.mint(mintParameter).send();
console.log(`Waiting for ${op.opHash} to be confirmed...`);
const hash = await op.confirmation(2).then(() => op.opHash);
console.log(`Operation injected: https://ghostnet.tzkt.io/${hash}`);
} catch (error) {
console.error("Error minting NFT:", error);
} finally {
statusMessage = "Ready to mint another NFT.";
buttonActive = true;
}When you call the
Tezos.wallet.at()
method, Taquito creates an object that represents the contract. This object has amethodsObject
property that has a method for each entrypoint in the contract. In this way, thenftContract.methodsObject.mint()
method represents a call to the contract'smint
entrypoint.The complete function looks like this:
const createNFT = async () => {
if (!buttonActive) {
return;
}
buttonActive = false;
statusMessage = "Minting NFT; please wait...";
// Create token metadata
const metadata = new MichelsonMap();
metadata.set("name", stringToBytes("My Token"));
metadata.set("symbol", stringToBytes("Tok"));
metadata.set("decimals", stringToBytes("0"));
metadata.set("artifactUri", stringToBytes(defaultImage));
metadata.set("displayUri", stringToBytes(defaultImage));
metadata.set("thumbnailUri", stringToBytes(defaultImage));
const mintItem = {
to_: address,
metadata: metadata,
};
const mintParameter = [mintItem];
try {
Tezos.setWalletProvider(wallet);
console.log("getting contract");
const nftContract = await Tezos.wallet.at(nftContractAddress);
console.log("minting");
const op = await nftContract.methodsObject.mint(mintParameter).send();
console.log(`Waiting for ${op.opHash} to be confirmed...`);
const hash = await op.confirmation(2).then(() => op.opHash);
console.log(`Operation injected: https://ghostnet.tzkt.io/${hash}`);
} catch (error) {
console.error("Error minting NFT:", error);
} finally {
statusMessage = "Ready to mint another NFT.";
buttonActive = true;
}
} -
In the
<main>
section, add a button to call thecreateNFT
function. The<main>
section looks like this:<main>
<h1>Create NFTs</h1>
<div class="card">
{#if wallet}
<p>The address of the connected wallet is {address}.</p>
<p>Its balance in tez is {balance}.</p>
<button on:click={disconnectWallet}>Disconnect wallet</button>
<button on:click={createNFT}>Create NFT</button>
{:else}
<button on:click={connectWallet}>Connect wallet</button>
{/if}
<p>{statusMessage}</p>
</div>
</main> -
Run the application with the command
npm run dev
and connect your wallet as you did previously. -
Click the Create NFT button and approve the transaction in your wallet.
-
Verify that the NFT was created by looking up the transaction hash in a block explorer. Here are some ways to get the transaction hash:
- Open the browser console and find the message that starts with
Operation injected
. - Click the link in the confirmation window in your wallet application.
- Open the contract in a block explorer and look at the most recent transaction or search for your address in its recent transactions.
For example, this transaction shows the address of the token creator, the
mint
entrypoint, and the name of the new token: - Open the browser console and find the message that starts with
Viewing the NFT in your wallet
Because the contract follows the FA2 standard, Tezos wallets can show information about it. However, your wallet is not immediately aware that you have the token. You can add the token to your wallet manually to see it and work with it in your wallet:
-
In your wallet, go to the tab that shows NFTs, which is usually called "Collectibles" or "NFTs."
For example, the Temple wallet shows NFTs on the Collectibles tab:
-
Add the predefined contract address
KT1Lr8m7HgfY5UF6nXDDcXDxDgEmKyMeds1b
as a source of NFTs.For example, in Temple, click Manage assets list > Manage, click Add Collectible, add the contract address in the Address field, and click Add Asset:
In most cases you can leave the asset ID blank and the wallet will retrieve all of your tokens in the contract.
Now the wallet shows the NFT:
You can click the token to see information about it and to send it to another account. Because the contract is FA2-compliant, wallets can perform operations on the token without any further information.
Now you can create NFTs with your application and the built-in contract. In the next section you start creating your own contract to create NFTs your own way.