Onchain Storage
Irys in the Browser
Overview
The Irys SDK minimizes dependency bloat by offering dedicated packages for each token. Installation statements, import code, and connection procedures vary based on the payment token and provider selection.
EVM Chains
When connecting from EVM chains, connection code differs based on token selection. The following examples use Ethereum with the WebEthereum class.
| Token | Class Name |
|---|---|
| Ethereum | WebEthereum |
| Polygon | WebMatic |
| Binance Coin | WebBNB |
| Avalanche C-Chain | WebAvalanche |
| Base Ethereum | WebBaseEth |
| USDC (Ethereum) | WebUSDCEth |
| Arbitrum | WebArbitrum |
| Chainlink | WebChainlink |
| USDC (Polygon) | WebUSDCPolygon |
| Berachain | WebBera |
| Scroll Ethereum | WebScrollEth |
| Linea Ethereum | WebLineaEth |
| IoTeX | WebIotex |
Ethers v5
Installation:
npm install \
@irys/web-upload \
@irys/web-upload-ethereum \
ethers@5Importing and configuring:
import { WebUploader } from "@irys/web-upload";
import { WebEthereum } from "@irys/web-upload-ethereum";
const getIrysUploader = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const irysUploader = await WebUploader(WebEthereum).withProvider(provider);
return irysUploader;
};Ethers v6
Installation:
npm install \
@irys/web-upload \
@irys/web-upload-ethereum \
@irys/web-upload-ethereum-ethers-v6 \
ethers@6Importing and configuring:
import { WebUploader } from "@irys/web-upload";
import { WebEthereum } from "@irys/web-upload-ethereum";
import { EthersV6Adapter } from "@irys/web-upload-ethereum-ethers-v6";
import { ethers } from "ethers";
const getIrysUploader = async () => {
const provider = new ethers.BrowserProvider(window.ethereum);
const irysUploader = await WebUploader(WebEthereum).withAdapter(EthersV6Adapter(provider));
return irysUploader;
};Viem v2
Installation:
npm install \
@irys/web-upload \
@irys/web-upload-ethereum \
@irys/web-upload-ethereum-viem-v2 \
viemImporting and configuring:
import { WebUploader } from "@irys/web-upload";
import { WebEthereum } from "@irys/web-upload-ethereum";
import { ViemV2Adapter } from "@irys/web-upload-ethereum-viem-v2";
const getIrysUploader = async () => {
const [account] = await window.ethereum.request({ method: "eth_requestAccounts" });
const provider = createWalletClient({
account,
chain: sepolia,
transport: custom(window.ethereum),
});
const publicClient = createPublicClient({
chain: sepolia,
transport: custom(window.ethereum),
});
const irysUploader = await WebUploader(WebEthereum).withAdapter(ViemV2Adapter(provider, { publicClient }));
return irysUploader;
};Solana
Installation:
npm install \
@irys/web-upload \
@irys/web-upload-solana \
@solana/wallet-adapter-base \
@solana/wallet-adapter-react \
@solana/wallet-adapter-react-ui \
@solana/wallet-adapter-wallets \
@solana/web3.jsClientProviders Setup
Create a top-level file named ClientProviders.tsx:
"use client";
import { ReactNode, useMemo } from "react";
import { ConnectionProvider, WalletProvider } from "@solana/wallet-adapter-react";
import { WalletAdapterNetwork } from "@solana/wallet-adapter-base";
import { UnsafeBurnerWalletAdapter } from "@solana/wallet-adapter-wallets";
import { WalletModalProvider } from "@solana/wallet-adapter-react-ui";
import { clusterApiUrl } from "@solana/web3.js";
require("@solana/wallet-adapter-react-ui/styles.css");
export default function ClientProviders({ children }: { children: ReactNode }) {
const network = WalletAdapterNetwork.Devnet;
const endpoint = useMemo(() => clusterApiUrl(network), [network]);
const wallets = useMemo(
() => [new UnsafeBurnerWalletAdapter()],
[network]
);
return (
<ConnectionProvider endpoint={endpoint}>
<WalletProvider wallets={wallets} autoConnect>
<WalletModalProvider>
{children}
</WalletModalProvider>
</WalletProvider>
</ConnectionProvider>
);
}Layout Setup
Load the ClientProviders component via layout.tsx:
import type { Metadata } from "next";
import ClientProviders from "@/app/components/ClientProviders";
import { Inter } from "next/font/google";
const inter = Inter({ subsets: ["latin"] });
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={inter.className}>
<ClientProviders>
{children}
</ClientProviders>
</body>
</html>
);
}Wallet Connection Component
Create a wallet connection component ConnectSolana.tsx:
"use client";
import React, { useEffect, useState } from "react";
import { WalletMultiButton, WalletDisconnectButton } from "@solana/wallet-adapter-react-ui";
import "@solana/wallet-adapter-react-ui/styles.css";
const ConnectSolana: React.FC = () => {
const [isClient, setIsClient] = useState(false);
// Prevent hydration errors by ensuring this runs only on the client side
useEffect(() => {
setIsClient(true);
}, []);
if (!isClient) {
return null;
}
return (
<div className="border-2 border-primary rounded-2xl p-4 w-full max-w-md">
{/* Solana wallet connect button */}
<div className="mr-5">
<WalletMultiButton />
</div>
{/* Solana wallet disconnect button */}
<div className="ml-5">
<WalletDisconnectButton />
</div>
</div>
);
};
export default ConnectSolana;Irys Connection Component
Create an Irys connection component ConnectIrys.tsx:
"use client";
import { useState } from "react";
import { useWallet } from "@solana/wallet-adapter-react";
import { WebUploader } from "@irys/web-upload";
import { WebSolana } from "@irys/web-upload-solana";
const getIrysUploader = async (wallet: any) => {
try {
const irysUploader = await WebUploader(WebSolana).withProvider(wallet);
return irysUploader;
} catch (error) {
console.error("Error connecting to Irys:", error);
throw new Error("Error connecting to Irys");
}
};
const ConnectIrys = (): JSX.Element => {
const wallet = useWallet();
const [isConnected, setIsConnected] = useState<boolean>(false);
const connectToIrys = async () => {
if (!wallet) {
console.log("Wallet not connected");
return;
}
try {
const irysUploader = await getIrysUploader(wallet);
console.log(`Connected to Irys from ${irysUploader.address}`);
setIsConnected(true);
} catch (error) {
console.log("Error connecting to Irys");
}
};
return (
<div>
<button onClick={connectToIrys}>
{isConnected ? "Connected to Irys" : "Connect Irys"}
</button>
</div>
);
};
export default ConnectIrys;Page Setup
Load the components through page.tsx:
import Image from "next/image";
import ConnectSolana from "./components/ConnectSolana";
import ConnectIrys from "./components/ConnectIrys";
export default function Home() {
return (
<main className="flex min-h-screen flex-col justify-around items-center p-24 bg-black">
<ConnectSolana />
<ConnectIrys />
</main>
);
}Aptos
Start with scaffolding:
npx create-aptos-dappPackage installation:
npm install \
@irys/web-upload \
@irys/web-upload-aptos \
axiosApp.tsx Configuration
import React, { useState } from "react";
import { useWallet } from "@aptos-labs/wallet-adapter-react";
import { WebUploader } from "@irys/web-upload";
import { WebAptos } from "@irys/web-upload-aptos";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Header } from "@/components/Header";
function App() {
const { connected } = useWallet();
const wallet = useWallet();
const [irysStatus, setIrysStatus] = useState("Not connected");
const connectIrys = async () => {
console.log("connect irys called");
console.log({ wallet });
try {
const irysUploader = await WebUploader(WebAptos).withProvider(wallet);
console.log({ irysUploader });
setIrysStatus(`Connected to Irys: ${irysUploader.address}`);
} catch (error) {
console.error("Error connecting to Irys:", error);
setIrysStatus("Error connecting to Irys");
}
};
return (
<>
<Header />
<div className="flex items-center justify-center flex-col">
<Card className="mt-6">
<CardHeader>
{connected ? (
<CardTitle>
<button onClick={connectIrys}>
{irysStatus === "Not connected" ? "Connect Irys" : irysStatus}
</button>
</CardTitle>
) : (
<CardTitle>To get started, connect a wallet</CardTitle>
)}
</CardHeader>
</Card>
</div>
</>
);
}
export default App;Vite Configuration
Install polyfill packages:
npm install --save-dev \
crypto-browserify \
stream-browserify \
os-browserify \
path-browserify \
vite-plugin-node-polyfillsUpdate vite.config.js:
import path from "path";
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
import { nodePolyfills } from "vite-plugin-node-polyfills";
export default defineConfig({
plugins: [
react(),
nodePolyfills({
globals: {
Buffer: true,
global: true,
process: true,
},
protocolImports: true,
}),
],
resolve: {
alias: {
crypto: "crypto-browserify",
stream: "stream-browserify",
os: "os-browserify/browser",
path: "path-browserify",
"@": path.resolve(__dirname, "./frontend"),
},
},
build: {
outDir: "dist",
},
server: {
open: true,
},
});After configuration, restart the development server with npm run dev.