Irys in the browser

Irys in the browser

Working with Irys in the browser is similar to working with our server-side SDK, however there are a few differences which are demonstrated below.

🚀

If you're using Irys with React and npx create-react-app, you will need to follow some extra setup steps.

Installing

Install using npm:

npm install @irys/sdk

or yarn:

yarn add @irys/sdk

Importing

import { WebIrys } from "@irys/sdk";

Connecting to a node

When instantiating a WebIrys object pass:

  • network: Either "mainnet" or "devnet"
  • token: Payment token
  • wallet: A wallet object containing the end-user's injected provider and the name of the provider package your project uses
const getWebIrys = async () => {
	// Ethers5 provider
	await window.ethereum.enable();
	const provider = new providers.Web3Provider(window.ethereum);
 
	const network = "mainnet";
	const token = "ethereum";
	// Devnet RPC URLs change often, use a recent one from https://chainlist.org
	const rpcUrl = "";
 
	// Create a wallet object
	const wallet = { rpcUrl: rpcUrl, name: "ethersv5", provider: provider };
	// Use the wallet object
	const webIrys = new WebIrys({ network, token, wallet });
	await webIrys.ready();
 
	return webIrys;
};

After instantiating the object, call webIrys.ready().

Supported providers

WebIrys supports the following providers. When instantiating a new WebIrys object, you must pass in the name of the provider you will be using.

PackageParameter value
Ethers 5 (opens in a new tab)ethersv5
Ethers 6 (opens in a new tab)ethersv6
Solana (opens in a new tab)solana
Viem v2 (opens in a new tab)viemv2

Aptos

const aptosWallet = useWallet();
 
const getWebIrys = async () => {
	const network = "devnet";
	const token = "aptos";
	const rpcUrl = "testnet"; // "mainnet" || "testnet"
	const wallet = { rpcUrl: rpcUrl, name: "aptos", provider: aptosWallet };
	const webIrys = new WebIrys({ network, token, wallet });
	await webIrys.ready();
 
	return webIrys;
};

Solana React Hooks

When working with the Solana React hooks, start by wrapping your components in the Solana ConnectionProvider WalletProvider and WalletModalProvider providers.

import { ConnectionProvider, WalletProvider } from "@solana/wallet-adapter-react";
import { WalletModalProvider } from "@solana/wallet-adapter-react-ui";
import { PhantomWalletAdapter } from "@solana/wallet-adapter-wallets";
 
// Devnet or Mainnet
const network = WalletAdapterNetwork.Devnet;
const endpoint = useMemo(() => clusterApiUrl(network), [network]);
 
const wallets = useMemo(() => [new PhantomWalletAdapter()], [network]);
 
<ConnectionProvider endpoint={endpoint}>
	<WalletProvider wallets={wallets} autoConnect>
		<WalletModalProvider>
			<YourComponents />
		</WalletModalProvider>
	</WalletProvider>
</ConnectionProvider>;

Then, in components where you need to access a WebIrys object use the useWallet() hook to get a reference to the user's injected provider, and pass that into WebIrys when instantiating a new object.

import { useWallet } from "@solana/wallet-adapter-react";
const wallet = useWallet();
 
const getIrys = async (): Promise<WebIrys> => {
	// Devnet RPC URLs change often, use a recent one from https://chainlist.org
	const rpcUrl = "";
 
	const wallet = { rpcUrl: rpcUrl, name: "solana", provider: wallet };
	const webIrys = new WebIrys({ network: "mainnet", token: "solana", wallet });
	await webIrys.ready();
	return webIrys;
};

Additional providers

Additionally, the following providers will work with extra setup code.

PackageParameter value
Othentothent
Privyprivy

Othent (opens in a new tab)

export const getWebIrys = async () => {
	const wallet = { name: "Othent KMS", provider: othentKMS };
	const network = "mainnet";
	const token = "arweave";
	const webIrys = new WebIrys({ network, token, wallet });
	await webIrys.ready();
	return webIrys;
};

Privy (opens in a new tab)

Initialize the Privy provider with your app ID and wrap it around your components. In most NextJS projects, you will place this code in your app.tsx file. In our example, we use the <PrivyIrys /> component as a placeholder for your app's top-level component structure.

