diff --git a/app/me/earnings/page.tsx b/app/me/earnings/page.tsx index f599da39f..7174a2426 100644 --- a/app/me/earnings/page.tsx +++ b/app/me/earnings/page.tsx @@ -81,7 +81,9 @@ const BreakdownItem: React.FC = ({ {label} - ${value.toLocaleString()} + + ${(Number(value) || 0).toLocaleString()} + ); @@ -106,7 +108,9 @@ const ActivityItem: React.FC = ({ activity }) => (
-

${activity.amount.toLocaleString()}

+

+ ${(Number(activity.amount) || 0).toLocaleString()} +

{activity.currency && (

{activity.currency}

)} @@ -118,7 +122,7 @@ const ActivityItem: React.FC = ({ activity }) => ( * EarningsSkeleton component for loading states. */ const EarningsSkeleton: React.FC = () => ( -
+
@@ -146,8 +150,10 @@ const EarningsPage: React.FC = () => { const fetchData = async () => { try { const res = await getUserEarnings(); - if (res.success && res.data) { + if (res.success) { setData(res.data); + } else { + toast.error(res.error || 'Failed to load earnings data'); } } catch (error) { console.error('Failed to fetch earnings:', error); @@ -174,7 +180,7 @@ const EarningsPage: React.FC = () => { } return ( -
+
{ + if (!profile) return 0; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const joined = (profile as any)?.user?.joinedHackathons || []; + + return joined.length; + }, [profile]); + if (isLoading) { return (
@@ -18,14 +36,6 @@ export default function MeLayout({ children }: { children: React.ReactNode }) { ); } - const { name = '', email = '', profile, image: userImage = '' } = user || {}; - - const userData = { - name: name || '', - email, - image: profile?.image || userImage, - }; - return ( - +
{children}
diff --git a/app/me/participating/page.tsx b/app/me/participating/page.tsx new file mode 100644 index 000000000..142b26131 --- /dev/null +++ b/app/me/participating/page.tsx @@ -0,0 +1,256 @@ +'use client'; + +import { useMemo, useState } from 'react'; +import { useRouter } from 'next/navigation'; +import { useAuthStatus } from '@/hooks/use-auth'; +import { Tabs, TabsList, TabsTrigger } from '@/components/ui/tabs'; +import { motion, AnimatePresence } from 'framer-motion'; +import HackathonCard from '@/components/landing-page/hackathon/HackathonCard'; +import { + ProgressIndicator, + SubmissionStage, +} from '@/components/hackathons/ProgressIndicator'; +import { cn } from '@/lib/utils'; +import { Hackathon } from '@/lib/api/hackathons'; +import EmptyState from '@/components/EmptyState'; + +type TabType = 'all' | 'hackathons' | 'projects'; + +interface UnifiedItem extends Hackathon { + type: 'hackathon'; +} + +export default function ParticipatingPage() { + const router = useRouter(); + const { user, isLoading } = useAuthStatus(); + const [activeTab, setActiveTab] = useState('all'); + + const handleTabChange = (value: string) => { + setActiveTab(value as TabType); + }; + + const unifiedList = useMemo(() => { + const profile = user?.profile; + if (!profile) { + return []; + } + + const joinedHackathons = profile.user?.joinedHackathons || []; + const hackathonsAsParticipant = profile.hackathonsAsParticipant || []; + const submissions = profile.user?.hackathonSubmissionsAsParticipant || []; + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const typedJoinedHackathons: UnifiedItem[] = joinedHackathons + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .filter((h: any) => { + const data = h?.hackathon || h; + return data && data.id; + }) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .map((h: any) => { + const hackathonData = h.hackathon || h; + return { + ...hackathonData, + type: 'hackathon' as const, + }; + }); + + // Map hackathons from participating list — filter first to ensure p.hackathon is defined + const typedParticipatingHackathons: UnifiedItem[] = hackathonsAsParticipant + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .filter((p: any) => p && p.hackathon && p.hackathon.id) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .map((p: any) => ({ + ...p.hackathon, + type: 'hackathon' as const, + })); + + // Map hackathons from submissions + const typedSubmissionHackathons: UnifiedItem[] = submissions + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .filter((s: any) => s.hackathon) + // eslint-disable-next-line @typescript-eslint/no-explicit-any + .map((s: any) => ({ + ...s.hackathon, + type: 'hackathon' as const, + })); + + // Merge and deduplicate by ID + const merged = [ + ...typedParticipatingHackathons, + ...typedJoinedHackathons, + ...typedSubmissionHackathons, + ]; + + const seen = new Set(); + const deduplicated = merged.filter(item => { + if (!item.id || seen.has(item.id)) return false; + seen.add(item.id); + return true; + }); + + const sorted = deduplicated.sort((a, b) => { + const getPriority = (h: UnifiedItem) => { + const now = new Date().getTime(); + if (!h.startDate || !h.submissionDeadline) return 1; + + const start = new Date(h.startDate).getTime(); + const deadline = new Date(h.submissionDeadline).getTime(); + + if (now >= start && now <= deadline) return 0; + if (now < start) return 1; + return 2; + }; + + return getPriority(a) - getPriority(b); + }); + + return sorted; + }, [user]); + + const filteredList = useMemo(() => { + if (activeTab === 'projects') return []; + + let result = unifiedList; + if (activeTab === 'hackathons') { + result = unifiedList.filter(item => item.type === 'hackathon'); + } + return result; + }, [unifiedList, activeTab]); + + const getSubmissionStage = (hackathonId: string): SubmissionStage => { + const submission = + // eslint-disable-next-line @typescript-eslint/no-explicit-any + user?.profile?.user?.hackathonSubmissionsAsParticipant?.find( + (s: any) => s.hackathonId === hackathonId + ); + + if (!submission) return 'Not Started'; + + const statusRaw = submission.status; + if (!statusRaw || typeof statusRaw !== 'string') return 'In Progress'; + + const status = statusRaw.toUpperCase(); + if (status === 'DRAFT') return 'In Progress'; + if (status === 'SUBMITTED') return 'Submitted'; + if (status === 'UNDER_REVIEW') return 'Under Review'; + if (status === 'WINNER' || status === 'COMPLETED') return 'Results Pending'; + + return 'In Progress'; + }; + + const handleEmptyStateClick = () => { + router.push(activeTab === 'projects' ? '/projects' : '/hackathons'); + }; + + if (isLoading) { + return ( +
+
+
+ ); + } + + return ( +
+
+
+

+ Participating +

+

+ Track your active hackathons, projects, and pending submissions. +

+
+ + + + {['all', 'hackathons', 'projects'].map(tab => ( + + {tab} + {activeTab === tab && ( + + )} + + ))} + + +
+ + + {filteredList.length > 0 ? ( + + {filteredList.map(hackathon => ( + +
+ +
+ +
+
+
+ ))} +
+ ) : ( + + )} +
+
+ ); +} diff --git a/components/EmptyState.tsx b/components/EmptyState.tsx index 2796bca45..ba50d8590 100644 --- a/components/EmptyState.tsx +++ b/components/EmptyState.tsx @@ -66,11 +66,11 @@ const EmptyState: React.FC = ({ switch (type) { case 'compact': - return `${baseStyle} px-4 py-2 text-sm bg-[#00D2A4] text-black hover:bg-[#00B894] focus:ring-[#00D2A4] shadow-sm`; + return `${baseStyle} px-4 py-2 text-sm bg-primary text-primary-foreground hover:bg-primary/90 focus:ring-primary shadow-sm`; case 'custom': return `${baseStyle} px-6 py-3 bg-blue-600 text-white hover:bg-blue-700 focus:ring-blue-500 shadow-md`; default: - return `${baseStyle} px-6 py-3 bg-[#00D2A4] text-black hover:bg-[#00B894] focus:ring-[#00D2A4] shadow-[0_2px_8px_rgba(0,210,164,0.2)]`; + return `${baseStyle} px-6 py-3 bg-primary text-primary-foreground hover:bg-primary/90 focus:ring-primary shadow-[0_2px_8px_rgba(167,249,80,0.2)]`; } }; diff --git a/components/app-sidebar.tsx b/components/app-sidebar.tsx index 6f0bf025e..bdc0ce57c 100644 --- a/components/app-sidebar.tsx +++ b/components/app-sidebar.tsx @@ -28,7 +28,7 @@ import { import Image from 'next/image'; import Link from 'next/link'; -const navigationData = { +const getNavigationData = (counts?: { participating?: number }) => ({ main: [ { title: 'Overview', @@ -62,9 +62,12 @@ const navigationData = { hackathons: [ { title: 'Participating', - url: '/me/hackathons', + url: '/me/participating', icon: IconShieldCheck, - badge: '2', + badge: + counts?.participating && counts.participating > 0 + ? counts.participating.toString() + : undefined, }, { title: 'Submissions', @@ -97,16 +100,27 @@ const navigationData = { badge: '5', }, ], -}; -interface userData { +}); + +interface UserData { name: string; email: string; - image: string; + image: string | null; } + export function AppSidebar({ user, + counts, ...props -}: { user: userData } & React.ComponentProps) { +}: { + user: UserData; + counts?: { participating?: number }; +} & React.ComponentProps) { + const navigationData = React.useMemo( + () => getNavigationData(counts), + [counts] + ); + return (
diff --git a/components/hackathons/ProgressIndicator.tsx b/components/hackathons/ProgressIndicator.tsx new file mode 100644 index 000000000..98748abd7 --- /dev/null +++ b/components/hackathons/ProgressIndicator.tsx @@ -0,0 +1,57 @@ +'use client'; + +import React from 'react'; +import { cn } from '@/lib/utils'; + +export type SubmissionStage = + | 'Not Started' + | 'In Progress' + | 'Submitted' + | 'Under Review' + | 'Results Pending'; + +interface ProgressIndicatorProps { + stage: SubmissionStage; + className?: string; +} + +const STAGE_CONFIG: Record = + { + 'Not Started': { + color: 'bg-zinc-500/20 text-zinc-400', + label: 'Not Started', + }, + 'In Progress': { + color: 'bg-blue-500/20 text-blue-400', + label: 'In Progress', + }, + Submitted: { color: 'bg-green-500/20 text-green-400', label: 'Submitted' }, + 'Under Review': { + color: 'bg-purple-500/20 text-purple-400', + label: 'Under Review', + }, + 'Results Pending': { + color: 'bg-yellow-500/20 text-yellow-400', + label: 'Results Pending', + }, + }; + +export function ProgressIndicator({ + stage, + className, +}: ProgressIndicatorProps) { + const config = STAGE_CONFIG[stage]; + + return ( +
+
+ {config.label} +
+ ); +} diff --git a/components/landing-page/hackathon/HackathonCard.tsx b/components/landing-page/hackathon/HackathonCard.tsx index dd135c30e..e700bfb87 100644 --- a/components/landing-page/hackathon/HackathonCard.tsx +++ b/components/landing-page/hackathon/HackathonCard.tsx @@ -2,8 +2,9 @@ import { useRouter } from 'nextjs-toploader/app'; import Image from 'next/image'; import { MapPinIcon } from 'lucide-react'; -import { useEffect, useState } from 'react'; +import { useEffect, useState, useCallback } from 'react'; import { Hackathon } from '@/lib/api/hackathons'; +import { cn } from '@/lib/utils'; // type HackathonCardProps = { // id: string; @@ -157,7 +158,13 @@ function calculateTimeRemaining(targetDate: string): TimeRemaining { // } // } -function HackathonCard({ +interface HackathonCardProps extends Hackathon { + isFullWidth?: boolean; + className?: string; + target?: string; +} + +export const HackathonCard = ({ id, slug, name, @@ -176,8 +183,9 @@ function HackathonCard({ categories, prizeTiers, isFullWidth = false, - // className, -}: Hackathon & { isFullWidth?: boolean }) { + className, + target, +}: HackathonCardProps) => { const router = useRouter(); const [timeRemaining, setTimeRemaining] = useState({ days: 0, @@ -189,11 +197,17 @@ function HackathonCard({ const handleClick = () => { const slugPath = slug || id || ''; - router.push(`/hackathons/${slugPath}`); + const url = `/hackathons/${slugPath}`; + if (target === '_blank') { + window.open(url, '_blank'); + } else { + router.push(url); + } }; - // Determine top badge status using raw dates - const getTopBadgeStatus = () => { + // Determine top badge status using raw dates — memoised so it can safely + // appear in the useEffect dependency array without triggering infinite loops. + const getTopBadgeStatus = useCallback(() => { if (status === 'ARCHIVED') { return 'Archived'; } @@ -216,7 +230,7 @@ function HackathonCard({ // Otherwise it's upcoming return 'Upcoming'; - }; + }, [status, startDate, submissionDeadline]); const getTopBadgeColor = () => { const badgeStatus = getTopBadgeStatus(); @@ -332,7 +346,7 @@ function HackathonCard({ return () => clearInterval(interval); } - }, [status, startDate, submissionDeadline]); + }, [status, startDate, submissionDeadline, getTopBadgeStatus]); const bottomStatusInfo = getBottomStatusInfo(); const topBadgeStatus = getTopBadgeStatus(); @@ -352,9 +366,9 @@ function HackathonCard({ // })(); const CategoriesDisplay = ({ - categoriesList, + categoriesList = [], }: { - categoriesList: string[]; + categoriesList?: string[]; }) => { const MAX_VISIBLE = 3; @@ -386,9 +400,11 @@ function HackathonCard({ return (
{/* Image */}
@@ -411,13 +427,17 @@ function HackathonCard({
-
- - {organization.name} - + {organization?.logo && ( +
+ )} + {organization?.name && ( + + {organization.name} + + )}
@@ -478,6 +498,6 @@ function HackathonCard({
); -} +}; export default HackathonCard; diff --git a/components/nav-main.tsx b/components/nav-main.tsx index 0bec9fcb8..0648e5092 100644 --- a/components/nav-main.tsx +++ b/components/nav-main.tsx @@ -41,7 +41,8 @@ export function NavMain({ {items.map(item => { const isActive = - pathname === item.url || pathname?.startsWith(`${item.url}/`); + pathname === item.url || + (item.url !== '/me' && pathname?.startsWith(`${item.url}/`)); return ( diff --git a/components/nav-user.tsx b/components/nav-user.tsx index 9abede733..183f684f9 100644 --- a/components/nav-user.tsx +++ b/components/nav-user.tsx @@ -32,7 +32,7 @@ export function NavUser({ user: { name: string; email: string; - image: string; + image: string | null; }; }) { const { isMobile } = useSidebar(); @@ -47,7 +47,7 @@ export function NavUser({ className='data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground hover:bg-sidebar-accent/50 transition-colors' > - + {user.name .split(' ') @@ -75,7 +75,7 @@ export function NavUser({
- + {user.name .split(' ') diff --git a/components/profile/ProfileDataClient.tsx b/components/profile/ProfileDataClient.tsx index 1e2dd6fe8..b5507cf9f 100644 --- a/components/profile/ProfileDataClient.tsx +++ b/components/profile/ProfileDataClient.tsx @@ -46,8 +46,8 @@ export default function ProfileDataClient({ user }: ProfileDataClientProps) { const isOwnProfile = userData.id === currentUser?.id; const organizationsData = userData.members?.map(org => ({ - name: org.organization.name, - avatarUrl: org.organization.logo || '/blog1.jpg', + name: org.organization?.name || 'Unknown Organization', + avatarUrl: org.organization?.logo || '/blog1.jpg', })) || []; return ( diff --git a/components/profile/ProfileOverview.tsx b/components/profile/ProfileOverview.tsx index a966adf79..3113e36f9 100644 --- a/components/profile/ProfileOverview.tsx +++ b/components/profile/ProfileOverview.tsx @@ -21,9 +21,11 @@ export default function ProfileOverview({ isAuthenticated, isOwnProfile, }: ProfileOverviewProps) { + const nameParts = user.name?.split(' ') || []; const profileData: UserProfile = { username: user.username, - displayName: `${user.name?.split(' ')[0] || ''} ${user.name?.split(' ').slice(1).join(' ') || ''}`, + displayName: + `${nameParts[0] || ''} ${nameParts.slice(1).join(' ') || ''}`.trim(), bio: user.profile?.bio || 'No bio available', avatarUrl: user.image || '/', socialLinks: user.profile?.socialLinks || {}, @@ -39,8 +41,8 @@ export default function ProfileOverview({ const organizationsData: Organization[] = user.members?.map(org => { return { - name: org.organization.name, - avatarUrl: org.organization.logo || '/blog1.jpg', + name: org.organization?.name || 'Unknown Organization', + avatarUrl: org.organization?.logo || '/blog1.jpg', id: org.organizationId, }; }) || []; diff --git a/hooks/use-auth.ts b/hooks/use-auth.ts index de50467c7..fa402b301 100644 --- a/hooks/use-auth.ts +++ b/hooks/use-auth.ts @@ -11,6 +11,7 @@ export function useAuth(requireAuth = true) { } = authClient.useSession(); const router = useRouter(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const [userProfile, setUserProfile] = useState(null); const [profileLoading, setProfileLoading] = useState(false); @@ -97,6 +98,7 @@ export function useOptionalAuth() { export function useAuthStatus() { const { data: session, isPending: sessionPending } = authClient.useSession(); + // eslint-disable-next-line @typescript-eslint/no-explicit-any const [userProfile, setUserProfile] = useState(null); const [profileLoading, setProfileLoading] = useState(false); diff --git a/lib/api/types.ts b/lib/api/types.ts index 45584207f..3c6d39a2e 100644 --- a/lib/api/types.ts +++ b/lib/api/types.ts @@ -111,6 +111,15 @@ export interface User { status: string; rank?: number | null; submittedAt: string; + hackathonId: string; + hackathon?: any; + }>; + joinedHackathons?: Array<{ + id: string; + userId: string; + hackathonId: string; + registrationDate: string; + hackathon?: any; }>; profile?: Record; stats?: { @@ -252,6 +261,13 @@ export interface GetMeResponse { project?: Record; organization?: Record; }>; + hackathonsAsParticipant?: Array<{ + id: string; + hackathonId: string; + participantId: string; + status: string; + hackathon?: any; + }>; } // Logout diff --git a/lib/api/user/earnings.ts b/lib/api/user/earnings.ts index a86d7dc13..31e5a90a7 100644 --- a/lib/api/user/earnings.ts +++ b/lib/api/user/earnings.ts @@ -25,10 +25,9 @@ export interface EarningsData { activities: EarningActivity[]; } -export interface GetEarningsResponse extends ApiResponse { - success: true; - data: EarningsData; -} +export type GetEarningsResponse = + | { success: true; data: EarningsData; message?: string } + | { success: false; error: string; message?: string }; export interface ClaimEarningRequest { activityId: string; @@ -46,7 +45,7 @@ export interface ClaimEarningResponse extends ApiResponse { * Get user earnings data */ export const getUserEarnings = async (): Promise => { - const res = await api.get('/user/earnings'); + const res = await api.get('/users/earnings'); return res.data; }; @@ -57,7 +56,7 @@ export const claimEarning = async ( data: ClaimEarningRequest ): Promise => { const res = await api.post( - '/user/earnings/claim', + '/users/earnings/claim', data ); return res.data; diff --git a/package-lock.json b/package-lock.json index 6c07d7376..65287815c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6198,9 +6198,9 @@ } }, "node_modules/@trezor/connect": { - "version": "9.7.1", - "resolved": "https://registry.npmjs.org/@trezor/connect/-/connect-9.7.1.tgz", - "integrity": "sha512-W2ym0bs4FVmXByEr9gANBp+bRErzNcmqqqYzSJLOVkawxikqYXag2aCpdiXU3LlZbFbhFhIsT/fpDLfwiLRySA==", + "version": "9.7.2", + "resolved": "https://registry.npmjs.org/@trezor/connect/-/connect-9.7.2.tgz", + "integrity": "sha512-Sn6F4mNH+yi2vAHy29kwhs50bRLn92drg3znm3pkY+8yEBxI4MmuP8sKYjdgUEJnQflWh80KlcvEDeVa4olVRA==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -6216,18 +6216,18 @@ "@solana-program/token-2022": "^0.4.2", "@solana/kit": "^2.3.0", "@trezor/blockchain-link": "2.6.1", - "@trezor/blockchain-link-types": "1.5.0", - "@trezor/blockchain-link-utils": "1.5.1", + "@trezor/blockchain-link-types": "1.5.1", + "@trezor/blockchain-link-utils": "1.5.2", "@trezor/connect-analytics": "1.4.0", - "@trezor/connect-common": "0.5.0", + "@trezor/connect-common": "0.5.1", "@trezor/crypto-utils": "1.2.0", - "@trezor/device-authenticity": "1.1.1", + "@trezor/device-authenticity": "1.1.2", "@trezor/device-utils": "1.2.0", "@trezor/env-utils": "^1.5.0", - "@trezor/protobuf": "1.5.1", + "@trezor/protobuf": "1.5.2", "@trezor/protocol": "1.3.0", "@trezor/schema-utils": "1.4.0", - "@trezor/transport": "1.6.1", + "@trezor/transport": "1.6.2", "@trezor/type-utils": "1.2.0", "@trezor/utils": "9.5.0", "@trezor/utxo-lib": "2.5.0", @@ -6256,9 +6256,9 @@ } }, "node_modules/@trezor/connect-common": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/@trezor/connect-common/-/connect-common-0.5.0.tgz", - "integrity": "sha512-WE71iaFcWmfQxDCiTUNynj2DccRgUiLBJ+g3nrqCBJqEYzu+cD6eZ5k/OLtZ3hfh5gyB5EQwXdGvRT07iNdxAA==", + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/@trezor/connect-common/-/connect-common-0.5.1.tgz", + "integrity": "sha512-wdpVCwdylBh4SBO5Ys40tB/d59UlfjmxgBHDkkLgaR+JcqkthCfiw5VlUrV9wu65lquejAZhA5KQL4mUUUhCow==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { @@ -6614,6 +6614,74 @@ "base-x": "^5.0.0" } }, + "node_modules/@trezor/connect/node_modules/@stellar/stellar-sdk": { + "version": "14.2.0", + "resolved": "https://registry.npmjs.org/@stellar/stellar-sdk/-/stellar-sdk-14.2.0.tgz", + "integrity": "sha512-7nh2ogzLRMhfkIC0fGjn1LHUzk3jqVw8tjAuTt5ADWfL9CSGBL18ILucE9igz2L/RU2AZgeAvhujAnW91Ut/oQ==", + "hasInstallScript": true, + "license": "Apache-2.0", + "peer": true, + "dependencies": { + "@stellar/stellar-base": "^14.0.1", + "axios": "^1.12.2", + "bignumber.js": "^9.3.1", + "eventsource": "^2.0.2", + "feaxios": "^0.0.23", + "randombytes": "^2.1.0", + "toml": "^3.0.0", + "urijs": "^1.19.1" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/@trezor/connect/node_modules/@trezor/blockchain-link-types": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@trezor/blockchain-link-types/-/blockchain-link-types-1.5.1.tgz", + "integrity": "sha512-Idavz6LwLBW8sXc69fh5AJEnl666EDl2Nt3io7updvBgOR0/P12I900DgjNhCKtiWuv66A33/5RE7zLcj3lfnw==", + "license": "See LICENSE.md in repo root", + "peer": true, + "dependencies": { + "@trezor/utils": "9.5.0", + "@trezor/utxo-lib": "2.5.0" + }, + "peerDependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@trezor/connect/node_modules/@trezor/blockchain-link-utils": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@trezor/blockchain-link-utils/-/blockchain-link-utils-1.5.2.tgz", + "integrity": "sha512-OSS5OEE98FMnYfjoEALPjBt7ebjC/FKnq3HOolHdEWXBpVlXZNN2+Vo1R9J6WbZUU087sHuUTJJy/GJYWY13Tg==", + "license": "See LICENSE.md in repo root", + "peer": true, + "dependencies": { + "@mobily/ts-belt": "^3.13.1", + "@stellar/stellar-sdk": "14.2.0", + "@trezor/env-utils": "1.5.0", + "@trezor/protobuf": "1.5.2", + "@trezor/utils": "9.5.0", + "xrpl": "4.4.3" + }, + "peerDependencies": { + "tslib": "^2.6.2" + } + }, + "node_modules/@trezor/connect/node_modules/@trezor/protobuf": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@trezor/protobuf/-/protobuf-1.5.2.tgz", + "integrity": "sha512-zViaL1jKue8DUTVEDg0C/lMipqNMd/Z3kr29/+MeZOoupjaXIQ2Lqp3WAMe8hvNTKKX8aNQH9JrbapJ6w9FMXw==", + "license": "See LICENSE.md in repo root", + "peer": true, + "dependencies": { + "@trezor/schema-utils": "1.4.0", + "long": "5.2.5", + "protobufjs": "7.4.0" + }, + "peerDependencies": { + "tslib": "^2.6.2" + } + }, "node_modules/@trezor/connect/node_modules/base-x": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/base-x/-/base-x-5.0.1.tgz", @@ -6642,15 +6710,15 @@ } }, "node_modules/@trezor/device-authenticity": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@trezor/device-authenticity/-/device-authenticity-1.1.1.tgz", - "integrity": "sha512-WlYbQgc5l0pWUVP9GkMp+Oj3rVAqMKsWF0HyxujoymNjEB7rLTl2hXs+GFjlz7VnldaSslECc6EBex/eQiNOnA==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@trezor/device-authenticity/-/device-authenticity-1.1.2.tgz", + "integrity": "sha512-313uSXYR4XKDv3CjtCpgHA+yEe9xxqN7EFl/D68FEn70SPsuWI0+2zUvjPPh6TIOh/EcLv7hCO/QTHUAGd7ZWQ==", "license": "See LICENSE.md in repo root", "peer": true, "dependencies": { "@noble/curves": "^2.0.1", "@trezor/crypto-utils": "1.2.0", - "@trezor/protobuf": "1.5.1", + "@trezor/protobuf": "1.5.2", "@trezor/schema-utils": "1.4.0", "@trezor/utils": "9.5.0" } @@ -6684,6 +6752,21 @@ "url": "https://paulmillr.com/funding/" } }, + "node_modules/@trezor/device-authenticity/node_modules/@trezor/protobuf": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@trezor/protobuf/-/protobuf-1.5.2.tgz", + "integrity": "sha512-zViaL1jKue8DUTVEDg0C/lMipqNMd/Z3kr29/+MeZOoupjaXIQ2Lqp3WAMe8hvNTKKX8aNQH9JrbapJ6w9FMXw==", + "license": "See LICENSE.md in repo root", + "peer": true, + "dependencies": { + "@trezor/schema-utils": "1.4.0", + "long": "5.2.5", + "protobufjs": "7.4.0" + }, + "peerDependencies": { + "tslib": "^2.6.2" + } + }, "node_modules/@trezor/device-utils": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@trezor/device-utils/-/device-utils-1.2.0.tgz", @@ -6758,13 +6841,13 @@ } }, "node_modules/@trezor/transport": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/@trezor/transport/-/transport-1.6.1.tgz", - "integrity": "sha512-RQNQingZ1TOVKSJu3Av9bmQovsu9n1NkcAYJ64+ZfapORfl/AzmZizRflhxU3FlIujQJK1gbIaW79+L54g7a8w==", + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/@trezor/transport/-/transport-1.6.2.tgz", + "integrity": "sha512-w0HlD1fU+qTGO3tefBGHF/YS/ts/TWFja9FGIJ4+7+Z9NphvIG06HGvy2HzcD9AhJy9pvDeIsyoM2TTZTiyjkQ==", "license": "SEE LICENSE IN LICENSE.md", "peer": true, "dependencies": { - "@trezor/protobuf": "1.5.1", + "@trezor/protobuf": "1.5.2", "@trezor/protocol": "1.3.0", "@trezor/type-utils": "1.2.0", "@trezor/utils": "9.5.0", @@ -6775,6 +6858,21 @@ "tslib": "^2.6.2" } }, + "node_modules/@trezor/transport/node_modules/@trezor/protobuf": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/@trezor/protobuf/-/protobuf-1.5.2.tgz", + "integrity": "sha512-zViaL1jKue8DUTVEDg0C/lMipqNMd/Z3kr29/+MeZOoupjaXIQ2Lqp3WAMe8hvNTKKX8aNQH9JrbapJ6w9FMXw==", + "license": "See LICENSE.md in repo root", + "peer": true, + "dependencies": { + "@trezor/schema-utils": "1.4.0", + "long": "5.2.5", + "protobufjs": "7.4.0" + }, + "peerDependencies": { + "tslib": "^2.6.2" + } + }, "node_modules/@trezor/type-utils": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@trezor/type-utils/-/type-utils-1.2.0.tgz", @@ -7588,37 +7686,24 @@ "typescript": ">=4.8.4 <6.0.0" } }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/balanced-match": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", - "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "18 || 20 || >=22" - } - }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.3.tgz", - "integrity": "sha512-fy6KJm2RawA5RcHkLa1z/ScpBeA762UF9KmZQxwIbDtRJrgLzM10depAiEQ+CXYcoiqW1/m96OAAoke2nE9EeA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^4.0.2" - }, - "engines": { - "node": "18 || 20 || >=22" + "balanced-match": "^1.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.6.tgz", - "integrity": "sha512-kQAVowdR33euIqeA0+VZTDqU+qo1IeVY+hrKYtZMio3Pg0P0vuh/kwRylLUddJhB6pf3q/botcOvRtx4IN1wqQ==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^5.0.2" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -15813,9 +15898,9 @@ "license": "MIT" }, "node_modules/minimatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.3.tgz", - "integrity": "sha512-M2GCs7Vk83NxkUyQV1bkABc4yxgz9kILhHImZiBPAZ9ybuvCb0/H7lEl5XvIg3g+9d4eNotkZA5IWwYl0tibaA==", + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", "dev": true, "license": "ISC", "dependencies": {