Spaces:
Build error
Build error
Luisnguyen1 commited on
Commit ·
5c12778
1
Parent(s): fb2d702
sd
Browse files- Meeting.sol +5 -2
- callSM.go +533 -0
- luonghoatdong.md +18 -0
- main.go +49 -83
Meeting.sol
CHANGED
|
@@ -52,7 +52,7 @@ contract Meeting {
|
|
| 52 |
address private owner;
|
| 53 |
|
| 54 |
// Events
|
| 55 |
-
event RoomCreated(string roomId, string name, address owner);
|
| 56 |
event JoinedRoom(string roomId, address user);
|
| 57 |
event LeftRoom(string roomId, address user);
|
| 58 |
event TrackPublished(string roomId, address participant, string trackName);
|
|
@@ -139,9 +139,11 @@ contract Meeting {
|
|
| 139 |
rooms[roomId].isActive = true;
|
| 140 |
|
| 141 |
roomIds.push(roomId);
|
| 142 |
-
|
|
|
|
| 143 |
}
|
| 144 |
|
|
|
|
| 145 |
function setRoomStatus(string memory roomId, bool isActive) public roomMustExist(roomId) {
|
| 146 |
require(rooms[roomId].owner == msg.sender || users[msg.sender].isModerator, "Not authorized");
|
| 147 |
|
|
@@ -193,6 +195,7 @@ contract Meeting {
|
|
| 193 |
return bytes(rooms[roomId].name).length > 0;
|
| 194 |
}
|
| 195 |
|
|
|
|
| 196 |
// Participant management
|
| 197 |
function joinRoom(string memory roomId) public roomMustExist(roomId) {
|
| 198 |
require(rooms[roomId].participants[msg.sender].user == address(0), "Already joined");
|
|
|
|
| 52 |
address private owner;
|
| 53 |
|
| 54 |
// Events
|
| 55 |
+
event RoomCreated(string roomId, string name, string metadata ,address owner ,uint256 timestamp, bool isActive);
|
| 56 |
event JoinedRoom(string roomId, address user);
|
| 57 |
event LeftRoom(string roomId, address user);
|
| 58 |
event TrackPublished(string roomId, address participant, string trackName);
|
|
|
|
| 139 |
rooms[roomId].isActive = true;
|
| 140 |
|
| 141 |
roomIds.push(roomId);
|
| 142 |
+
|
| 143 |
+
emit RoomCreated(roomId, name, metadata , msg.sender, rooms[roomId].createdAt , true);
|
| 144 |
}
|
| 145 |
|
| 146 |
+
|
| 147 |
function setRoomStatus(string memory roomId, bool isActive) public roomMustExist(roomId) {
|
| 148 |
require(rooms[roomId].owner == msg.sender || users[msg.sender].isModerator, "Not authorized");
|
| 149 |
|
|
|
|
| 195 |
return bytes(rooms[roomId].name).length > 0;
|
| 196 |
}
|
| 197 |
|
| 198 |
+
|
| 199 |
// Participant management
|
| 200 |
function joinRoom(string memory roomId) public roomMustExist(roomId) {
|
| 201 |
require(rooms[roomId].participants[msg.sender].user == address(0), "Already joined");
|
callSM.go
ADDED
|
@@ -0,0 +1,533 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
// package main
|
| 2 |
+
|
| 3 |
+
// import (
|
| 4 |
+
// "context"
|
| 5 |
+
// "crypto/ecdsa"
|
| 6 |
+
// "fmt"
|
| 7 |
+
// "log"
|
| 8 |
+
// "math/big"
|
| 9 |
+
// "os"
|
| 10 |
+
// "strings"
|
| 11 |
+
|
| 12 |
+
// "github.com/ethereum/go-ethereum"
|
| 13 |
+
// "github.com/ethereum/go-ethereum/accounts/abi"
|
| 14 |
+
// "github.com/ethereum/go-ethereum/common"
|
| 15 |
+
// "github.com/ethereum/go-ethereum/core/types"
|
| 16 |
+
// "github.com/ethereum/go-ethereum/crypto"
|
| 17 |
+
// "github.com/ethereum/go-ethereum/ethclient"
|
| 18 |
+
// "github.com/joho/godotenv"
|
| 19 |
+
// )
|
| 20 |
+
|
| 21 |
+
// // Global variables
|
| 22 |
+
// var (
|
| 23 |
+
// client *ethclient.Client
|
| 24 |
+
// contractAddress common.Address
|
| 25 |
+
// parsedABI abi.ABI
|
| 26 |
+
// privateKey *ecdsa.PrivateKey
|
| 27 |
+
// fromAddress common.Address
|
| 28 |
+
// chainID *big.Int
|
| 29 |
+
// )
|
| 30 |
+
|
| 31 |
+
// func init() {
|
| 32 |
+
// // Load environment variables
|
| 33 |
+
// if err := godotenv.Load(); err != nil {
|
| 34 |
+
// log.Fatal("Error loading .env file")
|
| 35 |
+
// }
|
| 36 |
+
|
| 37 |
+
// // Connect to the blockchain
|
| 38 |
+
// var err error
|
| 39 |
+
// client, err = ethclient.Dial("https://bsc-testnet.publicnode.com") // BSC Testnet
|
| 40 |
+
// if err != nil {
|
| 41 |
+
// log.Fatalf("Failed to connect to the blockchain: %v", err)
|
| 42 |
+
// }
|
| 43 |
+
|
| 44 |
+
// // Load contract information
|
| 45 |
+
// contractAddress = common.HexToAddress(os.Getenv("CONTRACT_ADDRESS"))
|
| 46 |
+
// parsedABI, err = abi.JSON(strings.NewReader(os.Getenv("ABI_JSON")))
|
| 47 |
+
// if err != nil {
|
| 48 |
+
// log.Fatalf("Failed to parse ABI: %v", err)
|
| 49 |
+
// }
|
| 50 |
+
|
| 51 |
+
// // Load private key
|
| 52 |
+
// privateKey, err = crypto.HexToECDSA(os.Getenv("PRIVATE_KEY"))
|
| 53 |
+
// if err != nil {
|
| 54 |
+
// log.Fatalf("Failed to parse private key: %v", err)
|
| 55 |
+
// }
|
| 56 |
+
|
| 57 |
+
// // Get public key and address
|
| 58 |
+
// publicKey := privateKey.Public()
|
| 59 |
+
// publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
|
| 60 |
+
// if !ok {
|
| 61 |
+
// log.Fatal("Error converting public key")
|
| 62 |
+
// }
|
| 63 |
+
// fromAddress = crypto.PubkeyToAddress(*publicKeyECDSA)
|
| 64 |
+
|
| 65 |
+
// // Set chain ID for BSC Testnet
|
| 66 |
+
// chainID = big.NewInt(97)
|
| 67 |
+
|
| 68 |
+
// fmt.Printf("Connected to blockchain with address: %s\n", fromAddress.Hex())
|
| 69 |
+
// }
|
| 70 |
+
|
| 71 |
+
// // Read function example - getAllRooms
|
| 72 |
+
// func getAllRooms() {
|
| 73 |
+
// callData, err := parsedABI.Pack("getAllRooms")
|
| 74 |
+
// if err != nil {
|
| 75 |
+
// log.Fatalf("Failed to pack call data: %v", err)
|
| 76 |
+
// }
|
| 77 |
+
|
| 78 |
+
// result, err := client.CallContract(context.Background(), ethereum.CallMsg{
|
| 79 |
+
// To: &contractAddress,
|
| 80 |
+
// Data: callData,
|
| 81 |
+
// }, nil)
|
| 82 |
+
// if err != nil {
|
| 83 |
+
// log.Fatalf("Failed to call getAllRooms: %v", err)
|
| 84 |
+
// }
|
| 85 |
+
|
| 86 |
+
// var roomIds []string
|
| 87 |
+
// err = parsedABI.UnpackIntoInterface(&roomIds, "getAllRooms", result)
|
| 88 |
+
// if err != nil {
|
| 89 |
+
// log.Fatalf("Failed to unpack result: %v", err)
|
| 90 |
+
// }
|
| 91 |
+
|
| 92 |
+
// fmt.Println("All Room IDs:")
|
| 93 |
+
// for i, roomId := range roomIds {
|
| 94 |
+
// fmt.Printf("%d. %s\n", i+1, roomId)
|
| 95 |
+
// }
|
| 96 |
+
// }
|
| 97 |
+
|
| 98 |
+
// // Read function - getRoomDetails
|
| 99 |
+
// func getRoomDetails(roomId string) {
|
| 100 |
+
// callData, err := parsedABI.Pack("getRoomDetails", roomId)
|
| 101 |
+
// if err != nil {
|
| 102 |
+
// log.Fatalf("Failed to pack call data: %v", err)
|
| 103 |
+
// }
|
| 104 |
+
|
| 105 |
+
// result, err := client.CallContract(context.Background(), ethereum.CallMsg{
|
| 106 |
+
// To: &contractAddress,
|
| 107 |
+
// Data: callData,
|
| 108 |
+
// }, nil)
|
| 109 |
+
// if err != nil {
|
| 110 |
+
// log.Fatalf("Failed to call getRoomDetails: %v", err)
|
| 111 |
+
// }
|
| 112 |
+
|
| 113 |
+
// // Unpack result
|
| 114 |
+
// output, err := parsedABI.Unpack("getRoomDetails", result)
|
| 115 |
+
// if err != nil {
|
| 116 |
+
// log.Fatalf("Failed to unpack result: %v", err)
|
| 117 |
+
// }
|
| 118 |
+
|
| 119 |
+
// // Process output
|
| 120 |
+
// if len(output) == 6 {
|
| 121 |
+
// fmt.Println("Room Details:")
|
| 122 |
+
// fmt.Printf("ID: %s\n", output[0].(string))
|
| 123 |
+
// fmt.Printf("Name: %s\n", output[1].(string))
|
| 124 |
+
// fmt.Printf("Metadata: %s\n", output[2].(string))
|
| 125 |
+
// fmt.Printf("Owner: %s\n", output[3].(common.Address).Hex())
|
| 126 |
+
// fmt.Printf("Created At: %s\n", output[4].(*big.Int).String())
|
| 127 |
+
// fmt.Printf("Is Active: %t\n", output[5].(bool))
|
| 128 |
+
// } else {
|
| 129 |
+
// fmt.Println("Unexpected output format")
|
| 130 |
+
// }
|
| 131 |
+
// }
|
| 132 |
+
|
| 133 |
+
// // Read function - getRoomParticipants
|
| 134 |
+
// func getRoomParticipants(roomId string) {
|
| 135 |
+
// callData, err := parsedABI.Pack("getRoomParticipants", roomId)
|
| 136 |
+
// if err != nil {
|
| 137 |
+
// log.Fatalf("Failed to pack call data: %v", err)
|
| 138 |
+
// }
|
| 139 |
+
|
| 140 |
+
// result, err := client.CallContract(context.Background(), ethereum.CallMsg{
|
| 141 |
+
// To: &contractAddress,
|
| 142 |
+
// Data: callData,
|
| 143 |
+
// }, nil)
|
| 144 |
+
// if err != nil {
|
| 145 |
+
// log.Fatalf("Failed to call getRoomParticipants: %v", err)
|
| 146 |
+
// }
|
| 147 |
+
|
| 148 |
+
// var participants []common.Address
|
| 149 |
+
// err = parsedABI.UnpackIntoInterface(&participants, "getRoomParticipants", result)
|
| 150 |
+
// if err != nil {
|
| 151 |
+
// log.Fatalf("Failed to unpack result: %v", err)
|
| 152 |
+
// }
|
| 153 |
+
|
| 154 |
+
// fmt.Printf("Participants in room %s:\n", roomId)
|
| 155 |
+
// for i, address := range participants {
|
| 156 |
+
// fmt.Printf("%d. %s\n", i+1, address.Hex())
|
| 157 |
+
// }
|
| 158 |
+
// }
|
| 159 |
+
|
| 160 |
+
// // Read function - getIceServers
|
| 161 |
+
// func getIceServers() {
|
| 162 |
+
// callData, err := parsedABI.Pack("getIceServers")
|
| 163 |
+
// if err != nil {
|
| 164 |
+
// log.Fatalf("Failed to pack call data: %v", err)
|
| 165 |
+
// }
|
| 166 |
+
|
| 167 |
+
// result, err := client.CallContract(context.Background(), ethereum.CallMsg{
|
| 168 |
+
// To: &contractAddress,
|
| 169 |
+
// Data: callData,
|
| 170 |
+
// }, nil)
|
| 171 |
+
// if err != nil {
|
| 172 |
+
// log.Fatalf("Failed to call getIceServers: %v", err)
|
| 173 |
+
// }
|
| 174 |
+
|
| 175 |
+
// // This is a bit trickier due to struct array return type
|
| 176 |
+
// // Just showing raw result for now
|
| 177 |
+
// fmt.Printf("ICE Servers Raw Result: %x\n", result)
|
| 178 |
+
// }
|
| 179 |
+
|
| 180 |
+
// // Write function - createRoom
|
| 181 |
+
// func createRoom(roomId, name, metadata string) {
|
| 182 |
+
// nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
|
| 183 |
+
// if err != nil {
|
| 184 |
+
// log.Fatalf("Failed to get nonce: %v", err)
|
| 185 |
+
// }
|
| 186 |
+
|
| 187 |
+
// gasPrice, err := client.SuggestGasPrice(context.Background())
|
| 188 |
+
// if err != nil {
|
| 189 |
+
// log.Fatalf("Failed to get gas price: %v", err)
|
| 190 |
+
// }
|
| 191 |
+
|
| 192 |
+
// // Pack the data for the function call
|
| 193 |
+
// data, err := parsedABI.Pack("createRoom", roomId, name, metadata)
|
| 194 |
+
// if err != nil {
|
| 195 |
+
// log.Fatalf("Failed to pack transaction data: %v", err)
|
| 196 |
+
// }
|
| 197 |
+
|
| 198 |
+
// // Estimate gas
|
| 199 |
+
// gasLimit := uint64(500000) // Default high value
|
| 200 |
+
// estimatedGas, err := client.EstimateGas(context.Background(), ethereum.CallMsg{
|
| 201 |
+
// From: fromAddress,
|
| 202 |
+
// To: &contractAddress,
|
| 203 |
+
// Value: big.NewInt(0),
|
| 204 |
+
// Data: data,
|
| 205 |
+
// })
|
| 206 |
+
|
| 207 |
+
// if err == nil {
|
| 208 |
+
// // Add 20% buffer to estimated gas
|
| 209 |
+
// gasLimit = uint64(float64(estimatedGas) * 1.2)
|
| 210 |
+
// fmt.Printf("Gas estimate: %d, using: %d\n", estimatedGas, gasLimit)
|
| 211 |
+
// } else {
|
| 212 |
+
// fmt.Printf("Gas estimation failed: %v. Using default: %d\n", err, gasLimit)
|
| 213 |
+
// }
|
| 214 |
+
|
| 215 |
+
// // Create the transaction
|
| 216 |
+
// tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, data)
|
| 217 |
+
|
| 218 |
+
// // Sign the transaction
|
| 219 |
+
// signedTx, err := types.SignTx(tx, types.NewLondonSigner(chainID), privateKey)
|
| 220 |
+
// if err != nil {
|
| 221 |
+
// log.Fatalf("Failed to sign transaction: %v", err)
|
| 222 |
+
// }
|
| 223 |
+
|
| 224 |
+
// // Send the transaction
|
| 225 |
+
// err = client.SendTransaction(context.Background(), signedTx)
|
| 226 |
+
// if err != nil {
|
| 227 |
+
// log.Fatalf("Failed to send transaction: %v", err)
|
| 228 |
+
// }
|
| 229 |
+
|
| 230 |
+
// fmt.Printf("Transaction sent! Hash: %s\n", signedTx.Hash().Hex())
|
| 231 |
+
// fmt.Println("Room creation initiated. Wait for the transaction to be mined.")
|
| 232 |
+
// }
|
| 233 |
+
|
| 234 |
+
// // Write function - joinRoom
|
| 235 |
+
// func joinRoom(roomId string) {
|
| 236 |
+
// nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
|
| 237 |
+
// if err != nil {
|
| 238 |
+
// log.Fatalf("Failed to get nonce: %v", err)
|
| 239 |
+
// }
|
| 240 |
+
|
| 241 |
+
// gasPrice, err := client.SuggestGasPrice(context.Background())
|
| 242 |
+
// if err != nil {
|
| 243 |
+
// log.Fatalf("Failed to get gas price: %v", err)
|
| 244 |
+
// }
|
| 245 |
+
|
| 246 |
+
// // Pack the data for the function call
|
| 247 |
+
// data, err := parsedABI.Pack("joinRoom", roomId)
|
| 248 |
+
// if err != nil {
|
| 249 |
+
// log.Fatalf("Failed to pack transaction data: %v", err)
|
| 250 |
+
// }
|
| 251 |
+
|
| 252 |
+
// gasLimit := uint64(300000)
|
| 253 |
+
|
| 254 |
+
// // Create the transaction
|
| 255 |
+
// tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, data)
|
| 256 |
+
|
| 257 |
+
// // Sign the transaction
|
| 258 |
+
// signedTx, err := types.SignTx(tx, types.NewLondonSigner(chainID), privateKey)
|
| 259 |
+
// if err != nil {
|
| 260 |
+
// log.Fatalf("Failed to sign transaction: %v", err)
|
| 261 |
+
// }
|
| 262 |
+
|
| 263 |
+
// // Send the transaction
|
| 264 |
+
// err = client.SendTransaction(context.Background(), signedTx)
|
| 265 |
+
// if err != nil {
|
| 266 |
+
// log.Fatalf("Failed to send transaction: %v", err)
|
| 267 |
+
// }
|
| 268 |
+
|
| 269 |
+
// fmt.Printf("Transaction sent! Hash: %s\n", signedTx.Hash().Hex())
|
| 270 |
+
// fmt.Println("Room join initiated. Wait for the transaction to be mined.")
|
| 271 |
+
// }
|
| 272 |
+
|
| 273 |
+
// // Write function - leaveRoom
|
| 274 |
+
// func leaveRoom(roomId string) {
|
| 275 |
+
// nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
|
| 276 |
+
// if err != nil {
|
| 277 |
+
// log.Fatalf("Failed to get nonce: %v", err)
|
| 278 |
+
// }
|
| 279 |
+
|
| 280 |
+
// gasPrice, err := client.SuggestGasPrice(context.Background())
|
| 281 |
+
// if err != nil {
|
| 282 |
+
// log.Fatalf("Failed to get gas price: %v", err)
|
| 283 |
+
// }
|
| 284 |
+
|
| 285 |
+
// // Pack the data for the function call
|
| 286 |
+
// data, err := parsedABI.Pack("leaveRoom", roomId)
|
| 287 |
+
// if err != nil {
|
| 288 |
+
// log.Fatalf("Failed to pack transaction data: %v", err)
|
| 289 |
+
// }
|
| 290 |
+
|
| 291 |
+
// gasLimit := uint64(300000)
|
| 292 |
+
|
| 293 |
+
// // Create the transaction
|
| 294 |
+
// tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, data)
|
| 295 |
+
|
| 296 |
+
// // Sign the transaction
|
| 297 |
+
// signedTx, err := types.SignTx(tx, types.NewLondonSigner(chainID), privateKey)
|
| 298 |
+
// if err != nil {
|
| 299 |
+
// log.Fatalf("Failed to sign transaction: %v", err)
|
| 300 |
+
// }
|
| 301 |
+
|
| 302 |
+
// // Send the transaction
|
| 303 |
+
// err = client.SendTransaction(context.Background(), signedTx)
|
| 304 |
+
// if err != nil {
|
| 305 |
+
// log.Fatalf("Failed to send transaction: %v", err)
|
| 306 |
+
// }
|
| 307 |
+
|
| 308 |
+
// fmt.Printf("Transaction sent! Hash: %s\n", signedTx.Hash().Hex())
|
| 309 |
+
// fmt.Println("Room leave initiated. Wait for the transaction to be mined.")
|
| 310 |
+
// }
|
| 311 |
+
|
| 312 |
+
// // Write function - saveSessionID
|
| 313 |
+
// func saveSessionID(roomId, sessionID string) {
|
| 314 |
+
// nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
|
| 315 |
+
// if err != nil {
|
| 316 |
+
// log.Fatalf("Failed to get nonce: %v", err)
|
| 317 |
+
// }
|
| 318 |
+
|
| 319 |
+
// gasPrice, err := client.SuggestGasPrice(context.Background())
|
| 320 |
+
// if err != nil {
|
| 321 |
+
// log.Fatalf("Failed to get gas price: %v", err)
|
| 322 |
+
// }
|
| 323 |
+
|
| 324 |
+
// // Pack the data for the function call
|
| 325 |
+
// data, err := parsedABI.Pack("saveSessionID", roomId, sessionID)
|
| 326 |
+
// if err != nil {
|
| 327 |
+
// log.Fatalf("Failed to pack transaction data: %v", err)
|
| 328 |
+
// }
|
| 329 |
+
|
| 330 |
+
// gasLimit := uint64(300000)
|
| 331 |
+
|
| 332 |
+
// // Create the transaction
|
| 333 |
+
// tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, data)
|
| 334 |
+
|
| 335 |
+
// // Sign the transaction
|
| 336 |
+
// signedTx, err := types.SignTx(tx, types.NewLondonSigner(chainID), privateKey)
|
| 337 |
+
// if err != nil {
|
| 338 |
+
// log.Fatalf("Failed to sign transaction: %v", err)
|
| 339 |
+
// }
|
| 340 |
+
|
| 341 |
+
// // Send the transaction
|
| 342 |
+
// err = client.SendTransaction(context.Background(), signedTx)
|
| 343 |
+
// if err != nil {
|
| 344 |
+
// log.Fatalf("Failed to send transaction: %v", err)
|
| 345 |
+
// }
|
| 346 |
+
|
| 347 |
+
// fmt.Printf("Transaction sent! Hash: %s\n", signedTx.Hash().Hex())
|
| 348 |
+
// fmt.Println("Session ID save initiated. Wait for the transaction to be mined.")
|
| 349 |
+
// }
|
| 350 |
+
|
| 351 |
+
// // Write function - updateRoomMetadata
|
| 352 |
+
// func updateRoomMetadata(roomId, key, value string) {
|
| 353 |
+
// nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
|
| 354 |
+
// if err != nil {
|
| 355 |
+
// log.Fatalf("Failed to get nonce: %v", err)
|
| 356 |
+
// }
|
| 357 |
+
|
| 358 |
+
// gasPrice, err := client.SuggestGasPrice(context.Background())
|
| 359 |
+
// if err != nil {
|
| 360 |
+
// log.Fatalf("Failed to get gas price: %v", err)
|
| 361 |
+
// }
|
| 362 |
+
|
| 363 |
+
// // Pack the data for the function call
|
| 364 |
+
// data, err := parsedABI.Pack("updateRoomMetadata", roomId, key, value)
|
| 365 |
+
// if err != nil {
|
| 366 |
+
// log.Fatalf("Failed to pack transaction data: %v", err)
|
| 367 |
+
// }
|
| 368 |
+
|
| 369 |
+
// gasLimit := uint64(300000)
|
| 370 |
+
|
| 371 |
+
// // Create the transaction
|
| 372 |
+
// tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, data)
|
| 373 |
+
|
| 374 |
+
// // Sign the transaction
|
| 375 |
+
// signedTx, err := types.SignTx(tx, types.NewLondonSigner(chainID), privateKey)
|
| 376 |
+
// if err != nil {
|
| 377 |
+
// log.Fatalf("Failed to sign transaction: %v", err)
|
| 378 |
+
// }
|
| 379 |
+
|
| 380 |
+
// // Send the transaction
|
| 381 |
+
// err = client.SendTransaction(context.Background(), signedTx)
|
| 382 |
+
// if err != nil {
|
| 383 |
+
// log.Fatalf("Failed to send transaction: %v", err)
|
| 384 |
+
// }
|
| 385 |
+
|
| 386 |
+
// fmt.Printf("Transaction sent! Hash: %s\n", signedTx.Hash().Hex())
|
| 387 |
+
// fmt.Println("Metadata update initiated. Wait for the transaction to be mined.")
|
| 388 |
+
// }
|
| 389 |
+
|
| 390 |
+
// // Write function - setRoomStatus
|
| 391 |
+
// func setRoomStatus(roomId string, isActive bool) {
|
| 392 |
+
// nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
|
| 393 |
+
// if err != nil {
|
| 394 |
+
// log.Fatalf("Failed to get nonce: %v", err)
|
| 395 |
+
// }
|
| 396 |
+
|
| 397 |
+
// gasPrice, err := client.SuggestGasPrice(context.Background())
|
| 398 |
+
// if err != nil {
|
| 399 |
+
// log.Fatalf("Failed to get gas price: %v", err)
|
| 400 |
+
// }
|
| 401 |
+
|
| 402 |
+
// // Pack the data for the function call
|
| 403 |
+
// data, err := parsedABI.Pack("setRoomStatus", roomId, isActive)
|
| 404 |
+
// if err != nil {
|
| 405 |
+
// log.Fatalf("Failed to pack transaction data: %v", err)
|
| 406 |
+
// }
|
| 407 |
+
|
| 408 |
+
// gasLimit := uint64(300000)
|
| 409 |
+
|
| 410 |
+
// // Create the transaction
|
| 411 |
+
// tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, data)
|
| 412 |
+
|
| 413 |
+
// // Sign the transaction
|
| 414 |
+
// signedTx, err := types.SignTx(tx, types.NewLondonSigner(chainID), privateKey)
|
| 415 |
+
// if err != nil {
|
| 416 |
+
// log.Fatalf("Failed to sign transaction: %v", err)
|
| 417 |
+
// }
|
| 418 |
+
|
| 419 |
+
// // Send the transaction
|
| 420 |
+
// err = client.SendTransaction(context.Background(), signedTx)
|
| 421 |
+
// if err != nil {
|
| 422 |
+
// log.Fatalf("Failed to send transaction: %v", err)
|
| 423 |
+
// }
|
| 424 |
+
|
| 425 |
+
// fmt.Printf("Transaction sent! Hash: %s\n", signedTx.Hash().Hex())
|
| 426 |
+
// fmt.Println("Room status update initiated. Wait for the transaction to be mined.")
|
| 427 |
+
// }
|
| 428 |
+
|
| 429 |
+
// func main() {
|
| 430 |
+
// fmt.Println("Smart Contract Testing Tool")
|
| 431 |
+
// fmt.Println("===========================")
|
| 432 |
+
|
| 433 |
+
// for {
|
| 434 |
+
// fmt.Println("\nSelect an operation:")
|
| 435 |
+
// fmt.Println("Read Operations:")
|
| 436 |
+
// fmt.Println("1. Get All Rooms")
|
| 437 |
+
// fmt.Println("2. Get Room Details")
|
| 438 |
+
// fmt.Println("3. Get Room Participants")
|
| 439 |
+
// fmt.Println("4. Get ICE Servers")
|
| 440 |
+
// fmt.Println("\nWrite Operations:")
|
| 441 |
+
// fmt.Println("5. Create Room")
|
| 442 |
+
// fmt.Println("6. Join Room")
|
| 443 |
+
// fmt.Println("7. Leave Room")
|
| 444 |
+
// fmt.Println("8. Save Session ID")
|
| 445 |
+
// fmt.Println("9. Update Room Metadata")
|
| 446 |
+
// fmt.Println("10. Set Room Status")
|
| 447 |
+
// fmt.Println("\n0. Exit")
|
| 448 |
+
|
| 449 |
+
// var choice int
|
| 450 |
+
// fmt.Print("\nEnter your choice: ")
|
| 451 |
+
// fmt.Scan(&choice)
|
| 452 |
+
|
| 453 |
+
// switch choice {
|
| 454 |
+
// case 0:
|
| 455 |
+
// fmt.Println("Exiting...")
|
| 456 |
+
// return
|
| 457 |
+
|
| 458 |
+
// case 1: // Get All Rooms
|
| 459 |
+
// getAllRooms()
|
| 460 |
+
|
| 461 |
+
// case 2: // Get Room Details
|
| 462 |
+
// var roomId string
|
| 463 |
+
// fmt.Print("Enter Room ID: ")
|
| 464 |
+
// fmt.Scan(&roomId)
|
| 465 |
+
// getRoomDetails(roomId)
|
| 466 |
+
|
| 467 |
+
// case 3: // Get Room Participants
|
| 468 |
+
// var roomId string
|
| 469 |
+
// fmt.Print("Enter Room ID: ")
|
| 470 |
+
// fmt.Scan(&roomId)
|
| 471 |
+
// getRoomParticipants(roomId)
|
| 472 |
+
|
| 473 |
+
// case 4: // Get ICE Servers
|
| 474 |
+
// getIceServers()
|
| 475 |
+
|
| 476 |
+
// case 5: // Create Room
|
| 477 |
+
// var roomId, name, metadata string
|
| 478 |
+
// fmt.Print("Enter Room ID: ")
|
| 479 |
+
// fmt.Scan(&roomId)
|
| 480 |
+
// fmt.Print("Enter Room Name: ")
|
| 481 |
+
// fmt.Scan(&name)
|
| 482 |
+
// fmt.Print("Enter Metadata (JSON string): ")
|
| 483 |
+
// fmt.Scan(&metadata)
|
| 484 |
+
// createRoom(roomId, name, metadata)
|
| 485 |
+
|
| 486 |
+
// case 6: // Join Room
|
| 487 |
+
// var roomId string
|
| 488 |
+
// fmt.Print("Enter Room ID: ")
|
| 489 |
+
// fmt.Scan(&roomId)
|
| 490 |
+
// joinRoom(roomId)
|
| 491 |
+
|
| 492 |
+
// case 7: // Leave Room
|
| 493 |
+
// var roomId string
|
| 494 |
+
// fmt.Print("Enter Room ID: ")
|
| 495 |
+
// fmt.Scan(&roomId)
|
| 496 |
+
// leaveRoom(roomId)
|
| 497 |
+
|
| 498 |
+
// case 8: // Save Session ID
|
| 499 |
+
// var roomId, sessionID string
|
| 500 |
+
// fmt.Print("Enter Room ID: ")
|
| 501 |
+
// fmt.Scan(&roomId)
|
| 502 |
+
// fmt.Print("Enter Session ID: ")
|
| 503 |
+
// fmt.Scan(&sessionID)
|
| 504 |
+
// saveSessionID(roomId, sessionID)
|
| 505 |
+
|
| 506 |
+
// case 9: // Update Room Metadata
|
| 507 |
+
// var roomId, key, value string
|
| 508 |
+
// fmt.Print("Enter Room ID: ")
|
| 509 |
+
// fmt.Scan(&roomId)
|
| 510 |
+
// fmt.Print("Enter Metadata Key: ")
|
| 511 |
+
// fmt.Scan(&key)
|
| 512 |
+
// fmt.Print("Enter Metadata Value: ")
|
| 513 |
+
// fmt.Scan(&value)
|
| 514 |
+
// updateRoomMetadata(roomId, key, value)
|
| 515 |
+
|
| 516 |
+
// case 10: // Set Room Status
|
| 517 |
+
// var roomId string
|
| 518 |
+
// var status int
|
| 519 |
+
// fmt.Print("Enter Room ID: ")
|
| 520 |
+
// fmt.Scan(&roomId)
|
| 521 |
+
// fmt.Print("Enter Status (1 for active, 0 for inactive): ")
|
| 522 |
+
// fmt.Scan(&status)
|
| 523 |
+
// isActive := status == 1
|
| 524 |
+
// setRoomStatus(roomId, isActive)
|
| 525 |
+
|
| 526 |
+
// default:
|
| 527 |
+
// fmt.Println("Invalid choice. Please try again.")
|
| 528 |
+
// }
|
| 529 |
+
|
| 530 |
+
// fmt.Println("\nPress Enter to continue...")
|
| 531 |
+
// fmt.Scanln() // Wait for Enter
|
| 532 |
+
// }
|
| 533 |
+
// }
|
luonghoatdong.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
graph LR
|
| 2 |
+
A[Client (Frontend)] --> B(Backend Server - Go package main)
|
| 3 |
+
B --> C[Cloudflare Calls API]
|
| 4 |
+
B <--> D[WebSocket Connections]
|
| 5 |
+
B --> E[Data Storage (In-memory)]
|
| 6 |
+
|
| 7 |
+
subgraph "Backend Server (Go)"
|
| 8 |
+
B -- Gin HTTP Routes --> B1[Route Handlers]
|
| 9 |
+
B -- WebSocket Endpoint --> B2[WebSocket Handler]
|
| 10 |
+
B1 --> B3[Cloudflare API Functions]
|
| 11 |
+
B2 --> B4[Broadcast Functions]
|
| 12 |
+
B1 & B2 --> E
|
| 13 |
+
end
|
| 14 |
+
|
| 15 |
+
style B fill:#f9f,stroke:#333,stroke-width:2px
|
| 16 |
+
style C fill:#ccf,stroke:#333,stroke-width:1px
|
| 17 |
+
style D fill:#ccf,stroke:#333,stroke-width:1px
|
| 18 |
+
style E fill:#eee,stroke:#333,stroke-width:1px
|
main.go
CHANGED
|
@@ -3,7 +3,6 @@ package main
|
|
| 3 |
import (
|
| 4 |
"bytes"
|
| 5 |
"context"
|
| 6 |
-
"crypto/ecdsa"
|
| 7 |
"crypto/hmac"
|
| 8 |
"crypto/sha256"
|
| 9 |
"encoding/base64"
|
|
@@ -11,7 +10,6 @@ import (
|
|
| 11 |
"fmt"
|
| 12 |
"io"
|
| 13 |
"log"
|
| 14 |
-
"math/big"
|
| 15 |
"net/http"
|
| 16 |
"os"
|
| 17 |
"strconv"
|
|
@@ -19,10 +17,10 @@ import (
|
|
| 19 |
"sync"
|
| 20 |
"time"
|
| 21 |
|
|
|
|
| 22 |
"github.com/ethereum/go-ethereum/accounts/abi"
|
| 23 |
"github.com/ethereum/go-ethereum/common"
|
| 24 |
"github.com/ethereum/go-ethereum/core/types"
|
| 25 |
-
"github.com/ethereum/go-ethereum/crypto"
|
| 26 |
"github.com/ethereum/go-ethereum/ethclient"
|
| 27 |
"github.com/gin-gonic/gin"
|
| 28 |
"github.com/golang-jwt/jwt/v5"
|
|
@@ -614,22 +612,12 @@ func serializeRoom(roomId string, room *Room) gin.H {
|
|
| 614 |
|
| 615 |
// --- Route Handlers ---
|
| 616 |
|
| 617 |
-
func createRoom(c *gin.Context) {
|
| 618 |
-
roomId := uuid.NewString()
|
| 619 |
-
var req struct {
|
| 620 |
-
Name string `json:"name"`
|
| 621 |
-
Metadata map[string]interface{} `json:"metadata"`
|
| 622 |
-
}
|
| 623 |
-
|
| 624 |
-
if err := c.ShouldBindJSON(&req); err != nil {
|
| 625 |
-
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
| 626 |
-
return
|
| 627 |
-
}
|
| 628 |
|
| 629 |
room := &Room{
|
| 630 |
RoomId: roomId, // Thêm trường này
|
| 631 |
-
Name:
|
| 632 |
-
Metadata:
|
| 633 |
Participants: []*Participant{},
|
| 634 |
CreatedAt: time.Now().Unix(),
|
| 635 |
}
|
|
@@ -638,13 +626,6 @@ func createRoom(c *gin.Context) {
|
|
| 638 |
rooms.m[roomId] = room
|
| 639 |
rooms.Unlock()
|
| 640 |
|
| 641 |
-
// Update data on the smart contract
|
| 642 |
-
err := updateRoomOnContract(roomId, req.Name, req.Metadata)
|
| 643 |
-
if err != nil {
|
| 644 |
-
c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to update smart contract", "details": err.Error()})
|
| 645 |
-
return
|
| 646 |
-
}
|
| 647 |
-
|
| 648 |
log.Printf("Room metadata: %s", room.Metadata)
|
| 649 |
|
| 650 |
// Trả về format giống Express
|
|
@@ -655,66 +636,7 @@ func createRoom(c *gin.Context) {
|
|
| 655 |
"participantCount": len(room.Participants),
|
| 656 |
"createdAt": room.CreatedAt,
|
| 657 |
})
|
| 658 |
-
}
|
| 659 |
-
|
| 660 |
-
func updateRoomOnContract(roomId string, name string, metadata map[string]interface{}) error {
|
| 661 |
-
client, err := ethclient.Dial(RPC_URL)
|
| 662 |
-
if err != nil {
|
| 663 |
-
return fmt.Errorf("failed to connect to blockchain: %v", err)
|
| 664 |
-
}
|
| 665 |
-
defer client.Close()
|
| 666 |
-
|
| 667 |
-
contractAddress := common.HexToAddress(CONTRACT_ADDRESS)
|
| 668 |
-
parsedABI, err := abi.JSON(strings.NewReader(ABI_JSON))
|
| 669 |
-
if err != nil {
|
| 670 |
-
return fmt.Errorf("failed to parse ABI: %v", err)
|
| 671 |
-
}
|
| 672 |
-
|
| 673 |
-
privateKey, err := crypto.HexToECDSA(PRIVATE_KEY)
|
| 674 |
-
if err != nil {
|
| 675 |
-
return fmt.Errorf("failed to parse private key: %v", err)
|
| 676 |
-
}
|
| 677 |
-
publicKey := privateKey.Public()
|
| 678 |
-
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
|
| 679 |
-
if !ok {
|
| 680 |
-
return fmt.Errorf("error converting public key")
|
| 681 |
-
}
|
| 682 |
-
fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
|
| 683 |
-
|
| 684 |
-
nonce, err := client.PendingNonceAt(context.Background(), fromAddress)
|
| 685 |
-
if err != nil {
|
| 686 |
-
return fmt.Errorf("failed to get nonce: %v", err)
|
| 687 |
-
}
|
| 688 |
-
gasLimit := uint64(300000)
|
| 689 |
-
gasPrice, err := client.SuggestGasPrice(context.Background())
|
| 690 |
-
if err != nil {
|
| 691 |
-
return fmt.Errorf("failed to get gas price: %v", err)
|
| 692 |
-
}
|
| 693 |
-
|
| 694 |
-
metadataJSON, err := json.Marshal(metadata)
|
| 695 |
-
if err != nil {
|
| 696 |
-
return fmt.Errorf("failed to marshal metadata: %v", err)
|
| 697 |
-
}
|
| 698 |
-
|
| 699 |
-
data, err := parsedABI.Pack("createRoom", roomId, name, string(metadataJSON))
|
| 700 |
-
if err != nil {
|
| 701 |
-
return fmt.Errorf("failed to pack transaction data: %v", err)
|
| 702 |
-
}
|
| 703 |
|
| 704 |
-
tx := types.NewTransaction(nonce, contractAddress, big.NewInt(0), gasLimit, gasPrice, data)
|
| 705 |
-
chainID := big.NewInt(97) // BSC Testnet chain ID
|
| 706 |
-
signedTx, err := types.SignTx(tx, types.NewLondonSigner(chainID), privateKey)
|
| 707 |
-
if err != nil {
|
| 708 |
-
return fmt.Errorf("failed to sign transaction: %v", err)
|
| 709 |
-
}
|
| 710 |
-
|
| 711 |
-
err = client.SendTransaction(context.Background(), signedTx)
|
| 712 |
-
if err != nil {
|
| 713 |
-
return fmt.Errorf("failed to send transaction: %v", err)
|
| 714 |
-
}
|
| 715 |
-
|
| 716 |
-
log.Printf("Transaction sent! Hash: %s", signedTx.Hash().Hex())
|
| 717 |
-
return nil
|
| 718 |
}
|
| 719 |
|
| 720 |
func inspectRooms(c *gin.Context) {
|
|
@@ -1859,7 +1781,7 @@ func main() {
|
|
| 1859 |
api := r.Group("/api", verifyToken)
|
| 1860 |
{
|
| 1861 |
// Match Express routes
|
| 1862 |
-
api.POST("/rooms", createRoom)
|
| 1863 |
api.GET("/rooms", getRooms)
|
| 1864 |
api.GET("/inspect-rooms", inspectRooms)
|
| 1865 |
api.POST("/rooms/:roomId/join", joinRoom)
|
|
@@ -1887,4 +1809,48 @@ func main() {
|
|
| 1887 |
if err := r.Run(":" + port); err != nil {
|
| 1888 |
log.Fatal("Failed to start server:", err)
|
| 1889 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1890 |
}
|
|
|
|
| 3 |
import (
|
| 4 |
"bytes"
|
| 5 |
"context"
|
|
|
|
| 6 |
"crypto/hmac"
|
| 7 |
"crypto/sha256"
|
| 8 |
"encoding/base64"
|
|
|
|
| 10 |
"fmt"
|
| 11 |
"io"
|
| 12 |
"log"
|
|
|
|
| 13 |
"net/http"
|
| 14 |
"os"
|
| 15 |
"strconv"
|
|
|
|
| 17 |
"sync"
|
| 18 |
"time"
|
| 19 |
|
| 20 |
+
"github.com/ethereum/go-ethereum"
|
| 21 |
"github.com/ethereum/go-ethereum/accounts/abi"
|
| 22 |
"github.com/ethereum/go-ethereum/common"
|
| 23 |
"github.com/ethereum/go-ethereum/core/types"
|
|
|
|
| 24 |
"github.com/ethereum/go-ethereum/ethclient"
|
| 25 |
"github.com/gin-gonic/gin"
|
| 26 |
"github.com/golang-jwt/jwt/v5"
|
|
|
|
| 612 |
|
| 613 |
// --- Route Handlers ---
|
| 614 |
|
| 615 |
+
func createRoom(c *gin.Context, roomId string, name string, metadata map[string]interface{}) {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 616 |
|
| 617 |
room := &Room{
|
| 618 |
RoomId: roomId, // Thêm trường này
|
| 619 |
+
Name: name,
|
| 620 |
+
Metadata: metadata,
|
| 621 |
Participants: []*Participant{},
|
| 622 |
CreatedAt: time.Now().Unix(),
|
| 623 |
}
|
|
|
|
| 626 |
rooms.m[roomId] = room
|
| 627 |
rooms.Unlock()
|
| 628 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 629 |
log.Printf("Room metadata: %s", room.Metadata)
|
| 630 |
|
| 631 |
// Trả về format giống Express
|
|
|
|
| 636 |
"participantCount": len(room.Participants),
|
| 637 |
"createdAt": room.CreatedAt,
|
| 638 |
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 639 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 640 |
}
|
| 641 |
|
| 642 |
func inspectRooms(c *gin.Context) {
|
|
|
|
| 1781 |
api := r.Group("/api", verifyToken)
|
| 1782 |
{
|
| 1783 |
// Match Express routes
|
| 1784 |
+
// api.POST("/rooms", createRoom)
|
| 1785 |
api.GET("/rooms", getRooms)
|
| 1786 |
api.GET("/inspect-rooms", inspectRooms)
|
| 1787 |
api.POST("/rooms/:roomId/join", joinRoom)
|
|
|
|
| 1809 |
if err := r.Run(":" + port); err != nil {
|
| 1810 |
log.Fatal("Failed to start server:", err)
|
| 1811 |
}
|
| 1812 |
+
|
| 1813 |
+
// Tạo Phòng và lắng nghe smrtract
|
| 1814 |
+
client, err := ethclient.Dial(RPC_URL)
|
| 1815 |
+
if err != nil {
|
| 1816 |
+
log.Fatalf("Không thể kết nối đến BSC Testnet: %v", err)
|
| 1817 |
+
}
|
| 1818 |
+
fmt.Println("Đã kết nối đến BSC Testnet!")
|
| 1819 |
+
|
| 1820 |
+
contractAddress := common.HexToAddress(CONTRACT_ADDRESS)
|
| 1821 |
+
query := ethereum.FilterQuery{
|
| 1822 |
+
Addresses: []common.Address{contractAddress},
|
| 1823 |
+
}
|
| 1824 |
+
|
| 1825 |
+
contractAbi, err := abi.JSON(strings.NewReader(ABI_JSON))
|
| 1826 |
+
if err != nil {
|
| 1827 |
+
log.Fatalf("Không thể phân tích ABI: %v", err)
|
| 1828 |
+
}
|
| 1829 |
+
|
| 1830 |
+
logs := make(chan types.Log)
|
| 1831 |
+
sub, err := client.SubscribeFilterLogs(context.Background(), query, logs)
|
| 1832 |
+
fmt.Println("Đã kết nối đến BSC Testnet!", sub)
|
| 1833 |
+
if err != nil {
|
| 1834 |
+
log.Fatalf("Không thể đăng ký lắng nghe sự kiện: %v", err)
|
| 1835 |
+
}
|
| 1836 |
+
fmt.Println("Đang lắng nghe sự kiện RoomCreated...")
|
| 1837 |
+
|
| 1838 |
+
type RoomCreatedEvent struct {
|
| 1839 |
+
RoomId string `abi:"roomId"`
|
| 1840 |
+
Name string `abi:"name"`
|
| 1841 |
+
Metadata string `abi:"metadata"`
|
| 1842 |
+
Owner common.Address `abi:"owner"`
|
| 1843 |
+
Timestamp int64 `abi:"timestamp"`
|
| 1844 |
+
IsActive bool `abi:"isActive"`
|
| 1845 |
+
}
|
| 1846 |
+
go func() {
|
| 1847 |
+
for eventLog := range logs {
|
| 1848 |
+
event := new(RoomCreatedEvent)
|
| 1849 |
+
if err := contractAbi.UnpackIntoInterface(event, "RoomCreated", eventLog.Data); err != nil {
|
| 1850 |
+
log.Printf("Lỗi giải mã sự kiện: %v", err)
|
| 1851 |
+
continue
|
| 1852 |
+
}
|
| 1853 |
+
fmt.Printf("Sự kiện RoomCreated: RoomId=%s, Name=%s, Owner=%s\n", event.RoomId, event.Name, event.Owner.Hex())
|
| 1854 |
+
}
|
| 1855 |
+
}()
|
| 1856 |
}
|