# Getting the Sui Latest Object States

*Pawtato Heroes NFT Collection on Dune *

By [Defi, Data, Degen](https://paragraph.com/@evandekim) · 2025-11-13

web3, data, sui, dune, sql, nft

---

How “Latest State” Works on Sui
===============================

The latest-state pattern is one of the most important techniques for anyone working with Sui object data. This technique generalizes to every Sui object type and forms the backbone for any analysis rooted in the chain’s actual state. Every asset—whether a coin, NFT, or protocol object—exists as a Move object that evolves through a sequence of versions.

Each mutation creates a new version, deleted objects remain visible with `object_status = 'Deleted'`, and there is no separate balance table or account registry keeping track of state elsewhere. As a result, the _canonical truth_ for any asset is simply the **row with the highest version number**. If you want to know “what does this object look like right now?”, the answer is always: _find its latest version_.

This structural choice gives Sui enormous flexibility but also shapes how analysts must work with the data. Tasks like fetching the current owner or metadata of an object become trivial once you understand the pattern. But tasks like reconstructing transfers, ownership histories, or application-level flows require walking through the full sequence of versions—something covered in the previous post.

The Pawtato Heroes example highlights why the latest-state pattern is so essential: the latest version reveals the object’s current metadata and owner, but because objects can be owned by other objects, the last modifying transaction’s `sender` is often the real controller.

    object_id: 0xHERO...123
    
                          object versions
              +-----------------------------------------------+
              |                                               |
     version 1   version 2          version 3 (latest)
     +--------+  +--------+         +------------------------+
     |owner:A |  |owner:X |   →     |owner:Y (wrapper obj)   |
     |meta:v1 |  |meta:v1 |         |meta:v2                 |
     +--------+  +--------+         +------------------------+
         ^           ^                        ^
         |           |                        |
     Created      Mutated                Mutated
                                         (ownership changed,
                                         but to an object)
    
              transaction producing version 3
              -----------------------------------------
              tx_digest: 0xTX...789
              sender:    0xREAL_OWNER   ← true controller
              -----------------------------------------
                                 ↑
                                 |
                        previous_transaction  
                        on version 3 object row
    
    Latest-state logic:
    - MAX(version) = 3 → latest object row (owner:Y, meta:v2)
    - But owner:Y is another object (wrapper/vault)
    - Join version 3's previous_transaction → transaction.sender
    - Effective owner = 0xREAL_OWNER
    
    

* * *

Querying Latest State Objects on Dune
=====================================

Below is a practical pattern for retrieving the **latest version** and owner for a Sui NFT collection Pawtato Heroes. The query can be found on Dune [here](https://dune.com/queries/6204236/9899927/). This example demonstrates how to apply latest-state logic to an NFT collection by tracking ownership changes that occur through `Mutated` versions, and resolving the _true_ owner by joining the object’s most recent version to the transaction that produced it.

    WITH params AS (
      SELECT
        DATE '2025-10-30' AS start_date,
        CURRENT_DATE      AS end_date
    ),
    
    -- All relevant HERO object versions in the date window
    base AS (
      SELECT
        o.object_id,
        o.version,
        o.object_status,
        o.owner_address,   -- may be an intermediary object
        o.timestamp_ms,
        o.type_,
        o.object_json,
        o.previous_transaction AS tx_digest,
        from_unixtime(CAST(o.timestamp_ms AS DOUBLE) / 1000.0) AS updated_at_utc
      FROM sui.objects o
      CROSS JOIN params p
      WHERE o.type_ = '0xe0fa7b75a3dc8137b38bceb0c0c21c10e0f57c408fe9068694f58fd21e071925::pawtato_heroes::HERO'
        AND o.object_status IN ('Created', 'Mutated')   -- ownership may change on Mutated
        AND o.date >= p.start_date                     -- efficient partition pruning
        AND o.date <  p.end_date
    ),
    
    -- Latest version per HERO
    latest AS (
      SELECT
        object_id,
        MAX(version) AS max_version
      FROM base
      GROUP BY object_id
    ),
    
    -- Date-windowed transactions (prevents full-table scan)
    tx_window AS (
      SELECT
        t.transaction_digest,
        t.sender,
        t.timestamp_ms AS tx_timestamp_ms,
        from_unixtime(CAST(t.timestamp_ms AS DOUBLE) / 1000.0) AS tx_timestamp_utc
      FROM sui.transactions t
      CROSS JOIN params p
      WHERE t.date >= p.start_date
        AND t.date <  p.end_date
    )
    
    -- Final latest state + effective owner
    SELECT
      b.object_id,
      b.version,
      b.object_status,
      b.owner_address,     -- raw object owner (could be another object)
      b.updated_at_utc,
      b.type_,
      b.object_json,
      b.tx_digest,
      tx.sender            AS effective_owner,     -- true controller of the NFT
      tx.tx_timestamp_utc  AS last_tx_at_utc
    FROM base b
    JOIN latest l
      ON b.object_id = l.object_id
     AND b.version   = l.max_version
    LEFT JOIN tx_window tx
      ON b.tx_digest = tx.transaction_digest;
    
    

This query works by first collecting all relevant Pawtato HERO object versions—both `Created` and `Mutated`. The date window is recent because the collection launched October 2025 which makes the dataset small and efficient to scan. It then identifies the latest version of each object by selecting the maximum `version` per `object_id`, which represents the current on-chain state of that NFT.

To resolve the true owner, the query pulls in a date-filtered slice of `sui.transactions` and joins each object’s most recent `previous_transaction` to the corresponding transaction record. This allows the query to enrich the final result with full `object_json` metadata, the transaction that last updated the object, and most importantly the `sender` of that transaction—who is often the actual controlling address, even when the object’s recorded owner is an intermediate wrapper object.

---

*Originally published on [Defi, Data, Degen](https://paragraph.com/@evandekim/getting-the-sui-latest-object-states)*
