Skip to content

3. Fetch Data from Chain

In the third chapter of the tutorial on building an end-to-end dapp on Aptos, you will be learning to fetch data from chain.

Our UI logic relies on whether the connected account has created a todo list. If the account has created a todo list, our app should display that list; if not, the app should display a button offering the option to create a new list.

For that, we first need to check if the connected account has a TodoList resource. In our smart contract, whenever someone creates a todo list we create and assign a TodoList resource to their account.

To fetch data from chain, we can use the Aptos TypeScript SDK. The SDK provides classes and functions for us to easily interact and query the Aptos chain.

To get started:

  1. Stop the local server if running and go to the App.tsx file.

  2. Import wallet from the wallet adapter React provider:

    import { useWallet } from "@aptos-labs/wallet-adapter-react";
  3. Extract the account object from the wallet adapter:

    function App (
    const { account } = useWallet();
    )

    The account object is null if there is no account connected; when an account is connected, the account object holds the account information, including the account address.

  4. Set up React hooks and state:

    • Import useEffect and useState using:
    import { useState, useEffect } from "react";
    • Create local state to track whether the account has a todo list and add a useEffect hook to fetch data when the account changes:
    function App() {
    const [accountHasList, setAccountHasList] = useState<boolean>(false);
    useEffect(() => {
    fetchList();
    }, [account?.address]);
    }
  5. Import required dependencies:

    • Import MODULE_ADDRESS variable using:
    import { MODULE_ADDRESS } from "./constants";
    • Import aptosClient using:
    import { aptosClient } from "./utils/aptosClient";
  6. Create the fetchList function:

    const fetchList = async () => {
    if (!account) return [];
    const moduleAddress = MODULE_ADDRESS;
    try {
    const todoListResource = await aptosClient().getAccountResource(
    {
    accountAddress:account?.address,
    resourceType:`${moduleAddress}::todolist::TodoList`
    }
    );
    setAccountHasList(true);
    } catch (e: any) {
    setAccountHasList(false);
    }
    };
  7. Update the UI based on the accountHasList state:

    • Import Button component using:
    import { Button } from "./components/ui/button";
    • Update the UI based on the accountHasList state:
    return (
    <>
    <TopBanner />
    <Header />
    <div className="flex items-center justify-center flex-col">
    {!accountHasList && (
    <div className="flex items-center justify-center flex-col">
    <Button>Add new list</Button>
    </div>
    )}
    </div>
    </>
    );

    The aptosClient().getAccountResource() expects an account address that holds the resource we are looking for and a string representation of an on-chain Move struct type:

    • account address - is the current connected account (we are getting it from the wallet account object)
    • Move struct type string syntax:
      • The account address who holds the move module
      • The module name the resource lives in = todolist
      • The resource name = TodoList

    If the request succeeds and there is a resource for that account, we want to set our local state to true; otherwise, we would set it to false.

    We now have an Add new list button that appears only if the account doesn’t have a list.

  8. Start the local server with npm run dev. You should see the Add new list button.

Next, let’s understand how to create a new list by submitting data to chain in chapter 4.