
Research
Malicious npm Packages Impersonate Flashbots SDKs, Targeting Ethereum Wallet Credentials
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
@oxyhq/services
Advanced tools
Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀
A comprehensive TypeScript client library for the Oxy API providing authentication, user management, and UI components for React Native, Expo, and Node.js applications.
npm install @oxyhq/services
To avoid duplicate native modules and ensure smooth integration across apps, install (or ensure your app already includes) the following peer dependencies:
Example for Expo:
npm i react-native-reanimated react-native-gesture-handler react-native-safe-area-context react-native-svg \
expo expo-font expo-image expo-linear-gradient @react-navigation/native
For React Native and Expo projects, add the polyfill import at the very top of your entry file:
// index.js or App.js (very first line)
import 'react-native-url-polyfill/auto';
Note: This polyfill is already included in the package dependencies, but you need to import it to activate it.
import { OxyProvider, useOxy } from '@oxyhq/services';
function App() {
return (
<OxyProvider baseURL="https://api.oxy.so">
<YourApp />
</OxyProvider>
);
}
function UserProfile() {
const { oxyServices, user, isAuthenticated } = useOxy();
if (!isAuthenticated) {
return <Text>Please sign in</Text>;
}
return <Text>Welcome, {user?.name}!</Text>;
}
// Prefer the core-only entry on the backend
import { oxyClient, OxyServices } from '@oxyhq/services/core';
// Quick Express example
import express from 'express';
const app = express();
app.use(express.json());
// Optional: create your own client (e.g., different baseURL per env)
const services = new OxyServices({ baseURL: process.env.OXY_CLOUD_URL || 'https://api.oxy.so' });
app.post('/api/auth/login', async (req, res) => {
try {
const { username, password } = req.body;
const session = await oxyClient.signIn(username, password);
res.json(session);
} catch (err: any) {
res.status(401).json({ error: err.message });
}
});
app.get('/api/users/:id', async (req, res) => {
try {
const user = await services.getUserById(req.params.id);
res.json(user);
} catch (err: any) {
res.status(404).json({ error: err.message });
}
});
app.listen(3000);
This pattern provides full React Native integration with automatic state management, UI components, and authentication flow.
import { OxyProvider, useOxy } from '@oxyhq/services';
// App.tsx - Setup the provider
function App() {
return (
<OxyProvider
baseURL="https://api.oxy.so"
onAuthStateChange={(user) => {
console.log('Auth state changed:', user ? 'logged in' : 'logged out');
}}
>
<YourApp />
</OxyProvider>
);
}
// Component.tsx - Use the hook
function UserProfile() {
const {
oxyServices, // OxyServices instance
user, // Current user data
isAuthenticated, // Authentication state
login, // Login method
logout, // Logout method
showBottomSheet // UI methods
} = useOxy();
const handleLogin = async () => {
try {
await login('username', 'password');
} catch (error) {
console.error('Login failed:', error);
}
};
const openSignIn = () => {
showBottomSheet('SignIn');
};
return (
<View>
{isAuthenticated ? (
<View>
<Text style={styles.title}>Welcome, {user?.name}!</Text>
<TouchableOpacity onPress={logout} style={styles.button}>
<Text>Sign Out</Text>
</TouchableOpacity>
</View>
) : (
<TouchableOpacity onPress={openSignIn} style={styles.button}>
<Text>Sign In</Text>
</TouchableOpacity>
)}
</View>
);
}
For utility functions, services, or non-React Native files:
import { oxyClient } from '@oxyhq/services';
// utils/api.ts
export const userUtils = {
async fetchUserById(userId: string) {
return await oxyClient.getUserById(userId);
},
async fetchProfileByUsername(username: string) {
return await oxyClient.getProfileByUsername(username);
},
async updateUserProfile(updates: any) {
return await oxyClient.updateProfile(updates);
}
};
Use the pre-configured oxyClient
for immediate access:
import { oxyClient } from '@oxyhq/services/core';
// routes/auth.ts
export const signIn = async (req, res) => {
try {
const { username, password } = req.body;
const response = await oxyClient.signIn(username, password);
res.json(response);
} catch (error) {
res.status(401).json({ error: error.message });
}
};
// routes/users.ts
export const getUserProfile = async (req, res) => {
try {
const { userId } = req.params;
const user = await oxyClient.getUserById(userId);
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
// routes/profiles.ts
export const getProfileByUsername = async (req, res) => {
try {
const { username } = req.params;
const profile = await oxyClient.getProfileByUsername(username);
res.json(profile);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
// routes/social.ts
export const getFollowers = async (req, res) => {
try {
const { userId } = req.params;
const followers = await oxyClient.getUserFollowers(userId);
res.json(followers);
} catch (error) {
res.status(500).json({ error: error.message });
}
};
Create your own instance with custom settings:
import { OxyServices, OXY_CLOUD_URL } from '@oxyhq/services';
const oxy = new OxyServices({
baseURL: process.env.OXY_API_URL || OXY_CLOUD_URL
});
export { oxy };
You can use both patterns in the same application:
// App.tsx - React Native setup
import { OxyProvider } from '@oxyhq/services';
function App() {
return (
<OxyProvider baseURL="https://cloud.oxy.so">
<YourApp />
</OxyProvider>
);
}
// utils/api.ts - Direct import
import { oxyClient } from '@oxyhq/services';
export const apiUtils = {
async fetchData() {
return await oxyClient.getCurrentUser();
}
};
// Component.tsx - React Native hook
import { useOxy } from '@oxyhq/services';
function Component() {
const { oxyServices } = useOxy();
// Both oxyServices and oxyClient share the same tokens!
}
import {
OxyServices, // Main service class
oxyClient, // Pre-configured instance
OXY_CLOUD_URL, // Default API URL
OxyAuthenticationError,
OxyAuthenticationTimeoutError
} from '@oxyhq/services';
import {
OxyProvider, // Context provider
useOxy, // React Native hook
OxySignInButton, // UI components
Avatar,
FollowButton
} from '@oxyhq/services';
// Authentication
await oxyClient.signIn(username, password);
await oxyClient.signUp(username, email, password);
await oxyClient.logout();
// User Management
const user = await oxyClient.getCurrentUser(); // Get current user
const userById = await oxyClient.getUserById('user123'); // Get user by ID
const profileByUsername = await oxyClient.getProfileByUsername('john_doe'); // Get profile by username
await oxyClient.updateProfile({ name: 'John Doe' }); // Update current user
await oxyClient.updateUser('user123', { name: 'John' }); // Update user by ID (admin)
// Session Management
const userBySession = await oxyClient.getUserBySession('session123'); // Get user by session
const sessions = await oxyClient.getSessionsBySessionId('session123'); // Get all sessions
await oxyClient.logoutSession('session123'); // Logout specific session
await oxyClient.logoutAllSessions('session123'); // Logout all sessions
// Social Features
await oxyClient.followUser('user123'); // Follow user
await oxyClient.unfollowUser('user123'); // Unfollow user
const followStatus = await oxyClient.getFollowStatus('user123'); // Check follow status
const followers = await oxyClient.getUserFollowers('user123'); // Get user followers
const following = await oxyClient.getUserFollowing('user123'); // Get user following
// Notifications
const notifications = await oxyClient.getNotifications(); // Get notifications
const unreadCount = await oxyClient.getUnreadCount(); // Get unread count
await oxyClient.markNotificationAsRead('notification123'); // Mark as read
await oxyClient.markAllNotificationsAsRead(); // Mark all as read
await oxyClient.deleteNotification('notification123'); // Delete notification
// File Management
const fileData = await oxyClient.uploadFile(file); // Upload file
const file = await oxyClient.getFile('file123'); // Get file info
await oxyClient.deleteFile('file123'); // Delete file
const downloadUrl = oxyClient.getFileDownloadUrl('file123'); // Get download URL
const streamUrl = oxyClient.getFileStreamUrl('file123'); // Get stream URL
const userFiles = await oxyClient.listUserFiles('user123'); // List user files
// Payments
const payment = await oxyClient.createPayment(paymentData); // Create payment
const paymentInfo = await oxyClient.getPayment('payment123'); // Get payment info
const userPayments = await oxyClient.getUserPayments(); // Get user payments
// Karma System
const karma = await oxyClient.getUserKarma('user123'); // Get user karma
await oxyClient.giveKarma('user123', 10, 'helpful comment'); // Give karma
const karmaTotal = await oxyClient.getUserKarmaTotal('user123'); // Get karma total
const karmaHistory = await oxyClient.getUserKarmaHistory('user123'); // Get karma history
const leaderboard = await oxyClient.getKarmaLeaderboard(); // Get leaderboard
const rules = await oxyClient.getKarmaRules(); // Get karma rules
// Location Services
await oxyClient.updateLocation(40.7128, -74.0060); // Update location
const nearby = await oxyClient.getNearbyUsers(1000); // Get nearby users
// Analytics
await oxyClient.trackEvent('user_action', { action: 'click' }); // Track event
const analytics = await oxyClient.getAnalytics('2024-01-01', '2024-01-31'); // Get analytics
// Device Management
await oxyClient.registerDevice(deviceData); // Register device
const devices = await oxyClient.getUserDevices(); // Get user devices
await oxyClient.removeDevice('device123'); // Remove device
const deviceSessions = await oxyClient.getDeviceSessions('session123'); // Get device sessions
await oxyClient.logoutAllDeviceSessions('session123'); // Logout device sessions
await oxyClient.updateDeviceName('session123', 'iPhone 15'); // Update device name
// Utilities
const metadata = await oxyClient.fetchLinkMetadata('https://example.com'); // Fetch link metadata
const {
// Service instance
oxyServices,
// Authentication state
user,
isAuthenticated,
isLoading,
error,
// Authentication methods
login,
logout,
signUp,
// Session management
sessions,
activeSessionId,
switchSession,
removeSession,
// UI methods
showBottomSheet,
hideBottomSheet
} = useOxy();
<OxyProvider
baseURL="https://api.oxy.so" // API base URL
storageKeyPrefix="oxy_session" // Storage key prefix
onAuthStateChange={(user) => {}} // Auth state callback
onError={(error) => {}} // Error callback
bottomSheetRef={bottomSheetRef} // Bottom sheet ref
>
{children}
</OxyProvider>
# .env
OXY_API_URL=https://cloud.oxy.so
NODE_ENV=production
import { OxyServices } from '@oxyhq/services';
const oxy = new OxyServices({
baseURL: process.env.OXY_API_URL || 'https://cloud.oxy.so'
});
The library handles authentication automatically:
import { oxyClient } from '@oxyhq/services';
// Set tokens manually
oxyClient.setTokens(accessToken, refreshToken);
// Clear tokens
oxyClient.clearTokens();
// Check authentication
const isAuthenticated = oxyClient.hasValidToken();
import {
OxySignInButton,
Avatar,
FollowButton,
OxyLogo
} from '@oxyhq/services';
function MyComponent() {
return (
<View style={styles.container}>
<OxyLogo />
<Avatar userId="user123" size={40} />
<FollowButton userId="user123" />
<OxySignInButton />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
},
});
import { useOxy } from '@oxyhq/services';
function MyComponent() {
const { showBottomSheet } = useOxy();
const openSignIn = () => {
showBottomSheet('SignIn');
};
const openProfile = () => {
showBottomSheet('Profile');
};
return (
<View style={styles.container}>
<TouchableOpacity onPress={openSignIn} style={styles.button}>
<Text>Sign In</Text>
</TouchableOpacity>
<TouchableOpacity onPress={openProfile} style={styles.button}>
<Text>Profile</Text>
</TouchableOpacity>
</View>
);
}
Solution: Wrap your app with OxyProvider
import { OxyProvider } from '@oxyhq/services';
function App() {
return (
<OxyProvider baseURL="https://cloud.oxy.so">
<YourApp />
</OxyProvider>
);
}
Solution: Add polyfill import at the very top of your entry file
// index.js or App.js (very first line)
import 'react-native-url-polyfill/auto';
Why needed: Your app uses file uploads which require FormData
. React Native with Hermes engine doesn't include FormData
natively, so it needs to be polyfilled.
Solution: Check storage configuration
<OxyProvider
baseURL="https://api.oxy.so"
storageKeyPrefix="my_app_oxy" // Custom storage key
>
{children}
</OxyProvider>
import { OxyAuthenticationError } from '@oxyhq/services';
try {
await oxyClient.getCurrentUser();
} catch (error) {
if (error instanceof OxyAuthenticationError) {
// Handle authentication errors
console.log('Auth error:', error.message);
} else {
// Handle other errors
console.log('Other error:', error.message);
}
}
For React Native/Expo projects:
npm install axios jwt-decode invariant
Note: react-native-url-polyfill
is already included as a dependency in this package.
// App.tsx
import { OxyProvider } from '@oxyhq/services';
function App() {
return (
<OxyProvider baseURL="https://cloud.oxy.so">
<UserDashboard />
</OxyProvider>
);
}
// UserDashboard.tsx
import { useOxy } from '@oxyhq/services';
import { View, Text, StyleSheet } from 'react-native';
function UserDashboard() {
const { user, isAuthenticated, oxyServices } = useOxy();
const [followers, setFollowers] = useState([]);
useEffect(() => {
if (isAuthenticated && user) {
oxyServices.getUserFollowers(user.id).then(setFollowers);
}
}, [isAuthenticated, user]);
if (!isAuthenticated) {
return <Text>Please sign in</Text>;
}
return (
<View style={styles.container}>
<Text style={styles.title}>Welcome, {user?.name}!</Text>
<Text>Followers: {followers.length}</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
padding: 16,
justifyContent: 'center',
},
title: {
fontSize: 24,
fontWeight: 'bold',
marginBottom: 16,
},
});
// server.ts
import express from 'express';
import { oxyClient } from '@oxyhq/services';
const app = express();
app.use(express.json());
// Auth routes
app.post('/api/auth/signin', async (req, res) => {
try {
const { username, password } = req.body;
const response = await oxyClient.signIn(username, password);
res.json(response);
} catch (error) {
res.status(401).json({ error: error.message });
}
});
// User routes
app.get('/api/users/:userId', async (req, res) => {
try {
const { userId } = req.params;
const user = await oxyClient.getUserById(userId);
res.json(user);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
// Social routes
app.get('/api/users/:userId/followers', async (req, res) => {
try {
const { userId } = req.params;
const followers = await oxyClient.getUserFollowers(userId);
res.json(followers);
} catch (error) {
res.status(500).json({ error: error.message });
}
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
This project is licensed under the MIT License. See the LICENSE file for details.
FAQs
Reusable OxyHQ module to handle authentication, user management, karma system, device-based session management and more 🚀
The npm package @oxyhq/services receives a total of 726 weekly downloads. As such, @oxyhq/services popularity was classified as not popular.
We found that @oxyhq/services demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Four npm packages disguised as cryptographic tools steal developer credentials and send them to attacker-controlled Telegram infrastructure.
Security News
Ruby maintainers from Bundler and rbenv teams are building rv to bring Python uv's speed and unified tooling approach to Ruby development.
Security News
Following last week’s supply chain attack, Nx published findings on the GitHub Actions exploit and moved npm publishing to Trusted Publishers.