@pump-fun/shared-contracts
Version:
Shared contracts for Pump.fun microservices.
228 lines (198 loc) • 5.29 kB
text/typescript
/**
* Core notification types for the Pump.fun notification system
*/
import type { PumpDeeplinks } from "./deep-links";
// ============================================
// CONSTANTS
// ============================================
/**
* Available FCM topics
*
* Current usage:
* - GLOBAL: Currently used for all article/news notifications (temporary)
* - NEWS: Reserved for future migration of article notifications
* - TRENDING: Reserved for trending/popular content notifications
*/
export const TOPICS = {
GLOBAL: "global" as const,
NEWS: "news" as const,
TRENDING: "trending" as const,
} as const;
/**
* Notification type identifiers
*/
export const NOTIFICATION_TYPES = {
ARTICLE_PUBLISHED: "ARTICLE_PUBLISHED" as const,
PORTFOLIO_LIVESTREAM_STARTED: "PORTFOLIO_LIVESTREAM_STARTED" as const,
PORTFOLIO_PNL_ALERT: "PORTFOLIO_PNL_ALERT" as const,
} as const;
/**
* String union type of all notification types
*/
export type NotificationType = (typeof NOTIFICATION_TYPES)[keyof typeof NOTIFICATION_TYPES];
// ============================================
// NOTIFICATION CONTENT TYPES
// ============================================
/**
* Base structure for all notification content data
*/
export interface BaseNotificationData {
notificationId: string;
notificationType: NotificationType;
deeplink: PumpDeeplinks;
}
/**
* Livestream started notification content
*/
export interface LivestreamStartedData extends BaseNotificationData {
notificationType: "PORTFOLIO_LIVESTREAM_STARTED";
livestreamId: string;
creatorAddress: string;
creatorUsername: string;
mintId: string;
tokenAmount: string;
}
/**
* Article published notification content
*/
export interface ArticlePublishedData extends BaseNotificationData {
notificationType: "ARTICLE_PUBLISHED";
articleId: string;
documentId: string;
mintId: string;
timestamp: string;
locale: string;
}
export interface PortfolioPnlData extends BaseNotificationData {
notificationType: "PORTFOLIO_PNL_ALERT";
mintId: string;
pnlPercent: number;
tickerName: string;
timestamp: string;
}
/**
* Union of all notification content types
*/
export type NotificationData = LivestreamStartedData | ArticlePublishedData | PortfolioPnlData;
// ============================================
// NOTIFICATION DELIVERY TYPES
// ============================================
/**
* Individual user targeting
*/
export interface IndividualTarget {
type: "individual";
walletAddress: string;
}
/**
* Topic-based broadcast targeting
*/
export interface TopicTarget {
type: "topic";
topic: "global" | "news" | "announcements";
}
/**
* Union of all targeting types
*/
export type NotificationTarget = IndividualTarget | TopicTarget;
// ============================================
// COMPLETE NOTIFICATION TYPE
// ============================================
/**
* A complete push notification ready to be sent
*/
export interface PushNotification {
/**
* Unique identifier for this notification instance
*/
id: string;
/**
* Display content
*/
title: string;
body: string;
/**
* Structured data payload
*/
data: NotificationData;
/**
* Delivery target
*/
target: NotificationTarget;
/**
* Metadata
*/
timestamp: number;
priority?: "normal" | "high";
ttl?: number; // Time to live in seconds
}
// ============================================
// FACTORY FUNCTIONS
// ============================================
/**
* Create an individual notification
*/
export function createIndividualNotification(params: {
id: string;
title: string;
body: string;
data: LivestreamStartedData | ArticlePublishedData;
walletAddress: string;
priority?: "normal" | "high";
ttl?: number;
}): PushNotification {
return {
body: params.body,
data: params.data,
id: params.id,
priority: params.priority,
target: {
type: "individual",
walletAddress: params.walletAddress,
},
timestamp: Date.now(),
title: params.title,
ttl: params.ttl,
};
}
/**
* Create a topic broadcast notification
*/
export function createTopicNotification(params: {
id: string;
title: string;
body: string;
data: ArticlePublishedData;
topic: TopicTarget["topic"];
priority?: "normal" | "high";
ttl?: number;
}): PushNotification {
return {
body: params.body,
data: params.data,
id: params.id,
priority: params.priority,
target: {
topic: params.topic,
type: "topic",
},
timestamp: Date.now(),
title: params.title,
ttl: params.ttl,
};
}
// ============================================
// TYPE GUARDS
// ============================================
export function isIndividualTarget(target: NotificationTarget): target is IndividualTarget {
return target.type === "individual";
}
export function isTopicTarget(target: NotificationTarget): target is TopicTarget {
return target.type === "topic";
}
export function isLivestreamNotification(data: NotificationData): data is LivestreamStartedData {
return data.notificationType === "PORTFOLIO_LIVESTREAM_STARTED";
}
export function isArticleNotification(data: NotificationData): data is ArticlePublishedData {
return data.notificationType === "ARTICLE_PUBLISHED";
}