<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/">
    <channel>
        <title>luispoveda.eth 🌻</title>
        <link>https://paragraph.com/@luispoveda</link>
        <description>undefined</description>
        <lastBuildDate>Sat, 25 Apr 2026 00:03:11 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <language>en</language>
        <copyright>All rights reserved</copyright>
        <item>
            <title><![CDATA[How to build your NFT Gallery with Tatum]]></title>
            <link>https://paragraph.com/@luispoveda/how-to-build-your-nft-gallery-with-tatum</link>
            <guid>l2p8GRcC1WgiggmpRems</guid>
            <pubDate>Tue, 08 Nov 2022 00:13:03 GMT</pubDate>
            <description><![CDATA[While coding to enter a hackathon, I had to use Tatum’s API since it was one of the sponsors there, although I had used Tatum before, this time I reached a new level, using the API to build an NFT gallery, with just a few other tools, and I’d like to share it with you.Tech StackIn this case, I used React JS, react-query, wagmi.sh to connect the wallet, and Tatum’s API key. You can find the code in my GitHub repository.Goals we want to achieveIn this case, we’ll show the NFTs of a specific col...]]></description>
            <content:encoded><![CDATA[<p>While coding to enter a hackathon, I had to use Tatum’s API since it was one of the sponsors there, although I had used Tatum before, this time I reached a new level, using the API to build an NFT gallery, with just a few other tools, and I’d like to share it with you.</p><h2 id="h-tech-stack" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Tech Stack</h2><p>In this case, I used React JS, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tanstack.com/query/v4/?from=reactQueryV3&amp;original=https://react-query-v3.tanstack.com/">react-query</a>, <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://wagmi.sh">wagmi.sh</a> to connect the wallet, and <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tatum.io/">Tatum’s API key</a>. You can find the code in my <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://github.com/PovedaAqui/bookverse">GitHub repository</a>.</p><h2 id="h-goals-we-want-to-achieve" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Goals we want to achieve</h2><p>In this case, we’ll show the NFTs of a specific collection that an address hold. We’ll need to do three consecutive API calls using Tatum to get it done.</p><ul><li><p>Get the total token balance.</p></li><li><p>Filter by collection (contract).</p></li><li><p>Get the metadata.</p></li><li><p>Show the NFTs.</p></li></ul><h2 id="h-lets-begin" class="text-3xl font-header !mt-8 !mb-4 first:!mt-0 first:!mb-0">Let’s begin</h2><p>First of all, you need to connect your wallet, I’m using wagmi.sh which is a powerful open-source library for React, I’ll teach you how to use it in another post, meanwhile you can try using the official docs on their site.</p><p>Once you have your wallet connected, you need to get the balance of the tokens you hold and <strong>filter the result to get the data you need directly from the call</strong>.</p><p>To make this first call, you can use <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://apidoc.tatum.io/tag/Multi-Tokens-(ERC-1155-or-compatible)/#operation/MultiTokenGetAddressBalance">this Tatum’s endpoint</a>, as you can see in the code below.</p><pre data-type="codeBlock" text="const fetchBalance = async () =&gt; {
        const res = await fetch(`https://api-eu1.tatum.io/v3/multitoken/address/balance/${chain}/${address}`, {
            &quot;method&quot;: &quot;GET&quot;,
            &quot;headers&quot;: {
                &quot;Content-Type&quot;: &quot;application/json&quot;,
                &quot;x-api-key&quot;: process.env.REACT_APP_TATUM
                }
            }
        )
        try {
            const result = await res.json();
            const resultFiltered = result.find(element =&gt; element?.contractAddress?.toLowerCase() === nftContract.toLowerCase());
            const resultBalances = resultFiltered.balances.map(ids =&gt; ids.tokenId)
            return resultBalances;
        } catch (error) {
            console.log(error);
        }
};

//First call
const { data: balance } = useQuery({ queryKey: [&apos;nfts&apos;], queryFn: fetchBalance});
"><code>const fetchBalance <span class="hljs-operator">=</span> async () <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
        const res <span class="hljs-operator">=</span> await fetch(`https:<span class="hljs-comment">//api-eu1.tatum.io/v3/multitoken/address/balance/${chain}/${address}`, {</span>
            <span class="hljs-string">"method"</span>: <span class="hljs-string">"GET"</span>,
            <span class="hljs-string">"headers"</span>: {
                <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
                <span class="hljs-string">"x-api-key"</span>: process.env.REACT_APP_TATUM
                }
            }
        )
        <span class="hljs-keyword">try</span> {
            const result <span class="hljs-operator">=</span> await res.json();
            const resultFiltered <span class="hljs-operator">=</span> result.find(element <span class="hljs-operator">=</span><span class="hljs-operator">></span> element?.contractAddress?.toLowerCase() <span class="hljs-operator">=</span><span class="hljs-operator">=</span><span class="hljs-operator">=</span> nftContract.toLowerCase());
            const resultBalances <span class="hljs-operator">=</span> resultFiltered.balances.map(ids <span class="hljs-operator">=</span><span class="hljs-operator">></span> ids.tokenId)
            <span class="hljs-keyword">return</span> resultBalances;
        } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
            console.log(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
        }
};

