---
title: Sync Native
description:
  Update a wrapped SOL token account amount after transferring SOL into the
  account.
url: /docs/tokens/basics/sync-native
type: tutorial
prerequisites:
  - /docs/tokens/basics/create-token-account
related:
  - /docs/tokens/basics/create-token-account
  - /docs/tokens/basics/close-account
  - /docs/tokens/basics/transfer-tokens
---

## What Is Wrapped SOL?

Wrapped SOL (WSOL) is SOL held in a token account for the Token Program's native
mint. The native mint is the mint address the Token Program uses for token
accounts that wrap SOL. The native mint enables SOL to be used through the Token
Program's instructions.

| Program                 | Native mint address                            |
| ----------------------- | ---------------------------------------------- |
| Token Program           | `So11111111111111111111111111111111111111112`  |
| Token Extension Program | `9pan9bMn5HatX4EJdBwg9VgCa7Uz5HL8N1m5D3NdXejP` |

A wrapped SOL token account stores SOL in the account's `lamports` field, but
tracks the SOL held in the wrapped SOL token account as a token balance through
the token account _rs`amount`_ field. If you transfer SOL into a wrapped SOL
token account, the lamport balance increases immediately, but the token
_rs`amount`_ field does not change until you call the Token Program's
_rs`SyncNative`_ instruction.

## How to Sync Native SOL

Use the Token Program's _rs`SyncNative`_ instruction after transferring SOL into
a wrapped SOL token account. The _rs`SyncNative`_ instruction updates the token
account _rs`amount`_ field to match the lamports held in the account above its
rent-exempt reserve.

### Source Reference

| Item                      | Description                                                                                                                                                                                          | Token Program                                                                                                  | Token Extension Program                                                                                              |
| ------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------- |
| _rs`Account`_             | The token account state uses _rs`is_native`_ to mark the account as WSOL and stores the native reserve, the rent-exempt minimum lamport balance the account must keep, and the tracked token amount. | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/state.rs#L84-L108)        | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/state.rs#L99-L123)        |
| _rs`SyncNative`_          | An instruction that updates a wrapped SOL token account _rs`amount`_ field to match the lamports held in the account above its rent-exempt reserve.                                                  | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/interface/src/instruction.rs#L366-L376) | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/interface/src/instruction.rs#L434-L444) |
| _rs`process_sync_native`_ | Shared processor logic for synchronizing wrapped SOL balances.                                                                                                                                       | [Source](https://github.com/solana-program/token/blob/program%40v9.0.0/program/src/processor.rs#L757-L779)     | [Source](https://github.com/solana-program/token-2022/blob/program%40v10.0.0/program/src/processor.rs#L1344-L1371)   |

### Typescript

The `Kit` examples below show the recommended approach using `@solana/kit`.
Legacy examples using `@solana/web3.js` are included for reference.

#### Kit

<CodeTabs storage="token-ts-kit" flags="r">

```ts !! title="Plugin"
import { address, createClient, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import { systemProgram } from "@solana-program/system";
import {
  findAssociatedTokenPda,
  getCreateAssociatedTokenInstructionAsync,
  tokenProgram,
  TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)))
  // !mark[/\.use\(systemProgram\(\)\)/]
  .use(systemProgram())
  // !mark[/\.use\(tokenProgram\(\)\)/]
  .use(tokenProgram());

const NATIVE_MINT = address("So11111111111111111111111111111111111111112");

const [tokenAccount] = await findAssociatedTokenPda({
  mint: NATIVE_MINT,
  owner: client.payer.address,
  tokenProgram: TOKEN_PROGRAM_ADDRESS
});

// !collapse(1:8) collapsed
// Setup: create a WSOL ATA before wrapping and syncing SOL.
await client.sendTransaction([
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer,
    mint: NATIVE_MINT,
    owner: client.payer.address
  })
]);

const result = await client.sendTransaction([
  // !mark(1:8)
  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);
```

```ts !! title="Instructions"
import { address, createClient, lamports } from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import { getTransferSolInstruction } from "@solana-program/system";
import {
  fetchToken,
  findAssociatedTokenPda,
  getCreateAssociatedTokenInstructionAsync,
  getSyncNativeInstruction,
  TOKEN_PROGRAM_ADDRESS
} from "@solana-program/token";

const client = await createClient()
  .use(generatedPayer())
  .use(
    solanaRpc({
      rpcUrl: "http://localhost:8899",
      rpcSubscriptionsUrl: "ws://localhost:8900"
    })
  )
  .use(rpcAirdrop())
  .use(airdropPayer(lamports(1_000_000_000n)));

const NATIVE_MINT = address("So11111111111111111111111111111111111111112");

const [tokenAccount] = await findAssociatedTokenPda({
  mint: NATIVE_MINT,
  owner: client.payer.address,
  tokenProgram: TOKEN_PROGRAM_ADDRESS
});

// !collapse(1:8) collapsed
// Setup: create a WSOL ATA before wrapping and syncing SOL.
await client.sendTransaction([
  await getCreateAssociatedTokenInstructionAsync({
    payer: client.payer,
    mint: NATIVE_MINT,
    owner: client.payer.address
  })
]);

const result = await client.sendTransaction([
  // !mark(1:8)
  getTransferSolInstruction({
    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.
  }),
  getSyncNativeInstruction({
    account: tokenAccount // WSOL token account to synchronize.
  })
]);

const tokenAccountData = await fetchToken(client.rpc, tokenAccount);

console.log("WSOL Token Account Address:", tokenAccount);
console.log("WSOL Token Account:", tokenAccountData.data);
console.log("\nTransaction Signature:", result.context.signature);
```

</CodeTabs>

#### Web3.js

<CodeTabs storage="token-ts-legacy" flags="r">

```ts !! title="Helper Function"
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";

// !collapse(1:42) collapsed
// Setup: create a WSOL ATA and transfer SOL into the WSOL ATA before calling SyncNative.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  2 * LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const associatedTokenAccount = await createAssociatedTokenAccount(
  connection,
  feePayer,
  NATIVE_MINT,
  feePayer.publicKey,
  {
    commitment: "confirmed"
  },
  TOKEN_PROGRAM_ID
);

await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: latestBlockhash.blockhash,
    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
  }).add(
    SystemProgram.transfer({
      fromPubkey: feePayer.publicKey, // Account sending the SOL to wrap.
      toPubkey: associatedTokenAccount, // WSOL token account receiving the SOL.
      lamports: 1_000_000 // SOL amount in lamports.
    })
  ),
  [feePayer]
);

// !mark(1:8)
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);
```

```ts !! title="Instructions"
import {
  Connection,
  Keypair,
  sendAndConfirmTransaction,
  SystemProgram,
  Transaction,
  LAMPORTS_PER_SOL
} from "@solana/web3.js";
import {
  ASSOCIATED_TOKEN_PROGRAM_ID,
  createAssociatedTokenAccountInstruction,
  createSyncNativeInstruction,
  getAccount,
  getAssociatedTokenAddressSync,
  NATIVE_MINT,
  TOKEN_PROGRAM_ID
} from "@solana/spl-token";

// !collapse(1:42) collapsed
// Setup: create a WSOL ATA before wrapping and syncing SOL.
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();

const feePayer = Keypair.generate();

const airdropSignature = await connection.requestAirdrop(
  feePayer.publicKey,
  2 * LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
  blockhash: latestBlockhash.blockhash,
  lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
  signature: airdropSignature
});

const associatedTokenAccount = getAssociatedTokenAddressSync(
  NATIVE_MINT,
  feePayer.publicKey,
  false,
  TOKEN_PROGRAM_ID,
  ASSOCIATED_TOKEN_PROGRAM_ID
);

await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: latestBlockhash.blockhash,
    lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
  }).add(
    createAssociatedTokenAccountInstruction(
      feePayer.publicKey,
      associatedTokenAccount,
      feePayer.publicKey,
      NATIVE_MINT,
      TOKEN_PROGRAM_ID,
      ASSOCIATED_TOKEN_PROGRAM_ID
    )
  ),
  [feePayer]
);

const syncBlockhash = await connection.getLatestBlockhash();
// !mark(1:19)
const result = await sendAndConfirmTransaction(
  connection,
  new Transaction({
    feePayer: feePayer.publicKey,
    blockhash: syncBlockhash.blockhash,
    lastValidBlockHeight: syncBlockhash.lastValidBlockHeight
  }).add(
    SystemProgram.transfer({
      fromPubkey: feePayer.publicKey, // Account sending the SOL to wrap.
      toPubkey: associatedTokenAccount, // WSOL token account receiving the SOL.
      lamports: 1_000_000 // SOL amount in lamports.
    }),
    createSyncNativeInstruction(
      associatedTokenAccount, // WSOL token account to synchronize.
      TOKEN_PROGRAM_ID // Token program to invoke.
    )
  ),
  [feePayer]
);

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);
```

</CodeTabs>

### Rust

<CodeTabs storage="token-rs" flags="r">

```rust !! title="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(),
    );

    // !collapse(1:28) collapsed
    // Setup: create a WSOL ATA before wrapping and syncing SOL.
    let fee_payer = Keypair::new();

    let airdrop_signature = client
        .request_airdrop(&fee_payer.pubkey(), 2_000_000_000)
        .await?;
    loop {
        let confirmed = client.confirm_transaction(&airdrop_signature).await?;
        if confirmed {
            break;
        }
    }

    let latest_blockhash = client.get_latest_blockhash().await?;
    let setup_transaction = Transaction::new_signed_with_payer(
        &[create_associated_token_account(
            &fee_payer.pubkey(),
            &fee_payer.pubkey(),
            &NATIVE_MINT_ID,
            &token_program_id(),
        )],
        Some(&fee_payer.pubkey()),
        &[&fee_payer],
        latest_blockhash,
    );
    client
        .send_and_confirm_transaction(&setup_transaction)
        .await?;

    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(
        &[
            // !mark(1:9)
            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(())
}
```

</CodeTabs>

### Python

<CodeTabs flags="r">

```py !! title="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:
        # !collapse(1:16) collapsed
        # Setup: create the wrapped SOL token account before updating its token balance.
        fee_payer = Keypair()
        airdrop_signature = (await rpc.request_airdrop(fee_payer.pubkey(), 1_000_000_000)).value
        await rpc.confirm_transaction(airdrop_signature)
        wrapped_sol_account = get_associated_token_address(fee_payer.pubkey(), WRAPPED_SOL_MINT)
        setup_instructions = [
            create_associated_token_account(fee_payer.pubkey(), fee_payer.pubkey(), WRAPPED_SOL_MINT, TOKEN_PROGRAM_ID),
        ]
        setup_blockhash = await rpc.get_latest_blockhash()
        setup_transaction = Transaction(
            [fee_payer],
            Message(setup_instructions, fee_payer.pubkey()),
            setup_blockhash.value.blockhash,
        )
        await rpc.send_transaction(setup_transaction)
        token = AsyncToken(rpc, WRAPPED_SOL_MINT, TOKEN_PROGRAM_ID, fee_payer)

        # !mark(1:15)
        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())
```

</CodeTabs>
