NUEVO: Helius adquiere Light Protocol
Extensiones de tokens listas para usar
Blog/Desarrollo

Extensiones de tokens listas para usar

Ingeniero de integraciones0xSolanaGirl en X
8 min de lectura

Introducción

Las extensiones de tokens facilitan la creación de tokens programables en Solana. Los desarrolladores pueden combinar más de una docena de extensiones de acuñación y cuenta con el nuevo programa Token Extensions. Al completar el tutorial, crearás e interactuarás con tokens fungibles y no fungibles, tokens que generan intereses, tokens congelados y tokens sobre los que tienes autoridad absoluta, incluso para retirarlos de cuentas que no te pertenecen. También cerrarás cuentas de acuñación para recuperar fondos. 

Extensiones de tokens listas para usar es un tutorial con ejemplos interactivos de Solana Playground que te ayudará a aprender sobre las extensiones de tokens con TypeScript mediante la creación de los siguientes tokens:

El código de este tutorial está adaptado de la Guía para desarrolladores de Solana. Puedes encontrar scripts para crear extensiones de tokens en la sección Recursos adicionales. 

Cuenta de extensiones de tokens

Las extensiones de tokens introducen nuevas instrucciones y se basan en el Token Program. Las cuentas creadas con ambos programas son idénticas en su longitud inicial, hasta que terminan las instrucciones del Token Program y comienzan las instrucciones de las extensiones de tokens. Si no conoces los datos de las cuentas, puedes leer sobre el espacio de las cuentas en una introducción a Anchor. En resumen, las cuentas de Solana deben crearse con espacio asignado explícitamente para almacenar datos en la cadena. Con ese espacio, podemos calcular la cantidad de lamports necesaria para eximir a la cuenta del pago de alquiler.

Así se crea una cuenta de acuñación con extensiones. Para asignar espacio a las extensiones de tokens, usa la función getMintLen para obtener el tamaño de la cuenta de acuñación con extensiones. En el ejemplo NonFungibleToken.ts, obtén la longitud de acuñación de los tipos de extensión MetadataPointer y MintCloseAuthority.

NonFungibleToken.ts línea 54:

Código
  // Size of Mint Account with extension
  const mintLen = getMintLen([
    ExtensionType.MetadataPointer,
    ExtensionType.MintCloseAuthority,
  ]);

Las extensiones Metadata y Metadata Pointer permiten almacenar metadatos y apuntar a ellos sin depender de protocolos externos. TokenMetadata es una interfaz de @solana/spl-token-metadata con campos como updateAuthority, mint, name, symbol, uri y additionalMetadata. La longitud de los metadatos se obtiene mediante la función pack en el objeto de metadatos. 

‍NonFungibleToken.ts línea 60:

Código
  // Metadata to store in Mint Account
  const metaData: TokenMetadata = {
    updateAuthority: updateAuthority,
    mint: mint,
    name: "Solana Soldier",
    symbol: "SOLD",
    uri: "https://shdw-drive.genesysgo.net/G1Tzt42SDqCV3x9vPY5X826foA8fEk8BR4bB5wARh75d/OIG2.jpg",
    additionalMetadata: [["armor", null]],
  };
  // Size of metadata
  const metadataLen = pack(metaData).length;
  // Size of MetadataExtension 2 bytes for type, 2 bytes for length
  const metadataExtension = TYPE_SIZE + LENGTH_SIZE;

Suma la longitud de acuñación, la extensión de metadatos y la longitud de los metadatos para calcular la cantidad mínima de lamports necesaria para la cuenta de acuñación.

NonFungibleToken.ts línea 75:

Código
  // Minimum lamports required for Mint Account
  const lamports = await connection.getMinimumBalanceForRentExemption(
    mintLen + metadataExtension + metadataLen
  );

Instrucciones de extensiones de tokens

