Overview
The Flip.is backend is built with Node.js and WebSocket technology to provide real-time gaming updates. It integrates with MongoDB for data persistence and interfaces directly with the Solana blockchain.
Core Components
1. WebSocket Server
The WebSocket server handles real-time game state updates, player connections, and event broadcasting.
Copy export const server = new WebSocket.Server({ port: 8881 });
interface Client {
ws: WebSocket;
}
let clients: Client[] = [];
2. Database Models
Game Schema
Copy const GameSchema = new mongoose.Schema({
unit: { type: String, require: true },
mint: { type: String, require: true },
decimal: { type: String, require: true },
amount: { type: String, require: true },
creator: { type: String, require: true },
selection: { type: Boolean, require: true },
opposite: { type: String, default: "" },
gamePDA: { type: String, default: "", unique: true },
finished: { type: Boolean, default: false },
readyToPlay: { type: Boolean, default: false },
createdAt: { type: Number },
result: { type: Boolean, require: true },
index: { type: Number, default: 0 }
});
Message Schema
Copy const MessageSchema = new mongoose.Schema({
message: { type: String, require: true },
wallet: { type: String, require: true },
createdAt: { type: Number }
});
3. Token Management
The system supports multiple tokens with specific configurations:
Copy const token_list = [
{
name: "Solana",
unit: "SOL",
selected: true,
mint: "So11111111111111111111111111111111111111112",
decimal: 9
},
{
name: "Solana USDT",
unit: "USDT",
selected: false,
mint: "Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB",
decimal: 6
},
{
name: "Solana USDC",
unit: "USDC",
selected: false,
mint: "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v",
decimal: 6
},
{
name: "BONK Coin",
unit: "BONK",
selected: false,
mint: "DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263",
decimal: 5
}
];
4. Game Management
Game Creation Process
Copy const createGame = async (selection: boolean, creatorPubkey: String, mint: String, amount: number, decimal: number, isSol: boolean, index: number) => {
const global = PublicKey.findProgramAddressSync([Buffer.from(GLOBAL_VAULT_SEED)], COINFLIP)[0];
const newGame = PublicKey.findProgramAddressSync([Buffer.from(GAME_VAULT_SEED), creator.toBuffer(), Buffer.from(index.toString())], COINFLIP)[0];
// Game creation logic
};
Game Joining Process
Copy const joinGame = async (opposite: String, creator_key: String, mint: String, index: number) => {
const global = PublicKey.findProgramAddressSync([Buffer.from(GLOBAL_VAULT_SEED)], COINFLIP)[0];
const coinFlipGame = PublicKey.findProgramAddressSync([Buffer.from(GAME_VAULT_SEED), creator.toBuffer(), Buffer.from(index.toString())], COINFLIP)[0];
// Game joining logic
};
5. Safety Systems
Expired Game Handler
Copy const expireGame = async () => {
const fiveMinutesAgo = Math.floor(Date.now() / 1000) - 5 * 60;
let result = await GameModel.findOneAndDelete({
finished: false,
opposite: "",
createdAt: { $lt: fiveMinutesAgo }
});
if (result) {
// Process refunds and cleanup
}
};
Balance Verification
Copy export const checkBalance = async (isSol: boolean, mint: String, amount: number, address: string) => {
if (isSol) {
const balance = await solConnection.getBalance(new PublicKey(address));
return balance > amount;
} else {
const ataAddress = await getAssociatedTokenAddress(new PublicKey(mint), new PublicKey(address));
const tokenAccount = await getAccount(solConnection, ataAddress);
return tokenAccount.amount >= amount;
}
};
6. Event System
Event Listeners
Copy const listenInitGameEvent = program.addEventListener("InitEvent", async (event, slot, signature) => {
const sigstatus = await connection.getSignatureStatus(signature);
if (sigstatus.value?.confirmationStatus === 'finalized') {
// Handle game initialization
}
});
const joiningListener = program.addEventListener("JoinEvent", async (event, slot, signature) => {
if (sigstatus.value?.confirmationStatus === 'finalized') {
// Handle game joining
}
});
const gameResultListener = program.addEventListener("HandleEvent", async (event, slot, signature) => {
if (sigstatus.value?.confirmationStatus === 'finalized') {
// Handle game results
}
});
7. Message System
Message Handling
Copy export const handleMessage = async (ws: WebSocket, message: string) => {
const data = JSON.parse(message);
switch (data.type) {
case "CREATE_ROOM":
// Handle room creation
break;
case "JOIN_ROOM":
// Handle room joining
break;
case "MESSAGE":
// Handle chat messages
break;
// Other message types
}
};
8. System Maintenance
Message Cleanup
Copy const expireMessage = async () => {
const twoDaysAgo = Math.floor(Date.now() / 1000) - 60 * 60 * 24 * 5;
await MessageModel.deleteMany({
createdAt: { $lt: twoDaysAgo }
});
};
Periodic Maintenance
Copy const filpsBot = async () => {
await expireGame();
await saveMessage();
await expireMessage();
};
setInterval(filpsBot, 10000);
Environment Configuration
Copy export const MONGO_URL = `mongodb+srv://${process.env.DB_USERNAME}:${process.env.DB_PASSWORD}@${process.env.DB_HOST}/${process.env.DB_NAME}`;
export const PORT = process.env.PORT || 9000;
Conclusion
The backend provides a secure and scalable foundation for the Flip.is platform, featuring:
Real-time WebSocket communication
Robust database management
Comprehensive token support
Regular maintenance routines
For system updates or issues, please contact the development team.
Last updated 2 months ago