WEB3DEV Español

Delia Viloria T
Delia Viloria T

Posted on

Cómo acuñar un NFT en la red de prueba de Cardano mediante la línea de comandos

¿Por qué hacer eso?

Tienes un activo digital que predice que otras personas querrán comprar. Puede ser único, donde cada activo tiene su propio número de serie digital (lo que significa que no es fungible y puede ser representado por un NFT), o un activo donde cada uno de ellos tiene el mismo valor (similar a monedas físicas como nickles/dimes/quarters) y puede ser representado por un activo nativo.

Alternativas a este método

Este artículo muestra cómo crear un NFT mediante la línea de comandos. Es el método que te da control completo (nivel bajo) sobre cada pequeño detalle de principio al fin. Eso está bien si tú necesitas ese nivel de control o si estás tratando de aprender cómo todo encaja desde cero, para que puedas entender y apreciar la tecnología. Pero implica descargar una copia del blockchain completa y mantenerla actualizada.

Una alternativa es utilizar NamiWallet, que puede ser hecha a partir de tu navegador web. Pero, por el momento, es muy limitada en recursos. Sólo puedes especificar el nombre, cantidad, autor y hacer upload de una foto. No tienes control sobre los metadatos.

Crear un nodo Cardano

Método 1: Cartera Daedalus

Si estás utilizando un sistema operativo que posee un ambiente de desktop completo como Windows o Mac (a diferencia de uno que está apenas en línea de comandos), puedes instalar la Cartera Daedalus para la Red Principal de Cardano y/o para la Red de Prueba de Cardano. Ella hará el download de todo el blockchain.

La Cartera Daedalus viene con cardano-cli y cardano-wallet que usaremos a lo largo de esta guía. Necesitarás crear una variable de ambiente para que esto funcione.

Método 2: Nodo Cardano

Si estás utilizando un sistema operativo que posee apenas una línea de comandos/shell como Ubuntu Server, consulta esta guía: Cómo crear un nodo Cardano en la Red de Pruebas de Linux.

En mi caso, uso la Cartera Daedalus en Windows para la red principal y Ubuntu Server 20.04 LTS dentro de una máquina virtual para la red de prueba. Esto mantiene mi entorno de prueba aislado de mi entorno de producción (Red Principal), evitando accidentes.

Inicia el Nodo Cardano y la Cartera

Método 1: Cartera Daedalus

Abre la Cartera Daedalus, espera hasta que se sincronice al 100% con el blockchain y mantenla en ejecución. Te recuerdo que necesitarás crear una variable de entorno para que esto funcione.

Abre un terminal/shell o prompt de comandos y navega hasta la carpeta Daedalus Wallet.

Método 2: Nodo Cardano

OBSERVACIÓN: Si terminaste la guía Cómo crear un nodo Cardano en la Red de Prueba de Linux y ya tienes el Nodo Cardano y la Cartera Cardano en ejecución, puedes omitir este paso.

Abres tres shells. Esto puede ser tres prompts de comandos (si estás utilizando Windows) o tres ventanas/shells de terminal (si estás usando Linux o Mac).

En el primer shell, inicia Cardano Node. Esto es lo que mantiene tu copia local del blockchain en la Red de Prueba actualizada.

cardano-node run \
--topology ~/cardano/configuration/testnet/testnet-topology.json \
--database-path ~/cardano/testnet-db \
--socket-path ~/cardano/testnet-db/node.socket \
--host-addr 127.0.0.1 \
--port 3001 \
--config ~/cardano/configuration/testnet/testnet-config.json
Enter fullscreen mode Exit fullscreen mode

En el segundo shell, inicia el servidor Cardano Wallet. Esto es lo que te permite interactuar con el nodo.

cardano-wallet serve \
--port 8090 \
--database ~/cardano/testnet-db \
--node-socket $CARDANO_NODE_SOCKET_PATH \
--testnet ~/cardano/configuration/testnet/testnet-byron-genesis.jso
Enter fullscreen mode Exit fullscreen mode

De aquí en adelante, usarás el tercer shell para todo el resto. Mantén los dos shells de arriba abiertos.

Crea una carpeta para almacenar todo

Vamos a almacenar nuestras llaves y metadatos en una nueva carpeta para mantener las cosas organizadas. Nuestro NFT será nombrado TestNFT1234

mkdir -p ~/cardano/nft/TestNFT1234/policy
cd ~/cardano/nft/TestNFT1234
Enter fullscreen mode Exit fullscreen mode

Crear un activo digital que el NFT representa

En algún momento en el futuro, los NFTs serán más que solo una foto de algo. Por ahora, esto normalmente es una imagen. Por ejemplo:

https://ipfs.io/ipfs/QmRhTTbUrPYEw3mJGGhQqQST9k86v1DPBiTTWJGKDJsVFw

Coloca tu NFT en IPFS

Coloca tu recurso NFT (la imagen o lo que fuera) en IPFS. Mira esta guía: Types of IPFS links and when to use them y How to Use IPFS: The Backbone of Web3.

En este ejemplo, estamos utilizando la imagen ya enviada por la persona que escribió la guía oficial de Cardano NFT:

ipfs://QmRhTTbUrPYEw3mJGGhQqQST9k86v1DPBiTTWJGKDJsVFw (Mira la imagen en ipfs.io.)

Gestiona las llaves de pago

Ejecuta esto. Nunca compartas el contenido de estos dos archivos con nadie.

cardano-cli address key-gen \
--verification-key-file payment.vkey \
--signing-key-file payment.skey
Enter fullscreen mode Exit fullscreen mode

Generar una dirección de las llaves de pago

Ejecuta esto para generar la dirección y grabarla en un archivo llamado payment.addr. En este ejemplo, mi dirección de pago termina siendo: addr_test1vzcwn6u3fephqacec4g6fr9gpsp9znpr5hsk9ggcfarn23sthac04.

cardano-cli address build \
--payment-verification-key-file payment.vkey \
--out-file payment.addr \
--testnet-magic 1097911063
Enter fullscreen mode Exit fullscreen mode

Para facilitar las cosas, vamos a almacenar la dirección en una variable. Más tarde, cuando ejecutemos comandos, podemos decir $payment_addres en vez de escribir/copiar la dirección completa.

payment_address=$(cat payment.addr)
Enter fullscreen mode Exit fullscreen mode

Cuando ves - - testnet -magic 1097911063, significa que estamos interactuando con la Red de Prueba en lugar de la Red Principal (que utiliza - -mainnet sin ningún número). ¿Por qué es 1097911063? Es el identificador de red de la Red de Prueba.

Financia la dirección

Debes tener, al menos, 2 ADA en tu dirección de pago anterior para acuñar un token. Si estuvieses en la Red Principal, transferiría algunos fondos a esa dirección de tu cartera o de una corredora.

Como estamos en Testnet, podemos usar el faucet para financiar esa cuenta. Solicita tokens de prueba utilizando el faucet de ADA para obtener inmediatamente 1.000 tAda (prueba ADA). Envíalo a la dirección de pago que acabas de crear.

Mira cuánto lovelace hay en nuestra cuenta ( 1.000.000 lovelace = 1 ADA)

cardano-cli query utxo \
--address $payment_address \
--testnet-magic 1097911063
Enter fullscreen mode Exit fullscreen mode

Aquí está lo que puede aparecer:

TxHash                                                            TxIx        Amount
--------------------------------------------------------------------------------------
0ba233973412b629d8d1bcf6cf219a83c7cf16b59f84c1f2c488d80c5d0404dd     0        1000000000 lovelace + TxOutDatumNone
Enter fullscreen mode Exit fullscreen mode

Exportar parámetros de protocolo

Necesitamos parámetros de protocolo actuales para cuando calculamos transacciones.

cardano-cli query protocol-parameters \
--testnet-magic 1097911063 \
--out-file protocol.json
Enter fullscreen mode Exit fullscreen mode

Esto genera un archivo de 10 KB llamado protocol.json que contiene informaciones como esta:

