7

Is there a way to use cardano-cli (or another tool) to query a Cardano node for an NFT's current owner (wallet address holding the NFT)? The parameters for such a query would likely be the Policy ID & Asset Name of the NFT.

Since, from a blockchain perspective, there is no difference between native tokens for which an arbitrary amount of tokens exist and those where there is only a single one (NFTs), I guess a query like the one I'm looking for is not something that fits into the grand scheme of things; but maybe I'm missing something?

If there is no tool readily available, how could I use cardano-cli (or another tool) to look through all transactions (starting with the most recent and going backwards in time) until I find the most recent transaction containing the NFT in question?

8

There is no way to find that information without syncing the whole blockchain into a database with a tool such as cardano-db-sync.

This takes a lot of time and resources, so you might want to use an API like blockfrost.io to query the addresses owning a specific token.

$ curl  -s -H "Project_id: $BLOCKFROST_PROJECT_ID" https://cardano-mainnet.blockfrost.io/api/v0/assets/00000002df633853f6a47465c9496721d2d5b1291b8398016c0e87ae6e7574636f696e/addresses | jq
  [
   {
    "address": "addr1qxlmfhfcjck5pctuvlpww3kuxvqjucz40qusgeqgmyqq4utntgjccmteyrsldd67rxv2yq6ew2a7t48q34p9j7nf0kjqskku78",
    "quantity": "1"
   }
  ]
3

As suggested by Marek, blockfrost.io seems to be a great way to jump right in.
For an alternative do-it-yourself way other tools can be used.

Using cardano-db-sync the blockchain data acquired by a Cardano node will be fed into a PostgreSQL database, allowing to query the data through SQL.

Querying that database looks like this (this is just a random query taken from the example queries, it does not answer the original question):

select tx_out.* from tx_out
inner join tx_in on tx_out.tx_id = tx_in.tx_out_id
inner join tx on tx.id = tx_in.tx_in_id and tx_in.tx_out_index = tx_out.index
where tx.hash = '\xf9c0997afc8159dbe0568eadf0823112e0cc29cd097c8dc939ff44c372388bc0' ;

   id    | tx_id  | index |        address          |    value     |        address_raw        | payment_cred
---------+--------+-------+-------------------------+--------------+---------------------------+--------------
 2195714 | 996126 |     4 | DdzFFzCqrh...dtq1FQQSCN | 158685237964 | \x82d8185842...1a330b42df |

Building on that, one could further set up cardano-graphql to provide a GraphQL API for cardano-db-sync. This is what the Cardano Explorer is built upon.

Using cardano-graphql, a query to find the current owner of a given token could look like this:

query TokenOwner($policy_id : Hash28Hex, $asset_name : String) {
  utxos (where: {tokens: {_and: {asset: {policyId: {_eq: $policy_id} assetName: {_eq: $asset_name}}}}})
  { 
    txHash
    address
    value
    tokens {asset {policyId assetName} quantity}
  }
}

Where the arguments denoting the NFT are its policy id and asset name, for example:

{
  "policy_id": "d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc",
  "asset_name": "537061636542756433373430"
}

Note that asset_name is provided in hex format.

For this example, a random SpaceBud (SpaceBud759) with no other tokens in the UTXO was selected, resulting in the following output (on 2021-05-02) where the address field denotes the current owner:

{
  "data": {
    "utxos": [
      {
        "txHash": "4fcf200a8b18f866bd4e9324600ffe636b081d79a9bb06b748fa41947f3a6a5e",
        "address": "addr1qxjtqaxmv44u2zx02v7658wrlt87tv9yp7knzwh6hana3ra5ay9tjpf6e0d3p2t7s6gnnqtwmva02lx4p0dlx8a7x8uqrw46dy",
        "value": "1500000",
        "tokens": [
          {
            "asset": {
              "policyId": "d5e6bf0500378d4f0da4e8dde6becec7621cd8cbf5cbb9b87013d4cc",
              "assetName": "5370616365427564373539"
            },
            "quantity": "1"
          }
        ]
      }
    ]
  }
}

As of writing, using the policy id in queries like shown above seems to be non-functional, as described in this github issue.

Further example queries can found here, one might also check out this graphical representation of the API.

2
  • 1
    Provided an edit to this answer with a graphql query that answers the original question. However, the query is bugged as of writing, documented w/quick fix in this issue: github.com/input-output-hk/cardano-graphql/issues/485
    – Ben NOBLE
    May 2 at 17:33
  • Thank you very much @stakenoble-ben, that's great! I made some minor changes to your edit and applied it.
    – nullcheck
    May 3 at 17:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.