Ariela Wenner
EstudianteJean Nuñez
EstudianteCristian Alexis Zambrano Badillo
ProfesorJean Nuñez
EstudianteAriela Wenner
EstudianteCristian Alexis Zambrano Badillo
ProfesorEber Laurente Lliuyacc
EstudianteEduwin Celiano Ricardo Chavarro
EstudianteSergio Martinez Marin
EstudianteEdward Rodriguez
EstudianteJuan David Díaz Pastrana
EstudianteSolución equivalente un poquito más concisa :3
pub fn obtener_memes_museo(&self, nombre_museo: String) -> Vec<Meme> { // con map_or_else evitamos alojar un nuevo vector de no ser necesario self.museos.get(&nombre_museo).map_or_else(Vec::new, |m| { // filtramos y mapeamos en una sola llamada los memes existentes // es decir, si self.memes.get(...) devuelve None, esto no se incluye m.iter().filter_map(|id| self.memes.get(id)).collect() }) }
yoctonear 1a la 24
Y es muy útil para tener un numero super exacto, aunque aveces es difícil de escribirlo en la consola jajaja :grin:
Un vector para añadir datos usamos el push
Pregunta, según la definición de un Meme, sería posible que se haga más de una llamada al método crear_meme en un mismo bloque?
Y de ser así, no puede pasar que ese ID entonces deje de ser único ya que se usa el número de bloque como tal, y se sobreescriban Memes?
Si así es 🙌🏻 super bien analizado! Pensando en que esta fuera una dApp muy demandada podría pasar. Ya que si hubieran 2 transacciones en un mismo bloque todas estas tomarían como referencia el mismo número de bloque.
El tema de la aleatoriedad es compleja en blockchain en general ya que estos son sistemas deterministas.
Para un ejemplo como este es útil, pero para una aplicación compleja podríamos utilizar oráculos o llevar un contador como id :fire:
Profesor, me sale error en la obención del account_id desde &meme.creado_por
Promise::new(String::from(&meme.creado_por)) .transfer(env::attached_deposit());
tambien me sale el mismo error
lo pudiste resolver?
De premio de consolación: Temporalmente, si se deja la versión del near-dsk en 3.1.0 funciona.
Con la version 4.1.1 o superiores toca ver como dejar la estructura creado por como AccountID y no un string o buscar como pasar Strings a AccountID ( un cast o conversión)
28/01/2024
Bueno bebés hermosos, presten atención, para aquellos compas que les esté dando problema el cargo build, mas específicamente lo siguiente:
error: no matching package named parity-secp256k1 found
location searched: registry crates-io
required by package near-crypto v0.14.0
... which satisfies dependency `near-crypto = "^0.14"` of package `near-sdk v4.1.1`
Deben agregar lo siguiente al
cargo.toml
[package]
name = "museo_memes"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at
[lib]
crate-type = ["cdylib", "rlib"] # más para rust que para near
[dependencies]
near-sdk = "3.1.0"
[patch.crates-io]
parity-secp256k1 = { git = "https://github.com/paritytech/rust-secp256k1/", version = "0.7.0" }
y para el lib.rs:
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};use near_sdk::collections::UnorderedMap;use near_sdk::serde::{Deserialize, Serialize};use near_sdk::{env, near_bindgen, setup_alloc, Promise};
setup_alloc!(); //alocar dirección de memoria
/*Clases necesarias para el contratoimplementamos serde cuando necesitamos retornar la estructuracli y frontend. En este caso se usan ambas serializaciones yaque la serialización y desearializacipon del contrato en la blockchain de near usar los borsh para optimizacion y los normales para parsear jsons*/
#[derive(Serialize, Deserialize, BorshSerialize, BorshDeserialize)]#[serde(crate = "near_sdk::serde")]pub struct Meme { pub id: u64, pub creado_por: String, pub titulo: String, pub museo: String, pub url: String, pub donaciones: u128,}
//implementación del trait Default para inicializar la estructuraimpl Default for Meme { fn default() -> Self { Meme { id: 0, creado_por: String::from(""), titulo: String::from(""), museo: String::from(""), url: String::from(""), donaciones: 0, } }}
//implementación del método new que permitirá crear nuevos memesimpl Meme { pub fn new(titulo: String, url: String, museo: String) -> Self { Self { id: env::block_index(), // env::block_height(), //env::block_index(), //id:0 creado_por: env::signer_account_id().to_string(), titulo, museo, url, donaciones: 0, } }}
//1. estructura, state del contrato e inicialización de variables#[near_bindgen]#[derive(BorshDeserialize, BorshSerialize)]
pub struct SimpleMemeMuseum { //Guardamos solo los ID para evitar tener que editar en ambos museos: UnorderedMap<String, Vec<u64>>, memes: UnorderedMap<u64, Meme>,}
//inicializamos el state del contratoimpl Default for SimpleMemeMuseum { fn default() -> Self { Self { //Inicializamos las colecciones museos: UnorderedMap::new(b"u".to_vec()), memes: UnorderedMap::new(b"e".to_vec()), } }}
//Métodos
impl SimpleMemeMuseum { pub fn <u>crear_meme</u>(&mut <u>self</u>, titulo: String, url: String, nombre_museo: String) { //crear el objeto meme: let meme = Meme::new( String::from(&titulo), String::from(&url), String::from(&nombre_museo), );
//Lo guardamos en la colección de memes <u>self</u>.memes.<u>insert</u>(&meme.id, &meme);
//Buscamos si el museo eiste para despues añadir el meme en el. La función get //El valor de un key dado como un Option<Vec<u64>> como el vector de museos
let museo = <u>self</u>.museos.get(&nombre_museo); //si eiste el museo entonces is_some() retornará true y agregamos el nuevo Id de ese museo
if museo.is_some() { //m almacena el valor del some() del option<> o da un panic en caso de ser nulo let mut <u>m</u> = museo.unwrap(); //m al ser un vector hacemos un push para almacenar el dato <u>m</u>.<u>push</u>(meme.id);
//insertamos en la colección de museos el museo y el meme ligado a él. <u>self</u>.museos.<u>insert</u>(&nombre_museo, &<u>m</u>); } //si no existe, creamos un nuevo museo, le agregamos el meme y lo guardamos. else { let mut <u>nuevo_museo</u> = Vec::new(); <u>nuevo_museo</u>.<u>push</u>(meme.id); <u>self</u>.museos.<u>insert</u>(&nombre_museo, &<u>nuevo_museo</u>); }
//Manda un mensaje a la terminal al ejecutar el método: env::log( format!( "Nuevo meme añadido con éito, Museo: {}, Id Meme: {}", &nombre_museo, meme.id ) .as_bytes(), ); } pub fn obtener_meme(&self, id: u64) -> Option<Meme> { //el option retorna un some o null, entonces con este método veremos si eiste o no self.memes.get(&id) } pub fn obtener_lista_memes(&self) -> Vec<(u64, Meme)> { self.memes.to_vec() } pub fn obtener_lista_museos(&self) -> Vec<String> { self.museos.keys_as_vector().to_vec() } pub fn obtener_memes_museo(&self, nombre_museo: String) -> Vec<Meme> { let museo = self.museos.get(&nombre_museo); //Si el museo existe: if museo.is_some() { let mut <u>lista_memes</u> = Vec::new();
//el for recorre cada elemento en el museo: for meme in &museo.unwrap() { //obtenemos el meme mediante su id let m = self.memes.get(meme);
//si el meme existe if m.is_some() { //mandamos el meme al vector de la lista de memes <u>lista_memes</u>.<u>push</u>(m.unwrap()); } } //retornamos la lista de memes <u>lista_memes</u> //si no existe el museo } else { //creamos el vector vacio de memes Vec::new() } }
//#[payable] pub fn <u>donar_a_meme</u>(&mut <u>self</u>, id: u64) -> bool { assert!( env::attached_deposit() > 0, "Debes agregar NEAR para hacer una donación." );
//Buscamos el meme match <u>self</u>.memes.get(&id) { //analizamos si el meme eiste y mandamos el valor mutable de la colección Some(mut <u>meme</u>) => { //si eiste guardamos la donación en el registro <u>meme</u>.donaciones <u>+=</u> env::attached_deposit(); <u>self</u>.memes.<u>insert</u>(&<u>meme</u>.id, &<u>meme</u>); //y le transferimos al creador del meme lo que donaron Promise::new(String::from(&<u>meme</u>.creado_por)).transfer(env::attached_deposit()); true } None => false, } }}
y voila, salu2.
const NEAR: u128 = 10u128.pow(24); // Yocto-near