diff --git a/netlify/edge-functions/events.js b/netlify/edge-functions/events.js index 05a441c..ddbb0c2 100644 --- a/netlify/edge-functions/events.js +++ b/netlify/edge-functions/events.js @@ -87,10 +87,10 @@ export default async function handler(request, context) { }) } - totalSupply += eventInfo.owners.length + totalSupply += eventInfo.owners?.owners.length ?? 0 totalReservations += eventInfo.metrics?.emailReservations ?? 0 names = [...names, eventInfo.event.name] - ts = Math.max(ts, eventInfo.ts ?? eventInfo.metrics?.ts) + ts = Math.max(ts, eventInfo.owners?.ts ?? eventInfo.metrics?.ts) } return new Response( diff --git a/netlify/edge-functions/frame.jsx b/netlify/edge-functions/frame.jsx index c1148bb..c1e7809 100644 --- a/netlify/edge-functions/frame.jsx +++ b/netlify/edge-functions/frame.jsx @@ -44,9 +44,9 @@ export default async function handler(request, context) { for (const eventInfo of eventsInfo) { allCollectors = allCollectors == null - ? eventInfo.owners - : intersection(allCollectors, eventInfo.owners) - totalSupply += eventInfo.owners.length + ? eventInfo.owners?.owners ?? [] + : intersection(allCollectors, eventInfo.owners?.owners ?? []) + totalSupply += eventInfo.owners?.owners.length ?? 0 totalReservations += eventInfo.metrics?.emailReservations ?? 0 totalMoments += eventInfo.metrics?.momentsUploaded ?? 0 } diff --git a/netlify/loaders/api.js b/netlify/loaders/api.js index 4c7ba1d..d63c17b 100644 --- a/netlify/loaders/api.js +++ b/netlify/loaders/api.js @@ -3,7 +3,7 @@ export async function getEventInfo(eventId, env) { return null } const response = await fetch( - `${env.FAMILY_API_URL}/event/${eventId}?description=false&metrics=true&fresh=true&refresh=false`, + `${env.FAMILY_API_URL}/event/${eventId}?description=false&metrics=true`, { headers: { 'x-api-key': env.FAMILY_API_KEY, @@ -64,7 +64,7 @@ export async function getEvents(eventIds, env) { return null } const response = await fetch( - `${env.FAMILY_API_URL}/events/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}?fresh=true`, + `${env.FAMILY_API_URL}/events/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}`, { headers: { 'x-api-key': env.FAMILY_API_KEY, @@ -93,11 +93,7 @@ export async function getEvents(eventIds, env) { if (typeof body !== 'object') { return null } - return Object.fromEntries( - Object.entries(body).map( - ([eventId, event]) => [eventId, event] - ) - ) + return body } export async function getEventsOwners(eventIds, env) { @@ -106,16 +102,13 @@ export async function getEventsOwners(eventIds, env) { } const response = await fetch( `${env.FAMILY_API_URL}/events` + - `/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}/owners?fresh=false`, + `/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}/owners`, { headers: { 'x-api-key': env.FAMILY_API_KEY, }, } ) - if (response.status === 404) { - return null - } if (response.status !== 200) { let message try { @@ -143,7 +136,7 @@ export async function getEventsMetrics(eventIds, env) { throw new Error(`Events (${eventIds.length}) metrics could not be fetched, configure Family API key`) } const response = await fetch( - `${env.FAMILY_API_URL}/events/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}/metrics?fresh=true`, + `${env.FAMILY_API_URL}/events/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}/metrics`, { headers: { 'x-api-key': env.FAMILY_API_KEY, @@ -168,9 +161,9 @@ export async function getEventsMetrics(eventIds, env) { } throw new Error(`Events (${eventIds.length}) failed to fetch metrics (status ${response.status})`) } - const metricsMap = await response.json() - if (typeof metricsMap !== 'object') { + const body = await response.json() + if (typeof body !== 'object') { return null } - return metricsMap + return body } diff --git a/package.json b/package.json index 11668d2..068482f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@poap-xyz/poap-family", - "version": "1.12.9", + "version": "1.12.10", "author": { "name": "POAP", "url": "https://poap.xyz" diff --git a/src/loaders/api.js b/src/loaders/api.js index 231fed7..b589221 100644 --- a/src/loaders/api.js +++ b/src/loaders/api.js @@ -1,13 +1,12 @@ import axios from 'axios' import { FAMILY_API_KEY, FAMILY_API_URL } from '../models/api' -import { encodeExpiryDates, Event } from '../models/event' +import { encodeExpiryDates, Event, EventOwners } from '../models/event' async function getEventAndOwners( eventId, abortSignal, includeDescription = false, includeMetrics = true, - fresh = true, refresh = false, ) { if (!FAMILY_API_KEY) { @@ -17,7 +16,6 @@ async function getEventAndOwners( `${FAMILY_API_URL}/event/${eventId}?` + `description=${encodeURIComponent(includeDescription)}&` + `metrics=${encodeURIComponent(includeMetrics)}` + - `${fresh ? '&fresh=true' : ''}` + `${refresh ? '&refresh=true' : ''}`, { signal: abortSignal instanceof AbortSignal ? abortSignal : undefined, @@ -213,13 +211,12 @@ async function getLastEvents(page = 1, qty = 3) { } } -async function getEvents(eventIds, fresh = true) { +async function getEvents(eventIds) { if (!FAMILY_API_KEY) { return null } const response = await fetch( - `${FAMILY_API_URL}/events/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}` + - `${fresh ? '?fresh=true' : ''}`, + `${FAMILY_API_URL}/events/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}`, { headers: { 'x-api-key': FAMILY_API_KEY, @@ -255,7 +252,7 @@ async function getEvents(eventIds, fresh = true) { ) } -async function getEventsOwners(eventIds, abortSignal, expiryDates, fresh = true) { +async function getEventsOwners(eventIds, abortSignal, expiryDates) { if (!FAMILY_API_KEY) { return null } @@ -263,7 +260,7 @@ async function getEventsOwners(eventIds, abortSignal, expiryDates, fresh = true) const response = await fetch( `${FAMILY_API_URL}/events` + `/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}` + - `/owners${queryString ? `?${queryString}${fresh ? '&fresh=true' : ''}` : fresh ? '?fresh=true' : ''}`, + `/owners${queryString ? `?${queryString}` : ''}`, { signal: abortSignal instanceof AbortSignal ? abortSignal : null, headers: { @@ -271,9 +268,6 @@ async function getEventsOwners(eventIds, abortSignal, expiryDates, fresh = true) }, } ) - if (response.status === 404) { - return null - } if (response.status !== 200) { let message try { @@ -293,17 +287,19 @@ async function getEventsOwners(eventIds, abortSignal, expiryDates, fresh = true) if (typeof body !== 'object') { return null } - return body + return Object.fromEntries( + Object.entries(body).map( + ([eventId, event]) => [eventId, EventOwners(event)] + ) + ) } -async function getEventMetrics(eventId, abortSignal, refresh = false, fresh = true) { +async function getEventMetrics(eventId, abortSignal, refresh = false) { if (!FAMILY_API_KEY) { throw new Error(`Event ${eventId} metrics could not be fetched, configure Family API key`) } const response = await fetch( - `${FAMILY_API_URL}/event/${eventId}/metrics?` + - `refresh=${encodeURIComponent(refresh)}&` + - `fresh=${encodeURIComponent(fresh)}`, + `${FAMILY_API_URL}/event/${eventId}/metrics${refresh ? '?refresh=true' : ''}`, { signal: abortSignal instanceof AbortSignal ? abortSignal : null, headers: { @@ -340,13 +336,12 @@ async function getEventMetrics(eventId, abortSignal, refresh = false, fresh = tr } } -async function getEventsMetrics(eventIds, abortSignal, fresh = true) { +async function getEventsMetrics(eventIds, abortSignal) { if (!FAMILY_API_KEY) { throw new Error(`Events (${eventIds.length}) metrics could not be fetched, configure Family API key`) } const response = await fetch( - `${FAMILY_API_URL}/events/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}/metrics?` + - `fresh=${encodeURIComponent(fresh)}`, + `${FAMILY_API_URL}/events/${eventIds.map((eventId) => encodeURIComponent(eventId)).join(',')}/metrics`, { signal: abortSignal instanceof AbortSignal ? abortSignal : null, headers: { diff --git a/src/loaders/event.js b/src/loaders/event.js index 4ab1944..b128e0f 100644 --- a/src/loaders/event.js +++ b/src/loaders/event.js @@ -154,7 +154,6 @@ async function eventLoader({ params, request }) { /*abortSignal*/undefined, /*includeDescription*/true, /*includeMetrics*/true, - /*fresh*/true, /*refresh*/force === 'true' ) if (eventAndOwners != null) { @@ -177,7 +176,7 @@ async function eventLoader({ params, request }) { } const [tokensSettled, metricsSettled] = await Promise.allSettled([ fetchPOAPs(params.eventId), - getEventMetrics(params.eventId, null, /*refresh*/force === 'true', /*fresh*/true), + getEventMetrics(params.eventId, null, /*refresh*/force === 'true'), ]) if (tokensSettled.status === 'rejected') { throw new Response('', { @@ -233,7 +232,7 @@ async function eventsLoader({ params, request }) { const force = new URL(request.url).searchParams.get('force') if (!force) { try { - const events = await getEvents(eventIds, /*fresh*/true) + const events = await getEvents(eventIds) if (events) { const notFoundEventIds = [] for (const eventId of eventIds) { diff --git a/src/models/event.js b/src/models/event.js index 2c77490..c058dfd 100644 --- a/src/models/event.js +++ b/src/models/event.js @@ -18,6 +18,27 @@ function Event(event, includeDescription) { } } +function EventOwners(eventOwners) { + if ( + eventOwners == null || + typeof eventOwners !== 'object' || + !('owners' in eventOwners) || + ( + eventOwners.owners != null && + !Array.isArray(eventOwners.owners) + ) || + !('ts' in eventOwners) || + eventOwners.ts == null || + typeof eventOwners.ts !== 'number' + ) { + throw new Error('Malformed event owners') + } + return { + owners: eventOwners.owners, + ts: eventOwners.ts, + } +} + function parseEventIds(rawIds) { let eventIds = (rawIds ?? '').split(',') .filter((value, index, all) => all.indexOf(value) === index) @@ -65,6 +86,7 @@ const SEARCH_LIMIT = 10 export { Event, + EventOwners, parseEventIds, joinEventIds, parseExpiryDates, diff --git a/src/pages/Addresses.js b/src/pages/Addresses.js index 6896a99..6c9af3d 100644 --- a/src/pages/Addresses.js +++ b/src/pages/Addresses.js @@ -357,7 +357,10 @@ function Addresses() { setLoadingEventsOwners(false) if (ownersMap) { const uniqueOwners = Object.values(ownersMap).reduce( - (allOwners, eventOwners) => new Set([...allOwners, ...eventOwners]), + (allOwners, eventOwners) => new Set([ + ...allOwners, + ...(eventOwners?.owners ?? []), + ]), new Set() ) const addresses = [...uniqueOwners].map((owner) => parseAddress(owner)) diff --git a/src/pages/Events.js b/src/pages/Events.js index 59f3e4f..6f0a096 100644 --- a/src/pages/Events.js +++ b/src/pages/Events.js @@ -122,7 +122,13 @@ function Events() { } removeErrors(eventId) setLoading((alsoLoading) => ({ ...alsoLoading, [eventId]: LOADING_OWNERS })) - return getEventAndOwners(eventId, abortSignal, /*includeDescription*/false, /*includeMetrics*/true, /*fresh*/true).then( + return getEventAndOwners( + eventId, + abortSignal, + /*includeDescription*/false, + /*includeMetrics*/true, + /*refresh*/false + ).then( (eventAndOwners) => { removeLoading(eventId) if (eventAndOwners != null) { @@ -157,7 +163,7 @@ function Events() { setLoading((alsoLoading) => ({ ...alsoLoading, [eventId]: LOADING_OWNERS })) return Promise.allSettled([ fetchPOAPs(eventId, abortSignal), - getEventMetrics(eventId, abortSignal, searchParams.get('force') === 'true', /*fresh*/true), + getEventMetrics(eventId, abortSignal, searchParams.get('force') === 'true'), ]).then( ([eventOwnerTokensResult, eventMetricsResult]) => { removeLoading(eventId) @@ -337,17 +343,26 @@ function Events() { const controller = new AbortController() const expiryDates = parseExpiryDates(events) Promise.all([ - getEventsOwners(eventIds, controller.signal, expiryDates, /*fresh*/false), - getEventsMetrics(eventIds, controller.signal, /*fresh*/true), + getEventsOwners(eventIds, controller.signal, expiryDates), + getEventsMetrics(eventIds, controller.signal), ]).then( - ([newOwners, eventsMetrics]) => { + ([eventsOwners, eventsMetrics]) => { if (eventsMetrics) { const foundMetrics = Object.fromEntries( Object.entries(eventsMetrics).filter(([, metrics]) => metrics != null) ) setMetrics((oldReservations) => ({ ...oldReservations, ...foundMetrics })) } - if (newOwners) { + if (eventsOwners) { + const newOwners = Object.fromEntries( + Object.entries(eventsOwners) + .map( + ([eventId, eventOwners]) => [ + eventId, + eventOwners == null ? [] : eventOwners.owners, + ] + ) + ) setOwners((oldOwners) => ({ ...oldOwners, ...newOwners })) if (Object.keys(newOwners).length === eventIds.length) { resolveEnsNames(