Wysłanie środków na nieprawidłowy adres może skutkować ich trwałą utratą. Weryfikacja adresu zapewnia, że Ty i Twoi użytkownicy wysyłacie środki wyłącznie na adresy, które mogą je prawidłowo odbierać i do nich uzyskiwać dostęp. Jeśli prowadzisz giełdę, zaleca się przeprowadzenie tych kontroli oraz poproszenie użytkownika o weryfikację adresu przed wysłaniem.
Walidacja zależy od tego, co wysyłasz:
- Tokeny SPL są częściowo samochroniące. Token Program odrzuca transfer, którego konta nie pasują do oczekiwanego mintu, więc błędnie skierowany transfer tokenów kończy się niepowodzeniem bez utraty środków. Większość tej strony dotyczy wysyłania tokenów SPL.
- Natywne SOL nie ma takiego zabezpieczenia. Transfer przez System Program powiedzie się na każdym koncie, więc nieprawidłowy odbiorca trwale blokuje SOL. Zobacz Wysyłanie natywnego SOL.
Zobacz Jak działają płatności na Solanie, aby poznać podstawowe koncepcje dotyczące płatności.
Zrozumienie adresów Solany
Konta Solany mają dwa typy adresów: na krzywej (on-curve) i poza krzywą (off-curve).
Adresy na krzywej (On-Curve)
Standardowe adresy to klucze publiczne z keypairs Ed25519. Te adresy:
- Posiadają odpowiadający klucz prywatny, który może podpisywać transakcje
- Są używane jako adresy portfeli
Adresy poza krzywą (PDAs)
Program Derived Addresses są deterministycznie wyprowadzane z identyfikatora programu i ziaren (seeds). Te adresy:
- Nie posiadają odpowiadającego klucza prywatnego
- Mogą być podpisywane wyłącznie przez program, z którego adres został wyprowadzony
Portfele kontrolowane przez programy, powszechnie określane jako smart portfele lub smart konta, posiadają adresy poza krzywą (off-curve). W tym przewodniku konsekwentnie używany jest termin „smart portfel“.
Typy kont w płatnościach
Użyj adresu, aby pobrać konto z sieci, sprawdź właściciela programu i typ konta, aby określić sposób obsługi adresu.
Wiedza o tym, czy adres jest na krzywej, czy poza krzywą, nie mówi ci, jaki to typ konta, który program jest jego właścicielem ani czy konto istnieje pod tym adresem. Aby ustalić te szczegóły, musisz pobrać konto z sieci.
Konta System Program (Portfele)
Konta należące do System Program to standardowe portfele. Aby wysłać tokeny SPL do portfela, należy wyprowadzić i użyć jego Associated Token Account (ATA).
Po wyprowadzeniu adresu ATA sprawdź, czy token account istnieje w łańcuchu. Jeśli ATA nie istnieje, możesz dołączyć instrukcję jego utworzenia dla odbiorcy w tej samej transakcji co przelew. Wymaga to jednak opłacenia rent za nowy token account. Ponieważ odbiorca jest właścicielem ATA, SOL zapłacony za rent nie może zostać odzyskany przez nadawcę.
Konta systemowe mogą istnieć poza krzywą (off-curve). Jeśli użytkownik chce wysłać tokeny na adres off-curve, zaleca się wyświetlenie monitu z prośbą o potwierdzenie, że zamierza wysłać środki do smart portfela.
Bez odpowiednich zabezpieczeń, finansowanie tworzenia ATA może zostać wykorzystane do nadużyć. Złośliwy użytkownik mógłby zażądać przelewu, doprowadzić do utworzenia swojego ATA na Twój koszt, zamknąć ATA w celu odzyskania rent SOL, a następnie powtarzać ten proceder.
Token Accounts
Token accounts są własnością Token Program lub Token-2022 Program i przechowują salda tokenów. Jeśli adres, który otrzymujesz, należy do programu tokenów, powinieneś zweryfikować, czy konto jest token account (nie mint account) i czy odpowiada oczekiwanemu token mint account przed wysłaniem.
Token Programs automatycznie weryfikują, czy oba token accounts w transakcji przechowują tokeny tego samego mintu. Jeśli weryfikacja się nie powiedzie, transakcja zostaje odrzucona i żadne środki nie są tracone.
Konta Mint
Mint accounts śledzą podaż tokenów oraz metadane konkretnego tokena. Mint accounts są również własnością Token Programs, ale nie są prawidłowymi odbiorcami transferów tokenów. Próba wysłania tokenów na adres mint skutkuje nieudaną transakcją, jednak żadne środki nie są tracone.
Inne konta
Konta należące do innych programów są prawidłowe, lecz podlegają regułom uprawnień określonym przez odpowiedni program będący właścicielem. Zaleca się wyświetlenie monitu z prośbą o potwierdzenie, że użytkownik zamierza wysłać środki do smart portfela.
Wysyłanie natywnego SOL
Powyższa klasyfikacja określa, dokąd mogą trafiać tokeny SPL. Natywny SOL jest bardziej restrykcyjny: jedynym bezpiecznym odbiorcą jest portfel System Program (lub niefinansowany adres na krzywej, który staje się nim).
Transfer w ramach System Program dodaje lamport do dowolnego konta, w tym mint, token accounts, programów i PDA. Lamports mogą być wyprowadzone tylko przez program będący właścicielem konta, więc wysłanie SOL do nieprawidłowego odbiorcy może skutkować trwałą utratą środków.
W przeciwieństwie do transferu tokenów SPL, transakcja nie kończy się niepowodzeniem, gdy odbiorca jest nieoczekiwanym adresem.
Podczas wysyłania natywnego SOL akceptowalnym wynikiem jest wyłącznie
IS_WALLET. IS_TOKEN_ACCOUNT nie jest: token account przechowuje tokeny
SPL, a SOL wysłany tam jest poza kontrolą nadawcy.
To częsty sposób na utratę SOL: użytkownik wkleja adres mint tokena (lub adres programu) do pola wypłaty SOL. Transfer kończy się powodzeniem, a SOL jest nieodwracalnie utracony. Zawsze klasyfikuj odbiorcę przed podpisaniem transferu SOL.
Przepływ weryfikacji
Poniższy diagram przedstawia referencyjne drzewo decyzyjne do walidacji adresu:
Pobierz konto
Użyj adresu, aby pobrać szczegóły konta z sieci.
Konto nie istnieje
Jeśli pod tym adresem nie istnieje żadne konto, sprawdź, czy adres jest on-curve, czy off-curve:
-
Off-curve (PDA): Wymagaj jawnego potwierdzenia odbiorcy przed utworzeniem ATA lub wysłaniem tokenów SPL. Bez istniejącego konta nie można określić wyłącznie na podstawie adresu, który program wyprowadził ten PDA ani czy program odbiorcy może uzyskać dostęp do jego ATA.
-
On-curve: Jest to prawidłowy adres portfela (klucz publiczny), który nie został jeszcze zasilony. Wyprowadź ATA, sprawdź, czy istnieje, i wyślij na niego tokeny. Musisz podjąć decyzję dotyczącą polityki, czy sfinansować utworzenie ATA, jeśli jeszcze nie istnieje.
Konto istnieje
Jeśli konto istnieje, sprawdź, który program jest jego właścicielem:
-
System Program: Jest to standardowy portfel. Wyprowadź ATA, sprawdź, czy istnieje, i wyślij na niego tokeny. Musisz podjąć decyzję dotyczącą polityki, czy sfinansować utworzenie ATA, jeśli jeszcze nie istnieje.
-
Token Program / Token-2022: Sprawdź, czy konto jest token account (nie mint account) oraz czy przechowuje token (mint), który zamierzasz wysłać. Jeśli jest prawidłowe, wyślij tokeny bezpośrednio na ten adres. Jeśli jest to mint account lub token account powiązany z innym mintem, odrzuć adres.
-
Inny program: Programy takie jak portfele multisig są dopuszczalnymi właścicielami token accounts. Wymagaj od użytkownika potwierdzenia, że zamierza wysłać środki do smart portfela.
Niektóre popularne smart portfele:
Demo
Poniższy przykład pokazuje wyłącznie logikę walidacji adresu. Jest to kod referencyjny dla celów ilustracyjnych.
Demo nie pokazuje, jak wyprowadzić ATA ani jak zbudować transakcję wysyłania tokenów. Zapoznaj się z dokumentacją token account oraz token transfer, aby zobaczyć przykładowy kod.
Demo poniżej wykorzystuje trzy możliwe wyniki:
| Wynik | Znaczenie | Akcja |
|---|---|---|
IS_WALLET | Prawidłowy adres portfela | Wyprowadź i wyślij na associated token account |
IS_TOKEN_ACCOUNT | Prawidłowy token account | Wyślij tokeny bezpośrednio na ten adres |
USER_VERIFICATION | Adres wymaga potwierdzenia przez odbiorcę | Wymagaj jawnej weryfikacji przed wysłaniem tokenów SPL lub sfinansowaniem ATA |
REJECT | Nieprawidłowy adres | Nie wysyłaj |
Następnie mapuje każdy wynik na akceptowalność dla poszczególnych zasobów za pomocą canReceiveNativeSol (wyłącznie portfele) oraz canReceiveSplToken (portfele lub token accounts). Wynik USER_VERIFICATION nie jest akceptowany automatycznie — Twoja aplikacja powinna wymagać od użytkownika potwierdzenia zamiaru przed wysłaniem tokenów SPL. Token account zwraca IS_TOKEN_ACCOUNT, dzięki czemu może odbierać tokeny SPL, ale nie natywny SOL — to rozróżnienie zapobiega zablokowaniu SOL.
/*** Validates an input address and classifies it as a wallet, token account,* address requiring recipient verification, 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* - USER_VERIFICATION: Require explicit review before sending SPL tokens* - 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 democonsole.log("\nAccount:", account);// Account doesn't exist onchainif (!account.exists) {// An unfunded PDA may belong to a smart wallet, but the address// alone cannot prove that its program can access a newly-created ATA.if (isOffCurveAddress(inputAddress)) {return {type: "USER_VERIFICATION",reason:"Unfunded PDA: confirm the recipient is using a smart wallet and controls this address"};}// On-curve = valid keypair address, treat as unfunded walletreturn { type: "IS_WALLET" };}// Account exists, check program ownerconst owner = account.programAddress;// A System Program account can be a standard wallet or an off-curve smart// wallet. Require verification before automatically sending to the// latter.if (owner === SYSTEM_PROGRAM) {if (isOffCurveAddress(inputAddress)) {return {type: "USER_VERIFICATION",reason:"Off-curve System Program account: confirm recipient is using a smart wallet"};}return { type: "IS_WALLET" };}// Token Program or Token-2022, check if token accountif (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"};}// An account owned by another program can be a smart wallet.return {type: "USER_VERIFICATION",reason:"Program-owned account: confirm the recipient is using a smart wallet"};}/*** Native SOL is only safe to send to a wallet. Any other account locks it.*/function canReceiveNativeSol(result: ValidationResult): boolean {return result.type === "IS_WALLET";}/*** SPL tokens can go to a wallet (via its ATA) or directly to a token account.*/function canReceiveSplToken(result: ValidationResult): boolean {return result.type === "IS_WALLET" || result.type === "IS_TOKEN_ACCOUNT";}// =============================================================================// Examples// =============================================================================
Is this page helpful?