Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file modified bun.lockb
Binary file not shown.
15,926 changes: 15,926 additions & 0 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@
"clsx": "^2.1.1",
"d3": "^7.9.0",
"ethereum-identity-kit": "^0.2.74",
"motion": "^12.38.0",
"next": "15.5.9",
"prettier": "^3.6.2",
"prettier-plugin-tailwindcss": "^0.6.14",
"puppeteer": "^24.31.0",
"puppeteer-core": "^24.31.0",
"react": "19.2.1",
"react-dom": "19.2.1",
"react-grid-layout": "^2.2.3",
"react-redux": "^9.2.0",
"redux": "^5.0.1",
"redux-persist": "^6.0.0",
Expand Down
3 changes: 3 additions & 0 deletions public/icons/bell-primary.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions public/icons/chat.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 6 additions & 0 deletions public/icons/grid-primary.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/view-primary.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions public/icons/watchlist-primary.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
44 changes: 44 additions & 0 deletions src/api/offers/createBulk.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import type { SeaportOrder } from '@/lib/seaport/bulkTypes'

interface BulkOfferItem {
ensNameId: number
offerAmountWei: string
orderData: { parameters: SeaportOrder; signature: string }
signature: string
}

interface CreateBulkOfferParams {
offers: BulkOfferItem[]
buyerAddress: string
currencyAddress?: string
expiresAt?: string
treeHeight: number
merkleRoot?: string
}

export interface BulkOfferResponse {
groupId: string
totalOffers: number
created: number
failed: number
results: Array<{ ensNameId: number; status: 'success' | 'failed'; error?: string }>
errors?: string[]
}

export const createBulkOffer = async (params: CreateBulkOfferParams): Promise<BulkOfferResponse> => {
const response = await fetch(`/api/offers/bulk`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify(params),
})

if (!response.ok) {
const errorData = await response.json().catch(() => null)
throw new Error(errorData?.error?.message || errorData?.message || 'Failed to create bulk offers')
}

const json = await response.json()
return json.data
}
4 changes: 4 additions & 0 deletions src/api/siwe/checkAuthentication.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export type ProfileResponseType = {
emailVerified: boolean
telegram: string | null
discord: string | null
tier: 'free' | 'pro' | 'plus' | 'gold'
tierId: number
tierExpiresAt: string | null
isAdmin: boolean
createdAt: string
lastSignIn: string
updatedAt: string
Expand Down
4 changes: 4 additions & 0 deletions src/api/siwe/verifySignature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ type VerifyResponse = {
minOfferThreshold: number | null
notifyOnListingSold: boolean
notifyOnOfferReceived: boolean
tier: 'free' | 'pro' | 'plus' | 'gold'
tierId: number
tierExpiresAt: string | null
isAdmin: boolean
}
}

Expand Down
29 changes: 20 additions & 9 deletions src/app/analytics/hooks/useAnalyticsData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,18 @@ import {
} from '@/api/analytics'
import { AnalyticsPeriod, AnalyticsSource } from '@/types/analytics'

interface UseAnalyticsOptions {
export interface UseAnalyticsOptions {
categoryOverride?: string | null
periodOverride?: AnalyticsPeriod
sourceOverride?: AnalyticsSource
limitOverride?: number
}

export const useTopListings = (options?: UseAnalyticsOptions) => {
const { period, source, category: reduxCategory } = useAppSelector(selectAnalytics)
const { period: reduxPeriod, source: reduxSource, category: reduxCategory } = useAppSelector(selectAnalytics)
const category = options?.categoryOverride !== undefined ? options.categoryOverride : reduxCategory
const period = options?.periodOverride !== undefined ? options.periodOverride : reduxPeriod
const source = options?.sourceOverride !== undefined ? options.sourceOverride : reduxSource

return useQuery({
queryKey: ['analytics', 'topListings', period, source, category],
Expand All @@ -33,8 +35,10 @@ export const useTopListings = (options?: UseAnalyticsOptions) => {
}

export const useTopOffers = (options?: UseAnalyticsOptions) => {
const { period, source, category: reduxCategory } = useAppSelector(selectAnalytics)
const { period: reduxPeriod, source: reduxSource, category: reduxCategory } = useAppSelector(selectAnalytics)
const category = options?.categoryOverride !== undefined ? options.categoryOverride : reduxCategory
const period = options?.periodOverride !== undefined ? options.periodOverride : reduxPeriod
const source = options?.sourceOverride !== undefined ? options.sourceOverride : reduxSource

return useQuery({
queryKey: ['analytics', 'topOffers', period, source, category],
Expand All @@ -44,8 +48,10 @@ export const useTopOffers = (options?: UseAnalyticsOptions) => {
}

export const useTopSales = (options?: UseAnalyticsOptions) => {
const { period, source, category: reduxCategory } = useAppSelector(selectAnalytics)
const { period: reduxPeriod, source: reduxSource, category: reduxCategory } = useAppSelector(selectAnalytics)
const category = options?.categoryOverride !== undefined ? options.categoryOverride : reduxCategory
const period = options?.periodOverride !== undefined ? options.periodOverride : reduxPeriod
const source = options?.sourceOverride !== undefined ? options.sourceOverride : reduxSource

return useQuery({
queryKey: ['analytics', 'topSales', period, source, category],
Expand All @@ -69,8 +75,9 @@ export const useTopRegistrations = (options?: UseAnalyticsOptions) => {
}

export const useListingsChart = (options?: UseAnalyticsOptions) => {
const { period, category: reduxCategory } = useAppSelector(selectAnalytics)
const { period: reduxPeriod, category: reduxCategory } = useAppSelector(selectAnalytics)
const category = options?.categoryOverride !== undefined ? options.categoryOverride : reduxCategory
const period = options?.periodOverride !== undefined ? options.periodOverride : reduxPeriod

return useQuery({
queryKey: ['analytics', 'listingsChart', period, category],
Expand All @@ -80,8 +87,9 @@ export const useListingsChart = (options?: UseAnalyticsOptions) => {
}

export const useOffersChart = (options?: UseAnalyticsOptions) => {
const { period, category: reduxCategory } = useAppSelector(selectAnalytics)
const { period: reduxPeriod, category: reduxCategory } = useAppSelector(selectAnalytics)
const category = options?.categoryOverride !== undefined ? options.categoryOverride : reduxCategory
const period = options?.periodOverride !== undefined ? options.periodOverride : reduxPeriod

return useQuery({
queryKey: ['analytics', 'offersChart', period, category],
Expand All @@ -91,8 +99,9 @@ export const useOffersChart = (options?: UseAnalyticsOptions) => {
}

export const useSalesChart = (options?: UseAnalyticsOptions) => {
const { period, category: reduxCategory } = useAppSelector(selectAnalytics)
const { period: reduxPeriod, category: reduxCategory } = useAppSelector(selectAnalytics)
const category = options?.categoryOverride !== undefined ? options.categoryOverride : reduxCategory
const period = options?.periodOverride !== undefined ? options.periodOverride : reduxPeriod

return useQuery({
queryKey: ['analytics', 'salesChart', period, category],
Expand All @@ -102,8 +111,9 @@ export const useSalesChart = (options?: UseAnalyticsOptions) => {
}

export const useRegistrationsChart = (options?: UseAnalyticsOptions) => {
const { period, category: reduxCategory } = useAppSelector(selectAnalytics)
const { period: reduxPeriod, category: reduxCategory } = useAppSelector(selectAnalytics)
const category = options?.categoryOverride !== undefined ? options.categoryOverride : reduxCategory
const period = options?.periodOverride !== undefined ? options.periodOverride : reduxPeriod

return useQuery({
queryKey: ['analytics', 'registrationsChart', period, category],
Expand All @@ -113,8 +123,9 @@ export const useRegistrationsChart = (options?: UseAnalyticsOptions) => {
}

export const useVolumeChart = (options?: UseAnalyticsOptions) => {
const { period, category: reduxCategory } = useAppSelector(selectAnalytics)
const { period: reduxPeriod, category: reduxCategory } = useAppSelector(selectAnalytics)
const category = options?.categoryOverride !== undefined ? options.categoryOverride : reduxCategory
const period = options?.periodOverride !== undefined ? options.periodOverride : reduxPeriod

return useQuery({
queryKey: ['analytics', 'volumeChart', period, category],
Expand Down
3 changes: 1 addition & 2 deletions src/app/api/auth/logout/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { NextRequest, NextResponse } from 'next/server'

const API_URL = 'https://api.grails.app/api/v1'
import { API_URL } from '@/constants/api'

export async function POST(request: NextRequest) {
try {
Expand Down
3 changes: 1 addition & 2 deletions src/app/api/auth/nonce/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { NextRequest, NextResponse } from 'next/server'

const API_URL = 'https://api.grails.app/api/v1'
import { API_URL } from '@/constants/api'

export async function GET(request: NextRequest) {
const { searchParams } = new URL(request.url)
Expand Down
3 changes: 1 addition & 2 deletions src/app/api/auth/verify/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { NextRequest, NextResponse } from 'next/server'

const API_URL = 'https://api.grails.app/api/v1'
import { API_URL } from '@/constants/api'

export async function POST(request: NextRequest) {
try {
Expand Down
28 changes: 28 additions & 0 deletions src/app/api/offers/bulk/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { NextRequest, NextResponse } from 'next/server'
import { API_URL } from '@/constants/api'

export async function POST(request: NextRequest) {
try {
const token = request.cookies.get('token')?.value
if (!token) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}

const body = await request.json()

const response = await fetch(`${API_URL}/offers/bulk`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${token}`,
},
body: JSON.stringify(body),
})

const data = await response.json()
return NextResponse.json(data, { status: response.status })
} catch (error) {
console.error('Error creating bulk offers:', error)
return NextResponse.json({ error: 'Failed to create bulk offers' }, { status: 500 })
}
}
3 changes: 1 addition & 2 deletions src/app/api/users/me/route.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { NextRequest, NextResponse } from 'next/server'

const API_URL = 'https://api.grails.app/api/v1'
import { API_URL } from '@/constants/api'

export async function GET(request: NextRequest) {
try {
Expand Down
Loading