Documentation Index Fetch the complete documentation index at: https://mintlify.com/peLuis123/crypto-shop-backend/llms.txt
Use this file to discover all available pages before exploring further.
This guide explains how to integrate Socket.io to receive real-time notifications when cryptocurrency transactions are confirmed.
Overview
The Crypto Shop Backend uses Socket.io to push real-time notifications to clients when:
TRX payment transactions are confirmed on the blockchain
Order status changes from “pending” to “completed”
Product stock is updated
Socket.io Server Configuration
From src/config/socket.js:5, the server is configured with CORS support:
import { Server } from 'socket.io' ;
let io ;
export const initializeSocket = ( server ) => {
io = new Server ( server , {
cors: {
origin: [ 'http://localhost:3000' , 'http://localhost:5173' , process . env . FRONTEND_URL ],
credentials: true ,
methods: [ 'GET' , 'POST' ]
}
});
io . on ( 'connection' , ( socket ) => {
console . log ( `[Socket] User connected: ${ socket . id } ` );
socket . on ( 'join-user' , ( userId ) => {
socket . join ( `user: ${ userId } ` );
console . log ( `[Socket] User ${ userId } joined room user: ${ userId } ` );
});
socket . on ( 'disconnect' , () => {
console . log ( `[Socket] User disconnected: ${ socket . id } ` );
});
});
return io ;
};
Connection Flow
User Connects
Client establishes WebSocket connection to the server.
Join User Room
Client emits join-user event with their user ID to join a private room.
Wait for Events
Client listens for transaction:confirmed events.
Receive Notification
When a transaction is confirmed, server emits event to the user’s room.
Client Setup
Installation
Install the Socket.io client library:
npm install socket.io-client
Basic Connection
import { io } from 'socket.io-client' ;
// Connect to the server
const socket = io ( 'http://localhost:3000' , {
withCredentials: true ,
transports: [ 'websocket' , 'polling' ]
});
// Wait for connection
socket . on ( 'connect' , () => {
console . log ( 'Connected to server:' , socket . id );
// Join your user room
const userId = '507f1f77bcf86cd799439010' ; // Your user ID
socket . emit ( 'join-user' , userId );
console . log ( 'Joined user room:' , userId );
});
// Listen for transaction confirmations
socket . on ( 'transaction:confirmed' , ( data ) => {
console . log ( 'Transaction confirmed!' , data );
// data contains:
// - orderId: The order that was confirmed
// - txHash: Transaction hash on blockchain
// - message: Confirmation message
// - timestamp: When it was confirmed
});
// Handle disconnection
socket . on ( 'disconnect' , () => {
console . log ( 'Disconnected from server' );
});
Transaction Confirmation Event
From src/config/socket.js:37, when a transaction is confirmed:
export const emitTransactionConfirmed = ( userId , orderId , txHash ) => {
const io = getIO ();
io . to ( `user: ${ userId } ` ). emit ( 'transaction:confirmed' , {
orderId ,
txHash ,
message: 'Your purchase has been confirmed. You can now place new orders.' ,
timestamp: new Date ()
});
};
Event Data Structure
{
"orderId" : "507f1f77bcf86cd799439013" ,
"txHash" : "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0" ,
"message" : "Your purchase has been confirmed. You can now place new orders." ,
"timestamp" : "2024-01-20T14:35:22.123Z"
}
Complete Integration Example
React Hook
Vue Composition API
import { useEffect , useState } from 'react' ;
import { io } from 'socket.io-client' ;
export function useTransactionNotifications ( userId ) {
const [ socket , setSocket ] = useState ( null );
const [ notifications , setNotifications ] = useState ([]);
useEffect (() => {
// Create socket connection
const newSocket = io ( 'http://localhost:3000' , {
withCredentials: true ,
transports: [ 'websocket' , 'polling' ]
});
newSocket . on ( 'connect' , () => {
console . log ( 'Socket connected' );
newSocket . emit ( 'join-user' , userId );
});
newSocket . on ( 'transaction:confirmed' , ( data ) => {
console . log ( 'Transaction confirmed:' , data );
// Add to notifications
setNotifications ( prev => [ ... prev , data ]);
// Show browser notification
if ( 'Notification' in window && Notification . permission === 'granted' ) {
new Notification ( 'Payment Confirmed' , {
body: data . message ,
icon: '/icon.png'
});
}
// Play sound
const audio = new Audio ( '/notification.mp3' );
audio . play ();
});
newSocket . on ( 'disconnect' , () => {
console . log ( 'Socket disconnected' );
});
setSocket ( newSocket );
// Cleanup
return () => {
newSocket . disconnect ();
};
}, [ userId ]);
return { socket , notifications };
}
// Usage in component
function App () {
const userId = '507f1f77bcf86cd799439010' ;
const { notifications } = useTransactionNotifications ( userId );
return (
< div >
< h2 > Notifications </ h2 >
{ notifications . map (( notif , index ) => (
< div key = { index } >
Order { notif . orderId } confirmed!
< br />
TX: { notif . txHash }
</ div >
));
</ div >
);
}
When Notifications are Sent
From src/services/transactionListener.js:72, notifications are sent when:
A pending transaction receives 21 confirmations on the blockchain
The transaction type is “purchase”
The order status is “pending”
if ( status && status . confirmed ) {
// Update transaction status
transaction . status = 'confirmed' ;
transaction . confirmations = CONFIRMATIONS_REQUIRED ;
await transaction . save ();
if ( transaction . orderId ) {
const order = await Order . findById ( transaction . orderId );
if ( order ) {
if ( transaction . type === 'purchase' && order . status === 'pending' ) {
order . status = 'completed' ;
await order . save ();
// Reduce stock
for ( const item of order . products ) {
await Product . findByIdAndUpdate (
item . productId ,
{ $inc: { stock: - item . quantity } }
);
}
// Send notification
emitTransactionConfirmed (
transaction . userId . toString (),
transaction . orderId . toString (),
transaction . transactionHash
);
}
}
}
}
Room-based Messaging
The system uses room-based messaging to ensure users only receive their own notifications:
Each user joins a private room: user:{userId}
Notifications are emitted only to the specific user’s room
Multiple clients can connect with the same user ID and all will receive notifications
Error Handling
Connection Error Handling
import { io } from 'socket.io-client' ;
const socket = io ( 'http://localhost:3000' , {
withCredentials: true ,
transports: [ 'websocket' , 'polling' ],
reconnection: true ,
reconnectionDelay: 1000 ,
reconnectionAttempts: 5
});
socket . on ( 'connect' , () => {
console . log ( 'Connected successfully' );
});
socket . on ( 'connect_error' , ( error ) => {
console . error ( 'Connection error:' , error . message );
});
socket . on ( 'disconnect' , ( reason ) => {
console . log ( 'Disconnected:' , reason );
if ( reason === 'io server disconnect' ) {
// Server disconnected, reconnect manually
socket . connect ();
}
});
socket . on ( 'reconnect' , ( attemptNumber ) => {
console . log ( 'Reconnected after' , attemptNumber , 'attempts' );
// Re-join user room
const userId = '507f1f77bcf86cd799439010' ;
socket . emit ( 'join-user' , userId );
});
socket . on ( 'reconnect_error' , ( error ) => {
console . error ( 'Reconnection error:' , error );
});
socket . on ( 'reconnect_failed' , () => {
console . error ( 'Reconnection failed after maximum attempts' );
});
Browser Notifications
Request permission and show browser notifications:
// Request notification permission
async function requestNotificationPermission () {
if ( 'Notification' in window ) {
const permission = await Notification . requestPermission ();
return permission === 'granted' ;
}
return false ;
}
// Setup socket with browser notifications
async function setupNotifications ( userId ) {
const hasPermission = await requestNotificationPermission ();
const socket = io ( 'http://localhost:3000' , {
withCredentials: true
});
socket . on ( 'connect' , () => {
socket . emit ( 'join-user' , userId );
});
socket . on ( 'transaction:confirmed' , ( data ) => {
console . log ( 'Transaction confirmed:' , data );
if ( hasPermission ) {
const notification = new Notification ( 'Payment Confirmed' , {
body: `Order ${ data . orderId } has been confirmed!` ,
icon: '/icon.png' ,
badge: '/badge.png' ,
tag: data . orderId ,
requireInteraction: false
});
notification . onclick = () => {
window . focus ();
window . location . href = `/orders/ ${ data . orderId } ` ;
};
}
});
return socket ;
}
Testing Notifications
To test the notification system:
Connect Socket.io
Connect your client and join your user room.
Wait for Confirmation
The transaction listener checks every 15 seconds. You should receive a notification when the transaction is confirmed (21 confirmations on TRON blockchain).
Socket.io Events Reference
Client → Server
Server → Client
Built-in Events
join-user Join a user-specific room to receive notifications. socket . emit ( 'join-user' , userId );
Parameters:
userId (string): The user’s MongoDB ObjectId
transaction:confirmed Sent when a transaction is confirmed on the blockchain. socket . on ( 'transaction:confirmed' , ( data ) => {
// Handle confirmation
});
Payload: {
"orderId" : "string" ,
"txHash" : "string" ,
"message" : "string" ,
"timestamp" : "Date"
}
connect Fired when connection is established. disconnect Fired when connection is lost. connect_error Fired when connection fails. reconnect Fired when reconnection succeeds.
Production Considerations
For production deployments:
Use secure WebSocket connections (wss://)
Set secure: true in CORS configuration
Add rate limiting for socket events
Implement authentication middleware for socket connections
Use Redis adapter for horizontal scaling
Monitor socket connections and events
Next Steps
Payment Processing Understand how payments trigger notifications
Creating Orders Learn how to create orders that can be paid