{
    "txFeePerByte": 44,
    "minUTxOValue": null,
    "decentralization": 0,
    "utxoCostPerWord": 34482,
    "stakePoolDeposit": 500000000,
    "poolRetireMaxEpoch": 18,
    "extraPraosEntropy": null,
    "collateralPercentage": 150,
    "stakePoolTargetNum": 500,
    "maxBlockBodySize": 73728,
    "minPoolCost": 340000000,
    "maxTxSize": 16384,
    "treasuryCut": 0.2,
    "maxBlockExecutionUnits": {
        "memory": 50000000,
        "steps": 40000000000
    },
    "maxCollateralInputs": 3,
    "maxValueSize": 5000,
    "maxBlockHeaderSize": 1100,
    "maxTxExecutionUnits": {
        "memory": 12500000,
        "steps": 10000000000
    },
    "costModels": {
        "PlutusScriptV1": {
            "cekConstCost-exBudgetMemory": 100,
            "unBData-cpu-arguments": 150000,
            "divideInteger-memory-arguments-minimum": 1,
            "nullList-cpu-arguments": 150000,
            "cekDelayCost-exBudgetMemory": 100,
            ...
        }
    },
    "protocolVersion": {
        "minor": 0,
        "major": 6
    },
    "txFeeFixed": 155381,
    "stakeAddressDeposit": 2000000,
    "monetaryExpansion": 3.0e-3,
    "poolPledgeInfluence": 0.3,
    "executionUnitPrices": {
        "priceSteps": 7.21e-5,
        "priceMemory": 5.77e-2
    }
}
Enter fullscreen mode Exit fullscreen mode

Generar el policy Keys

Ejecuta esto. Nunca compartas el contenido de estos dos archivos con nadie.

cardano-cli address key-gen \
--verification-key-file policy/policy.vkey \
--signing-key-file policy/policy.skey
Enter fullscreen mode Exit fullscreen mode

Generar el Policy Script

Ejecuta lo siguiente para generar el archivo policy.script.

echo "{" >> policy/policy.script
echo "  \"type\": \"all\"," >> policy/policy.script
echo "  \"scripts\":" >> policy/policy.script
echo "  [" >> policy/policy.script
echo "   {" >> policy/policy.script
echo "     \"type\": \"sig\"," >> policy/policy.script
echo "     \"keyHash\": \"$(cardano-cli address key-hash --payment-verification-key-file policy/policy.vkey)\"" >> policy/policy.script
echo "   }" >> policy/policy.script
echo "  ]" >> policy/policy.script
Enter fullscreen mode Exit fullscreen mode

Va a aparecer algo así:

{
  "type": "all",
  "scripts":
  [
   {
     "type": "sig",
     "keyHash": "6d1321490cde0b447794edff9239cf0668ae01f0df33823d0a3bbcf7"
   }
  ]
}
Enter fullscreen mode Exit fullscreen mode

Almacena el nombre del archivo de script en una variable.

script="policy/policy.script"
Enter fullscreen mode Exit fullscreen mode

Generar el PolicyID

Ejecuta esto para general el hash PolicyID exclusivo usando el policy script.

cardano-cli transaction policyid \
--script-file ./policy/policy.script >> policy/policyID
Enter fullscreen mode Exit fullscreen mode

En este ejemplo, el PolicyID es
155f313f864d009d7b0b519b1295c9fab7b75c17cfc5ba1aed501b7c.

Almacena el PolicyID en una variable.

policyid=$(cat policy/policyID)
Enter fullscreen mode Exit fullscreen mode

Codifica el nombre de NFT en base-16

Codifica el nombre de tu NFT usando base-16 (hexadecimal). Puedes utilizar esta herramienta online para hacer esto o utilizar el siguiente comando en Linux.

echo -n "TestNFT1234" | xxd -ps
Enter fullscreen mode Exit fullscreen mode

Almacena esto en una variable. Estamos creando un NFT en este ejemplo solo para que la variable Token Amount sea definida en consecuencia.

tokenname="546573744e465431323334"
tokenamount=1
Enter fullscreen mode Exit fullscreen mode

Crea los metadatos

Crea los metadatos para tu NFT. Consulta https://github.com/cardano-foundation/CIPs/tree/master/CIP-0025 para obtener la estructura más reciente.

Guárdalo como metadata.json

nano metadata.json
Enter fullscreen mode Exit fullscreen mode

En el siguiente ejemplo:

