# Billeteras y cuentas

<div data-with-frame="true"><figure><img src="https://3385590278-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2Fgit-blob-2d782448481ac5b6f078b0307da62a30af1d8d6f%2FFrame%20316126255.jpg?alt=media" alt=""><figcaption></figcaption></figure></div>

{% hint style="info" %}
En Stacks, los términos 'address' y 'principal' se usan indistintamente.
{% endhint %}

## Introducción

Las wallets de Stacks son herramientas de software o hardware para almacenar criptomonedas, NFT y otros activos digitales. También se usan para establecer una identidad en cadena en aplicaciones descentralizadas (dApps). Estas wallets almacenan y gestionan criptográficamente la identidad y los fondos de cada usuario mediante una única dirección de blockchain, lo que aprovecha la criptografía de clave pública.

### Propósito de una wallet de Stacks

* Establecer la identidad del usuario
* Almacenar activos
* Mostrar saldos
* Firmar transacciones
* Firmar mensajes
* Participar en la economía de Bitcoin

Las wallets en Stacks constan de cuentas, que usan un modelo basado en cuentas, en lugar de un modelo UTXO como Bitcoin. Este modelo es más simple que el modelo UTXO y tiene un concepto más tradicional de “saldo”, similar al que encontrarías en un banco. En este modelo, cada dirección tiene una única cifra de “saldo” para un token determinado que aumenta/disminuye a medida que se envían transacciones desde/hacia esa cuenta. Esto es lo que usan la mayoría de los ecosistemas Web3. En un modelo UTXO, la red funciona como un libro mayor, donde cada UTXO es análogo a un billete de efectivo.

### Componentes de una cuenta de Stacks

<div data-with-frame="true"><figure><img src="https://3385590278-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FLK9iA5RYSuLt1pt6kcqL%2Fstacks-address-generation-flowchart.png?alt=media&#x26;token=f322e0cc-7d6d-4df6-a8d1-7cf08a8828ec" alt=""><figcaption></figcaption></figure></div>

* **Clave privada** - La clave privada es un código alfanumérico que está emparejado con una única clave pública en una relación 1:1. Nunca compartas tu clave privada con nadie. Una clave privada es la forma en que demuestras la propiedad de una clave pública y cómo puedes gastar los activos mantenidos por ese par de claves concreto.\
  \
  Ejemplo de clave privada en Stacks (32 bytes añadidos con un byte 0x01):\
  `5a4133fec2cf923d37238d3ba2fcd2ee9c8dce882c22218fd210d8a02ceb2c7401`
* **Clave pública** - La clave pública se deriva matemáticamente de la clave privada. Se puede compartir de forma segura y la red la usa para verificar las firmas creadas por la clave privada, sin revelar la propia clave privada.\
  \
  Ejemplo de clave pública en Stacks (formato comprimido):\
  `02e8eb87862945d369511fdcce326ffef9a01b68c7d070e3ce685a5cbb9b1ecfc5`
* **Dirección (Principal)** - La dirección es una representación más corta y fácil de usar derivada de la clave pública. Es lo que compartes para recibir sBTC, STX, tokens o NFT en Stacks, y actúa como el identificador en cadena del usuario.\
  \
  Ejemplo de dirección pública en Stacks (codificación c32check):\
  `SPM9G3CNGSCTB4956290NESM0MR9W9CCEPVEPSQC`

{% hint style="info" %}
La generación de claves privada/pública utiliza la curva criptográfica **secp256k1** .

El algoritmo de firma criptográfica usado en Stacks es **ECDSA** sobre **secp256k1**.

Las direcciones se crean generando el **RIPEMD-160** hash de **SHA256** de la clave pública. Las direcciones BTC se codifican con **Base58Check**. Para las direcciones de Stacks, se usa [**c32check**](https://github.com/stacks-network/c32check) .
{% endhint %}

Las cuentas de Stacks son entidades que poseen activos, como tokens de Stacks (STX). Una cuenta tiene una dirección, clave privada, nonce y uno o más saldos de activos. Los activos no pueden salir de una cuenta sin una acción del propietario de la cuenta. Todos los cambios en los activos (y en los saldos de la cuenta) requieren una transacción correspondiente.

Todas las wallets de Stacks también admiten direcciones de Bitcoin, lo que permite una participación fluida en los ecosistemas de Stacks y Bitcoin.

#### Formatos de direcciones <a href="#address-formats" id="address-formats"></a>

Las direcciones de Stacks usan diferentes prefijos para indicar la red a la que pertenecen, lo que facilita distinguir entre direcciones de mainnet y de testnet.

```typescript
// La dirección de mainnet comienza con 'SP'
const mainnetAddress = 'SP3FGQ8Z7JY9BWYZ5WM53E0M9NK7WHJF0691NZ159';

// La dirección multisig de mainnet comienza con 'SM'
const multisigMainnetAddress = 'SM3VDXK3WZZSA84XXFKAFAF15NNZX32CTSG82JFQ4'

// La dirección multisig de testnet comienza con 'SN'
const multisigTestnetAddress = 'SNJSPGVBFZHPXGESC9ZQWVFSNF4RHNNRTW2HYYJ7'

// La dirección de testnet comienza con 'ST'
const testnetAddress = 'ST2F4BK4GZH6YFBNHYDDGN4T1RKBA7DA1BJZPJEJJ';
```

***

## ¿Cómo crear una cuenta de Stacks?

Las cuentas de una wallet se generan a partir de una frase mnemónica de 24 palabras conforme al estándar BIP39. A esto a menudo se le denomina **frase semilla**. La frase semilla proporciona acceso a las cuentas de Stacks.

{% hint style="danger" %}
Si se pierde la frase semilla, no se puede restaurar el acceso a las cuentas asociadas. Ninguna persona u organización puede recuperar una frase semilla perdida.
{% endhint %}

Hay algunas formas diferentes de crear una cuenta de Stacks tanto como desarrollador como no desarrollador.

{% stepper %}
{% step %}

#### Usando Stacks.js

Para la generación programática de wallets o al restaurar cuentas desde una copia de seguridad, puedes derivar direcciones a partir de una frase semilla mnemónica. Cada wallet puede contener múltiples cuentas, todas derivadas de la misma frase semilla usando diferentes rutas de derivación.

{% code expandable="true" %}

```typescript
import { generateWallet, generateSecretKey, type Wallet, Account } from '@stacks/wallet-sdk';
import { privateKeyToAddress, privateKeyToPublic } from '@stacks/transactions'

// Genera una nueva frase semilla de 24 palabras
const secretKey: string = generateSecretKey();

// O usa una frase semilla existente
// const secretKey = 'frase semilla ya poseída ...';

const wallet: Wallet = await generateWallet({
  secretKey,
  password: 'optional-encryption-password',
});

// Obtén la clave pública y la dirección de la primera cuenta
const account: Account = wallet.accounts[0];
const publicKey = privateKeyToPublic(account.stxPrivateKey);
const mainnetAddress = privateKeyToAddress(account.stxPrivateKey, 'mainnet');

console.log('Clave privada:', account.stxPrivateKey);
console.log('Dirección:', mainnetAddress);
// Clave privada: 97ff523937735dc6c9e3180f98a6aa94f526fbe072230b99e07482260f59988c01
// Dirección: SP1WNA65XE3M665RJ9AC81J18XPMJ5QC5XJDHWXE
```

{% endcode %}

Para más formas de generar claves y cuentas programáticamente, consulta la guía [aquí](https://app.gitbook.com/s/Zz9BLmTU9oydDpL3qiUh/stacks.js/accounts-and-addresses).
{% endstep %}

{% step %}

#### Uso de la herramienta CLI de Stacks

Usar la herramienta CLI de Stacks te permite gestionar wallets desde la línea de comandos.

**`make_keychain`**

```bash
# Instala la CLI globalmente
npm install --global @stacks/cli

# Genera una nueva cuenta y guarda los detalles en un nuevo archivo.
# La opción '-t' hace que esta sea una cuenta de testnet
stx make_keychain -t > cli_keychain.json

# make_keychain muestra lo siguiente:
{
  "mnemonic": "aaa bbb ccc ddd ...",
  "keyInfo": {
    "privateKey": "5a3f1f15245bb3fb...",
    "address": "STJRM2AMVF90ER6G3RW1QTF85E3HZH37006D5ER1",
    "btcAddress": "biwSd6KTEvJcyX2R8oyfgj5REuLzczMYC1",
    "wif": "L4HXn7PLmzoNW...",
    "index": 0
  }
}
```

**`get_address`**

```bash
# Obtén la dirección de una clave privada o de un paquete de claves privadas multisig.
# Devuelve las direcciones BTC y STACKS

stx get_address f5185b9ca93bdcb5753fded3b097dab8547a8b47d2be578412d0687a9a0184cb01
{
  "BTC": "1JFhWyVPpZQjbPcXFtpGtTmU22u4fhBVmq",
  "STACKS": "SP2YM3J4KQK09V670TD6ZZ1XYNYCNGCWCVVKSDFWQ"
}

stx get_address 1,f5185b9ca93bdcb5753fded3b097dab8547a8b47d2be578412d0687a9a0184cb01,ff2ff4f4e7f8a1979ffad4fc869def1657fd5d48fc9cf40c1924725ead60942c01
{
  "BTC": "363pKBhc5ipDws1k5181KFf6RSxhBZ7e3p",
  "STACKS": "SMQWZ30EXVG6XEC1K4QTDP16C1CAWSK1JSWMS0QN"
}
```

Para más ejemplos de uso, consulta el repositorio de la CLI de Stacks [aquí](https://github.com/stx-labs/stacks.js/tree/main/packages/cli).
{% endstep %}

{% step %}

#### Usando extensiones/apps de wallet de Bitcoin L2

Hay muchas wallets populares de Bitcoin que admiten capas y metaprotocolos de Bitcoin. Leather y Xverse son opciones populares para comenzar con Stacks.

{% embed url="<https://youtu.be/RvTuex1jbGY?si=KGEGESS3sr38G_Tj>" %}
{% endstep %}

{% step %}

#### Usando otras herramientas creadas por la comunidad

Consulta el [Catálogo de herramientas de desarrollo de Stacks](https://app.gitbook.com/s/Zz9BLmTU9oydDpL3qiUh/stacks-devtools-catalog) para otras herramientas creativas de desarrollo para crear y gestionar wallets de Stacks.
{% endstep %}
{% endstepper %}

***

## ¿Cómo se formatean las direcciones de contratos de Clarity?

En Stacks, una **dirección/principal de contrato** identifica de forma única un contrato inteligente desplegado y está estructurada como un principal de cuenta más un espacio de nombres del contrato, formando una identidad única en cadena:

```
<dirección-del-desplegador>.<nombre-del-contrato>
```

#### Desglose de la estructura

1. **Dirección del desplegador**\
   Un principal estándar de Stacks (derivado de un hash160 de una clave pública), como:
   * `SP...` → mainnet
   * `ST...` → testnet
2. **Nombre del contrato**\
   Un identificador ASCII elegido en el momento del despliegue (por ejemplo, `my-token`, `amm-v1`, `nft-market`).

#### Por qué está estructurado de esta manera

Porque los identificadores de contrato están segmentados por el espacio de nombres de la dirección del desplegador:

* Dos cuentas diferentes pueden desplegar contratos con el mismo nombre.
* Una sola cuenta no puede desplegar dos contratos con el mismo nombre.
* El identificador es determinista y único a nivel global.

***

## Manejo de diferentes formatos

Es común que los nuevos desarrolladores de Stacks se confundan con las diferentes formas de especificar los principales de Stacks (también conocidos como direcciones) en su desarrollo.

Aquí tienes un desglose para tratar con principales en 3 casos de uso diferentes.

<div data-with-frame="true"><figure><img src="https://3385590278-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2F9habwlXLqQ25fu6TUVM5%2Fhandling-principal-formats.jpeg?alt=media&#x26;token=08fcc12c-ee57-48e9-9ab5-a18233773fe2" alt=""><figcaption></figcaption></figure></div>

***

### La conexión entre la dirección de Stacks y Bitcoin

Lo que hace que Stacks esté maravillosamente conectado con su capa de liquidación L1, Bitcoin, son sus muchos aspectos compartidos. Uno de ellos es cómo ambos utilizan un esquema similar de generación de direcciones basado en el formato P2PKH, lo que permite que tanto una dirección de Bitcoin como una de Stacks compartan el mismo hash de clave pública. Si decodificas con base58check una dirección legacy de bitcoin, puedes revelar el hash de la clave pública, que luego puede usarse para generar su correspondiente dirección de Stacks codificada en c32check.

Programáticamente, también podrías usar un método llamado `b58ToC32`, de la `c32check` biblioteca de JavaScript, que puede abstraer la conversión por ti.

<div data-with-frame="true"><figure><img src="https://3385590278-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FH74xqoobupBWwBsVMJhK%2Fuploads%2FVqWJul0cMmHoNGXiwsg3%2Fbitcoin-stacks-address-connection.jpeg?alt=media&#x26;token=90fe1ed0-29dc-4a1f-a2d4-0a89d57acc23" alt=""><figcaption></figcaption></figure></div>

***

### Recursos adicionales

* \[[Blog de Hiro](https://www.hiro.so/blog/understanding-the-differences-between-bitcoin-address-formats-when-developing-your-app)] Comprendiendo las diferencias entre los formatos de direcciones de Bitcoin
* \[[Blog de Hiro](https://www.hiro.so/blog/how-every-stacks-address-has-a-corresponding-bitcoin-address)] Cómo cada dirección de Stacks tiene una dirección de Bitcoin correspondiente
* \[[Blog de Hiro](https://www.hiro.so/blog/an-intro-to-web3-wallets-for-web3-founders)] Introducción a las wallets Web3 para fundadores de Web3
* \[[Blog de Hiro](https://www.hiro.so/blog/why-web3-needs-bitcoin-centric-wallet-standards)] Por qué Web3 necesita estándares de wallet centrados en Bitcoin
* \[[Stacks YT](https://youtu.be/RvTuex1jbGY?si=KGEGESS3sr38G_Tj)] Cómo configurar tu primera wallet de Bitcoin L2
* \[[SIP-005](https://github.com/stacksgov/sips/blob/main/sips/sip-005/sip-005-blocks-and-transactions.md)] Para el desglose técnico y el estándar sobre cómo se generan las wallets/cuentas.
