Solana Kit

Upload a File

Learn how to upload files to Shelby from a Solana application

Uploading Files to Shelby

This guide walks you through uploading files to the Shelby Protocol using the Solana Kit SDK.

Complete Upload Example

Set Up the Client

import { Shelby, Network } from "@shelby-protocol/solana-kit/node";
import { Connection, Keypair } from "@solana/web3.js";

const connection = new Connection("https://api.devnet.solana.com");

const shelbyClient = new Shelby({
  network: Network.SHELBYNET,
  connection,
  apiKey: "AG-***",
});

Create a Storage Account

const solanaKeypair = Keypair.generate();
const domain = "my-awesome-dapp.com";

const storageAccount = shelbyClient.createStorageAccount(solanaKeypair, domain);

Fund the Account

// Fund with ShelbyUSD for storage fees
await shelbyClient.fundAccountWithShelbyUSD({
  address: storageAccount.accountAddress,
  amount: 1_000_000,
});

// Fund with APT for transaction fees
await shelbyClient.fundAccountWithAPT({
  address: storageAccount.accountAddress,
  amount: 1_000_000,
});

Upload the File

import * as fs from "fs";

// Read file from disk
const fileData = fs.readFileSync("./my-file.txt");
const blobData = new Uint8Array(fileData);

// Set expiration (1 day from now)
const expirationMicros = Date.now() * 1000 + 86400000000;

// Upload to Shelby
await shelbyClient.upload({
  blobData,
  signer: storageAccount,
  blobName: "my-file.txt",
  expirationMicros,
});

console.log("File uploaded successfully!");

Set Up the Hook

"use client";

import { useStorageAccount, Network } from "@shelby-protocol/solana-kit/react";
import { ShelbyClient } from "@shelby-protocol/sdk/browser";
import { useWallet } from "@solana/wallet-adapter-react";
import { useMemo, useState } from "react";

function FileUploader() {
  const { publicKey, signMessage, connected } = useWallet();
  const [status, setStatus] = useState("");

  const shelbyClient = useMemo(
    () =>
      new ShelbyClient({
        network: Network.SHELBYNET,
        apiKey: process.env.NEXT_PUBLIC_SHELBY_API_KEY!,
      }),
    []
  );

  const { storageAccountAddress, signAndSubmitTransaction } = useStorageAccount(
    {
      client: shelbyClient,
      solanaAddress: publicKey?.toBase58(),
      signMessageFn: signMessage,
    }
  );

  // ... continue in next step
}

Fund the Account (if needed)

const handleFund = async () => {
  if (!storageAccountAddress) return;

  // Fund with ShelbyUSD for storage fees
  await shelbyClient.fundAccountWithShelbyUSD({
    address: storageAccountAddress,
    amount: 1_000_000,
  });

  // Fund with APT for transaction fees
  await shelbyClient.fundAccountWithAPT({
    address: storageAccountAddress,
    amount: 1_000_000,
  });
};

Handle File Upload

import { useUploadBlobs } from "@shelby-protocol/react";

const { mutateAsync: uploadBlobs } = useUploadBlobs({
  client: shelbyClient,
});

const handleFileUpload = async (event: React.ChangeEvent<HTMLInputElement>) => {
  const file = event.target.files?.[0];
  if (!file || !storageAccountAddress) return;

  setStatus("Reading file...");
  const arrayBuffer = await file.arrayBuffer();
  const blobData = new Uint8Array(arrayBuffer);

  setStatus("Uploading to Shelby...");
  try {
    const expirationMicros = Date.now() * 1000 + 86400000000; // 1 day

    await uploadBlobs({
      signer: { account: storageAccountAddress, signAndSubmitTransaction },
      blobs: [
        {
          blobName: "example.txt",
          blobData,
        },
      ],
      expirationMicros,
    });

    setStatus("Upload complete!");
  } catch (error) {
    setStatus(`Error: ${error}`);
  }
};

Render the Component

return (
  <div>
    {!connected ? (
      <p>Please connect your wallet</p>
    ) : (
      <>
        <p>Storage Account: {storageAccountAddress?.toString()}</p>
        <input type="file" onChange={handleFileUpload} />
        <p>{status}</p>
      </>
    )}
  </div>
);

Next Steps

After uploading, learn how to retrieve your files: