@pump-fun/shared-contracts v0.2.2
@pump-fun/shared-contracts
Shared contracts and type definitions for the Pump.fun notification system microservices.
Installation
bun add @pump-fun/shared-contractsNATS Subjects
The package exports NATS subject constants organized by service domain:
Trade Subjects
import { TRADE_SUBJECTS } from "@pump-fun/shared-contracts/events";
// Subscribe to all unified trades
nats.subscribe(TRADE_SUBJECTS.UNIFIED_TRADE);Watcher Service Subjects
import {
TRENDING_SUBJECTS,
WATCHLIST_SUBJECTS,
PORTFOLIO_SUBJECTS,
MILESTONE_SUBJECTS
} from "@pump-fun/shared-contracts/events";
// Subscribe to trending events
nats.subscribe(TRENDING_SUBJECTS.EVENT);
// Subscribe to watchlist alerts
nats.subscribe(WATCHLIST_SUBJECTS.ALERT);
// Subscribe to portfolio alerts
nats.subscribe(PORTFOLIO_SUBJECTS.ALERT);
// Subscribe to milestone events
nats.subscribe(MILESTONE_SUBJECTS.EVENT);Notification Processor Subjects
import { NOTIFICATION_SUBJECTS } from "@pump-fun/shared-contracts/events";
// Subscribe to all notification events
nats.subscribe(NOTIFICATION_SUBJECTS.ALL);
// Publish processed notification
nats.publish(NOTIFICATION_SUBJECTS.PROCESSED, notification);Gateway Subjects
import {
EMAIL_GATEWAY_SUBJECTS,
FCM_GATEWAY_SUBJECTS
} from "@pump-fun/shared-contracts/events";
// Send email command
nats.publish(EMAIL_GATEWAY_SUBJECTS.SEND, emailCommand);
// Send push notification
nats.publish(FCM_GATEWAY_SUBJECTS.SEND, pushCommand);Message Types
All message types are defined using Zod schemas for runtime validation:
Trade Messages
import { UnifiedTradeSchema, type UnifiedTrade } from "@pump-fun/shared-contracts/events";
// Validate incoming trade
const trade = UnifiedTradeSchema.parse(message.data);
// Type-safe trade object
const processTrade = (trade: UnifiedTrade) => {
console.log(`${trade.type} trade: ${trade.amountUsd} USD for ${trade.mintAddress}`);
};Alert Messages
import {
TrendingEventSchema,
WatchlistAlertSchema,
PortfolioAlertSchema,
MilestoneEventSchema
} from "@pump-fun/shared-contracts/events";
// Parse and validate alerts
const trendingEvent = TrendingEventSchema.parse(data);
const watchlistAlert = WatchlistAlertSchema.parse(data);
const portfolioAlert = PortfolioAlertSchema.parse(data);
const milestoneEvent = MilestoneEventSchema.parse(data);Notification Messages
import {
ProcessedNotificationSchema,
NotificationDeliveryStatusSchema
} from "@pump-fun/shared-contracts/events";
// Create a processed notification
const notification = ProcessedNotificationSchema.parse({
notificationId: "123",
userId: "user-456",
type: "watchlist_alert",
title: "Price Alert",
body: "BONK reached your target price",
channels: ["push", "email"],
priority: "high",
data: { tokenMint: "...", price: 0.001 },
createdAt: Date.now()
});Utility Functions
Message Envelopes
import { createMessageEnvelope } from "@pump-fun/shared-contracts/events";
// Wrap data in a message envelope with headers
const envelope = createMessageEnvelope(
{ type: "buy", amount: 1000 },
{
correlationId: "req-123",
userId: "user-456",
source: "watchlist-watcher"
}
);Subject Matching
import { subjectMatches } from "@pump-fun/shared-contracts/events";
// Check if a subject matches a pattern
subjectMatches("trade.unified", "trade.*"); // true
subjectMatches("notification.push", "notification.>"); // true
subjectMatches("trending.event", "watchlist.*"); // falseSubject Builder
import { SubjectBuilder } from "@pump-fun/shared-contracts/events";
// Build subjects dynamically
const subject = SubjectBuilder
.create("notification")
.add("user")
.add(userId)
.add("push")
.build(); // "notification.user.123.push"Error Handling
import { NatsError } from "@pump-fun/shared-contracts/events";
try {
await nats.publish(subject, data);
} catch (error) {
throw new NatsError(
"PUBLISH_FAILED",
`Failed to publish to ${subject}`,
error
);
}Core NATS Usage
This system uses core NATS (not JetStream), so subscriptions are simple:
import { UNIFIED_TRADE_SUBJECTS } from "@pump-fun/shared-contracts/events";
import { connect } from "nats";
// Connect to NATS
const nc = await connect({ servers: ["nats://localhost:4222"] });
// Simple subscription
const sub = nc.subscribe(UNIFIED_TRADE_SUBJECTS.ALL);
// Process messages
(async () => {
for await (const msg of sub) {
try {
const tradeData = JSON.parse(msg.data.toString());
// Validate with schema
const trade = UnifiedTradeSchema.parse(tradeData);
console.log(`Processing ${trade.type} trade:`, {
mintAddress: trade.mintAddress,
amountUsd: trade.amountUsd,
tx: trade.tx
});
await processTrade(trade);
} catch (error) {
console.error("Failed to process trade:", error);
}
}
})();Complete Example
import {
WATCHLIST_SUBJECTS,
WatchlistAlertSchema,
createMessageEnvelope,
NatsError
} from "@pump-fun/shared-contracts/events";
import { connect } from "nats";
// Connect to NATS
const nc = await connect({ servers: ["nats://localhost:4222"] });
// Subscribe to watchlist alerts
const sub = nc.subscribe(WATCHLIST_SUBJECTS.ALERT);
(async () => {
for await (const msg of sub) {
try {
// Parse and validate the alert
const alert = WatchlistAlertSchema.parse(
JSON.parse(msg.data.toString())
);
console.log(`Alert for ${alert.userId}: ${alert.message}`);
// Process the message (no ack needed in core NATS)
console.log(`Processed alert for ${alert.userId}: ${alert.message}`);
} catch (error) {
console.error("Failed to process alert:", error);
}
}
})();
// Publish a watchlist alert
const alert = {
userId: "user-123",
tokenMint: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
symbol: "BONK",
alertType: "price_above" as const,
threshold: 0.001,
currentValue: 0.0012,
message: "BONK price exceeded $0.001",
timestamp: Date.now()
};
try {
const envelope = createMessageEnvelope(alert, {
source: "watchlist-watcher",
userId: alert.userId
});
await nc.publish(
WATCHLIST_SUBJECTS.ALERT,
JSON.stringify(envelope)
);
} catch (error) {
throw new NatsError(
"PUBLISH_FAILED",
"Failed to publish watchlist alert",
error as Error
);
}Type Exports
The package exports all TypeScript types for the schemas:
export type UnifiedTrade = z.infer<typeof UnifiedTradeSchema>;
export type TrendingEvent = z.infer<typeof TrendingEventSchema>;
export type WatchlistAlert = z.infer<typeof WatchlistAlertSchema>;
export type PortfolioAlert = z.infer<typeof PortfolioAlertSchema>;
export type MilestoneEvent = z.infer<typeof MilestoneEventSchema>;
export type ProcessedNotification = z.infer<typeof ProcessedNotificationSchema>;
export type NotificationDeliveryStatus = z.infer<typeof NotificationDeliveryStatusSchema>;
export type EmailSendCommand = z.infer<typeof EmailSendCommandSchema>;
export type PushSendCommand = z.infer<typeof PushSendCommandSchema>;
export type HealthCheckRequest = z.infer<typeof HealthCheckRequestSchema>;
export type HealthCheckResponse = z.infer<typeof HealthCheckResponseSchema>;
export type SystemError = z.infer<typeof SystemErrorSchema>;
export type UserPreferences = z.infer<typeof UserPreferencesSchema>;
export type DeviceRegistration = z.infer<typeof DeviceRegistrationSchema>;Shared Contracts
This package contains shared API contracts and types for Pump.fun services.
For Mobile App Developers
What to Import
The notification API exports its router type which you can use to create a fully typed client:
import type { Router } from "@pump-fun/notification-api";Setting Up the Client
You have two options for consuming the notification API:
Option 1: Using RPC Endpoint (Recommended for oRPC clients)
import { createORPCClient } from "@orpc/client";
import { RPCLink } from "@orpc/client/fetch";
import type { RouterClient } from "@orpc/server";
import type { Router } from "@pump-fun/notification-api";
function createNotificationApiClient(config: {
baseUrl: string;
getAuthToken: () => string | null;
}): RouterClient<Router> {
return createORPCClient(
new RPCLink({
url: `${config.baseUrl}/rpc`,
headers: () => {
const token = config.getAuthToken();
return token ? { Authorization: `Bearer ${token}` } : {};
},
}),
);
}Option 2: Using OpenAPI/REST Endpoints
If you prefer REST semantics or are not using oRPC:
// Direct REST calls
const response = await fetch("https://api.pump.fun/api/mobile/users/me/pnl-tracking", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${token}`,
},
body: JSON.stringify({
deviceInfo: {
appVersion: "1.0.0",
deviceId: "device-123",
platform: "ios",
},
}),
});Available Endpoints
The notification API provides:
Mobile User P&L Tracking
POST /api/mobile/users/me/pnl-tracking- Setup 7-day P&L trackingGET /api/mobile/users/me/pnl-tracking-status- Check tracking status
Authentication Demo (for testing)
POST /api/auth/generate-token- Generate test JWT tokensGET /api/auth/profile- Get authenticated user profileGET /api/public/info- Public endpoint (no auth required)
Health Check
GET /api/health- Check API health status
Notification Settings
- Various endpoints for managing notification preferences
Authentication
All endpoints except /api/health and /api/public/* require JWT authentication:
headers: {
Authorization: `Bearer ${yourJwtToken}`,
}OpenAPI Documentation
The full OpenAPI specification is available at:
- JSON:
https://api.pump.fun/api/openapi.json - Interactive UI:
https://api.pump.fun/api/reference
Contract-First Development
This package also contains contract definitions that can be imported for type safety:
import { mobileUserContract } from "@pump-fun/shared-contracts/api-contracts";These contracts define the API specification and can be used to ensure client-server compatibility.
5 months ago