Запись в сеть

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

Программы определяют бизнес-логику для каждой инструкции. Когда вы отправляете транзакцию, среда выполнения Solana выполняет инструкции транзакции по порядку. Транзакции являются атомарными: либо все инструкции в транзакции выполняются успешно, либо вся транзакция завершается с ошибкой.

Примеры в этом разделе показывают, как:

  1. Перевести SOL между аккаунтами
  2. Создать новый токен-минт

Перевод SOL

Приведённый ниже пример переводит SOL с одного аккаунта на другой. Только программа, назначенная владельцем аккаунта, может изменять данные аккаунта или списывать lamport с его баланса. Кошельковые аккаунты принадлежат System Program, поэтому перевод SOL между кошельковыми аккаунтами требует инструкции, вызывающей инструкцию transfer System Program. Исходный аккаунт также должен подписать транзакцию.

Transfer SOL
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);
Console
Click to execute the code.

Создайте клиент Kit для локального тестового validator. Этот фрагмент добавляет подписанта-плательщика, подключается к локальному RPC-эндпоинту, включает аирдропы и пополняет кошелёк плательщика тестовыми SOL для перевода.

Client setup
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().

Receiver signer
const receiver = await generateKeyPairSigner();

Вспомогательная функция getTransferSolInstruction() создаёт инструкцию System Program. Инструкция переводит SOL от подписанта source на адрес destination на указанное amount lamports.

Transfer instruction
const transferInstruction = getTransferSolInstruction({
source: client.payer,
destination: receiver.address,
amount: lamports(10_000_000n)
});

Вызовите client.sendTransaction() с массивом инструкций. Клиент Kit объединяет инструкции в одну транзакцию, подписывает с помощью подписантов, прикреплённых к инструкциям, отправляет транзакцию и ожидает подтверждения.

Send transaction
const result = await client.sendTransaction([transferInstruction]);
console.log("Transaction Signature:", result.context.signature);

После подтверждения транзакции получите оба баланса с помощью client.rpc.

Fetch balances
const { value: senderBalance } = await client.rpc
.getBalance(client.payer.address)
.send();
const { value: receiverBalance } = await client.rpc
.getBalance(receiver.address)
.send();

Создайте клиент Kit для локального тестового validator. Этот фрагмент добавляет подписанта-плательщика, подключается к локальному RPC-эндпоинту, включает аирдропы и пополняет кошелёк плательщика тестовыми SOL для перевода.

Client setup
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().

Receiver signer
const receiver = await generateKeyPairSigner();

Вспомогательная функция getTransferSolInstruction() создаёт инструкцию System Program. Инструкция переводит SOL от подписанта source на адрес destination на указанное amount lamports.

Transfer instruction
const transferInstruction = getTransferSolInstruction({
source: client.payer,
destination: receiver.address,
amount: lamports(10_000_000n)
});

Вызовите client.sendTransaction() с массивом инструкций. Клиент Kit объединяет инструкции в одну транзакцию, подписывает с помощью подписантов, прикреплённых к инструкциям, отправляет транзакцию и ожидает подтверждения.

Send transaction
const result = await client.sendTransaction([transferInstruction]);
console.log("Transaction Signature:", result.context.signature);

После подтверждения транзакции получите оба баланса с помощью client.rpc.

Fetch balances
const { value: senderBalance } = await client.rpc
.getBalance(client.payer.address)
.send();
const { value: receiverBalance } = await client.rpc
.getBalance(receiver.address)
.send();
Transfer SOL
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)));

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

В примере ниже создаётся новый mint account с использованием Token Extensions Program. mint account — это аккаунт, определяющий глобальные настройки токена: количество знаков после запятой, эмиссию, полномочия на выпуск и полномочия на заморозку.

Создание mint account требует двух инструкций:

  1. Вызов System Program для создания нового аккаунта, принадлежащего Token Extensions Program.
  2. Вызов Token Extensions Program для инициализации этого аккаунта как mint.
Create mint account
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);
Console
Click to execute the code.

Создайте и пополните клиент Kit, затем сгенерируйте подписанта, который будет использоваться в качестве адреса нового mint account. Плательщик клиента финансирует создание аккаунта и оплачивает комиссию за транзакцию.

Client and mint setup
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.

Mint account size and rent
const space = BigInt(getMintSize());
const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();

Первая инструкция вызывает System Program. Инструкция использует payer для пополнения newAccount, выделяет mint account space, переводит освобождённые от rent lamports и передаёт право собственности programAddress.

Create account instruction
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.

Initialize mint instruction
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 сможет записать данные минта в аккаунт.

Send transaction
const result = await client.sendTransaction([
createAccountInstruction,
initializeMintInstruction
]);

После подтверждения транзакции получите mint account.

Fetch mint account
const mintAccount = await fetchMint(client.rpc, mint.address);
console.log("Mint Account:", mintAccount);

Создайте и пополните клиент Kit, затем сгенерируйте подписанта, который будет использоваться в качестве адреса нового mint account. Плательщик клиента финансирует создание аккаунта и оплачивает комиссию за транзакцию.

Client and mint setup
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.

Mint account size and rent
const space = BigInt(getMintSize());
const rent = await client.rpc.getMinimumBalanceForRentExemption(space).send();

Первая инструкция вызывает System Program. Инструкция использует payer для пополнения newAccount, выделяет mint account space, переводит освобождённые от rent lamports и передаёт право собственности programAddress.

Create account instruction
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.

Initialize mint instruction
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 сможет записать данные минта в аккаунт.

Send transaction
const result = await client.sendTransaction([
createAccountInstruction,
initializeMintInstruction
]);

После подтверждения транзакции получите mint account.

Fetch mint account
const mintAccount = await fetchMint(client.rpc, mint.address);
console.log("Mint Account:", mintAccount);
Create mint account
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();

Is this page helpful?

Содержание

Редактировать страницу
Запись в сеть | Solana