diff --git a/.gitignore b/.gitignore index 13c21d25b..2c964b252 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,5 @@ public/sitemap-0.xml public/nexus public/da public/user-guides +public/tutorials public/llms-full.txt \ No newline at end of file diff --git a/app/_meta.ts b/app/_meta.ts index fb056e2fd..65c2f5bf5 100644 --- a/app/_meta.ts +++ b/app/_meta.ts @@ -14,6 +14,12 @@ export default { type: "page", title: "Data Availability", }, + + 'tutorials': { + type: "page", + title: "Tutorials", + }, + 'user-guides': { type: 'page', title: 'User Guides', diff --git a/app/nexus/nexus-cheatsheet/page.mdx b/app/nexus/nexus-cheatsheet/page.mdx new file mode 100644 index 000000000..2dace16ac --- /dev/null +++ b/app/nexus/nexus-cheatsheet/page.mdx @@ -0,0 +1,67 @@ +--- +image: "/img/docs-link-preview.png" +title: Nexus cheat sheet +description: "A single page to find all external links and resources to help you get started with Avail Nexus" +--- + +import { Callout, Steps, Tabs, Cards } from 'nextra/components'; +import { FileIcon, FilesIcon, LinkIcon, GithubIcon24 } from '@components/icons' + + +# Nexus cheat sheet + +We created this page to make it easier for devs to navigate between all the links and resources related to Avail Nexus. +Feel free to suggest any additions you think are missing. + +## Nexus SDK + +The most convenient way to interact with the decentralized solver network powering Avail Nexus is through the Nexus SDK. + +Link to the Nexus SDK Github repo: + + +} arrow /> + + +The overall Nexus SDK is split into two main packages: + +### Nexus-core + +The headless version , for fine-grained control over the Nexus SDK. + + + } href="https://github.com/availproject/nexus-sdk/tree/main/packages/core" target="_blank" rel="noopener noreferrer" arrow /> + } href="https://www.npmjs.com/package/@avail-project/nexus-core?activeTab=code" target="_blank" rel="noopener noreferrer" arrow /> + + +We also built a demo app with `nexus-core` to provide more reference code: + + + } href="https://avail-nexus-demo-five.vercel.app/" target="_blank" rel="noopener noreferrer" arrow /> + } href="https://github.com/availproject/avail-nexus-demo" target="_blank" rel="noopener noreferrer" arrow /> + + +### Nexus-widgets + +Comes with built-in UI components to make it easier to integrate the Nexus SDK into your React app. + + + } href="https://github.com/availproject/nexus-sdk/tree/main/packages/widgets" target="_blank" rel="noopener noreferrer" arrow /> + } href="https://www.npmjs.com/package/@avail-project/nexus-widgets?activeTab=code" target="_blank" rel="noopener noreferrer" arrow /> + + +We also built a demo app with `nexus-widgets` to provide more reference code: + + + } href="https://nexus-demo.availproject.org/" target="_blank" rel="noopener noreferrer" arrow /> + } href="https://github.com/availproject/nexus-ui-components-demo" target="_blank" rel="noopener noreferrer" arrow /> + + +## Nexus SDK templates + +Clone these repos to quickly get started with the Nexus SDK using `Next JS` or `Vite`. + + + } href="https://github.com/availproject/nexus-nextjs-template" target="_blank" rel="noopener noreferrer" arrow /> + } href="https://github.com/availproject/nexus-vite-template" target="_blank" rel="noopener noreferrer" arrow /> + \ No newline at end of file diff --git a/app/tutorials/_meta.ts b/app/tutorials/_meta.ts new file mode 100644 index 000000000..e85bde8a0 --- /dev/null +++ b/app/tutorials/_meta.ts @@ -0,0 +1,13 @@ +export default { + + "Nexus Tutorials": { + type: "separator", + title: "Nexus Tutorials", + }, + + "nexus-initialization": "Initialize the Nexus SDK using Next JS", + "nexus-bridge": "Bridge tokens using the Nexus SDK", + "tut-3": "Tutorial-3", + "tut-4": "Tutorial-4", + "tut-5": "Tutorial-5", +} \ No newline at end of file diff --git a/app/tutorials/nexus-bridge/page.mdx b/app/tutorials/nexus-bridge/page.mdx new file mode 100644 index 000000000..3fbbe9982 --- /dev/null +++ b/app/tutorials/nexus-bridge/page.mdx @@ -0,0 +1,51 @@ +--- +title: "Bridge tokens using the Nexus SDK" +description: "This tutorial will teach you about the .bridge() function of the Nexus SDK" +keywords: + - docs + - Avail Nexus + - Nexus SDK + - bridge +--- + +import { Callout, Steps, Tabs } from 'nextra/components'; + +# Bridge tokens using the Nexus SDK + +This tutorial will cover the bridging functionality of the Nexus SDK, +covered under the `bridge()` function. + +We will use the [Nexus Next JS template repo](https://github.com/availproject/nexus-nextjs-template) to +make the setup process easier. + +## Start the template locally + +1. Clone the template repo: + +```bash filename="Terminal" +git clone https://github.com/availproject/nexus-nextjs-template.git +``` + +2. Install the dependencies: + +```bash filename="Terminal" +cd nexus-nextjs-template +pnpm install +``` + +3. Set up the `NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID` environment variable by creating a `.env.local` file: + +```dotenv filename=".env" +NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=YOUR_PROJECT_ID +``` + + +**Note:**
+Log in to your [WalletConnect](https://walletconnect.network/) account and create a project to get your project ID. +
+ +4. Run the dev server: + +```bash filename="Terminal" +pnpm dev +``` \ No newline at end of file diff --git a/app/tutorials/nexus-initialization/page.mdx b/app/tutorials/nexus-initialization/page.mdx new file mode 100644 index 000000000..5c4c0368d --- /dev/null +++ b/app/tutorials/nexus-initialization/page.mdx @@ -0,0 +1,344 @@ +--- +title: "Get Started with the Nexus SDK using Next JS" +description: "This tutorial will help you get started with the Nexus SDK using Next JS" +keywords: + - docs + - Avail Nexus + - Next JS + - Vite + - Nexus SDK initialization + - Unified balances + - Fetch Balances using the Nexus SDK +--- + +import { Callout, Steps, Tabs } from 'nextra/components'; + +# Get Started with the Nexus SDK using Next JS + + +**WANT TO SKIP THE TUTORIAL?**
+We created two template repos for devs to easily get started with the Nexus SDK using Next JS and Vite. +We recommend going through the tutorial first, but to each their own: + +1. [availproject/nexus-nextjs-template](https://github.com/availproject/nexus-nextjs-template) +2. [availproject/nexus-vite-template](https://github.com/availproject/nexus-vite-template) +
+ +## Prerequisites + + +The following tutorial uses `pnpm` as the package manager, adjust the commands +if you're using a different one. + + +1. Make sure [Node.js](https://nodejs.org/en) is installed on your system. We recommend +version `20.x.x` or higher. + +2. Set up a package manager of your choice. We use [pnpm](https://pnpm.io/) for this tutorial, +but alternatives like [npm](https://www.npmjs.com/) and [yarn](https://yarnpkg.com/) work just fine. + +3. Make sure you have an [EIP-1193](https://eips.ethereum.org/EIPS/eip-1193) compatible wallet provider (for example, MetaMask) installed in your browser to follow along with the tutorial. + +## Objectives + +By the end of this tutorial you will have: + +1. Understood how to initialize the Nexus SDK inside a frontend environment. +2. Implemented said initialization using Next JS. +3. Fetched unified balances using the Nexus SDK. + + +**WHAT IS A 'UNIFIED BALANCE'?**
+You can refer to this [page in our docs](/nexus/concepts/unified-balance) for more details. +
+ +## What Does 'Initialization' Mean Here? + +- The Nexus SDK allows you to seamlessly transfer tokens across-chains using the `.transfer()` +and `.bridge()` functions *(We'll go through them in the following tutorials)*. You can also fetch unified balances using the `.getUnifiedBalances()` function. + +- To do any of that though, the SDK needs access to a wallet. You can do this on the frontend +by using an injected wallet provider that follows the [`EIP-1193`](https://eips.ethereum.org/EIPS/eip-1193) standard. + +- And to do that, you need to call the `.initialize()` function of the SDK while passing +the wallet provider to it. + +- The flows to do this differ between the headless and the widgets SDK. +We will go over both of them in this tutorial. + + +The `.initialize()` function must be called **AFTER** a wallet has been connected. +Otherwise, the SDK will throw an error. + + +## Initialize the Nexus SDK using Next JS (A minimal example using nexus-core) + +### Objective + +In this section we will create a minimal Next JS page with 4 buttons: + +1. The first button will be used to connect a wallet to the app. +2. The second button will be used to initialize the SDK using `nexus-core`. +3. The third button will be used to fetch the unified balances using the Nexus SDK. +4. The fourth button will de-initialize the SDK using the `deinit()` function. + +### Set up a basic Next JS project + +1. Navigate into a directory of your choice and create a new Next JS project at it's root: + +```bash filename="Terminal" +pnpm create next-app@latest . --ts --eslint --app --src-dir +``` + +2. Install the `nexus-core` package: + +```bash filename="Terminal" +pnpm add @avail-project/nexus-core@0.0.3-beta.0 +``` + +3. Update the `src/app/page.tsx` file to the following: + +```tsx filename="src/app/page.tsx" +export default function Home() { + return
Hello Nexus!
; +} +``` + +4. Run a dev server using: + +```bash filename="Terminal" +pnpm dev +``` + +You should now have a bare bones Next JS project running in your browser. \ +Let us now get down to business!!! + +### Set up an instance of the Nexus SDK + +We will set up a single instance of the Nexus SDK and use it across the app. +This will help keep the code clean and make it easier to understand the flow of the app. + +1. Create a file at `src/lib/nexus.ts` and add the following code: + +```tsx filename="src/lib/nexus.ts" +import { NexusSDK } from '@avail-project/nexus-core'; + +export const sdk = new NexusSDK({ network: 'testnet'}); +``` + +This initializes the Nexus SDK with the `testnet` chains. +If this param is not provided, the SDK will default to `mainnet`. + + +You can check out a complete list of the supported networks [here](/nexus/avail-nexus-sdk/examples/nexus-core/api-reference#supported-chains). + + +2. Now fill the page with the following helper functions: + +```tsx filename="src/lib/nexus.ts" + +// Thin wrapper that calls sdk.isInitialized() from the SDK +export function isInitialized() { + return sdk.isInitialized(); +} + +export async function initializeWithProvider(provider: any) { + if (!provider) throw new Error('No EIP-1193 provider (e.g., MetaMask) found'); + + //If the SDK is already initialized, return + if (sdk.isInitialized()) return; + + //If the SDK is not initialized, initialize it with the provider passed as a parameter + await sdk.initialize(provider); +} + +export async function deinit() { + + //If the SDK is not initialized, return + if (!sdk.isInitialized()) return; + + //If the SDK is initialized, de-initialize it + await sdk.deinit(); +} + +export async function getUnifiedBalances() { + + //Get the unified balances from the SDK + return await sdk.getUnifiedBalances(); +} +``` + +Let's quickly go over the role of each function: + +1. `isInitialized()`: This thin wrapper calls `sdk.isInitialized()` from the Nexus SDK to query and return the initialization status of the SDK. +2. `initializeWithProvider(provider: any)`: This function checks if the SDK is already initialized and if not, it initializes it with the provider passed as a parameter. + +This function must be called **AFTER** a wallet has been connected. +Otherwise, the SDK will throw an error. + +3. `deinit()`: This function checks if the SDK is initialized and if so, it de-initializes it. +4. `getUnifiedBalances()`: This function calls `sdk.getUnifiedBalances()` from the Nexus SDK to fetch the unified balance of the user. + +### Set up the buttons + +Create four new files in the `src/components` directory: + + + +#### connect-button.tsx + +This component will be used to connect a `EIP-1193` compatible wallet to the app. + +```tsx filename="src/components/connect-button.tsx" +'use client'; + +export default function ConnectButton({ className }: { className?: string }) { + const onClick = async () => { + const eth = (window as any)?.ethereum; + if (!eth) return alert('Install an EIP-1193 wallet (e.g., MetaMask)'); + await eth.request?.({ method: 'eth_requestAccounts' }); + alert('Wallet already connected'); + }; + return ; +} +``` + +#### init-button.tsx + +This component will be used to initialize the SDK using `nexus-core`. + +```tsx filename="src/components/init-button.tsx" +'use client'; + +import { initializeWithProvider, isInitialized } from '../lib/nexus'; + +export default function InitButton({ + className, + onReady, +}: { className?: string; onReady?: () => void }) { + const onClick = async () => { + const eth = (window as any)?.ethereum; + try { + // We're calling our wrapper function from the lib/nexus.ts file here. + await initializeWithProvider(eth); + onReady?.(); + alert('Nexus initialized'); + } catch (e: any) { + alert(e?.message ?? 'Init failed'); + } + }; + return ; +} +``` + +#### fetch-unified-balance-button.tsx + +This component will be used to fetch the unified balances using the Nexus SDK. + +```tsx filename="src/components/fetch-unified-balance-button.tsx" +'use client'; + +import { getUnifiedBalances, isInitialized } from '../lib/nexus'; + +export default function FetchUnifiedBalanceButton({ + className, + onResult, +}: { className?: string; onResult?: (r: any) => void }) { + const onClick = async () => { + if (!isInitialized()) return alert('Initialize first'); + const res = await getUnifiedBalances(); + onResult?.(res); + console.log(res); + }; + return ; +} +``` + +#### de-init-button.tsx + +This component will be used to de-initialize the SDK using the `deinit()` function. + +```tsx filename="src/components/de-init-button.tsx" +'use client'; + +import { deinit, isInitialized } from '../lib/nexus'; + +export default function DeinitButton({ + className, + onDone, +}: { className?: string; onDone?: () => void }) { + const onClick = async () => { + await deinit(); + onDone?.(); + alert('Nexus de-initialized'); + }; + return ; +} +``` + + + +### Set up the Landing Page + +Update the `src/app/page.tsx` file to the following: + +```tsx filename="src/app/page.tsx" +'use client'; + +import { useState } from 'react'; +import ConnectButton from '@/components/connect-button'; +import InitButton from '@/components/init-button'; +import FetchUnifiedBalanceButton from '@/components/fetch-unified-balance-button'; +import DeinitButton from '@/components/de-init-button'; +import { isInitialized } from '@/lib/nexus'; + +export default function Page() { + const [initialized, setInitialized] = useState(isInitialized()); + const [balances, setBalances] = useState(null); + + const btn = + 'px-4 py-2 rounded-md bg-blue-600 text-white hover:bg-blue-700 ' + + 'disabled:opacity-50 disabled:cursor-not-allowed'; + + return ( +
+
+ + setInitialized(true)} /> + setBalances(r)} /> + { setInitialized(false); setBalances(null); }} /> + +
+ Nexus SDK Initialization Status: {initialized ? 'Initialized' : 'Not initialized'} +
+ + {balances && ( +
{JSON.stringify(balances, null, 2)}
+ )} +
+
+ ); +} +``` + +`sdk.getUnifiedBalances()` returns a JSON object with the balances of the user on each of the supported chains. +We're rendering it out on the screen raw to keep the tutorial simple, but you can always format it as you please. + + +**What's Happening Here?** + +1. We use the `useState` hook to manage the initialization status and balances of the SDK. +2. Some basic CSS is applied to the buttons to arrange them in a column. +3. Some buttons are conditionally toggled based on the initialization status of the SDK. +4. All in all, clicking through the buttons will allow you to initialize the SDK, fetch balances for a user, and de-initialize the SDK. + + +## Think About What You Just Did Here!!! + +In just a few lines of code, you leveraged the power of the Nexus SDK to fetch a list of tokens that the user holds across several different chains. +You can now move around those tokens as you please, the possibilities are endless! + +You might want to bridge one of the tokens across chains, or maybe you want to swap all existing tokens of your user spread across +different chains into `ETH` on `Arbitrum`. + +Once you have a wallet connected and the SDK initialized, you can do all of this and more! \ No newline at end of file diff --git a/app/tutorials/tut-3/page.mdx b/app/tutorials/tut-3/page.mdx new file mode 100644 index 000000000..e69de29bb diff --git a/app/tutorials/tut-4/page.mdx b/app/tutorials/tut-4/page.mdx new file mode 100644 index 000000000..e69de29bb diff --git a/app/tutorials/tut-5/page.mdx b/app/tutorials/tut-5/page.mdx new file mode 100644 index 000000000..e69de29bb diff --git a/components/icons/github-24.svg b/components/icons/github-24.svg new file mode 100644 index 000000000..830f00462 --- /dev/null +++ b/components/icons/github-24.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/components/icons/index.ts b/components/icons/index.ts index 2324bcb7a..973d6f7d9 100644 --- a/components/icons/index.ts +++ b/components/icons/index.ts @@ -27,3 +27,4 @@ export { default as TerminalIcon } from './terminal.svg' export { default as DiagramIcon } from './diagram.svg' export { default as FolderTreeIcon } from './folder-tree.svg' export { default as IdCardIcon } from './id-card.svg' +export { default as GithubIcon24 } from './github-24.svg' diff --git a/static/introductionData.ts b/static/introductionData.ts index 05ceacf71..9eaad88c2 100644 --- a/static/introductionData.ts +++ b/static/introductionData.ts @@ -36,6 +36,24 @@ export const IntroData = [ }, ] }, + + { + title: "Tutorials", + description: + "Hands-on tutorials to help you build with Avail", + links: [ + { + topic: "Read more", + links: [{ link: "/tutorials/nexus-initialization", textcolor: "3CA3FC", placeholder: "Initialize Nexus SDK with Next JS"}, + {link: "/tutorials/nexus-bridge", textcolor: "3CA3FC", placeholder: "Bridge tokens using the Nexus SDK"}, + {link: "/tutorials/tut-3", textcolor: "3CA3FC", placeholder: "Tutorial 3"}, + {link: "/tutorials/tut-4", textcolor: "3CA3FC", placeholder: "Tutorial 4"}, + {link: "/tutorials/tut-5", textcolor: "3CA3FC", placeholder: "Tutorial 5"}, + ], + textcolor: "9C3D3D" + }, + ] + }, { title: "User guides", description: