TypeScript SDKGuides

Uploading a File

Learn how to upload a file to the Shelby network from a Browser environment

Prerequisites

This guide demonstrates how to upload files to the Shelby network from a browser environment. Before proceeding, ensure you have:

  • A basic understanding of React and TypeScript
  • An Aptos wallet configured for the Shelby network
  • ShelbyUSD tokens for file uploads (1 ShelbyUSD per upload)

Environment Setup

To integrate with Aptos wallets, this guide uses the Aptos Wallet Adapter package. Follow these steps to configure your environment:

Install the Wallet Adapter Package

Install the required wallet adapter dependency:

npm install @aptos-labs/wallet-adapter-react

Configure the Wallet Provider

Initialize the AptosWalletAdapterProvider in your application:

import { AptosWalletAdapterProvider } from "@aptos-labs/wallet-adapter-react";
import { PropsWithChildren } from "react";
import { Network } from "@aptos-labs/ts-sdk";

export const WalletProvider = ({ children }: PropsWithChildren) => {
return (
  <AptosWalletAdapterProvider
    autoConnect={true}
    dappConfig={{
      network: Network.TESTNET,
      aptosApiKeys: {
        testnet: process.env.TESTNET_API_KEY
      }
    }}
    onError={(error) => {
      console.log("Wallet connection error:", error);
    }}
  >
    {children}
  </AptosWalletAdapterProvider>
);
};

File Upload Process

Uploading a file to the Shelby network involves three sequential steps:

  1. File Encoding: Split the file into chunks and generate commitment hashes
  2. On-Chain Registration: Submit a transaction to register the file metadata
  3. RPC Upload: Upload the actual file data to Shelby storage providers

Step 1: File Encoding

File encoding involves splitting the file into chunks, generating commitment hashes for each chunk, and creating a blob merkle root hash. These hashes are used for verification with storage providers.

import {
  type BlobCommitments,
  createDefaultErasureCodingProvider,
  generateCommitments,
} from "@shelby-protocol/sdk/browser";

export const encodeFile = async (file: File): Promise<BlobCommitments> => {
  // Convert file to Buffer format
  const data = Buffer.isBuffer(file)
    ? file
    : Buffer.from(await file.arrayBuffer());

  // Create the erasure coding provider
  const provider = await createDefaultErasureCodingProvider();

  // Generate commitment hashes for the file
  const commitments = await generateCommitments(provider, data);

  return commitments;
};

Step 2: On-Chain Registration

Before uploading, ensure your account is funded:

  1. APT tokens: Fund your account with testnet APT through the Aptos Testnet Faucet.
  2. ShelbyUSD tokens: Sign up for early access through the Shelby Discord to receive testnet ShelbyUSD tokens.

Register the file metadata on the Aptos blockchain by creating and submitting a transaction:

import {
  expectedTotalChunksets,
  ShelbyBlobClient,
} from "@shelby-protocol/sdk/browser";

// Create the registration transaction payload
const payload = ShelbyBlobClient.createRegisterBlobPayload({
  account: account.address,
  blobName: file.name,
  blobMerkleRoot: commitments.blob_merkle_root,
  numChunksets: expectedTotalChunksets(commitments.raw_data_size),
  expirationMicros: (1000 * 60 * 60 * 24 * 30 + Date.now()) * 1000, // 30 days from now
  blobSize: commitments.raw_data_size,
});

Submit the transaction using the wallet adapter:

Ensure your wallet is configured for Aptos Testnet.

In addition, to upload a file, you will need your account to have two assets:

  • APT tokens: Used to pay for gas fees when sending transactions
  • ShelbyUSD tokens: Used to pay for uploading the file to the Shelby network
  1. APT tokens: Fund your account with testnet APT through the Aptos Testnet Faucet.
  2. ShelbyUSD tokens: Sign up for early access through the Shelby Discord to receive testnet ShelbyUSD tokens.

Submit the previously created register blob payload with the wallet

import { Aptos, AptosConfig, Network } from "@aptos-labs/ts-sdk";
import {
  type InputTransactionData,
  useWallet,
} from "@aptos-labs/wallet-adapter-react";

const { signAndSubmitTransaction } = useWallet();

// Submit the registration transaction
const transaction: InputTransactionData = {
  data: payload,
};

const transactionSubmitted = await signAndSubmitTransaction(transaction);

// Initialize Aptos client
export const aptosClient = new Aptos(
  new AptosConfig({
    network: Network.TESTNET,
    clientConfig: {
      API_KEY: process.env.APTOS_API_KEY,
    },
  }),
);

// Wait for transaction confirmation
await aptosClient.waitForTransaction({
  transactionHash: transactionSubmitted.hash,
});

Step 3: RPC Upload

After successful on-chain registration, upload the file data to the Shelby RPC. The RPC validates the file against the registered commitment hashes before accepting the upload.

Important: The RPC upload must occur after on-chain registration, as the RPC verifies the file's registration status before processing the upload.

import { ShelbyClient } from "@shelby-protocol/sdk/browser";
import { Network } from "@aptos-labs/ts-sdk";
import { useWallet } from "@aptos-labs/wallet-adapter-react";

const { account } = useWallet();

// Initialize Shelby client
const shelbyClient = new ShelbyClient({
  network: Network.TESTNET,
  apiKey: process.env.SHELBY_API_KEY,
});

// Upload file data to Shelby RPC
await shelbyClient.rpc.putBlob({
  account: account.address,
  blobName: file.name,
  blobData: new Uint8Array(await file.arrayBuffer()),
});

After successful upload, your file is stored on the Shelby network and can be retrieved using the download functionality.