Токены на Солане

Токены - это цифровые активы, которые представляют собой права собственности на различные категории активов. Токенизация позволяет оцифровать права собственности, служа фундаментальным компонентом для управления как сменными, так и несменными активами.

  • Сменные токены представляют собой взаимозаменяемые и делимые активы одного типа и стоимости (например, USDC).
  • Несъемные токены (NFT) представляют собой собственность на неделимые активы (например, произведения искусства).

В этом разделе мы рассмотрим основы того, как токены представлены на Solana. Эти токены называются SPL (Solana Program Library) Tokens.

  • Программа токенов содержит всю логику команд для взаимодействия с токенами в сети (как сменными, так и несменными).

  • Монетный счет представляет определенный тип токена и хранит глобальные метаданные о нем, такие как общий запас и полномочия монетного двора (адрес, уполномоченный создавать новые единицы токена).

  • Токен-счет отслеживает индивидуальное владение количеством единиц конкретного типа токена (монетного счета), принадлежащего определенному адресу.

Info

В настоящее время существует две версии программы Token Program. Оригинальная программа Token Program и программа расширения Token Extensions Program (Token2022). Программа Token Extensions функционирует так же, как и оригинальная программа Token Program, но с дополнительными возможностями и улучшениями. Token Extensions Program - это версия, которую рекомендуется использовать для создания новых токенов (монетных счетов).

Ключевые точки #

  • Токены представляют собой право собственности на сменные (взаимозаменяемые) или несменные (уникальные) активы.

  • Программа Token Program содержит все инструкции по взаимодействию с сменными и несменными токенами в сети.

  • Программа расширений токенов - это новая версия Программы токенов, которая включает в себя дополнительные возможности при сохранении основных функций.

  • Учетная запись Mint представляет собой уникальный токен в сети и хранит глобальные метаданные, такие как общий объем предложения.

  • Токен-счет отслеживает индивидуальное владение токенами для конкретной учетной записи монетного двора.

  • Ассоциированный токен-аккаунт - это токен-аккаунт, созданный с адресом, полученным из адресов владельца и монетного счета.

Программа токена #

Программа токенов содержит всю логику взаимодействия с токенами в сети (как сменными, так и не сменными). Все токены на Solana фактически являются учетными записями данных, принадлежащими Token Program.

Полный список инструкций Token Program можно найти здесь.

Программа токенаПрограмма токена

Несколько часто используемых инструкций включают:

  • InitializeMint: Создать новую учетную запись для представления нового типа токенов.
  • InitializeAccount (Инициализировать счет): Создать новую учетную запись для хранения единиц определенного типа токенов (mint).
  • MintTo: Создать новые единицы определенного типа токенов и добавить их в учетную запись токена. Это увеличивает предложение токена и может быть сделано только уполномоченным лицом учетной записи монетного двора.
  • Transfer: Передача единиц определенного типа токенов с одной учетной записи на другую.

Учетная запись Mint #

Токены на Solana уникально идентифицируются по адресу учетной записи Mint, принадлежащей Программе токенов. Эта учетная запись фактически является глобальным счетчиком для конкретного токена и хранит такие данные, как:

  • Supply:Общий объем предложения токена
  • Decimals: Десятичная точность токена
  • Mint authority: Учетная запись, уполномоченная создавать новые единицы токена, тем самым увеличивая предложение
  • Freeze authority: Учетная запись, уполномоченная замораживать передачу токенов с "учетных записей".

Учетная запись Mint

Полная информация, хранящаяся на каждой учетной записи Mint, включает следующее:

pub struct Mint {
    /// Optional authority used to mint new tokens. The mint authority may only
    /// be provided during mint creation. If no mint authority is present
    /// then the mint has a fixed supply and no further tokens may be
    /// minted.
    pub mint_authority: COption<Pubkey>,
    /// Total supply of tokens.
    pub supply: u64,
    /// Number of base 10 digits to the right of the decimal place.
    pub decimals: u8,
    /// Is `true` if this structure has been initialized
    pub is_initialized: bool,
    /// Optional authority to freeze token accounts.
    pub freeze_authority: COption<Pubkey>,
}

Для справки, вот ссылка Solana Explorer на учетную запись монетного двора USDC.

Учетная запись токена #

Чтобы отслеживать индивидуальное владение каждой единицей конкретного токена, необходимо создать другой тип учетной записи данных, принадлежащий Программе токенов. Эта учетная запись называется Счет токена.

Наиболее часто на учетной записи Токена хранятся следующие данные:

  • Mint: Тип токена, единицы которого хранятся на Счете токена.
  • Owner: учетная запись, уполномоченная переводить токены со Счета токенов
  • Amount: Единицы токена, который в настоящее время хранится на Счете токена

Учетная запись токена

Полная информация, хранящаяся на каждой учетной записи Токена, включает следующее:

pub struct Account {
    /// The mint associated with this account
    pub mint: Pubkey,
    /// The owner of this account.
    pub owner: Pubkey,
    /// The amount of tokens this account holds.
    pub amount: u64,
    /// If `delegate` is `Some` then `delegated_amount` represents
    /// the amount authorized by the delegate
    pub delegate: COption<Pubkey>,
    /// The account's state
    pub state: AccountState,
    /// If is_native.is_some, this is a native token, and the value logs the
    /// rent-exempt reserve. An Account is required to be rent-exempt, so
    /// the value is used by the Processor to ensure that wrapped SOL
    /// accounts do not drop below this threshold.
    pub is_native: COption<u64>,
    /// The amount delegated
    pub delegated_amount: u64,
    /// Optional authority to close the account.
    pub close_authority: COption<Pubkey>,
}

Чтобы кошелек мог владеть единицами определенного токена, ему необходимо создать токен учетной записи конкретного типа токена (майнить), в котором кошелек будет указан в качестве владельца токена учетная записи. Кошелек может создать несколько токенов учетной записи для одного и того же типа токенов, но каждый токен учетной записи может принадлежать только одному кошельку и хранить единицы одного типа токенов

Связь с Учетной записью

Info

Обратите внимание, что данные каждого токена учетной записи включают в себя поле владелец, используемое для идентификации имеющего полномочия над этой конкретной учетной записью. Это не владелец программы, указанный в AccountInfo, который является программой токенов для всех учетных записей токенов.

Связанный токен учетной записи #

Чтобы упростить процесс поиска адреса учетной записи токенов для конкретного монетного двора и владельца, мы часто используем ассоциированные записи токенов.

Ассоциированный счет токенов - это счет токенов, адрес которого детерминирован с помощью адреса владельца и адреса монетного двора. Ассоциированный счет токенов можно рассматривать как счет токенов "по умолчанию" для конкретного монетного двора и владельца.

Важно понимать, что ассоциированный счет токенов - это не другой тип счета токенов. Это просто счет токенов с определенным адресом.

Ассоциированная учетная запись токенов

Здесь раскрывается ключевое понятие в разработке Solana: Программный производный адрес (PDA). Концептуально, PDA обеспечивает детерминированный способ генерации адреса с использованием некоторых предопределенных входных данных. Это позволяет нам легко найти адрес учетной записи в более позднее время.

Вот пример Solana Playground, который выводит адрес и владельца учетной записи токенов USDC Associated. Он всегда будет генерировать один и тот же адрес для одного и того же монетного двора и владельца.

import { getAssociatedTokenAddressSync } from "@solana/spl-token";
 
const associatedTokenAccountAddress = getAssociatedTokenAddressSync(
  USDC_MINT_ADDRESS,
  OWNER_ADDRESS,
);

В частности, адрес ассоциированной учетной записи токенов определяется с помощью следующих входных данных. Вот пример Playana Playground, который генерирует тот же адрес, что и предыдущий пример.

import { PublicKey } from "@solana/web3.js";
 
const [PDA, bump] = PublicKey.findProgramAddressSync(
  [
    OWNER_ADDRESS.toBuffer(),
    TOKEN_PROGRAM_ID.toBuffer(),
    USDC_MINT_ADDRESS.toBuffer(),
  ],
  ASSOCIATED_TOKEN_PROGRAM_ID,
);

Чтобы два кошелька могли хранить единицы одного и того же типа токенов, каждому кошельку нужен свой собственный учетный счет токенов для конкретного монетного счета. На изображении ниже показано, как выглядят эти отношения между счетами.

Связь с Учетной записью

Примеры токенов #

CLI spl-token можно использовать для экспериментов с токенами SPL. В примерах ниже мы будем использовать терминал Solana Playground, чтобы выполнять команды CLI прямо в браузере без необходимости устанавливать CLI локально.

Создание токенов и учетных записей требует использования SOL для внесения арендной платы за учетную запись и оплаты транзакций. Если вы впервые используете Solana Playground, создайте кошелек Playground и выполните команду solana airdrop в терминале Playground. Вы также можете получить devnet SOL с помощью публичного веб-крана.

solana airdrop 2

Запустите spl-token --help для полного описания доступных команд.

spl-token --help

В качестве альтернативы, вы можете установить локально CLI spl-token с помощью следующей команды . Для этого необходимо сначала установить Rust.

Info

В следующих разделах адреса учетных записей, отображаемые при выполнении команды CLI, будут отличаться от примера, показанного ниже. Пожалуйста, используйте адрес, отображаемый в терминале Playground. Например, адрес, выводимый командой create-token, - это учетная запись mint, где ваш кошелек Playground установлен в качестве авторитета mint.

Создание нового токена #

Чтобы создать новый токен (mint account) запустите следующую команду в терминале Solana Playground terminal.

spl-token create-token

Вы должны увидеть вывод, подобный следующему ниже. Вы можете проверить как токен, так и детали транзакции в Solana Explorer, используя Address и Signature.

В приведенном ниже примере уникальным идентификатором (адресом) нового токена является 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg.

Terminal
Creating token 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg
 
Address:  99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg
Decimals:  9
 
Signature: 44fvKfT1ezBUwdzrCys3fvCdFxbLMnNvBstds76QZyE6cXag5NupBprSXwxPTzzjrC3cA6nvUZaLFTvmcKyzxrm1

Новые токены изначально не имеют поставок. Вы можете проверить текущий запас токена с помощью следующей команды:

spl-token supply <TOKEN_ADDRESS>

Выполнение команды "supply" для только что созданного токена возвращает значение 0:

spl-token supply 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg

По сути, создание новой учетной записи Mint требует отправки транзакции с двумя инструкциями. Вы можете запустить этот пример на Playana Playground.

  1. Вызовите системную программу для создания новой учетной записи с достаточным объемом для данных учетной записи Mint Account и передайте право собственности на токенскую программу.

  2. Вызовите программу токенов для инициализации данных новой учетной записи как Mint

Создать учетную запись токенов #

Чтобы хранить единицы определенного токена, необходимо сначала создать учетную запись токена. Чтобы создать новый счет токена, выполните следующую команду:

spl-token create-account [OPTIONS] <TOKEN_ADDRESS>

Например, выполнение следующей команды в терминале Playground Solana:

spl-token create-account 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg

Возвращает следующий вывод:

  • AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9 - это адрес токена аккаунта, созданного для хранения единиц токена, указанного в команде create-account .
Terminal
Creating account AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9
 
Signature: 2BtrynuCLX9CNofFiaw6Yzbx6hit66pup9Sk7aFjwU2NEbFz7NCHD9w9sWhrCfEd73XveAGK1DxFpJoQZPXU9tS1

По умолчанию команда create-account создает связанный аккаунт токена с адресом вашего кошелька в качестве владельца аккаунта токена.

Вы можете создать учетную запись с другим владельцем, используя следующую команду:

