Zinstragende Token

Was ist eine zinstragende Mint?

Die InterestBearingConfig-Mint-Erweiterung des Token Extensions Program ermöglicht es einer Mint, einen annualisierten Zinssatz direkt onchain zu speichern.

Zinstragende Token fügen nicht im Laufe der Zeit mehr Token zu token account hinzu. Der in jedem token account gespeicherte Token-Betrag bleibt gleich, bis eine Anweisungen des Token-Programms ihn ändert, wie z. B. beim Prägen, Übertragen oder Verbrennen.

Mit der Zeit kann der berechnete UI-Betrag mit Zinsen steigen, auch wenn der Token-Betrag und die Token-Versorgung gleich bleiben.

Wie historische Zinsänderungen berechnet werden

  • InterestBearingConfig speichert initialization_timestamp, pre_update_average_rate, last_update_timestamp und current_rate.
  • amount_to_ui_amount berechnet den UI-Betrag in zwei Schritten: Zunächst werden Zinsen von der Initialisierung bis last_update_timestamp unter Verwendung von pre_update_average_rate berechnet, dann werden Zinsen von last_update_timestamp bis zum aktuellen Zeitstempel unter Verwendung von current_rate berechnet.
  • Wenn UpdateRate ausgeführt wird, ruft process_update_rate time_weighted_average_rate auf und aktualisiert pre_update_average_rate auf einen neuen zeitgewichteten historischen Durchschnitt, dann wird ein neuer last_update_timestamp und current_rate gespeichert.
  • Nach Zinsänderungen im Laufe der Zeit werden die früheren Änderungen durch pre_update_average_rate dargestellt, während der Zeitraum von last_update_timestamp bis zur aktuellen Zeit mit current_rate berechnet wird.

So erstellen und verwenden Sie zinstragende Token

Um zinstragende Token zu erstellen und zu verwenden:

  1. Berechnen Sie die Größe des mint account und die benötigte rent für die Mint und die InterestBearingConfig-Erweiterung.
  2. Erstellen Sie das mint account mit CreateAccount, initialisieren Sie InterestBearingConfig und initialisieren Sie die Mint mit InitializeMint.
  3. Prägen Sie Token wie üblich.
  4. Verwenden Sie UpdateRate, um den aktuellen Zinssatz der Mint im Laufe der Zeit zu ändern.
  5. Konvertieren Sie Token-Beträge in einen UI-Betrag mit Zinsen mit AmountToUiAmount oder Hilfsmethoden, die das mint account und den Clock-Sysvar abrufen und dann den UI-Betrag berechnen, ohne eine Transaktion zu senden.

Offchain- und Onchain-Konvertierung von UI-Beträgen

Der Offchain-Hilfspfad ruft das Mint-Konten und die Clock-Sysvar ab und berechnet dann den UI-Betrag lokal, ohne eine Transaktion zu senden. Der Onchain- Pfad verwendet AmountToUiAmount, das im Token Program ausgeführt wird und den UI-Betrag in den Transaktionsrückgabedaten zurückgibt. AmountToUiAmount kann in einer Transaktion gesendet oder simuliert werden.

Kontengröße berechnen

Berechnen Sie die Mint-Kontengröße für das Basis-Mint plus die InterestBearingConfig-Erweiterung. Dies ist die Größe, die in CreateAccount verwendet wird.

Miete berechnen

Berechnen Sie die Miete unter Verwendung der für das Mint plus die InterestBearingConfig-Erweiterung benötigten Größe.

Das Mint-Konten erstellen

Erstellen Sie das Mint-Konten mit dem berechneten Speicherplatz und den Lamports.

InterestBearingConfig initialisieren

Initialisieren Sie die InterestBearingConfig-Erweiterung auf dem Mint.

Das Mint initialisieren

Initialisieren Sie das Mint mit InitializeMint in derselben Transaktion.

Ein Token-Konten erstellen und Tokens prägen

Erstellen Sie ein Token-Konten für das Mint und prägen Sie dann Tokens auf dieses Token-Konten.

Berechnen Sie den UI-Betrag mit dem Offchain-Helfer

Rufen Sie das Mint-Konto und den Clock-Sysvar ab und berechnen Sie dann den UI-Betrag, ohne eine Transaktion zu senden.

Kontengröße berechnen

Berechnen Sie die Mint-Kontengröße für das Basis-Mint plus die InterestBearingConfig-Erweiterung. Dies ist die Größe, die in CreateAccount verwendet wird.

Miete berechnen

Berechnen Sie die Miete unter Verwendung der für das Mint plus die InterestBearingConfig-Erweiterung benötigten Größe.

Das Mint-Konten erstellen

Erstellen Sie das Mint-Konten mit dem berechneten Speicherplatz und den Lamports.

InterestBearingConfig initialisieren

Initialisieren Sie die InterestBearingConfig-Erweiterung auf dem Mint.

Das Mint initialisieren

Initialisieren Sie das Mint mit InitializeMint in derselben Transaktion.

Ein Token-Konten erstellen und Tokens prägen

Erstellen Sie ein Token-Konten für das Mint und prägen Sie dann Tokens auf dieses Token-Konten.

Berechnen Sie den UI-Betrag mit dem Offchain-Helfer

Rufen Sie das Mint-Konto und den Clock-Sysvar ab und berechnen Sie dann den UI-Betrag, ohne eine Transaktion zu senden.

Example
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 mint = await generateKeyPairSigner();
const interestBearingExtension = extension("InterestBearingConfig", {
rateAuthority: client.payer.address,
initializationTimestamp: BigInt(Math.floor(Date.now() / 1000)),
lastUpdateTimestamp: BigInt(Math.floor(Date.now() / 1000)),
preUpdateAverageRate: 30000,
currentRate: 30000
});
const mintSpace = BigInt(getMintSize([interestBearingExtension]));

Anweisungsreihenfolge

InterestBearingMintInstruction::Initialize muss vor InitializeMint erfolgen. CreateAccount, InterestBearingMintInstruction::Initialize und InitializeMint müssen in derselben Transaktion enthalten sein.

Quellenreferenz

ElementBeschreibungQuelle
InterestBearingConfigMint-Erweiterung, die die Zinssatzbehörde, Zeitstempel sowie aktuelle und historische Zinssätze speichert.Quelle
InterestBearingMintInstruction::InitializeAnweisung, die die zinstragende Konfiguration vor InitializeMint initialisiert.Quelle
InterestBearingMintInstruction::UpdateRateAnweisung, die den aktuellen Zinssatz des Mints ändert.Quelle
AmountToUiAmountAnweisung, die den aktuellen UI-Betrag als Zeichenkette für einen Token-Betrag unter Verwendung der aktiven Konfiguration des Mints zurückgibt.Quelle
InterestBearingConfig::amount_to_ui_amountHelfer, der einen Token-Betrag in einen UI-Betrag mit Zinsen für einen Zeitstempel umwandelt.Quelle
process_initializeProzessorlogik, die InterestBearingConfig initialisiert und die anfänglichen Zeitstempel und Zinssätze aufzeichnet.Quelle
process_update_rateProzessorlogik, die den aktuellen Zinssatz aktualisiert, den zeitgewichteten Durchschnittszinssatz neu berechnet und den Aktualisierungszeitstempel aufzeichnet.Quelle
process_amount_to_ui_amountProzessorlogik, die die UI-Betragszeichenkette unter Verwendung der aktiven zinstragenden Konfiguration des Mints zurückgibt.Quelle

Typescript

Das nachstehende Beispiel Kit verwendet die generierten Anweisungen direkt. Legacy-Beispiele mit @solana/web3.js und @solana/spl-token sind als Referenz enthalten.

Kit

Instructions
import {
lamports,
createClient,
appendTransactionMessageInstructions,
createTransactionMessage,
generateKeyPairSigner,
getBase64EncodedWireTransaction,
pipe,
setTransactionMessageFeePayerSigner,
setTransactionMessageLifetimeUsingBlockhash,
signTransactionMessageWithSigners,
unwrapOption
} from "@solana/kit";
import { solanaRpc, rpcAirdrop } from "@solana/kit-plugin-rpc";
import { generatedPayer, airdropPayer } from "@solana/kit-plugin-signer";
import { getCreateAccountInstruction } from "@solana-program/system";
import {
amountToUiAmountForMintWithoutSimulation,
extension,
fetchMint,
findAssociatedTokenPda,
getAmountToUiAmountInstruction,
getCreateAssociatedTokenInstructionAsync,
getInitializeInterestBearingMintInstruction,
getInitializeMintInstruction,
getMintSize,
getMintToCheckedInstruction,
getUpdateRateInterestBearingMintInstruction,
isExtension,
TOKEN_2022_PROGRAM_ADDRESS
} from "@solana-program/token-2022";
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 mint = await generateKeyPairSigner();
const recipient = await generateKeyPairSigner();
const tokenAmount = 1_000_000_000_000n;
const interestBearingExtension = extension("InterestBearingConfig", {
rateAuthority: client.payer.address,
initializationTimestamp: BigInt(Math.floor(Date.now() / 1000)),
lastUpdateTimestamp: BigInt(Math.floor(Date.now() / 1000)),
preUpdateAverageRate: 30000,
currentRate: 30000
});
const mintSpace = BigInt(getMintSize([interestBearingExtension]));
const mintRent = await client.rpc
.getMinimumBalanceForRentExemption(mintSpace)
.send();
const [tokenAccount] = await findAssociatedTokenPda({
mint: mint.address,
owner: recipient.address,
tokenProgram: TOKEN_2022_PROGRAM_ADDRESS
});
await client.sendTransaction([
getCreateAccountInstruction({
payer: client.payer, // Account funding the new mint account.
newAccount: mint, // New mint account to create.
lamports: mintRent, // Lamports funding the mint account rent.
space: mintSpace, // Account size in bytes for the mint plus InterestBearingConfig.
programAddress: TOKEN_2022_PROGRAM_ADDRESS // Program that owns the mint account.
}),
getInitializeInterestBearingMintInstruction({
mint: mint.address, // Mint account that stores the InterestBearingConfig extension.
rateAuthority: client.payer.address, // Authority allowed to update the interest rate later.
rate: 30000 // Interest rate in basis points.
}),
getInitializeMintInstruction({
mint: mint.address, // Mint account to initialize.
decimals: 0, // Number of decimals for the token.
mintAuthority: client.payer.address, // Authority allowed to mint new tokens.
freezeAuthority: client.payer.address // Authority allowed to freeze token accounts.
})
]);
await client.sendTransaction([
await getCreateAssociatedTokenInstructionAsync({
payer: client.payer, // Account funding the associated token account creation.
mint: mint.address, // Mint for the associated token account.
owner: recipient.address // Owner of the token account.
}),
getMintToCheckedInstruction({
mint: mint.address, // Mint account that issues the tokens.
token: tokenAccount, // Token account receiving the newly minted tokens.
mintAuthority: client.payer, // Signer authorized to mint new tokens.
amount: tokenAmount, // Token amount in base units.
decimals: 0 // Decimals defined on the mint.
})
]);
await new Promise((resolve) => setTimeout(resolve, 2_000));
const calculatedUiAmount = await amountToUiAmountForMintWithoutSimulation(
client.rpc,
mint.address,
tokenAmount
);
const amountToUiInstruction = getAmountToUiAmountInstruction({
mint: mint.address, // Mint whose UI amount conversion is being simulated.
amount: tokenAmount // Token amount in base units.
});
const { value: latestBlockhash } = await client.rpc.getLatestBlockhash().send();
const amountToUiMessage = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayerSigner(client.payer, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(latestBlockhash, tx),
(tx) => appendTransactionMessageInstructions([amountToUiInstruction], tx)
);
const signedAmountToUiMessage =
await signTransactionMessageWithSigners(amountToUiMessage);
const simulation = await client.rpc
.simulateTransaction(
getBase64EncodedWireTransaction(signedAmountToUiMessage),
{
encoding: "base64"
}
)
.send();
const simulatedUiAmount = Buffer.from(
simulation.value.returnData?.data?.[0] ?? "",
"base64"
).toString("utf8");
const updateRateInstruction = getUpdateRateInterestBearingMintInstruction({
mint: mint.address, // Mint account that stores the InterestBearingConfig extension.
rateAuthority: client.payer, // Signer authorized to update the interest rate.
rate: 15000 // New interest rate in basis points.
});
await client.sendTransaction([updateRateInstruction]);
const mintAccount = await fetchMint(client.rpc, mint.address);
const interestBearingConfig = (
unwrapOption(mintAccount.data.extensions) ?? []
).find((item) => isExtension("InterestBearingConfig", item));
console.log("Mint Address:", mint.address);
console.log("Token Account:", tokenAccount);
console.log("Calculated UI Amount:", calculatedUiAmount);
console.log("Simulated UI Amount:", simulatedUiAmount);
console.log("InterestBearingConfig:", interestBearingConfig);
Console
Click to execute the code.

