Sui.

Explorar

Conéctate con comunidades y descubre nuevas ideas.

Sui.X.Peera.

Gana tu parte de 1000 Sui

Gana puntos de reputación y obtén recompensas por ayudar a crecer a la comunidad de Sui.

Comunidades

Recompensa

  • Xavier.eth.Peera.
    ParaSuiJun 17, 2025
    +15

    ¿Cómo interactúan las restricciones de capacidad con los campos dinámicos en colecciones heterogéneas?

    Estoy creando un mercado que necesita gestionar varios tipos de activos con diferentes requisitos de capacidad, y me he planteado algunas preguntas fundamentales sobre el sistema de tipos de Move. Quiero almacenar diferentes tipos de activos en la misma colección, pero tienen diferentes capacidades: NFT normales: key + store(transferibles) Tokens Soulbound: key únicamente (no transferibles) Activos personalizados con restricciones de transferencia public struct Marketplace has key { id: UID, listings: Bag, // Want to store different asset types here } // This works for transferable assets public fun list_transferable( marketplace: &mut Marketplace, asset: T, price: u64 ) { /* ... */ } // But how to handle soulbound assets? public fun list_soulbound( // No store ability marketplace: &mut Marketplace, asset_ref: &T, // Can only take reference price: u64 ) { /* How do I store metadata about this? */ } Preguntas clave: Requisitos de habilidad: Cuando se usadynamic_field::add(), ¿Vsiempre se necesita store en tiempo de compilación? ¿Pueden los tipos de contenedores solucionar esto? Almacenamiento heterogéneo: ¿puede una sola bolsa almacenar objetos con diferentes conjuntos de habilidades (key + store + copycontrakey + store) y manipularlos de forma diferente durante el tiempo de ejecución? Seguridad de tipos: dado que los campos dinámicos eliminan los tipos, ¿cómo puedo mantener la seguridad de los tipos al recuperar los valores? ¿Cuál es el patrón para almacenar los metadatos de tipo? Patrón de testigos: ¿Cómo funcionan las restricciones de habilidad con los tipos de fantasmas? ¿Puedo AssetAssetguardarlos en la misma colección y extraer la información de tipos más adelante? Construir un sistema en el que los NFT, los tokens de soul bound y los activos restringidos requieran funciones de mercado, pero con una semántica de transferencia diferente. He probado los tipos de contenedores, varias colecciones por conjunto de habilidades y el almacenamiento de metadatos de tipos separados. Cada uno tiene sus ventajas y desventajas entre la seguridad del tipo, los costos de la gasolina y la complejidad.

    0
    3
  • Peera Admin.Peera.
    ParaSuiMay 29, 2025
    +10

    ¿Por qué BCS requiere un orden de campo exacto para la deserialización cuando las estructuras Move tienen campos con nombre?

    ¿Por qué BCS requiere un orden exacto de los campos para la deserialización cuando las estructuras de Move tienen campos con nombre? He profundizado en la codificación y decodificación de BCS en Move, especialmente para la comunicación entre cadenas y el procesamiento de datos fuera de la cadena. Mientras estudiaba los ejemplos de la documentación de Sui Move, me encontré con algunos comportamientos que parecen contradictorios y estoy intentando entender las decisiones de diseño subyacentes. Según la especificación de BCS, «no hay estructuras en BCS (ya que no hay tipos); la estructura simplemente define el orden en el que se serializan los campos». Esto significa que, al deserializar, debemos usar peel_*las funciones exactamente en el mismo orden en que se definieron los campos de estructura. Mis preguntas específicas: Justificación del diseño: ¿Por qué BCS exige que los campos coincidan exactamente en el orden de los campos cuando las estructuras de movimiento tienen campos con nombre? ¿No sería más sólido serializar los nombres de los campos junto con los valores, de forma similar a JSON u otros formatos autodescriptivos? Interacción de tipos genéricos: Los documentos mencionan que «los tipos que contienen campos de tipo genérico se pueden analizar hasta el primer campo de tipo genérico». Considera esta estructura: struct ComplexObject has drop, copy { id: ID, owner: address, metadata: Metadata, generic_data: T, more_metadata: String, another_generic: U } ¿Cómo funciona exactamente la deserialización parcial aquí? ¿Puedo deserializar hasta more_metadata e ignorar ambos campos genéricos, o el primer campo genérico (generic_data) bloquea por completo la deserialización posterior? Coherencia entre idiomas: al utilizar la biblioteca JavaScript @mysten /bcs para serializar los datos que consumirán los contratos de Move, qué ocurre si: ¿Reordeno accidentalmente los campos del objeto de JavaScript? ¿La definición de la estructura Move cambia el orden de los campos en una actualización de contrato? ¿Tengo estructuras anidadas con sus propios parámetros genéricos? Implicaciones prácticas: En los sistemas de producción, ¿cómo gestionan los equipos la evolución del esquema BCS? ¿Versionan sus esquemas de BCS o esperan que el orden de los campos de las estructuras sea inmutable una vez implementados?

    5
    3
  • Peera Admin.Peera.
    ParaMoveMar 11, 2025
    +10

    Sui Move vs Aptos Move - What is the difference?

    Sui Move and Aptos Move - two prominent implementations of the Move programming language. While both are rooted in the same foundational principles, they have diverged significantly in design, execution, and ecosystem development. To better understand their differences, we need to uncover some of their key aspects: How do their runtimes differ? Both Sui and Aptos implement their own custom Move virtual machines (VMs). How does this impact performance, scalability, and developer experience? For instance: Does Sui's runtime optimize for parallel execution differently than Aptos'? Are there notable differences in transaction lifecycle management or gas models? What are the differences between their standard libraries? The Move standard library is a critical component for building smart contracts. However, Sui and Aptos have forked their implementations, leading to divergence: Are there modules or functions unique to one implementation but absent in the other? How do these differences affect common use cases like token creation, NFTs, or decentralized finance (DeFi)? How does data storage differ between them? One of the most significant distinctions lies in how Sui and Aptos handle data storage: Sui uses an object-centric model, where each object has its own ownership and permissions. Aptos, on the other hand, retains a more traditional account-based model similar to Ethereum. How does this impact state management, composability, and gas efficiency? Is it fair to say that Aptos is closer to EVM while Sui is closer to SVM? Some developers argue that Aptos' account-based architecture resembles Ethereum's EVM, while Sui's object-centric approach aligns more closely with Solana's SVM. Do you agree with this analogy? Why or why not? How does this architectural choice influence developer ergonomics and application design? Are there universal packages working for both Sui Move and Aptos Move? Given their shared origins, it would be ideal if some libraries or tools were interoperable across both ecosystems. Are there any existing universal packages or frameworks that work seamlessly on both platforms? If not, what are the main barriers to achieving compatibility? Can one of them be transpiled into another? If a project is built on Sui Move, could it theoretically be transpiled to run on Aptos Move, or vice versa? What are the technical challenges involved in such a process? Are there tools or compilers currently available to facilitate this kind of migration?

    2
    1

Más reciente

  • Santorini.Peera.
    ParaSuiJun 20, 2025

    He perdido las direcciones de mi monedero Sui, ¿cómo las recupero?

    Estoy usando Suiscanner y veo actividad conocida en diferentes direcciones a las que solía tener acceso en mi monedero Sui, pero ahora solo aparece una en Sluch. ¿Cómo puedo recuperar las direcciones que faltan?

    0
    1
  • farshad.Peera.
    ParaWalrusJun 20, 2025

    How to fix 'Cannot open wallet config file' error in Walrus?

    I'm trying to use the Walrus CLI to store a file with the command walrus store --wallet. However, I'm encountering an error: Cannot open wallet config file at "~/.sui/sui_config/client.yaml". Err: Unable to load config. I've tried using relative and absolute paths in the command, but the error persists. I can open the file using a text editor, so I know it exists. How can I resolve this issue?

    0
    4
  • md rifat hossen.Peera.
    ParaSuiJun 19, 2025

    Soulbound Activo transferible

    ¡Gran artículo! Me gustaría añadir algunos puntos prácticos para reforzar el diseño y la seguridad tipográfica en torno a los activos heterogéneos de Sui Move: ✅ Como se dynamic_field::add()requiere esta storehabilidad, los activos como los tokens Soulbound (que solo los tienenkey) no se pueden almacenar directamente. IDEn su lugar, almacena solo sus storemetadatos y los de la lista, que sí tienen. ✅ El mejor enfoque: separar las colecciones en función de las limitaciones de capacidad: VecMap→ para key + storeactivos (por ejemplo, NFT transferibles) VecMap→ para keyactivos exclusivos (p. ej., tokens Soulbound) ✅ Agregue una asset_type: Stringetiqueta de tiempo de ejecución a los metadatos. Esto le permite identificar y gestionar de forma segura la lógica de los activos (por ejemplo, las transferencias o la visualización) incluso después de la eliminación del tipo. ✅ Los tipos fantasma son excelentes para etiquetar tipos en tiempo de compilación y evitar el uso indebido por parte de los desarrolladores (como las transferencias accidentales de tokens no transferibles). Esta estructura modular es escalable, evita que se infrinjan las capacidades de Move y permite un diseño flexible del mercado sin sacrificar la seguridad. ¡Buen trabajo al explicarlo tan minuciosamente!

    0
    1

Sin respuesta

  • Owen.Peera.
    Owen212
    ParaSuiJun 11, 2025

    ¿Cómo actualizar la clave de un comerciante en ObjectTable cuando cambia en la estructura?

    Hola a todos, acabo de empezar a escribir contratos inteligentes y estoy trabajando en mi primer proyecto. Me encantaría recibir ayuda con un problema en el que estoy atrapado. Hasta ahora, he creado una Merchantestructura que se ve así: -id: un identificador único (UID) -owner: la dirección del comerciante -key: una cadena utilizada como clave única -balance: un u64 que representa su saldo También creé una MerchantRegistryestructura para administrar a todos los comerciantes: -id: otro identificador -merchant_to_address: una ObjectTableasignación de direcciones a los comerciantes -merchant_to_key: un ObjectTablemapeo de claves para los comerciantes Quiero poder buscar un comerciante por sudireccióno por suclave. MerchantCuando un usuario actualiza su clave dentro de la merchant_to_keyestructura, el cambio no actualiza automáticamente la clave de la tabla. Esto significa que la llave antigua sigue apuntando al comerciante, lo que descifra las cosas. Intenté eliminar la entrada de la tabla y volver a insertarla con la nueva clave, pero sigo encontrando errores como: «No se pueden ignorar los valores sin la habilidad de soltar» Estoy bastante seguro de que se trata de un error de principiante, pero no he podido encontrar una explicación o solución clara en ninguna parte. ¿Existe una forma adecuada de gestionar la actualización de la clave tanto en la estructura como en la tabla de búsqueda?

    2
    0
  • 0xduckmove.Peera.
    ParaSuiJun 06, 2025

    ¿Cuál es la interfaz más fácil para subir manchas de morsa?

    ¿solo una interfaz de usuario simple para subirla a Walrus? (además de Tusky)

    1
    0
  • 1 Luca.Peera.
    ParaSuiApr 09, 2025

    ¿Qué pasa si no solicito ETH a través del puente Sui?

    He estado usando el puente Sui para transferir algunos ETH, pero aún no los he reclamado porque las comisiones son bastante altas. ¿Qué pasará si lo dejo sin reclamar?

    0
    0

Tendencia

  • 0xduckmove.Peera.
    ParaSuiApr 08, 2025

    👀 SEAL: creo que la privacidad de los datos de Web3 está a punto de cambiar

    👀 SEAL está disponible en Sui Testnet. Creo que la privacidad de los datos de Web3 está a punto de cambiar En la Web3, es común escuchar frases como* «los usuarios son dueños de sus datos»* o* «descentralizado por diseño»*. Sin embargo, si se analiza detenidamente, muchas aplicaciones aún dependen de infraestructuras centralizadas para gestionar los datos confidenciales, y utilizan servicios como AWS o Google Cloud para la administración de claves. Esto introduce una contradicción: descentralización en la superficie, centralización en el fondo. Pero, ¿y si hubiera una forma de gestionar los secretos de forma segura, sin renunciar a la descentralización? Presentamos SEAL: Decentralized Secrets Management (DSM), que ya está disponible en la red de pruebas Sui. SEAL tiene como objetivo corregir una de las mayores hipocresías de Web3: propugnar la descentralización mientras usa AWS en secreto Quizás me preguntes: ¿Qué es SEAL? SEAL es un protocolo que te permite gestionar datos confidenciales de forma segura ydescentralizada, creado específicamente para el mundo de la Web3. Piense en ello como una capa de control de acceso que prioriza la privacidad y que se conecta a su dApp. Puede pensar en SEAL como una especie de bloqueo programable para sus datos. Con Move on Sui no solo bloqueas y desbloqueas archivos manualmente, sino queescribes políticas directamente en tus contratos inteligentes. Supongamos que estás creando una dApp en la que: Solo los titulares de NFT pueden desbloquear un tutorial premium O tal vez un DAO tenga que votar antes de que se revelen los archivos confidenciales O quieres que los metadatos estén bloqueados en el tiempo y que solo se pueda acceder a ellos después de una fecha específica SEAL hace que todo eso sea posible. El control de acceso funciona en cadena, es totalmente automatizado, sin necesidad de que un administrador lo gestione. Solo lógica, integrada directamente en la cadena de bloques. SEAL hace que todo eso sea posible. El control de acceso funciona en cadena, es totalmente automatizado, sin necesidad de que un administrador lo gestione. Solo lógica, integrada directamente en la cadena de bloques. Otra pieza interesante es cómo SEAL maneja elcifrado. Utiliza algo llamadocifrado de umbral, lo que significa que ningún nodo puede descifrar los datos por sí solo. Se necesita un grupo de servidores para trabajar juntos, algo parecido a la firma múltiple, pero para desbloquear secretos. Esto distribuye la confianza y evita el problema habitual de un único punto de fallo. Y para mantener la verdadera privacidad, SEAL cifra y descifra todo lo que esté en el lado del cliente**. Tus datos nunca son visibles para ningún backend. Permanecen en tus manos, literalmente, en tu dispositivo. y a SEAL no le importa dónde guardes tus datos. Ya sea IPFS, Arweave, Walrus o alguna otra plataforma, SEAL no intenta controlar esa parte. Solo se centra enquién puede ver qué, no en dónde se almacenan las cosas. Así que sí, no se trata solo de una biblioteca o API, sino de unacapa que prioriza la cadena, el acceso controlado y la privacidad por defectopara tu DApp. SEAL llena un vacío bastante crítico. Vamos a desglosarlo un poco más. Si estás creando una dApp que tratacualquier tipo de datos confidenciales(contenido cerrado, documentos de usuario, mensajes cifrados e incluso metadatos de NFT bloqueados por tiempo), te encontrarás con el mismo problema: ➡️ ¿Cómo se gestiona el acceso de forma segura, sin depender de un servicio centralizado? Sin algo como SEAL, la mayoría de los equipos tampoco: Utilice herramientas centralizadas como AWS KMS o Firebase, lo que claramente va en contra de la descentralización O trate de arreglar ellos mismos la lógica de cifrado a medias, que por lo general termina siendo frágil y difícil de auditar https://x.com/EmanAbio/status/1908240279720841425?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1908240279720841425%7Ctwgr%5E697f93dc65359d0c8c7d64ddede66c0c4adeadf1%7Ctwcon%5Es1_&ref_url=https%3A%2F%2Fwww.notion.so%2Fharryph%2FSEAL-Launches-on-Sui-Testnet-1cc4f8e09bb380969c0dcc627b96cc22 Ninguno de los dos se ajusta bien. Especialmente cuando intentas crear aplicaciones confiables en múltiples cadenas o comunidades. SEAL hace que todo ese proceso sea modular y programable. Usted define las reglas de acceso en los contratos inteligentes de Move y SEAL se encarga del resto (generación de claves, aprobación del descifrado y control del acceso), todo ello sin que nadie emita las claves manualmente ni realice comprobaciones de backend. Y lo que es mejor, esas reglas sonauditables e inmutables: una vez que están en cadena, se rigen por el contrato, no por un administrador humano. Así que en lugar de preguntar «¿quién debe gestionar el acceso a estos datos?» solo tienes que preguntar: «¿Qué lógica debería definir el acceso?» > ... y deja que la cadena se encargue. Limpio y escalable. Eso es lo que hace que SEAL sea relevante para algo más que «herramientas de seguridad»: es una capa base para cualquier dApp que se preocupe por la privacidad, el cumplimiento o la lógica de acceso dinámico.** Es un cambio pequeño, pero cambia mucho la forma en que pensamos sobre los datos en la Web3. En lugar de cifrarlos después de la implementación o confiar en servicios externos,se empieza con la privacidad integrada y el acceso se gestiona completamente mediante la lógica de los contratos inteligentes. Y eso es exactamente lo que Web3 necesita ahora mismo. ¿Cómo funciona realmente SEAL? Hemos explicadoqué es SEALypor qué Web3lo necesita**. Veamos cómo se construye realmente bajo el capó. En esta parte es donde las cosas se vuelven más técnicas, pero en el buen sentido. La arquitectura es elegante una vez que ves cómo encajan todas las piezas. En un nivel superior, SEAL combina lalógica de acceso en cadenacon lagestión de claves fuera de la cadena, mediante una técnica denominadaCifrado basado en la identidad (IBE). Esto permite a los desarrolladores cifrar los datos para convertirlos en una identidad y, luego, confiar en contratos inteligentes para definir *quién puede descifrarlos. Paso 1: reglas de acceso en los contratos inteligentes (en Sui) Todo comienza con el contrato inteligente. Cuando utilizas SEAL, defines una función llamada seal_approve en tu contrato de Move; aquí es donde escribes las condiciones para el descifrado. Por ejemplo, esta es una sencilla regla de bloqueo temporal escrita en Move: entry fun seal_approve(id: vector, c: &clock::Clock) { let mut prepared: BCS = bcs::new(id); let t = prepared.peel_u64(); let leftovers = prepared.into_remainder_bytes(); assert!((leftovers.length() == 0) && (c.timestamp_ms() >= t), ENoAccess); } Una vez desplegado, este contrato actúa como guardián. Siempre que alguien quiera descifrar datos, su solicitud se comparará con esta lógica. Si se aprueba, la clave se libera. Si no, están bloqueados. Nadie tiene que intervenir. ##Paso 2: Cifrado basado en la identidad (IBE) Aquí es donde ocurre la magia. En lugar de cifrar los datos de una dirección de monedero específica (como en el caso de PGP o RSA), SEAL utilizacadenas de identidad, lo que significa que los cifras de forma similar a: 0 x dirección de monedero dao_vote: proposal_xyz PKGID_2025_05_01 (una regla basada en la marca de tiempo) o incluso game_user_nft_holder Cuando los datos están cifrados, tienen el siguiente aspecto: Encrypt(mpk, identity, message) mpk = clave pública maestra (conocida por todos) identidad = el destinatario definido de forma lógica mensaje = los datos reales Más adelante, si alguien quiere descifrarlos, el servidor de claves comprueba si cumplen con la política (mediante la llamada en cadena seal_approve). Si se aprueba, devuelve una clave privada derivada para esa identidad. Derive(msk, identity) → sk Decrypt(sk, encrypted_data) A continuación, el usuario puede descifrar el contenido localmente. Por lo tanto, el cifrado se realiza sin necesidad de saber con antelación quién lo descifrará. Solo tiene que definir las condiciones y SEAL se encargará del resto más adelante. Es dinámico. ##Paso 3: El servidor de claves: fuera de la cadena, pero no centralizado Quizás te preguntes: ¿quién tiene estas llaves maestras? Aquí es donde entra en juego elservidor de clavede SEAL. Piense en ello como un backend que: Contiene la clave secreta maestra (msk) Controla los contratos en cadena (como tu lógica seal_approve) Solo emite claves derivadas si se cumplen las condiciones Pero, y esto es clave, SEAL no depende solo de un servidor de claves. Puedes ejecutarlo enmodo umbral, donde varios servidores independientes deben ponerse de acuerdo antes de emitir una clave de descifrado. Por ejemplo: 3 de cada 5 servidores de claves deben aprobar la solicitud. Esto evita los puntos centrales de falla y también permite la descentralización en la capa de administración de claves. Aún mejor, en el futuro, SEAL admitiráMPC (computación multipartita) yconfiguraciones basadas en enclaves(como TEE), por lo que puede obtener garantías aún más sólidas sin comprometer la usabilidad. ##Paso 4: Descifrado del lado del cliente Una vez que se devuelve la clave al usuario, el descifrado propiamente dicho se lleva a caboen su dispositivo. Esto significa: El servidor nunca ve tus datos El backend nunca almacena contenido descifrado Solo el usuario puede acceder al mensaje final Es un modelo de privacidad sólido. Incluso si alguien pone en peligro la capa de almacenamiento (IPFS, Arweave, etc.), no podrá leer los datos sin pasar por la lógica de acceso. Este es el modelo mental rápido: Esta estructura facilita la creación de dApps en las que las reglas de acceso no estén codificadas: son dinámicas, auditables y están totalmente integradas en la lógica de la cadena. ##El equipo detrás de SEAL SEAL está dirigido porSamczsun, una figura muy conocida en la comunidad de seguridad de cadenas de bloques. Anteriormente fue socio de investigación en Paradigm, y ha auditado múltiples ecosistemas y los ha salvado de grandes vulnerabilidades. Ahora, se dedica a tiempo completo a convertir a SEAL en una pieza central de la infraestructura de privacidad de Web3. Con su experiencia y credibilidad, SEAL no es solo otra herramienta experimental: es un intento serio de hacer que la privacidad de datos descentralizada sea práctica y escalable. A medida que SEAL se lanza en la red de pruebas Sui, incorpora un nuevo estándar sobre la forma en que las aplicaciones Web3 pueden gestionar los secretos. Al combinar el control de acceso en cadena, el cifrado de umbrales y la privacidad del lado del cliente, SEAL ofrece una base más confiable para el manejo descentralizado de datos. Ya sea que estés creando dApps, DAO o juegos descentralizados, SEAL proporciona un potente conjunto de herramientas para reforzar el control de acceso y proteger los datos de los usuarios sin comprometer la descentralización. Si Web3 quiere avanzar, una infraestructura segura como SEAL no es opcional, es esencial

    8
  • Vens.sui.Peera.
    ParaSuiApr 29, 2025

    AMM Bot en el ecosistema Sui

    ¿Cuáles son las principales características y funcionalidades de los bots AMM dentro del ecosistema de Sui? ¿Cómo mejoran los mecanismos comerciales tradicionales y qué ventajas ofrecen a los usuarios que utilizan los protocolos DeFi en la red Sui? ¿Necesito construir uno o puedo usar Turbos Finance, por ejemplo

    6
    2
  • harry phan.Peera.
    ParaSuiApr 24, 2025

    Administración de niños entre módulos con public_receive

    Esta es la tercera parte de la serie «Objetos entre padres e hijos en movimiento». A veces, los tipos de padre e hijo se definen en diferentes módulos o incluso en paquetes diferentes. Por ejemplo, es posible que tengas un objeto Warehouse genérico que pueda almacenar cualquier tipo de objeto Parcel. El módulo Warehouse quiere extraer un paquete secundario, pero el tipo de paquete se define en otro lugar. En estos casos, utilizamos transfer: :public_receive, que es el primo de receive entre módulos. ###receive vs public_receive Como hemos visto, transfer: :receive solo se puede invocar en el módulo que define T (o a un amigo) porque no requiere T: store. De hecho, el verificador de códigos de bytes Move garantiza que, en cualquier llamada que se reciba, el tipo T provenga del módulo actual. Se trata de una restricción de seguridad para objetos que solo pueden utilizarse con una llave. transfer: :public_receive es una variante que requiere T: key + store, pero permite recibir datos fuera del módulo T. En otras palabras, si el tipo de objeto tiene la capacidad de almacenamiento (lo que significa que puede existir libremente en el almacenamiento global), cualquier módulo (con el UID &mut del elemento principal) puede recibirlo mediante public_receive. Esto es perfecto para los casos en los que el módulo principal es diferente del módulo secundario. ¿Por qué requerir una tienda? Porque almacenar marcas de que el objeto puede conservarse y distribuirse de forma segura fuera de su módulo de definición. Los objetos de solo clave pueden tener invariantes personalizados que el módulo original quiera aplicar al transferirlos o recibirlos; al excluir los de public_receive, Sui obliga a los desarrolladores a gestionarlos dentro del módulo (como veremos con los objetos enlazados al alma). Si un objeto tiene almacenamiento, es más permisivo, y Sui permite una lógica genérica de transferencia/recepción para gestionarlo externamente. ###Ejemplo: módulos separados para padres e hijo Vamos a ilustrarlo con un escenario sencillo: un almacén que almacena objetos de paquetería. El tipo de paquete se define en su propio módulo y el almacén en otro. Mostraremos cómo Warehouse puede recibir un paquete secundario mediante public_receive. module demo::parcel { // Child module use sui::object::{Self, UID}; use sui::tx_context::{Self, TxContext}; /// A parcel object that can be stored in a Warehouse. /// It has both key and store, so it can be transferred across modules. struct Parcel has key, store { id: UID, contents: vector } public entry fun create_parcel(contents: vector, ctx: &mut TxContext): Parcel { Parcel { id: object::new(ctx), contents } } } module demo::warehouse { // Parent module use sui::transfer::{Self, Receiving, public_receive}; use demo::parcel::{Self, Parcel}; use sui::object::{UID}; use sui::tx_context::{Self, TxContext}; struct Warehouse has key { id: UID, location: address } public entry fun create_warehouse(location: address, ctx: &mut TxContext): Warehouse { Warehouse { id: object::new(ctx), location } } /// Receive a Parcel that was sent to this Warehouse. /// Returns the Parcel to the caller (transferred to caller's address). public entry fun withdraw_parcel( warehouse: &mut Warehouse, parcel_ticket: Receiving, ctx: &mut TxContext ): Parcel { // Using public_receive because Parcel is defined in another module and has store let parcel = public_receive(&mut warehouse.id, parcel_ticket) oai_citation_attribution:27‡docs.sui.io oai_citation_attribution:28‡github.com; // Transfer the parcel to the transaction sender (so the caller gets ownership) transfer::transfer(parcel, tx_context::sender(ctx)); // We return nothing because we've transferred the Parcel out to the caller. } } Analicemos lo que está sucediendo en draw_parcel: Llamamos a public_receive (&mut warehouse.id, parcel_ticket). Como Parcel tiene la capacidad de almacenar, esta llamada está permitida aunque no estemos en el módulo de paquetería. En principio, realiza las mismas comprobaciones y extracciones que las de recepción, pero se permite usar varios módulos, ya que la tienda indica que es seguro hacerlo. https://github.com/MystenLabs/sui/blob/main/crates/sui-framework/packages/sui-framework/sources/transfer.move#:~:text=public%20fun%20public_receive,T%3E%29%3A%20T A continuación, transferimos inmediatamente el paquete recibido a la dirección de la persona que llama (tx_context: :sender (ctx)). Este paso garantiza que el paquete salga del almacén y llegue al usuario que inició la retirada. También podríamos haber devuelto Parcel desde la función y Sui lo trataría como una salida que pertenecería a la dirección de la persona que llama (ya que es una salida de una función de entrada). Hacer una transferencia explícita es más detallado, pero deja claro lo que está sucediendo (y nos permite hacer cualquier comprobación antes de liberar el objeto). ¿Por qué incluir la tienda en Parcel? Si Parcel carecía de la capacidad de almacenar (es decir, solo tenía una clave), la llamada public_receive de demo: :warehouse no se compilaba; Sui exige que T tenga store para public_receive. En ese caso, nos veríamos obligados a recuperar el paquete utilizando la función de recepción dentro del propio módulo de paquetería (o utilizar alguna relación de amistad), lo que complica el diseño de varios módulos. Al añadir store a Parcel, decimos que «este objeto se puede mover y recibir libremente en módulos externos», que es lo que queremos para un patrón de contenedor genérico. Patrón de llamada a una función: Para usarlos en una transacción, el flujo sería: 1.Depósito (transferencia al objeto) :Llama a transfer: :public_transfer (parcel_obj, @warehouse_id) para enviar un paquete a un almacén. Esto marca al propietario del paquete como el almacén. (Aquí utilizamos public_transfer porque está fuera del módulo Parcel y Parcel tiene un almacén. Dentro del módulo del paquete, una simple transferencia también funcionaría). Retirar (recibir de nuevo) :Más tarde, llama a draw_parcel (warehouse_obj, Receiving (parcel_id,...)). El SDK puede obtener la recepción haciendo referencia al identificador del paquete y a la última versión. La función llamará a public_receive y, a continuación, te transferirá el paquete. Tras la llamada a withdrawal _parcel, el propietario del paquete vuelve a su dirección (la suya), por lo que vuelve a ser un objeto propiedad de una dirección normal. El almacén ya no es su propietario. Consideraciones relacionadas con varios módulos: Tenga en cuenta que el módulo de almacén necesitaba conocer el tipo de paquete (utilizamos demo: :parcel: :Parcel). Esto se debe a que escribimos explícitamente la recepción como recepción. Si querías un contenedor verdaderamente genérico que pudiera recibir cualquier tipo de objeto, tendrías que usar genéricos o un enfoque diferente (posiblemente campos dinámicos con borrado de tipos). Sin embargo, en la mayoría de los casos de uso, sabrás qué tipo de niños esperas tener. ¿Por qué public_receive en lugar de simplemente llamar a receive? Si probáramos con transfer: :receive (&mut warehouse.id, parcel_ticket) en el módulo de almacén, el verificador de Move lo rechazaría porque Parcel no está definido en demo: :warehouse. Sui ofrece la opción public_receive como la mejor forma de hacerlo, con una comprobación de habilidad adicional (se requiere almacenar). Del mismo modo, Sui utiliza transfer vs public_transfer, freeze_object vs public_freeze_object, etc., siguiendo el mismo patrón: las versiones public_ son para usarse fuera del módulo de definición y requieren almacenamiento. No olvides el permiso de los padres: Incluso con public_receive, necesitarás ese &mut warehouse.id. Lo tenemos porque draw_parcel está en el módulo de Warehouse y acepta &mut Warehouse. Por lo tanto, solo alguien que pueda llamar a esa persona (el propietario del almacén) puede retirar el paquete. Si el módulo de almacén no proporcionara esta función de forma pública, tampoco se podría invocar externamente a public_receive en sus módulos secundarios. Por lo tanto, los módulos cruzados no eluden el control del padre; solo permiten que el código del padre funcione con elementos secundarios de tipos que no ha definido. Nota sobre la posibilidad de almacenar objetos: Ofrecer un almacén de objetos hace que sea más flexible, pero un poco menos restringido: cualquier módulo que tenga la referencia principal puede extraerla usando public_receive. Si quieresrestringirla forma en que se recupera un objeto (por ejemplo, aplicar una lógica personalizada o impedir que se extraiga fácilmente), puedes hacer que sea solo con clave de forma deliberada. Veremos un ejemplo de ello con objetos ligados al alma. En esos casos, puedes implementar una función de recepción personalizada en lugar de confiar en public_receive. Para resumir esta parte: public_receive es tu mejor opción para administrar objetos secundarios definidos en otros módulos, siempre que esos objetos tengan la capacidad de almacenamiento. Te permite crear sistemas multimodulares (como nuestro almacén/paquetería) sin dejar de respetar la propiedad y el control de acceso. Solo recuerda incluir los tipos secundarios de almacenamiento y usar public_transfer cuando los envíes a un padre desde fuera de su módulo.

    5