Tokens com rendimento de juros

O Que É um Mint com Juros?

A extensão de mint InterestBearingConfig do Token Extensions Program permite que um mint armazene uma taxa de juros anualizada diretamente onchain.

Tokens com juros não adicionam mais tokens às contas de tokens ao longo do tempo. A quantidade de tokens armazenada em cada token account permanece a mesma até que uma instrução do programa de tokens a modifique, como cunhagem, transferência ou queima.

À medida que o tempo passa, o valor de UI calculado com juros pode aumentar mesmo que a quantidade de tokens e o fornecimento de tokens permaneçam os mesmos.

Como as Mudanças Históricas de Taxa São Calculadas

  • InterestBearingConfig armazena initialization_timestamp, pre_update_average_rate, last_update_timestamp e current_rate.
  • amount_to_ui_amount calcula o valor de UI em duas etapas: primeiro calcula os juros desde a inicialização até last_update_timestamp usando pre_update_average_rate, depois calcula os juros de last_update_timestamp até o timestamp atual usando current_rate.
  • Quando UpdateRate é executada, process_update_rate chama time_weighted_average_rate e atualiza pre_update_average_rate para uma nova média histórica ponderada pelo tempo, depois registra um novo last_update_timestamp e current_rate.
  • Após mudanças de taxa ao longo do tempo, as mudanças anteriores são representadas por pre_update_average_rate, enquanto o período de last_update_timestamp até o tempo atual é calculado com current_rate.

Como Criar e Usar Tokens com Juros

Para criar e usar tokens com juros:

  1. Calcule o tamanho da mint account e o rent necessário para o mint e a extensão InterestBearingConfig.
  2. Crie a mint account com CreateAccount, inicialize InterestBearingConfig e inicialize o mint com InitializeMint.
  3. Cunhe tokens normalmente.
  4. Use UpdateRate para alterar a taxa atual do mint ao longo do tempo.
  5. Converta quantidades de tokens em um valor de UI com juros usando AmountToUiAmount ou métodos auxiliares que buscam a mint account e o sysvar do relógio, depois calculam o valor de UI sem enviar uma transação.

Conversão de Valor de Interface Offchain e Onchain

O caminho auxiliar offchain busca a mint account e o sysvar de relógio, depois calcula o valor de interface localmente sem enviar uma transação. O caminho onchain usa AmountToUiAmount, que é executado no Token Program e retorna o valor de interface nos dados de retorno da transação. AmountToUiAmount pode ser enviado em uma transação ou simulado.

Calcular o tamanho da conta

Calcule o tamanho da mint account para a mint base mais a extensão InterestBearingConfig. Este é o tamanho usado em CreateAccount.

Calcular rent

Calcule o rent usando o tamanho necessário para a mint mais a extensão InterestBearingConfig.

Criar a mint account

Crie a mint account com o espaço e lamports calculados.

Inicializar InterestBearingConfig

Inicialize a extensão InterestBearingConfig na mint.

Inicializar a mint

Inicialize a mint com InitializeMint na mesma transação.

Criar uma token account e cunhar tokens

Crie uma token account para a mint e, em seguida, cunhe tokens para essa token account.

Calcular o valor da UI com o auxiliar offchain

Busque a mint account e o sysvar do relógio, depois calcule o valor da UI sem enviar uma transação.

Calcular o tamanho da conta

Calcule o tamanho da mint account para a mint base mais a extensão InterestBearingConfig. Este é o tamanho usado em CreateAccount.

Calcular rent

Calcule o rent usando o tamanho necessário para a mint mais a extensão InterestBearingConfig.

Criar a mint account

Crie a mint account com o espaço e lamports calculados.

Inicializar InterestBearingConfig

Inicialize a extensão InterestBearingConfig na mint.

Inicializar a mint

Inicialize a mint com InitializeMint na mesma transação.

Criar uma token account e cunhar tokens

Crie uma token account para a mint e, em seguida, cunhe tokens para essa token account.

Calcular o valor da UI com o auxiliar offchain

Busque a mint account e o sysvar do relógio, depois calcule o valor da UI sem enviar uma transação.

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

Ordem das Instruções

InterestBearingMintInstruction::Initialize deve vir antes de InitializeMint. CreateAccount, InterestBearingMintInstruction::Initialize e InitializeMint devem ser incluídos na mesma transação.

Referência da Fonte

ItemDescriçãoFonte
InterestBearingConfigExtensão de mint que armazena a autoridade de taxa de juros, timestamps e taxas atuais e históricas.Fonte
InterestBearingMintInstruction::InitializeInstrução que inicializa a configuração de juros antes de InitializeMint.Fonte
InterestBearingMintInstruction::UpdateRateInstrução que altera a taxa de juros atual do mint.Fonte
AmountToUiAmountInstrução que retorna a string de valor da UI atual para um valor de token usando a configuração ativa do mint.Fonte
InterestBearingConfig::amount_to_ui_amountAuxiliar que converte um valor de token em um valor de UI com juros para um timestamp.Fonte
process_initializeLógica de processamento que inicializa InterestBearingConfig e registra os timestamps e taxa iniciais.Fonte
process_update_rateLógica de processamento que atualiza a taxa atual, recalcula a taxa média ponderada pelo tempo e registra o timestamp da atualização.Fonte
process_amount_to_ui_amountLógica de processamento que retorna a string de valor da UI usando a configuração ativa de juros do mint.Fonte

Typescript

O exemplo Kit abaixo usa as instruções geradas diretamente. Exemplos legados usando @solana/web3.js e @solana/spl-token estão incluídos para referência.

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?

Índice

Editar Página

Gerenciado por

© 2026 Fundação Solana.
Todos os direitos reservados.
Conecte-se
  • Blog