同步原生 SOL

什么是包装 SOL?

包装 SOL (WSOL) 是指存储在 Token Program 原生铸币地址的 token account 中的 SOL。原生铸币地址是 Token Program 用于包装 SOL 的 token account 的铸币地址。原生铸币使 SOL 能够通过 Token Program 的指令进行使用。

程序原生铸币地址
Token ProgramSo11111111111111111111111111111111111111112
Token Extension Program9pan9bMn5HatX4EJdBwg9VgCa7Uz5HL8N1m5D3NdXejP

包装 SOL token account 将 SOL 存储在账户的 lamports 字段中,但通过 token account 的 amount 字段将持有的 SOL 作为代币余额进行跟踪。如果您将 SOL 转入包装 SOL token account,lamport 余额会立即增加,但 amount 字段不会改变,直到您调用 Token Program 的 SyncNative 指令。

如何同步原生 SOL

在将 SOL 转入包装 SOL token account 后,使用 Token Program 的 SyncNative 指令。SyncNative 指令会更新 token account 的 amount 字段,使其与账户中超出免租金储备的 lamport 数量相匹配。

源代码参考

项目描述Token ProgramToken Extension Program
Accounttoken account 状态使用 is_native 来标记账户为 WSOL,并存储原生储备、账户必须保留的免租金最低 lamport 余额以及跟踪的代币金额。源代码源代码
SyncNative该指令更新包装 SOL token account 的 amount 字段,使其与账户中超出免租金储备的 lamport 数量相匹配。源代码源代码
process_sync_native用于同步包装 SOL 余额的共享处理器逻辑。源代码源代码

Typescript

以下 Kit 示例展示了使用 @solana/kit 的推荐方法。同时包含使用 @solana/web3.js 的旧版示例以供参考。

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 python3
import asyncio
import json
from solana.rpc.async_api import AsyncClient
from solders.keypair import Keypair
from solders.message import Message
from solders.pubkey import Pubkey
from solders.transaction import Transaction
from solders.system_program import transfer, TransferParams
from spl.token.async_client import AsyncToken
from 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_MINT
AMOUNT_TO_WRAP = 1_000_000
async 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 value
for 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?

Table of Contents

Edit Page

管理者

©️ 2026 Solana 基金会版权所有
取得联系