В предыдущем разделе вы узнали, как читать данные из сети Solana путём получения аккаунтов. Запись данных в сеть Solana требует транзакции. Транзакция содержит одну или несколько инструкций, и каждая инструкция вызывает программу.
Программы определяют бизнес-логику для каждой инструкции. Когда вы отправляете транзакцию, среда выполнения Solana выполняет инструкции транзакции по порядку. Транзакции являются атомарными: либо все инструкции в транзакции выполняются успешно, либо вся транзакция завершается с ошибкой.
Примеры в этом разделе показывают, как:
- Перевести SOL между аккаунтами
- Создать новый токен-минт
Перевод SOL
Приведённый ниже пример переводит SOL с одного аккаунта на другой. Только программа, назначенная владельцем аккаунта, может изменять данные аккаунта или списывать lamport с его баланса. Кошельковые аккаунты принадлежат System Program, поэтому перевод SOL между кошельковыми аккаунтами требует инструкции, вызывающей инструкцию transfer System Program. Исходный аккаунт также должен подписать транзакцию.
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";import { getTransferSolInstruction } from "@solana-program/system";const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const receiver = await generateKeyPairSigner();const transferInstruction = getTransferSolInstruction({source: client.payer,destination: receiver.address,amount: lamports(10_000_000n)});const result = await client.sendTransaction([transferInstruction]);console.log("Transaction Signature:", result.context.signature);const { value: senderBalance } = await client.rpc.getBalance(client.payer.address).send();const { value: receiverBalance } = await client.rpc.getBalance(receiver.address).send();console.log("Sender Balance:", senderBalance);console.log("Receiver Balance:", receiverBalance);
Создайте клиент Kit для локального тестового validator. Этот фрагмент добавляет подписанта-плательщика, подключается к локальному RPC-эндпоинту, включает аирдропы и пополняет кошелёк плательщика тестовыми SOL для перевода.
const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));
Создайте подписанта для получателя. Отправителем является client.payer,
который был создан с помощью generatedPayer() и пополнен через
airdropPayer().
const receiver = await generateKeyPairSigner();
Вспомогательная функция getTransferSolInstruction() создаёт инструкцию System
Program. Инструкция переводит SOL от подписанта source на
адрес destination на указанное
amount lamports.
const transferInstruction = getTransferSolInstruction({source: client.payer,destination: receiver.address,amount: lamports(10_000_000n)});
Вызовите client.sendTransaction() с массивом инструкций. Клиент Kit объединяет
инструкции в одну транзакцию, подписывает с помощью подписантов, прикреплённых к
инструкциям, отправляет транзакцию и ожидает подтверждения.
const result = await client.sendTransaction([transferInstruction]);console.log("Transaction Signature:", result.context.signature);
После подтверждения транзакции получите оба баланса с помощью client.rpc.
const { value: senderBalance } = await client.rpc.getBalance(client.payer.address).send();const { value: receiverBalance } = await client.rpc.getBalance(receiver.address).send();
Создание токена
В примере ниже создаётся новый mint account с использованием Token Extensions Program. mint account — это аккаунт, определяющий глобальные настройки токена: количество знаков после запятой, эмиссию, полномочия на выпуск и полномочия на заморозку.
Создание mint account требует двух инструкций:
- Вызов System Program для создания нового аккаунта, принадлежащего Token Extensions Program.
- Вызов Token Extensions Program для инициализации этого аккаунта как mint.
import { createClient, generateKeyPairSigner, lamports } from "@solana/kit";import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";import { getCreateAccountInstruction } from "@solana-program/system";import {fetchMint,getInitializeMintInstruction,getMintSize,TOKEN_2022_PROGRAM_ADDRESS} from "@solana-program/token-2022";const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const mint = await generateKeyPairSigner();const space = BigInt(getMintSize());const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();const createAccountInstruction = getCreateAccountInstruction({payer: client.payer,newAccount: mint,space,lamports: rent,programAddress: TOKEN_2022_PROGRAM_ADDRESS});const initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: 2,mintAuthority: client.payer.address,freezeAuthority: client.payer.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS});const result = await client.sendTransaction([createAccountInstruction,initializeMintInstruction]);console.log("Mint Address:", mint.address);console.log("Transaction Signature:", result.context.signature);const mintAccount = await fetchMint(client.rpc, mint.address);console.log("Mint Account:", mintAccount);
Создайте и пополните клиент Kit, затем сгенерируйте подписанта, который будет использоваться в качестве адреса нового mint account. Плательщик клиента финансирует создание аккаунта и оплачивает комиссию за транзакцию.
const client = await createClient().use(generatedPayer()).use(solanaRpc({rpcUrl: "http://localhost:8899",rpcSubscriptionsUrl: "ws://localhost:8900"})).use(rpcAirdrop()).use(airdropPayer(lamports(1_000_000_000n)));const mint = await generateKeyPairSigner();
Вычислите размер mint account в байтах, затем выполните RPC-запрос для расчёта количества lamport, необходимых для хранения этих данных в аккаунте. Этот требуемый баланс называется rent.
const space = BigInt(getMintSize());const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();
Первая инструкция вызывает System Program. Инструкция использует
payer для пополнения newAccount,
выделяет mint account space, переводит освобождённые от rent
lamports и передаёт право собственности
programAddress.
const createAccountInstruction = getCreateAccountInstruction({payer: client.payer,newAccount: mint,space,lamports: rent,programAddress: TOKEN_2022_PROGRAM_ADDRESS});
Вторая инструкция вызывает Token Extensions Program. Инструкция инициализирует
адрес mint со значением
decimals, mintAuthority,
freezeAuthority и указывает
tokenProgram, которому принадлежит mint account.
const initializeMintInstruction = getInitializeMintInstruction({mint: mint.address,decimals: 2,mintAuthority: client.payer.address,freezeAuthority: client.payer.address,tokenProgram: TOKEN_2022_PROGRAM_ADDRESS});
Отправьте обе инструкции в одной транзакции. Инструкция создания аккаунта должна идти перед инструкцией инициализации mint account, поскольку mint account должен существовать до того, как Token Extensions Program сможет записать данные минта в аккаунт.
const result = await client.sendTransaction([createAccountInstruction,initializeMintInstruction]);
После подтверждения транзакции получите mint account.
const mintAccount = await fetchMint(client.rpc, mint.address);console.log("Mint Account:", mintAccount);
Is this page helpful?