Las bibliotecas de Solana como @solana/spl-token y @solana/spl-token-metadata añaden compatibilidad con TypeScript para el programa Token Extensions. Comienza creando una cuenta con la cantidad correcta de espacio y lamports exentos de alquiler mediante SystemProgram de @solana/web3.js.

NonFungibleToken.ts línea 80:

Código
  // Instruction to invoke System Program to create new account
  const createAccountInstruction = SystemProgram.createAccount({
    fromPubkey: payer.publicKey, // Account that will transfer lamports to created account
    newAccountPubkey: mint, // Address of the account to create
    space: mintLen, // Amount of bytes to allocate to the created account
    lamports, // Amount of lamports transferred to created account
    programId: TOKEN_2022_PROGRAM_ID, // Program assigned as owner of created account
  });

A continuación, podemos crear instrucciones para especificar la acuñación. Las siguientes instrucciones deben ejecutarse antes de llamar a initializeMint. Las instrucciones previas a la acuñación usadas en Extensiones de tokens listas para usar son:

Las cuentas de metadatos se pueden inicializar y actualizar independientemente de initializeMint. Sin embargo, el puntero de metadatos debe inicializarse antes de la acuñación. El orden de las instrucciones en la transacción determina el orden en que se ejecutan. Crea una cuenta de acuñación, inicializa el puntero de metadatos y luego la autoridad de cierre de acuñación con la clave pública de la acuñación. Después, inicializa las cuentas de acuñación y metadatos y actualiza los metadatos adicionales.

‍NonFungibleToken.ts línea 135:

Código
  transaction = new Transaction().add(
    createAccountInstruction,
    initializeMetadataPointerInstruction,
    initializeMintCloseAuthorityInstruction,
    initializeMintInstruction,
    initializeMetadataInstruction,
    updateFieldInstruction
  );

Los archivos nonFungibleToken.ts, soulboundToken.ts, interestBearingToken.ts e delegateToken.ts siguen la misma estructura para crear tokens. La diferencia está en las extensiones e instrucciones utilizadas. 

El proceso comienza importando todas las funciones necesarias desde las bibliotecas de Solana requeridas, definiendo un pagador y generando una dirección de acuñación. Luego, calcula el espacio y los lamports necesarios para la dirección de acuñación con las extensiones de tokens deseadas. Crea instrucciones con las bibliotecas @solana/spl-token y @solana/spl-token-metadata, añádelas a una transacción, envía la transacción a la red y valida los resultados. 

Las operaciones de tokens, como transferir y quemar, pueden usarse con distintas extensiones de tokens. Los tokens con la extensión Metadata pueden usar las instrucciones createUpdateFieldInstruction e createRemoveKeyInstruction para actualizar o eliminar metadatos, respectivamente. 

Listo para usar 

En Solana Playground, el cliente contiene las funciones necesarias para interactuar con las extensiones de tokens. Por ejemplo, el token vinculado al alma usa las extensiones Non-Transferable y Metadata para crear un NFT vinculado al alma. Las funciones para crear los tokens e interactuar con ellos están disponibles en el mismo archivo y se pueden importar. En Solana Playground, debes copiar y pegar el código en lugar de importarlo. 

El archivo quest.ts te permite jugar a Solana Soldier. También puedes ejecutar cada archivo que contenga extensiones de tokens para ver su funcionalidad específica. La billetera de Playground necesita SOL de Devnet para ejecutar la misión. Nuestro faucet de Solana Devnet también está disponible para distribuir SOL de Devnet mediante airdrop.

La misión comienza con la creación de un Solana Soldier, un NFT en el que el pagador (pg.wallet.keypair) tendrá la autoridad de cierre de acuñación. Esto permite que el pagador cierre la cuenta de acuñación y recupere sus SOL. Esta mecánica permite que las aplicaciones recuperen SOL de cuentas que ya no están activas.

Después de crear un Solana Soldier, usa su dirección de acuñación para actualizar los metadatos del NFT. Actualicemos la armadura del soldado a iron. Las funciones getMetadata, updateMetadata e removeMetadata se encuentran en el archivo NonFungibleToken.ts a partir de la línea 167. Las funciones pueden invocarse para cuentas de acuñación que usen la extensión Metadata. Para simplificar, las funciones de metadatos solo se incluirán en el archivo NonFungibleToken.ts.

Ahora es momento de empezar a subir de nivel. Un token que genera intereses representará el nivel del Solana Soldier. Desde InterestBearingToken.ts, importa createInterestBearingToken y usa la instrucción para crear el token. El interés de la cuenta crecerá según la tasa establecida en la línea 43 de InterestBearingToken.ts. Puedes usar la función amountToUiAmount para determinar la cantidad de tokens con intereses acumulados. El interés se acumula con el tiempo y podemos llamar a amountToUiAmount para comprobar el nivel del Solana Soldier.

Cuando el soldado comience a subir de nivel, deberá recibir una misión. La misión está representada por un token vinculado al alma. El soldado no puede transferirlo —intenta detectar el error llamando a la función de transferencia— y la única forma de deshacerse de la misión es quemarlo. En lugar de abandonar la misión, veamos de qué se trata. Pista: ¡revisa los metadatos!

Una vez que hayas leído la misión, el tutorial Listo para usar desplegará un ejército en una dirección de token. El Solana Soldier debe poder convocar al ejército de regreso al pagador después de desplegar los tokens. Las extensiones de tokens lo hacen posible mediante la autoridad de delegado. Esta autoridad puede transferir y quemar tokens sin importar quién sea su propietario. Configura como delegado permanente un par de claves al que tengas acceso. Este par de claves debe firmar las operaciones de quema y transferencia de tokens.

Los tokens de delegado representarán al ejército de Solana. Crea tokens de delegado con createDelegateTokens, en la línea 33 de DelegateToken.ts, y envíalos a la cuenta de tokens del enemigo. Cuando se acuñan los tokens, el ejército de Solana y el enemigo se enfrentan en una batalla hipotética. Después de la batalla, retira a los soldados de la cuenta del enemigo con la función transferDelegateTokens, que se encuentra en la línea 176 de DelegateTokens.ts.

Observa que no todos los soldados regresaron de la dirección del enemigo. Supongamos que perecieron. Usa la función burn de @solana/spl-token para quemar los tokens restantes en la cuenta de tokens del enemigo (sourceTokenAccount). 

Con el éxito de la batalla, la misión del Solana Soldier llega a su fin. Se usó la función closeAccount de @solana/spl-token para cerrar la cuenta y devolver el alquiler. Entre las extensiones de tokens que no se analizan en este artículo están las transferencias confidenciales, las comisiones de transferencia y los hooks de transferencia. Casi todas las extensiones de tokens se pueden combinar, con algunas excepciones, como los hooks de transferencia y los tokens no transferibles. Los Solana Playgrounds de referencia para las extensiones de tokens tratadas en este tutorial están enlazados en Recursos adicionales. 

Conclusión

Inspirado en CryptoZombies, este tutorial Listo para usar explicó los fundamentos para crear extensiones de tokens populares mediante una combinación de extensiones. El tutorial demuestra la capacidad de composición de las extensiones de tokens mediante una experiencia de juego práctica. Puedes usar los ejemplos directamente o como guía para desarrollar tus propios tokens. Desde calcular el tamaño de las cuentas hasta ordenar las instrucciones, los ejemplos ofrecen un proceso simplificado para crear cuentas con extensiones de tokens.  Si esta experiencia de aprendizaje gamificada te resultó útil, comparte tus comentarios en nuestro Discord o etiqueta a @helius en X.

Recursos adicionales

Suscríbete a Helius

Mantente al día con las novedades del desarrollo en Solana y recibe actualizaciones cuando publiquemos

Imagen ampliada