-
SDK Example - Viem
+
+ Integrator Toolkit Demo
+
diff --git a/apps/example/app/viem/components/index.ts b/apps/example/app/viem/components/index.ts
index 9e08a64..c9b1134 100644
--- a/apps/example/app/viem/components/index.ts
+++ b/apps/example/app/viem/components/index.ts
@@ -1 +1,2 @@
export * from "./Header";
+export * from "./Bridge";
diff --git a/apps/example/app/viem/providers.tsx b/apps/example/app/viem/providers.tsx
index 75ba9c9..c6f7de5 100644
--- a/apps/example/app/viem/providers.tsx
+++ b/apps/example/app/viem/providers.tsx
@@ -10,6 +10,7 @@ import {
} from "@rainbow-me/rainbowkit";
import { ThemeProvider, useTheme } from "next-themes";
import { config } from "@/lib/wagmi";
+import { AcrossProvider } from "@/lib/across";
const queryClient = new QueryClient();
@@ -17,13 +18,15 @@ export function Providers({ children }: { children: React.ReactNode }) {
return (
-
- {children}
-
+
+
+ {children}
+
+
);
diff --git a/apps/example/components/ChainSelect.tsx b/apps/example/components/ChainSelect.tsx
new file mode 100644
index 0000000..ec15dec
--- /dev/null
+++ b/apps/example/components/ChainSelect.tsx
@@ -0,0 +1,73 @@
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select";
+import { cn } from "@/lib/utils";
+import { AcrossChain } from "@across-toolkit/sdk";
+import { Skeleton } from "./ui";
+import Image from "next/image";
+import { Divider } from "./Divider";
+import { SelectProps } from "@radix-ui/react-select";
+
+export type ChainSelectProps = SelectProps & {
+ chains: AcrossChain[] | undefined;
+ chain: AcrossChain["chainId"] | undefined;
+ onChainChange: (_chainId: AcrossChain["chainId"]) => void;
+ className?: string;
+ id?: string;
+};
+
+export function ChainSelect({
+ chains,
+ chain,
+ onChainChange,
+ id,
+ className,
+ ...props
+}: ChainSelectProps) {
+ if (!chains) {
+ return (
+
+ );
+ }
+ return (
+
+ );
+}
diff --git a/apps/example/components/Divider.tsx b/apps/example/components/Divider.tsx
new file mode 100644
index 0000000..33fe7f1
--- /dev/null
+++ b/apps/example/components/Divider.tsx
@@ -0,0 +1,24 @@
+import { cn } from "@/lib/utils";
+
+type DividerProps = {
+ className?: string;
+ orientation?: "horizontal" | "vertical";
+};
+
+export function Divider({
+ className,
+ orientation = "horizontal",
+}: DividerProps) {
+ return (
+
+ );
+}
diff --git a/apps/example/components/TokenSelect.tsx b/apps/example/components/TokenSelect.tsx
new file mode 100644
index 0000000..9b68584
--- /dev/null
+++ b/apps/example/components/TokenSelect.tsx
@@ -0,0 +1,69 @@
+import {
+ Select,
+ SelectContent,
+ SelectGroup,
+ SelectItem,
+ SelectLabel,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select";
+import { cn } from "@/lib/utils";
+import { TokenInfo } from "@across-toolkit/sdk";
+import { Skeleton } from "./ui";
+import Image from "next/image";
+import { SelectProps } from "@radix-ui/react-select";
+
+export type TokenSelectProps = SelectProps & {
+ tokens: TokenInfo[] | undefined;
+ token: TokenInfo["address"] | undefined;
+ onTokenChange: (_address: TokenInfo["address"]) => void;
+ className?: string;
+};
+
+export function TokenSelect({
+ tokens,
+ token,
+ className,
+ onTokenChange,
+ ...props
+}: TokenSelectProps) {
+ if (!tokens) {
+ return (
+
+ );
+ }
+
+ return (
+
+ );
+}
diff --git a/apps/example/components/ui/button.tsx b/apps/example/components/ui/button.tsx
index cf096b6..bee71dd 100644
--- a/apps/example/components/ui/button.tsx
+++ b/apps/example/components/ui/button.tsx
@@ -5,18 +5,18 @@ import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const buttonVariants = cva(
- "inline-flex items-center shrink-0 justify-center whitespace-nowrap rounded-lg text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-50 border",
+ "inline-flex items-center shrink-0 justify-center bg-background hover:bg-foreground whitespace-nowrap rounded-lg text-sm font-medium transition-colors disabled:pointer-events-none disabled:opacity-50 border",
{
variants: {
variant: {
default: "border-border",
filled:
- "w-full shadow-md text-background hover:bg-accent hover:border-accent focus-visible:border-accent bg-text py-5 px-6 leading-6 rounded-lg",
+ "w-full shadow-md text-background hover:border-accent focus-visible:border-accent bg-text py-5 px-6 leading-6 rounded-lg",
bordered:
- "rounded-full border-border text-md font-normal bg-foreground text-text/75 hover:border-text/75",
+ "rounded-2xl border-border text-sm font-normal text-text/75 hover:border-text/75",
navigation: "rounded-full shadow-md bg-gradient-primary",
accent:
- "text-background shadow-md focus-visible:border-accent border-transparent bg-accent py-5 px-6 leading-6 rounded-lg",
+ "text-background shadow-md hover:bg-accent/80 focus-visible:border-accent border-transparent bg-accent py-5 px-6 leading-6 rounded-lg",
ghost:
"border-transparent hover:border-border hover:text-text/75 text-text/75 font-medium",
},
diff --git a/apps/example/components/ui/dropdown-menu.tsx b/apps/example/components/ui/dropdown-menu.tsx
new file mode 100644
index 0000000..f69a0d6
--- /dev/null
+++ b/apps/example/components/ui/dropdown-menu.tsx
@@ -0,0 +1,200 @@
+"use client"
+
+import * as React from "react"
+import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu"
+import { Check, ChevronRight, Circle } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+
+const DropdownMenu = DropdownMenuPrimitive.Root
+
+const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger
+
+const DropdownMenuGroup = DropdownMenuPrimitive.Group
+
+const DropdownMenuPortal = DropdownMenuPrimitive.Portal
+
+const DropdownMenuSub = DropdownMenuPrimitive.Sub
+
+const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup
+
+const DropdownMenuSubTrigger = React.forwardRef<
+ React.ElementRef
,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, children, ...props }, ref) => (
+
+ {children}
+
+
+))
+DropdownMenuSubTrigger.displayName =
+ DropdownMenuPrimitive.SubTrigger.displayName
+
+const DropdownMenuSubContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSubContent.displayName =
+ DropdownMenuPrimitive.SubContent.displayName
+
+const DropdownMenuContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, sideOffset = 4, ...props }, ref) => (
+
+
+
+))
+DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName
+
+const DropdownMenuItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName
+
+const DropdownMenuCheckboxItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, checked, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+DropdownMenuCheckboxItem.displayName =
+ DropdownMenuPrimitive.CheckboxItem.displayName
+
+const DropdownMenuRadioItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+ {children}
+
+))
+DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName
+
+const DropdownMenuLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef & {
+ inset?: boolean
+ }
+>(({ className, inset, ...props }, ref) => (
+
+))
+DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName
+
+const DropdownMenuSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName
+
+const DropdownMenuShortcut = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => {
+ return (
+
+ )
+}
+DropdownMenuShortcut.displayName = "DropdownMenuShortcut"
+
+export {
+ DropdownMenu,
+ DropdownMenuTrigger,
+ DropdownMenuContent,
+ DropdownMenuItem,
+ DropdownMenuCheckboxItem,
+ DropdownMenuRadioItem,
+ DropdownMenuLabel,
+ DropdownMenuSeparator,
+ DropdownMenuShortcut,
+ DropdownMenuGroup,
+ DropdownMenuPortal,
+ DropdownMenuSub,
+ DropdownMenuSubContent,
+ DropdownMenuSubTrigger,
+ DropdownMenuRadioGroup,
+}
diff --git a/apps/example/components/ui/index.ts b/apps/example/components/ui/index.ts
new file mode 100644
index 0000000..2713025
--- /dev/null
+++ b/apps/example/components/ui/index.ts
@@ -0,0 +1,8 @@
+export * from "./button";
+export * from "./dropdown-menu";
+export * from "./input";
+export * from "./label";
+export * from "./popover";
+export * from "./skeleton";
+export * from "./sonner";
+export * from "./tooltip";
diff --git a/apps/example/components/ui/input.tsx b/apps/example/components/ui/input.tsx
new file mode 100644
index 0000000..e3559f4
--- /dev/null
+++ b/apps/example/components/ui/input.tsx
@@ -0,0 +1,25 @@
+import * as React from "react";
+
+import { cn } from "@/lib/utils";
+
+export interface InputProps
+ extends React.InputHTMLAttributes {}
+
+const Input = React.forwardRef(
+ ({ className, type, ...props }, ref) => {
+ return (
+
+ );
+ },
+);
+Input.displayName = "Input";
+
+export { Input };
diff --git a/apps/example/components/ui/label.tsx b/apps/example/components/ui/label.tsx
new file mode 100644
index 0000000..12d4fe4
--- /dev/null
+++ b/apps/example/components/ui/label.tsx
@@ -0,0 +1,26 @@
+"use client";
+
+import * as React from "react";
+import * as LabelPrimitive from "@radix-ui/react-label";
+import { cva, type VariantProps } from "class-variance-authority";
+
+import { cn } from "@/lib/utils";
+
+const labelVariants = cva(
+ "text-sm text-text leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
+);
+
+const Label = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef &
+ VariantProps
+>(({ className, ...props }, ref) => (
+
+));
+Label.displayName = LabelPrimitive.Root.displayName;
+
+export { Label };
diff --git a/apps/example/components/ui/select.tsx b/apps/example/components/ui/select.tsx
new file mode 100644
index 0000000..03c7537
--- /dev/null
+++ b/apps/example/components/ui/select.tsx
@@ -0,0 +1,163 @@
+"use client";
+
+import * as React from "react";
+import * as SelectPrimitive from "@radix-ui/react-select";
+import { Check, ChevronDown, ChevronUp } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+
+const Select = SelectPrimitive.Root;
+
+const SelectGroup = SelectPrimitive.Group;
+
+const SelectValue = SelectPrimitive.Value;
+
+const SelectTrigger = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+ span]:line-clamp-1",
+ className,
+ )}
+ {...props}
+ >
+ {children}
+
+
+
+
+));
+SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
+
+type SelectTriggerProps = React.ComponentProps;
+
+const SelectScrollUpButton = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+));
+SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
+
+const SelectScrollDownButton = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+
+
+));
+SelectScrollDownButton.displayName =
+ SelectPrimitive.ScrollDownButton.displayName;
+
+const SelectContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, position = "popper", ...props }, ref) => (
+
+
+
+
+ {children}
+
+
+
+
+));
+SelectContent.displayName = SelectPrimitive.Content.displayName;
+
+const SelectLabel = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+SelectLabel.displayName = SelectPrimitive.Label.displayName;
+
+const SelectItem = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+
+
+
+ {children}
+
+));
+SelectItem.displayName = SelectPrimitive.Item.displayName;
+
+const SelectSeparator = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+));
+SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
+
+export {
+ Select,
+ SelectGroup,
+ SelectValue,
+ SelectTrigger,
+ SelectContent,
+ SelectLabel,
+ SelectItem,
+ SelectSeparator,
+ SelectScrollUpButton,
+ SelectScrollDownButton,
+ type SelectTriggerProps,
+};
diff --git a/apps/example/components/ui/skeleton.tsx b/apps/example/components/ui/skeleton.tsx
new file mode 100644
index 0000000..2cdf440
--- /dev/null
+++ b/apps/example/components/ui/skeleton.tsx
@@ -0,0 +1,15 @@
+import { cn } from "@/lib/utils";
+
+function Skeleton({
+ className,
+ ...props
+}: React.HTMLAttributes) {
+ return (
+
+ );
+}
+
+export { Skeleton };
diff --git a/apps/example/components/ui/sonner.tsx b/apps/example/components/ui/sonner.tsx
new file mode 100644
index 0000000..452f4d9
--- /dev/null
+++ b/apps/example/components/ui/sonner.tsx
@@ -0,0 +1,31 @@
+"use client"
+
+import { useTheme } from "next-themes"
+import { Toaster as Sonner } from "sonner"
+
+type ToasterProps = React.ComponentProps
+
+const Toaster = ({ ...props }: ToasterProps) => {
+ const { theme = "system" } = useTheme()
+
+ return (
+
+ )
+}
+
+export { Toaster }
diff --git a/apps/example/components/ui/tooltip.tsx b/apps/example/components/ui/tooltip.tsx
index 354ee98..2c42a2c 100644
--- a/apps/example/components/ui/tooltip.tsx
+++ b/apps/example/components/ui/tooltip.tsx
@@ -19,7 +19,7 @@ const TooltipContent = React.forwardRef<
ref={ref}
sideOffset={sideOffset}
className={cn(
- "z-50 overflow-hidden rounded-md border border-slate-200 bg-white px-3 py-1.5 text-sm text-slate-950 shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 dark:border-slate-800 dark:bg-slate-950 dark:text-slate-50",
+ "z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
className,
)}
{...props}
diff --git a/apps/example/lib/across.tsx b/apps/example/lib/across.tsx
new file mode 100644
index 0000000..2c28e4d
--- /dev/null
+++ b/apps/example/lib/across.tsx
@@ -0,0 +1,23 @@
+import React from "react";
+import { AcrossClient } from "@across-toolkit/sdk";
+import { SUPPORTED_CHAINS } from "./chains";
+
+const sdk = AcrossClient.create({
+ chains: [...SUPPORTED_CHAINS],
+ useTestnet: false,
+ integratorId: "TEST",
+ logLevel: "DEBUG",
+});
+
+// assuming we want to update the sdk (??), we should pass it around via context.
+const AcrossContext = React.createContext(sdk);
+
+export function AcrossProvider({ children }: { children: React.ReactNode }) {
+ return (
+ {children}
+ );
+}
+
+export function useAcross() {
+ return React.useContext(AcrossContext);
+}
diff --git a/apps/example/lib/chains.ts b/apps/example/lib/chains.ts
new file mode 100644
index 0000000..1736e9c
--- /dev/null
+++ b/apps/example/lib/chains.ts
@@ -0,0 +1,9 @@
+import { arbitrum, base, mainnet, optimism, polygon } from "wagmi/chains";
+
+export const SUPPORTED_CHAINS = [
+ arbitrum,
+ base,
+ mainnet,
+ optimism,
+ polygon,
+] as const;
diff --git a/apps/example/lib/hooks/useAvailableRoutes.tsx b/apps/example/lib/hooks/useAvailableRoutes.tsx
new file mode 100644
index 0000000..28e1666
--- /dev/null
+++ b/apps/example/lib/hooks/useAvailableRoutes.tsx
@@ -0,0 +1,27 @@
+import { useQuery } from "@tanstack/react-query";
+import { useAcross } from "../across";
+import { AcrossClient } from "@across-toolkit/sdk";
+import { buildQueryKey } from "../utils";
+
+export type useAvailableRoutesParams = Parameters<
+ AcrossClient["actions"]["getAvailableRoutes"]
+>[0];
+
+export function useAvailableRoutes(params: useAvailableRoutesParams) {
+ const sdk = useAcross();
+
+ const queryKey = buildQueryKey("availableRoutes", params);
+
+ const { data: availableRoutes, ...rest } = useQuery({
+ queryKey,
+ queryFn: () => {
+ return sdk.actions.getAvailableRoutes(params);
+ },
+ enabled: Boolean(
+ params.originChainId && params.destinationChainId && params.originToken,
+ ), // FIXME
+ refetchInterval: Infinity,
+ });
+
+ return { availableRoutes, ...rest };
+}
diff --git a/apps/example/lib/hooks/useInputTokens.tsx b/apps/example/lib/hooks/useInputTokens.tsx
new file mode 100644
index 0000000..9c33faf
--- /dev/null
+++ b/apps/example/lib/hooks/useInputTokens.tsx
@@ -0,0 +1,25 @@
+import { useQuery } from "@tanstack/react-query";
+import { useAcross } from "../across";
+
+export function useInputTokens(originChainId: number | undefined) {
+ const sdk = useAcross();
+ const queryKey = ["inputTokens", originChainId];
+
+ const { data: chains, ...rest } = useQuery({
+ queryKey,
+ queryFn: () => {
+ return sdk.utils.getSupportedChains({ chainId: originChainId });
+ },
+ enabled: Boolean(originChainId),
+ refetchInterval: Infinity,
+ retry: (_, error) => {
+ console.log(error);
+ return true;
+ },
+ });
+
+ return {
+ inputTokens: chains?.[0] ? chains[0].inputTokens : undefined,
+ ...rest,
+ };
+}
diff --git a/apps/example/lib/hooks/useOutputTokens.tsx b/apps/example/lib/hooks/useOutputTokens.tsx
new file mode 100644
index 0000000..fc74f46
--- /dev/null
+++ b/apps/example/lib/hooks/useOutputTokens.tsx
@@ -0,0 +1,25 @@
+import { useQuery } from "@tanstack/react-query";
+import { useAcross } from "../across";
+
+export function useOutputTokens(destinationChainId: number | undefined) {
+ const sdk = useAcross();
+ const queryKey = ["outputTokens", destinationChainId];
+
+ const { data: chains, ...rest } = useQuery({
+ queryKey,
+ queryFn: () => {
+ return sdk.utils.getSupportedChains({ chainId: destinationChainId });
+ },
+ enabled: Boolean(destinationChainId),
+ refetchInterval: Infinity,
+ retry: (_, error) => {
+ console.log(error);
+ return true;
+ },
+ });
+
+ return {
+ outputTokens: chains?.[0] ? chains[0].outputTokens : undefined,
+ ...rest,
+ };
+}
diff --git a/apps/example/lib/hooks/useQuote.tsx b/apps/example/lib/hooks/useQuote.tsx
new file mode 100644
index 0000000..ea352f6
--- /dev/null
+++ b/apps/example/lib/hooks/useQuote.tsx
@@ -0,0 +1,35 @@
+import { useQuery } from "@tanstack/react-query";
+import { useAcross } from "../across";
+import { AcrossClient } from "@across-toolkit/sdk";
+import { buildQueryKey } from "../utils";
+
+export type useQuoteParams =
+ | Pick<
+ Parameters[0],
+ "inputAmount" | "route"
+ >
+ | undefined;
+
+export function useQuote(params: useQuoteParams) {
+ const sdk = useAcross();
+ const queryKey = buildQueryKey("getQuote", params);
+
+ const { data: quote, ...rest } = useQuery({
+ queryKey,
+ queryFn: async () => {
+ if (!params) return;
+ return await sdk.actions.getQuote(params);
+ },
+ enabled: Boolean(params),
+ refetchInterval: 20_000,
+ retryDelay(failureCount, error) {
+ return 10_000;
+ },
+ retry: (_, error) => {
+ console.log(error);
+ return true;
+ },
+ });
+
+ return { quote, ...rest };
+}
diff --git a/apps/example/lib/hooks/useSupportedAcrossChains.tsx b/apps/example/lib/hooks/useSupportedAcrossChains.tsx
new file mode 100644
index 0000000..34399be
--- /dev/null
+++ b/apps/example/lib/hooks/useSupportedAcrossChains.tsx
@@ -0,0 +1,28 @@
+import { useQuery } from "@tanstack/react-query";
+import { useAcross } from "../across";
+import { AcrossClient } from "@across-toolkit/sdk";
+import { buildQueryKey } from "../utils";
+
+export type useAcrossChainsParams = Parameters<
+ AcrossClient["utils"]["getSupportedChains"]
+>[0];
+
+export function useSupportedAcrossChains(params: useAcrossChainsParams) {
+ const sdk = useAcross();
+ const queryKey = buildQueryKey("supportedChains", params);
+
+ const { data: supportedChains, ...rest } = useQuery({
+ queryKey,
+ queryFn: () => {
+ return sdk.utils.getSupportedChains(params);
+ },
+ enabled: true,
+ refetchInterval: Infinity,
+ retry: (_, error) => {
+ console.log(error);
+ return true;
+ },
+ });
+
+ return { supportedChains, ...rest };
+}
diff --git a/apps/example/lib/utils.ts b/apps/example/lib/utils.ts
index 8401850..4980f52 100644
--- a/apps/example/lib/utils.ts
+++ b/apps/example/lib/utils.ts
@@ -1,5 +1,7 @@
+import { ChainsQueryResponse } from "@across-toolkit/sdk";
import { type ClassValue, clsx } from "clsx";
import { twMerge } from "tailwind-merge";
+import { Chain, Hex } from "viem";
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
@@ -12,3 +14,31 @@ export function sleep(ms: number) {
}, ms);
});
}
+
+export function truncateHexString(string: Hex) {
+ return `${string.slice(0, 6)}...${string.slice(-5)}`;
+}
+
+export function reduceAcrossChains(
+ acrossChains: ChainsQueryResponse | undefined,
+ configuredChains: Chain[],
+) {
+ if (!acrossChains) return;
+ // Create a Set of IDs for efficient lookup
+ const configuredChainIds = new Set(configuredChains.map((chain) => chain.id));
+
+ // Only use across chain data this app is configured for
+ return acrossChains.filter((chain) => configuredChainIds.has(chain.chainId));
+}
+
+export function buildQueryKey(
+ queryName: string,
+ params: T,
+) {
+ if (!params) return [queryName];
+ return [queryName, ...Object.entries(params).map((entry) => entry.join("="))];
+}
+
+export type NoNullValuesOfObject = {
+ [Property in keyof T]-?: NonNullable;
+};
diff --git a/apps/example/lib/wagmi.ts b/apps/example/lib/wagmi.ts
index 4173a1e..6a32e8f 100644
--- a/apps/example/lib/wagmi.ts
+++ b/apps/example/lib/wagmi.ts
@@ -1,9 +1,9 @@
import { getDefaultConfig } from "@rainbow-me/rainbowkit";
-import { arbitrum, base, mainnet, optimism, polygon } from "wagmi/chains";
+import { SUPPORTED_CHAINS } from "./chains";
export const config = getDefaultConfig({
appName: "Across toolkit demo",
projectId: "YOUR_PROJECT_ID",
- chains: [mainnet, polygon, optimism, arbitrum, base],
+ chains: SUPPORTED_CHAINS,
ssr: true,
});
diff --git a/apps/example/package.json b/apps/example/package.json
index 93b3044..92bab25 100644
--- a/apps/example/package.json
+++ b/apps/example/package.json
@@ -14,11 +14,15 @@
"dependencies": {
"@across-toolkit/sdk": "workspace:*",
"@next/env": "^14.2.8",
+ "@radix-ui/react-dropdown-menu": "^2.1.1",
+ "@radix-ui/react-label": "^2.1.0",
"@radix-ui/react-popover": "^1.1.1",
+ "@radix-ui/react-select": "^2.1.1",
"@radix-ui/react-slot": "^1.1.0",
"@radix-ui/react-tooltip": "^1.1.2",
"@rainbow-me/rainbowkit": "^2.1.5",
"@tanstack/react-query": "^5.52.2",
+ "@uidotdev/usehooks": "^2.4.1",
"@usedapp/core": "^1.2.16",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
@@ -28,6 +32,7 @@
"next-themes": "^0.3.0",
"react": "^18",
"react-dom": "^18",
+ "sonner": "^1.5.0",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7",
"viem": "^2.20.1",
diff --git a/apps/example/tailwind.config.ts b/apps/example/tailwind.config.ts
index 11689ac..06ba1b0 100644
--- a/apps/example/tailwind.config.ts
+++ b/apps/example/tailwind.config.ts
@@ -24,17 +24,20 @@ const config = {
},
colors: {
success: "hsl(var(--success) / )",
- fail: "hsl(var(--fail) / )",
- loading: "hsl(var(--loading) / )",
- idle: "hsl(var(--idle) / )",
+ destructive: "hsl(var(--destructive) / )",
accent: "hsl(var(--accent) / )",
accent2: "hsl(var(--accent-2) / )",
- border: "hsl(var(--border) / )",
+ border: {
+ DEFAULT: "hsl(var(--border) / )",
+ secondary: "hsl(var(--border-secondary) / )",
+ input: "hsl(var(--border-secondary) / )",
+ },
background: "hsl(var(--background) / )",
foreground: "hsl(var(--foreground) / )",
text: "hsl(var(--text-color) / )",
ring: "hsl(var(--ring) / )",
- "chainlink-blue": "var(--chainlink-blue)",
+ popover: "hsl(var(--popover) / )",
+ muted: "hsl(var(--muted) / )",
},
keyframes: {
"accordion-down": {
diff --git a/packages/sdk/src/utils/getSupportedChains.ts b/packages/sdk/src/utils/getSupportedChains.ts
index 5834605..2997de8 100644
--- a/packages/sdk/src/utils/getSupportedChains.ts
+++ b/packages/sdk/src/utils/getSupportedChains.ts
@@ -37,7 +37,7 @@ export async function getSupportedChains({
return data;
}
-export type ChainsQueryResponse = {
+export type AcrossChain = {
chainId: number;
name: string;
publicRpcUrl: string;
@@ -46,4 +46,6 @@ export type ChainsQueryResponse = {
spokePool: string;
inputTokens: TokenInfo[];
outputTokens: TokenInfo[];
-}[];
+};
+
+export type ChainsQueryResponse = AcrossChain[];
diff --git a/packages/sdk/src/utils/logger.ts b/packages/sdk/src/utils/logger.ts
index 76e67d2..4cff39e 100644
--- a/packages/sdk/src/utils/logger.ts
+++ b/packages/sdk/src/utils/logger.ts
@@ -33,11 +33,10 @@ export class DefaultLogger implements LoggerT {
log(logLevel: LogLevel, ...data: any[]) {
const { label, prefix } = this.createLogLevelLabel(logLevel);
console.log(`${label}\n`);
- console.group();
+
data.forEach((item) => {
console.log(prefix, item, "\n");
});
- console.groupEnd();
}
debug(...data: any[]) {
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index c44767d..9b2d84a 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -29,9 +29,18 @@ importers:
'@next/env':
specifier: ^14.2.8
version: 14.2.8
+ '@radix-ui/react-dropdown-menu':
+ specifier: ^2.1.1
+ version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-label':
+ specifier: ^2.1.0
+ version: 2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-popover':
specifier: ^1.1.1
version: 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-select':
+ specifier: ^2.1.1
+ version: 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@radix-ui/react-slot':
specifier: ^1.1.0
version: 1.1.0(@types/react@18.3.4)(react@18.3.1)
@@ -44,6 +53,9 @@ importers:
'@tanstack/react-query':
specifier: ^5.52.2
version: 5.52.2(react@18.3.1)
+ '@uidotdev/usehooks':
+ specifier: ^2.4.1
+ version: 2.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
'@usedapp/core':
specifier: ^1.2.16
version: 1.2.16(ethers@5.7.2(bufferutil@4.0.8)(utf-8-validate@5.0.10))(node-fetch@2.7.0)(react@18.3.1)
@@ -71,6 +83,9 @@ importers:
react-dom:
specifier: ^18
version: 18.3.1(react@18.3.1)
+ sonner:
+ specifier: ^1.5.0
+ version: 1.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
tailwind-merge:
specifier: ^2.5.2
version: 2.5.2
@@ -1941,6 +1956,9 @@ packages:
resolution: {integrity: sha512-wfzX8kc1PMyUILA+1Z/EqoE4UCXGy0iRGMhPwdfae1+f0OXlLqCk+By+aMzgJBzR9AzS4CDizioG6Ss1gvAFJw==}
engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0}
+ '@radix-ui/number@1.1.0':
+ resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==}
+
'@radix-ui/primitive@1.1.0':
resolution: {integrity: sha512-4Z8dn6Upk0qk4P74xBhZ6Hd/w0mPEzOOLxy4xiPXOXqjF7jZS0VAKk7/x/H6FyY2zCkYJqePf1G5KmkmNJ4RBA==}
@@ -1957,6 +1975,19 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-collection@1.1.0':
+ resolution: {integrity: sha512-GZsZslMJEyo1VKm5L1ZJY8tGDxZNPAoUeQUIbKeJfoi7Q4kmig5AsgLMYYuyYbfjd8fBmFORAIwYAkXMnXZgZw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-compose-refs@1.1.0':
resolution: {integrity: sha512-b4inOtiaOnYf9KWyO3jAeeCG6FeyfY6ldiEPanbUjWd+xIk5wZeHa8yVwmrJ2vderhu/BQvzCrJI0lHd+wIiqw==}
peerDependencies:
@@ -1975,6 +2006,15 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-direction@1.1.0':
+ resolution: {integrity: sha512-BUuBvgThEiAXh2DWu93XsT+a3aWrGqolGlqqw5VU1kG7p/ZH2cuDlM1sRLNnY3QcBS69UIz2mcKhMxDsdewhjg==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
'@radix-ui/react-dismissable-layer@1.1.0':
resolution: {integrity: sha512-/UovfmmXGptwGcBQawLzvn2jOfM0t4z3/uKffoBlj724+n3FvBbZ7M0aaBOmkp6pqFYpO4yx8tSVJjx3Fl2jig==}
peerDependencies:
@@ -1988,6 +2028,19 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-dropdown-menu@2.1.1':
+ resolution: {integrity: sha512-y8E+x9fBq9qvteD2Zwa4397pUVhYsh9iq44b5RD5qu1GMJWBCBuVg1hMyItbc6+zH00TxGRqd9Iot4wzf3OoBQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-focus-guards@1.1.0':
resolution: {integrity: sha512-w6XZNUPVv6xCpZUqb/yN9DL6auvpGX3C/ee6Hdi16v2UUy25HV2Q5bcflsiDyT/g5RwbPQ/GIT1vLkeRb+ITBw==}
peerDependencies:
@@ -2019,6 +2072,32 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-label@2.1.0':
+ resolution: {integrity: sha512-peLblDlFw/ngk3UWq0VnYaOLy6agTZZ+MUO/WhVfm14vJGML+xH4FAl2XQGLqdefjNb7ApRg6Yn7U42ZhmYXdw==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-menu@2.1.1':
+ resolution: {integrity: sha512-oa3mXRRVjHi6DZu/ghuzdylyjaMXLymx83irM7hTxutQbD+7IhPKdMdRHD26Rm+kHRrWcrUkkRPv5pd47a2xFQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-popover@1.1.1':
resolution: {integrity: sha512-3y1A3isulwnWhvTTwmIreiB8CF4L+qRjZnK1wYLO7pplddzXKby/GnZ2M7OZY3qgnl6p9AodUIHRYGXNah8Y7g==}
peerDependencies:
@@ -2084,6 +2163,32 @@ packages:
'@types/react-dom':
optional: true
+ '@radix-ui/react-roving-focus@1.1.0':
+ resolution: {integrity: sha512-EA6AMGeq9AEeQDeSH0aZgG198qkfHSbvWTf1HvoDmOB5bBG/qTxjYMWUKMnYiV6J/iP/J8MEFSuB2zRU2n7ODA==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
+ '@radix-ui/react-select@2.1.1':
+ resolution: {integrity: sha512-8iRDfyLtzxlprOo9IicnzvpsO1wNCkuwzzCM+Z5Rb5tNOpCdMvcc2AkzX0Fz+Tz9v6NJ5B/7EEgyZveo4FBRfQ==}
+ peerDependencies:
+ '@types/react': '*'
+ '@types/react-dom': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ react-dom: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+ '@types/react-dom':
+ optional: true
+
'@radix-ui/react-slot@1.1.0':
resolution: {integrity: sha512-FUCf5XMfmW4dtYl69pdS4DbxKy8nj4M7SafBgPllysxmdachynNflAdp/gCsnYWNDnge6tI9onzMp5ARYc1KNw==}
peerDependencies:
@@ -2142,6 +2247,15 @@ packages:
'@types/react':
optional: true
+ '@radix-ui/react-use-previous@1.1.0':
+ resolution: {integrity: sha512-Z/e78qg2YFnnXcW88A4JmTtm4ADckLno6F7OXotmkQfeuCVaKuYzqAATPhVzl3delXE7CxIV8shofPn3jPc5Og==}
+ peerDependencies:
+ '@types/react': '*'
+ react: ^16.8 || ^17.0 || ^18.0 || ^19.0 || ^19.0.0-rc
+ peerDependenciesMeta:
+ '@types/react':
+ optional: true
+
'@radix-ui/react-use-rect@1.1.0':
resolution: {integrity: sha512-0Fmkebhr6PiseyZlYAOtLS+nb7jLmpqTrJyv61Pe68MKYW6OWdRE2kI70TaYY27u7H0lajqM3hSMMLFq18Z7nQ==}
peerDependencies:
@@ -2763,6 +2877,13 @@ packages:
resolution: {integrity: sha512-FhUqNWluiGNzlvnDZiXad4mZRhtghdoKW6e98GoEOYSu5cND+E39rG5KwJMUzeENwm1ztYBRqof8wMLP+wNPIA==}
engines: {node: ^16.0.0 || >=18.0.0}
+ '@uidotdev/usehooks@2.4.1':
+ resolution: {integrity: sha512-1I+RwWyS+kdv3Mv0Vmc+p0dPYH0DTRAo04HLyXReYBL9AeseDWUJyi4THuksBJcu9F0Pih69Ak150VDnqbVnXg==}
+ engines: {node: '>=16'}
+ peerDependencies:
+ react: '>=18.0.0'
+ react-dom: '>=18.0.0'
+
'@ungap/structured-clone@1.2.0':
resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
@@ -6056,6 +6177,12 @@ packages:
sonic-boom@2.8.0:
resolution: {integrity: sha512-kuonw1YOYYNOve5iHdSahXPOK49GqwA+LZhI6Wz/l0rP57iKyXXIHaRagOBHAPmGwJC6od2Z9zgvZ5loSgMlVg==}
+ sonner@1.5.0:
+ resolution: {integrity: sha512-FBjhG/gnnbN6FY0jaNnqZOMmB73R+5IiyYAw8yBj7L54ER7HB3fOSE5OFiQiE2iXWxeXKvg6fIP4LtVppHEdJA==}
+ peerDependencies:
+ react: ^18.0.0
+ react-dom: ^18.0.0
+
sort-object-keys@1.1.3:
resolution: {integrity: sha512-855pvK+VkU7PaKYPc+Jjnmt4EzejQHyhhF33q31qG8x7maDzkeFhAAThdCYay11CISO+qAMwjOBP+fPZe0IPyg==}
@@ -9103,6 +9230,8 @@ snapshots:
tiny-glob: 0.2.9
tslib: 2.6.2
+ '@radix-ui/number@1.1.0': {}
+
'@radix-ui/primitive@1.1.0': {}
'@radix-ui/react-arrow@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
@@ -9114,6 +9243,18 @@ snapshots:
'@types/react': 18.3.4
'@types/react-dom': 18.3.0
+ '@radix-ui/react-collection@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.4
+ '@types/react-dom': 18.3.0
+
'@radix-ui/react-compose-refs@1.1.0(@types/react@18.3.4)(react@18.3.1)':
dependencies:
react: 18.3.1
@@ -9126,6 +9267,12 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.4
+ '@radix-ui/react-direction@1.1.0(@types/react@18.3.4)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.4
+
'@radix-ui/react-dismissable-layer@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.0
@@ -9139,6 +9286,21 @@ snapshots:
'@types/react': 18.3.4
'@types/react-dom': 18.3.0
+ '@radix-ui/react-dropdown-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.0
+ '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-menu': 2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.4
+ '@types/react-dom': 18.3.0
+
'@radix-ui/react-focus-guards@1.1.0(@types/react@18.3.4)(react@18.3.1)':
dependencies:
react: 18.3.1
@@ -9163,6 +9325,41 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.4
+ '@radix-ui/react-label@2.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.4
+ '@types/react-dom': 18.3.0
+
+ '@radix-ui/react-menu@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.0
+ '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-id': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-presence': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-roving-focus': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ aria-hidden: 1.2.4
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-remove-scroll: 2.5.7(@types/react@18.3.4)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.4
+ '@types/react-dom': 18.3.0
+
'@radix-ui/react-popover@1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
dependencies:
'@radix-ui/primitive': 1.1.0
@@ -9233,6 +9430,52 @@ snapshots:
'@types/react': 18.3.4
'@types/react-dom': 18.3.0
+ '@radix-ui/react-roving-focus@1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/primitive': 1.1.0
+ '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-id': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.4
+ '@types/react-dom': 18.3.0
+
+ '@radix-ui/react-select@2.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ '@radix-ui/number': 1.1.0
+ '@radix-ui/primitive': 1.1.0
+ '@radix-ui/react-collection': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-context': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-direction': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-dismissable-layer': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-focus-guards': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-focus-scope': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-id': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-popper': 1.2.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-portal': 1.1.1(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-primitive': 2.0.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ '@radix-ui/react-slot': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-use-callback-ref': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-use-controllable-state': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-use-layout-effect': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-use-previous': 1.1.0(@types/react@18.3.4)(react@18.3.1)
+ '@radix-ui/react-visually-hidden': 1.1.0(@types/react-dom@18.3.0)(@types/react@18.3.4)(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
+ aria-hidden: 1.2.4
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+ react-remove-scroll: 2.5.7(@types/react@18.3.4)(react@18.3.1)
+ optionalDependencies:
+ '@types/react': 18.3.4
+ '@types/react-dom': 18.3.0
+
'@radix-ui/react-slot@1.1.0(@types/react@18.3.4)(react@18.3.1)':
dependencies:
'@radix-ui/react-compose-refs': 1.1.0(@types/react@18.3.4)(react@18.3.1)
@@ -9286,6 +9529,12 @@ snapshots:
optionalDependencies:
'@types/react': 18.3.4
+ '@radix-ui/react-use-previous@1.1.0(@types/react@18.3.4)(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ optionalDependencies:
+ '@types/react': 18.3.4
+
'@radix-ui/react-use-rect@1.1.0(@types/react@18.3.4)(react@18.3.1)':
dependencies:
'@radix-ui/rect': 1.1.0
@@ -10151,6 +10400,11 @@ snapshots:
'@typescript-eslint/types': 7.1.0
eslint-visitor-keys: 3.4.3
+ '@uidotdev/usehooks@2.4.1(react-dom@18.3.1(react@18.3.1))(react@18.3.1)':
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
'@ungap/structured-clone@1.2.0': {}
'@uniswap/token-lists@1.0.0-beta.34': {}
@@ -14295,6 +14549,11 @@ snapshots:
dependencies:
atomic-sleep: 1.0.0
+ sonner@1.5.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
+ dependencies:
+ react: 18.3.1
+ react-dom: 18.3.1(react@18.3.1)
+
sort-object-keys@1.1.3: {}
sort-package-json@2.6.0: