래핑된 SOL이란?
래핑된 SOL(WSOL)은 Token Program의 네이티브 민트를 위해 token account에 보관된 SOL입니다. 네이티브 민트는 Token Program이 SOL을 래핑하는 token account에 사용하는 민트 주소입니다. 네이티브 민트를 통해 SOL을 Token Program의 명령어로 사용할 수 있습니다.
| 프로그램 | 네이티브 민트 주소 |
|---|---|
| Token Program | So11111111111111111111111111111111111111112 |
| Token Extension Program | 9pan9bMn5HatX4EJdBwg9VgCa7Uz5HL8N1m5D3NdXejP |
래핑된 SOL token account는 계정의 lamports 필드에 SOL을 저장하지만, token
account의 amount 필드를 통해 래핑된 SOL token account에 보관된 SOL을 토큰
잔액으로 추적합니다. 래핑된 SOL token account로 SOL을 전송하면 lamport 잔액은
즉시 증가하지만, Token Program의 SyncNative 명령어를 호출하기 전까지 토큰
amount 필드는 변경되지 않습니다.
네이티브 SOL 동기화 방법
래핑된 SOL token account로 SOL을 전송한 후 Token Program의 SyncNative
명령어를 사용하세요. SyncNative 명령어는 token account의 amount
필드를 렌트 면제 준비금을 초과하여 계정에 보관된 lamport와 일치하도록
업데이트합니다.
소스 참조
| 항목 | 설명 | Token Program | Token Extension Program |
|---|---|---|---|
Account | token account 상태는 is_native 를 사용하여 계정을 WSOL로 표시하고, 네이티브 준비금, 계정이 유지해야 하는 렌트 면제 최소 lamport 잔액, 그리고 추적된 토큰 금액을 저장합니다. | Source | Source |
SyncNative | 래핑된 SOL token account의 amount 필드를 렌트 면제 준비금을 초과하여 계정에 보관된 lamport와 일치하도록 업데이트하는 명령어입니다. | Source | Source |
process_sync_native | 래핑된 SOL 잔액을 동기화하기 위한 공유 프로세서 로직입니다. | Source | Source |
Typescript
아래 예제들은 Kit를 사용하는 권장 방법을 보여줍니다. 참고용으로
@solana/kit를 사용하는 레거시 예제도 포함되어 있습니다.
Kit
import { address } from "@solana/kit";import { createLocalClient } from "@solana/kit-client-rpc";import { systemProgram } from "@solana-program/system";import {findAssociatedTokenPda,getCreateAssociatedTokenInstructionAsync,tokenProgram,TOKEN_PROGRAM_ADDRESS} from "@solana-program/token";const client = await createLocalClient().use(systemProgram()).use(tokenProgram());const NATIVE_MINT = address("So11111111111111111111111111111111111111112");const [tokenAccount] = await findAssociatedTokenPda({mint: NATIVE_MINT,owner: client.payer.address,tokenProgram: TOKEN_PROGRAM_ADDRESS});const result = await client.sendTransaction([client.system.instructions.transferSol({source: client.payer, // Account sending the SOL to wrap.destination: tokenAccount, // WSOL token account receiving the SOL.amount: 1_000_000n // SOL amount in lamports.}),client.token.instructions.syncNative({account: tokenAccount // WSOL token account to synchronize.})]);const tokenAccountData = await client.token.accounts.token.fetch(tokenAccount);console.log("WSOL Token Account Address:", tokenAccount);console.log("WSOL Token Account:", tokenAccountData.data);console.log("\nTransaction Signature:", result.context.signature);
Console
Click to execute the code.
Web3.js
import {Connection,Keypair,sendAndConfirmTransaction,LAMPORTS_PER_SOL,SystemProgram,Transaction} from "@solana/web3.js";import {createAssociatedTokenAccount,getAccount,NATIVE_MINT,syncNative,TOKEN_PROGRAM_ID} from "@solana/spl-token";const result = await syncNative(connection,feePayer, // Account paying transaction fees.associatedTokenAccount, // WSOL token account to synchronize.{commitment: "confirmed"},TOKEN_PROGRAM_ID // Token program to invoke.);const tokenAccountData = await getAccount(connection,associatedTokenAccount,"confirmed",TOKEN_PROGRAM_ID);console.log("WSOL Token Account Address:", associatedTokenAccount.toBase58());console.log("WSOL Token Account:", tokenAccountData);console.log("\nTransaction Signature:", result);
Console
Click to execute the code.
Rust
Rust
use anyhow::Result;use solana_client::nonblocking::rpc_client::RpcClient;use solana_commitment_config::CommitmentConfig;use solana_sdk::{program_pack::Pack,signature::{Keypair, Signer},transaction::Transaction,};use solana_system_interface::instruction::transfer;use spl_associated_token_account_interface::{address::get_associated_token_address, instruction::create_associated_token_account,};use spl_token_interface::{id as token_program_id,instruction::sync_native,native_mint::ID as NATIVE_MINT_ID,state::Account,};#[tokio::main]async fn main() -> Result<()> {let client = RpcClient::new_with_commitment(String::from("http://localhost:8899"),CommitmentConfig::confirmed(),);let associated_token_address = get_associated_token_address(&fee_payer.pubkey(), &NATIVE_MINT_ID);let sync_amount = 1_000_000;let transaction = Transaction::new_signed_with_payer(&[transfer(&fee_payer.pubkey(), // Account sending the SOL to wrap.&associated_token_address, // WSOL token account receiving the SOL.sync_amount, // SOL amount in lamports.),sync_native(&token_program_id(), // Token program to invoke.&associated_token_address, // WSOL token account to synchronize.)?,],Some(&fee_payer.pubkey()),&[&fee_payer],latest_blockhash,);let transaction_signature = client.send_and_confirm_transaction(&transaction).await?;let token_account = client.get_account(&associated_token_address).await?;let token_data = Account::unpack(&token_account.data)?;println!("WSOL Token Account Address: {}", associated_token_address);println!("WSOL Token Account: {:#?}", token_data);println!("\nTransaction Signature: {}", transaction_signature);Ok(())}
Console
Click to execute the code.
Python
Python
#!/usr/bin/env python3import asyncioimport jsonfrom solana.rpc.async_api import AsyncClientfrom solders.keypair import Keypairfrom solders.message import Messagefrom solders.pubkey import Pubkeyfrom solders.transaction import Transactionfrom solders.system_program import transfer, TransferParamsfrom spl.token.async_client import AsyncTokenfrom spl.token.instructions import (create_associated_token_account,get_associated_token_address,sync_native,SyncNativeParams,)from spl.token.constants import TOKEN_PROGRAM_ID, WRAPPED_SOL_MINTAMOUNT_TO_WRAP = 1_000_000async def main():rpc = AsyncClient("http://localhost:8899")async with rpc:sync_native_instructions = [transfer(TransferParams(from_pubkey=fee_payer.pubkey(), # Account sending SOL to the wrapped SOL token account.to_pubkey=wrapped_sol_account, # Wrapped SOL token account receiving the lamports.lamports=AMOUNT_TO_WRAP, # Lamports to wrap as WSOL.)),sync_native(SyncNativeParams(program_id=TOKEN_PROGRAM_ID, # Token program to invoke.account=wrapped_sol_account, # Wrapped SOL token account whose amount field updates.)),]latest_blockhash = await rpc.get_latest_blockhash()transaction = Transaction([fee_payer],Message(sync_native_instructions, fee_payer.pubkey()),latest_blockhash.value.blockhash,)result = await rpc.send_transaction(transaction)token_account_info = await token.get_account_info(wrapped_sol_account)token_account = {key: str(value) if isinstance(value, Pubkey) else valuefor key, value in token_account_info._asdict().items()}print("Native Mint Address:", WRAPPED_SOL_MINT)print("\nWrapped SOL Token Account Address:", wrapped_sol_account)print("Token Account:")print(json.dumps(token_account, indent=2))print("\nTransaction Signature:", result.value)if __name__ == "__main__":asyncio.run(main())
Console
Click to execute the code.
Is this page helpful?