July 27, 2022

Токены Solan'ы

Всем привет! С вами Тёма!

Сегодня я вместе с вами начну погружаться в солану, а поможет нам в этом данная статья ТЫК (моя статья это просто ее перевод)

Начнем

Понимание токенов Solana может быть довольно сложным, если вы имеете опыт работы с Ethereum. В Ethereum обычные токены используют стандарт ERC20, а NFT токены используют стандарт ERC721. Каждый токен ERC20, ровно как и каждая NFT коллекция, имеет свой собственный смарт-контракт

Модель аккаунтов Соланы

Чтобы понять как работают токены на солане, вам сначала нужно понять модель учетных записей соланы. Я настоятельно рекомендую прочитать эту вики, особенно если вы имеете опыт работы с Ethereum. Вот краткая выжимка:

  • Учетная запись либо содержит данные (например, сколько у вас токенов), либо представляет собой исполняемую программу (например, смарт-контракт). Первые называются «data accounts», а вторые — «program accounts». Важно отметить, что в отличие от Ethereum, учетные записи программы не хранят состояние. Все состояние хранится в учетных записях данных
  • Каждый аккаунт содержит следующие поля:
  • Каждая учетная запись имеет уникальный адрес (похожий на Ethereum). Большинство адресов являются открытым ключом keypair
  • Каждая учетная запись принадлежит program. По умолчанию вновь созданная учетная запись принадлежит встроенной программе под названием «System Program». Только владелец учетной записи может изменить ее

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

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

Что такое Solana’s Token Program?

Solana Token Program позволяет следующее (для взаимозаменяемых и невзаимозаменяемых токенов):

  • Минт токенов
  • Трансфер токена
  • Сжигание токенов

Вот hana рассказывал о том, как это работает:

Одним из преимуществ модели программы/учетной записи является то, что у вас может быть одна общая программа, которая работает с различными данными. Лучшим примером этого является программа токена spl. Чтобы создать новый токен, вам не нужно развертывать код, как это делается в эфириуме. Вы создаете учетную запись, которая может минтить токены, и другие учетные записи, которые могут их получать. Адрес минтера однозначно определяет тип токена, и все они передаются в качестве аргументов одному статическому экземпляру программы

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

Если вы еще не совсем поняли, не волнуйтесь! Рассмотрение примера должно прояснить ситуацию!

Примечание: иногда вы увидите токены Solana, называемые «SPL tokens». SPL означает Solana Program Library (библиотеку программ Solana), которая представляет собой набор программ Solana, которые команда Соланы развернула в сети. Токены SPL аналогичны токенам ERC20, поскольку каждый токен SPL имеет стандартный набор функций

Как работает Solana Token Program?

Самый простой способ понять это — рассмотреть несколько примеров. В наших примерах будут рассмотрены взаимозаменяемые токены, и мы будем использовать инструмент командной строки spl-token для взаимодействия с программой токена (вы можете установить его, запустив в командной строке cargo install spl-token-cli)

Повторюсь, все, что делает spl-token — это отправляет инструкции в token program. Вы можете имитировать следующее поведение, используя клиент JavaScript или взаимодействуя с программой токена через CPI в Rust

Подготовка

Во-первых, убедитесь, что вы установили Solana CLI и spl-token

Затем запустите solana-keygen new -o ~/my_solana_wallet1.json и создайте новую переменную окружения с именем $SOLADDR1, в которой будет храниться полученный открытый ключ. Повторите эти действия, но со второй переменной окружения с именем $SOLADDR2 (и назовите файл пары ключей my_solana_wallet2.json). Мы будем использовать эти адреса и файлы пар ключей позже, чтобы протестировать минт и трансфер токенов

Вот как это выглядит у меня:

$ echo $SOLADDR1
3sdsSwWWjjGA7HpPBQfGaXRE2HqmdKicMXHRapqLAu4L
$ echo $SOLADDR2
ES2C1YPzNh5JjQu7DdxrveaPUHj9CnrRWSdrFo4ku5Zh

Примечание: многие команды в этом руководстве можно сократить, запустив solana config set — keypair ~/my_solana_wallet1.json, который устанавливает пару ключей клиента по умолчанию. Например, это позволяет не указывать флаг --owner для многих из следующих команд. Я использую более длинные версии команд, чтобы обьяснение было более понятным

Создание токена

Теперь, когда мы все настроили, мы можем использовать spl-token. Во-первых, давайте создадим новый тип токена

$ spl-token create-token --mint-authority ~/my_solana_wallet1.json 
Creating token 6ifRGEkJ6XmEjuqfTFNqAjjomUiDJTjRv4GHqBH6usWr

