From 71ce7650564e9b91886b4f8aa1906c4032395ef1 Mon Sep 17 00:00:00 2001 From: Supreme2580 Date: Tue, 17 Dec 2024 21:06:01 +0100 Subject: [PATCH 1/4] implemented on contract --- onchain/src/canvas_factory.cairo | 28 +++++++------- onchain/src/multi_canvas.cairo | 63 +++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 36 deletions(-) diff --git a/onchain/src/canvas_factory.cairo b/onchain/src/canvas_factory.cairo index daccfd78..a4d302df 100644 --- a/onchain/src/canvas_factory.cairo +++ b/onchain/src/canvas_factory.cairo @@ -113,29 +113,27 @@ pub mod CanvasFactory { fn create_canvas( ref self: ContractState, init_params: super::Canvas::InitParams ) -> (ContractAddress, u64) { - // TODO: Serialize before calling this function to defer serialization to the contract input let mut init_params_serialized = array![]; init_params.serialize(ref init_params_serialized); let deploy_res = deploy_syscall( self.canvas_class_hash.read(), - self.canvas_count.read().into(), + get_caller_address().into(), init_params_serialized.span(), - true + false ); - if deploy_res.is_err() { - panic!("Failed to deploy canvas contract"); - } - let (addr, _response) = deploy_res.unwrap(); + let (canvas_address, _) = deploy_res.unwrap(); let canvas_id = self.canvas_count.read(); - self.canvases.write(canvas_id, addr); + self.canvases.write(canvas_id, canvas_address); self.canvas_count.write(canvas_id + 1); - self - .emit( - Event::CanvasCreated( - CanvasCreated { canvas_id, canvas_address: addr, init_params, } - ) - ); - (addr, canvas_id) + + // Auto-favorite the canvas for the creator + let caller = get_caller_address(); + self.canvas_favorites.write((canvas_id, caller), true); + self.emit(Event::CanvasFavorited(CanvasFavorited { canvas_id, user: caller })); + + // Emit the canvas created event + self.emit(Event::CanvasCreated(CanvasCreated { canvas_id, canvas_address, init_params })); + (canvas_address, canvas_id) } fn get_canvas(self: @ContractState, canvas_id: u64) -> ContractAddress { diff --git a/onchain/src/multi_canvas.cairo b/onchain/src/multi_canvas.cairo index 98344cb6..02f6faf6 100644 --- a/onchain/src/multi_canvas.cairo +++ b/onchain/src/multi_canvas.cairo @@ -113,6 +113,8 @@ pub mod MultiCanvas { stencil_counts: LegacyMap::, // Map: (canvas_id, stencil_id) -> stencil metadata stencils: LegacyMap::<(u32, u32), StencilMetadata>, + // Maps: (canvas_id, stencil_id, user addr) -> if favorited + stencil_favorites: LegacyMap::<(u32, u32, ContractAddress), bool> } #[event] @@ -296,19 +298,17 @@ pub mod MultiCanvas { assert(!self.unique_names.read(init_params.unique_name), 'Unique name already taken'); assert(validate_unique_name(init_params.unique_name), 'Invalid unique name'); let canvas_id = self.canvas_count.read(); - self - .canvases - .write( - canvas_id, - CanvasMetadata { - name: init_params.name, - unique_name: init_params.unique_name, - width: init_params.width, - height: init_params.height, - start_time: init_params.start_time, - end_time: init_params.end_time, - } - ); + self.canvases.write( + canvas_id, + CanvasMetadata { + name: init_params.name, + unique_name: init_params.unique_name, + width: init_params.width, + height: init_params.height, + start_time: init_params.start_time, + end_time: init_params.end_time, + } + ); self.hosts.write(canvas_id, init_params.host); self.time_between_pixels.write(canvas_id, init_params.time_between_pixels); let color_count = init_params.color_palette.len().try_into().unwrap(); @@ -316,16 +316,22 @@ pub mod MultiCanvas { let mut i: u8 = 0; while i < color_count { self.color_palettes.write((canvas_id, i), *init_params.color_palette.at(i.into())); - self - .emit( - CanvasColorAdded { - canvas_id, color_key: i, color: *init_params.color_palette.at(i.into()) - } - ); + self.emit( + CanvasColorAdded { + canvas_id, color_key: i, color: *init_params.color_palette.at(i.into()) + } + ); i += 1; }; self.canvas_count.write(canvas_id + 1); self.unique_names.write(init_params.unique_name, true); + + // Auto-favorite the canvas for the creator + let caller = get_caller_address(); + self.canvas_favorites.write((canvas_id, caller), true); + self.emit(Event::CanvasFavorited(CanvasFavorited { canvas_id, user: caller })); + + // Emit canvas created event self.emit(CanvasCreated { canvas_id, init_params }); canvas_id } @@ -489,6 +495,13 @@ pub mod MultiCanvas { assert(stencil.height <= MAX_STENCIL_SIZE, 'Stencil too large'); self.stencils.write((canvas_id, stencil_id), stencil.clone()); self.stencil_counts.write(canvas_id, stencil_id + 1); + + // Auto-favorite the stencil for the creator + let caller = get_caller_address(); + self.stencil_favorites.write((canvas_id, stencil_id, caller), true); + self.emit(StencilFavorited { canvas_id, stencil_id, user: caller }); + + // Emit the stencil added event self.emit(StencilAdded { canvas_id, stencil_id, stencil }); stencil_id } @@ -502,12 +515,20 @@ pub mod MultiCanvas { fn favorite_stencil(ref self: ContractState, canvas_id: u32, stencil_id: u32) { let caller = get_caller_address(); - self.emit(StencilFavorited { canvas_id, stencil_id, user: caller, }); + if self.stencil_favorites.read((canvas_id, stencil_id, caller)) { + return; + } + self.stencil_favorites.write((canvas_id, stencil_id, caller), true); + self.emit(StencilFavorited { canvas_id, stencil_id, user: caller }); } fn unfavorite_stencil(ref self: ContractState, canvas_id: u32, stencil_id: u32) { let caller = get_caller_address(); - self.emit(StencilUnfavorited { canvas_id, stencil_id, user: caller, }); + if !self.stencil_favorites.read((canvas_id, stencil_id, caller)) { + return; + } + self.stencil_favorites.write((canvas_id, stencil_id, caller), false); + self.emit(StencilUnfavorited { canvas_id, stencil_id, user: caller }); } } From df5da9e5dbcd290cfafc27d6c1483f0c2c367d78 Mon Sep 17 00:00:00 2001 From: Supreme2580 Date: Wed, 18 Dec 2024 01:04:58 +0100 Subject: [PATCH 2/4] backend --- backend/routes/stencils.go | 17 ++++++++++-- backend/routes/worlds.go | 53 ++++++++++++++++++++++++++++++++++---- 2 files changed, 63 insertions(+), 7 deletions(-) diff --git a/backend/routes/stencils.go b/backend/routes/stencils.go index b8c60e92..2830d3ff 100644 --- a/backend/routes/stencils.go +++ b/backend/routes/stencils.go @@ -6,6 +6,7 @@ import ( "image/color" "image/png" "io" + "log" "net/http" "os" "os/exec" @@ -589,16 +590,28 @@ func addStencilDevnet(w http.ResponseWriter, r *http.Request) { return } + // Add the stencil shellCmd := core.ArtPeaceBackend.BackendConfig.Scripts.AddStencilDevnet contract := os.Getenv("CANVAS_FACTORY_CONTRACT_ADDRESS") cmd := exec.Command(shellCmd, contract, "add_stencil", strconv.Itoa(worldId), hash, strconv.Itoa(width), strconv.Itoa(height), strconv.Itoa(position)) - _, err = cmd.Output() + output, err := cmd.CombinedOutput() if err != nil { + log.Printf("Add stencil command failed: %v\nOutput: %s\nCommand: %v", err, string(output), cmd.String()) routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to add stencil to devnet") return } - routeutils.WriteResultJson(w, "Stencil added to devnet") + // Favorite the newly created stencil + shellCmd = core.ArtPeaceBackend.BackendConfig.Scripts.FavoriteStencilDevnet + cmd = exec.Command(shellCmd, contract, "favorite_stencil", strconv.Itoa(worldId), strconv.Itoa(position)) + output, err = cmd.CombinedOutput() + if err != nil { + log.Printf("Favorite stencil command failed: %v\nOutput: %s\nCommand: %v", err, string(output), cmd.String()) + routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to favorite newly created stencil") + return + } + + routeutils.WriteResultJson(w, "Stencil added and favorited") } func removeStencilDevnet(w http.ResponseWriter, r *http.Request) { diff --git a/backend/routes/worlds.go b/backend/routes/worlds.go index cc62a700..94e042b5 100644 --- a/backend/routes/worlds.go +++ b/backend/routes/worlds.go @@ -2,6 +2,8 @@ package routes import ( "context" + "fmt" + "log" "net/http" "os" "os/exec" @@ -540,13 +542,24 @@ func createCanvasDevnet(w http.ResponseWriter, r *http.Request) { contract := os.Getenv("CANVAS_FACTORY_CONTRACT_ADDRESS") cmd := exec.Command(shellCmd, contract, "create_canvas", host, name, uniqueName, strconv.Itoa(width), strconv.Itoa(height), strconv.Itoa(timer), strconv.Itoa(len(palette)), paletteInput, strconv.Itoa(startTime), strconv.Itoa(endTime)) - _, err = cmd.Output() + output, err := cmd.CombinedOutput() + if err != nil { + log.Printf("Create canvas command failed: %v\nOutput: %s\nCommand: %v", err, string(output), cmd.String()) + routeutils.WriteErrorJson(w, http.StatusInternalServerError, fmt.Sprintf("Failed to create canvas: %v", err)) + return + } + + // Favorite the newly created canvas + shellCmd = core.ArtPeaceBackend.BackendConfig.Scripts.FavoriteWorldDevnet + cmd = exec.Command(shellCmd, contract, "favorite_canvas", uniqueName) + output, err = cmd.CombinedOutput() if err != nil { - routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to create canvas") + log.Printf("Favorite canvas command failed: %v\nOutput: %s\nCommand: %v", err, string(output), cmd.String()) + routeutils.WriteErrorJson(w, http.StatusInternalServerError, fmt.Sprintf("Failed to favorite newly created canvas: %v", err)) return } - routeutils.WriteResultJson(w, "Canvas created") + routeutils.WriteResultJson(w, "Canvas created and favorited") } func favoriteWorldDevnet(w http.ResponseWriter, r *http.Request) { @@ -561,7 +574,22 @@ func favoriteWorldDevnet(w http.ResponseWriter, r *http.Request) { return } - worldId := (*jsonBody)["worldId"] + // Try to get worldId either directly or from worldName + var worldId string + if (*jsonBody)["worldId"] != "" { + worldId = (*jsonBody)["worldId"] + } else if (*jsonBody)["worldName"] != "" { + // Get worldId from worldName + id, err := core.PostgresQueryOne[int]("SELECT world_id FROM worlds WHERE unique_name = $1", (*jsonBody)["worldName"]) + if err != nil { + routeutils.WriteErrorJson(w, http.StatusBadRequest, "Invalid world name") + return + } + worldId = strconv.Itoa(*id) + } else { + routeutils.WriteErrorJson(w, http.StatusBadRequest, "Must provide either worldId or worldName") + return + } shellCmd := core.ArtPeaceBackend.BackendConfig.Scripts.FavoriteWorldDevnet contract := os.Getenv("CANVAS_FACTORY_CONTRACT_ADDRESS") @@ -588,7 +616,22 @@ func unfavoriteWorldDevnet(w http.ResponseWriter, r *http.Request) { return } - worldId := (*jsonBody)["worldId"] + // Try to get worldId either directly or from worldName + var worldId string + if (*jsonBody)["worldId"] != "" { + worldId = (*jsonBody)["worldId"] + } else if (*jsonBody)["worldName"] != "" { + // Get worldId from worldName + id, err := core.PostgresQueryOne[int]("SELECT world_id FROM worlds WHERE unique_name = $1", (*jsonBody)["worldName"]) + if err != nil { + routeutils.WriteErrorJson(w, http.StatusBadRequest, "Invalid world name") + return + } + worldId = strconv.Itoa(*id) + } else { + routeutils.WriteErrorJson(w, http.StatusBadRequest, "Must provide either worldId or worldName") + return + } shellCmd := core.ArtPeaceBackend.BackendConfig.Scripts.UnfavoriteWorldDevnet contract := os.Getenv("CANVAS_FACTORY_CONTRACT_ADDRESS") From d8c31c9568acdc12aa1ff33dc0aede0046354761 Mon Sep 17 00:00:00 2001 From: Supreme2580 Date: Wed, 18 Dec 2024 10:31:52 +0100 Subject: [PATCH 3/4] scarb fmt --- onchain/src/canvas_factory.cairo | 9 ++++--- onchain/src/multi_canvas.cairo | 43 +++++++++++++++++--------------- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/onchain/src/canvas_factory.cairo b/onchain/src/canvas_factory.cairo index a4d302df..4dcc4462 100644 --- a/onchain/src/canvas_factory.cairo +++ b/onchain/src/canvas_factory.cairo @@ -125,14 +125,17 @@ pub mod CanvasFactory { let canvas_id = self.canvas_count.read(); self.canvases.write(canvas_id, canvas_address); self.canvas_count.write(canvas_id + 1); - + // Auto-favorite the canvas for the creator let caller = get_caller_address(); self.canvas_favorites.write((canvas_id, caller), true); self.emit(Event::CanvasFavorited(CanvasFavorited { canvas_id, user: caller })); - + // Emit the canvas created event - self.emit(Event::CanvasCreated(CanvasCreated { canvas_id, canvas_address, init_params })); + self + .emit( + Event::CanvasCreated(CanvasCreated { canvas_id, canvas_address, init_params }) + ); (canvas_address, canvas_id) } diff --git a/onchain/src/multi_canvas.cairo b/onchain/src/multi_canvas.cairo index 02f6faf6..11a403fa 100644 --- a/onchain/src/multi_canvas.cairo +++ b/onchain/src/multi_canvas.cairo @@ -298,17 +298,19 @@ pub mod MultiCanvas { assert(!self.unique_names.read(init_params.unique_name), 'Unique name already taken'); assert(validate_unique_name(init_params.unique_name), 'Invalid unique name'); let canvas_id = self.canvas_count.read(); - self.canvases.write( - canvas_id, - CanvasMetadata { - name: init_params.name, - unique_name: init_params.unique_name, - width: init_params.width, - height: init_params.height, - start_time: init_params.start_time, - end_time: init_params.end_time, - } - ); + self + .canvases + .write( + canvas_id, + CanvasMetadata { + name: init_params.name, + unique_name: init_params.unique_name, + width: init_params.width, + height: init_params.height, + start_time: init_params.start_time, + end_time: init_params.end_time, + } + ); self.hosts.write(canvas_id, init_params.host); self.time_between_pixels.write(canvas_id, init_params.time_between_pixels); let color_count = init_params.color_palette.len().try_into().unwrap(); @@ -316,21 +318,22 @@ pub mod MultiCanvas { let mut i: u8 = 0; while i < color_count { self.color_palettes.write((canvas_id, i), *init_params.color_palette.at(i.into())); - self.emit( - CanvasColorAdded { - canvas_id, color_key: i, color: *init_params.color_palette.at(i.into()) - } - ); + self + .emit( + CanvasColorAdded { + canvas_id, color_key: i, color: *init_params.color_palette.at(i.into()) + } + ); i += 1; }; self.canvas_count.write(canvas_id + 1); self.unique_names.write(init_params.unique_name, true); - + // Auto-favorite the canvas for the creator let caller = get_caller_address(); self.canvas_favorites.write((canvas_id, caller), true); self.emit(Event::CanvasFavorited(CanvasFavorited { canvas_id, user: caller })); - + // Emit canvas created event self.emit(CanvasCreated { canvas_id, init_params }); canvas_id @@ -495,12 +498,12 @@ pub mod MultiCanvas { assert(stencil.height <= MAX_STENCIL_SIZE, 'Stencil too large'); self.stencils.write((canvas_id, stencil_id), stencil.clone()); self.stencil_counts.write(canvas_id, stencil_id + 1); - + // Auto-favorite the stencil for the creator let caller = get_caller_address(); self.stencil_favorites.write((canvas_id, stencil_id, caller), true); self.emit(StencilFavorited { canvas_id, stencil_id, user: caller }); - + // Emit the stencil added event self.emit(StencilAdded { canvas_id, stencil_id, stencil }); stencil_id From db46f6ab72398f29844967a58996ccc58d04432f Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Thu, 19 Dec 2024 10:43:08 -0600 Subject: [PATCH 4/4] Cleanup changes --- backend/routes/stencils.go | 115 ++++++++++++++++++++++++++----- backend/routes/worlds.go | 53 ++------------ onchain/src/canvas_factory.cairo | 25 ++++--- onchain/src/multi_canvas.cairo | 7 +- 4 files changed, 118 insertions(+), 82 deletions(-) diff --git a/backend/routes/stencils.go b/backend/routes/stencils.go index 2830d3ff..2f1f48c4 100644 --- a/backend/routes/stencils.go +++ b/backend/routes/stencils.go @@ -1,12 +1,13 @@ package routes import ( + "bytes" + "encoding/json" "fmt" "image" "image/color" "image/png" "io" - "log" "net/http" "os" "os/exec" @@ -27,6 +28,7 @@ func InitStencilsRoutes() { http.HandleFunc("/get-hot-stencils", getHotStencils) http.HandleFunc("/add-stencil-img", addStencilImg) http.HandleFunc("/add-stencil-data", addStencilData) + http.HandleFunc("/get-stencil-pixel-data", getStencilPixelData) if !core.ArtPeaceBackend.BackendConfig.Production { http.HandleFunc("/add-stencil-devnet", addStencilDevnet) http.HandleFunc("/remove-stencil-devnet", removeStencilDevnet) @@ -403,7 +405,7 @@ func addStencilImg(w http.ResponseWriter, r *http.Request) { r.Body.Close() - imageData, err := imageToPixelData(fileBytes, 1) + imageData, err := worldImageToPixelData(fileBytes, 1, 0) if err != nil { routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to convert image to pixel data") return @@ -590,28 +592,16 @@ func addStencilDevnet(w http.ResponseWriter, r *http.Request) { return } - // Add the stencil shellCmd := core.ArtPeaceBackend.BackendConfig.Scripts.AddStencilDevnet contract := os.Getenv("CANVAS_FACTORY_CONTRACT_ADDRESS") cmd := exec.Command(shellCmd, contract, "add_stencil", strconv.Itoa(worldId), hash, strconv.Itoa(width), strconv.Itoa(height), strconv.Itoa(position)) - output, err := cmd.CombinedOutput() + _, err = cmd.Output() if err != nil { - log.Printf("Add stencil command failed: %v\nOutput: %s\nCommand: %v", err, string(output), cmd.String()) routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to add stencil to devnet") return } - // Favorite the newly created stencil - shellCmd = core.ArtPeaceBackend.BackendConfig.Scripts.FavoriteStencilDevnet - cmd = exec.Command(shellCmd, contract, "favorite_stencil", strconv.Itoa(worldId), strconv.Itoa(position)) - output, err = cmd.CombinedOutput() - if err != nil { - log.Printf("Favorite stencil command failed: %v\nOutput: %s\nCommand: %v", err, string(output), cmd.String()) - routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to favorite newly created stencil") - return - } - - routeutils.WriteResultJson(w, "Stencil added and favorited") + routeutils.WriteResultJson(w, "Stencil added to devnet") } func removeStencilDevnet(w http.ResponseWriter, r *http.Request) { @@ -721,3 +711,96 @@ func unfavoriteStencilDevnet(w http.ResponseWriter, r *http.Request) { routeutils.WriteResultJson(w, "Stencil unfavorited in devnet") } + +func worldImageToPixelData(imageData []byte, scaleFactor int, worldId int) ([]int, error) { + img, _, err := image.Decode(bytes.NewReader(imageData)) + if err != nil { + return nil, err + } + + colors, err := core.PostgresQuery[ColorType]("SELECT hex FROM WorldsColors WHERE world_id = $1 ORDER BY color_key", worldId) + if err != nil { + return nil, err + } + + colorCount := len(colors) + palette := make([]color.Color, colorCount) + for i := 0; i < colorCount; i++ { + colorHex := colors[i] + palette[i] = hexToRGBA(colorHex) + } + + bounds := img.Bounds() + width, height := bounds.Max.X, bounds.Max.Y + scaledWidth := width / scaleFactor + scaledHeight := height / scaleFactor + pixelData := make([]int, scaledWidth*scaledHeight) + + for y := 0; y < height; y += scaleFactor { + for x := 0; x < width; x += scaleFactor { + newX := x / scaleFactor + newY := y / scaleFactor + rgba := color.RGBAModel.Convert(img.At(x, y)).(color.RGBA) + if rgba.A < 128 { // Consider pixels with less than 50% opacity as transparent + pixelData[newY*scaledWidth+newX] = 0xFF + } else { + closestIndex := findClosestColor(rgba, palette) + pixelData[newY*scaledWidth+newX] = closestIndex + } + } + } + + return pixelData, nil +} + +func getStencilPixelData(w http.ResponseWriter, r *http.Request) { + // Get stencil hash from query params + hash := r.URL.Query().Get("hash") + if hash == "" { + routeutils.WriteErrorJson(w, http.StatusBadRequest, "Hash parameter is required") + return + } + + // Read the stencil image file + filename := fmt.Sprintf("stencils/stencil-%s.png", hash) + fileBytes, err := os.ReadFile(filename) + if err != nil { + routeutils.WriteErrorJson(w, http.StatusNotFound, "Stencil not found") + return + } + + // Convert image to pixel data + pixelData, err := worldImageToPixelData(fileBytes, 1, 0) + if err != nil { + routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to process image") + return + } + + // Get image dimensions + img, _, err := image.Decode(bytes.NewReader(fileBytes)) + if err != nil { + routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to decode image") + return + } + bounds := img.Bounds() + width, height := bounds.Max.X, bounds.Max.Y + + // Create response structure + response := struct { + Width int `json:"width"` + Height int `json:"height"` + PixelData []int `json:"pixelData"` + }{ + Width: width, + Height: height, + PixelData: pixelData, + } + + jsonResponse, err := json.Marshal(response) + if err != nil { + routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to create response") + return + } + + routeutils.WriteDataJson(w, string(jsonResponse)) +} diff --git a/backend/routes/worlds.go b/backend/routes/worlds.go index 94e042b5..cc62a700 100644 --- a/backend/routes/worlds.go +++ b/backend/routes/worlds.go @@ -2,8 +2,6 @@ package routes import ( "context" - "fmt" - "log" "net/http" "os" "os/exec" @@ -542,24 +540,13 @@ func createCanvasDevnet(w http.ResponseWriter, r *http.Request) { contract := os.Getenv("CANVAS_FACTORY_CONTRACT_ADDRESS") cmd := exec.Command(shellCmd, contract, "create_canvas", host, name, uniqueName, strconv.Itoa(width), strconv.Itoa(height), strconv.Itoa(timer), strconv.Itoa(len(palette)), paletteInput, strconv.Itoa(startTime), strconv.Itoa(endTime)) - output, err := cmd.CombinedOutput() - if err != nil { - log.Printf("Create canvas command failed: %v\nOutput: %s\nCommand: %v", err, string(output), cmd.String()) - routeutils.WriteErrorJson(w, http.StatusInternalServerError, fmt.Sprintf("Failed to create canvas: %v", err)) - return - } - - // Favorite the newly created canvas - shellCmd = core.ArtPeaceBackend.BackendConfig.Scripts.FavoriteWorldDevnet - cmd = exec.Command(shellCmd, contract, "favorite_canvas", uniqueName) - output, err = cmd.CombinedOutput() + _, err = cmd.Output() if err != nil { - log.Printf("Favorite canvas command failed: %v\nOutput: %s\nCommand: %v", err, string(output), cmd.String()) - routeutils.WriteErrorJson(w, http.StatusInternalServerError, fmt.Sprintf("Failed to favorite newly created canvas: %v", err)) + routeutils.WriteErrorJson(w, http.StatusInternalServerError, "Failed to create canvas") return } - routeutils.WriteResultJson(w, "Canvas created and favorited") + routeutils.WriteResultJson(w, "Canvas created") } func favoriteWorldDevnet(w http.ResponseWriter, r *http.Request) { @@ -574,22 +561,7 @@ func favoriteWorldDevnet(w http.ResponseWriter, r *http.Request) { return } - // Try to get worldId either directly or from worldName - var worldId string - if (*jsonBody)["worldId"] != "" { - worldId = (*jsonBody)["worldId"] - } else if (*jsonBody)["worldName"] != "" { - // Get worldId from worldName - id, err := core.PostgresQueryOne[int]("SELECT world_id FROM worlds WHERE unique_name = $1", (*jsonBody)["worldName"]) - if err != nil { - routeutils.WriteErrorJson(w, http.StatusBadRequest, "Invalid world name") - return - } - worldId = strconv.Itoa(*id) - } else { - routeutils.WriteErrorJson(w, http.StatusBadRequest, "Must provide either worldId or worldName") - return - } + worldId := (*jsonBody)["worldId"] shellCmd := core.ArtPeaceBackend.BackendConfig.Scripts.FavoriteWorldDevnet contract := os.Getenv("CANVAS_FACTORY_CONTRACT_ADDRESS") @@ -616,22 +588,7 @@ func unfavoriteWorldDevnet(w http.ResponseWriter, r *http.Request) { return } - // Try to get worldId either directly or from worldName - var worldId string - if (*jsonBody)["worldId"] != "" { - worldId = (*jsonBody)["worldId"] - } else if (*jsonBody)["worldName"] != "" { - // Get worldId from worldName - id, err := core.PostgresQueryOne[int]("SELECT world_id FROM worlds WHERE unique_name = $1", (*jsonBody)["worldName"]) - if err != nil { - routeutils.WriteErrorJson(w, http.StatusBadRequest, "Invalid world name") - return - } - worldId = strconv.Itoa(*id) - } else { - routeutils.WriteErrorJson(w, http.StatusBadRequest, "Must provide either worldId or worldName") - return - } + worldId := (*jsonBody)["worldId"] shellCmd := core.ArtPeaceBackend.BackendConfig.Scripts.UnfavoriteWorldDevnet contract := os.Getenv("CANVAS_FACTORY_CONTRACT_ADDRESS") diff --git a/onchain/src/canvas_factory.cairo b/onchain/src/canvas_factory.cairo index 4dcc4462..daccfd78 100644 --- a/onchain/src/canvas_factory.cairo +++ b/onchain/src/canvas_factory.cairo @@ -113,30 +113,29 @@ pub mod CanvasFactory { fn create_canvas( ref self: ContractState, init_params: super::Canvas::InitParams ) -> (ContractAddress, u64) { + // TODO: Serialize before calling this function to defer serialization to the contract input let mut init_params_serialized = array![]; init_params.serialize(ref init_params_serialized); let deploy_res = deploy_syscall( self.canvas_class_hash.read(), - get_caller_address().into(), + self.canvas_count.read().into(), init_params_serialized.span(), - false + true ); - let (canvas_address, _) = deploy_res.unwrap(); + if deploy_res.is_err() { + panic!("Failed to deploy canvas contract"); + } + let (addr, _response) = deploy_res.unwrap(); let canvas_id = self.canvas_count.read(); - self.canvases.write(canvas_id, canvas_address); + self.canvases.write(canvas_id, addr); self.canvas_count.write(canvas_id + 1); - - // Auto-favorite the canvas for the creator - let caller = get_caller_address(); - self.canvas_favorites.write((canvas_id, caller), true); - self.emit(Event::CanvasFavorited(CanvasFavorited { canvas_id, user: caller })); - - // Emit the canvas created event self .emit( - Event::CanvasCreated(CanvasCreated { canvas_id, canvas_address, init_params }) + Event::CanvasCreated( + CanvasCreated { canvas_id, canvas_address: addr, init_params, } + ) ); - (canvas_address, canvas_id) + (addr, canvas_id) } fn get_canvas(self: @ContractState, canvas_id: u64) -> ContractAddress { diff --git a/onchain/src/multi_canvas.cairo b/onchain/src/multi_canvas.cairo index 11a403fa..676b12af 100644 --- a/onchain/src/multi_canvas.cairo +++ b/onchain/src/multi_canvas.cairo @@ -328,14 +328,12 @@ pub mod MultiCanvas { }; self.canvas_count.write(canvas_id + 1); self.unique_names.write(init_params.unique_name, true); + self.emit(CanvasCreated { canvas_id, init_params }); // Auto-favorite the canvas for the creator let caller = get_caller_address(); self.canvas_favorites.write((canvas_id, caller), true); self.emit(Event::CanvasFavorited(CanvasFavorited { canvas_id, user: caller })); - - // Emit canvas created event - self.emit(CanvasCreated { canvas_id, init_params }); canvas_id } @@ -498,14 +496,13 @@ pub mod MultiCanvas { assert(stencil.height <= MAX_STENCIL_SIZE, 'Stencil too large'); self.stencils.write((canvas_id, stencil_id), stencil.clone()); self.stencil_counts.write(canvas_id, stencil_id + 1); + self.emit(StencilAdded { canvas_id, stencil_id, stencil }); // Auto-favorite the stencil for the creator let caller = get_caller_address(); self.stencil_favorites.write((canvas_id, stencil_id, caller), true); self.emit(StencilFavorited { canvas_id, stencil_id, user: caller }); - // Emit the stencil added event - self.emit(StencilAdded { canvas_id, stencil_id, stencil }); stencil_id }