Проверка адреса

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

Подробнее о ключевых понятиях платежей читайте в разделе Как работают платежи в Solana.

Понимание адресов Solana

В Solana у аккаунтов есть два типа адресов: on-curve и off-curve.

On-curve адреса

Стандартные адреса — это публичные ключи из пар ключей Ed25519. Эти адреса:

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

Off-curve адреса (PDA)

Program Derived Addresses (PDA) детерминировано создаются на основе ID программы и seed-значений. Эти адреса:

  • Не имеют соответствующего приватного ключа
  • Могут быть подписаны только программой, от которой был получен этот адрес

Типы аккаунтов в платежах

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

Знание того, является ли адрес on-curve или off-curve, не говорит о том, какой это тип аккаунта, какая программа им владеет или существует ли аккаунт по этому адресу. Необходимо получить аккаунт из сети, чтобы узнать эти детали.

Аккаунты System Program (кошельки)

Аккаунты, принадлежащие System Program, являются стандартными кошельками. Чтобы отправить SPL токены на кошелек, необходимо получить и использовать его associated token account (ATA).

После получения адреса ATA проверьте, существует ли этот token account в блокчейне. Если ATA не существует, вы можете добавить инструкцию на создание токен-аккаунта получателя в ту же транзакцию, что и перевод. Однако для этого потребуется оплатить rent за новый token account. Поскольку получатель владеет ATA, SOL, потраченные на rent, не могут быть возвращены отправителю.

Без мер предосторожности субсидирование создания ATA может быть использовано в корыстных целях. Злоумышленник может запросить перевод, создать свой ATA за ваш счёт, закрыть ATA, чтобы вернуть rent в SOL, и повторить это снова.

Токен-аккаунты

Токен-аккаунты принадлежат Token Program или Token-2022 Program и содержат балансы токенов. Если полученный вами адрес принадлежит токен-программе, необходимо убедиться, что это токен-аккаунт (а не mint account) и что он соответствует ожидаемому mint account токена перед отправкой.

Token Program автоматически проверяют, что оба токен-аккаунта при переводе содержат токены одного и того же mint. Если проверка не проходит, транзакция отклоняется, и средства не теряются.

Mint-аккаунты

Mint-аккаунты отслеживают эмиссию токена и метаданные конкретного токена. Mint-аккаунты также принадлежат Token Program, но не являются допустимыми получателями токенов. Попытка отправить токены на адрес mint приводит к неудачной транзакции, но средства не теряются.

Другие аккаунты

Аккаунты, принадлежащие другим программам, требуют отдельной политики. Некоторые аккаунты (например, мультисиг-кошельки) могут быть допустимыми владельцами токен-аккаунтов, а другие должны быть отклонены.

Процесс верификации

На следующей схеме показано примерное дерево решений для проверки адреса:

Address Verification Flow

Получить аккаунт

Используйте адрес для получения данных аккаунта из сети.

Аккаунт не существует

Если по этому адресу нет аккаунта, проверьте, находится ли адрес на кривой или вне кривой:

  • Off-curve (PDA): Консервативно отклоняйте этот адрес, чтобы избежать отправки на ATA, который может быть недоступен. Без существующего аккаунта невозможно определить только по адресу, какая программа сгенерировала этот PDA или предназначен ли адрес для ATA. Создание ATA для этого адреса с целью отправки токенов может привести к блокировке средств на недоступном token account.

  • On-curve: Это действительный адрес кошелька (публичный ключ), который еще не был профинансирован. Получите ATA, проверьте его наличие и отправьте туда токены. Вам необходимо принять решение о политике: финансировать ли создание ATA, если он отсутствует.

Аккаунт существует

Если аккаунт существует, проверьте, какая программа им владеет:

  • System Program: Это стандартный кошелек. Получите ATA, проверьте его наличие и отправьте туда токены. Необходимо принять решение о политике: финансировать ли создание ATA, если он отсутствует.

  • Token Program / Token-2022: Убедитесь, что аккаунт является token account (а не mint account) и что он содержит нужный вам токен (mint). Если все верно, отправьте токены напрямую на этот адрес. Если это mint account или token account для другого mint, отклоните адрес.

  • Other Program: Требуется решение по политике. Некоторые программы, например мультисиг-кошельки, могут быть допустимыми владельцами token account. Если ваша политика это разрешает, получите ATA и отправьте. В противном случае отклоните адрес.

Демонстрация

Следующий пример показывает только логику валидации адреса. Это справочный код для иллюстрации.

В этом демо не показано, как получить ATA или сформировать транзакцию для отправки токенов. Обратитесь к документации по token account и token transfer, чтобы посмотреть примеры кода.

В демо ниже используются три возможных результата:

РезультатЗначениеДействие
IS_WALLETВалидный адрес кошелькаПолучить и отправить на associated token account
IS_TOKEN_ACCOUNTВалидный token accountОтправить токены напрямую на этот адрес
REJECTНеверный адресНе отправлять
Demo
/**
* Validates an input address and classifies it as a wallet, token account, or invalid.
*
* @param inputAddress - The address to validate
* @param rpc - Optional RPC client (defaults to mainnet)
* @returns Classification result:
* - IS_WALLET: Valid wallet address
* - IS_TOKEN_ACCOUNT: Valid token account
* - REJECT: Invalid address for transfers
*/
export async function validateAddress(
inputAddress: Address,
rpc: Rpc<GetAccountInfoApi> = defaultRpc
): Promise<ValidationResult> {
const account = await fetchJsonParsedAccount(rpc, inputAddress);
// Log the account data for demo
console.log("\nAccount:", account);
// Account doesn't exist on-chain
if (!account.exists) {
// Off-curve = PDA that doesn't exist as an account
// Reject conservatively to avoid sending to an address that may be inaccessible.
if (isOffCurveAddress(inputAddress)) {
return { type: "REJECT", reason: "PDA doesn't exist as an account" };
}
// On-curve = valid keypair address, treat as unfunded wallet
return { type: "IS_WALLET" };
}
// Account exists, check program owner
const owner = account.programAddress;
// System Program = wallet
if (owner === SYSTEM_PROGRAM) {
return { type: "IS_WALLET" };
}
// Token Program or Token-2022, check if token account
if (owner === TOKEN_PROGRAM || owner === TOKEN_2022_PROGRAM) {
const accountType = (
account.data as { parsedAccountMeta?: { type?: string } }
).parsedAccountMeta?.type;
if (accountType === "account") {
return { type: "IS_TOKEN_ACCOUNT" };
}
// Reject if not a token account (mint account)
return {
type: "REJECT",
reason: "Not a token account"
};
}
// Unknown program owner
return { type: "REJECT", reason: "Unknown program owner" };
}
// =============================================================================
// Examples
// =============================================================================
Console
Click to execute the code.

Is this page helpful?

Управляется

© 2026 Фонд Solana.
Все права защищены.
Подключиться