使用 python 进行 Solana SPL 代币转移

Solana SPL token transfer with python

所以在阅读了几篇文章之后,我还没有理解如何创建交易并在 Solana 区块链上发送自定义 SPL 代币。 我在下面附上了我的代码。
我真的不明白交易的每一部分应该是什么。
所以我认为 owner 是发送和支付交易的 account/wallet。我假设 dest 是我希望将令牌发送到的地方。
This 是我希望发送的令牌(在 devnet 上),但我似乎无法发送。

from spl.token.constants import TOKEN_PROGRAM_ID
from spl.token.instructions import transfer_checked, TransferCheckedParams

from solana.rpc.commitment import Confirmed
from solana.rpc.api import Client
from solana.rpc.types import TxOpts
from solana.keypair import Keypair
from solana.publickey import PublicKey
from solana.transaction import Transaction

import os
from dotenv import load_dotenv

class TransferService:
    def __init__(self, client: Client, service: SolanaService, token) -> None:
        self.client = client
        self.service = service
        self.keypair = self.service.get_keypair(token)

    def make_transaction(self, source, mint, dest, owner, amount=1, decimals=0) -> Transaction:
        transaction = Transaction()
        transaction.add(transfer_checked(
            TransferCheckedParams(
                program_id=TOKEN_PROGRAM_ID,
                mint=PublicKey(mint),
                source=PublicKey(source),
                dest=PublicKey(dest),
                owner=owner,
                amount=amount,
                decimals=decimals,
                signers=[]
        )))
        return transaction

    def send_transaction(self, transaction) -> None:
        self.client.send_transaction(
            transaction,
            self.keypair,
            opts=TxOpts(skip_confirmation=False, preflight_commitment=Confirmed)
        )

load_dotenv()

if __name__ == "__main__":
    token = os.getenv('TOKEN')
    client = Client('https://api.devnet.solana.com')
    service = SolanaService(client)
    token = os.getenv('KEYPAIR')
    transfer = TransferService(client, service, token)
    a = client.get_account_info(transfer.keypair.public_key)
    transaction = transfer.make_transaction(
        source='CtURxXpzn9aredXse2KNtyDMeVW627tL3p7DCucdv8bc',
        mint='DCzbhHu3YGnc8Vhez4YEMznQ38ad6WYGVYqeB4Wn3mie',
        dest='sPkypr2LBtF5Go87zYSn5fBtWxCDEcobWeQQxXHpxJR',
        owner=transfer.keypair.public_key,
        amount=1,
        decimals=9

    )
    transfer.send_transaction(transaction)

目的地 sPkypr2LBtF5Go87zYSn5fBtWxCDEcobWeQQxXHpxJR 不正确。

当您发送SPL代币时,sourcedest必须是代币账户地址,在这种情况下,sPkypr2LBtF5Go87zYSn5fBtWxCDEcobWeQQxXHpxJR是一个钱包,所以您需要为此钱包创建收款人帐户。

首选标准是使用关联的令牌帐户,使用 solana-py 客户端的 SPL 部分中的 create_associated_token_account 创建:https://github.com/michaelhly/solana-py/blob/2c45353cb510bfeb7259fa19dacbaefe6b9ae3d1/src/spl/token/client.py#L173

供参考,最重要的部分是创建创建关联代币账户的指令:

def create_associated_token_account(payer: PublicKey, owner: PublicKey, mint: PublicKey) -> TransactionInstruction:
    associated_token_address = PublicKey.find_program_address(
        seeds=[bytes(owner), bytes(TOKEN_PROGRAM_ID), bytes(mint)], program_id=ASSOCIATED_TOKEN_PROGRAM_ID
    )
    return TransactionInstruction(
        keys=[
            AccountMeta(pubkey=payer, is_signer=True, is_writable=True),
            AccountMeta(pubkey=associated_token_address, is_signer=False, is_writable=True),
            AccountMeta(pubkey=owner, is_signer=False, is_writable=False),
            AccountMeta(pubkey=mint, is_signer=False, is_writable=False),
            AccountMeta(pubkey=SYS_PROGRAM_ID, is_signer=False, is_writable=False),
            AccountMeta(pubkey=TOKEN_PROGRAM_ID, is_signer=False, is_writable=False),
            AccountMeta(pubkey=SYSVAR_RENT_PUBKEY, is_signer=False, is_writable=False),
        ],
        program_id=ASSOCIATED_TOKEN_PROGRAM_ID,
    )

有关关联令牌帐户的更多背景信息,请访问 https://spl.solana.com/associated-token-account