FUCKAEM SOLANU JAVASCRIPT EDITION
а солане то уже 18 исполнилось...
вассааааааап другалек давно не виделись в статьях в телетайпе ебаний его рот не правда ли? давно я тебе обещал статейку, вот завожу по соланочке наваливая жесткую музяку суисайдбойс и не только...
если ты давно хотел понять как же сука с соланой играться юзая джс то эта статья для тебя! у соланы есть кукбук так шо если у тебя возникнут вопросы ты всегда можешь обратиться к кукбуку либо к рубурику. практически все шо есть в статье есть в кукбуке — здесь я просто разжую основные концепты
подготавливаем среду разработки
если у тебя все еще нет nodejs (проказник) скачай его тут
если у тебя не установлен yarn — установи его следующей командой в терминале
npm i -g yarn
первое шо тебе надо сделать это создать папочку где будет храниться твой новый проектик
теперь давай установим нужные пакеты и модули для работы с соланой используя команды:
yarn init -y yarn add bip39 bs58 @solana/web3.js @solana/spl-token
и наконец в файлике package.json
прописываем type: "module"
как на скрине
коннектимся к рпс
здесь нам нужна рпс ноды соланы. достать можно в alchemy
https://solana-mainnet.g.alchemy.com/v2/QY6qW6UrMVDw8DINgQLqyDZJgAOdJOt2
для того шобы взаимодействовать с блокчейном соланы нам нужно для начала подключиться к каой нибудь ноде которая сможет обрабатывать наши капризы. в данном примере я подрубаюсь к паблик ноде
import { Connection } from "@solana/web3.js"; (async () => { const connection = new Connection( "https://solana-mainnet.g.alchemy.com/v2/QY6qW6UrMVDw8DINgQLqyDZJgAOdJOt2", "confirmed" ); console.log(await connection.getEpochInfo()); })();
node index
после этого у тебя в консоли должна отобразиться инфа о текущей эпохе епта
поздравляю! ты законнектился к ноде
учимся работать с кошаками
после того как мы законектились к ноде мы можем работать с чейном! но к сведению -- для создания коша сам коннект к ноде нам не нужен
как сгенерировать мнемонику
ты можешь сгенерировать новую мнемонику а соответственно новый кошелек используя bip39
import { generateMnemonic } from 'bip39'; const mnemonic = generateMnemonic(); console.log(mnemonic);
запустив этот код твоим глазам предстанет новая мнемоника! погнали дальше
как восстановить кош по мнемонике
для того чтобы восстановить кош по мнемонике нам нужно конвертнуть мнемонику в сид, а затем создать новую пару ключей (приватный и паблик ключ). так мы и получим наш восстановленный кошелек
import { Keypair } from '@solana/web3.js'; import { mnemonicToSeedSync } from 'bip39'; const mnemonic = 'ruburi dao ebashit'; // тут твоя мнемоника const seed = mnemonicToSeedSync(mnemonic); const keypair = Keypair.fromSeed(seed.subarray(0, 32)); console.log(keypair.publicKey.toBase58());
так ты получишь в консоли адрес своего коша
как восстановить кош по приватнику
import { Keypair } from '@solana/web3.js'; const keypair = Keypair.fromSecretKey(bs58.decode('xuipizda')); // вместо `xuipizda` твой приватник console.log(keypair.publicKey.toBase58());
как подписать сообщение используя кош
для подписьки сообщений нам пригодятся еще два модуля:
yarn add tweetnacl tweetnacl-util
подписываем сообщение уже существующей парой ключей:
import { sign } from 'tweetnacl'; import { decodeUTF8 } from 'tweetnacl-util'; const keypair = ... const message = 'ТЫ ЛУЧШИЙ! СПАСИБО ЗА ТО ЧТО ЧИТАЕШЬ СТАТЬЮ;)'; // превращаем нашу строчку в большие буфера (байты проще говоря) const messageBytes = decodeUTF8(message); const signature = sign.detached(messageBytes, keypair.secretKey); const result = sign.detached.verify( messageBytes, signature, keypair.publicKey.toBytes() ); // наше подписанное сообщение console.log(result);
получаем баланс и нфт кошеля
получить баланс любого адреса можно используя конекшен к ноде. вспоминаем про наш коннект
import { Connection, LAMPORTS_PER_SOL } from "@solana/web3.js"; (async () => { const connection = new Connection( "https://solana-mainnet.g.alchemy.com/v2/QY6qW6UrMVDw8DINgQLqyDZJgAOdJOt2", "confirmed" ); // получим баланс дегодс енджоера в лампортах const lamportBalance = await connection.getBalance( '5KrLikZiv39RNuz66azZqtHSoEiUHCa6oDWyMq64XSmh' ); // конвертируем его в солану (поделив на количество лампортов в 1 соли) const solBalance = lamportBalance / LAMPORTS_PER_SOL; // отображаем console.log(`${solBalance} SOL`); })();
так мы с тобой получили баланс дегодс енджоера. а шо по нфт?
для того чтобы получить нфт нам нужно преобразовать адрес аккаунта в паблик ключ. как это сделать? а вот как
import { Connection, PublicKey } from "@solana/web3.js"; import { TOKEN_PROGRAM_ID } from '@solana/spl-token'; (async () => { const connection = new Connection( "https://solana-mainnet.g.alchemy.com/v2/QY6qW6UrMVDw8DINgQLqyDZJgAOdJOt2", "confirmed" ); const owner = new PublicKey('5KrLikZiv39RNuz66azZqtHSoEiUHCa6oDWyMq64XSmh'); const { value: tokenAccounts } = await connection.getParsedTokenAccountsByOwner(owner, { programId: TOKEN_PROGRAM_ID, }); })();
tokenAccounts
— это список всех токенов аккаунта (в общем всего что не соль). это может быть нфт или любой другой токен. возникнет вопрос как отличить нфт от какого то щитка? все токены можно отфильтровывать по минт адресу. в массиве tokenAccounts
можно получить минт адрес токена, сколько токенов на аккаунте и decimals
(количество знаков после запятой у токена по дефолту, как у эфира допустим 18, тк 1 eth = 10**18 wei
)
отличить более менее норм токен от щитка можно через @solana/spl-token-registry
щитки в моем понимании это токены без иконки, имени и тд. но насколько мне известно в регистри не записываются нфт типа дегодс. они обычно не состоят в регистри
давайте найдем дегодса #9382 у челика выше
import { Connection, PublicKey } from "@solana/web3.js"; import { TOKEN_PROGRAM_ID } from '@solana/spl-token'; (async () => { const connection = new Connection( "https://solana-mainnet.g.alchemy.com/v2/QY6qW6UrMVDw8DINgQLqyDZJgAOdJOt2", "confirmed" ); const owner = new PublicKey('5KrLikZiv39RNuz66azZqtHSoEiUHCa6oDWyMq64XSmh'); const { value: tokenAccounts } = await connection.getParsedTokenAccountsByOwner(owner, { programId: TOKEN_PROGRAM_ID, mint: new PublicKey('qzHFrK32hhWQuPkaFSKKVwbuqWMB2qUK8cbHVZHKvy2') }); if (tokenAccounts.length > 0) { const degod = tokenAccounts[0]; console.log(degod.account.data.parsed.info.tokenAmount.amount); } })();
выведет нам 1 (если конечно чел не продал все еще его). давай немного разберем код. мы ищем в tokenAccounts тот токен чей минт адрес совпадает с минт адресом DeGod #9382
ты можешь отфильтровать токены если ты ищешь определенный токен по минт адресу с помощью свойства mint
в методе getParsedTokenAccountsByOwner
на выходе мы получаем массив, проверяем что дегодс на месте и выводим количество дегодсов (в данном случае 1)
как отправлять соляну и нфт на другие коши
как отправлять соляну
import { Connection, Transaction, SystemProgram, sendAndConfirmTransaction, PublicKey } from "@solana/web3.js"; (async () => { const connection = new Connection( "https://solana-mainnet.g.alchemy.com/v2/QY6qW6UrMVDw8DINgQLqyDZJgAOdJOt2", "confirmed" ); // keypair откуда отправляем const fromKeypair = ... // 1 - получаем хэш последнего блока в сети const blockhash = (await connection.getLatestBlockhash('finalized')).blockhash; // 2 - создаем транзу const transferTransaction = new Transaction({ // здесь можно указать адрес который платит комсу, нужен именно паблик ключ // feePayer: fromKeypair.publicKey blockhash }).add( SystemProgram.transfer({ fromPubKey: fromKeypair.publicKey, // publicKey кому мы отправляем солану (адрес вместо `wassup`) toPubKey: new PublicKey('wassup'), lamports: 100000000 // количество в лампортах (!) }) ); // 3 - подписываем и отправляем транзу await sendAndConfirmTransaction(connection, transferTransaction, [fromKeypair]); })();
этого достаточно для того чтобы отправить соль на другой адрес. тебе нужно будет иметь keypair кошелька откуда ты отправляешь соль и публичный ключ аккаунта куда ты отправляешь
как отправить токен (нфт)
механизм в целом ничем особенным не отличается кроме того в случае токена если под токен на адресе не создан токен аккаунт (дада, в солане нужно создавать токен аккаунт для того чтобы посылать на него какой то токен). а токен аккаунты создаются по минт адресу токена
проверить создан ли у тебя токен аккаунт под определенный токен можно лишь вызвав getParsedTokenAccountsByOwner
из предыдущей секции и получив существующие у тебя токен аккаунты на коше
import { Connection, transferChecked, PublicKey, Keypair } from "@solana/web3.js"; import { TOKEN_PROGRAM_ID } from '@solana/spl-token'; import { mnemonicToSeedSync } from 'bip39'; (async () => { const connection = new Connection( "https://solana-mainnet.g.alchemy.com/v2/QY6qW6UrMVDw8DINgQLqyDZJgAOdJOt2", "confirmed" ); const mnemonic = 'ruburi dao ebashit'; // тут твоя мнемоника окда const seed = mnemonicToSeedSync(mnemonic); // keypair откуда отправляем нфт const owner = Keypair.fromSeed(seed.subarray(0, 32)); const fromTokenAccount = new PublicKey('lolkek'); const mintAddress = 'sosopaviashvilidao' const toTokenAccount = newPublicKey('scammer'); const amount = 1, decimals = 1; const txHash = await transferChecked( connection, // наш коннкешен owner, // keypair кто платит комсу fromTokenAccount, // publicKey адреса токен аккаунта откуда отправляем mintAddress, // publicKey минт адреса отправляемого токена toTokenAccount, // publicKey адреса токен аккаунта куда отправляем owner, // keypair кошеля овнера токена amount, // количество токенов decimals // числа после запятых (можно получить в инфе из tokenAccounts) ); })();
создаем токен аккаунт если у коша его нет
import { ..., PublicKey, createAssociatedTokenAccount } from '@solana/web3.js'; (async () => { ...code const mint = new PublicKey('bulshitmintaddress'); const ata = await createAssociatedTokenAccount( connection, // наш коннекшен feePayer, // keypair кто платит комсу mint, // publicKey (!) минт адреса owner.publicKey // publicKey (!) владельца нового токен аккаунта ); console.log(ata.toBase58()); // выводим адрес нового токен аккаунта })();
адрес нового токен аккаунта как раз таки и будет нужен тебе для отправки нужного токена, только не запутайся где publicKey
а где keypair
!
как преобразовать адрес в publicKey адреса
new PublicKey('ADDRESS')
заключение
вот в принципе все шо я хотел тебе сегодня рассказать и показать о солане на javascript!
скоро будет статья также по солане как создавать свой токен и минтить его, сжигать, как создавать candy machine, как туда вносить свои нфт и как минтить нфт через candy machine id. в общем будет оч оч гемно нахуй
я буду еще писать о концептах js более подробно и емко, так что подписывайся на рубури дао!
можешь не беспокоиться если чето не запомнилось, это нормально. не отступай и иди к цели. когда я учился я хотел бросить люто масштабно два раза... но не останавливался пон!!!!! я не остановился и ща работаю дворничком (шутка конечно мужики я во вкусно и точка)
благодарности
спасибо тебе за прочтение, спасибо тем кто ставит реакции, подпищекам, рыжему, сс ресерч, моей девочке, френдли тагу 52 нгг и всем остальным кто пон мотивирует ебашить люто жоска
и удачи тебе в пути кодинга еба!
отзыв
если в каком то примере ошибка, или что то не получается вы всегда можете обратиться за вопросом в телегу к рубурику @rubyuroboros
мой канал — https://t.me/ruburi