The NFT Tech Stack to Decentralize your NFT and Token-Gated Projects

The NFT Tech Stack for Decentralized Web3 Development

How to Integrate Portal RPC, Storj DCS, and The Graph’s Indexer Data for decentralized Web3 development.

In this tutorial, we will guide you through the process of integrating Portal RPC, Storj DCS, and The Graph’s Indexer Data to decentralized your Web3 development. These integrations enable you to store and retrieve data from Storj, query and index data using The Graph, and power your NFT drop or token-gated experience through Portal’s RPC access. 

Want to learn more about the power of choosing  the right “infrastructure Legos” to power your NFT projects and Web3 development? Make sure to check out our study on decentralized Web3 development as well.

Table of Contents

A – Upload your first NFT object using Storj Decentralized Cloud Storage

First, make sure you have the necessary prerequisites by following this guide.

[Note: You can check back with the Storj docs as the “source of truth” for any step along this tutorial.]

Step 1. Create an account

Go to, and start for free.

Step 2. Download and install the binary for your OS

  • Windows

Download the Windows Uplink Binary zip file

In the Downloads folder, right-click and select “Extract all”

Decentralized Web3 development with Storj.

Extract to your Users folder (“Alexey” in this example):

Decentralized Web3 development with Storj.
  • Linux:


Curl Download

curl -L <> -o
unzip -o
sudo install uplink /usr/local/bin/uplink

Direct Download

 Linux AMD64 Uplink Binary


Curl Download

curl -L <> -o
unzip -o
sudo install uplink /usr/local/bin/uplink

Direct Download

Linux ARM Uplink Binary


Curl Download

curl -L <> -o
unzip -o
sudo install uplink /usr/local/bin/uplink

Direct Download

Linux ARM64 Uplink Binary

  • macOS

Curl Download

curl -L <> -o
unzip -o
sudo install uplink /usr/local/bin/uplink

Direct Download

macOS Uplink Binary

Step 3. Create your first access grant

An Access Grant is a set of permissions and credentials that allows users to securely access their data stored on the Storj network. To create an Access Grant, follow these steps:

(Note: to complete this step, you need to have a satellite account (from Step 1) and install Uplink CLI as described in Uplink CLI (from Step 2).)

Navigate to the Access page within your project, and click on Create Access Grant. A modal window will pop up, where you should enter a name for this access grant.

Decentralized Web3 development with Storj.
Decentralized Web3 development with Storj.

If you click Encrypt My Access, the client-side script will finalize your access grant with your encryption passphrase. Your data will remain end-to-end encrypted until you explicitly register your access grant with AWS CLI and Hosted Gateway MT for S3 compatibility. Only then will your access grant be shared with Storj servers. Storj does not know or store your encryption passphrase.

However, if you are still reluctant to enter your passphrase into the web application, you should cancel creation of Access Grant in Web UI, select Create Keys for CLI, and follow these instructions to create an Access Grant in CLI.

⚠️ The instructions below assume you selected “Encrypt My Access.

Assign the permissions you want this access grant to have, then click on Encrypt My Access:

Select a Passphrase type: Either Enter your own Encryption Passphrase or Generate a 12-Word Mnemonic Passphrase. Make sure you save your encryption passphrase, as you’ll not be able to reset this after it’s created.

Enter the Encryption Passphrase you used for your other access grants. If this is your first access grant, we strongly encourage you to use a mnemonic phrase as your encryption passphrase (the GUI automatically generates one on the client-side for you).

This passphrase is important! Encryption keys derived from it are used to encrypt your data at rest, and your data will have to be re-uploaded if you want it to change!

Importantly, if you want two access grants to have access to the same data, they must use the same passphrase. You won’t be able to access your data if the passphrase in your access grant is different than the passphrase you uploaded the data with.

Please note that Storj does not know or store your encryption passphrase, so if you lose it, you will not be able to recover your files.

Click on either the Copy to clipboard link or Download .txt, and then confirm that you copied your Encryption Phrase to a safe place.

Click the Create my Access link to finish generating the Access Grant.

The Access Grant is now generated. The Access Grant will only display once. Save this information in a password manager or wherever you prefer to store sensitive information.

[See more info on this step here.]

  1. Save the Create an Access Grant to a file. The Access Grant that you created in the web interface (or Create Access Grant in CLI) needs to be saved to disk in a plain text file for simplicity (for example – Mac terminal would not allow you to paste the whole access grant directly due to terminal limitations). Specify the path to the saved access grant in the following command (~/Downloads/accessgrant.txt for example).
  2. Import Access Grant.

[See more info on this step here.]

Step 5. Create a bucket in your project

Let’s create a bucket to store photos of cake for our “food app” project.


./uplink.exe mb sj://cakes


uplink mb sj://cakes


uplink mb sj://cakes

[See more info on this step here.]

Step 6. Upload an NFT object

The NFT Object we’ll upload:

Right-click and save as cheesecake.jpg to your Desktop:

Upload our NFT object: To upload our photo, let’s use the copy command.


./uplink.exe cp ~/Desktop/cheesecake.jpg sj://cakes


uplink cp ~/Desktop/cheesecake.jpg sj://cakes


uplink cp ~/Desktop/cheesecake.jpg sj://cakes

[See more info on this step here.]

Step 7. View the distribution of an NFT object

You can view the geographic distribution of your NFT object and generate a shareable URL via the Link Sharing Service. Run the uplink share –url command below. See share command for specifications on how to select an auth region and restrict the uplink share –url command:


./uplink.exe share --url --not-after=+2h sj://cakes/cheesecake.jpg


uplink share --url --not-after=+2h sj://cakes/cheesecake.jpg


uplink share --url --not-after=+2h sj://cakes/cheesecake.jpg

Copy the URL that is returned by the uplink share –url command, and paste into your browser window.

=========== ACCESS RESTRICTIONS ==========================================================
Download  : Allowed
Upload    : Disallowed
Lists     : Allowed
Deletes   : Disallowed
NotBefore : No restriction
NotAfter  : 2022-03-01 09:56:13
Paths     : sj://cakes/cheesecake.jpg
Access    : 1Dv4...
========== CREDENTIALS ===================================================================
Access Key ID: jvw3fmzqyg2cvxm27qishw6y4qka
Secret Key   : ...
Endpoint     : [<>](<>)
Public Access:  true
=========== BROWSER URL ==================================================================
REMINDER  : Object key must end in '/' when trying to share recursively
URL       : [<>](<>)

This is a real distribution of your file’s pieces that you uploaded to the network. You can share this file with anyone you’d like.

[See more info on this step here.]

You’ve just decentralized the storage of your NFT, reducing the risk of data loss and vulnerabilities and boosting privacy, cost-efficiency, and scalability with your Web3 development. Next up: enable your front-end project to query and index data from the blockchain.

B – Initialize, create, and deploy your subgraph with The Graph:

Follow the quick-start guide from The Graph to initialize, create, and deploy your subgraph.

Ensure that your subgraph will be indexing NFT data from one of the supported networks.

[Note: You can check back with The Graph’s docs as the “source of truth” for any step along this tutorial.]

Step 8. Install the Graph CLI

The Graph CLI is written in JavaScript and you will need to have either npm or yarn installed to use it.

# NPM$ npm install -g @graphprotocol/graph-cli
# Yarn$ yarn global add @graphprotocol/graph-cli

Step 9. Initialize your Subgraph

  • Initialize your subgraph from an existing contract.

Not sure how to deploy an NFT contract? Here’s a super simple standard NFT contract deployment with Remix.

graph init --studio <SUBGRAPH_SLUG>

  • Your subgraph slug is an identifier for your subgraph. The CLI tool will walk you through the steps for creating a subgraph, such as contract address, network, etc as you can see in the screenshot below.

