Cardano
Cardano is a collection of open-source, patent-free protocols. It's a platform that enables you to store, transform, and manage value, identity, and governance. Cardano follows research not opinions or bias.
Concepts
For a detailed overview of Cardano basic concepts, please consult Cardano developer docs.
In Blockfrost, we use two main types of encoding when querying resources on the network:
Bech32 - we use Bech32 when querying addresses, stake addresses and pools(also queryable through hex due to historical reasons)
hex - we use lowercase hex when querying assets, asset policies, scripts, transactions and blocks (also queryable through block number, with the exception of boundary blocks)
Mainnet and Testnet (preview and preprod) addresses and stake addresses use different Bech32 prefixes. It is therefore easy to tell them apart. Pool Bech32 encoding, however, is network agnostic and therefore non distinguishable.
When querying the API directly as we do in this guide, Blockfrost.io OpenAPI documentation comes very handy.
Usage
This section covers using Cardano in Blockfrost API.
Don't forget to export
the PROJECT_ID
first when trying examples in this guide!
# Don't forget to replace the PROJECT_ID with yours!
export PROJECT_ID=mainnetEnrkKWDwlA9hV4IajI4ILrFdsHJpIqNC
As there is extremely long list of available methods, we will only cover few from most categories. We will use Cardano Mainnet network for the purpose of this tutorial.
During development phase, use Cardano Testnet (preview or preprod) and get yourself some TADA to play with!
Accounts
Accounts are represented by a stake_address
and usually they represent a single wallet, comprised of multiple standard addresses.
Let's query a Mainnet stake address stake1u9uz4j024qfud557ucrqw3kqfdndjgaxj7m44x7tamkvmyqzdwe7v
.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/accounts/stake1u9uz4j024qfud557ucrqw3kqfdndjgaxj7m44x7tamkvmyqzdwe7v"
{
"stake_address": "stake1u9uz4j024qfud557ucrqw3kqfdndjgaxj7m44x7tamkvmyqzdwe7v",
"active": true,
"active_epoch": 385,
"controlled_amount": "3932327",
"rewards_sum": "0",
"withdrawals_sum": "0",
"reserves_sum": "0",
"treasury_sum": "0",
"withdrawable_amount": "0",
"pool_id": "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy"
}
We can see that there's something below 4 ADA (3 932 327 / 1 000 000) and that the account is participating in staking since epoch 385. It's also visible which pool it stakes with and we'll look at the pool later on.
Let's also query addresses which made at least 1 transaction on the blockchain and belong to this stake address.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/accounts/stake1u9uz4j024qfud557ucrqw3kqfdndjgaxj7m44x7tamkvmyqzdwe7v/addresses"
[
{
"address": "addr1q8zsjx7vxkl4esfejafhxthyew8c54c9ch95gkv3nz37sxrc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgq3jd3w2"
},
{
"address": "addr1qxrrzqsqnzqx3p8sxxsry936h6c78ml4rdl224f33l7pmcnc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgqr735lq"
},
{
"address": "addr1q9x625ny9y42s5z8n78afjg9meyeknvt5kwm3y6sdlrz66tc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgqsyx3uz"
},
{
"address": "addr1qy6qvd3szupa7ayqf6zw7cd0ple7w3yg5f3xh5gkkc4q9zmc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgq52e2en"
}
]
Let's focus just on the last one at the moment, by using query parameters count
and order
.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/accounts/stake1u9uz4j024qfud557ucrqw3kqfdndjgaxj7m44x7tamkvmyqzdwe7v/addresses?count=1&order=desc"
[
{
"address": "addr1qy6qvd3szupa7ayqf6zw7cd0ple7w3yg5f3xh5gkkc4q9zmc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgq52e2en"
}
]
Addresses
Let's continue where we left off and pick the last known address from our account. Have you noticed that there aren't any tokens displayed? To view those, we have to query the associated addresses, as only those can hold tokens.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/addresses/addr1qy6qvd3szupa7ayqf6zw7cd0ple7w3yg5f3xh5gkkc4q9zmc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgq52e2en"
{
"address": "addr1qy6qvd3szupa7ayqf6zw7cd0ple7w3yg5f3xh5gkkc4q9zmc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgq52e2en",
"amount": [
{
"unit": "lovelace",
"quantity": "0"
}
],
"stake_address": "stake1u9uz4j024qfud557ucrqw3kqfdndjgaxj7m44x7tamkvmyqzdwe7v",
"type": "shelley",
"script": false
}
It seems that the queried address is now empty but since we can see it on the blockchain and it didn't return a 404 Not Found from API, it must have made some transactions. Let's confirm this by querying just the most recent transaction. We'll achieve this by using a combination of two query parameters, count=1
and order=desc
.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/addresses/addr1qy6qvd3szupa7ayqf6zw7cd0ple7w3yg5f3xh5gkkc4q9zmc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgq52e2en/transactions?count=1&order=desc"
[
{
"tx_hash": "c34c232d6574d35a92f3bdcc6159b6d0b04f98de9f311db629f8973ac66dec10",
"tx_index": 9,
"block_height": 8223596,
"block_time": 1672766667
}
]
Ok, let's try querying the first address from the account instead:
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/addresses/addr1q8zsjx7vxkl4esfejafhxthyew8c54c9ch95gkv3nz37sxrc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgq3jd3w2"
{
"address": "addr1q8zsjx7vxkl4esfejafhxthyew8c54c9ch95gkv3nz37sxrc9ty742qncmffaesxqarvqjmxmy36d9aht2duhmhvekgq3jd3w2",
"amount": [
{
"unit": "lovelace",
"quantity": "3932327"
},
{
"unit": "d436d9f6b754582f798fe33f4bed12133d47493f78b944b9cc55fd1853756d6d69744c6f64676534393539",
"quantity": "1"
}
],
"stake_address": "stake1u9uz4j024qfud557ucrqw3kqfdndjgaxj7m44x7tamkvmyqzdwe7v",
"type": "shelley",
"script": false
}
Finally a non-empty address! And it contains ADA as well as a single token, or as we call it, asset.
Assets
Let's pick the first asset from the previous call and query its details.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/assets/d436d9f6b754582f798fe33f4bed12133d47493f78b944b9cc55fd1853756d6d69744c6f64676534393539"
{
"asset": "d436d9f6b754582f798fe33f4bed12133d47493f78b944b9cc55fd1853756d6d69744c6f64676534393539",
"policy_id": "d436d9f6b754582f798fe33f4bed12133d47493f78b944b9cc55fd18",
"asset_name": "53756d6d69744c6f64676534393539",
"fingerprint": "asset1smjzaahccwjrmqx5nslm5ph7egfkh3guta5wfn",
"quantity": "1",
"initial_mint_tx_hash": "72c014fccc4c02ed8993087ae0faddd2517d6ed2060173ba6154fb476615a512",
"mint_or_burn_count": 1,
"onchain_metadata": {
"city": "Summit Lodge",
"date": "November 19-21, 2022",
"name": "Cardano Summit 2022 | Summit Lodge",
"files": [
{
"src": "ipfs://QmU1BETyTqbvQQThwGiWTENWxbsuzNgiJYnwe9xJxbGahD",
"name": "Cardano Summit 2022 | Summit Lodge",
"mediaType": "text/html"
},
{
"src": "ipfs://QmetCTi9y1Yr85rrR5fdHxaMmZ5zQZznzZqtge9H1a6HRm",
"name": "Cardano Summit 2022 | Summit Lodge",
"mediaType": "image/jpeg"
}
],
"image": "ipfs://QmVGuPgXg2qXfv4YUdw5Y4QyK8eJhQzGVenV9p8feraqMH",
"author": "TURF",
"country": "Cardano",
"variety": "Common",
"website": "https://www.turfnft.com",
"mediaType": "image/gif",
"event type": "Virtual",
"location code": "00000000+00",
"cardano summit 2022 organizer": "Cardano Foundation"
},
"onchain_metadata_standard": "CIP25v1",
"metadata": null
}
Let's look at the first transaction which has information about this asset. We use similar approach as we used when querying latest, but we'll reverse the order. All the results are by default ordered in ascending order from the oldest transaction, so we may omit the order
query parameter. But it won't hurt to use it explicitly, so let's do that. So again, two query parameters, count=1
stays but the second one changes to order=asc
.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/assets/d436d9f6b754582f798fe33f4bed12133d47493f78b944b9cc55fd1853756d6d69744c6f64676534393539/transactions?count=1&order=asc"
[
{
"tx_hash": "72c014fccc4c02ed8993087ae0faddd2517d6ed2060173ba6154fb476615a512",
"tx_index": 22,
"block_height": 8038275,
"block_time": 1668961302
}
]
Seems familiar? The tx_hash
is matching initial_mint_tx_hash
from the previous call! It is in fact the very first, i.e. mint, transaction of that particular asset.
Blocks
Blocks can be queried either by their hash
or their height
. Let's try querying block from the previous call.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/blocks/8038275"
{
"time": 1668961302,
"height": 8038275,
"hash": "4660d994f9099cbe9bf980f10e2dc02902505cbeadcff10b21b819d61076a93c",
"slot": 77395011,
"epoch": 376,
"epoch_slot": 326211,
"slot_leader": "pool1jgwu8lq3dqddnnx7prymcgcyrqy0fdlghg33he2hmw9t2gma3zd",
"size": 88725,
"tx_count": 70,
"output": "663048152642",
"fees": "15583364",
"block_vrf": "vrf_vk1ga52prse4ws509nah3p9d9l6nf5jurkx8j2g7fh8ljwtaj9t9ysqt9g0ku",
"op_cert": "04f80395f8f1876c393b725fd5d633739591dde72ae136a9042aab0ada0d393e",
"op_cert_counter": "9",
"previous_block": "89a1f73719fc29810dc540bea103fd4454679f16201e2d541eef44a10d3421ab",
"next_block": "4e5d4fc281d43fc85921dd002357b4785fb0692d0a66df56a59da81fb3f0a760",
"confirmations": 185374
}
There's a lot of going on, 70 txs in the block where that asset was minted! Ok, let's try another very useful call, querying the latest block, a.k.a. the tip of the blockchain.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/blocks/latest"
{
"time": 1672766054,
"height": 8223577,
"hash": "4f07277d9b5f5141cc27bcb469682f4010439f0725e870862622f569a7c86222",
"slot": 81199763,
"epoch": 385,
"epoch_slot": 242963,
"slot_leader": "pool17taqml487n9t4r9a6ppvf9qv0qlw2lu4zcrzwfdsfcv6xp7uqym",
"size": 4,
"tx_count": 0,
"output": null,
"fees": null,
"block_vrf": "vrf_vk1w064pps8jkpee8hs6szluyv7smksch0v4adzja03wepfdw0jxs6q9lh8kg",
"op_cert": "aed510b38a5d4cf76a5165b3ef46538788bf0f62d7e07988b31e99a8d7ba96c4",
"op_cert_counter": "8",
"previous_block": "84ffff75fde7898b71acf777e85d8e8c3fcd64708ac845a92429cb9b023894a4",
"next_block": null,
"confirmations": 0
}
Huh, an empty block. There are no transactions. Well, it might happen when the blockchain is not under load, so let's try again.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/blocks/latest"
{
"time": 1672766182,
"height": 8223582,
"hash": "eb625cdac8f97791b2fc7d86057b26179e2c08f772411e43809afc6d997f900a",
"slot": 81199891,
"epoch": 385,
"epoch_slot": 243091,
"slot_leader": "pool1wf7wk3802jxtkmek6uprm77cgqx53t4qep9kwkl078w3yw0ff69",
"size": 11714,
"tx_count": 5,
"output": "251134283914",
"fees": "2201272",
"block_vrf": "vrf_vk1hpnf7ytfvtq7h5ns5zcqg6yxrjg34kkfj5njmgs8hjxtfle6qrnsash3xy",
"op_cert": "6e965ee09632519948258f8ba7a2e8fbd84db91ede232ef85046ccf61988bd58",
"op_cert_counter": "9",
"previous_block": "972d5f7142ed5fc7339bce36d15813554403780db61b87b6a5441033fa8a53d1",
"next_block": null,
"confirmations": 0
}
Excellent. Notice how confirmations
and next_block
are always null. That's because we're looking at the tip of the blockchain.
We can also look at the transactions in a block.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/blocks/eb625cdac8f97791b2fc7d86057b26179e2c08f772411e43809afc6d997f900a/txs"
[
"f1c24763f4ddca8a8b0dcc91ea76a1a9657cfe1615c72a459f5f370069a28874",
"0eb9596a8234e8f797640fc890d8888ba30040983665d4689d016033f2d73031",
"66d8e7046fb30b5645b31e65be0b27d17af9111936ffb25414fd933af4f6d2bb",
"df10b32aea46240d0ca240a83eac5f5b1e9790dada14b0772066e008ad3ddac1",
"080877b20e5fcbc0d3d3bd56bb875dac5ef03b7541c79f2c81bb2552ac628f0e"
]
Transactions
Ah, transactions. The life and soul of every blockchain. Nearly everything is a transaction of some sort.
Let's look at the first transaction we found when we were querying the latest block.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/txs/f1c24763f4ddca8a8b0dcc91ea76a1a9657cfe1615c72a459f5f370069a28874"
{
"hash": "f1c24763f4ddca8a8b0dcc91ea76a1a9657cfe1615c72a459f5f370069a28874",
"block": "eb625cdac8f97791b2fc7d86057b26179e2c08f772411e43809afc6d997f900a",
"block_height": 8223582,
"block_time": 1672766182,
"slot": 81199891,
"index": 0,
"output_amount": [
{
"unit": "lovelace",
"quantity": "337920356"
},
{
"unit": "8e0556c569082f195b406737647765ed6b05d27dcb2c65319b7ce39154434332393239",
"quantity": "1"
}
],
"fees": "440501",
"deposit": "0",
"size": 1379,
"invalid_before": null,
"invalid_hereafter": "81201678",
"utxo_count": 12,
"withdrawal_count": 0,
"mir_cert_count": 0,
"delegation_count": 0,
"stake_cert_count": 0,
"pool_update_count": 0,
"pool_retire_count": 0,
"asset_mint_or_burn_count": 0,
"redeemer_count": 1,
"valid_contract": true
}
We can inspect transactions further by querying them and then using sub-queries to get even more info. For example, querying this transaction, we see that redeemer_count
is non-zero, so we could then fetch additional info by using /redeemers
call. i.e.:
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/txs/f1c24763f4ddca8a8b0dcc91ea76a1a9657cfe1615c72a459f5f370069a28874/redeemers"
[
{
"tx_index": 1,
"purpose": "spend",
"script_hash": "9068a7a3f008803edac87af1619860f2cdcde40c26987325ace138ad",
"redeemer_data_hash": "e5ee0cfe4d99494b8022f26e0cefd24fc78b23f798d59886eba97f9f6475648f",
"datum_hash": "e5ee0cfe4d99494b8022f26e0cefd24fc78b23f798d59886eba97f9f6475648f",
"unit_mem": "2858646",
"unit_steps": "824631790",
"fee": "224400"
}
]
and even query the script involved!
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/scripts/9068a7a3f008803edac87af1619860f2cdcde40c26987325ace138ad"
{
"script_hash": "9068a7a3f008803edac87af1619860f2cdcde40c26987325ace138ad",
"type": "plutusV2",
"serialised_size": 2561
}
Epochs
Let's look at some epoch stats. We'll query the epoch from the previous call. There are two ways of making the call. Either query a specific epoch or query the latest epoch. Since we're now in the latest epoch, both calls will return the same output.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/epochs/latest"
{
"epoch": 385,
"start_time": 1672523091,
"end_time": 1672955091,
"first_block_time": 1672523095,
"last_block_time": 1672767811,
"block_count": 11993,
"tx_count": 203952,
"output": "27826751355072919",
"fees": "71879981640",
"active_stake": "25388654503848140"
}
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/epochs/385"
{
"epoch": 385,
"start_time": 1672523091,
"end_time": 1672955091,
"first_block_time": 1672523095,
"last_block_time": 1672767836,
"block_count": 11994,
"tx_count": 203983,
"output": "27846411264491280",
"fees": "71891439390",
"active_stake": "25388654503848140"
}
Wait, what? The numbers differ! That's because a new block has been generated between the two calls, as you can see from the block_count
and other properties being updated. When a new epoch starts, calling a specific epoch number will produce static results, unlike now, when it's still active.
Pools
Let's take a look a the pool from the very beginning, the pool at which the account is currently staking.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/pools/pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy"
{
"pool_id": "pool1pu5jlj4q9w9jlxeu370a3c9myx47md5j5m2str0naunn2q3lkdy",
"hex": "0f292fcaa02b8b2f9b3c8f9fd8e0bb21abedb692a6d5058df3ef2735",
"vrf_key": "b512cc7c1a8ba689c2d8fd27adfdbac2049a3f8f95c8b85e8298f14d7d8dc4e6",
"blocks_minted": 2068,
"blocks_epoch": 1,
"live_stake": "5174880859704",
"live_size": 0.00020379184476411696,
"live_saturation": 0.07495042680626458,
"live_delegators": 177,
"active_stake": "5327138850257",
"active_size": 0.0002098235985467276,
"declared_pledge": "510000000000",
"live_pledge": "515645620665",
"margin_cost": 0.049,
"fixed_cost": "340000000",
"reward_account": "stake1u98nnlkvkk23vtvf9273uq7cph5ww6u2yq2389psuqet90sv4xv9v",
"owners": ["stake1u98nnlkvkk23vtvf9273uq7cph5ww6u2yq2389psuqet90sv4xv9v"],
"registration": [
"a96c79773b7506211eb56bf94886a2face17657d1009f52fb5ea05f19cc8823e"
],
"retirement": []
}
There are many information which we can query about a pool, such as history, updates or info about its delegators.
Mempool
The mempool in Cardano is not global, which means that different block producing nodes can have different state of the network, including pending transactions in the mempool. However, if your application is using Blockfrost submit endpoint, you can verify whether your transaction is present in our mempools.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/mempool"
[
{
"tx_hash": "edb1c7fab58d94b6b402686956391a366548696431387d24e214c228ce7311eb"
},
{
"tx_hash": "68757830e3eb8ac6b79169734310e624c9c7c18c92c0b1d32d392124ad34a17e"
},
{
"tx_hash": "ce2e9ce0c5ef2701f083b005529b2fd2e47acc48e3aff9e60bc96e970306d087"
},
{
"tx_hash": "33b78c1b3dfca35854bd236143f49d1aacbe2003ad21d13f5018009a002da65c"
},
{
"tx_hash": "ad5b4f7c394782593f750124c9917c53336a1623ae5d58523e83257c6080c5d6"
}
]
Network
To finish our Cardano adventure, let's look at the Mainnet stats at the time of writing this guide. You can also use jq
, if you happen to have it.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/network"
{
"supply": {
"max": "45000000000000000",
"total": "35322101769949668",
"circulating": "34522023957783973",
"locked": "147932183023929",
"treasury": "1113894699593937",
"reserves": "9677898230050332"
},
"stake": {
"live": "25392973235478445",
"active": "25388654503848140"
}
}
jq is a really useful tool. When used without any arguments, it will format the JSON. Just pipe any output from curl
to jq
.
curl -H "project_id: $PROJECT_ID" \
"https://cardano-mainnet.blockfrost.io/api/v0/network" | jq
FAQ
For more information related to Cardano in Blockfrost, please see our Cardano FAQ.
Although it is perfectly possible to create your apps directly through the API, you will probably save a lot of time and nerves by using one of our many SDKs.