Desenvolvendo um Token na Blockchain Solana com JavaScript
Tags: webdev, solana, javascript, token
Published: 2023-10-30 01:04:48


Neste tutorial, nosso principal objetivo é guiar você na criação de seu próprio token personalizado na Solana.

## O que é uma token ?

Uma token é uma unidade de valor digital que representa ativos ou direitos em uma blockchain ou tecnologia de registro distribuído (DLT). Elas são digitais, programáveis, transferíveis e podem representar uma ampla variedade de ativos, desde dinheiro até ativos únicos como obras de arte. As tokens desempenham papéis cruciais em blockchains, incluindo acesso a serviços, votações em governança, recompensas em DeFi e muito mais. São a base de inovações nas tecnologias blockchain e na economia digital.

No geral, tokens têm como finalidade a representação de posse de diversos ativos, sejam eles valores financeiros ou ativos digitais. Para criar um token com êxito, é fundamental atender a alguns requisitos essenciais, que incluem a capacidade de criar e configurar tokens, realizar operações de mintagem para gerar novos tokens e efetuar transferências.

## Tipos de conta (Solana) 
 
1. **Contas PDA:** As contas PDA são contas especiais criadas a partir de contas programa. Elas são derivadas de contas programa usando uma fórmula específica que inclui um endereço base, uma semente (seed), é um programa para derivar a chave pública. Essa derivação permite que cada PDA tenha seu próprio endereço exclusivo. PDAs são usadas para armazenar dados específicos de um usuário ou realizar operações em nome de um usuário sem exigir que o usuário crie contas separadas para cada ação.


2. **Conta Programa (Program Account):** Cada programa tem uma conta associada a ele. Essa conta armazena o código binário do programa e os dados relacionados à conta. As contas programa são usadas para definir a lógica dos programas e contratos inteligentes na rede.

3. **Conta de Usuário (User Account):** As contas de usuário são contas tradicionais na rede Solana que representam os ativos e identidade dos usuários. Elas são usadas para armazenar saldos de criptomoedas, tokens não fungíveis (NFTs) e outros ativos digitais, bem como para realizar transações e interações na blockchain.

4. **Contas associadas ( Associated Token Account ):** As contas associadas são vinculadas a contas de usuário na Solana. Isso significa que elas estão diretamente conectadas a uma conta de usuário específica e podem ser usadas para representar os ativos pertencentes a esse usuário.Elas oferecem escalabilidade, herdam a segurança da conta de usuário e são flexíveis para diversos casos de uso, sendo amplamente empregadas em aplicativos descentralizados e representação de ativos digitais.

![Fluxo das contas Solana](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/500psigak3jga5olbt65.png)

## Token Program

 Os programas Solana são essencialmente contratos inteligentes ou aplicativos descentralizados (dApps) que são executados na rede Solana. Eles são escritos em linguagem de programação Rust e compilados para o formato binário.
 Um _Token Program_ e um programa padrão na blockchain Solana,este programa define uma implementação comum para tokens fungíveis e não fungíveis.O token program é responsável pela criação, gerenciamento e operações relacionadas a tokens na rede, permitindo a criação e operação eficiente de ativos digitais.


![Token Program account](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/79fr5nu20zpvpnscxxx1.png)

## Pré-requisitos:

1. **Conhecimento Básico de Blockchain:** É fundamental ter uma compreensão mínima de como as blockchains funcionam para entender o processo de criação de tokens na Solana.
A blockchain Solana, com sua impressionante velocidade e escalabilidade, tem desempenhado um papel de destaque no cenário das criptomoedas e ativos digitais. Nesse contexto, os tokens desempenham um papel central. Eles são a espinha dorsal das aplicações na Solana, desde NFTs (Tokens Não Fungíveis) até projetos DeFi (Finanças Descentralizadas) inovadores.

> Blockchain é um conjunto de registros digitais descentralizados, funcionando como um livro-razão público e imutável. Ele registra transações em blocos encadeados, onde cada bloco contém um conjunto de transações. A característica fundamental do blockchain é a sua imutabilidade: uma vez que um bloco é adicionado, ele não pode ser alterado. Isso assegura a segurança e a integridade dos dados, tornando o blockchain resistente à adulteração e confiável para diversas aplicações.

2. **Conta na Solana:** Para interagir com a rede Solana, você precisa de uma conta Solana. Certifique-se de criar uma conta usando a Solana Wallet. As contas são identificadas por endereços de 256 bits e desempenham um papel essencial no ecossistema Solana, permitindo a realização de transações e a gestão de ativos digitais.

3. **Solana Command Line Tools:** É necessário ter as ferramentas de linha de comando da Solana instaladas. Você pode obtê-las no site oficial da Solana (https://docs.solana.com/cli). Essas ferramentas facilitam a interação com a rede Solana e são essenciais para criar e gerenciar tokens.

4. **Linguagem de Programação JavaScript:** Ter o Node.js instalado na máquina local é importante, e uma sugestão é usar o Node Version Manager (NVM) (https://github.com/nvm-sh/nvm) para gerenciar as versões do Node.js, o que evita a necessidade de alterar a instalação em diversos projetos. O Node.js é frequentemente usado para o desenvolvimento de aplicativos que interagem com a Solana e seus contratos inteligentes.

Garantindo a conformidade com estes requisitos iniciais.Vamos iniciar o processo de desenvolver a token. 

## Iniciar o projeto

O primeiro passo para iniciar a construção de uma token na Solana é a preparação do ambiente de desenvolvimento. Isso envolve a criação de um diretório de projeto e a instalação das bibliotecas necessárias. Aqui está um resumo do passo inicial:

1. **Crie um Diretório:**
   ```
   mkdir token-spl
   ```

2. **Inicialize o Projeto com npm:**
   ```
   npm init
   ```

3. **Instale as Bibliotecas Necessárias:**

   - Para interagir com tokens na Solana, você precisará instalar as bibliotecas apropriadas. Use os seguintes comandos npm para instalar as bibliotecas requeridas:

   ```
   npm install @solana/spl-token
   npm install @solana/web3.js
   npm install bs58
   npm install dotenv
   ```

Com essas etapas iniciais concluídas, você está pronto para começar a construir sua token na blockchain Solana. O diretório do projeto está configurado, e você tem as bibliotecas necessárias à disposição para facilitar o desenvolvimento. Agora, você pode prosseguir com a configuração, desenvolvimento e implantação da sua token personalizada.

## Script para obter faucets de Solana

A Devnet é a rede de desenvolvimento da Solana, que permite testar e desenvolver aplicativos e scripts sem gastar ativos reais. Para obtê-la:

- Certifique-se de que você possui as ferramentas necessárias da Solana instaladas, incluindo o `solana-cli`.

- Execute o seguinte comando para definir a rede Devnet como a rede padrão:
   ```
   solana config set --url https://api.devnet.solana.com
   ```
Agora você pode criar um arquivo JavaScript para o script e configurar o `package.json` para torná-lo executável:

1. Crie um arquivo chamado `airdrop.js` no diretório do seu projeto. Este arquivo conterá o código JavaScript para airdrop. 
   ```javascript
// Decodifica a chave privada da variável de ambiente PRIVATE_KEY_1 usando o formato base58
var secretKey1 = bs58.decode(process.env.PRIVATE_KEY_1)

// Cria um par de chaves (chave pública e chave privada) a partir da chave privada decodificada
const key = Keypair.fromSecretKey(secretKey1)

// Imprime a chave pública no formato base58 no console
console.log("KEY", key.publicKey.toBase58())

// Cria uma conexão com a rede Solana (no ambiente de desenvolvimento Devnet)
const connection = new Connection(
    clusterApiUrl('devnet'),
    'confirmed'
)

// Solicita um airdrop (distribuição gratuita de Solana) para a chave pública da conta
const airdropSignature = await connection.requestAirdrop(
    key.publicKey,
    LAMPORTS_PER_SOL, // Quantidade de lamports (a menor unidade de Solana)
)

// Obtém o hash do bloco mais recente na rede Solana
const latestBlockHash = await prog.provider.connection.getLatestBlockhash()

// Confirma a transação do airdrop, especificando o bloco, a altura do bloco e a assinatura
await prog.provider.connection.confirmTransaction({
    blockhash: latestBlockHash.blockhash,
    lastValidBlockHeight: latestBlockHash.lastValidBlockHeight,
    signature: airdropSignature,
})
```

2. Abra o arquivo `package.json` no diretório do seu projeto.

3. Dentro de `package.json`, encontre a seção `"scripts"` e adicione um novo script chamado "airdrop" que executará o arquivo `airdrop.js`:
   ```json
   "scripts": {
       "airdrop": "node airdrop.js"
   }
   ```

Agora que você configurou o script, pode executá-lo facilmente usando o `npm`:

1. Abra o terminal.

2. Navegue até o diretório do seu projeto onde o arquivo `package.json` está localizado.

3. Execute o script airdrop com o seguinte comando:
   ```
   npm run airdrop
   ```

Isso executará o script `airdrop.js` e realizará as operações especificadas no código do script. Certifique-se de que o script esteja configurado corretamente para executar as ações desejadas, como airdrop de tokens, e que sua conta Solana na Devnet tenha os recursos necessários para realizar as transações.Observação: Esta configuração pode ser empregada para a execução dos próximos scripts no projeto de criação do token.

## Criando seu próprio token fungível 

A criação de um token na rede Solana é um processo detalhado que envolve várias etapas. 

   ```javascript
// Decodifica a chave privada da variável de ambiente PRIVATE_KEY_1 usando o formato base58
var secretKey1 = bs58.decode(process.env.PRIVATE_KEY_1)

// Cria um par de chaves (chave pública e chave privada) a partir da chave privada decodificada
const key = Keypair.fromSecretKey(secretKey1)

// Imprime a chave pública no formato base58 no console
console.log("KEY", key.publicKey.toBase58())

// Cria uma conexão com a rede Solana (no ambiente de desenvolvimento Devnet)
const connection = new Connection(
    clusterApiUrl('devnet'),
    'confirmed'
)

// Obtém o saldo da conta associada à chave pública
const vl = await connection.getBalance(key.publicKey)
console.log("Balance", vl)

// Define o "pagador" (payer) da criação do token
const payer = key

// Define a autoridade de criação do token (mintAuthority) e autoridade de congelamento (freezeAuthority) como a mesma chave
const mintAuthority = key
const freezeAuthority = key

// Cria um token fungível com 9 casas decimais (para corresponder ao padrão da CLI)
const mintToken = await token.createMint(
    connection,
    payer,
    mintAuthority.publicKey,
    freezeAuthority.publicKey,
    9
)
```

O código é um exemplo de como criar um token fungível usando o SPL Token, uma biblioteca de código aberto para a Solana. Aqui está uma descrição resumida do que está acontecendo neste código:

   - Localiza no código a linha da função  `createMint`: demonstra a criação do token fungível. Para isso, você está utilizando a função `createMint`, que requer vários parâmetros:
     - `connection`: A conexão à rede Solana.
     - `payer`: A conta que pagará as taxas da transação.
     - `mintAuthority.publicKey`: A chave pública da autoridade de criação do token.
     - `freezeAuthority.publicKey`: A chave pública da autoridade de congelamento (opcional).
     - `9`: O número de casas decimais do token.

Os tokens quando criados inicialmente pelo spl-token não têm “supply”.
 
Lembre-se de que esse é um exemplo simplificado. A criação e gerenciamento de tokens na Solana envolve mais detalhes, como a gestão de autoridades, configuração de políticas de emissão e segurança. Certifique-se de entender completamente o processo e suas implicações antes de criar tokens na rede Solana.

## Mint das tokens

Realizar o "mint" (emissão) de tokens na rede Solana é um passo fundamental para criar e distribuir esses ativos digitais. 

   ```javascript
// Decodifica a chave privada da variável de ambiente PRIVATE_KEY_1 usando o formato base58
var secretKey1 = bs58.decode(process.env.PRIVATE_KEY_1)

// Cria um par de chaves (chave pública e chave privada) a partir da chave privada decodificada
const key = web3.Keypair.fromSecretKey(secretKey1)

// Imprime a chave pública no formato base58 no console
console.log("KEY", key.publicKey.toBase58())

// Cria uma conexão com a rede Solana (no ambiente de desenvolvimento Devnet)
const connection = new web3.Connection(
    web3.clusterApiUrl('devnet'),
    'confirmed'
)

// Obtém o saldo da conta associada à chave pública
const vl = await connection.getBalance(key.publicKey)
console.log("Balance", vl)

// Define a conta do usuário como a chave pública da chave
const user = key

// Define a conta de destino como a chave pública da chave
const to = key.publicKey

// Define o endereço da conta token
let tokenAddr = '9RE5hEQV5SLRwr7PANryxYMZsootEkY5txxJyRNU4FYR'
const tokenAccount = new web3.PublicKey(tokenAddr)

// Obtém informações sobre o token associado ao endereço da conta token
const mintInfo = await token.getMint(
    connection,
    tokenAccount
)

// Cria ou obtém a conta de token associada à conta do usuário
const tokenMint = await token.getOrCreateAssociatedTokenAccount(
    connection,
    user,
    mintInfo.address,
    key.publicKey
)

// Define a autoridade de mintagem do token como a conta do usuário
const mintAuthority = user

// Realiza a mintagem de tokens na conta do usuário
await token.mintTo(
    connection,
    user,
    mintInfo.address,
    tokenMint.address,
    mintAuthority,
    100000000000 // devido à configuração de 9 casas decimais para o token
)
``` 
O código acima  demonstra a execução desse processo, e aqui está uma descrição do que está acontecendo:

Para adicionar 1000 tokens à conta “tokenMint.address”, é necessário executar a operação de "mintagem" com as seguintes etapas:

1. **Criação de Conta de Saldo:**
   Antes de realizar a mintagem, é importante criar uma conta para manter o saldo do novo token. Neste caso, a conta de saldo é "tokenMint.address".

2. **Mintagem dos Tokens:**
   O código utiliza a função `token.mintTo` para criar 1000 tokens e adicioná-los à conta "tokenMint.address". Isso envolve os seguintes parâmetros:
   - `connection`: A conexão à rede Solana.
   - `user`: A conta que vai pagar a transação.
   - `mintInfo.address`: O endereço de mint (token) a ser criada.
   - `tokenMint.address`: O endereço destino das tokens após o mint  (token que será emitido).
   - `mintAuthority`: A autoridade que controla a mintagem.
   - `100000000000`: O número de tokens a serem criados, considerando que a token possui 9 casas decimais.

Após a execução deste código, a conta "tokenMint.address" terá 1000 tokens mintados nela, prontos para serem usados ou distribuídos conforme necessário.

A mintagem de tokens é um procedimento fundamental para criar ativos digitais na Solana, e essa operação permite o controle e distribuição desses ativos de forma eficaz na rede.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/194546fk45iyvzpbfz27.png)

## Os metadados , nome , sigla , imagem da token

A criação de metadados para tokens Solana com Metaplex é um processo essencial para associar informações e características específicas aos ativos digitais que você está emitindo. Abaixo estão os passos resumidos para realizar essa tarefa:


**Passo 1: Importação da Chave Privada**

1. Importe sua chave privada em sua carteira Solana. Certifique-se de que a chave privada corresponda à conta que possui a token "Unrecognized Token". Isso permitirá que você tenha acesso aos ativos digitais e realize operações com eles.

**Passo 2: Instalação de Pacotes Necessários**

Para criar os metadados da token com Metaplex, você precisará instalar algumas dependências:

1. Instale a biblioteca Metaplex usando npm:
   ```
   npm install @metaplex-foundation/js
   ```

2. Instale o TypeScript e o pacote ts-node para suportar a execução de scripts TypeScript:
   ```
   npm install typescript ts-node
   ```

**Passo 3: Utilização do Metaplex para a Criação de Metadados**

Agora que você tem as dependências instaladas, você pode usar o Metaplex para criar os metadados da token:

1. Escreva um script TypeScript (`.ts`) que utiliza as funcionalidades do Metaplex para criar os metadados da token. Você pode criar um novo arquivo, por exemplo, `metadata.ts`, e escrever o código necessário nele.

A criação de metadados pode envolver configurações específicas, como imagens, descrições e outros detalhes associados às suas tokens.Antes veja na sua wallet ou na solscan como a sua token está representada. 


![token metadata account](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hncl16ks7cgq2wan90fc.png)

No código abaixo, você está criando uma conta de metadados associada a um token na Solana e fazendo upload de informações sobre o token, como nome, símbolo, descrição e imagem. As etapas incluem a configuração de informações do token, o upload de uma imagem, o upload de metadados e a criação da conta de metadados na blockchain.

  ```javascript
// Decodifica a chave privada da variável de ambiente PRIVATE_KEY_1
var secretKey = bs58.decode(process.env.PRIVATE_KEY_1 as string)

// Cria um objeto Keypair a partir da chave privada decodificada
const user = web3.Keypair.fromSecretKey(secretKey)

// Imprime a chave pública do usuário
console.log("KEY", user.publicKey.toBase58())

// Define informações iniciais do token (nome, símbolo, descrição e imagem)
const MY_TOKEN_METADATA: UploadMetadataInput = {
  name: "Happy",
  symbol: "•‿•",
  description: "Happy - distribute happiness",
  image: "TO_UPDATE_LATER" // substitua pelo URL público da imagem
}

// Cria um objeto ON_CHAIN_METADATA baseado nas informações iniciais do token
const ON_CHAIN_METADATA = {
  name: MY_TOKEN_METADATA.name,
  symbol: MY_TOKEN_METADATA.symbol,
  uri: 'TO_UPDATE_LATER',
  sellerFeeBasisPoints: 0,
  creators: null,
  collection: null,
  uses: null
} as DataV2

// Cria uma conexão com a rede Solana (no ambiente de desenvolvimento Devnet)
const connection = new web3.Connection(
  web3.clusterApiUrl('devnet'),
  'confirmed'
)

// Cria uma instância do Metaplex para interagir com os contratos Metaplex
const metaplex = Metaplex.make(connection)
  .use(keypairIdentity(user))
  .use(bundlrStorage({
    address: 'https://devnet.bundlr.network',
    providerUrl: web3.clusterApiUrl('devnet'),
    timeout: 60000,
  }))

// Carrega um arquivo de imagem a partir do sistema de arquivos
const imageFile = "happy.png"
const buffer = fs.readFileSync("img/" + imageFile)

// Converte o buffer da imagem em um formato compatível com Metaplex
const file = toMetaplexFile(buffer, imageFile)

// Faz o upload da imagem para um serviço de armazenamento e obtém o URI da imagem
const imageUri = await metaplex.storage().upload(file)
console.log("image uri:", imageUri)

// Atualiza o URI da imagem nos metadados do token
MY_TOKEN_METADATA.image = imageUri

// Faz o upload dos metadados e obtém o URI dos metadados
const metaURI = await metaplex.nfts().uploadMetadata(MY_TOKEN_METADATA)
console.log(`Arweave URL: `, metaURI)

// Atualiza o URI dos metadados ON_CHAIN_METADATA
ON_CHAIN_METADATA.uri = metaURI.uri

// Define o endereço da conta do token
let mitTokenAddr = '9RE5hEQV5SLRwr7PANryxYMZsootEkY5txxJyRNU4FYR'
const mintAccount = new web3.PublicKey(mitTokenAddr)

// Obtém informações sobre a conta do token
const mintKeypair = await getMint(
  connection,
  mintAccount
)
console.log(mintKeypair.address)

// Obtém informações sobre a conta PDA (Program Derived Address) dos metadados
const metadataPDA = await metaplex.nfts().pdas().metadata({ mint: mintKeypair.address })

// Cria uma transação para criar uma nova conta de metadados na blockchain Solana
const createNewMetadataTransaction = new web3.Transaction().add(
  createCreateMetadataAccountV3Instruction({
    metadata: metadataPDA,
    mint: mintKeypair.address,
    mintAuthority: user.publicKey,
    payer: user.publicKey,
    updateAuthority: user.publicKey,
  }, {
    createMetadataAccountArgsV3: {
      data: ON_CHAIN_METADATA,
      isMutable: true,
      collectionDetails: null
    }
  })
)

// Obtém o bloco mais recente e define a transação recentBlockhash
let { lastValidBlockHeight, blockhash } = await connection.getLatestBlockhash('finalized');
createNewMetadataTransaction.recentBlockhash = blockhash;
createNewMetadataTransaction.lastValidBlockHeight = lastValidBlockHeight;
createNewMetadataTransaction.feePayer = user.publicKey;

// Envia e confirma a transação
const transactionId = await web3.sendAndConfirmTransaction(connection, createNewMetadataTransaction, [user]);          
```    
2. Execute o script TypeScript utilizando o pacote ts-node. Por exemplo, se o seu script se chama `metadata.ts`, você pode executá-lo da seguinte forma:
   ```
   ts-node metadata.ts
   ```


Lembre-se de que a criação de metadados pode envolver configurações específicas, como imagens, descrições e outros detalhes associados às suas tokens. Certifique-se de seguir as diretrizes e documentação do Metaplex para criar metadados precisos e completos para seus tokens Solana.


![Token Happy](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/hhxct38vtz3brlrieifk.gif)

## Transferência 

A transferência de tokens na rede Solana envolve a movimentação de ativos digitais de uma conta para outra. Para realizar esse processo, você pode seguir os passos a seguir:

**Identificação das Contas**

Para iniciar uma transferência de tokens, você precisa ter as seguintes informações:

- A conta de origem: A conta que detém os tokens que você deseja transferir.
- A conta de destino: A conta que receberá os tokens.
- A quantidade de tokens a serem transferidos.

**Criação da Transação**

Você precisará criar uma transação que especifique a transferência de tokens. Isso envolve a construção de uma transação Solana que inclui as informações necessárias:

- A conta de origem.
- A conta de destino.
- A quantidade de tokens a serem transferidos.

Você também pode incluir uma taxa de transação (fee) para pagar pelos recursos de rede utilizados na transferência.

**Assinatura da Transação**

A transação deve ser assinada com a chave privada da conta de origem para autenticar a operação. Isso garante que apenas o proprietário da conta possa efetuar a transferência.

**Envio da Transação**

A transação assinada é enviada para a rede Solana para ser processada. Você pode usar o `solana-web3.js` para enviar a transação para a rede.

**Confirmação da Transação**

A rede Solana processará a transação e, uma vez confirmada, a quantidade especificada de tokens será transferida da conta de origem para a conta de destino. Você pode verificar o estado da transação para garantir que a transferência tenha sido concluída com sucesso.

**Um exemplo**

Agora, exemplificarei o uso dos métodos de transferência e a criação de contas associadas. Com a biblioteca SPL-Token, todos os passos detalhados anteriormente serão simplificados e executados internamente no método "transfer".

- Criação de Contas de Token Associadas

Primeiro, o receptor deve criar uma conta de token associada para o tipo Token. Isso é necessário para receber os tokens. O destinatário obtém o endereço da carteira e o fornece ao remetente. O código a seguir demonstra como criar essas contas associadas:

```javascript
// Defina o valor da quantidade que você deseja transferir (50 tokens, neste caso)
let amount = 50 * 10 ** mintInfo.decimals

// Crie a conta de token associada para o remetente
const fromTokenAccount = await token.getOrCreateAssociatedTokenAccount(
    solConnection,
    from,
    mint,
    from.publicKey
)

// Crie a conta de token associada para o destinatário (forneça o endereço toPublicKey)
const toTokenAccount = await token.getOrCreateAssociatedTokenAccount(
    solConnection,
    from,
    mint,
    toPublicKey
)
```

- Realização da Transferência

Uma vez que as contas de token associadas tenham sido criadas, você pode proceder com a transferência dos tokens. O código a seguir demonstra como realizar a transferência:

```javascript
// Realize a transferência dos tokens da conta "fromTokenAccount" para a conta "toTokenAccount"
let signature = await token.transfer(
    solConnection,
    from,
    fromTokenAccount.address,
    toTokenAccount.address,
    from.publicKey,
    amount
)
```

Neste exemplo, a função `token.transfer` está sendo usada para efetuar a transferência dos tokens da conta "fromTokenAccount" para a conta "toTokenAccount". Certifique-se de que as contas associadas foram corretamente configuradas antes de executar a transferência. A variável "signature" conterá a assinatura da transação após a conclusão da transferência.

## Obtendo o saldo das tokens

Neste código, utilizamos a biblioteca Solana JavaScript (@solana/web3.js) para interagir com a blockchain Solana e consultar o saldo de tokens associados à chave pública `key.publicKey`. 

```javascript
// Obtém todas as contas de tokens associadas à chave pública
const tokenAccounts = await connection.getTokenAccountsByOwner(
    key.publicKey,
    {
        programId: token.TOKEN_PROGRAM_ID, // Programa de token padrão da Solana
    }
)

// Imprime um cabeçalho para a lista de tokens e saldos
console.log("Token                                         Balance");
console.log("------------------------------------------------------------");

// Itera sobre todas as contas de tokens retornadas
tokenAccounts.value.forEach((tokenAccount) => {
    // Decodifica os dados da conta para obter informações sobre o token
    const accountData = token.AccountLayout.decode(tokenAccount.account.data);

    // Imprime o endereço do token (mint) e o saldo da conta
    console.log(`${new web3.PublicKey(accountData.mint)}   ${accountData.amount}`);
})
```
Como o código funciona:

1. `const tokenAccounts = await connection.getTokenAccountsByOwner(key.publicKey, { programId: token.TOKEN_PROGRAM_ID })`: Esta linha solicita à rede Solana informações sobre todas as contas de tokens associadas à chave pública especificada. O parâmetro `programId` garante que apenas as contas relacionadas ao programa de token sejam retornadas.

2. A próxima seção do código formata e exibe os resultados em um formato legível. Ele cria uma tabela com duas colunas: "Token" e "Balance".

3. `tokenAccounts.value.forEach((tokenAccount) => { ... }`: Iteramos pelas contas de tokens retornadas e realizamos as seguintes ações para cada uma delas:

   a. Decodificamos os dados da conta usando `token.AccountLayout.decode(tokenAccount.account.data)`. Isso nos permite obter informações sobre o token, incluindo o mint (tipo de token) e o saldo.

   b. Imprimimos o endereço do token (mint) e o saldo da conta na tabela formatada.


![balance account](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/yvpx82jzeinbzkjwbx18.gif)


## Final ....
Neste tutorial, exploramos a criação de uma  token na blockchain Solana, usando a biblioteca SPL-Token. Aprendemos a criar tokens, configurar suas propriedades e realizar transferências.
No entanto, este é apenas o começo. A Solana oferece inúmeras oportunidades para a inovação, e você pode explorar ainda mais, criando aplicações personalizadas, tokens não fungíveis únicos e muito mais. Continue aprendendo, experimentando e contribuindo para a evolução da blockchain Solana.

## Referências:
   -[Token Program](https://spl.solana.com/token)
   -[Create Tokens With The Token Program](https://www.soldev.app/course/token-program)
  -[Repositório com os exemplos do tutorial - token-spl] (https://github.com/valterlobo/token-spl)

Espero que este tutorial tenha sido útil. Se você tiver alguma dúvida, não hesite em perguntar.