<span class="hljs-comment">//First call</span>
const { data: balance } <span class="hljs-operator">=</span> useQuery({ queryKey: [<span class="hljs-string">'nfts'</span>], queryFn: fetchBalance});
</code></pre><p>After that, you’ll get a list of the tokens you hold, something like <code>[0, 1, 20, 400, 123]</code>. I recommend you use <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://tanstack.com/query/v4/docs/devtools">ReactQueryDevtools</a> to see the data you’re fetching directly in your browser.</p><p>Once you have the balance and you’ve filtered it by collection (contract), you want to make a second and <strong>dependent</strong> query, to get the metadata of every token you find in the previous call. To do that, you can use <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://apidoc.tatum.io/tag/Multi-Tokens-(ERC-1155-or-compatible)#operation/MultiTokenGetMetadata">this Tatum’s endpoint</a>, as you can see below.</p><pre data-type="codeBlock" text="const fetchMetadata = async (ids) =&gt; {
        const res = await fetch(`https://api-eu1.tatum.io/v3/multitoken/metadata/${chain}/${nftContract}/${ids}`,    {
            &quot;method&quot;: &quot;GET&quot;,
            &quot;headers&quot;: {
                &quot;Content-Type&quot;: &quot;application/json&quot;,
                &quot;x-api-key&quot;: process.env.REACT_APP_TATUM
                }
            }
        )
        try {
            const result = await res.json();
            return result;
        } catch (error) {
            console.log(error);
        }
};

//Second call
const { data: tokenId } = useQuery({ queryKey: [&apos;tokenId&apos;], queryFn: () =&gt; Promise.all(balance.map(ids =&gt; fetchMetadata(ids))), enabled: !!balance });
"><code>const fetchMetadata <span class="hljs-operator">=</span> async (ids) <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
        const res <span class="hljs-operator">=</span> await fetch(`https:<span class="hljs-comment">//api-eu1.tatum.io/v3/multitoken/metadata/${chain}/${nftContract}/${ids}`,    {</span>
            <span class="hljs-string">"method"</span>: <span class="hljs-string">"GET"</span>,
            <span class="hljs-string">"headers"</span>: {
                <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
                <span class="hljs-string">"x-api-key"</span>: process.env.REACT_APP_TATUM
                }
            }
        )
        <span class="hljs-keyword">try</span> {
            const result <span class="hljs-operator">=</span> await res.json();
            <span class="hljs-keyword">return</span> result;
        } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
            console.log(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
        }
};

