Um token é uma unidade de valor digital que representa ativos ou direitos em uma blockchain ou tecnologia de registro distribuído (DLT). Eles são digitais, programáveis, transferíveis e podem representar uma ampla variedade de ativos, desde dinheiro até ativos únicos como obras de arte.
Neste tutorial, nosso principal objetivo é orientá-lo na criação de seu próprio token personalizado na blockchain Solana.
Um token é uma unidade de valor digital que representa ativos ou direitos em uma blockchain ou tecnologia de registro distribuído (DLT). Eles são digitais, programáveis, transferíveis e podem representar uma ampla variedade de ativos, desde dinheiro até ativos únicos como obras de arte. Os tokens desempenham papéis cruciais nas blockchains, incluindo acesso a serviços, votações de governança, recompensas em DeFi e muito mais. Eles são a base de inovações nas tecnologias blockchain e na economia digital.
De maneira geral, os tokens têm como finalidade a representação de posse de diversos ativos, sejam valores financeiros ou ativos digitais. Para criar um token com sucesso, é fundamental cumprir alguns requisitos essenciais, como a capacidade de criar e configurar tokens, realizar operações de minting para gerar novos tokens e efetuar transferências.
Os programas Solana são essencialmente contratos inteligentes ou aplicações descentralizadas (dApps) que se executam na rede Solana. Eles são escritos na linguagem de programação Rust e compilados em formato binário. Um Token Program é um programa padrão na blockchain Solana que define uma implementação comum para tokens fungíveis e não fungíveis. O Token Program é responsável pela criação, gestão e operações relacionadas a tokens na rede, permitindo a criação e operação eficiente de ativos digitais.
O primeiro passo para iniciar a construção de um token na Solana é a preparação do ambiente de desenvolvimento. Isso implica a criação de um diretório de projeto e a instalação das bibliotecas necessárias. Aqui está um resumo do passo inicial:
mkdir token-spl
npm init
Para interagir com tokens na Solana, você precisará instalar as bibliotecas apropriadas. Use os seguintes comandos npm para instalar as bibliotecas necessárias:
npm install @solana/spl-token
npm install @solana/web3.js
npm install bs58
npm install dotenv
Com esses passos iniciais concluídos, você está pronto para começar a construir seu token na blockchain Solana. O diretório do projeto está configurado, e você tem as bibliotecas necessárias à sua disposição para facilitar o desenvolvimento. Agora, você pode prosseguir com a configuração, desenvolvimento e implementação de seu token personalizado.
A Devnet é a rede de desenvolvimento da Solana, que permite testar e desenvolver aplicações e scripts sem gastar ativos reais. Para obtê-la:
solana-cli.
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:
airdrop.js no diretório do seu projeto. Este arquivo conterá o código JavaScript para o airdrop.
// 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 em 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 unidade mais pequena 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,
})
package.json no diretório do seu projeto.
package.json, encontre a seção "scripts" e adicione um novo script chamado "airdrop" que executará o arquivo airdrop.js:
"scripts": {
"airdrop": "node airdrop.js"
}
Agora que você configurou o script, pode executá-lo facilmente usando npm:
package.json.
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 utilizada para a execução dos próximos scripts no projeto de criação do token.
A criação de um token na rede Solana é um processo detalhado que envolve várias etapas.
// 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 em 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("Saldo", vl)
// Define o "pagador" da criação do token
const payer = key
// Define a autoridade de criação do token (mintAuthority) e a autoridade de congelamento (freezeAuthority) como a mesma chave
const mintAuthority = key
const freezeAuthority = key
// Cria um token fungível com 9 decimais (para atender 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 SPL Token, uma biblioteca de código aberto para Solana. Aqui está uma descrição resumida do que está acontecendo no código:
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 com a 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 decimais do token.
connection: A conexão com a 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 decimais do token.
Os tokens, quando são criados inicialmente via spl-token, não têm “supply”.
Lembre-se de que este é um exemplo simplificado. A criação e gestão 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.
Realizar o "mint" (emissão) de tokens na rede Solana é um passo fundamental para criar e distribuir esses ativos digitais.
// 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 em 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("Saldo", 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 de token
let tokenAddr = '9RE5hEQV5SLRwr7PANryxYMZsootEkY5txxJyRNU4FYR'
const tokenAccount = new web3.PublicKey(tokenAddr)
// Obtém informações sobre o token associado ao endereço da conta de 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 minting do token como a conta do usuário
const mintAuthority = user
// Realiza o minting de tokens na conta do usuário
await token.mintTo(
connection,
user,
mintInfo.address,
tokenMint.address,
mintAuthority,
100000000000 // devido à configuração de 9 decimais para o token
)
O código anterior 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 "minting" com os seguintes passos:
Antes de realizar o minting, é importante criar uma conta para manter o saldo do novo token. Neste caso, a conta de saldo é "tokenMint.address".
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 com a rede Solana.
user: A conta que vai pagar a transação.
mintInfo.address: O endereço do mint (token) a ser criado.
tokenMint.address: O endereço de destino dos tokens após o mint (token que será emitido).
mintAuthority: A autoridade que controla o minting.
100000000000: O número de tokens a serem criados, considerando que o token possui 9 decimais.
Após a execução deste código, a conta "tokenMint.address" terá 1000 tokens emitidos nela, prontos para serem usados ou distribuídos conforme necessário.
O minting de tokens é um procedimento fundamental para criar ativos digitais na Solana, e esta operação permite o controle e distribuição desses ativos de forma eficaz na rede.
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. A seguir, um resumo dos passos para realizar essa tarefa:
Passo 1: Importação da Chave Privada
Passo 2: Instalação dos Pacotes Necessários
Para criar os metadados do token com Metaplex, você precisará instalar algumas dependências:
npm install @metaplex-foundation/js
npm install typescript ts-node
Passo 3: Uso de Metaplex para a Criação de Metadados
Agora que você tem as dependências instaladas, pode usar o Metaplex para criar os metadados do token:
.ts) que utilize as funcionalidades de Metaplex para criar os metadados do 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 aos seus tokens. Primeiro verifique na sua wallet ou no Solscan como seu token está representado.
No código a seguir, você está criando uma conta de metadados associada a um token na Solana e carregando informações sobre o token, como nome, símbolo, descrição e imagem. Os passos incluem a configuração das informações do token, o carregamento de uma imagem, o carregamento de metadados e a criação da conta de metadados na blockchain.
// 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 de 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 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 o Metaplex
const file = toMetaplexFile(buffer, imageFile)
// Carrega a imagem em 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
// Carrega os 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]);
metadata.ts, você pode executá-lo da seguinte maneira:
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 aos seus tokens. Certifique-se de seguir as diretrizes e documentação do Metaplex para criar metadados precisos e completos para seus tokens Solana.
A transferência de tokens na rede Solana implica a mobilização de ativos digitais de uma conta para outra. Para realizar esse processo, você pode seguir os seguintes passos:
Identificação das Contas
Para iniciar uma transferência de tokens, você precisa ter as seguintes informações:
Criação da Transação
Você precisará criar uma transação que especifique a transferência de tokens. Isso implica a construção de uma transação Solana que inclua as informações necessárias:
Também é possível 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 assegura 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 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 status da transação para garantir que a transferência foi 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".
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 abaixo demonstra como criar essas contas associadas:
// Define o valor da quantidade que deseja transferir (50 tokens, neste caso)
let amount = 50 * 10 ** mintInfo.decimals
// Cria a conta de token associada para o remetente
const fromTokenAccount = await token.getOrCreateAssociatedTokenAccount(
solConnection,
from,
mint,
from.publicKey
)
// Cria a conta de token associada para o destinatário (forneça o endereço toPublicKey)
const toTokenAccount = await token.getOrCreateAssociatedTokenAccount(
solConnection,
from,
mint,
toPublicKey
)
Uma vez que as contas de token associadas tenham sido criadas, você pode proceder com a transferência dos tokens. O código abaixo demonstra como realizar a transferência:
// Realiza 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 utilizada para efetuar a transferência dos tokens da conta "fromTokenAccount" para a conta "toTokenAccount". Certifique-se de que as contas associadas tenham sido configuradas corretamente antes de executar a transferência. A variável "signature" conterá a assinatura da transação após a conclusão da transferência.
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.
// 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 Saldo");
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:
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.
tokenAccounts.value.forEach((tokenAccount) => { ... }: Iteramos por todas as 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.
Neste tutorial, exploramos a criação de um token na blockchain Solana, utilizando a biblioteca SPL-Token. Aprendemos a criar tokens, configurar suas propriedades e realizar transferências. No entanto, este é apenas o começo. 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.
Jorge García
Fullstack developer