diff --git a/docker-compose.yml b/docker-compose.yml index 4556492..98d0634 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -38,10 +38,10 @@ services: DB_NAME: ${POSTGRES_DB} DB_USER: ${POSTGRES_USER} DB_PASSWORD: ${POSTGRES_PASSWORD} - SECURE_SSL_REDIRECT: False - SECURE_HSTS_SECONDS: 31536000 - SECURE_HSTS_INCLUDE_SUBDOMAINS: True - SECURE_HSTS_PRELOAD: True + PRIVATE_KEY: ${PRIVATE_KEY} + WEB3_PROVIDER: ${WEB3_PROVIDER} + CONTRACT_ADDRESS: ${CONTRACT_ADDRESS} + WEB3_ACCOUNT: ${WEB3_ACCOUNT} depends_on: - db healthcheck: diff --git a/env_template b/env_template index bb900b3..3325676 100644 --- a/env_template +++ b/env_template @@ -23,3 +23,9 @@ KIBANA_USERNAME=kibana_system KIBANA_PASSWORD= ENCRYPTION_KEY=c34d38b3a14956121ff2170e5030b471551370178f43e5626eec58b04a30fae2 + +# Web3 settings +PRIVATE_KEY= +WEB3_PROVIDER= +CONTRACT_ADDRESS= +WEB3_ACCOUNT= diff --git a/pong/game/tournament.py b/pong/game/tournament.py index c057f3e..eb9bd04 100644 --- a/pong/game/tournament.py +++ b/pong/game/tournament.py @@ -9,6 +9,7 @@ from .game import Game from .models import Tournoi from .utils import create_tournament, update_tournament, getlen from asgiref.sync import sync_to_async +from .views import write_data TOURNAMENT_NAMES = [ "Champion's Clash", "Ultimate Showdown", "Battle Royale", @@ -209,6 +210,10 @@ class TournamentMatchMaker: }) await sync_to_async(update_tournament)(self.final_name, winner_username) + + player_list = [player.user.username for player in self.waiting_players] + write_data(player_list, winner_username) + # Reset tournament state self.waiting_players = [] self.matches = [] diff --git a/pong/game/urls.py b/pong/game/urls.py index b5f6eb0..087e26f 100644 --- a/pong/game/urls.py +++ b/pong/game/urls.py @@ -11,7 +11,6 @@ urlpatterns = [ path('check_user_exists/', views.check_user_exists, name='check_user_exists'), path('register_user/', views.register_user, name='register_user'), path('authenticate_user/', views.authenticate_user, name='authenticate_user'), - path('web3/', views.read_data, name='read_data'), path('api/match_list/', match_list_json, name='match_list_json'), path('api/player_list/', player_list_json, name='player_list_json'), path('api/tournoi_list/', tournoi_list_json, name='tournoi_list_json'), diff --git a/pong/game/views.py b/pong/game/views.py index 49ef32c..8fb6c62 100644 --- a/pong/game/views.py +++ b/pong/game/views.py @@ -113,67 +113,47 @@ def tournoi_list_json(request): return JsonResponse({"tournois": tournois_data}) +import os from web3 import Web3 +import time -provider = Web3.HTTPProvider("https://sepolia.infura.io/v3/60e51df7c97c4f4c8ab41605a4eb9907") +provider = Web3.HTTPProvider(os.getenv('WEB3_PROVIDER')) web3 = Web3(provider) eth_gas_price = web3.eth.gas_price/1000000000 print(eth_gas_price) -contract_address = "0x078D04Eb6fb97Cd863361FC86000647DC876441B" -contract_abi = [{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"uint256","name":"_timecode","type":"uint256"},{"internalType":"uint256","name":"_participantCount","type":"uint256"},{"internalType":"string[]","name":"_playerPseudonyms","type":"string[]"},{"internalType":"string[]","name":"_finalOrder","type":"string[]"}],"name":"addTournament","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getAllTournaments","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"timecode","type":"uint256"},{"internalType":"uint256","name":"participantCount","type":"uint256"},{"internalType":"string[]","name":"playerPseudonyms","type":"string[]"},{"internalType":"string[]","name":"finalOrder","type":"string[]"}],"internalType":"struct PongTournament.Tournament[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_id","type":"uint256"}],"name":"getTournament","outputs":[{"components":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"timecode","type":"uint256"},{"internalType":"uint256","name":"participantCount","type":"uint256"},{"internalType":"string[]","name":"playerPseudonyms","type":"string[]"},{"internalType":"string[]","name":"finalOrder","type":"string[]"}],"internalType":"struct PongTournament.Tournament","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tournamentCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"tournaments","outputs":[{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"string","name":"name","type":"string"},{"internalType":"uint256","name":"timecode","type":"uint256"},{"internalType":"uint256","name":"participantCount","type":"uint256"}],"stateMutability":"view","type":"function"}] +contract_address = os.getenv('CONTRACT_ADDRESS') +contract_abi = [{"inputs": [{"internalType": "uint256","name": "_timecode","type": "uint256"},{"internalType": "string[]","name": "_player_list","type": "string[]"},{"internalType": "string","name": "_winner","type": "string"}],"name": "addTournament","outputs": [],"stateMutability": "nonpayable","type": "function"},{"inputs": [],"stateMutability": "nonpayable","type": "constructor"},{"inputs": [],"name": "getAllTournaments","outputs": [{"components": [{"internalType": "uint256","name": "id","type": "uint256"},{"internalType": "uint256","name": "timecode","type": "uint256"},{"internalType": "string[]","name": "player_list","type": "string[]"},{"internalType": "string","name": "winner","type": "string"}],"internalType": "struct PongTournament.Tournament[]","name": "","type": "tuple[]"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "_id","type": "uint256"}],"name": "getTournament","outputs": [{"components": [{"internalType": "uint256","name": "id","type": "uint256"},{"internalType": "uint256","name": "timecode","type": "uint256"},{"internalType": "string[]","name": "player_list","type": "string[]"},{"internalType": "string","name": "winner","type": "string"}],"internalType": "struct PongTournament.Tournament","name": "","type": "tuple"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "owner","outputs": [{"internalType": "address","name": "","type": "address"}],"stateMutability": "view","type": "function"},{"inputs": [],"name": "tournamentCount","outputs": [{"internalType": "uint256","name": "","type": "uint256"}],"stateMutability": "view","type": "function"},{"inputs": [{"internalType": "uint256","name": "","type": "uint256"}],"name": "tournaments","outputs": [{"internalType": "uint256","name": "id","type": "uint256"},{"internalType": "uint256","name": "timecode","type": "uint256"},{"internalType": "string","name": "winner","type": "string"}],"stateMutability": "view","type": "function"}] contract = web3.eth.contract(address=contract_address, abi=contract_abi) -def read_data(request): - # Créer une instance du contrat +def write_data(player_list, winner): + if (os.getenv('WEB3_PROVIDER') != "https://sepolia.infura.io/v3/60e51df7c97c4f4c8ab41605a4eb9907"): + return + timecode = int(time.time()) + account = os.getenv('WEB3_ACCOUNT') + private_key = os.getenv('PRIVATE_KEY') - # Appeler une fonction du contrat pour obtenir tous les tournois - tournaments = contract.functions.getAllTournaments().call() + print(contract_address, account, private_key) + print(timecode, player_list, winner) - # Afficher les résultats - json_data = [] - for tournament in tournaments: - tournament_data = [] - for item in tournament: - print(f"{item}") - tournament_data.append(item) - json_data.append(tournament_data) + nonce = web3.eth.get_transaction_count(account) + print(web3.to_wei(eth_gas_price, 'gwei')) + print(nonce) + transaction = contract.functions.addTournament(timecode, player_list, winner).build_transaction({ + 'chainId': 11155111, # ID de la chaîne Sepolia + 'gas': 2000000, + 'gasPrice': web3.to_wei(eth_gas_price, 'gwei'), + 'nonce': nonce + }) - # Retourner le JSON comme réponse HTTP - # print(f"Tournament ID: {tournament[0]}") - # print(f"Name: {tournament[1]}") - # print(f"Timecode: {tournament[2]}") - # print(f"Participant Count: {tournament[3]}") - # print(f"Player Pseudonyms: {', '.join(tournament[4])}") - # print(f"Final Order: {', '.join(tournament[5])}") - print("-----------------------------") - return JsonResponse(json_data, safe=False) - + # Signature de la transaction + signed_txn = web3.eth.account.sign_transaction(transaction, private_key) -def write_data(request): - # addTournament(string,uint256,uint256,string[],string[]) + # Envoi de la transaction + tx_hash = web3.eth.send_raw_transaction(signed_txn.raw_transaction) + print("Transaction hash:", web3.to_hex(tx_hash)) - # # Configuration de la transaction pour la fonction store - # account = "0x66CeBE2A1F7dae0F6AdBAad2c15A56A9121abfEf" - # private_key = "beb16ee3434ec5abec8b799549846cc04443c967b8d3643b943e2e969e7d25be" - - # nonce = web3.eth.get_transaction_count(account) - # transaction = contract.functions.addTournament("test",1721830559,6,["aaudeber", "tlorne", "ocassany", "yestello", "jcheca", "toto"],["toto", "jcheca", "yestello", "tlorne", "ocassany", "aaudeber"]).build_transaction({ - # 'chainId': 11155111, # ID de la chaîne Sepolia - # 'gas': 2000000, - # 'gasPrice': web3.to_wei(eth_gas_price, 'gwei'), - # 'nonce': nonce - # }) - - # # Signature de la transaction - # signed_txn = web3.eth.account.sign_transaction(transaction, private_key) - - # # Envoi de la transaction - # tx_hash = web3.eth.send_raw_transaction(signed_txn.rawTransaction) - # print("Transaction hash:", web3.to_hex(tx_hash)) - - # # Attente de la confirmation de la transaction - # tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash) - # print("Transaction receipt:", tx_receipt) - print("-----------------------------") + # Attente de la confirmation de la transaction + tx_receipt = web3.eth.wait_for_transaction_receipt(tx_hash) + print("Transaction receipt:", tx_receipt) diff --git a/pong/static/burger.js b/pong/static/burger.js index ca45088..0633783 100644 --- a/pong/static/burger.js +++ b/pong/static/burger.js @@ -55,7 +55,7 @@ document.addEventListener('DOMContentLoaded', () => { fetchTournois(); } else if (tableId === 'blockchain-list') { console.log('Opening external page in a new tab'); - window.open('https://sepolia.etherscan.io/address/0x078d04eb6fb97cd863361fc86000647dc876441b', '_blank'); + window.open('https://sepolia.etherscan.io/address/0x32a4bf81628fdd65d7b00ac676b80772c920e0c4', '_blank'); } if (dropdownMenu) { diff --git a/pong/static/language.js b/pong/static/language.js index dd5b518..ca5a24a 100644 --- a/pong/static/language.js +++ b/pong/static/language.js @@ -1,39 +1,94 @@ document.addEventListener('DOMContentLoaded', () => { const translations = { fr: { - welcome: "BIENVENUE DANS LE PONG 42", + labelWelcome: "BIENVENUE DANS LE PONG 42", labelNickname: "Entrez votre surnom:", labelPassword: "Entrez votre mot de passe:", labelConfirmPassword: "Confirmez votre mot de passe:", - labelLoginPassword: "Entrez votre mot de passe:" + labelLoginPassword: "Entrez votre mot de passe:", + labelSettings: "Paramètres", + labelCheckNickname: "Vérifiez votre surnom:", + labelLogin: "Se connecter", + labelLocalGame: "Jeu local", + labelQuickMatch: "Match rapide", + labelTournament: "Tournoi", + labelHome: "Accueil", + labelRetry: "Rejouer" }, en: { - welcome: "WELCOME TO PONG 42", + labelWelcome: "WELCOME TO PONG 42", labelNickname: "Enter your nickname:", labelPassword: "Enter your password:", labelConfirmPassword: "Confirm your password:", - labelLoginPassword: "Enter your password:" + labelLoginPassword: "Enter your password:", + labelSettings: "Settings", + labelCheckNickname: "Check your nickname:", + labelLogin: "Log in", + labelLocalGame: "Local game", + labelQuickMatch: "Quick match", + labelTournament: "Tournament", + labelHome: "Home", + labelRetry: "Retry" }, it: { - welcome: "BENVENUTO A PONG 42", + labelWelcome: "BENVENUTO A PONG 42", labelNickname: "Inserisci il tuo soprannome:", labelPassword: "Inserisci la tua password:", labelConfirmPassword: "Conferma la tua password:", - labelLoginPassword: "Inserisci la tua password:" + labelLoginPassword: "Inserisci la tua password:", + labelSettings: "Impostazioni", + labelCheckNickname: "Controlla il tuo soprannome:", + labelLogin: "Accedi", + labelLocalGame: "Gioco locale", + labelQuickMatch: "Partita rapida", + labelTournament: "Torneo", + labelHome: "Home", + labelRetry: "Riprova" }, es: { - welcome: "BIENVENIDO A PONG 42", + labelWelcome: "BIENVENIDO A PONG 42", labelNickname: "Introduce tu apodo:", labelPassword: "Introduce tu contraseña:", labelConfirmPassword: "Confirma tu contraseña:", - labelLoginPassword: "Introduce tu contraseña:" + labelLoginPassword: "Introduce tu contraseña:", + labelSettings: "Ajustes", + labelCheckNickname: "Comprueba tu apodo:", + labelLogin: "Iniciar sesión", + labelLocalGame: "Juego local", + labelQuickMatch: "Partida rápida", + labelTournament: "Torneo", + labelHome: "Inicio", + labelRetry: "Reintentar" }, de: { - welcome: "WILLKOMMEN BEI PONG 42", + labelWelcome: "WILLKOMMEN BEI PONG 42", labelNickname: "Geben Sie Ihren Spitznamen ein:", labelPassword: "Geben Sie Ihr Passwort ein:", labelConfirmPassword: "Bestätigen Sie Ihr Passwort:", - labelLoginPassword: "Geben Sie Ihr Passwort ein:" + labelLoginPassword: "Geben Sie Ihr Passwort ein:", + labelSettings: "Einstellungen", + labelCheckNickname: "Überprüfen Sie Ihren Spitznamen:", + labelLogin: "Anmelden", + labelLocalGame: "Lokales Spiel", + labelQuickMatch: "Schnelles Spiel", + labelTournament: "Turnier", + labelHome: "Startseite", + labelRetry: "Wiederholen" + }, + test: { + labelWelcome: "1", + labelNickname: "2", + labelPassword: "3", + labelConfirmPassword: "4", + labelLoginPassword: "5", + labelSettings: "6", + labelCheckNickname: "7", + labelLogin: "8", + labelLocalGame: "9", + labelQuickMatch: "10", + labelTournament: "11", + labelHome: "12", + labelRetry: "13" } }; @@ -62,11 +117,19 @@ document.addEventListener('DOMContentLoaded', () => { function changeLanguage(lang) { setCookie('preferredLanguage', lang, 365); - document.getElementById('welcome').innerText = translations[lang].welcome; + document.getElementById('welcome').innerText = translations[lang].labelWelcome; document.getElementById('label-nickname').innerText = translations[lang].labelNickname; document.getElementById('label-password').innerText = translations[lang].labelPassword; document.getElementById('label-confirm-password').innerText = translations[lang].labelConfirmPassword; document.getElementById('label-login-password').innerText = translations[lang].labelLoginPassword; + document.getElementById('settings-btn').innerText = translations[lang].labelSettings; + document.getElementById('check-nickname').innerText = translations[lang].labelCheckNickname; + document.getElementById('login').innerText = translations[lang].labelLogin; + document.getElementById('local-game').innerText = translations[lang].labelLocalGame; + document.getElementById('quick-match').innerText = translations[lang].labelQuickMatch; + document.getElementById('tournament').innerText = translations[lang].labelTournament; + document.getElementById('home').innerText = translations[lang].labelHome; + document.getElementById('retry').innerText = translations[lang].labelRetry; } function setLanguageFromCookie() {