spl-token create-account --owner <OWNER_ADDRESS> <TOKEN_ADDRESS>

Например, выполнить следующую команду:

spl-token create-account --owner 2i3KvjDCZWxBsqcxBHpdEaZYQwQSYE6LXUMx5VjY5XrR 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg

Возвращает следующий вывод:

  • Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt является адресом токена аккаунта, созданного для хранения единиц токена, указанного в команде create-account (99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg) и принадлежащего адресу, указанному по следующей строке --owner флага (2i3KvjDCZWxBsqcxBHpdEaZYQSYE6LXUMx5VjY5XrR). Это полезно, когда вам нужно для создания аккаунта с токеном для другого пользователя.
Terminal
Создание учетной записи Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt
 
Подпись: 44vqKdfzspT592REDPY4goaRJH3uJ3Ce13G4BCuUH35dVUbHuGTHvqn4ZjYF9BGe9QrjMfe9GmuLkQhSZCBQuEt

Под капотом создание учетной записи токенов требует одной инструкции, вызывающей программу Associated Token. Вот пример на Javascript на Solana Playground.

Программа Associated Token Program использует кросс-программные вызовы для обработки:

  • вызов системной программы для создания нового аккаунта с использованием предоставленного PDA в качестве адреса нового аккаунта
  • Вызов Программы Токенов для инициализации данных учетных записей Токенов для новой учетной записи.

В качестве альтернативы, создание новой учетной записи токенов с использованием случайно сгенерированной пары ключей (не ассоциированной учетной записи токенов) требует отправки транзакции с двумя инструкциями. Вот пример на Javascript в Solana Playground.

  1. Вызовите системную программу для создания новой учетной записи с достаточным пространством для данных учетной записи токенов, а затем передайте право собственности программе токенов.

  2. Вызовите программу Token Program для инициализации данных нового счета в качестве учетной записи токенов

Mint Токен #

Чтобы создать новый счет токена, выполните следующую команду:

spl-token mint [OPTIONS] <TOKEN_ADDRESS> <TOKEN_AMOUNT> [--] [RECIPIENT_TOKEN_ACCOUNT_ADDRESS]

Например, выполнить следующую команду:

spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100

Возвращает следующий вывод:

  • Чтобы перевести токены на другой учетный счет токенов, укажите адрес учетного счета токенов получателя.

  • AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9 является адресом счета вашего кошелька токен, который фиксируется в единицах токена (увеличивается).

Terminal
Minting 100 tokens
  Token: 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg
  Recipient: AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9
 
Signature: 2NJ1m7qCraPSBAVxbr2ssmWZmBU9Jc8pDtJAnyZsZJRcaYCYMqq1oRY1gqA4ddQno3g3xcnny5fzr1dvsnFKMEqG

Чтобы перевести токены на другой учетный счет токенов, укажите адрес учетного счета токенов получателя. Например, выполнить следующую команду:

spl-token mint 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 -- Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt

Возвращает следующий вывод:

  • 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg - адрес счета mint, для которого выпускаются токены (увеличивается общее предложение).

  • Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt - адрес счета минта, на который выпускаются единицы токена (увеличение количества).

Terminal
Minting 100 tokens
  Token: 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg
  Recipient: Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt
 
Signature: 3SQvNM3o9DsTiLwcEkSPT1Edr14RgE2wC54TEjonEP2swyVCp2jPWYWdD6RwXUGpvDNUkKWzVBZVFShn5yntxVd7

Передача токенов требует вызова инструкции Transfer в программе Token Program. Эта инструкция должна быть подписана владельцем mint. Инструкция производит начисление новых единиц токена на счет mint и увеличивает общее предложение на счете mint. Вот пример на Javascript на Solana Playground.

Передача токенов #

Чтобы перевести единицы токена между двумя учетными записями токенов, используйте следующую команду:

spl-token transfer [OPTIONS] <TOKEN_ADDRESS> <TOKEN_AMOUNT> <RECIPIENT_ADDRESS
or RECIPIENT_TOKEN_ACCOUNT_ADDRESS>

Например, выполните следующую команду:

spl-token transfer 99zqUzQGohamfYxyo8ykTEbi91iom3CLmwCA75FK5zTg 100 Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt

Возвращает следующий вывод:

  • AfB7uwBEsGtrrBqPTVqEgzWed5XdYfM1psPNLmf7EeX9 - это адрес учетной записи токенов, с которой переводятся токены. Это будет адрес вашего счета токенов для указанного передаваемого токена.

  • Hmyk3FSw4cfsuAes7sanp2oxSkE9ivaH6pMzDzbacqmt - адрес счета токенов, на который переводятся токены.

Terminal
Перевести 100 токенов

Передача токенов требует вызова инструкции Transfer в программе Token Program. Эта инструкция должна быть подписана владельцем учетной записи токенов отправителя. Инструкция передает единицы токена с одного учетного записи токенов на другой учетный записи токенов. Вот пример на Javascript на Solana Playground.

Важно понимать, что и отправитель, и получатель должны иметь существующие учетные записи токенов для конкретного типа передаваемого токена. Отправитель может включить в транзакцию дополнительные инструкции по созданию учетной записи токенов получателя, которая обычно является ассоциированной учетной записью токенов.

Создание метаданных токена #

Программа Token Extensions позволяет хранить дополнительные настраиваемые метаданные (например, имя, символ, ссылку на изображение) непосредственно на счете минта.

Info

Чтобы использовать флаги Token Extensions CLI, убедитесь, что у вас есть локальная установка CLI версии 3.4.0 или более поздней:

cargo install --version 3.4.0 spl-token-cli

Чтобы создать новый токен с включенным расширением метаданных, используйте следующую команду :

spl-token create-token --program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
--enable-metadata

Команда возвращает следующий вывод:

  • BdhzpzhTD1MFqBiwNdrRy4jFo2FHFuf3n9e8sVjJczP является адресом нового токена созданного с включенным расширением метаданных.
Terminal
Создание токена BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP в рамках программы TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb
Для инициализации метаданных внутри минуты, пожалуйста запустите `spl-token initialize-метаданных BdhzpzhTD1MFqBiwNdrRy4jFo2FHFuf3n9e8sVjJczP <YOUR_TOKEN_NAME> <YOUR_TOKEN_SYMBOL> <YOUR_TOKEN_URI>` и подпишите вместе с моим авторитетом.
 
Адрес: BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP
Decimals: 9
 
Подпись: 5iQofFeXdYhMi9uTzZghcq8stAaa6CY6saUwcdnELST13eNSifiuLbvR5DnRt311frkCTUh5oecj8YEvZSB3wfai

После создания нового токена с включенным расширением метаданных, используйте для инициализации метаданных.

spl-token initialize-metadata <TOKEN_MINT_ADDRESS> <YOUR_TOKEN_NAME>
<YOUR_TOKEN_SYMBOL> <YOUR_TOKEN_URI>

The token URI is normally a link to offchain metadata you want to associate with the token. Пример формата JSON можно найти здесь.

Например, выполнение следующей команды сохранит дополнительные метаданные непосредственно на указанной учетной записи mint:

spl-token initialize-metadata BdhzpzhTD1MFqBiwNdrRy4jFo2FHFufw3n9e8sVjJczP "TokenName" "TokenSymbol" "https://raw.githubusercontent.com/solana-developers/opos-asset/main/assets/DeveloperPortal/metadata.json"

Затем вы можете найти адрес учетной записи mint в проводнике, чтобы просмотреть метаданные. Например, здесь показан токен, созданный с включенным расширением метаданных в проводнике SolanaFm.

Вы можете узнать больше в руководстве по расширению метаданных. Для получения более подробной информации о различных расширениях токенов обратитесь к руководству по началу работы с расширениями токенов и документации SPL.