List all tokens in a wallet

4. List all tokens in a wallet

Some assets, particularly NFTs, may include additional information detailed in their metadata. For instance, in-game NFTs can have attributes such as power, speed, and strength encoded in this metadata. This information follows the standards set by various Cardano Improvement Proposals, such as CIP-25 (opens in a new tab), which define how metadata should be structured for assets on the Cardano blockchain.

💡

Metadata standards for Cardano are covered in CIPs (Cardano Improvement Proposals) 25 (opens in a new tab), 26 (opens in a new tab), 60 (opens in a new tab) and 68 (opens in a new tab)

To keep things simple, we will use the same address as before:

addr_test1qr70pedl22tnzswcfm39nqvsfan9jgtym2k0lgrftga8j67jel8q0vyag8770e8pu3rf6he70dtrexrsg6waj09cae0svmt57t

🔎 You can also verify the details on one of many Cardano Community Explorers listed here (opens in a new tab). For this one, lets use Cardanoscan (opens in a new tab) 🎯

To retrieve the metadata, you can use the following query:

SELECT
     ma.fingerprint,
    ma.name AS name,
    sum(mto.quantity) AS quantity
FROM
    ma_tx_out mto
JOIN multi_asset ma 
	ON ma.id = mto.ident 
JOIN tx_out 
	ON mto.tx_out_id = tx_out.id
LEFT JOIN tx_in ti 
	ON ti.tx_out_index = tx_out."index" AND ti.tx_out_id = tx_out.tx_id 
WHERE
    tx_out.address = 'addr_test1qr70pedl22tnzswcfm39nqvsfan9jgtym2k0lgrftga8j67jel8q0vyag8770e8pu3rf6he70dtrexrsg6waj09cae0svmt57t'
    AND ti.tx_out_id is null
GROUP BY ma.fingerprint, ma.name

Expected results format

     fingerprint                              |       name      |    quantity
----------------------------------------------+-----------------+--------------- 
asset1anpme6pcrc4jax2h230gm4pgmwsz80u27qsufq  | tBigTokenName03 |     20           
asset1etk8c8pscc0f6hy6q4wc3nphk9znj0xagv9acz  | tBigTokenName01 |     20                
asset1gvxdk7yhzupnruv9h54jc9eenf30w55xuq43vf  | tBigTokenName05 |     20         
asset1nvcwnq60jnm27efjm87xnhqt6alsv024tdyxjm  |     tDRIP       |  1,000,020
asset1qftk8hza6hn50lm2pl88wl8gea5fan5zhgx8gm  | tBigTokenName10 |     10
asset1rpsx8nx8gzmwt62tuzdwq66qj8jrdmsgjv6qsa  | tBigTokenName08 |     20
asset1t87nuhlan33l68hhtgmt3zfks3lwupayncz0k3  | tBigTokenName07 |     20
asset1tfpfjaz57vpcddwzxdz49f8pc7zmlswjfjfwwx  | tBigTokenName04 |     20
asset1uvkv85rk6pklfcdm39ht0yq60pf2fawtwndu2w  | tBigTokenName06 |     20
asset1vyddw8jc6w9679smf4d4d8r4qn7g2pzkqhgktd  | tBigTokenName02 |     20
asset1zutmprtn8te56av95m09sxj305rxm7yps3e3vr  | tBigTokenName09 |     20            
(11 rows)

At a high level, we are listing all the distinct tokens (fungible tokens) and NFTs (non-fungible tokens) present in our specific Cardano wallet address, along with their respective quantities. This is essential for wallet applications to display a user's asset holdings accurately. We are checking unspent Multi-Asset transaction output from the ma_tx_out (opens in a new tab) table for our specific address. 🔎 Let's break it down line by line:

SELECT the right information:

  • ma.fingerprint ,ie. the unique fingerprint of the token/NFT.
  • ma.name ...this is the name of the token/NFT (often used to distinguish NFTs).
  • sum(mto.quantity), ie. the total quantity of that specific token/NFT held in the wallet, calculated by summing quantities across UTXOs.

Table JOINs

  • ma_tx_out mto table stores information about multi-asset quantities within transaction outputs.
  • multi_asset ma table stores the metadata for each multi-asset.
  • The tx_out (opens in a new tab) table stores general transaction output information.
  • tx_in ti table stores transaction input information. We use this to check if a UTXO is spent.

Filters

  • tx_out.address = 'addr_test1qr70pedl22tnzswcfm39nqvsfan9jgtym2k0lgrftga8j67jel8q0vyag8770e8pu3rf6he70dtrexrsg6waj09cae0svmt57t'...we are filtering for our specific wallet address.
  • ti.tx_out_id IS NULL is an important condition ensuring we only consider unspent transaction outputs (UTXOs) since those are the ones containing the assets currently held in the wallet.

Grouping and Aggregating

  • GROUP BY ma.fingerprint, ma.name clause groups the results by the unique fingerprint and name of each token/NFT, enabling us to calculate the total quantity held.
  • SUM(mto.quantity) calculates the total quantity of each token/NFT by summing up the quantities found in all relevant UTXOs.

Summary

  • The query looks at all transaction outputs containing multi-assets.
  • It checks if the outputs belong to the specified wallet address and are unspent.
  • It retrieves the fingerprint and name of the multi-asset from the multi_asset (opens in a new tab) table.
  • It groups the results by fingerprint and name, summing up the quantities to get the total amount of each token/NFT held at our wallet address.
  • It returns a list of all the distinct tokens and NFTs in the wallet, along with their respective quantities.