Implementación de la Función buyItem en Sway para Compra de Artículos

Resumen

Implementar la función buy_item en un smart contract escrito en Sway es uno de los pasos más completos al construir un marketplace descentralizado. Aquí descubres cómo validar pagos, actualizar estructuras y manejar comisiones, línea por línea, para que tu contrato funcione con seguridad y lógica clara.

Esta función concentra varias verificaciones críticas: tipo de token, monto enviado, validez del ítem y registro del comprador. Si estás aprendiendo Sway o desarrollas sobre Fuel, te conviene practicar escribiéndola tú mismo en tu editor mientras avanzas.

¿Qué hace la función buy_item en un smart contract de Sway?

La función buy_item permite que un usuario compre un ítem listado en el marketplace. Antes de cerrar la compra, el contrato valida que se cumplan las condiciones esperadas y luego actualiza el estado del contrato.

¿Qué es buy_item en Sway? Es una función pública que ejecuta la compra de un ítem en un smart contract, validando el tipo de token, el monto enviado y el item_id antes de transferir fondos al vendedor.

La función arranca con la anotación de acceso a storage para leer y escribir, porque vas a modificar el vector de compras y el mapa de ítems. Recibe un argumento llamado item_id de tipo u64, que identifica de manera única el ítem que se quiere comprar.

¿Cómo validar el asset_id que envía el comprador?

Lo primero es capturar el identificador del token enviado en la transacción. Para eso usas msg_asset_id, importado desde std::call_frames en la librería estándar de Sway.

sway let asset_id: ContractId = msg_asset_id(); require(asset_id == BASE_ASSET_ID, InvalidError::IncorrectAssetId);

La constante BASE_ASSET_ID viene de std::constants y te permite comparar contra el token oficial aceptado por el contrato. Si alguien intenta pagar con un token distinto al esperado, el contrato lanza el error IncorrectAssetId y aborta la transacción.

¿Cómo verificar que el monto enviado es suficiente?

Después necesitas saber cuánto envió el comprador. Para eso usas msg_amount, también de la librería estándar.

sway let amount: u64 = msg_amount();

Pero antes de comparar, necesitas saber el precio del ítem. Para obtenerlo, accedes al mapa de ítems con la clave item_id. Aquí declaras la variable como mutable con la palabra clave mut, porque más adelante actualizarás el campo total_bought del struct.

sway let mut item: Item = storage.item_map.get(item_id); require(item_id > 0, InvalidError::IncorrectItemId); require(amount >= item.price, InvalidError::NotEnoughTokens(amount));

El chequeo de item_id > 0 tiene una razón concreta: el contador de ítems se inicializa en cero y se incrementa al listar el primero, por lo que ningún ítem real tendrá ID cero. Si el monto enviado es menor al precio, el error NotEnoughTokens devuelve además la cantidad enviada para informar al usuario.

¿Cómo actualizar el estado del contrato después de la compra?

Una vez pasadas las validaciones, toca reflejar la compra en el estado del contrato. Esto implica dos actualizaciones: el struct del ítem y el vector de compras.

Primero actualizas el contador de ventas del ítem y reinsertas el valor en el mapa para que el cambio quede persistido.

sway item.total_bought += 1; storage.item_map.insert(item_id, item);

Luego registras quién hizo la compra. Para obtener la identidad del comprador usas msg_sender, que devuelve un Result envolviendo un Identity en éxito o un AuthError en fallo.

sway let sender: Result<Identity, AuthError> = msg_sender(); storage.purchases.push((item_id, sender.unwrap()));

El vector purchases almacena tuplas, donde cada elemento empareja el item_id con la identidad del comprador. El método .unwrap abre el Result y extrae el valor real, una sintaxis que se vuelve familiar con la práctica.

¿Por qué usar mut al obtener el ítem? Porque al comprarse, el campo total_bought del struct cambia. En Sway todas las variables son inmutables por defecto, así que necesitas mut para modificarlas.

¿Cómo manejar la comisión del marketplace?

El marketplace cobra una comisión, pero solo cuando el precio supera los 1,000 tokens. La regla es sencilla: por cada 100 monedas, el contrato se queda con 5, lo que equivale a dividir el monto entre 20.

sway if amount > 1000 { let commission: u64 = amount / 20; let new_amount: u64 = amount - commission; transfer(new_amount, asset_id, item.owner); } else { transfer(amount, asset_id, item.owner); }

La función transfer recibe tres parámetros: el monto a enviar, el asset_id y el destinatario. El destinatario sale de item.owner, una propiedad que se asignó cuando el vendedor listó el producto originalmente.

¿Qué conceptos clave aparecen en esta implementación?

En esta función se concentran varias piezas que valen la pena tener mapeadas para tu propio código.

  • Anotación de storage [0:40]: declara si la función lee, escribe o ambas sobre el almacenamiento del contrato.
  • msg_asset_id y msg_amount [2:30]: helpers de la librería estándar para acceder al token y monto de la transacción entrante.
  • require [3:10]: keyword para validar condiciones; si fallan, lanza un error y revierte la ejecución.
  • BASE_ASSET_ID [3:50]: constante de std::constants que representa el token base aceptado.
  • Mutabilidad con mut [5:30]: necesario para modificar structs, ya que Sway es inmutable por defecto.
  • storage.item_map.get e .insert [6:20]: métodos para leer y reescribir entradas del mapa.
  • msg_sender y .unwrap [9:40]: obtienes la identidad del comprador desenvolviendo el Result.
  • storage.purchases.push [10:20]: agrega dinámicamente una tupla (item_id, identity) al vector de compras.
  • transfer [12:00]: función que envía tokens al destinatario con el monto y asset_id indicados.

Un detalle importante sobre la lógica de comisión: la regla del 5% sobre montos mayores a 1,000 se calcula con una división simple por 20, lo que mantiene el código limpio y predecible.

Reto: rediseña la lógica de comisión

Ahora prueba algo distinto. En lugar de basar la comisión en el monto de tokens, escribe código que solo aplique comisión cuando un ítem ya se haya vendido más de X veces. Guarda tu versión en tu repo y comparte una captura de pantalla con tu propuesta. ¿Cómo lo resolverías tú?

      Implementación de la Función buyItem en Sway para Compra de Artículos