Note: Consider adding –index-events to the command above to save time. It bootstraps the subgraph with entities in the schema and simple mappings for each emitted event. (In newer versions of graph-cli, this option is presented during initialization as default. It’s highly recommended to use it, especially for beginners.)

Step 10. Write your Subgraph

The previous commands create a scaffold subgraph that you can use as a starting point for building your subgraph. When making changes to the subgraph, you will mainly work with three files:

  • Manifest (subgraph.yaml) – The manifest defines what NFT data sources your subgraphs will index.
  • Schema (schema.graphql) – The GraphQL schema defines what NFT data you wish to retrieve from the subgraph.
  • AssemblyScript Mappings (mapping.ts) – This is the code that translates data from your NFT data sources to the entities defined in the schema.

[Note: if you’re looking for a template to use as an example, you can see a generic NFT (ERC721) subgraph here.]

For more information on how to write your subgraph, see Creating a Subgraph.

Step 11. Deploy to the Subgraph Studio

  • Go to the Subgraph Studio and connect your wallet.
  • Click “Create” and enter the subgraph slug you used in step 2.
  • Run these commands in the subgraph folder

$ graph codegen
$ graph build

  • Authenticate and deploy your subgraph. The deploy key can be found on the Subgraph page in Subgraph Studio.

$ graph auth --studio <DEPLOY_KEY>
$ graph deploy --studio <SUBGRAPH_SLUG>

  • You will be asked for a version label. It’s strongly recommended to use the following conventions for naming your versions. Example: 0.0.1, v1, version1

Step 12. Check your logs

Now we can go to<SUBGRAPH _SLUG>/logs to check if the subgraph is properly syncing.

Step 13. Query your subgraph

You can now query your subgraph by following these instructions. You can query from your dApp if you don’t have your API key via the free, rate-limited temporary query URL that can be used for development and staging. Read the additional instructions for how to query a subgraph from a frontend application here.

With the subgraph deployed, visit the Graph Explorer to open up a GraphiQL interface where you can explore the deployed GraphQL API for the subgraph by issuing queries and viewing the schema.

An example is provided below, but please see the Query API for a complete reference on how to query the subgraph’s entities.


This query lists all the counters our mapping has created. Since we only create one, the result will only contain our one default-counter:

  counters {

Step 14. Publishing a Subgraph

After deploying and testing your subgraph in the Subgraph Studio, you can proceed to publish it on the decentralized network. This makes it accessible for Curators to curate and Indexers to index. To watch a walkthrough on how to publish a subgraph, see this video.

To publish a subgraph directly from the Subgraph Studio dashboard, simply click the Publish button. Your subgraph will then be visible in the Graph Explorer. (Note that it can index data from any supported network, regardless of where it was published.)

The same rules apply when publishing a new version of an existing subgraph. For guidance on creating your subgraph, refer to the Publishing a Subgraph to the Decentralized Network documentation.

For more information on how to write your subgraph, see Publishing a Subgraph to the Decentralized Network.

Step 15. Using The Graph Explorer

Each subgraph published to the decentralized Graph Network has a unique query URL that you can find by navigating to the subgraph details page and clicking on the “Query” button on the top right corner. This will open a side pane that will give you the unique query URL of the subgraph as well as some instructions about how to query it.

As you can notice, this query URL must use a unique API key. You can create and manage your API keys in the Subgraph Studio in the “API Keys” section. Learn more about how to use Subgraph Studio here.

Querying subgraphs using your API keys will generate query fees that will be paid in GRT. You can learn more about billing here.

You can also use the GraphQL playground in the “Playground” tab to query a subgraph within The Graph Explorer.

Now you’re set up to query all the data needed for your NFT project, giving you efficient, simple, and optimized data access to complement your Web3 development. And in the previous steps, you’ve decentralized the storage. Now, it’s time to let your users interact from your frontend directly to a blockchain using decentralized RPC service.

C – Use Portal to create a Pocket Network RPC endpoint and plug it into your application

Follow this step-by-step tutorial to create an RPC endpoint and integrate it into your application using the Portal.

[Note: You can check back with the Pocket docs as the “source of truth” for any step along this tutorial.]

Prerequisites to Build a Token-Gated Experience on Pocket Network

The Portal account will allow you to set up an application and an endpoint – these credentials will be used in the steps below. It’s easy to set up your own private endpoint – ust head over to the Portal and:

  • Sign up for an account
  • Create a new application and give it a name
  • Select from dozens of supported chains and get your own private endpoint
  • Fine tune your whitelists and usage notifications
  • Start having RPC relays serviced by Pocket nodes!

You can also check out a video walkthrough of minting an endpoint in the Portal.

After these steps, you’ll be set up with your own application and private endpoint(s), and be ready to progress through the rest of the tutorial and learn how to build a NFT project. If you want to dig into pocket-core (the official implementation of the Pocket Network protocol) and learn more about the SDKs for interacting with Pocket in more detail, head to the Pocket Network GitHub and SDK Docs.

Step 16. Set up your project

First, create a new directory for your project and navigate to it in your terminal. Then, initialize a new Node.js project by running the following command:

npm init

Follow the prompts to set up your project and install the necessary dependencies:

npm install --save web3 pocket-js

The web3 package will allow you to interact with Pocket Network, while the pocket-js package provides you with monitoring tools to track the performance of your dApp.

View the web3.js Docs.

Step 17. Connect to Pocket Network

Next, we need to connect to Pocket Network using our account credentials. In your index.js file, add the following code:

const Pocket = require('pocket-js')
const Web3 = require('web3')

const pocket = new Pocket([
    "rpcUrl": "<>",
    "pocketAAT": {
      "version": "0.0.1",
      "clientPublicKey": "<YOUR CLIENT PUBLIC KEY HERE>",
      "applicationPublicKey": "<YOUR APP PUBLIC KEY HERE>",
      "applicationSignature": "<YOUR APP SIGNATURE HERE>"

const web3 = new Web3(pocket)

Replace the placeholders in the pocketAAT object with your actual Pocket Network credentials. This code creates a new Pocket object and a new Web3 object, which we will use to interact with the network.

Step 18. Interact with the network

Now that we’re connected to Pocket Network, we can make requests for data. For example, let’s estimate the gas for a transaction:

import requests

url = ""

payload = {
    "jsonrpc": "2.0",
    "method": "eth_estimateGas",
    "params": [
            "to": "0xd46e8dd67c5d32be8d46e8dd67c5d32be8058bb8eb970870f072445675058bb8eb970870f072445675",
            "from": "0xA69babEF1cA67A37Ffaf7a485DfFF3382056e78C"
    "id": 0
headers = {"Content-Type": "application/json"}

response = requests.request("POST", url, json=payload, headers=headers)


Replace “YourPortalIDHere” and addresses with the appropriate information. This code generates and returns an estimate of how much gas is necessary to allow the transaction to complete.

Step 19. Monitor network performance

Finally, let’s use Pocket Network’s monitoring tools to track the performance of our NFT dApp. Add the following code to your index.js file:

pocket.getStats((err, result) => {
  if (err) {
  } else {
    console.log(`Network stats: ${JSON.stringify(result)}`)

This code retrieves the current network statistics and logs them to the console.

Step 20. Run your NFT dApp

To run your NFT dApp, simply run the following command in your terminal:

node index.js

You should see the balance of the Ethereum address and the network statistics logged to your console.

Your Decentralized Foundation

Integrating Portal RPC, Storj DCS, and The Graph’s Indexer Data provides a powerful foundation for developing NFT projects and decentralizing your Web3 development. By following the steps outlined in this guide, you can leverage these technologies to create secure, scalable, and efficient applications.

If you have any questions about these technologies or need assistance with implementation, please don’t hesitate to reach out to our solutions team. Alternatively, you can join our developer community on Discord to connect with other developers and share your Web3 development experiences.

Thank you for choosing these cutting-edge Web3 development technologies for your NFT dApp development needs!