diff --git a/app/api/bookmarks/[bountyId]/route.ts b/app/api/bookmarks/[bountyId]/route.ts new file mode 100644 index 00000000..b4434050 --- /dev/null +++ b/app/api/bookmarks/[bountyId]/route.ts @@ -0,0 +1,51 @@ +import { NextRequest, NextResponse } from "next/server"; +import { getCurrentUser } from "@/lib/server-auth"; +import { graphqlRequest } from "@/lib/server-graphql"; +import { ToggleBookmarkDocument } from "@/lib/graphql/generated"; +import type { Bookmark } from "@/lib/graphql/generated"; + +/** + * POST /api/bookmarks/[bountyId] + * Toggles bookmark state for the given bounty + * If bookmarked → removes and returns null + * If not bookmarked → adds and returns bookmark + */ +export async function POST( + request: NextRequest, + { params }: { params: Promise<{ bountyId: string }> }, +) { + try { + const user = await getCurrentUser(); + + if (!user) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + } + + const { bountyId } = await params; + + if (!bountyId) { + return NextResponse.json( + { error: "bountyId is required" }, + { status: 400 }, + ); + } + + // Use generated GraphQL mutation document + const data = await graphqlRequest<{ toggleBookmark: Bookmark | null }>( + ToggleBookmarkDocument, + { input: { bountyId } }, + ); + + // GraphQL mutation returns the bookmark when added, null when removed + if (data.toggleBookmark) { + return NextResponse.json(data.toggleBookmark); + } else { + return NextResponse.json(null, { status: 200 }); + } + } catch (error: unknown) { + console.error("Error toggling bookmark:", error); + const message = + error instanceof Error ? error.message : "Failed to toggle bookmark"; + return NextResponse.json({ error: message }, { status: 500 }); + } +} diff --git a/app/api/bookmarks/ids/route.ts b/app/api/bookmarks/ids/route.ts new file mode 100644 index 00000000..e7ff5f28 --- /dev/null +++ b/app/api/bookmarks/ids/route.ts @@ -0,0 +1,42 @@ +import { NextResponse } from "next/server"; +import { getCurrentUser } from "@/lib/server-auth"; +import { graphqlRequest } from "@/lib/server-graphql"; + +/** + * GET /api/bookmarks/ids + * Returns an array of bookmarked bounty IDs for the current user + * Optimized for O(1) bookmark existence checks + */ +export async function GET() { + try { + const user = await getCurrentUser(); + + if (!user) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + } + + // Query GraphQL for bookmarks - we only need the IDs + const BOOKMARKS_QUERY = ` + query GetBookmarkIds { + bookmarks { + bountyId + } + } + `; + + const data = await graphqlRequest<{ + bookmarks: Array<{ bountyId: string }>; + }>(BOOKMARKS_QUERY); + + // Extract just the bounty IDs as a simple array + const bountyIds = data.bookmarks.map((b) => b.bountyId); + + return NextResponse.json(bountyIds); + } catch (error) { + console.error("Error fetching bookmark IDs:", error); + return NextResponse.json( + { error: "Failed to fetch bookmark IDs" }, + { status: 500 }, + ); + } +} diff --git a/app/api/bookmarks/route.ts b/app/api/bookmarks/route.ts new file mode 100644 index 00000000..63ca10fe --- /dev/null +++ b/app/api/bookmarks/route.ts @@ -0,0 +1,32 @@ +import { NextResponse } from "next/server"; +import { getCurrentUser } from "@/lib/server-auth"; +import { graphqlRequest } from "@/lib/server-graphql"; +import { BookmarksDocument } from "@/lib/graphql/generated"; +import type { Bookmark } from "@/lib/graphql/generated"; + +/** + * GET /api/bookmarks + * Returns all bookmarked bounties for the current user + */ +export async function GET() { + try { + const user = await getCurrentUser(); + + if (!user) { + return NextResponse.json({ error: "Unauthorized" }, { status: 401 }); + } + + // Use generated GraphQL document for type safety + const data = await graphqlRequest<{ bookmarks: Bookmark[] }>( + BookmarksDocument, + ); + + return NextResponse.json(data.bookmarks); + } catch (error) { + console.error("Error fetching bookmarks:", error); + return NextResponse.json( + { error: "Failed to fetch bookmarks" }, + { status: 500 }, + ); + } +} diff --git a/app/saved/page.tsx b/app/saved/page.tsx new file mode 100644 index 00000000..16f0927b --- /dev/null +++ b/app/saved/page.tsx @@ -0,0 +1,13 @@ +import { getCurrentUser } from "@/lib/server-auth"; +import { redirect } from "next/navigation"; +import SavedBountiesClient from "./saved-client"; + +export default async function SavedPage() { + const user = await getCurrentUser(); + + if (!user) { + redirect("/auth"); + } + + return ; +} diff --git a/app/saved/saved-client.tsx b/app/saved/saved-client.tsx new file mode 100644 index 00000000..62e33555 --- /dev/null +++ b/app/saved/saved-client.tsx @@ -0,0 +1,77 @@ +"use client"; + +import { useBookmarks } from "@/hooks/use-bookmarks"; +import { BountyCard } from "@/components/bounty/bounty-card"; +import { Skeleton } from "@/components/ui/skeleton"; +import { Bookmark } from "lucide-react"; +import Link from "next/link"; +import { Button } from "@/components/ui/button"; +import type { + Bookmark as BookmarkType, + Bounty as BountyType, +} from "@/lib/graphql/generated"; + +function SavedBountiesClient() { + const { data: bookmarks, isLoading, error } = useBookmarks(); + + if (isLoading) { + return ( +
+ {Array.from({ length: 6 }).map((_, i) => ( +
+ +
+ ))} +
+ ); + } + + if (error) { + return ( +
+

+ Failed to load saved bounties. Please try again. +

+ +
+ ); + } + + // Filter out any bookmarks with null bounty (defensive check) + const bookmarkedBounties = (bookmarks ?? []) + .filter((b): b is BookmarkType => b.bounty !== null) + .map((b) => b.bounty as BountyType); + + if (bookmarkedBounties.length === 0) { + return ( +
+
+ +
+

No saved bounties yet

+

+ Bookmark interesting bounties to save them here for later review. +

+ +
+ ); + } + + return ( +
+ {bookmarkedBounties.map((bounty) => ( + { + window.location.href = `/bounty/${bounty.id}`; + }} + /> + ))} +
+ ); +} + +export default SavedBountiesClient; diff --git a/codegen.ts b/codegen.ts index d387693e..851a6d0a 100644 --- a/codegen.ts +++ b/codegen.ts @@ -13,6 +13,11 @@ const config: CodegenConfig = { generates: { "./lib/graphql/generated.ts": { plugins: [ + { + add: { + content: "import { gql } from 'graphql-tag';", + }, + }, "typescript", "typescript-operations", "typescript-react-query", @@ -24,6 +29,7 @@ const config: CodegenConfig = { }, exposeQueryKeys: true, reactQueryVersion: 5, + documentMode: "graphQLTag", scalars: { DateTime: "string", JSON: "Record", diff --git a/components/bounty-detail/bounty-detail-header-card.tsx b/components/bounty-detail/bounty-detail-header-card.tsx index 9aaec8d9..fd00552c 100644 --- a/components/bounty-detail/bounty-detail-header-card.tsx +++ b/components/bounty-detail/bounty-detail-header-card.tsx @@ -2,13 +2,27 @@ import { ExternalLink, GitBranch } from "lucide-react"; import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"; import { BountyFieldsFragment } from "@/lib/graphql/generated"; import { StatusBadge, TypeBadge } from "./bounty-badges"; +import { BookmarkButton } from "@/components/bounty/bookmark-button"; export function HeaderCard({ bounty }: { bounty: BountyFieldsFragment }) { const orgName = bounty.organization?.name ?? "Unknown"; const orgLogo = bounty.organization?.logo; return ( -
+
+ {/* Bookmark button - top right corner */} +
e.stopPropagation()} + onKeyDown={(e) => { + if (e.key === "Enter" || e.key === " ") { + e.stopPropagation(); + } + }} + > + +
+ {/* Badges */}
diff --git a/components/bounty/bookmark-button.tsx b/components/bounty/bookmark-button.tsx new file mode 100644 index 00000000..66bcbdcf --- /dev/null +++ b/components/bounty/bookmark-button.tsx @@ -0,0 +1,121 @@ +"use client"; + +import { useMemo } from "react"; +import { Bookmark, BookmarkCheck } from "lucide-react"; +import { Button } from "@/components/ui/button"; +import { + Tooltip, + TooltipContent, + TooltipTrigger, +} from "@/components/ui/tooltip"; +import { toast } from "sonner"; +import { useBookmarkIds, useToggleBookmark } from "@/hooks/use-bookmarks"; +import { authClient } from "@/lib/auth-client"; + +interface BookmarkButtonProps { + bountyId: string; + size?: "sm" | "md" | "lg" | "icon"; + className?: string; + showLabel?: boolean; +} + +/** + * BookmarkButton component for toggling bookmark state on a bounty. + * + * Features: + * - Instant visual feedback (filled/outline icon) + * - Optimistic UI updates via React Query + * - Accessible: aria-pressed, keyboard operable + * - Handles loading state and errors + * - Shows disabled state with login tooltip for unauthenticated users + * + * @param bountyId - The bounty ID to toggle bookmark for + * @param size - Button size (default: "md") + * @param className - Additional CSS classes + * @param showLabel - Whether to show "Save" / "Saved" label (default: false, icon only) + */ +export function BookmarkButton({ + bountyId, + size = "md", + className, + showLabel = false, +}: BookmarkButtonProps) { + const { data: session } = authClient.useSession(); + const { data: bookmarkedIds } = useBookmarkIds(); + const toggleMutation = useToggleBookmark(); + + const isAuthenticated = Boolean(session?.user); + const bookmarkedIdsSet = useMemo(() => { + return new Set(bookmarkedIds ?? []); + }, [bookmarkedIds]); + + const isBookmarked = useMemo(() => { + return bookmarkedIdsSet.has(bountyId); + }, [bookmarkedIdsSet, bountyId]); + + const handleToggle = async (e: React.MouseEvent) => { + e.stopPropagation(); // Prevent card click + + if (!isAuthenticated) { + toast.error("Please log in to save bounties"); + return; + } + + try { + await toggleMutation.mutateAsync(bountyId); + } catch { + // Error handled by mutation hook + } + }; + + const isLoading = toggleMutation.isPending; + + const iconSize = size === "sm" ? 16 : size === "lg" ? 24 : 20; + const buttonSize = size === "md" ? "default" : size; + + const button = ( + + ); + + // If not authenticated, wrap in tooltip to prompt login + if (!isAuthenticated) { + return ( + + {button} + +

Log in to save bounties

+
+
+ ); + } + + return button; +} diff --git a/components/bounty/bounty-card.tsx b/components/bounty/bounty-card.tsx index 0a064867..3d2f2aff 100644 --- a/components/bounty/bounty-card.tsx +++ b/components/bounty/bounty-card.tsx @@ -16,6 +16,7 @@ import { BountyFieldsFragment } from "@/lib/graphql/generated"; import { EscrowStatus } from "./escrow-status"; import { useEscrowPool } from "@/hooks/use-escrow"; import { getRoundPhase } from "@/hooks/use-lightning-rounds"; +import { BookmarkButton } from "./bookmark-button"; interface BountyCardProps { bounty: BountyFieldsFragment; @@ -116,7 +117,7 @@ export function BountyCard({ )} + {/* Bookmark button - top-right corner */} +
e.stopPropagation()} + onKeyDown={(e) => { + if (e.key === "Enter" || e.key === " ") { + e.stopPropagation(); + } + }} + > + +
+
diff --git a/components/ui/stellar-link.tsx b/components/ui/stellar-link.tsx index 015e587b..f54df329 100644 --- a/components/ui/stellar-link.tsx +++ b/components/ui/stellar-link.tsx @@ -132,7 +132,7 @@ export function StellarLink({ const prefix = tooltipPrefix || `View ${type}`; const networkText = network || getStellarNetwork(); return `${prefix} on ${networkText} • ${explorer}`; - }, [type, network, explorer, isValid, tooltipPrefix, value]); + }, [type, network, explorer, isValid, tooltipPrefix]); if (!value || !isValid) { return ( diff --git a/hooks/use-bookmarks.ts b/hooks/use-bookmarks.ts new file mode 100644 index 00000000..c6a79fbd --- /dev/null +++ b/hooks/use-bookmarks.ts @@ -0,0 +1,130 @@ +import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"; +import { bookmarkKeys } from "@/lib/query/query-keys"; +import { get, post } from "@/lib/api/client"; +import { toast } from "sonner"; +import type { Bookmark } from "@/lib/graphql/generated"; + +const BOOKMARKS_ENDPOINT = "/api/bookmarks"; +const BOOKMARKS_IDS_ENDPOINT = "/api/bookmarks/ids"; +const BOOKMARK_STALE_TIME = 5 * 60 * 1000; // 5 minutes + +async function fetchBookmarks(): Promise { + return get(BOOKMARKS_ENDPOINT); +} + +async function fetchBookmarkIds(): Promise { + return get(BOOKMARKS_IDS_ENDPOINT); +} + +/** + * Hook to fetch and manage bookmarked bounties + */ +export function useBookmarks() { + return useQuery({ + queryKey: bookmarkKeys.list(), + queryFn: fetchBookmarks, + staleTime: BOOKMARK_STALE_TIME, + }); +} + +/** + * Hook to fetch just the bookmarked bounty IDs. + * Use this for O(1) bookmark state checks (backed by Set). + * + * NOTE: Derives from the full bookmarks query when available to keep caches in sync. + * Only falls back to independent fetch when the list cache is empty (e.g., on first load + * of a fresh session, or on the /saved page where the list is the primary source). + */ +export function useBookmarkIds() { + const queryClient = useQueryClient(); + const listData = queryClient.getQueryData(bookmarkKeys.list()); + + return useQuery({ + queryKey: bookmarkKeys.ids(), + queryFn: fetchBookmarkIds, + staleTime: BOOKMARK_STALE_TIME, + initialData: listData?.map((b) => b.bounty.id) ?? undefined, + }); +} + +/** + * Hook to toggle bookmark status for a bounty + * + * Optimistic update strategy: + * - IDs cache is the source of truth for UI state + * - List cache is derived and kept in sync when possible + * - Both caches are rolled back atomically on error + * - No fake bounty objects ever constructed + * + * All membership checks use Set for O(1) performance. + */ +export function useToggleBookmark() { + const queryClient = useQueryClient(); + + return useMutation({ + mutationFn: async (bountyId: string) => { + const response = await post( + `${BOOKMARKS_ENDPOINT}/${bountyId}`, + {}, + ); + return response; + }, + onMutate: async (bountyId: string) => { + await Promise.all([ + queryClient.cancelQueries({ queryKey: bookmarkKeys.list() }), + queryClient.cancelQueries({ queryKey: bookmarkKeys.ids() }), + ]); + + // Snapshot with safe fallbacks + const previousList = + queryClient.getQueryData(bookmarkKeys.list()) ?? []; + const previousIds = + queryClient.getQueryData(bookmarkKeys.ids()) ?? []; + + // Build Sets for O(1) membership checks + const prevIdsSet = new Set(previousIds); + const existsInIds = prevIdsSet.has(bountyId); + + // Check if real bookmark data exists in list cache + const existsInList = previousList.some((b) => b.bountyId === bountyId); + + // OPTIMISTIC UPDATE: IDs cache is authoritative + const newIds = existsInIds + ? previousIds.filter((id) => id !== bountyId) + : [bountyId, ...previousIds]; + + queryClient.setQueryData(bookmarkKeys.ids(), newIds); + + // Update list cache derivatively, only if we have real data + if (existsInList) { + const newList = previousList.filter((b) => b.bountyId !== bountyId); + queryClient.setQueryData(bookmarkKeys.list(), newList); + } + // If adding a new bookmark without cached bounty data, skip list mutation + // Server response will populate it after settlement. + + return { previousList, previousIds }; + }, + onError: (err, bountyId, context) => { + if (context) { + queryClient.setQueryData(bookmarkKeys.list(), context.previousList); + queryClient.setQueryData(bookmarkKeys.ids(), context.previousIds); + } + toast.error(`Failed to bookmark: ${err.message}`); + }, + onSettled: () => { + return Promise.all([ + queryClient.invalidateQueries({ queryKey: bookmarkKeys.list() }), + queryClient.invalidateQueries({ queryKey: bookmarkKeys.ids() }), + ]); + }, + onSuccess: (_result, variables) => { + // Source of truth: check current IDs cache using Set for O(1) + const currentIds = + queryClient.getQueryData(bookmarkKeys.ids()) ?? []; + const currentIdsSet = new Set(currentIds); + const isBookmarked = currentIdsSet.has(variables as string); + toast.success(isBookmarked ? "Bounty bookmarked!" : "Bookmark removed"); + }, + }); +} diff --git a/hooks/use-notifications.ts b/hooks/use-notifications.ts index 48e7b917..fafbb36d 100644 --- a/hooks/use-notifications.ts +++ b/hooks/use-notifications.ts @@ -1,7 +1,5 @@ -"use client"; - import { useCallback, useEffect, useMemo, useRef, useState } from "react"; -import { useQueryClient } from "@tanstack/react-query"; +import { useQueryClient, type QueryClient } from "@tanstack/react-query"; import { authClient } from "@/lib/auth-client"; import { @@ -12,14 +10,20 @@ import { type OnNewApplicationData, type OnSubmissionReviewedData, } from "@/lib/graphql/subscriptions"; -import { bountyKeys, submissionKeys } from "@/lib/query/query-keys"; +import { + bountyKeys, + submissionKeys, + bookmarkKeys, +} from "@/lib/query/query-keys"; +import type { Bookmark } from "@/lib/graphql/generated"; import { useGraphQLSubscription } from "./use-graphql-subscription"; export type NotificationType = | "bounty-updated" | "new-application" - | "submission-reviewed"; + | "submission-reviewed" + | "saved-bounty-updated"; export interface NotificationItem { id: string; @@ -83,6 +87,32 @@ function saveToStorage(userId: string, items: NotificationItem[]): void { } } +/** + * Get a Map of bountyId -> status for currently bookmarked bounties. + * Uses Set for O(1) membership filtering. + * Returns null if list cache is missing (no data available). + */ +function getBookmarkedStatusMap( + queryClient: QueryClient, +): Map | null { + const ids = queryClient.getQueryData(bookmarkKeys.ids()) ?? []; + const idsSet = new Set(ids); + const list = queryClient.getQueryData(bookmarkKeys.list()); + + // If list cache is missing or empty, return null to signal "no data" + if (!list || list.length === 0) { + return null; + } + + const statusMap = new Map(); + for (const b of list) { + if (b.bounty && idsSet.has(b.bountyId)) { + statusMap.set(b.bountyId, b.bounty.status); + } + } + return statusMap; +} + export function useNotifications() { const { data: session } = authClient.useSession(); const queryClient = useQueryClient(); @@ -90,29 +120,23 @@ export function useNotifications() { const isEnabled = Boolean(session?.user); const userId = session?.user?.id ?? null; - // Initialize state with lazy loading from localStorage - // This runs only once during initial render, avoiding setState in effect const [notifications, setNotifications] = useState(() => { if (typeof window === "undefined" || !userId) return []; return loadFromStorage(userId); }); - // Reset on user change - this is allowed during render as it's a state update - // based on a condition change (userId) const prevHydratedUserIdRef = useRef(userId); if (prevHydratedUserIdRef.current !== userId) { prevHydratedUserIdRef.current = userId; setNotifications(userId ? loadFromStorage(userId) : []); } - // Persist to localStorage whenever notifications change useEffect(() => { if (userId) { saveToStorage(userId, notifications); } }, [notifications, userId]); - // Helper to update notifications with cache invalidation const addNotification = useCallback( ( item: NotificationItem, @@ -148,6 +172,50 @@ export function useNotifications() { bountyKeys.allListKeys, ); + // Check bookmark membership using ONLY ids cache (O(1) via Set) + const bookmarkedIds = queryClient.getQueryData( + bookmarkKeys.ids(), + ); + const bookmarkedIdsSet = new Set(bookmarkedIds ?? []); + const isBookmarked = bookmarkedIdsSet.has(bounty.id); + + if (isBookmarked) { + // Get previous status from status map (derived from list cache) + const statusMap = getBookmarkedStatusMap(queryClient); + + // Only process notification if cached data exists (avoid false positives) + if (statusMap !== null) { + const previousStatus = statusMap.get(bounty.id); + + // Only notify if status changed (meaningful update) + if ( + previousStatus === undefined || + previousStatus !== bounty.status + ) { + const timestamp = Date.now(); + addNotification( + { + id: `saved-bounty-updated-${bounty.id}-${timestamp}`, + message: `Saved bounty "${bounty.title}" was updated.`, + type: "saved-bounty-updated", + timestamp: normaliseTimestamp(bounty.updatedAt), + read: false, + }, + [], + ); + + // Update status cache to prevent duplicate notifications + queryClient.setQueryData>( + bookmarkKeys.statusCache(), + (old = {}) => ({ + ...old, + [bounty.id]: bounty.status, + }), + ); + } + } + } + queryClient.invalidateQueries({ queryKey: bountyKeys.detail(bounty.id), }); diff --git a/lib/graphql/client.ts b/lib/graphql/client.ts index 762c7a4a..77cd5c0b 100644 --- a/lib/graphql/client.ts +++ b/lib/graphql/client.ts @@ -1,11 +1,23 @@ "use client"; -import { GraphQLClient } from "graphql-request"; +import { + GraphQLClient, + type RequestDocument, + type RequestOptions, + type Variables, +} from "graphql-request"; import { isAuthStatus } from "./errors"; import { toast } from "sonner"; import { getAccessToken } from "../auth-utils"; +import { TypedDocumentString } from "@/lib/graphql/generated"; -// Re-export all error utilities from errors.ts for convenience +export type GraphQLRequestDocument = + | RequestDocument + | TypedDocumentString>; + +export type GraphQLRequestHeaders = Parameters[0]; + +// Re-export all error utilities export { AppGraphQLError, ApiError, @@ -25,54 +37,75 @@ export async function hasAccessToken(): Promise { return token !== null; } -// Create the generic GraphQLClient instance +// Create GraphQL client const url = process.env.NEXT_PUBLIC_GRAPHQL_URL || "/api/graphql"; + export const graphQLClient = new GraphQLClient(url, { credentials: "include", }); -// A custom fetcher for @graphql-codegen/typescript-react-query -export const fetcher = < - TData, - TVariables extends object = Record, ->( - query: string, +/** + * Normalize any GraphQL document into a valid RequestDocument + */ +function normalizeDocument(query: GraphQLRequestDocument): RequestDocument { + if (typeof query === "string") return query; + + // TypedDocumentString behaves like string + return query.toString(); +} + +/** + * Custom fetcher for react-query + graphql-request + */ +export const fetcher = ( + query: GraphQLRequestDocument, variables?: TVariables, ) => { return async (): Promise => { const token = await getAccessToken(); - const headers: Record = {}; + + const headers: GraphQLRequestHeaders = {}; if (token) { headers.authorization = `Bearer ${token}`; } + const requestDocument = normalizeDocument(query); + try { - return await ( - graphQLClient.request as unknown as ( - q: string, - v?: TVariables, - h?: Record, - ) => Promise - )(query, variables, headers); + // Build request options and assert to RequestOptions to satisfy + // graphql-request's complex conditional types + const requestOptions = { + document: requestDocument, + variables: variables ?? ({} as TVariables), + requestHeaders: headers, + } as unknown as RequestOptions; + + return await graphQLClient.request(requestOptions); } catch (error: unknown) { - // Global error handling for auth failures + // Global auth error handling const gqlError = error as { - response?: { errors?: Array<{ extensions?: { status?: number } }> }; + response?: { + errors?: Array<{ extensions?: { status?: number } }>; + }; }; + if (gqlError?.response?.errors) { gqlError.response.errors.forEach((err) => { const status = err?.extensions?.status ?? 500; + if (isAuthStatus(status)) { - // Let the application handle unauthorized state, potentially redirecting to login if (typeof window !== "undefined") { toast.error("Your session has expired. Please log in again."); window.dispatchEvent( - new CustomEvent("auth:unauthorized", { detail: { status } }), + new CustomEvent("auth:unauthorized", { + detail: { status }, + }), ); } } }); } + throw error; } }; diff --git a/lib/graphql/generated.ts b/lib/graphql/generated.ts index da7d0be8..8cede818 100644 --- a/lib/graphql/generated.ts +++ b/lib/graphql/generated.ts @@ -1,10 +1,32 @@ import { - useMutation, useQuery, - UseMutationOptions, + useMutation, UseQueryOptions, + UseMutationOptions, } from "@tanstack/react-query"; import { fetcher } from "./client"; + +/** + * TypedDocumentString is a runtime class used by generated GraphQL documents. + * It extends String to hold the GraphQL query string and carries type metadata. + */ +export class TypedDocumentString< + TResult = unknown, + TVariables extends object = Record, +> extends String { + __apiType?: ((variables: TVariables) => TResult) | undefined; + private value: string; + __meta__?: Record | undefined; + constructor(value: string, __meta__?: Record | undefined) { + super(value); + this.value = value; + this.__meta__ = __meta__; + } + override toString(): string { + return this.value; + } +} + export type Maybe = T | null; export type InputMaybe = Maybe; export type Exact = { @@ -661,6 +683,15 @@ export enum BlogPostStatus { Scheduled = "SCHEDULED", } +export type Bookmark = { + __typename?: "Bookmark"; + bounty: Bounty; + bountyId: Scalars["String"]["output"]; + createdAt: Scalars["DateTime"]["output"]; + id: Scalars["ID"]["output"]; + userId: Scalars["String"]["output"]; +}; + export type Bounty = { __typename?: "Bounty"; _count?: Maybe; @@ -1003,6 +1034,8 @@ export type Mutation = { reviewSubmission: BountySubmissionType; /** Submit to a bounty (any authenticated user) */ submitToBounty: BountySubmissionType; + /** Toggle a bookmark on a bounty (authenticated users) */ + toggleBookmark: Bookmark; /** Update a blog post (Admin only) */ updateAdminBlogPost: AdminBlogPostDto; /** Update an existing bounty (organization members only) */ @@ -1139,6 +1172,10 @@ export type MutationSubmitToBountyArgs = { input: CreateSubmissionInput; }; +export type MutationToggleBookmarkArgs = { + input: ToggleBookmarkInput; +}; + export type MutationUpdateAdminBlogPostArgs = { id: Scalars["ID"]["input"]; input: UpdateBlogPostDto; @@ -1203,6 +1240,8 @@ export type Query = { adminUserCrowdfundingCampaigns: AdminCrowdfundingResponseDto; /** Get all users with pagination and filtering */ adminUsers: AdminUsersResponseDto; + /** Get all bookmarked bounties for the current user */ + bookmarks: Array; /** Get paginated list of bounties with filtering */ bounties: PaginatedBounties; /** Get a single bounty by ID */ @@ -1305,7 +1344,6 @@ export type QueryAdminUsersArgs = { isActive?: InputMaybe; limit?: InputMaybe; page?: InputMaybe; - role?: InputMaybe; search?: InputMaybe; }; @@ -1368,6 +1406,10 @@ export enum RewardDistributionStatus { Rejected = "REJECTED", } +export type ToggleBookmarkInput = { + bountyId: Scalars["ID"]["input"]; +}; + export type UpdateBlogPostDto = { categories?: InputMaybe>; content?: InputMaybe; @@ -1409,6 +1451,114 @@ export type UserLeaderboardRankResponse = { rank: Scalars["Int"]["output"]; }; +export type BookmarksQueryVariables = Exact<{ [key: string]: never }>; + +export type BookmarksQuery = { + __typename?: "Query"; + bookmarks: Array<{ + __typename?: "Bookmark"; + id: string; + userId: string; + bountyId: string; + createdAt: string; + bounty: { + __typename?: "Bounty"; + id: string; + title: string; + description: string; + status: string; + type: string; + rewardAmount: number; + rewardCurrency: string; + createdAt: string; + updatedAt: string; + organizationId: string; + projectId?: string | null; + bountyWindowId?: string | null; + githubIssueUrl: string; + githubIssueNumber?: number | null; + createdBy: string; + organization?: { + __typename?: "BountyOrganization"; + id: string; + name: string; + logo?: string | null; + slug?: string | null; + } | null; + project?: { + __typename?: "BountyProject"; + id: string; + title: string; + description?: string | null; + } | null; + bountyWindow?: { + __typename?: "BountyWindowType"; + id: string; + name: string; + status: string; + startDate?: string | null; + endDate?: string | null; + } | null; + _count?: { __typename?: "BountyCount"; submissions: number } | null; + }; + }>; +}; + +export type ToggleBookmarkMutationVariables = Exact<{ + input: ToggleBookmarkInput; +}>; + +export type ToggleBookmarkMutation = { + __typename?: "Mutation"; + toggleBookmark: { + __typename?: "Bookmark"; + id: string; + userId: string; + bountyId: string; + createdAt: string; + bounty: { + __typename?: "Bounty"; + id: string; + title: string; + description: string; + status: string; + type: string; + rewardAmount: number; + rewardCurrency: string; + createdAt: string; + updatedAt: string; + organizationId: string; + projectId?: string | null; + bountyWindowId?: string | null; + githubIssueUrl: string; + githubIssueNumber?: number | null; + createdBy: string; + organization?: { + __typename?: "BountyOrganization"; + id: string; + name: string; + logo?: string | null; + slug?: string | null; + } | null; + project?: { + __typename?: "BountyProject"; + id: string; + title: string; + description?: string | null; + } | null; + bountyWindow?: { + __typename?: "BountyWindowType"; + id: string; + name: string; + status: string; + startDate?: string | null; + endDate?: string | null; + } | null; + _count?: { __typename?: "BountyCount"; submissions: number } | null; + }; + }; +}; + export type CreateBountyMutationVariables = Exact<{ input: CreateBountyInput; }>; @@ -2103,7 +2253,8 @@ export type MarkSubmissionPaidMutation = { }; }; -export const BountyFieldsFragmentDoc = ` +export const BountyFieldsFragmentDoc = new TypedDocumentString( + ` fragment BountyFields on Bounty { id title @@ -2142,8 +2293,11 @@ export const BountyFieldsFragmentDoc = ` submissions } } - `; -export const SubmissionFieldsFragmentDoc = ` + `, + { fragmentName: "BountyFields" }, +); +export const SubmissionFieldsFragmentDoc = new TypedDocumentString( + ` fragment SubmissionFields on BountySubmissionType { id bountyId @@ -2168,8 +2322,11 @@ export const SubmissionFieldsFragmentDoc = ` paidAt rewardTransactionHash } - `; -export const SubmissionFieldsWithContactFragmentDoc = ` + `, + { fragmentName: "SubmissionFields" }, +); +export const SubmissionFieldsWithContactFragmentDoc = new TypedDocumentString( + ` fragment SubmissionFieldsWithContact on BountySubmissionType { ...SubmissionFields submittedByUser { @@ -2179,51 +2336,296 @@ export const SubmissionFieldsWithContactFragmentDoc = ` email } } - ${SubmissionFieldsFragmentDoc}`; -export const CreateBountyDocument = ` - mutation CreateBounty($input: CreateBountyInput!) { - createBounty(input: $input) { - ...BountyFields + fragment SubmissionFields on BountySubmissionType { + id + bountyId + submittedBy + submittedByUser { + id + name + image + } + githubPullRequestUrl + status + createdAt + updatedAt + reviewedAt + reviewedBy + reviewedByUser { + id + name + image + } + reviewComments + paidAt + rewardTransactionHash +}`, + { fragmentName: "SubmissionFieldsWithContact" }, +); +export const BookmarksDocument = new TypedDocumentString(` + query Bookmarks { + bookmarks { + id + userId + bountyId + createdAt + bounty { + ...BountyFields + } } } - ${BountyFieldsFragmentDoc}`; + fragment BountyFields on Bounty { + id + title + description + status + type + rewardAmount + rewardCurrency + createdAt + updatedAt + organizationId + projectId + bountyWindowId + githubIssueUrl + githubIssueNumber + createdBy + organization { + id + name + logo + slug + } + project { + id + title + description + } + bountyWindow { + id + name + status + startDate + endDate + } + _count { + submissions + } +}`); -export const useCreateBountyMutation = ( +export const useBookmarksQuery = ( + variables?: BookmarksQueryVariables, + options?: Omit, "queryKey"> & { + queryKey?: UseQueryOptions["queryKey"]; + }, +) => { + return useQuery({ + queryKey: + variables === undefined ? ["Bookmarks"] : ["Bookmarks", variables], + queryFn: fetcher( + BookmarksDocument, + variables, + ), + ...options, + }); +}; + +useBookmarksQuery.getKey = (variables?: BookmarksQueryVariables) => + variables === undefined ? ["Bookmarks"] : ["Bookmarks", variables]; + +export const ToggleBookmarkDocument = new TypedDocumentString(` + mutation ToggleBookmark($input: ToggleBookmarkInput!) { + toggleBookmark(input: $input) { + id + userId + bountyId + createdAt + bounty { + ...BountyFields + } + } +} + fragment BountyFields on Bounty { + id + title + description + status + type + rewardAmount + rewardCurrency + createdAt + updatedAt + organizationId + projectId + bountyWindowId + githubIssueUrl + githubIssueNumber + createdBy + organization { + id + name + logo + slug + } + project { + id + title + description + } + bountyWindow { + id + name + status + startDate + endDate + } + _count { + submissions + } +}`); + +export const useToggleBookmarkMutation = ( options?: UseMutationOptions< - CreateBountyMutation, + ToggleBookmarkMutation, TError, - CreateBountyMutationVariables, + ToggleBookmarkMutationVariables, TContext >, ) => { return useMutation< - CreateBountyMutation, + ToggleBookmarkMutation, TError, - CreateBountyMutationVariables, + ToggleBookmarkMutationVariables, TContext >({ - mutationKey: ["CreateBounty"], - mutationFn: (variables?: CreateBountyMutationVariables) => - fetcher( - CreateBountyDocument, + mutationKey: ["ToggleBookmark"], + mutationFn: (variables?: ToggleBookmarkMutationVariables) => + fetcher( + ToggleBookmarkDocument, variables, )(), ...options, }); }; -export const UpdateBountyDocument = ` - mutation UpdateBounty($input: UpdateBountyInput!) { - updateBounty(input: $input) { +export const CreateBountyDocument = new TypedDocumentString(` + mutation CreateBounty($input: CreateBountyInput!) { + createBounty(input: $input) { ...BountyFields } } - ${BountyFieldsFragmentDoc}`; - -export const useUpdateBountyMutation = ( - options?: UseMutationOptions< - UpdateBountyMutation, - TError, + fragment BountyFields on Bounty { + id + title + description + status + type + rewardAmount + rewardCurrency + createdAt + updatedAt + organizationId + projectId + bountyWindowId + githubIssueUrl + githubIssueNumber + createdBy + organization { + id + name + logo + slug + } + project { + id + title + description + } + bountyWindow { + id + name + status + startDate + endDate + } + _count { + submissions + } +}`); + +export const useCreateBountyMutation = ( + options?: UseMutationOptions< + CreateBountyMutation, + TError, + CreateBountyMutationVariables, + TContext + >, +) => { + return useMutation< + CreateBountyMutation, + TError, + CreateBountyMutationVariables, + TContext + >({ + mutationKey: ["CreateBounty"], + mutationFn: (variables?: CreateBountyMutationVariables) => + fetcher( + CreateBountyDocument, + variables, + )(), + ...options, + }); +}; + +export const UpdateBountyDocument = new TypedDocumentString(` + mutation UpdateBounty($input: UpdateBountyInput!) { + updateBounty(input: $input) { + ...BountyFields + } +} + fragment BountyFields on Bounty { + id + title + description + status + type + rewardAmount + rewardCurrency + createdAt + updatedAt + organizationId + projectId + bountyWindowId + githubIssueUrl + githubIssueNumber + createdBy + organization { + id + name + logo + slug + } + project { + id + title + description + } + bountyWindow { + id + name + status + startDate + endDate + } + _count { + submissions + } +}`); + +export const useUpdateBountyMutation = ( + options?: UseMutationOptions< + UpdateBountyMutation, + TError, UpdateBountyMutationVariables, TContext >, @@ -2244,11 +2646,11 @@ export const useUpdateBountyMutation = ( }); }; -export const DeleteBountyDocument = ` +export const DeleteBountyDocument = new TypedDocumentString(` mutation DeleteBounty($id: ID!) { deleteBounty(id: $id) } - `; + `); export const useDeleteBountyMutation = ( options?: UseMutationOptions< @@ -2274,7 +2676,7 @@ export const useDeleteBountyMutation = ( }); }; -export const BountiesDocument = ` +export const BountiesDocument = new TypedDocumentString(` query Bounties($query: BountyQueryInput) { bounties(query: $query) { bounties { @@ -2285,7 +2687,44 @@ export const BountiesDocument = ` offset } } - ${BountyFieldsFragmentDoc}`; + fragment BountyFields on Bounty { + id + title + description + status + type + rewardAmount + rewardCurrency + createdAt + updatedAt + organizationId + projectId + bountyWindowId + githubIssueUrl + githubIssueNumber + createdBy + organization { + id + name + logo + slug + } + project { + id + title + description + } + bountyWindow { + id + name + status + startDate + endDate + } + _count { + submissions + } +}`); export const useBountiesQuery = ( variables?: BountiesQueryVariables, @@ -2306,7 +2745,7 @@ export const useBountiesQuery = ( useBountiesQuery.getKey = (variables?: BountiesQueryVariables) => variables === undefined ? ["Bounties"] : ["Bounties", variables]; -export const BountyDocument = ` +export const BountyDocument = new TypedDocumentString(` query Bounty($id: ID!) { bounty(id: $id) { ...BountyFields @@ -2315,8 +2754,68 @@ export const BountyDocument = ` } } } - ${BountyFieldsFragmentDoc} -${SubmissionFieldsFragmentDoc}`; + fragment BountyFields on Bounty { + id + title + description + status + type + rewardAmount + rewardCurrency + createdAt + updatedAt + organizationId + projectId + bountyWindowId + githubIssueUrl + githubIssueNumber + createdBy + organization { + id + name + logo + slug + } + project { + id + title + description + } + bountyWindow { + id + name + status + startDate + endDate + } + _count { + submissions + } +} +fragment SubmissionFields on BountySubmissionType { + id + bountyId + submittedBy + submittedByUser { + id + name + image + } + githubPullRequestUrl + status + createdAt + updatedAt + reviewedAt + reviewedBy + reviewedByUser { + id + name + image + } + reviewComments + paidAt + rewardTransactionHash +}`); export const useBountyQuery = ( variables: BountyQueryVariables, @@ -2339,13 +2838,50 @@ useBountyQuery.getKey = (variables: BountyQueryVariables) => [ variables, ]; -export const ActiveBountiesDocument = ` +export const ActiveBountiesDocument = new TypedDocumentString(` query ActiveBounties { activeBounties { ...BountyFields } } - ${BountyFieldsFragmentDoc}`; + fragment BountyFields on Bounty { + id + title + description + status + type + rewardAmount + rewardCurrency + createdAt + updatedAt + organizationId + projectId + bountyWindowId + githubIssueUrl + githubIssueNumber + createdBy + organization { + id + name + logo + slug + } + project { + id + title + description + } + bountyWindow { + id + name + status + startDate + endDate + } + _count { + submissions + } +}`); export const useActiveBountiesQuery = < TData = ActiveBountiesQuery, @@ -2375,13 +2911,50 @@ export const useActiveBountiesQuery = < useActiveBountiesQuery.getKey = (variables?: ActiveBountiesQueryVariables) => variables === undefined ? ["ActiveBounties"] : ["ActiveBounties", variables]; -export const OrganizationBountiesDocument = ` +export const OrganizationBountiesDocument = new TypedDocumentString(` query OrganizationBounties($organizationId: ID!) { organizationBounties(organizationId: $organizationId) { ...BountyFields } } - ${BountyFieldsFragmentDoc}`; + fragment BountyFields on Bounty { + id + title + description + status + type + rewardAmount + rewardCurrency + createdAt + updatedAt + organizationId + projectId + bountyWindowId + githubIssueUrl + githubIssueNumber + createdBy + organization { + id + name + logo + slug + } + project { + id + title + description + } + bountyWindow { + id + name + status + startDate + endDate + } + _count { + submissions + } +}`); export const useOrganizationBountiesQuery = < TData = OrganizationBountiesQuery, @@ -2413,13 +2986,50 @@ useOrganizationBountiesQuery.getKey = ( variables: OrganizationBountiesQueryVariables, ) => ["OrganizationBounties", variables]; -export const ProjectBountiesDocument = ` +export const ProjectBountiesDocument = new TypedDocumentString(` query ProjectBounties($projectId: ID!) { projectBounties(projectId: $projectId) { ...BountyFields } } - ${BountyFieldsFragmentDoc}`; + fragment BountyFields on Bounty { + id + title + description + status + type + rewardAmount + rewardCurrency + createdAt + updatedAt + organizationId + projectId + bountyWindowId + githubIssueUrl + githubIssueNumber + createdBy + organization { + id + name + logo + slug + } + project { + id + title + description + } + bountyWindow { + id + name + status + startDate + endDate + } + _count { + submissions + } +}`); export const useProjectBountiesQuery = < TData = ProjectBountiesQuery, @@ -2448,7 +3058,7 @@ useProjectBountiesQuery.getKey = (variables: ProjectBountiesQueryVariables) => [ variables, ]; -export const LeaderboardDocument = ` +export const LeaderboardDocument = new TypedDocumentString(` query Leaderboard($filters: LeaderboardFilters!, $pagination: LeaderboardPagination!) { leaderboard(filters: $filters, pagination: $pagination) { entries { @@ -2483,7 +3093,7 @@ export const LeaderboardDocument = ` lastUpdatedAt } } - `; + `); export const useLeaderboardQuery = ( variables: LeaderboardQueryVariables, @@ -2509,7 +3119,7 @@ useLeaderboardQuery.getKey = (variables: LeaderboardQueryVariables) => [ variables, ]; -export const UserLeaderboardRankDocument = ` +export const UserLeaderboardRankDocument = new TypedDocumentString(` query UserLeaderboardRank($userId: ID!) { userLeaderboardRank(userId: $userId) { rank @@ -2537,7 +3147,7 @@ export const UserLeaderboardRankDocument = ` } } } - `; + `); export const useUserLeaderboardRankQuery = < TData = UserLeaderboardRankQuery, @@ -2569,7 +3179,7 @@ useUserLeaderboardRankQuery.getKey = ( variables: UserLeaderboardRankQueryVariables, ) => ["UserLeaderboardRank", variables]; -export const TopContributorsDocument = ` +export const TopContributorsDocument = new TypedDocumentString(` query TopContributors($count: Int = 5) { topContributors(count: $count) { id @@ -2594,7 +3204,7 @@ export const TopContributorsDocument = ` lastActiveAt } } - `; + `); export const useTopContributorsQuery = < TData = TopContributorsQuery, @@ -2626,13 +3236,36 @@ useTopContributorsQuery.getKey = (variables?: TopContributorsQueryVariables) => ? ["TopContributors"] : ["TopContributors", variables]; -export const SubmitToBountyDocument = ` +export const SubmitToBountyDocument = new TypedDocumentString(` mutation SubmitToBounty($input: CreateSubmissionInput!) { submitToBounty(input: $input) { ...SubmissionFields } } - ${SubmissionFieldsFragmentDoc}`; + fragment SubmissionFields on BountySubmissionType { + id + bountyId + submittedBy + submittedByUser { + id + name + image + } + githubPullRequestUrl + status + createdAt + updatedAt + reviewedAt + reviewedBy + reviewedByUser { + id + name + image + } + reviewComments + paidAt + rewardTransactionHash +}`); export const useSubmitToBountyMutation = ( options?: UseMutationOptions< @@ -2658,13 +3291,36 @@ export const useSubmitToBountyMutation = ( }); }; -export const ReviewSubmissionDocument = ` +export const ReviewSubmissionDocument = new TypedDocumentString(` mutation ReviewSubmission($input: ReviewSubmissionInput!) { reviewSubmission(input: $input) { ...SubmissionFields } } - ${SubmissionFieldsFragmentDoc}`; + fragment SubmissionFields on BountySubmissionType { + id + bountyId + submittedBy + submittedByUser { + id + name + image + } + githubPullRequestUrl + status + createdAt + updatedAt + reviewedAt + reviewedBy + reviewedByUser { + id + name + image + } + reviewComments + paidAt + rewardTransactionHash +}`); export const useReviewSubmissionMutation = < TError = unknown, @@ -2693,7 +3349,7 @@ export const useReviewSubmissionMutation = < }); }; -export const MarkSubmissionPaidDocument = ` +export const MarkSubmissionPaidDocument = new TypedDocumentString(` mutation MarkSubmissionPaid($submissionId: ID!, $transactionHash: String!) { markSubmissionPaid( submissionId: $submissionId @@ -2702,7 +3358,30 @@ export const MarkSubmissionPaidDocument = ` ...SubmissionFields } } - ${SubmissionFieldsFragmentDoc}`; + fragment SubmissionFields on BountySubmissionType { + id + bountyId + submittedBy + submittedByUser { + id + name + image + } + githubPullRequestUrl + status + createdAt + updatedAt + reviewedAt + reviewedBy + reviewedByUser { + id + name + image + } + reviewComments + paidAt + rewardTransactionHash +}`); export const useMarkSubmissionPaidMutation = < TError = unknown, diff --git a/lib/graphql/operations/bookmark-operations.graphql b/lib/graphql/operations/bookmark-operations.graphql new file mode 100644 index 00000000..7ce9bb15 --- /dev/null +++ b/lib/graphql/operations/bookmark-operations.graphql @@ -0,0 +1,23 @@ +query Bookmarks { + bookmarks { + id + userId + bountyId + createdAt + bounty { + ...BountyFields + } + } +} + +mutation ToggleBookmark($input: ToggleBookmarkInput!) { + toggleBookmark(input: $input) { + id + userId + bountyId + createdAt + bounty { + ...BountyFields + } + } +} diff --git a/lib/graphql/schema.graphql b/lib/graphql/schema.graphql index cdfb4a81..fa4d043b 100644 --- a/lib/graphql/schema.graphql +++ b/lib/graphql/schema.graphql @@ -701,6 +701,18 @@ type BountyWindowType { status: String! } +type Bookmark { + id: ID! + userId: String! + bountyId: String! + createdAt: DateTime! + bounty: Bounty! +} + +input ToggleBookmarkInput { + bountyId: ID! +} + input ContactOrganizersInput { message: String! subject: String! @@ -906,6 +918,9 @@ type Mutation { """Submit to a bounty (any authenticated user)""" submitToBounty(input: CreateSubmissionInput!): BountySubmissionType! + """Toggle a bookmark on a bounty (authenticated users)""" + toggleBookmark(input: ToggleBookmarkInput!): Bookmark + """Update a blog post (Admin only)""" updateAdminBlogPost(id: ID!, input: UpdateBlogPostDto!): AdminBlogPostDto! @@ -982,7 +997,7 @@ type Query { adminUserCrowdfundingCampaigns(limit: Int = 20, page: Int = 1, usernameOrId: String!): AdminCrowdfundingResponseDto! """Get all users with pagination and filtering""" - adminUsers(isActive: Boolean, limit: Int, page: Int, role: String, search: String): AdminUsersResponseDto! + adminUsers(isActive: Boolean, limit: Int, page: Int, search: String): AdminUsersResponseDto! """Get paginated list of bounties with filtering""" bounties(query: BountyQueryInput): PaginatedBounties! @@ -996,6 +1011,9 @@ type Query { """Get bounties for a specific project""" projectBounties(projectId: ID!): [Bounty!]! + """Get all bookmarked bounties for the current user""" + bookmarks: [Bookmark!]! + """Get leaderboard with filtering and pagination""" leaderboard(filters: LeaderboardFilters!, pagination: LeaderboardPagination!): LeaderboardResponse! diff --git a/lib/query/query-keys.ts b/lib/query/query-keys.ts index 6ac19098..8192321e 100644 --- a/lib/query/query-keys.ts +++ b/lib/query/query-keys.ts @@ -107,3 +107,17 @@ export const withdrawalKeys = { all: ["withdrawal"] as const, history: () => [...withdrawalKeys.all, "history"] as const, }; + +/** + * Query Key Factory for Bookmarks + */ +export const bookmarkKeys = { + all: ["bookmarks"] as const, + list: () => [...bookmarkKeys.all, "list"] as const, + ids: () => [...bookmarkKeys.all, "ids"] as const, + // Minimal status cache for notification deduplication: { [bountyId]: status } + statusCache: () => [...bookmarkKeys.all, "statusCache"] as const, +}; + +export type BookmarkQueryKey = ReturnType; +export type BookmarkIdsQueryKey = ReturnType; diff --git a/lib/server-graphql.ts b/lib/server-graphql.ts new file mode 100644 index 00000000..4b9fee5c --- /dev/null +++ b/lib/server-graphql.ts @@ -0,0 +1,43 @@ +import { getAccessToken } from "@/lib/auth-utils"; +import { TypedDocumentString } from "@/lib/graphql/generated"; + +const GRAPHQL_URL = process.env.NEXT_PUBLIC_GRAPHQL_URL || "/api/graphql"; + +/** + * Server-side GraphQL client using fetch with cookie-based auth + * Use this in Server Components and Route Handlers + */ +export async function graphqlRequest( + query: string | TypedDocumentString>, + variables?: Record, +): Promise { + const token = await getAccessToken(); + const headers: Record = { + "Content-Type": "application/json", + }; + if (token) { + headers.authorization = `Bearer ${token}`; + } + + // Normalize: if TypedDocumentString, convert to string + const queryString = typeof query === "string" ? query : query.toString(); + + const response = await fetch(GRAPHQL_URL, { + method: "POST", + headers, + body: JSON.stringify({ query, variables }), + // Don't cache - always get fresh data + cache: "no-store", + }); + + if (!response.ok) { + throw new Error(`GraphQL request failed: ${response.status}`); + } + + const json = await response.json(); + if (json.errors) { + throw new Error(json.errors[0]?.message || "GraphQL error"); + } + + return json.data; +} diff --git a/package-lock.json b/package-lock.json index c14f2d78..d391fa83 100644 --- a/package-lock.json +++ b/package-lock.json @@ -77,6 +77,7 @@ "@graphql-codegen/typescript": "^5.0.8", "@graphql-codegen/typescript-operations": "^5.0.8", "@graphql-codegen/typescript-react-query": "^7.0.0", + "@graphql-typed-document-node/core": "^3.2.0", "@next/swc-wasm-nodejs": "^16.1.6", "@tailwindcss/postcss": "^4", "@tailwindcss/typography": "^0.5.19", @@ -145,7 +146,7 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@csstools/css-calc": "^2.1.3", @@ -159,7 +160,7 @@ "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, + "devOptional": true, "license": "ISC" }, "node_modules/@babel/code-frame": { @@ -1101,21 +1102,6 @@ } } }, - "node_modules/@creit-tech/stellar-wallets-kit/node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "license": "Apache-2.0", - "optional": true, - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, "node_modules/@creit.tech/xbull-wallet-connect": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/@creit.tech/xbull-wallet-connect/-/xbull-wallet-connect-0.4.0.tgz", @@ -1157,7 +1143,7 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -1177,7 +1163,7 @@ "version": "2.1.4", "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -1201,7 +1187,7 @@ "version": "3.1.0", "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -1229,7 +1215,7 @@ "version": "3.0.5", "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -1252,7 +1238,7 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", - "dev": true, + "devOptional": true, "funding": [ { "type": "github", @@ -1278,7 +1264,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@emnapi/core/-/core-1.9.1.tgz", "integrity": "sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -1300,7 +1285,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/@emnapi/wasi-threads/-/wasi-threads-1.2.0.tgz", "integrity": "sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -6862,7 +6846,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6879,7 +6862,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6896,7 +6878,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6913,7 +6894,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6930,7 +6910,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6947,7 +6926,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6964,7 +6942,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6981,7 +6958,6 @@ "cpu": [ "ppc64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -6998,7 +6974,6 @@ "cpu": [ "s390x" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7015,7 +6990,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7032,7 +7006,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7049,7 +7022,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7066,7 +7038,6 @@ "cpu": [ "wasm32" ], - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -7080,7 +7051,6 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/@napi-rs/wasm-runtime/-/wasm-runtime-1.1.2.tgz", "integrity": "sha512-sNXv5oLJ7ob93xkZ1XnxisYhGYXfaG9f65/ZgYuAu3qt7b3NadcOEhLvx28hv31PgX8SZJRYrAIPQilQmFpLVw==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -7102,7 +7072,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -7119,7 +7088,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MIT", "optional": true, "os": [ @@ -10904,7 +10872,6 @@ "version": "0.10.1", "resolved": "https://registry.npmjs.org/@tybys/wasm-util/-/wasm-util-0.10.1.tgz", "integrity": "sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -12184,21 +12151,6 @@ "ws": "^7.5.1" } }, - "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/@walletconnect/jsonrpc-ws-connection/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", @@ -14840,7 +14792,7 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@asamuzakjp/css-color": "^3.2.0", @@ -14998,7 +14950,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "whatwg-mimetype": "^4.0.0", @@ -15134,7 +15086,7 @@ "version": "10.6.0", "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz", "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/decimal.js-light": { @@ -15598,7 +15550,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, + "devOptional": true, "license": "BSD-2-Clause", "engines": { "node": ">=0.12" @@ -16839,7 +16791,6 @@ "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -17634,7 +17585,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "whatwg-encoding": "^3.1.1" @@ -17698,7 +17649,7 @@ "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.0", @@ -17712,7 +17663,7 @@ "version": "7.0.6", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "agent-base": "^7.1.2", @@ -18393,7 +18344,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", "integrity": "sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/is-property": { @@ -18864,21 +18815,6 @@ "ws": "*" } }, - "node_modules/jayson/node_modules/utf-8-validate": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/utf-8-validate/-/utf-8-validate-5.0.10.tgz", - "integrity": "sha512-Z6czzLq4u8fPOyx7TU6X3dvUZVvoJmxSQ+IcrlmagKhilxlhZgxPK6C5Jqbkw1IDUmFTM+cz9QDnnLTwDz/2gQ==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "peer": true, - "dependencies": { - "node-gyp-build": "^4.3.0" - }, - "engines": { - "node": ">=6.14.2" - } - }, "node_modules/jayson/node_modules/ws": { "version": "7.5.10", "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", @@ -19834,7 +19770,7 @@ "version": "2.6.1", "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "jiti": "lib/jiti-cli.mjs" @@ -19878,7 +19814,7 @@ "version": "26.1.0", "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-26.1.0.tgz", "integrity": "sha512-Cvc9WUhxSMEo4McES3P7oK3QaXldCfNWp7pl2NNeiIFlCoLr3kfq9kb1fxftiwk1FLV7CvpvDfonxtzUDeSOPg==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "cssstyle": "^4.2.1", @@ -20141,7 +20077,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20162,7 +20097,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20183,7 +20117,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20204,7 +20137,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20225,7 +20157,6 @@ "cpu": [ "arm" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20246,7 +20177,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20267,7 +20197,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20288,7 +20217,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20309,7 +20237,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20330,7 +20257,6 @@ "cpu": [ "arm64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -20351,7 +20277,6 @@ "cpu": [ "x64" ], - "dev": true, "license": "MPL-2.0", "optional": true, "os": [ @@ -22368,7 +22293,7 @@ "version": "2.2.23", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.23.tgz", "integrity": "sha512-7wfH4sLbt4M0gCDzGE6vzQBo0bfTKjU7Sfpqy/7gs1qBfYz2vEJH6vXcBKpO3+6Yu1telwd0t9HpyOoLEQQbIQ==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/object-assign": { @@ -22767,7 +22692,7 @@ "version": "7.3.0", "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "entities": "^6.0.0" @@ -23287,7 +23212,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6" @@ -24434,7 +24359,7 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/run-parallel": { @@ -24558,14 +24483,14 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", "integrity": "sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==", - "dev": true, + "devOptional": true, "license": "ISC", "dependencies": { "xmlchars": "^2.2.0" @@ -25650,7 +25575,7 @@ "version": "3.2.4", "resolved": "https://registry.npmjs.org/symbol-tree/-/symbol-tree-3.2.4.tgz", "integrity": "sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/sync-fetch": { @@ -25882,7 +25807,7 @@ "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.86.tgz", "integrity": "sha512-WMi/OQ2axVTf/ykqCQgXiIct+mSQDFdH2fkwhPwgEwvJ1kSzZRiinb0zF2Xb8u4+OqPChmyI6MEu4EezNJz+FQ==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "tldts-core": "^6.1.86" @@ -25895,7 +25820,7 @@ "version": "6.1.86", "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.86.tgz", "integrity": "sha512-Je6p7pkk+KMzMv2XXKmAE3McmolOQFdxkKw0R8EYNr7sELW46JqnNeTX8ybPiQgvg1ymCoF8LXs5fzFaZvJPTA==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/tmpl": { @@ -25952,7 +25877,7 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.1.2.tgz", "integrity": "sha512-FVDYdxtnj0G6Qm/DhNPSb8Ju59ULcup3tuJxkFb5K8Bv2pUXILbf0xZWU8PX8Ov19OXljbUyveOFwRMwkXzO+A==", - "dev": true, + "devOptional": true, "license": "BSD-3-Clause", "dependencies": { "tldts": "^6.1.32" @@ -25965,7 +25890,7 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" @@ -27228,7 +27153,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", "integrity": "sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "xml-name-validator": "^5.0.0" @@ -27261,7 +27186,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, + "devOptional": true, "license": "BSD-2-Clause", "engines": { "node": ">=12" @@ -27272,7 +27197,7 @@ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "iconv-lite": "0.6.3" @@ -27285,7 +27210,7 @@ "version": "0.6.3", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" @@ -27298,7 +27223,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=18" @@ -27308,7 +27233,7 @@ "version": "14.2.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "tr46": "^5.1.0", @@ -27629,7 +27554,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", "integrity": "sha512-EvGK8EJ3DhaHfbRlETOWAS5pO9MZITeauHKJyb8wyajUfQUenkIg2MvLDTZ4T/TgIcm3HU0TFBgWWboAZ30UHg==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "engines": { "node": ">=18" @@ -27639,7 +27564,7 @@ "version": "2.2.0", "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/xrpl": { @@ -27694,7 +27619,7 @@ "version": "2.8.3", "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", - "dev": true, + "devOptional": true, "license": "ISC", "bin": { "yaml": "bin.mjs" diff --git a/package.json b/package.json index c2f54505..7587ee2f 100644 --- a/package.json +++ b/package.json @@ -84,6 +84,7 @@ "@graphql-codegen/typescript": "^5.0.8", "@graphql-codegen/typescript-operations": "^5.0.8", "@graphql-codegen/typescript-react-query": "^7.0.0", + "@graphql-typed-document-node/core": "^3.2.0", "@next/swc-wasm-nodejs": "^16.1.6", "@tailwindcss/postcss": "^4", "@tailwindcss/typography": "^0.5.19", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5e9af7a4..fa0720d3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,7 +10,7 @@ importers: dependencies: '@creit-tech/stellar-wallets-kit': specifier: npm:@creit.tech/stellar-wallets-kit@^2.0.1 - version: '@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6)' + version: '@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6)' '@hookform/resolvers': specifier: ^5.2.2 version: 5.2.2(react-hook-form@7.71.1(react@19.2.3)) @@ -139,7 +139,7 @@ importers: version: 2.12.6(graphql@16.12.0) graphql-ws: specifier: ^6.0.7 - version: 6.0.7(crossws@0.3.5)(graphql@16.12.0)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + version: 6.0.7(crossws@0.3.5)(graphql@16.12.0)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) input-otp: specifier: ^1.4.2 version: 1.4.2(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -184,7 +184,7 @@ importers: version: 4.0.1 smart-account-kit: specifier: ^0.2.10 - version: 0.2.10(@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6))(@stellar/stellar-sdk@14.6.1) + version: 0.2.10(@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6))(@stellar/stellar-sdk@14.6.1) sonner: specifier: ^2.0.7 version: 2.0.7(react-dom@19.2.3(react@19.2.3))(react@19.2.3) @@ -210,6 +210,9 @@ importers: '@graphql-codegen/typescript-react-query': specifier: ^7.0.0 version: 7.0.1(graphql@16.12.0) + '@graphql-typed-document-node/core': + specifier: ^3.2.0 + version: 3.2.0(graphql@16.12.0) '@next/swc-wasm-nodejs': specifier: ^16.1.6 version: 16.1.6 @@ -1143,89 +1146,105 @@ packages: resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] + libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-wasm32@0.34.5': resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} @@ -1615,24 +1634,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@next/swc-linux-arm64-musl@16.1.6': resolution: {integrity: sha512-S4J2v+8tT3NIO9u2q+S0G5KdvNDjXfAv06OhfOzNDaBn5rw84DGXWndOEB7d5/x852A20sW1M56vhC/tRVbccQ==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@next/swc-linux-x64-gnu@16.1.6': resolution: {integrity: sha512-2eEBDkFlMMNQnkTyPBhQOAyn2qMxyG2eE7GPH2WIDGEpEILcBPI/jdSv4t6xupSP+ot/jkfrCShLAa7+ZUPcJQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@next/swc-linux-x64-musl@16.1.6': resolution: {integrity: sha512-oicJwRlyOoZXVlxmIMaTq7f8pN9QNbdes0q2FXfRsPhfCi8n8JmOZJm5oo1pwDaFbnnD421rVU409M3evFbIqg==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@next/swc-wasm-nodejs@16.1.6': resolution: {integrity: sha512-U9Qpc9JefEXb1ykflZoYdFskAfVemCHNzTwKoG7nyRnO0DMmvitsoQwYl9JCcFVU2tR8MGmJu5cs4jVMiyOEPQ==} @@ -2622,66 +2645,79 @@ packages: resolution: {integrity: sha512-F8sWbhZ7tyuEfsmOxwc2giKDQzN3+kuBLPwwZGyVkLlKGdV1nvnNwYD0fKQ8+XS6hp9nY7B+ZeK01EBUE7aHaw==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.57.1': resolution: {integrity: sha512-rGfNUfn0GIeXtBP1wL5MnzSj98+PZe/AXaGBCRmT0ts80lU5CATYGxXukeTX39XBKsxzFpEeK+Mrp9faXOlmrw==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.57.1': resolution: {integrity: sha512-MMtej3YHWeg/0klK2Qodf3yrNzz6CGjo2UntLvk2RSPlhzgLvYEB3frRvbEF2wRKh1Z2fDIg9KRPe1fawv7C+g==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.57.1': resolution: {integrity: sha512-1a/qhaaOXhqXGpMFMET9VqwZakkljWHLmZOX48R0I/YLbhdxr1m4gtG1Hq7++VhVUmf+L3sTAf9op4JlhQ5u1Q==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.57.1': resolution: {integrity: sha512-QWO6RQTZ/cqYtJMtxhkRkidoNGXc7ERPbZN7dVW5SdURuLeVU7lwKMpo18XdcmpWYd0qsP1bwKPf7DNSUinhvA==} cpu: [loong64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.57.1': resolution: {integrity: sha512-xpObYIf+8gprgWaPP32xiN5RVTi/s5FCR+XMXSKmhfoJjrpRAjCuuqQXyxUa/eJTdAE6eJ+KDKaoEqjZQxh3Gw==} cpu: [loong64] os: [linux] + libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.57.1': resolution: {integrity: sha512-4BrCgrpZo4hvzMDKRqEaW1zeecScDCR+2nZ86ATLhAoJ5FQ+lbHVD3ttKe74/c7tNT9c6F2viwB3ufwp01Oh2w==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.57.1': resolution: {integrity: sha512-NOlUuzesGauESAyEYFSe3QTUguL+lvrN1HtwEEsU2rOwdUDeTMJdO5dUYl/2hKf9jWydJrO9OL/XSSf65R5+Xw==} cpu: [ppc64] os: [linux] + libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.57.1': resolution: {integrity: sha512-ptA88htVp0AwUUqhVghwDIKlvJMD/fmL/wrQj99PRHFRAG6Z5nbWoWG4o81Nt9FT+IuqUQi+L31ZKAFeJ5Is+A==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.57.1': resolution: {integrity: sha512-S51t7aMMTNdmAMPpBg7OOsTdn4tySRQvklmL3RpDRyknk87+Sp3xaumlatU+ppQ+5raY7sSTcC2beGgvhENfuw==} cpu: [riscv64] os: [linux] + libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.57.1': resolution: {integrity: sha512-Bl00OFnVFkL82FHbEqy3k5CUCKH6OEJL54KCyx2oqsmZnFTR8IoNqBF+mjQVcRCT5sB6yOvK8A37LNm/kPJiZg==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.57.1': resolution: {integrity: sha512-ABca4ceT4N+Tv/GtotnWAeXZUZuM/9AQyCyKYyKnpk4yoA7QIAuBt6Hkgpw8kActYlew2mvckXkvx0FfoInnLg==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.57.1': resolution: {integrity: sha512-HFps0JeGtuOR2convgRRkHCekD7j+gdAuXM+/i6kGzQtFhlCtQkpwtNzkNj6QhCDp7DRJ7+qC/1Vg2jt5iSOFw==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-openbsd-x64@4.57.1': resolution: {integrity: sha512-H+hXEv9gdVQuDTgnqD+SQffoWoc0Of59AStSzTEj/feWTBAnSfSD3+Dql1ZruJQxmykT/JVY0dE8Ka7z0DH1hw==} @@ -3455,24 +3491,28 @@ packages: engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-arm64-musl@4.2.0': resolution: {integrity: sha512-XKcSStleEVnbH6W/9DHzZv1YhjE4eSS6zOu2eRtYAIh7aV4o3vIBs+t/B15xlqoxt6ef/0uiqJVB6hkHjWD/0A==} engines: {node: '>= 20'} cpu: [arm64] os: [linux] + libc: [musl] '@tailwindcss/oxide-linux-x64-gnu@4.2.0': resolution: {integrity: sha512-/hlXCBqn9K6fi7eAM0RsobHwJYa5V/xzWspVTzxnX+Ft9v6n+30Pz8+RxCn7sQL/vRHHLS30iQPrHQunu6/vJA==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [glibc] '@tailwindcss/oxide-linux-x64-musl@4.2.0': resolution: {integrity: sha512-lKUaygq4G7sWkhQbfdRRBkaq4LY39IriqBQ+Gk6l5nKq6Ay2M2ZZb1tlIyRNgZKS8cbErTwuYSor0IIULC0SHw==} engines: {node: '>= 20'} cpu: [x64] os: [linux] + libc: [musl] '@tailwindcss/oxide-wasm32-wasi@4.2.0': resolution: {integrity: sha512-xuDjhAsFdUuFP5W9Ze4k/o4AskUtI8bcAGU4puTYprr89QaYFmhYOPfP+d1pH+k9ets6RoE23BXZM1X1jJqoyw==} @@ -3957,41 +3997,49 @@ packages: resolution: {integrity: sha512-34gw7PjDGB9JgePJEmhEqBhWvCiiWCuXsL9hYphDF7crW7UgI05gyBAi6MF58uGcMOiOqSJ2ybEeCvHcq0BCmQ==} cpu: [arm64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-arm64-musl@1.11.1': resolution: {integrity: sha512-RyMIx6Uf53hhOtJDIamSbTskA99sPHS96wxVE/bJtePJJtpdKGXO1wY90oRdXuYOGOTuqjT8ACccMc4K6QmT3w==} cpu: [arm64] os: [linux] + libc: [musl] '@unrs/resolver-binding-linux-ppc64-gnu@1.11.1': resolution: {integrity: sha512-D8Vae74A4/a+mZH0FbOkFJL9DSK2R6TFPC9M+jCWYia/q2einCubX10pecpDiTmkJVUH+y8K3BZClycD8nCShA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-riscv64-gnu@1.11.1': resolution: {integrity: sha512-frxL4OrzOWVVsOc96+V3aqTIQl1O2TjgExV4EKgRY09AJ9leZpEg8Ak9phadbuX0BA4k8U5qtvMSQQGGmaJqcQ==} cpu: [riscv64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-riscv64-musl@1.11.1': resolution: {integrity: sha512-mJ5vuDaIZ+l/acv01sHoXfpnyrNKOk/3aDoEdLO/Xtn9HuZlDD6jKxHlkN8ZhWyLJsRBxfv9GYM2utQ1SChKew==} cpu: [riscv64] os: [linux] + libc: [musl] '@unrs/resolver-binding-linux-s390x-gnu@1.11.1': resolution: {integrity: sha512-kELo8ebBVtb9sA7rMe1Cph4QHreByhaZ2QEADd9NzIQsYNQpt9UkM9iqr2lhGr5afh885d/cB5QeTXSbZHTYPg==} cpu: [s390x] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-x64-gnu@1.11.1': resolution: {integrity: sha512-C3ZAHugKgovV5YvAMsxhq0gtXuwESUKc5MhEtjBpLoHPLYM+iuwSj3lflFwK3DPm68660rZ7G8BMcwSro7hD5w==} cpu: [x64] os: [linux] + libc: [glibc] '@unrs/resolver-binding-linux-x64-musl@1.11.1': resolution: {integrity: sha512-rV0YSoyhK2nZ4vEswT/QwqzqQXw5I6CjoaYMOX0TqBlWhojUf8P94mvI7nuJTeaCkkds3QE4+zS8Ko+GdXuZtA==} cpu: [x64] os: [linux] + libc: [musl] '@unrs/resolver-binding-wasm32-wasi@1.11.1': resolution: {integrity: sha512-5u4RkfxJm+Ng7IWgkzi3qrFOvLvQYnPBmjmZQ8+szTK/b31fQCnleNl1GgEt7nIsZRIf5PLhPwT0WM+q45x/UQ==} @@ -6371,24 +6419,28 @@ packages: engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [glibc] lightningcss-linux-arm64-musl@1.31.1: resolution: {integrity: sha512-mVZ7Pg2zIbe3XlNbZJdjs86YViQFoJSpc41CbVmKBPiGmC4YrfeOyz65ms2qpAobVd7WQsbW4PdsSJEMymyIMg==} engines: {node: '>= 12.0.0'} cpu: [arm64] os: [linux] + libc: [musl] lightningcss-linux-x64-gnu@1.31.1: resolution: {integrity: sha512-xGlFWRMl+0KvUhgySdIaReQdB4FNudfUTARn7q0hh/V67PVGCs3ADFjw+6++kG1RNd0zdGRlEKa+T13/tQjPMA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [glibc] lightningcss-linux-x64-musl@1.31.1: resolution: {integrity: sha512-eowF8PrKHw9LpoZii5tdZwnBcYDxRw2rRCyvAXLi34iyeYfqCQNA9rmUM0ce62NlPhCvof1+9ivRaTY6pSKDaA==} engines: {node: '>= 12.0.0'} cpu: [x64] os: [linux] + libc: [musl] lightningcss-win32-arm64-msvc@1.31.1: resolution: {integrity: sha512-aJReEbSEQzx1uBlQizAOBSjcmr9dCdL3XuC/6HLXAxmtErsj2ICo5yYggg1qOODQMtnjNQv2UHb9NpOuFtYe4w==} @@ -8791,7 +8843,7 @@ snapshots: - utf-8-validate optional: true - '@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6)': + '@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6)': dependencies: '@albedo-link/intent': 0.12.0 '@creit.tech/xbull-wallet-connect': 0.4.0 @@ -8804,8 +8856,8 @@ snapshots: '@reown/appkit': 1.8.19(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(react@19.2.3)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(zod@4.3.6) '@stellar/freighter-api': 6.0.0 '@stellar/stellar-base': 14.0.1 - '@trezor/connect-plugin-stellar': 9.2.6(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(tslib@2.8.1) - '@trezor/connect-web': 9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@trezor/connect-plugin-stellar': 9.2.6(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(tslib@2.8.1) + '@trezor/connect-web': 9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@twind/core': 1.1.3(typescript@5.9.3) '@twind/preset-autoprefix': 1.0.7(@twind/core@1.1.3(typescript@5.9.3))(typescript@5.9.3) '@twind/preset-tailwind': 1.1.4(@twind/core@1.1.3(typescript@5.9.3))(typescript@5.9.3) @@ -11579,31 +11631,31 @@ snapshots: dependencies: '@sinonjs/commons': 3.0.1 - '@solana-program/compute-budget@0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))': + '@solana-program/compute-budget@0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))': dependencies: - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@solana-program/stake@0.2.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))': + '@solana-program/stake@0.2.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))': dependencies: - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@solana-program/system@0.10.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@6.0.6))': dependencies: '@solana/kit': 5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@6.0.6) optional: true - '@solana-program/system@0.7.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))': + '@solana-program/system@0.7.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))': dependencies: - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))': + '@solana-program/token-2022@0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))': dependencies: - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@solana/sysvars': 5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana-program/token@0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))': + '@solana-program/token@0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))': dependencies: - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@solana-program/token@0.9.0(@solana/kit@5.5.1(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(utf-8-validate@6.0.6))': dependencies: @@ -11835,7 +11887,7 @@ snapshots: - fastestsmallesttextencoderdecoder optional: true - '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@solana/accounts': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) @@ -11848,11 +11900,11 @@ snapshots: '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/rpc-parsed-types': 2.3.0(typescript@5.9.3) '@solana/rpc-spec-types': 2.3.0(typescript@5.9.3) - '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/signers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/sysvars': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana/transaction-confirmation': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) typescript: 5.9.3 @@ -12065,14 +12117,14 @@ snapshots: - fastestsmallesttextencoderdecoder optional: true - '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@solana/rpc-subscriptions-channel-websocket@2.3.0(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@solana/errors': 2.3.0(typescript@5.9.3) '@solana/functional': 2.3.0(typescript@5.9.3) '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.3) '@solana/subscribable': 2.3.0(typescript@5.9.3) typescript: 5.9.3 - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) + ws: 8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6) '@solana/rpc-subscriptions-channel-websocket@5.5.1(bufferutil@4.1.0)(typescript@5.9.3)(utf-8-validate@6.0.6)': dependencies: @@ -12106,7 +12158,7 @@ snapshots: typescript: 5.9.3 optional: true - '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@solana/rpc-subscriptions@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@solana/errors': 2.3.0(typescript@5.9.3) '@solana/fast-stable-stringify': 2.3.0(typescript@5.9.3) @@ -12114,7 +12166,7 @@ snapshots: '@solana/promises': 2.3.0(typescript@5.9.3) '@solana/rpc-spec-types': 2.3.0(typescript@5.9.3) '@solana/rpc-subscriptions-api': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana/rpc-subscriptions-channel-websocket': 2.3.0(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@solana/rpc-subscriptions-spec': 2.3.0(typescript@5.9.3) '@solana/rpc-transformers': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) @@ -12308,7 +12360,7 @@ snapshots: transitivePeerDependencies: - fastestsmallesttextencoderdecoder - '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@solana/transaction-confirmation@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@solana/addresses': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/codecs-strings': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) @@ -12316,7 +12368,7 @@ snapshots: '@solana/keys': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/promises': 2.3.0(typescript@5.9.3) '@solana/rpc': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) - '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana/rpc-subscriptions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/transaction-messages': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@solana/transactions': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) @@ -12684,13 +12736,13 @@ snapshots: - react-native - utf-8-validate - '@trezor/blockchain-link@2.6.1(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@trezor/blockchain-link@2.6.1(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@solana-program/compute-budget': 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))) - '@solana-program/stake': 0.2.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))) - '@solana-program/token': 0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))) - '@solana-program/token-2022': 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana-program/compute-budget': 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))) + '@solana-program/stake': 0.2.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))) + '@solana-program/token': 0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))) + '@solana-program/token-2022': 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@solana/rpc-types': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3) '@stellar/stellar-sdk': 14.2.0 '@trezor/blockchain-link-types': 1.5.0(tslib@2.8.1) @@ -12738,16 +12790,16 @@ snapshots: - expo-localization - react-native - '@trezor/connect-plugin-stellar@9.2.6(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(tslib@2.8.1)': + '@trezor/connect-plugin-stellar@9.2.6(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(tslib@2.8.1)': dependencies: '@stellar/stellar-sdk': 14.6.1 - '@trezor/connect': 9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@trezor/connect': 9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@trezor/utils': 9.5.0(tslib@2.8.1) tslib: 2.8.1 - '@trezor/connect-web@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@trezor/connect-web@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: - '@trezor/connect': 9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@trezor/connect': 9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@trezor/connect-common': 0.5.1(tslib@2.8.1) '@trezor/utils': 9.5.0(tslib@2.8.1) '@trezor/websocket-client': 1.3.0(bufferutil@4.1.0)(tslib@2.8.1)(utf-8-validate@6.0.6) @@ -12766,7 +12818,7 @@ snapshots: - utf-8-validate - ws - '@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))': + '@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))': dependencies: '@ethereumjs/common': 10.1.1 '@ethereumjs/tx': 10.1.1 @@ -12774,12 +12826,12 @@ snapshots: '@mobily/ts-belt': 3.13.1 '@noble/hashes': 1.8.0 '@scure/bip39': 1.6.0 - '@solana-program/compute-budget': 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))) - '@solana-program/system': 0.7.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))) - '@solana-program/token': 0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))) - '@solana-program/token-2022': 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) - '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) - '@trezor/blockchain-link': 2.6.1(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@solana-program/compute-budget': 0.8.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))) + '@solana-program/system': 0.7.0(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))) + '@solana-program/token': 0.5.1(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))) + '@solana-program/token-2022': 0.4.2(@solana/kit@2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)) + '@solana/kit': 2.3.0(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) + '@trezor/blockchain-link': 2.6.1(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)) '@trezor/blockchain-link-types': 1.5.1(tslib@2.8.1) '@trezor/blockchain-link-utils': 1.5.2(bufferutil@4.1.0)(tslib@2.8.1)(utf-8-validate@6.0.6) '@trezor/connect-analytics': 1.4.0(tslib@2.8.1) @@ -15498,13 +15550,6 @@ snapshots: graphql: 16.12.0 tslib: 2.8.1 - graphql-ws@6.0.7(crossws@0.3.5)(graphql@16.12.0)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)): - dependencies: - graphql: 16.12.0 - optionalDependencies: - crossws: 0.3.5 - ws: 8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6) - graphql-ws@6.0.7(crossws@0.3.5)(graphql@16.12.0)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)): dependencies: graphql: 16.12.0 @@ -18103,14 +18148,14 @@ snapshots: '@stellar/stellar-sdk': 14.6.1 buffer: 6.0.3 - smart-account-kit@0.2.10(@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6))(@stellar/stellar-sdk@14.6.1): + smart-account-kit@0.2.10(@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6))(@stellar/stellar-sdk@14.6.1): dependencies: '@simplewebauthn/browser': 13.3.0 '@stellar/stellar-sdk': 14.6.1 base64url: 3.0.1 smart-account-kit-bindings: 0.1.2(@stellar/stellar-sdk@14.6.1) optionalDependencies: - '@creit-tech/stellar-wallets-kit': '@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.18.3(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6)' + '@creit-tech/stellar-wallets-kit': '@creit.tech/stellar-wallets-kit@2.1.0(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(@stellar/stellar-sdk@14.6.1)(@trezor/connect@9.7.2(@solana/sysvars@5.5.1(fastestsmallesttextencoderdecoder@1.0.22)(typescript@5.9.3))(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(tslib@2.8.1)(typescript@5.9.3)(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6)))(@types/react@19.2.14)(bufferutil@4.1.0)(fastestsmallesttextencoderdecoder@1.0.22)(near-api-js@5.1.1)(react@19.2.3)(tslib@2.8.1)(typescript@5.9.3)(use-sync-external-store@1.6.0(react@19.2.3))(utf-8-validate@6.0.6)(ws@8.19.0(bufferutil@4.1.0)(utf-8-validate@6.0.6))(zod@4.3.6)' smart-buffer@4.2.0: {}