Created
May 30, 2025 17:00
-
-
Save Turupawn/b858c927ecfcbd1ad3fb5ada80ed731e to your computer and use it in GitHub Desktop.
wss real time backend
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require('dotenv').config(); | |
const express = require('express'); | |
const Web3 = require('web3'); | |
const app = express(); | |
const port = process.env.PORT || 3000; | |
// Initialize Web3 with WebSocket provider | |
const web3 = new Web3(new Web3.providers.WebsocketProvider(process.env.WSS_URL)); | |
const contractAddress = process.env.CONTRACT_ADDRESS; | |
const contractABI = require('../json_abi/MyContract.json'); | |
// Create contract instance | |
const contract = new web3.eth.Contract(contractABI, contractAddress); | |
// Create house wallet from private key | |
const houseAccount = web3.eth.accounts.privateKeyToAccount(process.env.HOUSE_PRIVATE_KEY); | |
web3.eth.accounts.wallet.add(houseAccount); | |
console.log('House wallet address:', houseAccount.address); | |
console.log('Server started on port', port); | |
// Keep track of processed games | |
const processingGameIds = new Set(); | |
// Function to generate random bytes32 hash | |
function generateRandomHash() { | |
return web3.utils.randomHex(32); | |
} | |
// Function to post hash for a player | |
async function postHashForPlayer(playerAddress, gameId) { | |
try { | |
if (processingGameIds.has(gameId)) { | |
console.log(`Already processing game ${gameId}, skipping`); | |
return; | |
} | |
processingGameIds.add(gameId); | |
console.log(`Started processing game ${gameId}`); | |
const gameState = await contract.methods.getGameState(playerAddress).call(); | |
if (gameState.gameState !== "1") { | |
console.log(`Game ${gameId} is no longer in committed state, skipping`); | |
processingGameIds.delete(gameId); | |
return; | |
} | |
const hash = generateRandomHash(); | |
const stakeAmount = await contract.methods.STAKE_AMOUNT().call(); | |
const tx = { | |
from: houseAccount.address, | |
to: contractAddress, | |
value: stakeAmount, | |
gas: 300000, | |
data: contract.methods.postHash(playerAddress, hash).encodeABI() | |
}; | |
const signedTx = await web3.eth.accounts.signTransaction(tx, houseAccount.privateKey); | |
const receipt = await web3.eth.sendSignedTransaction(signedTx.rawTransaction); | |
if (receipt.status) { | |
console.log(`Posted hash for game ${gameId} (player ${playerAddress}):`, { | |
hash: hash, | |
txHash: receipt.transactionHash | |
}); | |
} else { | |
console.error(`Transaction failed for game ${gameId}:`, receipt); | |
processingGameIds.delete(gameId); | |
} | |
} catch (error) { | |
console.error('Error posting hash:', error); | |
processingGameIds.delete(gameId); | |
} | |
} | |
// Set up WebSocket subscriptions | |
async function setupSubscriptions() { | |
try { | |
// Subscribe to GameCreated events | |
contract.events.GameCreated() | |
.on('data', async (event) => { | |
try { | |
const playerAddress = event.returnValues.player; | |
const gameId = event.returnValues.gameId; | |
console.log('New game created:', { player: playerAddress, gameId: gameId }); | |
await postHashForPlayer(playerAddress, gameId); | |
} catch (error) { | |
console.error('Error processing game created event:', error); | |
} | |
}) | |
.on('error', (error) => { | |
console.error('Error in GameCreated subscription:', error); | |
}); | |
// Subscribe to GameForfeited events | |
contract.events.GameForfeited() | |
.on('data', (event) => { | |
try { | |
const playerAddress = event.returnValues.player; | |
console.log('Game forfeited:', { player: playerAddress }); | |
processingGameIds.delete(playerAddress); | |
} catch (error) { | |
console.error('Error processing forfeit event:', error); | |
} | |
}) | |
.on('error', (error) => { | |
console.error('Error in GameForfeited subscription:', error); | |
}); | |
// Subscribe to connection errors | |
web3.currentProvider.on('error', (error) => { | |
console.error('WebSocket connection error:', error); | |
// Attempt to reconnect after a delay | |
setTimeout(setupSubscriptions, 5000); | |
}); | |
// Subscribe to connection close | |
web3.currentProvider.on('close', () => { | |
console.log('WebSocket connection closed. Attempting to reconnect...'); | |
// Attempt to reconnect after a delay | |
setTimeout(setupSubscriptions, 5000); | |
}); | |
console.log('WebSocket subscriptions set up successfully'); | |
} catch (error) { | |
console.error('Error setting up WebSocket subscriptions:', error); | |
// Attempt to reconnect after a delay | |
setTimeout(setupSubscriptions, 5000); | |
} | |
} | |
// Initialize subscriptions | |
setupSubscriptions(); | |
// Update health check to show processing game IDs | |
app.get('/health', (req, res) => { | |
res.json({ | |
status: 'ok', | |
houseAddress: houseAccount.address, | |
processingGameIds: Array.from(processingGameIds) | |
}); | |
}); | |
app.listen(port, () => { | |
console.log(`Server running at http://localhost:${port}`); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment