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.SHELBYNET,
      aptosApiKeys: {
        shelbynet: process.env.SHELBYNET_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,
  ClayErasureCodingProvider,
  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());

  // Initialize the erasure coding provider
  const provider = await ClayErasureCodingProvider.create();

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

  return commitments;
};

Step 2: On-Chain Registration

Before uploading, ensure your account has sufficient ShelbyUSD tokens. Visit the Shelby faucet to fund your account if needed.

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 the Shelby network. Petra (and some other wallets) wallet lets you define a custom network, create one called shelbynet and use these settings:

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.SHELBYNET,
    clientConfig: {
      API_KEY: process.env.NEXT_PUBLIC_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.SHELBYNET,
  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.