위임자 승인은 무엇을 하나요?
위임자를 승인하면 다른 주소가 token account 소유자를 대신하여 token account에서 제한된 양의 토큰을 전송하거나 소각할 수 있습니다.
token account는 한 번에 하나의 현재 위임자와 하나의 위임 수량을 저장합니다. 새로운 위임자를 승인하면 계정의 이전 위임자와 허용량이 교체됩니다.
위임자를 승인하는 방법
위임자 승인은 Token Program의 Approve 또는 ApproveChecked
인스트럭션을 사용합니다.
아래 예제는 ApproveChecked 를 사용하며, 이는 호출자가 민트와 소수점
자릿수를 제공하도록 요구하여 승인을 처리하기 전에 인스트럭션이 예상되는 민트와
토큰 정밀도를 확인할 수 있도록 합니다.
token account 소유자가 승인에 서명합니다.
소스 참조
| 항목 | 설명 | Token Program | Token Extensions Program |
|---|---|---|---|
Account | token account 상태는 소유자, 위임자 및 위임 수량을 저장합니다. | 소스 | 소스 |
Approve | 호출자가 민트나 소수점 자릿수를 제공할 필요 없이 token account의 위임자와 허용량을 기록하는 위임 승인 인스트럭션입니다. | 소스 | 소스 |
ApproveChecked | 호출자가 민트와 소수점 자릿수를 제공하도록 요구하고 위임자와 허용량을 기록하기 전에 해당 값을 확인하는 위임 승인 인스트럭션입니다. | 소스 | 소스 |
process_approve | 위임 승인을 위한 공유 프로세서 로직입니다. | 소스 | 소스 |
Typescript
아래의 Kit 예제는 @solana/kit를 사용한 권장 접근 방식을 보여줍니다.
@solana/web3.js를 사용한 레거시 예제는 참고용으로 포함되어 있습니다.
Kit
import { generateKeyPairSigner } from "@solana/kit";import { createLocalClient } from "@solana/kit-client-rpc";import {findAssociatedTokenPda,tokenProgram,TOKEN_PROGRAM_ADDRESS} from "@solana-program/token";const client = await createLocalClient().use(tokenProgram());const mint = await generateKeyPairSigner();const delegate = await generateKeyPairSigner();const [tokenAccount] = await findAssociatedTokenPda({mint: mint.address,owner: client.payer.address,tokenProgram: TOKEN_PROGRAM_ADDRESS});const result = await client.token.instructions.approveChecked({source: tokenAccount, // Token account whose delegate approval changes.mint: mint.address, // Mint for the token the delegate may spend.delegate: delegate.address, // Delegate allowed to spend from the token account.owner: client.payer, // Owner approving this delegate change.amount: 25n, // Token amount in base units.decimals: 2 // Decimals defined on the mint account.}).sendTransaction();const tokenAccountData = await client.token.accounts.token.fetch(tokenAccount);console.log("Mint Address:", mint.address);console.log("\nToken Account Address:", tokenAccount);console.log("Token Account:", tokenAccountData.data);console.log("\nDelegate Address:", delegate.address);console.log("\nTransaction Signature:", result.context.signature);
Console
Click to execute the code.
Web3.js
import { Connection, Keypair, LAMPORTS_PER_SOL } from "@solana/web3.js";import {createAssociatedTokenAccount,approveChecked,createMint,getAccount,mintToChecked,TOKEN_PROGRAM_ID} from "@solana/spl-token";const result = await approveChecked(connection, // Connection to the local validator.feePayer, // Account paying transaction fees.mintPubkey, // Mint for the token the delegate may spend.associatedTokenAccount, // Token account whose delegate approval changes.delegate.publicKey, // Delegate allowed to spend from the token account.feePayer, // Owner approving this delegate change.25, // Token amount in base units.2, // Decimals defined on the mint account.[], // Additional multisig signers.{commitment: "confirmed" // Confirmation options for the transaction.},TOKEN_PROGRAM_ID // Token program to invoke.);const tokenAccountData = await getAccount(connection,associatedTokenAccount,"confirmed",TOKEN_PROGRAM_ID);console.log("Mint Address:", mintPubkey.toBase58());console.log("\nAssociated Token Account Address:",associatedTokenAccount.toBase58());console.log("Associated Token Account:", tokenAccountData);console.log("\nDelegate Address:", delegate.publicKey.toBase58());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::create_account;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::{approve_checked, initialize_mint, mint_to_checked},state::{Account, Mint},};#[tokio::main]async fn main() -> Result<()> {let client = RpcClient::new_with_commitment(String::from("http://localhost:8899"),CommitmentConfig::confirmed(),);let delegate = Keypair::new();let approve_amount = 25;let transaction = Transaction::new_signed_with_payer(&[approve_checked(&token_program_id(), // Token program to invoke.&associated_token_address, // Token account whose delegate approval changes.&mint.pubkey(), // Mint for the token the delegate may spend.&delegate.pubkey(), // Delegate allowed to spend from the token account.&fee_payer.pubkey(), // Owner approving this delegate change.&[], // Additional multisig signers.approve_amount, // Token amount in base units.decimals, // Decimals defined on the mint account.)?,],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!("Mint Address: {}", mint.pubkey());println!("\nAssociated Token Account Address: {}",associated_token_address);println!("Associated Token Account: {:#?}", token_data);println!("\nDelegate Address: {}", delegate.pubkey());println!("\nTransaction Signature: {}", transaction_signature);Ok(())}
Console
Click to execute the code.
Python
Python
#!/usr/bin/env python3import asyncioimport jsonfrom solana.rpc.async_api import AsyncClientfrom solders.keypair import Keypairfrom solders.message import Messagefrom solders.pubkey import Pubkeyfrom solders.system_program import create_account, CreateAccountParamsfrom solders.transaction import Transactionfrom spl.token.async_client import AsyncTokenfrom spl.token.instructions import (approve_checked,ApproveCheckedParams,create_associated_token_account,get_associated_token_address,initialize_mint,InitializeMintParams,mint_to_checked,MintToCheckedParams,)from spl.token.constants import MINT_LEN, TOKEN_PROGRAM_IDDECIMALS = 2AMOUNT_TO_MINT = 100AMOUNT_TO_APPROVE = 25async def main():rpc = AsyncClient("http://localhost:8899")delegate = Keypair()async with rpc:approve_delegate_instruction = approve_checked(ApproveCheckedParams(program_id=TOKEN_PROGRAM_ID, # Token program to invoke.source=token_account_address, # Token account whose delegate approval changes.mint=mint.pubkey(), # Mint for the token the delegate may spend.delegate=delegate.pubkey(), # Account allowed to spend from the token account.owner=fee_payer.pubkey(), # Account that owns the token account.amount=AMOUNT_TO_APPROVE, # Token amount in base units.decimals=DECIMALS, # Decimals defined on the mint account.))latest_blockhash = await rpc.get_latest_blockhash()transaction = Transaction([fee_payer],Message([approve_delegate_instruction], fee_payer.pubkey()),latest_blockhash.value.blockhash,)result = await rpc.send_transaction(transaction)token_account_info = await token.get_account_info(token_account_address)token_account = {key: str(value) if isinstance(value, Pubkey) else valuefor key, value in token_account_info._asdict().items()}print("Mint Address:", mint.pubkey())print("\nToken Account Address:", token_account_address)print("Token Account:")print(json.dumps(token_account, indent=2))print("\nDelegate Address:", delegate.pubkey())print("\nTransaction Signature:", result.value)if __name__ == "__main__":asyncio.run(main())
Console
Click to execute the code.
Is this page helpful?