From 6a616486fcef8dd4ab314e9d5ece07d865bbed6b Mon Sep 17 00:00:00 2001 From: Samuel Tinnerholm Date: Sun, 21 Jun 2026 06:35:14 +0000 Subject: [PATCH] fix(core): handle renamed SuiBets event fields --- core/src/exchanges/suibets/fetcher.ts | 30 ++++++++------ core/src/exchanges/suibets/normalizer.ts | 29 +++++++++---- core/test/exchanges/suibets-fetcher.test.ts | 41 +++++++++++++++++++ .../normalizers/suibets-normalizer.test.ts | 19 +++++++++ 4 files changed, 100 insertions(+), 19 deletions(-) create mode 100644 core/test/exchanges/suibets-fetcher.test.ts diff --git a/core/src/exchanges/suibets/fetcher.ts b/core/src/exchanges/suibets/fetcher.ts index d3bcad39..2330e24b 100644 --- a/core/src/exchanges/suibets/fetcher.ts +++ b/core/src/exchanges/suibets/fetcher.ts @@ -4,9 +4,12 @@ import { suibetsErrorMapper } from './errors'; export interface SuibetsRawOffer { id: string; - matchId: string; - matchName: string; - sport: string; + matchId?: string; + eventId?: string; + matchName?: string; + eventName?: string; + sport?: string; + sportName?: string; homeTeam: string; awayTeam: string; creatorWallet: string; @@ -30,7 +33,8 @@ export interface SuibetsRawEvent { name: string; homeTeam: string; awayTeam: string; - sport: string; + sport?: string; + sportName?: string; leagueName?: string; matchDate: string; status: string; @@ -165,12 +169,13 @@ export class SuibetsFetcher implements IExchangeFetcher(); for (const offer of offers) { - if (!offer.matchId) continue; - const existing = byMatch.get(offer.matchId) ?? []; - byMatch.set(offer.matchId, [...existing, offer]); + const eventId = offer.matchId ?? offer.eventId; + if (!eventId) continue; + const existing = byMatch.get(eventId) ?? []; + byMatch.set(eventId, [...existing, offer]); } const q = params.query?.toLowerCase(); @@ -181,19 +186,20 @@ export class SuibetsFetcher implements IExchangeFetcher { normalizeMarket(raw: SuibetsRawOffer): UnifiedMarket | null { if (!raw?.id) return null; @@ -35,6 +47,9 @@ export class SuibetsNormalizer implements IExchangeNormalizer Boolean(t)), + tags: ['Sports', 'P2P', sport, raw.leagueName].filter((t): t is string => Boolean(t)), contractAddress: raw.onchainOfferId, yes: creatorOutcome, no: takerOutcome, @@ -93,7 +108,7 @@ export class SuibetsNormalizer implements IExchangeNormalizer Boolean(t)), + tags: ['Sports', 'P2P', 'Sui', offerSport(raw), raw.leagueName].filter((t): t is string => Boolean(t)), }; } normalizePosition(raw: SuibetsRawOffer): Position { const odds = Number(raw.creatorOdds) || 2; return { - marketId: toMarketId(raw.matchId ?? raw.id), + marketId: toMarketId(offerEventId(raw) ?? raw.id), outcomeId: toOutcomeId(raw.id, 'creator'), outcomeLabel: sideLabel(raw, 'creator'), size: mistToSui(raw.creatorStake ?? 0), diff --git a/core/test/exchanges/suibets-fetcher.test.ts b/core/test/exchanges/suibets-fetcher.test.ts new file mode 100644 index 00000000..b5e92790 --- /dev/null +++ b/core/test/exchanges/suibets-fetcher.test.ts @@ -0,0 +1,41 @@ +import { SuibetsFetcher } from '../../src/exchanges/suibets/fetcher'; + +describe('SuibetsFetcher', () => { + it('groups offers by renamed eventId when matchId is absent', async () => { + const http = { + get: jest.fn().mockResolvedValue({ + data: { + offers: [ + { + id: 'offer-1', + eventId: 'event-1', + eventName: 'Mets vs Yankees', + sportName: 'Baseball', + homeTeam: 'Mets', + awayTeam: 'Yankees', + creatorWallet: '0xabc', + creatorTeam: 'Mets', + creatorOdds: 2, + creatorStake: 1_000_000_000, + takerStake: 1_000_000_000, + matchDate: '2026-07-01T18:00:00Z', + expiresAt: '2026-07-01T17:00:00Z', + status: 'OPEN', + }, + ], + }, + }), + }; + const fetcher = new SuibetsFetcher({ http } as any, 'https://api.example.test'); + + const events = await fetcher.fetchRawEvents({} as any); + + expect(events).toHaveLength(1); + expect(events[0]).toMatchObject({ + id: 'event-1', + name: 'Mets vs Yankees', + sport: 'Baseball', + }); + expect(events[0].offers).toHaveLength(1); + }); +}); \ No newline at end of file diff --git a/core/test/normalizers/suibets-normalizer.test.ts b/core/test/normalizers/suibets-normalizer.test.ts index 3faa75de..d39a58ad 100644 --- a/core/test/normalizers/suibets-normalizer.test.ts +++ b/core/test/normalizers/suibets-normalizer.test.ts @@ -84,6 +84,25 @@ describe('SuibetsNormalizer', () => { // ------------------------------------------------------------------------- describe('normalizeMarket', () => { + it('uses renamed eventId, eventName, and sportName fields from current SuiBets offers', () => { + const renamedOffer = { + ...rawOffer, + matchId: undefined, + matchName: undefined, + sport: undefined, + eventId: 'event-789', + eventName: 'Mets vs Yankees', + sportName: 'Baseball', + } as unknown as SuibetsRawOffer; + + const market = normalizer.normalizeMarket(renamedOffer)!; + + expect(market.eventId).toBe('suibets:event-789'); + expect(market.title).toContain('Mets vs Yankees'); + expect(market.description).toContain('Baseball match'); + expect(market.tags).toContain('Baseball'); + }); + it('returns a non-null result for a valid offer', () => { const market = normalizer.normalizeMarket(rawOffer); expect(market).not.toBeNull();