A few months ago one of my friends asked me to help him mint some NFT on the Cardano blockchain. At that point, I had no idea how transactions work on Cardano and how to actually mint any NFT on it. So I started reading all the blog posts I could find and started banging my head on the Cardano documentation.
Now I’m writing this series (hopefully) of blog posts because I had to learn things from different places and couldn’t find everything in the Cardano documentation because it’s not very frequently updated. I believe the main reason for that is because Cardano is under very active development so most of the time devs focus on making the application instead of updating the documentation.
These blog posts will be my way of sharing the knowledge I’ve gained over these few months and probably help the newcomers planning to start in these.
What is Cardano?
According to cardano.org
Cardano is a blockchain platform for changemakers, innovators, and visionaries, with the tools and technologies required to create the possibility for the many, as well as the few, and bring about positive global change
In simple terms, it is one of the many blockchain platforms which has recently come into the limelight (I think). And is believed to be a competitor of ETH i.e do everything ETH can do but with less gas fee.
Without getting into the detail of why Cardano was made, how it’s different, etc. I’m just going to jump into how one can start their own cardano-node and then interact with using cardano-cli
to submit transactions, mint/burn/evolve tokens.
Running own cardano-node
In this, we are going to run our own testnet
. But what is testnet
?
To quote the cardano.org
The Cardano testnet offers full Cardano functionality, including stake pool operation, transaction metadata, native tokens, and more.
Basically, on testnet we can do exactly what can be done in the real-world but without using any real money(ADA).
Before we start I’d also like to point out that the almost everything will be similar in case you decide to run the mainnet
. And I’ll point out the things that could be different in the case of mainnet.
Starting Testnet
Go to releases page of the cardano-node repository. And in the
download
section you’ll see theHydra binaries
and theConfigurations files
.- Remember to download configuration files for
testnet
and NOT mainnet. - Only download the
config
,byronGenesis
,ShelleyGenesis
,alozonGenesis
andtopology
. - Store all the config files in a folder named
configs
- We don’t need
db-sync config
andrest config
for running the node.
- Remember to download configuration files for
To start the node run the following command:
cardano-node run \
--topology ./configs/testnet-topology.json \
--database-path ./db --port 3001 \
--config ./configs/testnet-config.json \
--socket-path testnet.socket
--topology
- path to thetestnet-topology.json
. This basically pushes the node alive message, showing that a new node has come into the network.--database-path
- This can be any path. Basically here all synced node information will be stored.--config
- path to the testnet config.--socket-path
- the path where you want to create thetestnet.socket
- If you are on windows then this will be changed to,
--socket-path \\.\\pipe\\cardano-node
- If you are on windows then this will be changed to,
--port
- This can be any port you want.
- Now run the following command:
export CARDANO_NODE_SOCKET_PATH="/path/to/your/testnet.socket"
If you are on Windows then run:
$env:CARDANO_NODE_SOCKET_PATH='\\.\\pipe\\cardano-node'
Remember the above commands will only set variables in your current shell and not globally. If you’d like to set variables globally then:
- For Linux - add this (
export CARDANO_NODE_SOCKET_PATH="/path/to/your/testnet.socket"
) in your .bashrc/.zshrc - For Windows - read this to see how to add Environment variables.
- Now you’ll have to wait for a few minutes and then run the following command:
cardano-cli query tip --testnet-magic 1097911063
The testnet-magic
number can be found in the testnet-shelley-genesis.json
file.
Now if everything was done correctly, then with the above command you must see something like:
{
"epoch": 166,
"hash": "c4060a65975397e84a5f59f73e09c5f857339f661a7db7389e6f5b76cb75b89a",
"slot": 41764705,
"block": 3049124,
"era": "Alonzo",
"syncProgress": "100.00"
}
The values might vary but if you get similar-looking output then your node is up and running and is being synced.
NOTE: The testnet network takes about 4-5 hours to sync 100% and the mainnet network takes about 24 hours to sync.
When you run the command given in step 4 and get an error saying something like:
cardano-cli: Network.Socket.connect: <socket: 11>: does not exist (Connection refused)%
Then please wait for some time before re-trying the same command, sometimes it takes a bit longer to generate the socket
file.
Create simple transactions
In this blog post, we are only going to focus on transferring tADA(testing ADA) from one wallet to another wallet. In the future, I’ll explain on how to mint NFTs on the Cardano chain and how to transfer them.
But before we get into making transactions we need to generate a payment address.
Generating payment address
- Make a new directory called
payment_addr1
mkdir -p $HOME/payment_addr1/
- Now generate a payment key-pair
cardano-cli address key-gen \
--verification-key-file $HOME/payment_addr1/payment.vkey \
--signing-key-file $HOME/payment_addr1/payment.skey
- Now using the above key-pair we can generate a wallet address
cardano-cli address build \
--payment-verification-key-file $HOME/payment_addr1/payment.vkey \
--out-file $HOME/payment_addr1/payment.addr --testnet-magic 1097911063
I’d suggest generating another address (under payment_addr2
) in a similar manner. This way you can perform all the transactions and see things happening.
Getting tADA in the wallet
Now that we have the wallet, you can run the following command to see if there are any tADA in your wallet (there shouldn’t be any)
cardano-cli query utxo --address <your_payment_addr1_address_here> --testnet-magic 1097911063
You should see something like:
TxHash TxIx Amount
--------------------------------------------------------------------------------------
This shows that you don’t have any tADA in your wallet. Now to get some tADA to go to, testnet faucet and enter your wallet address
. You don’t need an API key(it’s not compulsory to put it there). You can request any amount of tADA you want, for this tutorial we are going to request 20 tADA
.
Once you’ve requested the funds, wait for a few minutes and run the following command:
cardano-cli query utxo --address <your_payment_addr1_address_here> --testnet-magic 1097911063
you should see an output that looks like the following:
TxHash TxIx Amount
--------------------------------------------------------------------------------------
4606b0a96e0b69569be47293fdfcebda19da3fd2b7c0066d695f13020663c524 1 20000000 lovelace + TxOutDatumHashNone
What is a UTxO
We requested 10 tADA but in the above output, we can see a TxHash
, TxIx
, and Amount
. This as a whole is known as UTxO(Unspent Transaction Output). The concept of UTxO is taken from Bitcoin.
A UTxO represents a Transaction that isn’t spent, hence the name unspent
. This means that chain knows that in the whole network there is a UTxO with a certain unique identification (combination of TxHash
& TxIx
) which stores some unspent amount. Now, this UTxO(s) can be used to make transactions i.e to transfer the amount. The UTxO model in Cardano/BTC varies from what a chain like ETH uses. In ETH it’s what we are used to, A has 10 in their wallet and would like to send 5 to B, so when a transaction on ETH will be submitted it will reduce 5 from A and increase 5 on the B side. But a UTxO model doesn’t work like that. In a UTxO model, a whole UTxO is consumed when a transaction is submitted.
Ex: Say A has a UTxO with amount 10
tADA and would like to send 5 tADA to B and keep the remaining 5 tADA. Now in Cardano, a simple increment on B’s amount and decrement on A’s amount, won’t happen. Instead while making a transaction a UTxO(s) will be given as an input, which stores the 10 tADA. Once that transaction is submitted, that UTxO will be consumed completely and a new UTxO with the same TxHash but different TxIx will be generated. One of the UTxO will be present in A’s wallet showing 5 tADA remaining and another UTxO(same TxHash but different TxIx) will be shown in B’s wallet.
NOTE: In the above example I’ve not considered the gas fee.
Understanding UTxO can be a difficult task, if you like to further read about it then I’d suggest Cardano’s documentation on UTxO models
And in the UTxO we see the amount written in Lovelace.
1 ADA/tADA == 1000000 Lovelace
So when we transferred 20 tADA we got 20000000
Lovelace.
Making a transaction
Now that we understand what a UTxO is and also have a proper setup of tools. We can start making transactions. There are 3 steps to submit a transaction:
- Build a transaction: We provide the UTxO input and the output address along with the output and some other arguments.
- Sign a transaction: We then sign the transaction, to show that we actually own the UTxO which will be consumed.
- Submit the transaction
Building a transaction
In order to build a transaction we are going to use the following command:
cardano-cli transaction build --alonzo-era \
--tesnet-magic 1097911063 \
--tx-in $TX_IN \
--tx-out $ADDR+$AMOUNT \
--change-address $OWN_ADDR \
--out-file tx.raw
--alonzo-era
: This is the latest cardano era. You can also use--byron-era
or--shelley-era
but those might give errors.--testnet-magic
: If we were onmainnet
then this would have changed to--mainnet
. And with mainnet we don’t need to provide any magic number.--tx-in
: This is where we input the UTxO which has to be consumed.- In a single command, there can be as many
--tx-in
argument as you want.- Ex: Say you want to send 5 tADA but you have 3 tADA in X UTxO and 2 tADA in Y UTxO, so you can give 2
--tx-in
so both of them can be consumed.
- Ex: Say you want to send 5 tADA but you have 3 tADA in X UTxO and 2 tADA in Y UTxO, so you can give 2
- Another thing to remember is that the
$TX_IN
format would be TxHash#TxIx i.e if theTxHash
was4606b0a96e0b69569be47293fdfcebda19da3fd2b7c0066d695f13020663c524
andTxIx
was1
then we would write--tx-in 4606b0a96e0b69569be47293fdfcebda19da3fd2b7c0066d695f13020663c524#1
, notice the#1
in the end.
- In a single command, there can be as many
--tx-out
: Here we will put the address of the person we want to send the amount along with the amount, separated by+
.- Just the way we can have multiple
--tx-in
in the same way we can have multiple--tx-out
- The format for
--tx-out
will be<ADDR_TO_SEND_tADA>+<AMOUNT_TO_BE_SENT>
- Amount of ada has to be in Lovelace.
- Just the way we can have multiple
--change-address
: This will be the address to which the changes i.e the remaining amount, will be sent.- Say you have 5 tADA in the UTxO and you’d like to transfer 3 tADA and would like to have 2 tADA back. So in the
--change-address
you can put your own address, so once the transaction is submitted 3 tADA will be transferred,~0.2
will be paid as the gas fee and the remaining 1.8 tADA(changes) will be sent back to you.
- Say you have 5 tADA in the UTxO and you’d like to transfer 3 tADA and would like to have 2 tADA back. So in the
--out-file
: The output file which will hold all the transaction information.
Now I’m going to use 20 tADA that I got from testnet faucet to build a transaction:
cardano-cli transaction build --alonzo-era --tesnet-magic 1097911063 \
--tx-in 4606b0a96e0b69569be47293fdfcebda19da3fd2b7c0066d695f13020663c524#1 \
--tx-out $payment_addr2+10000000 --change-address $payment_addr1 --out-file tx.raw
In the above transaction I’m sending 10 tADA
from payment_addr1
-> payment_addr2
. When I ran the above command I got a file called tx.raw
Signing a transaction
Here we are going to sign the transaction which we generated in the building a transaction.
cardano-cli transaction sign \
--signing-key-file $HOME/payment_addr1/payment.skey \
--testnet-magic 1097911063 --tx-body-file tx.raw --out-file tx.signed
--signing-key-file
: This is the argument in which we provide our wallet’sskey
--tx-body-file
: This takes the path to the file which we get frombuilding a transaction
.
Ex: I’m going to sign the transaction which I built using the payment_addr1
skey. We have to use payment_addr1
keys because we are sending it from that wallet.
cardano-cli transaction sign \
--signing-key-file $HOME/payment_addr1/payment.skey \
--testnet-magic 1097911063 --tx-body-file tx.raw --out-file tx.signed
Submit a transaction
This is probably the easiest step. Just run the following command:
cardano-cli transaction submit --tx-file tx.signed --testnet-magic 1097911063
--tx-file
: Path of the file which we got after wesigned a transaction.
Once we run that we will get the acknowledgment that the transaction is submitted successfully.
So this was all you need to do/know to get started with cardano-node and cardano-cli. In the next post, I’ll try to explain how to mint an NFT and how to transfer them between wallets.
Thanks for reading, feedback is always appreciated :)
You can follow me on @0xmzfr