<span class="hljs-comment">//Second call</span>
const { data: tokenId } <span class="hljs-operator">=</span> useQuery({ queryKey: [<span class="hljs-string">'tokenId'</span>], queryFn: () <span class="hljs-operator">=</span><span class="hljs-operator">></span> Promise.all(balance.map(ids <span class="hljs-operator">=</span><span class="hljs-operator">></span> fetchMetadata(ids))), enabled: <span class="hljs-operator">!</span><span class="hljs-operator">!</span>balance });
</code></pre><p>The last call is very similar to the second one, another <strong>dependent query</strong>, but, this time, you need to resolve the IPFS CID you got in the previous one to see the entire metadata information, and finally, show it to the user.</p><p>In this case, I decided to add a proxy to resolve the CID, but you can find a ton of ways to do the same thing, some of them could be better than the one I’m using, feel free to contribute to the code, I’d be very grateful.</p><pre data-type="codeBlock" text="const fetchIPFS = async (ids) =&gt; {
        let url = &quot;&quot;;
        if (ids.data.includes(&quot;ipfs://&quot;)) {
            url = ids.data.replace(&quot;ipfs://&quot;, &quot;https://nftstorage.link/ipfs/&quot;);
        }
        const res = await fetch(`${url}`, {
            &quot;method&quot;: &quot;GET&quot;,
            &quot;headers&quot;: {
                &quot;Content-Type&quot;: &quot;application/json&quot;,
                }
            }
        )
        try {
            const result = await res.json();
            return result;
        } catch (error) {
            console.log(error);
        }
};

//Third call
const { data: ipfs } = useQuery({ queryKey: [&apos;ipfs&apos;], queryFn: () =&gt; Promise.all(tokenId.map(ids =&gt; fetchIPFS(ids))), enabled: !!tokenId });
"><code>const fetchIPFS <span class="hljs-operator">=</span> async (ids) <span class="hljs-operator">=</span><span class="hljs-operator">></span> {
        let url <span class="hljs-operator">=</span> <span class="hljs-string">""</span>;
        <span class="hljs-keyword">if</span> (ids.data.includes(<span class="hljs-string">"ipfs://"</span>)) {
            url <span class="hljs-operator">=</span> ids.data.replace(<span class="hljs-string">"ipfs://"</span>, <span class="hljs-string">"https://nftstorage.link/ipfs/"</span>);
        }
        const res <span class="hljs-operator">=</span> await fetch(`${url}`, {
            <span class="hljs-string">"method"</span>: <span class="hljs-string">"GET"</span>,
            <span class="hljs-string">"headers"</span>: {
                <span class="hljs-string">"Content-Type"</span>: <span class="hljs-string">"application/json"</span>,
                }
            }
        )
        <span class="hljs-keyword">try</span> {
            const result <span class="hljs-operator">=</span> await res.json();
            <span class="hljs-keyword">return</span> result;
        } <span class="hljs-keyword">catch</span> (<span class="hljs-function"><span class="hljs-keyword">error</span>) </span>{
            console.log(<span class="hljs-function"><span class="hljs-keyword">error</span>)</span>;
        }
};

<span class="hljs-comment">//Third call</span>
const { data: ipfs } <span class="hljs-operator">=</span> useQuery({ queryKey: [<span class="hljs-string">'ipfs'</span>], queryFn: () <span class="hljs-operator">=</span><span class="hljs-operator">></span> Promise.all(tokenId.map(ids <span class="hljs-operator">=</span><span class="hljs-operator">></span> fetchIPFS(ids))), enabled: <span class="hljs-operator">!</span><span class="hljs-operator">!</span>tokenId });
</code></pre><p>Now, just build a Card component (or reuse one from a library like TailwindCSS or MUI) is pending, I let it to your imagination. I hope it’ll be helpful in your journey. Happy code!</p>]]></content:encoded>
            <author>luispoveda@newsletter.paragraph.com (luispoveda.eth 🌻)</author>
        </item>
        <item>
            <title><![CDATA[It's not a garage, it's Moondance Diner]]></title>
            <link>https://paragraph.com/@luispoveda/it-s-not-a-garage-it-s-moondance-diner</link>
            <guid>NiJlmSziqviOYhnL306y</guid>
            <pubDate>Sat, 05 Feb 2022 00:38:05 GMT</pubDate>
            <description><![CDATA[They’ve said to us, there was a garage, they had nothing but the idea, the dawn, the midnight, and of course, the sunrise. It was very strong work, really strong, and just that. But you know, we know, there was an Ivy League School, a heritage, a mother, a father’s loan, blood diamonds… We did see some of them in our hard night shift at Moondance Diner. And, the next day, in the morning, we coded, designed, dreamed, did the math, and the moon is smiling at us. This time isn’t about them, this...]]></description>
            <content:encoded><![CDATA[<p>They’ve said to us, there was a garage, they had nothing but the idea, the dawn, the midnight, and of course, the sunrise. It was very strong work, really strong, and just that.</p><p>But you know, we know, there was an Ivy League School, a heritage, a mother, a father’s loan, blood diamonds… We did see some of them in our hard night shift at Moondance Diner.</p><p>And, the next day, in the morning, we coded, designed, dreamed, did the math, and the moon is smiling at us.</p><p>This time isn’t about them, this time is about us, the people, we who dream while we are working, at Moondance Diner.</p>]]></content:encoded>
            <author>luispoveda@newsletter.paragraph.com (luispoveda.eth 🌻)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/64725d5b2a570ea6477382c82d2eb59094103615954465b5a32340b626a926fa.jpg" length="0" type="image/jpg"/>
        </item>
        <item>
            <title><![CDATA[It’s time to bring eBooks into web3]]></title>
            <link>https://paragraph.com/@luispoveda/it-s-time-to-bring-ebooks-into-web3</link>
            <guid>XZdCXKrdhpsHLi5KPgM2</guid>
            <pubDate>Mon, 03 Jan 2022 21:31:04 GMT</pubDate>
            <description><![CDATA[More than 10 years have passed since Amazon’s eBooks Store was launched. It was a game-changer for the whole publishing market, perhaps only comparable to what iTunes was for the music industry. Since then, tens of billions of eBooks have been sold, with Kindle leading the digital race. 2020 was a new all-time high in the eBooks market. eBooks sales in the U.S. alone reached $1.1 billion, up by 18.4% compared to the previous year. According to statista.com, revenue in the eBooks segment is ex...]]></description>
            <content:encoded><![CDATA[<p>More than 10 years have passed since Amazon’s eBooks Store was launched. It was a game-changer for the whole publishing market, perhaps only comparable to what iTunes was for the music industry. Since then, tens of billions of eBooks have been sold, with Kindle leading the digital race.</p><p>2020 was a new all-time high in the eBooks market. eBooks sales in the U.S. alone reached  $1.1 billion, up by 18.4% compared to the previous year. <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="https://www.statista.com/outlook/dmo/digital-media/epublishing/ebooks/united-states">According to <em>statista.com</em>, revenue in the eBooks segment is expected to show an annual growth rate of 2.35% up to 2026</a>.</p><p>Apart from the financial data, a lot of us have enjoyed reading some of the most beautiful stories out there. Everything! from a great variety of authors and categories to novels, finance, and politics. Some of those stories have even changed us forever.</p><p>Despite the good taste we could have from eBooks, especially from Kindle, some things are just missing. For example, what happens when you want to share your most recent reading with a friend? What if you want to resell your oldest ones? Have you tried to download your eBooks to read them using another reader? These problems and others have been ringing in my mind.</p><p>When I went down the rabbit hole, I found in web3 the answer for many of those problems, problems that I also have. Since then, I stopped buying eBooks because it doesn’t make sense to me anymore. That’s when bookverse was born.</p><p>Bookverse is a project that wants to scale eBooks to a new level, integrating the web3 advantages to it. The possibilities are just limited by our imagination, but I’d like to share some of them:</p><p>For users:</p><ul><li><p>You’ll be able to resell your eBooks or share them for free with other users.</p></li><li><p>You could get limited, collectable and rare editions of your favourite books.</p></li><li><p>You could get an autographed book from your favourite author, backed by blockchain technology.</p></li><li><p>Your favourite book could be your key to DeFi, using your book as collateral.</p></li></ul><p>For authors and creators:</p><ul><li><p>You’ll get a considerable major income for any book you sell.</p></li><li><p>You’ll get a benefit for any book that is resold, forever, backed by public and audited smart contracts.</p></li><li><p>You’ll be able to shorten the distance between you and your community.</p></li><li><p>You’ll be able to launch rare or special editions of your books in seconds.</p></li><li><p>New ways to fund your incoming launches, even before they are written.</p></li></ul><p>If you want to know more, visit our site <a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://bookversexyz.com">bookversexyz.com</a>, and we’ll be grateful if you leave your email there to be part of the community.</p><p><a target="_blank" rel="noopener noreferrer nofollow ugc" class="dont-break-out" href="http://bookversexyz.com/">http://bookversexyz.com/</a></p>]]></content:encoded>
            <author>luispoveda@newsletter.paragraph.com (luispoveda.eth 🌻)</author>
            <enclosure url="https://storage.googleapis.com/papyrus_images/fc00d9c787d5f81ae357ce4db33e6377a2a180740ce44215518b14005f242f1e.png" length="0" type="image/png"/>
        </item>
    </channel>
</rss>