Wrapped SOL
使用 Wrapped SOL (wSOL),将原生 SOL 转换为 SPL Token 格式。
Code Implementation
#!/usr/bin/env python3
"""
Solana Cookbook - How to Use Wrapped SOL
"""
import asyncio
from solana.rpc.async_api import AsyncClient
from solders.keypair import Keypair
from solders.transaction import VersionedTransaction
from solders.message import MessageV0
from solders.system_program import transfer, TransferParams
from spl.token.instructions import (
create_associated_token_account,
sync_native, SyncNativeParams,
close_account, CloseAccountParams,
get_associated_token_address
)
from spl.token.constants import TOKEN_PROGRAM_ID, ASSOCIATED_TOKEN_PROGRAM_ID
from solders.pubkey import Pubkey
# Native mint address for wrapped SOL
NATIVE_MINT = Pubkey.from_string("So11111111111111111111111111111111111111112")
async def main():
rpc = AsyncClient("https://api.devnet.solana.com")
# Example keypairs
payer = Keypair()
owner = Keypair()
# Amount to wrap (in lamports)
amount_to_wrap = 1000000000 # 1 SOL
async with rpc:
# Get associated token address for wrapped SOL
wrapped_sol_account = get_associated_token_address(
owner=owner.pubkey(),
mint=NATIVE_MINT,
token_program_id=TOKEN_PROGRAM_ID
)
# Create associated token account for wrapped SOL
create_ata_instruction = create_associated_token_account(
payer=payer.pubkey(),
owner=owner.pubkey(),
mint=NATIVE_MINT,
token_program_id=TOKEN_PROGRAM_ID,
associated_token_program_id=ASSOCIATED_TOKEN_PROGRAM_ID
)
# Transfer SOL to the wrapped SOL account
transfer_instruction = transfer(
TransferParams(
from_pubkey=payer.pubkey(),
to_pubkey=wrapped_sol_account,
lamports=amount_to_wrap
)
)
# Sync native instruction to update the wrapped SOL balance
sync_native_instruction = sync_native(
SyncNativeParams(
program_id=TOKEN_PROGRAM_ID,
account=wrapped_sol_account
)
)
# Get latest blockhash
recent_blockhash = await rpc.get_latest_blockhash()
# Create message for wrapping SOL
wrap_message = MessageV0.try_compile(
payer=payer.pubkey(),
instructions=[
create_ata_instruction,
transfer_instruction,
sync_native_instruction
],
address_lookup_table_accounts=[],
recent_blockhash=recent_blockhash.value.blockhash
)
# Create transaction
wrap_transaction = VersionedTransaction(wrap_message, [payer, owner])
print(f"Wrapped SOL Account: {wrapped_sol_account}")
print(f"Amount to wrap: {amount_to_wrap / 1000000000} SOL")
# Send wrapping transaction
result = await rpc.send_transaction(wrap_transaction)
print(f"Wrap transaction signature: {result.value}")
# Unwrap SOL by closing the account
print("\nUnwrapping SOL...")
# Close account instruction to unwrap SOL
close_instruction = close_account(
CloseAccountParams(
program_id=TOKEN_PROGRAM_ID,
account=wrapped_sol_account,
dest=owner.pubkey(),
owner=owner.pubkey()
)
)
# Get latest blockhash
recent_blockhash = await rpc.get_latest_blockhash()
# Create message for unwrapping SOL
unwrap_message = MessageV0.try_compile(
payer=payer.pubkey(),
instructions=[close_instruction],
address_lookup_table_accounts=[],
recent_blockhash=recent_blockhash.value.blockhash
)
# Create transaction
unwrap_transaction = VersionedTransaction(unwrap_message, [payer, owner])
# Send unwrapping transaction
result = await rpc.send_transaction(unwrap_transaction)
print(f"Unwrap transaction signature: {result.value}")
if __name__ == "__main__":
asyncio.run(main())
Code Explanation
This example demonstrates how to use Wrapped SOL:
- Create a wSOL account: Create an associated token account for native SOL
- Transfer SOL: Transfer SOL into the wSOL account
- Sync balance: Use
sync_native()
to sync the wSOL account balance - Unwrap SOL: Convert wSOL back to native SOL by closing the account
Key Concepts
- Wrapped SOL (wSOL): Wraps native SOL into SPL Token format
- Native Mint: The special token mint address for native SOL
- Sync Native: Synchronizes the balance of native token accounts
- Unwrapping: Converts wSOL back to native SOL by closing the account
Usage
Wrapping SOL
- Create an associated token account for wSOL
- Transfer SOL to that account
- Call
sync_native()
to synchronize the balance
Unwrapping SOL
- Use
close_account()
to close the wSOL account - SOL in the account will be returned to the specified destination account
Why Use Wrapped SOL
- Unified Interface: Allows SOL to be operated like other SPL tokens
- DeFi Protocols: Use SOL in protocols that require token interfaces
- Trading Pairs: Create SOL trading pairs in decentralized exchanges
- Program Compatibility: Enables programs that only support SPL tokens to handle SOL
Important Notes
- The wSOL account balance equals the amount of SOL in it
- Creating a wSOL account requires rent, which can be recovered when closing
sync_native()
must be called after transferring SOL to correctly update the balance- When unwrapping, the account must have no delegation permissions
- Sufficient SOL is required to pay transaction fees