Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
@if (data) {
@for (
phunk of data;
track phunk.sha;
track phunk.event?.txId || phunk.sha;
let i = $index;
) {
@if (i < limit) {
Expand Down
49 changes: 34 additions & 15 deletions marketplace/src/app/services/data.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { Store } from '@ngrx/store';

import { createClient, RealtimePostgresUpdatePayload, RealtimePostgresInsertPayload } from '@supabase/supabase-js'

import { Observable, of, from, forkJoin, firstValueFrom, EMPTY, timer, merge, filter, share, catchError, debounceTime, expand, map, reduce, switchMap, tap, distinctUntilChanged, BehaviorSubject } from 'rxjs';
import { Observable, of, from, forkJoin, firstValueFrom, EMPTY, timer, merge, filter, share, catchError, debounceTime, expand, map, reduce, switchMap, tap, distinctUntilChanged, BehaviorSubject, defer, retry } from 'rxjs';

import { Web3Service } from '@/services/web3.service';
import { AttributesService } from '@/services/attributes.service';
Expand Down Expand Up @@ -316,19 +316,21 @@ export class DataService {
type: EventType,
slug: string,
): Observable<Event[]> {
const query = supabase.rpc(
'fetch_events' + this.suffix,
{
p_limit: limit,
p_type: type && type !== 'All' ? type : null,
p_collection_slug: slug,
p_offset: offset,
}
);

const rpcFetch$ = from(query).pipe(
const rpcFetch$ = defer(() => from(
supabase.rpc(
'fetch_events' + this.suffix,
{
p_limit: limit,
p_type: type && type !== 'All' ? type : null,
p_collection_slug: slug,
p_offset: offset,
}
)
)).pipe(
map((res: any) => {
const result = res.data?.map((tx: any) => {
if (res.error) throw res.error;

const result = (res.data || []).map((tx: any) => {
let type = tx.type;
if (type === 'transfer') {
if (tx.to?.toLowerCase() === environment.bridgeAddress) type = 'bridgeOut';
Expand All @@ -338,6 +340,14 @@ export class DataService {
});
return result;
}),
retry({
count: 2,
delay: (_err, retryCount) => timer(retryCount * 500),
}),
catchError((err) => {
console.warn('Failed to fetch recent activity events', { slug, type, offset, err });
return of([]);
}),
);

return merge(
Expand Down Expand Up @@ -826,13 +836,14 @@ export class DataService {
};

// Initial fetch
const rpcFetch$: Observable<Collection[]> = from(
const rpcFetch$: Observable<Collection[]> = defer(() => from(
supabase.rpc(
'fetch_collections_with_previews' + this.suffix,
params
)
).pipe(
)).pipe(
map((res: any) => {
if (res.error) throw res.error;
if (!res.data) return [];
return res.data
.map((item: any) => ({
Expand All @@ -847,6 +858,14 @@ export class DataService {
return true;
});
}),
retry({
count: 2,
delay: (_err, retryCount) => timer(retryCount * 500),
}),
catchError((err) => {
console.warn('Failed to fetch collections', { onlyDisabled, err });
return of([]);
}),
// tap((res) => console.log('fetchCollections', res)),
);

Expand Down
24 changes: 14 additions & 10 deletions marketplace/src/app/state/data/data-state.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import * as dataStateActions from '@/state/data/data-state.actions';
import * as dataStateSelectors from '@/state/data/data-state.selectors';

import * as marketStateSelectors from '@/state/market/market-state.selectors';
import * as marketStateActions from '@/state/market/market-state.actions';

import { filter, map, switchMap, take, tap } from 'rxjs';
import { distinctUntilChanged, filter, map, switchMap, take, withLatestFrom } from 'rxjs';

@Injectable()
export class DataStateEffects {
Expand Down Expand Up @@ -46,15 +47,18 @@ export class DataStateEffects {
));

setActiveCollection$ = createEffect(() => this.actions$.pipe(
ofType(dataStateActions.setCollections),
switchMap((action) => {
return this.store.select(marketStateSelectors.selectMarketSlug).pipe(
filter(() => !!action.collections),
map((slug) => action.collections.find((c) => c.slug === slug)),
filter((activeCollection) => !!activeCollection),
map((activeCollection) => dataStateActions.setActiveCollection({ activeCollection: { ...activeCollection! } }))
);
}),
ofType(
dataStateActions.setCollections,
marketStateActions.setMarketSlug,
),
withLatestFrom(
this.store.select(dataStateSelectors.selectCollections),
this.store.select(marketStateSelectors.selectMarketSlug),
),
map(([, collections, slug]) => collections.find((c) => c.slug === slug)),
filter((activeCollection) => !!activeCollection),
distinctUntilChanged((a, b) => a?.slug === b?.slug),
map((activeCollection) => dataStateActions.setActiveCollection({ activeCollection: { ...activeCollection! } }))
));

fetchLeaderboard$ = createEffect(() => this.actions$.pipe(
Expand Down
11 changes: 10 additions & 1 deletion marketplace/src/app/state/market/market-state.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,10 +154,19 @@ export class MarketStateEffects {
if (page === 0) return events;
return [...acc, ...events];
}, [] as Event[]),
map((events) => ({ events, marketSlug })),
);
}),
withLatestFrom(this.store.select(marketStateSelectors.selectMarketSlug)),
filter(([{ marketSlug }, currentMarketSlug]) => marketSlug === currentMarketSlug),
// tap((events) => console.log('fetchEvents$', events)),
map((events) => dataStateActions.setEvents({ events })),
map(([{ events }]) => dataStateActions.setEvents({ events })),
));

clearEventsOnMarketSlugChange$ = createEffect(() => this.actions$.pipe(
ofType(marketStateActions.setMarketSlug),
distinctUntilChanged((a, b) => a.marketSlug === b.marketSlug),
map(() => dataStateActions.setEvents({ events: [] })),
));

setActionData$ = createEffect(() => this.actions$.pipe(
Expand Down
13 changes: 12 additions & 1 deletion marketplace/src/app/state/market/market-state.reducers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,20 @@ export const marketStateReducer: ActionReducer<MarketState, Action> = createRedu
return setMarketType
}),
on(actions.setMarketSlug, (state, { marketSlug }) => {
if (state.marketSlug === marketSlug) return state;

const setMarketSlug = {
...state,
marketSlug
marketSlug,
marketData: initialState.marketData,
owned: initialState.owned,
listings: initialState.listings,
bids: initialState.bids,
all: initialState.all,
auctions: initialState.auctions,
activeMarketRouteData: initialState.activeMarketRouteData,
selectedPhunks: initialState.selectedPhunks,
pagination: initialState.pagination,
};
return setMarketSlug;
}),
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
CREATE INDEX IF NOT EXISTS ethscriptions_slug_hash_id_idx
ON public.ethscriptions (slug, "hashId");

CREATE INDEX IF NOT EXISTS events_hash_id_block_timestamp_tx_id_idx
ON public.events ("hashId", "blockTimestamp" DESC, "txId");

CREATE INDEX IF NOT EXISTS events_type_hash_id_block_timestamp_tx_id_idx
ON public.events (type, "hashId", "blockTimestamp" DESC, "txId");

CREATE INDEX IF NOT EXISTS events_recent_activity_order_idx
ON public.events ("blockTimestamp" DESC, "txId", "hashId")
INCLUDE ("from", "to", type, value)
WHERE
type <> 'PhunkNoLongerForSale'
AND "to" <> '0xd3418772623be1a3cc6b6d45cb46420cedd9154a'
AND "to" <> ''
AND "from" <> '';

CREATE INDEX IF NOT EXISTS ethscriptions_sepolia_slug_hash_id_idx
ON public.ethscriptions_sepolia (slug, "hashId");

CREATE INDEX IF NOT EXISTS events_sepolia_hash_id_block_timestamp_tx_id_idx
ON public.events_sepolia ("hashId", "blockTimestamp" DESC, "txId");

CREATE INDEX IF NOT EXISTS events_sepolia_type_hash_id_block_timestamp_tx_id_idx
ON public.events_sepolia (type, "hashId", "blockTimestamp" DESC, "txId");

CREATE INDEX IF NOT EXISTS events_sepolia_recent_activity_order_idx
ON public.events_sepolia ("blockTimestamp" DESC, "txId", "hashId")
INCLUDE ("from", "to", type, value)
WHERE
type <> 'PhunkNoLongerForSale'
AND "to" <> '0x3dfbc8c62d3ce0059bdaf21787ec24d5d116fe1e'
AND "to" <> '0xc6a824d8cce7c946a3f35879694b9261a36fc823'
AND "from" <> '0xc6a824d8cce7c946a3f35879694b9261a36fc823';