155f313f864d009d7b0b519b1295c9fab7b75c17cfc5ba1aed501b7c es el PolicyID
546573744e465431323334 es el nombre del activo (TestNFT1234) codificado en base 16 (hexadecimal)
721 es la clave que la comunidad está utilizando para significar que esto es un NFT

{
    "721": {
        "155f313f864d009d7b0b519b1295c9fab7b75c17cfc5ba1aed501b7c": {
            "546573744e465431323334": {
                "name": "TestNFT1234",
                "image": [ "https://ipfs.io/ipfs/", "QmRhTTbUrPYEw3mJGGhQqQST9k86v1DPBiTTWJGKDJsVFw" ],
                "mediaType": "image/png",
                "description": "Just another fun NFT"
            }
        },
    "version": "1.0"
    }
}
Enter fullscreen mode Exit fullscreen mode

Si no dividieramos el atributo “image” en un array, habríamos recibido este error:

Command failed: transaction build Error: Error reading metadata at: "metadata.json" Value out of range within the metadata item 721: [contents of metadata.json here] Text string metadata value must consist of at most 64 UTF8 bytes, but it consists of 67 bytes.

Reúne la información necesaria para construir la transacción

Ejecuta esto.

cardano-cli query utxo \
--address $payment_address \
--testnet-magic 1097911063
Enter fullscreen mode Exit fullscreen mode

Almacena el valor de TxHash en Txlx en variables.

txhash="0ba233973412b629d8d1bcf6cf219a83c7cf16b59f84c1f2c488d80c5d0404dd"
Enter fullscreen mode Exit fullscreen mode

Obtener la dirección del destinatario

Determina quién será el primer destinatario de este NFT. Puede ser tu propia cartera personal. En cualquier caso, consigue la dirección de la cartera de esa persona.

first_nft_owner_address="addr_test1qqwtrpkkh8a60pjjljn6n90mzdf6fa9wempj8s6t732xh4deudejw0dvq2hyrty7htt02xepkuq65w0peun9wx5kxpuskcgwl9"
Enter fullscreen mode Exit fullscreen mode

Estima la tasa y el objetivo del slot

Todavía no sabemos cuánto costará Lovelace. Comienza con 1400000 lovelace (1,4 ADA), que es el requisito mínimo de UTxO. Si termina costando más porque los metadatos son muy grandes, nos veremos obligados a ajustar más tarde.

fee=1400000
Enter fullscreen mode Exit fullscreen mode

Verifica si todas las variables están definidas

Ejecuta lo siguiente y observa la salida. Asegúrate de que todo tenga valor.

echo [payment_address] NFT will be generated by payment address \"$payment_address\"
echo [first_nft_owner_address] NFT will be sent to address \"$first_nft_owner_address\"
echo [fee] This is estimated to cost \"$fee\" lovelace
echo [policyid] The PolicyID is \"$policyid\"
echo [tokenname] The token name in hexadecimal is \"$tokenname\"
echo [tokenamount] We are going to mint \"$tokenamount\" tokens
echo [script] The policy script is \"$script\"
echo [txhash][txix] This transaction will be funded by TxHash \"$txhash\" using TxIx \"$txix\"
Enter fullscreen mode Exit fullscreen mode

En este ejemplo, aquí está la salida (con los comandos eliminados para facilitar la lectura):

[payment_address] NFT will be generated by payment address "addr_test1vzcwn6u3fephqacec4g6fr9gpsp9znpr5hsk9ggcfarn23sthac04"
[first_nft_owner_address] NFT will be sent to address "addr_test1qqwtrpkkh8a60pjjljn6n90mzdf6fa9wempj8s6t732xh4deudejw0dvq2hyrty7htt02xepkuq65w0peun9wx5kxpuskcgwl9"
[fee] This is estimated to cost "1400000" lovelace
[policyid] The PolicyID is "155f313f864d009d7b0b519b1295c9fab7b75c17cfc5ba1aed501b7c"
[tokenname] The token name in hexadecimal is "546573744e465431323334"
[tokenamount] We are going to mint "1" tokens
[script] The policy script is "policy/policy.script"
[txhash][txix] This transaction will be funded by TxHash "0ba233973412b629d8d1bcf6cf219a83c7cf16b59f84c1f2c488d80c5d0404dd" using TxIx "0"
Enter fullscreen mode Exit fullscreen mode

Construir la transacción

Ahora vamos a construir la transacción y almacenarla dentro de un archivo llamado matx.raw.

cardano-cli transaction build \
--testnet-magic 1097911063 \
--alonzo-era \
--tx-in $txhash#$txix \
--tx-out $first_nft_owner_address+$fee+"$tokenamount $policyid.$tokenname" \
--change-address $payment_address \
--mint="$tokenamount $policyid.$tokenname" \
--minting-script-file $script --metadata-json-file metadata.json \
--witness-override 2
--out-file matx.raw
Enter fullscreen mode Exit fullscreen mode

IMPORTANTE: Si defines el valor - -change -address en $first_nft_owner_address, todo el saldo ADA de tu cartera de pagos será enviado a esa dirección. Si eres el propietario, entonces esto no es un problema.

Por ejemplo, supongamos que $first_nft_owner_address es tu cartera principal y transferiste 10 ADA de $first_nft_owner_address a $payment_address para acuñar un NFT. La acuñación del NFT puede costar 1,590889 ADA. Si deseas devolver los 8.6 ADA restantes para tu cartera principal, define - -change -address como $first_nft_owner_address. Pero si quieres acuñar otro NFT y mantener los 8,6 ADA en esa cartera temporal, defínela como $payment_address.

Si recibes un mensaje diciendo algo como Minimum required UTxO: Lovelace 1448244 cambia la tasa a ese valor. De lo contrario, continúa sin hacer ningún cambio. En este ejemplo, dice Estimated transaction fee: Lovelace 190889, entonces todo está bien.

fee=1448244 # Run this only if you got the above warning
Enter fullscreen mode Exit fullscreen mode

Si recibes un mensaje indicando que no tienes fondos suficientes para cubrir el costo de la transacción, puedes especificar una segunda entrada --tx-in. Por ejemplo, cuando ejecutamos la consulta por cardano-cli utxo --address $address --testnet-magic 1097911063, se muestra lo siguiente. Al especificar una segunda entrada --tx-in, pude combinar los fondos.

TxHash                                 TxIx        Amount
--------------------------------------------------------------------------------------
0ba233973412b629d8d1bcf6cf219a83c7cf16b59f84c1f2c488d80c5d0404dd     0        50000000 lovelace + TxOutDatumNone
77300dc0598bdc8268a706705ee7521f76bf29cdd9d0c7580b69c660f0f38bec     0        48220906 lovelace + TxOutDatumNone
Enter fullscreen mode Exit fullscreen mode

Para los curiosos, el archivo se ve así:

{
    "type": "TxBodyAlonzo",
    "description": "",
    "cborHex": "86a700818258200ba233973412b629d8d1bcf6cf219a83c7cf16b59f84c1f
    2c488d80c5d0404dd000d800182825839001cb186d6b9fba78652fca7a995fb1353a4f4ae
    cec323c34bf4546bd5b9e373273dac02ae41ac9ebad6f51b21b701aa39e1cf26571a96307
    91a3b828397825839001cb186d6b9fba78652fca7a995fb1353a4f4aecec323c34bf4546b
    d5b9e373273dac02ae41ac9ebad6f51b21b701aa39e1cf26571a963079821a00155cc0a15
    81c155f313f864d009d7b0b519b1295c9fab7b75c17cfc5ba1aed501b7ca14b546573744e
    46543132333401021a0002e9a90e8009a1581c155f313f864d009d7b0b519b1295c9fab7b
    75c17cfc5ba1aed501b7ca14b546573744e465431323334010758206a46c80316d784a2b4
    936540adca437283d949a52878616b9494eb60279878779f82008201818200581c6d13214
    90cde0b447794edff9239cf0668ae01f0df33823d0a3bbcf7ff8080f5d90103a100a11902
    d1a2783831353566333133663836346430303964376230623531396231323935633966616
    23762373563313763666335626131616564353031623763a1763534363537333734346534
    3635343331333233333334a46b6465736372697074696f6e744a75737420616e6f7468657
    22066756e204e465465696d616765827568747470733a2f2f697066732e696f2f69706673
    2f782e516d5268545462557250594577336d4a4747685171515354396b383676314450426
    95454574a474b444a73564677696d656469615479706569696d6167652f706e67646e616d
    656b546573744e4654313233346776657273696f6e63312e30"
Enter fullscreen mode Exit fullscreen mode

A ver qué dice:
Accede a cbor.me
Pega el valor de cborHex en el cuadro de la derecha.
Marca las cuatro casillas de verificación arriba de este cuadro (como texto, utf8, emb cbor, cborseq)
Haz clic en la flecha verde ← junto a la palabra “Bytes”

La caja de la izquierda ahora contendrá algo así:

[{0: [[h'0BA233973412B629D8D1BCF6CF219A83C7CF16B59F84C1F2C488D80C5D0404DD', 0]],
13: [], 1: [[h'001CB186D6B9FBA78652FCA7A995FB1353A4F4AECEC323C34BF4546BD5B9E3732
73DAC02AE41AC9EBAD6F51B21B701AA39E1CF26571A963079', 998409111], [h'001CB186D6B9F
BA78652FCA7A995FB1353A4F4AECEC323C34BF4546BD5B9E373273DAC02AE41AC9EBAD6F51B21B70
1AA39E1CF26571A963079', [1400000, {h'155F313F864D009D7B0B519B1295C9FAB7B75C17CFC
5BA1AED501B7C': {'TestNFT1234': 1}}]]], 2: 190889, 14: [], 9: {h'155F313F864D009
D7B0B519B1295C9FAB7B75C17CFC5BA1AED501B7C': {'TestNFT1234': 1}}, 7: h'6A46C80316
D784A2B4936540ADCA437283D949A52878616B9494EB6027987877'}, [[0, [1, [[0, h'6D1321
490CDE0B447794EDFF9239CF0668AE01F0DF33823D0A3BBCF7']]]]], [], [], true, 259({0:
{721: {"155f313f864d009d7b0b519b1295c9fab7b75c17cfc5ba1aed501b7c": {"546573744e4
65431323334": {"description": "Just another fun NFT", "image": ["https://ipfs.io
/ipfs/", "QmRhTTbUrPYEw3mJGGhQqQST9k86v1DPBiTTWJGKDJsVFw"], "mediaType": "image/
png", "name": "TestNFT1234"}}, "version": "1.0"}}})]
Enter fullscreen mode Exit fullscreen mode

Es obvio lo que todo esto significa, entonces no me voy a tomar el trabajo de explicarlo. 🙃 Puedes ver el código fuente de Cbor.hs si estuvieses interesado en entrar en esa madriguera.

Firmar la transacción

Para demostrar que autorizamos esta transacción, debemos firmarla utilizando la clave de pago y Policy Key que generamos anteriormente. Recuerda, nunca compartas estas claves con nadie.

cardano-cli transaction sign \
--signing-key-file payment.skey \
--signing-key-file policy/policy.skey \
--testnet-magic 1097911063 \
--tx-body-file matx.raw \
--out-file matx.signed
Enter fullscreen mode Exit fullscreen mode

Envía la transacción al blockchain

Hasta este punto, solo leemos del blockchain Cardano Testnet. Pero una vez que ejecutamos el comando de abajo, estamos grabando en el blockchain. No hay vuelta atrás.

cardano-cli transaction submit \
--tx-file matx.signed \
--testnet-magic 1097911063
Enter fullscreen mode Exit fullscreen mode

Debes ver el mensaje:

Transaction successfully submitted.

Confirma si funcionó

Ve para https://testnet.cardanoscan.io/ y busca la dirección de la cartera (aquella almacenada en $first_nft_owner_address). Utiliza la lista desplegable para ver los tokens.

Si todavía no está visible, espera de 10 a 30 segundos y verifica nuevamente.

Devuelve la prueba ADA para el faucet

Si ya estuviese todo terminado, es recomendable que devuelvas cualquier tAda restante al faucet.

Haga esto en la Red Principal

Si todo funcionó como esperabas, ahora puedes hacer esto en la Red Principal. Substituye --testnet-magic 1097911063 por --mainnet en todos los comandos de esta guía.

Este artículo es una traducción de Christopher Huxley realizada por Delia Viloria T. Puedes encontrar el artículo original aquí.

Discussion (0)