diff --git a/app/nexus/nexus-examples/_meta.ts b/app/nexus/nexus-examples/_meta.ts index c6e48bfd0..d13fd1e39 100644 --- a/app/nexus/nexus-examples/_meta.ts +++ b/app/nexus/nexus-examples/_meta.ts @@ -1,8 +1,7 @@ export default { "nexus-initialization-basic": "Barebones initialization inside Next JS", "nexus-initialization-rainbowkit": "Initialize the Nexus SDK using RainbowKit", - - + "nexus-bridge": "Bridge tokens using the Nexus SDK", "bridge-and-transfer":{ title: "Bridge and transfer tokens using the Nexus SDK", display: "hidden", diff --git a/app/nexus/nexus-examples/nexus-bridge/page.mdx b/app/nexus/nexus-examples/nexus-bridge/page.mdx new file mode 100644 index 000000000..f2f666e97 --- /dev/null +++ b/app/nexus/nexus-examples/nexus-bridge/page.mdx @@ -0,0 +1,185 @@ +--- +title: "Add Bridge functionality to your RainbowKit Nexus SDK Project" +description: "Learn how to add bridge functionality to your existing Nexus SDK project with RainbowKit to bridge tokens between supported chains" +keywords: + - docs + - Avail Nexus + - Next JS + - RainbowKit + - Nexus SDK enhancement + - Wallet connection +--- + +import { Callout, Steps, Tabs } from "nextra/components"; + +# Add bridge token functionality to your Nexus SDK project + + + **PREREQUISITE** + +This tutorial assumes you have already completed the [basic Nexus SDK tutorial +with RainbowKit](/nexus/nexus-examples/nexus-initialization-rainbowkit). If +you haven't, please go through that first to set up your base project with +RainbowKit. + + + +## What You'll Learn + +By the end of this tutorial you will be able to bridge tokens from one supported chain to another. + +--- + +## Add Bridge functionality + + + +### Add Bridge Button + +Create a file at `src/components/bridge-button.tsx` and add the following lines: + +```tsx filename="src/components/bridge-button.tsx" showLineNumbers +"use client"; + +import { bridge, isInitialized } from "../lib/nexus"; + +export default function BridgeButton({ + className, + onResult, +}: { + className?: string; + onResult?: (r: any) => void; +}) { + const onClick = async () => { + if (!isInitialized()) return alert("Initialize first"); + const res = await bridge(); + onResult?.(res); + console.log(res); + }; + return ( + + ); +} +``` + +### Add a new helper function for bridging tokens + +Add the following lines at the end of the file `src/lib/nexus.ts` (This example uses Arbitrum Sepolia network as the destination chain): + +```tsx showLineNumbers filename="src/lib/nexus.ts" +import { NexusSDK, BridgeResult, NEXUS_EVENTS } from '@avail-project/nexus-core'; + +... +// The Bridge Button in this case is being prefill configured to bridge some USDC to Arbitrum Sepolia. You can customize it to take user inputs in your app. +export async function bridge() { + const bridgeResult: BridgeResult = await sdk.bridge( + { + token: "USDC", + amount: BigInt(100), + toChainId: 421614, // Arbitrum Sepolia + }, + { + onEvent: (event) => { + if (event.name === NEXUS_EVENTS.STEPS_LIST) { + // render steps if you wish to display them to the user + } else if (event.name === NEXUS_EVENTS.STEP_COMPLETE) { + // Returned per step of intent fulfillment. You can use this to mark the step as done and show the explorer URL if present. + const step = event.args; + if (step.type === "INTENT_SUBMITTED") { + const url = (step as any).data?.explorerURL; + if (url) console.log("Explorer:", url); + } + } + }, + } + ); + return bridgeResult; +} +``` + +### Update Main Page + +Update your `src/app/page.tsx` to show wallet connection status: + +```tsx filename="src/app/page.tsx" showLineNumbers +"use client"; + +import { useState } from "react"; +import { useAccount } from "wagmi"; +import ConnectWalletButton 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 BridgeButton from "@/components/bridge-button"; +import { isInitialized } from "@/lib/nexus"; + +export default function Page() { + const { isConnected } = useAccount(); + const [initialized, setInitialized] = useState(isInitialized()); + const [balances, setBalances] = useState(null); + const [bridgeResult, setBridgeResult] = 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)} + /> + setBridgeResult(r)} /> + { + setInitialized(false); + setBalances(null); + }} + /> + +
+ Wallet Status: {isConnected ? "Connected" : "Not connected"} +
+
+ Nexus SDK Initialization Status:{" "} + {initialized ? "Initialized" : "Not initialized"} +
+ + {balances && ( +
+            {JSON.stringify(balances, null, 2)}
+          
+ )} + + {bridgeResult && ( +
+            {JSON.stringify(bridgeResult, null, 2)}
+          
+ )} +
+
+ ); +} +``` + +Run the application with `pnpm dev` or `npm run dev`. + +You should now be able to bridge to Arbitrum Sepolia from any chain. Go ahead and play with the UI or code to get user inputs for the bridging or change the bridge destination or amounts manually. + +If the bridging is successful, an explorer URL will be displayed to see the transaction details. Such as this one below: +```JSON +{ + "explorerUrl": "https://explorer.nexus-folly.availproject.org/intent/37584" +} +``` + + + +
+ diff --git a/app/nexus/nexus-examples/nexus-initialization-rainbowkit/page.mdx b/app/nexus/nexus-examples/nexus-initialization-rainbowkit/page.mdx index be9283538..3d5517923 100644 --- a/app/nexus/nexus-examples/nexus-initialization-rainbowkit/page.mdx +++ b/app/nexus/nexus-examples/nexus-initialization-rainbowkit/page.mdx @@ -10,14 +10,19 @@ keywords: - Wallet connection --- -import { Callout, Steps, Tabs } from 'nextra/components'; +import { Callout, Steps, Tabs } from "nextra/components"; # Add RainbowKit to Your Nexus SDK Project +RainbowKit is a React-based UI library designed to make it easy for developers to add wallet connections to their decentralized applications (dApps). It provides elegant, customizable components that allow users to connect their crypto wallets (e.g., MetaMask, WalletConnect, Coinbase Wallet) seamlessly. + -**PREREQUISITE**
-This tutorial assumes you have already completed the [basic Nexus SDK tutorial](/nexus/nexus-examples/nexus-initialization-basic). -If you haven't, please go through that first to set up your base project. + **PREREQUISITE** + +This tutorial assumes you have already completed the [basic Nexus SDK +tutorial](/nexus/nexus-examples/nexus-initialization-basic). If you haven't, +please go through that first to set up your base project. +
## What You'll Learn @@ -29,9 +34,11 @@ By the end of this tutorial you will have: 3. Added support for multiple wallet providers 4. Maintained all existing Nexus SDK functionality ---- +--- + -Check out the [RainbowKit docs](https://rainbowkit.com/docs/introduction) for latest information on how to use and customize it. + Check out the [RainbowKit docs](https://rainbowkit.com/docs/introduction) for + latest information on how to use and customize it. ## Install RainbowKit Dependencies @@ -52,19 +59,30 @@ pnpm add @rainbow-me/rainbowkit wagmi viem @tanstack/react-query Create a new file at `src/lib/wagmi.ts`: ```tsx filename="src/lib/wagmi.ts" showLineNumbers -import { getDefaultConfig } from '@rainbow-me/rainbowkit'; -import { mainnet, arbitrum, polygon, optimism, base, avalanche } from 'wagmi/chains'; +import { getDefaultConfig } from "@rainbow-me/rainbowkit"; +import { + mainnet, + arbitrum, + polygon, + optimism, + base, + avalanche, +} from "wagmi/chains"; export const config = getDefaultConfig({ - appName: 'Nexus SDK with RainbowKit', - projectId: 'YOUR_PROJECT_ID', // Get this from https://cloud.walletconnect.com/ + appName: "Nexus SDK with RainbowKit", + projectId: "YOUR_PROJECT_ID", // Get this from https://cloud.walletconnect.com/ chains: [mainnet, arbitrum, polygon, optimism, base, avalanche], ssr: true, // If your dApp uses server side rendering (SSR) }); ``` +This snippet configures RainbowKit and WalletConnect for a dApp, specifying supported EVM chains and app metadata. It enables server-side rendering and requires a WalletConnect project ID for authentication. + -You need to get a Project ID from [WalletConnect Cloud](https://cloud.walletconnect.com/) for RainbowKit to work properly. This is free and only takes a few minutes to set up. + You need to get a Project ID from [WalletConnect + Cloud](https://cloud.walletconnect.com/) for RainbowKit to work properly. This + is free and only takes a few minutes to set up. ### Create Providers Component @@ -72,13 +90,13 @@ You need to get a Project ID from [WalletConnect Cloud](https://cloud.walletconn Create a new file at `src/components/providers.tsx`: ```tsx filename="src/components/providers.tsx" showLineNumbers -'use client'; +"use client"; -import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; -import { WagmiProvider } from 'wagmi'; -import { RainbowKitProvider } from '@rainbow-me/rainbowkit'; -import { config } from '@/lib/wagmi'; -import '@rainbow-me/rainbowkit/styles.css'; +import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; +import { WagmiProvider } from "wagmi"; +import { RainbowKitProvider } from "@rainbow-me/rainbowkit"; +import { config } from "@/lib/wagmi"; +import "@rainbow-me/rainbowkit/styles.css"; const queryClient = new QueryClient(); @@ -86,22 +104,22 @@ export function Providers({ children }: { children: React.ReactNode }) { return ( - - {children} - + {children} ); } ``` +This snippet sets up global providers for Wagmi, React Query, and RainbowKit in a React app, enabling blockchain interactions and wallet UI support. It wraps the app’s components (children) with these providers to share config and state across the app. + ### Update Layout Update your `src/app/layout.tsx` to wrap your app with the providers: ```tsx filename="src/app/layout.tsx" showLineNumbers -import { Providers } from '@/components/providers'; -import './globals.css'; +import { Providers } from "@/components/providers"; +import "./globals.css"; export default function RootLayout({ children, @@ -111,14 +129,13 @@ export default function RootLayout({ return ( - - {children} - + {children} ); } ``` + ## Update Your Components @@ -130,11 +147,15 @@ export default function RootLayout({ Update your `src/components/connect-button.tsx` to use RainbowKit: ```tsx filename="src/components/connect-button.tsx" showLineNumbers -'use client'; +"use client"; -import { ConnectButton } from '@rainbow-me/rainbowkit'; +import { ConnectButton } from "@rainbow-me/rainbowkit"; -export default function ConnectWalletButton({ className }: { className?: string }) { +export default function ConnectWalletButton({ + className, +}: { + className?: string; +}) { return ( {({ @@ -146,29 +167,32 @@ export default function ConnectWalletButton({ className }: { className?: string authenticationStatus, mounted, }) => { - const ready = mounted && authenticationStatus !== 'loading'; + const ready = mounted && authenticationStatus !== "loading"; const connected = ready && account && chain && - (!authenticationStatus || - authenticationStatus === 'authenticated'); + (!authenticationStatus || authenticationStatus === "authenticated"); return (
{(() => { if (!connected) { return ( - ); @@ -176,18 +200,22 @@ export default function ConnectWalletButton({ className }: { className?: string if (chain.unsupported) { return ( - ); } return ( -
+
-
); @@ -235,41 +267,51 @@ export default function ConnectWalletButton({ className }: { className?: string Update your `src/components/init-button.tsx` to use Wagmi's connector: ```tsx filename="src/components/init-button.tsx" showLineNumbers -'use client'; +"use client"; -import { useAccount } from 'wagmi'; -import { initializeWithProvider, isInitialized } from '../lib/nexus'; +import { useAccount } from "wagmi"; +import { initializeWithProvider, isInitialized } from "../lib/nexus"; export default function InitButton({ className, onReady, -}: { className?: string; onReady?: () => void }) { +}: { + className?: string; + onReady?: () => void; +}) { const { connector } = useAccount(); - + const onClick = async () => { try { // Get the provider from the connected wallet const provider = await connector?.getProvider(); - if (!provider) throw new Error('No provider found'); - + if (!provider) throw new Error("No provider found"); + // We're calling our wrapper function from the lib/nexus.ts file here. await initializeWithProvider(provider); onReady?.(); - alert('Nexus initialized'); + alert("Nexus initialized"); } catch (e: any) { - alert(e?.message ?? 'Init failed'); + alert(e?.message ?? "Init failed"); } }; - return ; + return ( + + ); } ``` + The lines of interest for us is majorly what's here below: + ```ts const provider = await connector?.getProvider(); - if (!provider) throw new Error('No provider found'); - // We're calling our wrapper function from the lib/nexus.ts file here. - await initializeWithProvider(provider); +if (!provider) throw new Error("No provider found"); +// We're calling our wrapper function from the lib/nexus.ts file here. +await initializeWithProvider(provider); ``` + - Since RainbowKit uses `wagmi`, you can easily get the EIP-1193 Provider of your connected wallet with `useAccount` - Here, we import `useAccount` hook from `wagmi`, and get the `connector` property from which we can call `getProvider()` which returns the EIP-1193 Provider for the connected wallet. This makes it very easy for any RainbowKit connected wallet to initialize the Nexus SDK and unlock crosschain features. - Once we have the `provider`, we can pass it into our helper function to initialize Nexus. @@ -279,15 +321,15 @@ const provider = await connector?.getProvider(); Update your `src/app/page.tsx` to show wallet connection status: ```tsx filename="src/app/page.tsx" showLineNumbers -'use client'; +"use client"; -import { useState } from 'react'; -import { useAccount } from 'wagmi'; -import ConnectWalletButton 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'; +import { useState } from "react"; +import { useAccount } from "wagmi"; +import ConnectWalletButton 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 { isConnected } = useAccount(); @@ -295,32 +337,45 @@ export default function Page() { 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'; + "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); }} /> + setBalances(r)} + /> + { + setInitialized(false); + setBalances(null); + }} + />
- Wallet Status: {isConnected ? 'Connected' : 'Not connected'} + Wallet Status: {isConnected ? "Connected" : "Not connected"}
- Nexus SDK Initialization Status: {initialized ? 'Initialized' : 'Not initialized'} + Nexus SDK Initialization Status:{" "} + {initialized ? "Initialized" : "Not initialized"}
{balances && ( -
{JSON.stringify(balances, null, 2)}
+
+            {JSON.stringify(balances, null, 2)}
+          
)}
); } ``` + ## What Changed? @@ -341,6 +396,8 @@ The only changes from your basic tutorial are: Your Nexus SDK project now has a much better wallet connection experience while maintaining all the same functionality. You can continue building with the same Nexus SDK methods you learned in the basic tutorial! -**Want to learn more?**
-Check out the [RainbowKit documentation](https://www.rainbowkit.com/docs) for more customization options and advanced features. + **Want to learn more?** +
+ Check out the [RainbowKit documentation](https://www.rainbowkit.com/docs) for + more customization options and advanced features.