Web3.js

Instructions
import {
Connection,
Keypair,
sendAndConfirmTransaction,
SystemProgram,
Transaction,
LAMPORTS_PER_SOL
} from "@solana/web3.js";
import {
ASSOCIATED_TOKEN_PROGRAM_ID,
amountToUiAmountForMintWithoutSimulation,
createAmountToUiAmountInstruction,
createAssociatedTokenAccountInstruction,
createInitializeMintInstruction,
createInitializeInterestBearingMintInstruction,
createMintToCheckedInstruction,
createUpdateRateInterestBearingMintInstruction,
ExtensionType,
getAssociatedTokenAddressSync,
getInterestBearingMintConfigState,
getMint,
getMintLen,
TOKEN_2022_PROGRAM_ID
} from "@solana/spl-token";
const connection = new Connection("http://localhost:8899", "confirmed");
const latestBlockhash = await connection.getLatestBlockhash();
const feePayer = Keypair.generate();
const recipient = Keypair.generate();
const tokenAmount = 1_000_000_000_000n;
const airdropSignature = await connection.requestAirdrop(
feePayer.publicKey,
5 * LAMPORTS_PER_SOL
);
await connection.confirmTransaction({
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight,
signature: airdropSignature
});
const extensions = [ExtensionType.InterestBearingConfig];
const mint = Keypair.generate();
const mintLength = getMintLen(extensions);
const mintRent = await connection.getMinimumBalanceForRentExemption(mintLength);
const tokenAccount = getAssociatedTokenAddressSync(
mint.publicKey,
recipient.publicKey,
false,
TOKEN_2022_PROGRAM_ID,
ASSOCIATED_TOKEN_PROGRAM_ID
);
const createMintAccountInstruction = SystemProgram.createAccount({
fromPubkey: feePayer.publicKey, // Account funding the new mint account.
newAccountPubkey: mint.publicKey, // New mint account to create.
space: mintLength, // Account size in bytes for the mint plus InterestBearingConfig.
lamports: mintRent, // Lamports funding the mint account rent.
programId: TOKEN_2022_PROGRAM_ID // Program that owns the mint account.
});
const initializeInterestBearingInstruction =
createInitializeInterestBearingMintInstruction(
mint.publicKey, // Mint account that stores the InterestBearingConfig extension.
feePayer.publicKey, // Authority allowed to update the interest rate later.
30000, // Interest rate in basis points.
TOKEN_2022_PROGRAM_ID // Token program that owns the mint.
);
const initializeMintInstruction = createInitializeMintInstruction(
mint.publicKey, // Mint account to initialize.
0, // Number of decimals for the token.
feePayer.publicKey, // Authority allowed to mint new tokens.
feePayer.publicKey, // Authority allowed to freeze token accounts.
TOKEN_2022_PROGRAM_ID // Program that owns the mint account.
);
const createTokenAccountInstruction = createAssociatedTokenAccountInstruction(
feePayer.publicKey, // Account funding the associated token account creation.
tokenAccount, // Associated token account address to create.
recipient.publicKey, // Owner of the token account.
mint.publicKey, // Mint for the associated token account.
TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
ASSOCIATED_TOKEN_PROGRAM_ID // Associated Token Program that creates the account.
);
const mintToTokenAccountInstruction = createMintToCheckedInstruction(
mint.publicKey, // Mint account that issues the tokens.
tokenAccount, // Token account receiving the newly minted tokens.
feePayer.publicKey, // Signer authorized to mint new tokens.
tokenAmount, // Token amount in base units.
0, // Decimals defined on the mint.
[], // Additional multisig signers.
TOKEN_2022_PROGRAM_ID // Token program that owns the mint and token account.
);
await sendAndConfirmTransaction(
connection,
new Transaction({
feePayer: feePayer.publicKey,
blockhash: latestBlockhash.blockhash,
lastValidBlockHeight: latestBlockhash.lastValidBlockHeight
}).add(
createMintAccountInstruction,
initializeInterestBearingInstruction,
initializeMintInstruction
),
[feePayer, mint]
);
await sendAndConfirmTransaction(
connection,
new Transaction().add(
createTokenAccountInstruction,
mintToTokenAccountInstruction
),
[feePayer]
);
await new Promise((resolve) => setTimeout(resolve, 2_000));
const calculatedUiAmount = await amountToUiAmountForMintWithoutSimulation(
connection,
mint.publicKey,
tokenAmount
);
const amountToUiInstruction = createAmountToUiAmountInstruction(
mint.publicKey, // Mint whose UI amount conversion is being simulated.
tokenAmount, // Token amount in base units.
TOKEN_2022_PROGRAM_ID // Token program that owns the mint.
);
const amountToUiSimulation = await connection.simulateTransaction(
new Transaction().add(amountToUiInstruction),
[feePayer],
false
);
const simulatedUiAmount = Buffer.from(
amountToUiSimulation.value.returnData?.data?.[0] ?? "",
"base64"
).toString("utf8");
const updateRateInstruction = createUpdateRateInterestBearingMintInstruction(
mint.publicKey, // Mint account that stores the InterestBearingConfig extension.
feePayer.publicKey, // Signer authorized to update the interest rate.
15000, // New interest rate in basis points.
[], // Additional multisig signers.
TOKEN_2022_PROGRAM_ID // Token program that owns the mint.
);
await sendAndConfirmTransaction(
connection,
new Transaction().add(updateRateInstruction),
[feePayer]
);
const mintAccount = await getMint(
connection,
mint.publicKey,
"confirmed",
TOKEN_2022_PROGRAM_ID
);
const interestBearingConfig = getInterestBearingMintConfigState(mintAccount);
console.log("Mint Address:", mint.publicKey.toBase58());
console.log("Token Account:", tokenAccount.toBase58());
console.log("Calculated UI Amount:", calculatedUiAmount);
console.log("Simulated UI Amount:", simulatedUiAmount);
console.log("InterestBearingConfig:", interestBearingConfig);
Console
Click to execute the code.

Rust

Rust
use anyhow::{anyhow, Result};
use base64::prelude::{Engine as _, BASE64_STANDARD};
use solana_client::nonblocking::rpc_client::RpcClient;
use solana_commitment_config::CommitmentConfig;
use solana_sdk::{
sysvar::clock::{self, Clock},
signature::{Keypair, Signer},
transaction::Transaction,
};
use solana_system_interface::instruction::create_account;
use spl_associated_token_account_interface::{
address::get_associated_token_address_with_program_id,
instruction::create_associated_token_account,
};
use spl_token_2022_interface::{
extension::{
interest_bearing_mint::{
instruction::{
initialize as initialize_interest_bearing_instruction, update_rate,
},
InterestBearingConfig,
},
BaseStateWithExtensions, ExtensionType, StateWithExtensions,
},
instruction::{amount_to_ui_amount, initialize_mint, mint_to_checked},
state::Mint,
ID as TOKEN_2022_PROGRAM_ID,
};
#[tokio::main]
async fn main() -> Result<()> {
let client = RpcClient::new_with_commitment(
String::from("http://localhost:8899"),
CommitmentConfig::confirmed(),
);
let fee_payer = Keypair::new();
let recipient = Keypair::new();
let token_amount = 1_000_000_000_000u64;
let airdrop_signature = client
.request_airdrop(&fee_payer.pubkey(), 5_000_000_000)
.await?;
loop {
let confirmed = client.confirm_transaction(&airdrop_signature).await?;
if confirmed {
break;
}
}
let mint = Keypair::new();
let mint_space =
ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::InterestBearingConfig])?;
let mint_rent = client
.get_minimum_balance_for_rent_exemption(mint_space)
.await?;
let create_mint_account_instruction = create_account(
&fee_payer.pubkey(), // Account funding the new mint account.
&mint.pubkey(), // New mint account to create.
mint_rent, // Lamports funding the mint account rent.
mint_space as u64, // Account size in bytes for the mint plus InterestBearingConfig.
&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.
);
let initialize_interest_bearing_instruction = initialize_interest_bearing_instruction(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.
&mint.pubkey(), // Mint account that stores the InterestBearingConfig extension.
Some(fee_payer.pubkey()), // Authority allowed to update the interest rate later.
30000, // Interest rate in basis points.
)?;
let initialize_mint_instruction = initialize_mint(
&TOKEN_2022_PROGRAM_ID, // Program that owns the mint account.
&mint.pubkey(), // Mint account to initialize.
&fee_payer.pubkey(), // Authority allowed to mint new tokens.
Some(&fee_payer.pubkey()), // Authority allowed to freeze token accounts.
0, // Number of decimals for the token.
)?;
let create_mint_transaction = Transaction::new_signed_with_payer(
&[
create_mint_account_instruction,
initialize_interest_bearing_instruction,
initialize_mint_instruction,
],
Some(&fee_payer.pubkey()),
&[&fee_payer, &mint],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&create_mint_transaction)
.await?;
let token_account = get_associated_token_address_with_program_id(
&recipient.pubkey(),
&mint.pubkey(),
&TOKEN_2022_PROGRAM_ID,
);
let create_token_account_instruction = create_associated_token_account(
&fee_payer.pubkey(), // Account funding the associated token account creation.
&recipient.pubkey(), // Owner of the token account.
&mint.pubkey(), // Mint for the associated token account.
&TOKEN_2022_PROGRAM_ID, // Token program that owns the token account.
);
let mint_to_token_account_instruction = mint_to_checked(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the mint and token account.
&mint.pubkey(), // Mint account that issues the tokens.
&token_account, // Token account receiving the newly minted tokens.
&fee_payer.pubkey(), // Signer authorized to mint new tokens.
&[], // Additional multisig signers.
token_amount, // Token amount in base units.
0, // Decimals defined on the mint.
)?;
let create_token_account_transaction = Transaction::new_signed_with_payer(
&[
create_token_account_instruction,
mint_to_token_account_instruction,
],
Some(&fee_payer.pubkey()),
&[&fee_payer],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&create_token_account_transaction)
.await?;
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
let mint_account = client.get_account(&mint.pubkey()).await?;
let mint_state = StateWithExtensions::<Mint>::unpack(&mint_account.data)?;
let interest_bearing_config = mint_state.get_extension::<InterestBearingConfig>()?;
let clock_account = client.get_account(&clock::ID).await?;
let clock: Clock = clock_account.deserialize_data()?;
let calculated_ui_amount = interest_bearing_config
.amount_to_ui_amount(token_amount, mint_state.base.decimals, clock.unix_timestamp)
.ok_or_else(|| anyhow!("Failed to calculate UI amount"))?;
let amount_to_ui_instruction = amount_to_ui_amount(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.
&mint.pubkey(), // Mint whose UI amount conversion is being simulated.
token_amount, // Token amount in base units.
)?;
let amount_to_ui_blockhash = client.get_latest_blockhash().await?;
let amount_to_ui_transaction = Transaction::new_signed_with_payer(
&[amount_to_ui_instruction],
Some(&fee_payer.pubkey()),
&[&fee_payer],
amount_to_ui_blockhash,
);
let amount_to_ui_result = client.simulate_transaction(&amount_to_ui_transaction).await?;
let simulated_ui_amount = String::from_utf8(
BASE64_STANDARD.decode(
amount_to_ui_result
.value
.return_data
.ok_or_else(|| anyhow!("Expected AmountToUiAmount return data"))?
.data
.0,
)?,
)?;
let update_rate_instruction = update_rate(
&TOKEN_2022_PROGRAM_ID, // Token program that owns the mint.
&mint.pubkey(), // Mint account that stores the InterestBearingConfig extension.
&fee_payer.pubkey(), // Signer authorized to update the interest rate.
&[], // Additional multisig signers.
15000, // New interest rate in basis points.
)?;
let update_rate_transaction = Transaction::new_signed_with_payer(
&[update_rate_instruction],
Some(&fee_payer.pubkey()),
&[&fee_payer],
client.get_latest_blockhash().await?,
);
client
.send_and_confirm_transaction(&update_rate_transaction)
.await?;
let updated_mint_account = client.get_account(&mint.pubkey()).await?;
let updated_mint_state = StateWithExtensions::<Mint>::unpack(&updated_mint_account.data)?;
let interest_bearing_config = updated_mint_state.get_extension::<InterestBearingConfig>()?;
println!("Mint Address: {}", mint.pubkey());
println!("Token Account: {}", token_account);
println!("Calculated UI Amount: {}", calculated_ui_amount);
println!("Simulated UI Amount: {}", simulated_ui_amount);
println!("InterestBearingConfig: {:#?}", interest_bearing_config);
Ok(())
}
Console
Click to execute the code.

Is this page helpful?

Inhaltsverzeichnis

Seite bearbeiten

Verwaltet von

© 2026 Solana Foundation.
Alle Rechte vorbehalten.
Verbinden Sie sich