🚀

We also have a demo repository (opens in a new tab) teaching how to build a PWA photo-sharing app using Privy and Irys.

import { PrivyProvider } from "@privy-io/react-auth";
 
<PrivyProvider
	appId="YOUR-APP-ID"
	onSuccess={handlePrivyLogin}
	config={{
		loginMethods: ["email", "wallet"],
		appearance: {
			theme: "dark",
			accentColor: "#676FFF",
			logo: "https://docs.irys.xyz/img/favicon.svg",
		},
		embeddedWallets: {
			createOnLogin: "users-without-wallets",
		},
	}}
>
	<PrivyIrys />
</PrivyProvider>;

Then, write code to login with Privy and create a new WebIrys object.

The code to create a WebIrys object differs depending on if you're using an external wallet (opens in a new tab) vs an embedded one (opens in a new tab). When using external wallets, pass the Ethers provider returned from the Wallet object, when using embedded wallets pass the sendTransaction Privy React hook.

The following code uses conditional logic to create the correct WebIrys object based on the wallet type. If your application only supports a single wallet type, feel free to simplify the code.

import { User, usePrivy, useWallets } from "@privy-io/react-auth";
 
const { wallets } = useWallets();
const { login } = usePrivy();
const { sendTransaction } = usePrivy();
 
// First login
login();
 
// The 0th position wallet is the most recently used one
const w = wallets.at(0);
// Or find the embedded wallet
// const w = wallets.find((wallet) => wallet.walletClientType === 'privy');
 
// Then create a WebIrys object
const getWebIrys = async () => {
	const network = "devnet";
	const token = "ethereum";
 
	const provider = await w?.getEthersProvider();
	if (!provider) throw new Error(`Cannot find privy wallet`);
	const irysWallet =
		w?.walletClientType === "privy"
			? { name: "privy-embedded", provider, sendTransaction }
			: { name: "privy", provider };
 
	const webIrys = new WebIrys({
		network,
		token,
		wallet: irysWallet,
	});
 
	await webIrys.ready();
};

Funding a node

Fund a node using any of our supported tokens:

const fundNode = async () => {
	const webIrys = await getWebIrys();
	try {
		const fundTx = await webIrys.fund(webIrys.utils.toAtomic(0.05));
		console.log(`Successfully funded ${webIrys.utils.fromAtomic(fundTx.quantity)} ${webIrys.token}`);
	} catch (e) {
		console.log("Error uploading data ", e);
	}
};

Uploading

Data uploaded to Irys is given a millisecond-accurate timestamp, attributes and authorship details before being passed to Arweave for permanent storage. This information is used to create a signed receipt that can be trustlessly verified.

Uploading data

const uploadData = async () => {
	const webIrys = await getWebIrys();
	const dataToUpload = "GM world.";
	try {
		const receipt = await webIrys.upload(dataToUpload);
		console.log(`Data uploaded ==> https://gateway.irys.xyz/${receipt.id}`);
	} catch (e) {
		console.log("Error uploading data ", e);
	}
};

Uploading a file

Upload a File (opens in a new tab) object.

const uploadFile = async (fileToUpload: File) => {
	const webIrys = await getWebIrys();
	// Your file
	const tags = [{ name: "application-id", value: "MyNFTDrop" }];
 
	try {
		const receipt = await webIrys.uploadFile(fileToUpload, { tags: tags });
		console.log(`File uploaded ==> https://gateway.irys.xyz/${receipt.id}`);
	} catch (e) {
		console.log("Error uploading file ", e);
	}
};

Uploading a folder

Upload an array of File (opens in a new tab) objects.

Upon upload, a manifest is automatically created. Your files can be accessed https://gateway.irys.xyz/[manifestId]/[file-name].

const uploadFolder = async (files: File[], tags: Tag[]) => {
	const webIrys = await getIrys();
 
	try {
		const receipt = await webIrys.uploadFolder(files, {
			tags,
		}); //returns the manifest ID
 
		console.log(`Files uploaded. Manifest Id=${receipt.manifestId} Receipt Id=${receipt.id}`);
	} catch (e) {
		console.log("Error uploading file ", e);
	}
};