При создании токена нового типа создается новая учетная запись с данными, которую в дальнейшем мы будем называть «mint account». Каждый тип токена связан ровно с одним mint account. Адрес mint account — 6ifRGEkJ6XmEjuqfTFNqAjjomUiDJTjRv4GHqBH6usWr, но вместо этого мы будем использовать $TOKEN1, чтобы упростить чтение. Мы можем запросить информацию об учетной записи следующим образом (в конце много непонятных символов, но не переживайте, они нам пока не нужны):

$ solana account $TOKEN1
Public Key: Aqf1rBKNQYgX1mjE64STwV3miEwXEe2ioZzD7n4vkpXk
Balance: 0.0014616 SOL
Owner: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Executable: false
Rent Epoch: 207
Length: 82 (0x52) bytes
0000: 01 00 00 00 2a b0 1a 64 bb c5 f0 df bf 57 d5 61 ....*..d.....W.a
0010: 56 a8 b8 85 8f a8 0b 09 f1 f1 a2 dc 4d 51 b3 63 V...........MQ.c
0020: 8f 72 bd e9 00 00 00 00 00 00 00 00 09 01 00 00 .r..............
0030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0040: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0050: 00 00

Мы можем проверить владельца (TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA) с помощью Solana Explorer. Владельцем является token program (учетная запись программы), которая отвечает за создание новых токенов, минт токенов и передачу токенов

Теперь давайте посмотрим на данные mint account, которые идут после «Length: 82 (0x52) bytes», как показано выше. Человеку трудно читать шестнадцатеричные данные, поэтому вместо этого мы можем использовать Solana Explorer:

Solana Explorer декодирует данные и отображает их в удобочитаемом формате. Вот что означает каждое из полей:

  • Address — это адрес mint account
  • Current Supply — количество сминченных токенов. Поскольку мы только что создали токен, он равен 0
  • Mint Authority — открытый ключ из keypair, которому разрешено минтить токены (мы указали это с помощью флага --mint-authority. Если кто-то еще попытается минтить токены, то он этого не сможет)
  • Decimals — определяет наименьший номинал токена. Для NFT он должен быть равен нулю. Девять по умолчанию

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

  • «Internal Solana relations» относятся к полю владельца, которое устанавливается для каждой учетной записи, например владелец, который отображается при запуске учетной записи solana $TOKEN1
  • «User-space relations» — это когда отношение между двумя учетными записями закодировано в данных учетной записи, например поле «mint authority», которое мы видели выше
Владельцем Token Program является загрузчик BPF. Я не изображаю это здесь, потому что это не так важно и загромождает диаграмму

Создание Token Account

Прежде чем мы сможем создать токены, мы должны сначала создать учетную запись токена

$ spl-token create-account $TOKEN1 --owner $SOLADDR1 
Creating account 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak

Отныне мы будем использовать $TOKENACCT1 вместо 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak, и мы будем называть эту учетную запись «token account». Вам может быть интересно, что такое токен-аккаунт? По сути, он просто хранит, сколько токенов есть у конкретного пользователя для определенного типа токена. Например, если у вас есть 10 токенов 1 и 5 токенов 2, то у вас будет две учетные записи токенов

Вот как выглядит токен-аккаунт:

$ solana account $TOKENACCT1
Public Key: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
Balance: 0.00203928 SOL
Owner: TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
Executable: false
Rent Epoch: 207

Учетная запись токена связана с тремя другими учетными записями. Его внутренним владельцем является token program, поскольку token program должна иметь возможность изменять учетную запись (например, добавлять к ней больше токенов). Затем в пользовательском пространстве его владельцем является $SOLADDR1, а его «mint» или связанный с ним mint account — $TOKEN1

Вот как теперь связаны все аккаунты:

Token Minting

Наконец-то мы можем сминтить токены! Эта часть проще — мы просто указываем mint account (которая определяет «type» токена для минта), количество токенов и учетную запись, которой их нужно передать

$ spl-token balance $TOKEN1 --owner $SOLADDR1
0

$ spl-token mint $TOKEN1 10 $TOKENACCT1 --mint-authority ~/my_solana_wallet1.json
Minting 10 tokens
  Token: Aqf1rBKNQYgX1mjE64STwV3miEwXEe2ioZzD7n4vkpXk
  Recipient: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
  
$ spl-token balance $TOKEN1 --owner $SOLADDR1
10

Помимо использования spl-token balance, вы также можете использовать spl-token accounts, чтобы просмотреть, сколько каждого токена принадлежит определенной учетной записи

$ spl-token accounts --owner $SOLADDR1 
Token                                        Balance
-------------------------------------------------------------
Aqf1rBKNQYgX1mjE64STwV3miEwXEe2ioZzD7n4vkpXk 10

Что произойдет, если вы попытаетесь создать токены с другим значением параметра --mint-authority?

$ spl-token mint $TOKEN1 10 $TOKENACCT1 --mint-authority ~/my_solana_wallet2.json
Minting 10 tokens
 Token: Aqf1rBKNQYgX1mjE64STwV3miEwXEe2ioZzD7n4vkpXk
 Recipient: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
RPC response error -32002: Transaction simulation failed: Error processing Instruction 0: custom program error: 0x4 [5 log messages]

Ответ? Это не работает! Это связано с тем, что в поле «mint authority» token account'а указана другая учетная запись, и только этой учетной записи разрешено минтить новые токены

Token Transferring

Давайте попробуем перенести некоторые токены в $SOLADDR2 (которые должны были быть созданы в разделе «Подготовка»)

$ spl-token transfer $TOKEN1 1 $SOLADDR2 --owner ~/my_solana_wallet1.json
Transfer 5 tokens
 Sender: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
 Recipient: ES2C1YPzNh5JjQu7DdxrveaPUHj9CnrRWSdrFo4ku5Zh
 Recipient associated token account: FFednTgQRKDbGYjXrXk8SWPfzSJW3Q8ApN5mGCpGdAtE
Error: Recipient's associated token account does not exist. Add `--fund-recipient` to fund their account

Неудача! Сообщение об ошибке говорит, что нам не разрешено передавать токены, если у получателя нет token account

Есть два способа исправить это:

  1. Создайтеtoken account для получателя, а затем перенесите токены.
  2. Используйте флаг --fund-recipient. Это заставляет отправителя платить за создание token account получателя

Мы пойдем с подходом № 1

$ spl-token create-account $TOKEN1 --owner $SOLADDR2
Creating account FFednTgQRKDbGYjXrXk8SWPfzSJW3Q8ApN5mGCpGdAtE

$ spl-token transfer $TOKEN1 1 $SOLADDR2 --owner ~/my_solana_wallet1.json
Transfer 1 tokens
  Sender: 9EYnoqiBQmJPR55db44cF4wkN1PD5D6vjxEz61r2Ujak
  Recipient: ES2C1YPzNh5JjQu7DdxrveaPUHj9CnrRWSdrFo4ku5Zh
  Recipient associated token account: FFednTgQRKDbGYjXrXk8SWPfzSJW3Q8ApN5mGCpGdAtE
  
$ spl-token balance $TOKEN1 --owner $SOLADDR2
1

Красиво, сработало! Давайте посмотрим на все учетные записи в этом действии

Wrapped SOL

Точно так же, как ETH можно обернуть токеном ERC20, чтобы сформировать wETH, так и SOL можно обернуть токеном SPL

$ spl-token wrap 1 ~/my_solana_wallet1.json
Wrapping 1 SOL into DXWzvX3RtZbito65G8ZgqmEzJM6Z6Fqy7NHkbpEmCUZD

Конечно, вы можете обратно развернуть полученный токен SPL, чтобы вернуть свои SOL

$ spl-token unwrap DXWzvX3RtZbito65G8ZgqmEzJM6Z6Fqy7NHkbpEmCUZD ~/my_solana_wallet1.json
Unwrapping DXWzvX3RtZbito65G8ZgqmEzJM6Z6Fqy7NHkbpEmCUZD
 Amount: 1 SOL
 Recipient: 3sdsSwWWjjGA7HpPBQfGaXRE2HqmdKicMXHRapqLAu4L

Такая упаковка SOL позволяет легко обменивать SOL на другие токены SPL

Подождите, а как там NFT?

Теперь, когда мы рассмотрели, как работают взаимозаменяемые токены, понять, что такое невзаимозаменяемые токены, должно быть легко. Я просто позволю вам прочитать доки, так как в любом случае я бы не стал много добавлять. Основными важными моментами являются:

  • Используйте --decimals 0 при создании токена, так как он должен быть только один
  • После минта одного токена отключите минты в будущем. Это гарантирует, что будет только один токен

На практике никто не создает NFT таким образом. Вместо этого большинство людей используют Candy Machine, инструмент для загрузки изображений и метаданных и создания NFT на их основе

Вот и все! К этому моменту вы должны понимать, как работают токены SPL и чем они отличаются от токенов ERC20

Заключение:

  • Одна программа, называемая Token Program, может создавать новые токены, минтить новые токены и передавать токены между учетными записями
  • В отличие от токенов ERC20, где каждый новый токен связан с новым смарт-контрактом ERC20, в солане существует только одна Token Program. Однако каждый новый тип токена связан с новым mint account
  • Если пользователь хочет владеть некоторыми токенами определенного типа, ему необходимо иметь учетную запись токена. Другими словами, если кто-то владеет пятью разными типами токенов, у него будет пять разных учетных записей токенов
  • Вы можете обернуть SOL в токен SPL, что позволяет легко обменять его на другие токены SPL
  • Не взаимозаменяемый токен SPL — это токен с нулевым Decimals, который создают одну копию и отключил минт в будущем

Надеюсь статья была интересной и понятной!

Телеграмм канал - https://t.me/ortomich_crypto

Твиттер - https://twitter.com/ortomichDev

Гитхаб - https://github.com/ortomich