tokencrawler/.venv/lib/python3.9/site-packages/spl/token/instructions.py
2022-03-17 22:16:30 +01:00

1147 lines
40 KiB
Python

"""SPL token instructions.""" # pylint: disable=too-many-lines
from enum import IntEnum
from typing import Any, List, NamedTuple, Optional, Union
from solana.publickey import PublicKey
from solana.system_program import SYS_PROGRAM_ID
from solana.sysvar import SYSVAR_RENT_PUBKEY
from solana.transaction import AccountMeta, TransactionInstruction
from solana.utils.validate import validate_instruction_keys, validate_instruction_type
from spl.token._layouts import INSTRUCTIONS_LAYOUT, InstructionType
from spl.token.constants import ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID
class AuthorityType(IntEnum):
"""Specifies the authority type for SetAuthority instructions."""
MINT_TOKENS = 0
""""Authority to mint new tokens."""
FREEZE_ACCOUNT = 1
"""Authority to freeze any account associated with the Mint."""
ACCOUNT_OWNER = 2
"""Owner of a given token account."""
CLOSE_ACCOUNT = 3
"""Authority to close a token account."""
# Instruction Params
class InitializeMintParams(NamedTuple):
"""Initialize token mint transaction params."""
decimals: int
"""Number of base 10 digits to the right of the decimal place."""
program_id: PublicKey
"""SPL Token program account."""
mint: PublicKey
"""Public key of the minter account."""
mint_authority: PublicKey
"""The authority/multisignature to mint tokens."""
freeze_authority: Optional[PublicKey] = None
"""The freeze authority/multisignature of the mint."""
class InitializeAccountParams(NamedTuple):
"""Initialize token account transaction params."""
program_id: PublicKey
"""SPL Token program account."""
account: PublicKey
"""Public key of the new account."""
mint: PublicKey
"""Public key of the minter account."""
owner: PublicKey
"""Owner of the new account."""
class InitializeMultisigParams(NamedTuple):
"""Initialize multisig token account transaction params."""
program_id: PublicKey
"""SPL Token program account."""
multisig: PublicKey
"""New multisig account address."""
m: int
"""The number of signers (M) required to validate this multisignature account."""
signers: List[PublicKey] = []
"""Addresses of multisig signers."""
class TransferParams(NamedTuple):
"""Transfer token transaction params."""
program_id: PublicKey
"""SPL Token program account."""
source: PublicKey
"""Source account."""
dest: PublicKey
"""Destination account."""
owner: PublicKey
"""Owner of the source account."""
amount: int
"""Number of tokens to transfer."""
signers: List[PublicKey] = []
"""Signing accounts if `owner` is a multiSig."""
class ApproveParams(NamedTuple):
"""Approve token transaction params."""
program_id: PublicKey
"""SPL Token program account."""
source: PublicKey
"""Source account."""
delegate: PublicKey
"""Delegate account authorized to perform a transfer of tokens from the source account."""
owner: PublicKey
"""Owner of the source account."""
amount: int
"""Maximum number of tokens the delegate may transfer."""
signers: List[PublicKey] = []
"""Signing accounts if `owner` is a multiSig."""
class RevokeParams(NamedTuple):
"""Revoke token transaction params."""
program_id: PublicKey
"""SPL Token program account."""
account: PublicKey
"""Source account for which transfer authority is being revoked."""
owner: PublicKey
"""Owner of the source account."""
signers: List[PublicKey] = []
"""Signing accounts if `owner` is a multiSig."""
class SetAuthorityParams(NamedTuple):
"""Set token authority transaction params."""
program_id: PublicKey
"""SPL Token program account."""
account: PublicKey
"""Public key of the token account."""
authority: AuthorityType
"""The type of authority to update."""
current_authority: PublicKey
"""Current authority of the specified type."""
signers: List[PublicKey] = []
"""Signing accounts if `current_authority` is a multiSig."""
new_authority: Optional[PublicKey] = None
"""New authority of the account."""
class MintToParams(NamedTuple):
"""Mint token transaction params."""
program_id: PublicKey
"""SPL Token program account."""
mint: PublicKey
"""Public key of the minter account."""
dest: PublicKey
"""Public key of the account to mint to."""
mint_authority: PublicKey
"""The mint authority."""
amount: int
"""Amount to mint."""
signers: List[PublicKey] = []
"""Signing accounts if `mint_authority` is a multiSig."""
class BurnParams(NamedTuple):
"""Burn token transaction params."""
program_id: PublicKey
"""SPL Token program account."""
account: PublicKey
"""Account to burn tokens from."""
mint: PublicKey
"""Public key of the minter account."""
owner: PublicKey
"""Owner of the account."""
amount: int
"""Amount to burn."""
signers: List[PublicKey] = []
"""Signing accounts if `owner` is a multiSig"""
class CloseAccountParams(NamedTuple):
"""Close token account transaction params."""
program_id: PublicKey
"""SPL Token program account."""
account: PublicKey
"""Address of account to close."""
dest: PublicKey
"""Address of account to receive the remaining balance of the closed account."""
owner: PublicKey
"""Owner of the account."""
signers: List[PublicKey] = []
"""Signing accounts if `owner` is a multiSig"""
class FreezeAccountParams(NamedTuple):
"""Freeze token account transaction params."""
program_id: PublicKey
"""SPL Token program account."""
account: PublicKey
"""Account to freeze."""
mint: PublicKey
"""Public key of the minter account."""
authority: PublicKey
"""Mint freeze authority"""
multi_signers: List[PublicKey] = []
"""Signing accounts if `authority` is a multiSig"""
class ThawAccountParams(NamedTuple):
"""Thaw token account transaction params."""
program_id: PublicKey
"""SPL Token program account."""
account: PublicKey
"""Account to thaw."""
mint: PublicKey
"""Public key of the minter account."""
authority: PublicKey
"""Mint freeze authority"""
multi_signers: List[PublicKey] = []
"""Signing accounts if `authority` is a multiSig"""
class TransferCheckedParams(NamedTuple):
"""TransferChecked token transaction params."""
program_id: PublicKey
"""SPL Token program account."""
source: PublicKey
"""Source account."""
mint: PublicKey
"""Public key of the minter account."""
dest: PublicKey
"""Destination account."""
owner: PublicKey
"""Owner of the source account."""
amount: int
"""Number of tokens to transfer."""
decimals: int
"""Amount decimals."""
signers: List[PublicKey] = []
"""Signing accounts if `owner` is a multiSig."""
class ApproveCheckedParams(NamedTuple):
"""ApproveChecked token transaction params."""
program_id: PublicKey
"""SPL Token program account."""
source: PublicKey
"""Source account."""
mint: PublicKey
"""Public key of the minter account."""
delegate: PublicKey
"""Delegate account authorized to perform a transfer of tokens from the source account."""
owner: PublicKey
"""Owner of the source account."""
amount: int
"""Maximum number of tokens the delegate may transfer."""
decimals: int
"""Amount decimals."""
signers: List[PublicKey] = []
"""Signing accounts if `owner` is a multiSig."""
class MintToCheckedParams(NamedTuple):
"""MintToChecked token transaction params."""
program_id: PublicKey
"""SPL Token program account."""
mint: PublicKey
"""Public key of the minter account."""
dest: PublicKey
"""Public key of the account to mint to."""
mint_authority: PublicKey
"""The mint authority."""
amount: int
"""Amount to mint."""
decimals: int
"""Amount decimals."""
signers: List[PublicKey] = []
"""Signing accounts if `mint_authority` is a multiSig."""
class BurnCheckedParams(NamedTuple):
"""BurnChecked token transaction params."""
program_id: PublicKey
"""SPL Token program account."""
mint: PublicKey
"""Public key of the minter account."""
account: PublicKey
"""Account to burn tokens from."""
owner: PublicKey
"""Owner of the account."""
amount: int
"""Amount to burn."""
decimals: int
"""Amount decimals."""
signers: List[PublicKey] = []
"""Signing accounts if `owner` is a multiSig"""
def __parse_and_validate_instruction(
instruction: TransactionInstruction,
expected_keys: int,
expected_type: InstructionType,
) -> Any: # Returns a Construct container.
validate_instruction_keys(instruction, expected_keys)
data = INSTRUCTIONS_LAYOUT.parse(instruction.data)
validate_instruction_type(data, expected_type)
return data
def decode_initialize_mint(instruction: TransactionInstruction) -> InitializeMintParams:
"""Decode an initialize mint token instruction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 2, InstructionType.INITIALIZE_MINT)
return InitializeMintParams(
decimals=parsed_data.args.decimals,
program_id=instruction.program_id,
mint=instruction.keys[0].pubkey,
mint_authority=PublicKey(parsed_data.args.mint_authority),
freeze_authority=PublicKey(parsed_data.args.freeze_authority)
if parsed_data.args.freeze_authority_option
else None,
)
def decode_initialize_account(instruction: TransactionInstruction) -> InitializeAccountParams:
"""Decode an initialize account token instruction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
_ = __parse_and_validate_instruction(instruction, 4, InstructionType.INITIALIZE_ACCOUNT)
return InitializeAccountParams(
program_id=instruction.program_id,
account=instruction.keys[0].pubkey,
mint=instruction.keys[1].pubkey,
owner=instruction.keys[2].pubkey,
)
def decode_initialize_multisig(instruction: TransactionInstruction) -> InitializeMultisigParams:
"""Decode an initialize multisig account token instruction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 2, InstructionType.INITIALIZE_MULTISIG)
num_signers = parsed_data.args.m
validate_instruction_keys(instruction, 2 + num_signers)
return InitializeMultisigParams(
program_id=instruction.program_id,
multisig=instruction.keys[0].pubkey,
signers=[signer.pubkey for signer in instruction.keys[-num_signers:]],
m=num_signers,
)
def decode_transfer(instruction: TransactionInstruction) -> TransferParams:
"""Decode a transfer token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 3, InstructionType.TRANSFER)
return TransferParams(
program_id=instruction.program_id,
source=instruction.keys[0].pubkey,
dest=instruction.keys[1].pubkey,
owner=instruction.keys[2].pubkey,
signers=[signer.pubkey for signer in instruction.keys[3:]],
amount=parsed_data.args.amount,
)
def decode_approve(instruction: TransactionInstruction) -> ApproveParams:
"""Decode a approve token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 3, InstructionType.APPROVE)
return ApproveParams(
program_id=instruction.program_id,
source=instruction.keys[0].pubkey,
delegate=instruction.keys[1].pubkey,
owner=instruction.keys[2].pubkey,
signers=[signer.pubkey for signer in instruction.keys[3:]],
amount=parsed_data.args.amount,
)
def decode_revoke(instruction: TransactionInstruction) -> RevokeParams:
"""Decode a revoke token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
_ = __parse_and_validate_instruction(instruction, 2, InstructionType.REVOKE)
return RevokeParams(
program_id=instruction.program_id,
account=instruction.keys[0].pubkey,
owner=instruction.keys[1].pubkey,
signers=[signer.pubkey for signer in instruction.keys[2:]],
)
def decode_set_authority(instruction: TransactionInstruction) -> SetAuthorityParams:
"""Decode a set authority token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 2, InstructionType.SET_AUTHORITY)
return SetAuthorityParams(
program_id=instruction.program_id,
account=instruction.keys[0].pubkey,
authority=AuthorityType(parsed_data.args.authority_type),
new_authority=PublicKey(parsed_data.args.new_authority) if parsed_data.args.new_authority_option else None,
current_authority=instruction.keys[1].pubkey,
signers=[signer.pubkey for signer in instruction.keys[2:]],
)
def decode_mint_to(instruction: TransactionInstruction) -> MintToParams:
"""Decode a mint to token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 3, InstructionType.MINT_TO)
return MintToParams(
program_id=instruction.program_id,
amount=parsed_data.args.amount,
mint=instruction.keys[0].pubkey,
dest=instruction.keys[1].pubkey,
mint_authority=instruction.keys[2].pubkey,
signers=[signer.pubkey for signer in instruction.keys[3:]],
)
def decode_burn(instruction: TransactionInstruction) -> BurnParams:
"""Decode a burn token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 3, InstructionType.BURN)
return BurnParams(
program_id=instruction.program_id,
amount=parsed_data.args.amount,
account=instruction.keys[0].pubkey,
mint=instruction.keys[1].pubkey,
owner=instruction.keys[2].pubkey,
signers=[signer.pubkey for signer in instruction.keys[3:]],
)
def decode_close_account(instruction: TransactionInstruction) -> CloseAccountParams:
"""Decode a close account token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
_ = __parse_and_validate_instruction(instruction, 3, InstructionType.CLOSE_ACCOUNT)
return CloseAccountParams(
program_id=instruction.program_id,
account=instruction.keys[0].pubkey,
dest=instruction.keys[1].pubkey,
owner=instruction.keys[2].pubkey,
signers=[signer.pubkey for signer in instruction.keys[3:]],
)
def decode_freeze_account(instruction: TransactionInstruction) -> FreezeAccountParams:
"""Decode a freeze account token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
_ = __parse_and_validate_instruction(instruction, 3, InstructionType.FREEZE_ACCOUNT)
return FreezeAccountParams(
program_id=instruction.program_id,
account=instruction.keys[0].pubkey,
mint=instruction.keys[1].pubkey,
authority=instruction.keys[2].pubkey,
multi_signers=[signer.pubkey for signer in instruction.keys[3:]],
)
def decode_thaw_account(instruction: TransactionInstruction) -> ThawAccountParams:
"""Decode a thaw account token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
_ = __parse_and_validate_instruction(instruction, 3, InstructionType.THAW_ACCOUNT)
return ThawAccountParams(
program_id=instruction.program_id,
account=instruction.keys[0].pubkey,
mint=instruction.keys[1].pubkey,
authority=instruction.keys[2].pubkey,
multi_signers=[signer.pubkey for signer in instruction.keys[3:]],
)
def decode_transfer_checked(instruction: TransactionInstruction) -> TransferCheckedParams:
"""Decode a transfer_checked token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 4, InstructionType.TRANSFER2)
return TransferCheckedParams(
program_id=instruction.program_id,
amount=parsed_data.args.amount,
decimals=parsed_data.args.decimals,
source=instruction.keys[0].pubkey,
mint=instruction.keys[1].pubkey,
dest=instruction.keys[2].pubkey,
owner=instruction.keys[3].pubkey,
signers=[signer.pubkey for signer in instruction.keys[4:]],
)
def decode_approve_checked(instruction: TransactionInstruction) -> ApproveCheckedParams:
"""Decode a approve_checked token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 4, InstructionType.APPROVE2)
return ApproveCheckedParams(
program_id=instruction.program_id,
amount=parsed_data.args.amount,
decimals=parsed_data.args.decimals,
source=instruction.keys[0].pubkey,
mint=instruction.keys[1].pubkey,
delegate=instruction.keys[2].pubkey,
owner=instruction.keys[3].pubkey,
signers=[signer.pubkey for signer in instruction.keys[4:]],
)
def decode_mint_to_checked(instruction: TransactionInstruction) -> MintToCheckedParams:
"""Decode a mintTo2 token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 3, InstructionType.MINT_TO2)
return MintToCheckedParams(
program_id=instruction.program_id,
amount=parsed_data.args.amount,
decimals=parsed_data.args.decimals,
mint=instruction.keys[0].pubkey,
dest=instruction.keys[1].pubkey,
mint_authority=instruction.keys[2].pubkey,
signers=[signer.pubkey for signer in instruction.keys[3:]],
)
def decode_burn_checked(instruction: TransactionInstruction) -> BurnCheckedParams:
"""Decode a burn_checked token transaction and retrieve the instruction params.
Args:
instruction: The instruction to decode.
Returns:
The decoded instruction.
"""
parsed_data = __parse_and_validate_instruction(instruction, 3, InstructionType.BURN2)
return BurnCheckedParams(
program_id=instruction.program_id,
amount=parsed_data.args.amount,
decimals=parsed_data.args.decimals,
account=instruction.keys[0].pubkey,
mint=instruction.keys[1].pubkey,
owner=instruction.keys[2].pubkey,
signers=[signer.pubkey for signer in instruction.keys[3:]],
)
def __add_signers(keys: List[AccountMeta], owner: PublicKey, signers: List[PublicKey]) -> None:
if signers:
keys.append(AccountMeta(pubkey=owner, is_signer=False, is_writable=False))
for signer in signers:
keys.append(AccountMeta(pubkey=signer, is_signer=True, is_writable=False))
else:
keys.append(AccountMeta(pubkey=owner, is_signer=True, is_writable=False))
def __burn_instruction(params: Union[BurnParams, BurnCheckedParams], data: Any) -> TransactionInstruction:
keys = [
AccountMeta(pubkey=params.account, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.mint, is_signer=False, is_writable=True),
]
__add_signers(keys, params.owner, params.signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def __freeze_or_thaw_instruction(
params: Union[FreezeAccountParams, ThawAccountParams], instruction_type: InstructionType
) -> TransactionInstruction:
data = INSTRUCTIONS_LAYOUT.build(dict(instruction_type=instruction_type, args=None))
keys = [
AccountMeta(pubkey=params.account, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.mint, is_signer=False, is_writable=False),
]
__add_signers(keys, params.authority, params.multi_signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def __mint_to_instruction(params: Union[MintToParams, MintToCheckedParams], data: Any) -> TransactionInstruction:
keys = [
AccountMeta(pubkey=params.mint, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.dest, is_signer=False, is_writable=True),
]
__add_signers(keys, params.mint_authority, params.signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def initialize_mint(params: InitializeMintParams) -> TransactionInstruction:
"""Creates a transaction instruction to initialize a new mint newly.
This instruction requires no signers and MUST be included within the same Transaction as
the system program's `CreateInstruction` that creates the account being initialized.
Otherwise another party can acquire ownership of the uninitialized account.
Example:
>>> from spl.token.constants import TOKEN_PROGRAM_ID
>>> mint_account, mint_authority, freeze_authority, owner = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = InitializeMintParams(
... decimals=6,
... freeze_authority=freeze_authority,
... mint=mint_account,
... mint_authority=mint_authority,
... program_id=TOKEN_PROGRAM_ID,
... )
>>> type(initialize_mint(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The instruction to initialize the mint.
""" # noqa: E501 # pylint: disable=line-too-long
freeze_authority, opt = (params.freeze_authority, 1) if params.freeze_authority else (PublicKey(0), 0)
data = INSTRUCTIONS_LAYOUT.build(
dict(
instruction_type=InstructionType.INITIALIZE_MINT,
args=dict(
decimals=params.decimals,
mint_authority=bytes(params.mint_authority),
freeze_authority_option=opt,
freeze_authority=bytes(freeze_authority),
),
)
)
return TransactionInstruction(
keys=[
AccountMeta(pubkey=params.mint, is_signer=False, is_writable=True),
AccountMeta(pubkey=SYSVAR_RENT_PUBKEY, is_signer=False, is_writable=False),
],
program_id=params.program_id,
data=data,
)
def initialize_account(params: InitializeAccountParams) -> TransactionInstruction:
"""Creates a transaction instruction to initialize a new account to hold tokens.
This instruction requires no signers and MUST be included within the same Transaction as
the system program's `CreateInstruction` that creates the account being initialized.
Otherwise another party can acquire ownership of the uninitialized account.
Example:
>>> account, mint, owner, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = InitializeAccountParams(
... account=account,
... mint=mint,
... owner=owner,
... program_id=token,
... )
>>> type(initialize_account(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The instruction to initialize the account.
"""
data = INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.INITIALIZE_ACCOUNT, args=None))
return TransactionInstruction(
keys=[
AccountMeta(pubkey=params.account, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.mint, is_signer=False, is_writable=False),
AccountMeta(pubkey=params.owner, is_signer=False, is_writable=False),
AccountMeta(pubkey=SYSVAR_RENT_PUBKEY, is_signer=False, is_writable=False),
],
program_id=params.program_id,
data=data,
)
def initialize_multisig(params: InitializeMultisigParams) -> TransactionInstruction:
"""Creates a transaction instruction to initialize a multisignature account with N provided signers.
This instruction requires no signers and MUST be included within the same Transaction as
the system program's `CreateInstruction` that creates the account being initialized.
Otherwise another party can acquire ownership of the uninitialized account.
Example:
>>> m = 2 # Two signers
>>> signers = [PublicKey(i) for i in range(m)]
>>> multisig_account, token = PublicKey(1), PublicKey(2)
>>> params = InitializeMultisigParams(
... m=m,
... multisig=multisig_account,
... signers=signers,
... program_id=token,
... )
>>> type(initialize_multisig(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The instruction to initialize the multisig.
"""
data = INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.INITIALIZE_MULTISIG, args=dict(m=params.m)))
keys = [
AccountMeta(pubkey=params.multisig, is_signer=False, is_writable=True),
AccountMeta(pubkey=SYSVAR_RENT_PUBKEY, is_signer=False, is_writable=False),
]
for signer in params.signers:
keys.append(AccountMeta(pubkey=signer, is_signer=False, is_writable=False))
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def transfer(params: TransferParams) -> TransactionInstruction:
"""Creates a transaction instruction to transfers tokens from one account to another.
Either directly or via a delegate.
Example:
>>> dest, owner, source, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = TransferParams(
... amount=1000,
... dest=dest,
... owner=owner,
... program_id=token,
... source=source,
... )
>>> type(transfer(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The transfer instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.TRANSFER, args=dict(amount=params.amount)))
keys = [
AccountMeta(pubkey=params.source, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.dest, is_signer=False, is_writable=True),
]
__add_signers(keys, params.owner, params.signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def approve(params: ApproveParams) -> TransactionInstruction:
"""Creates a transaction instruction to approve a delegate.
Example:
>>> delegate, owner, source, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = ApproveParams(
... amount=123,
... delegate=delegate,
... owner=owner,
... program_id=token,
... source=source
... )
>>> type(approve(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The approve instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.APPROVE, args=dict(amount=params.amount)))
keys = [
AccountMeta(pubkey=params.source, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.delegate, is_signer=False, is_writable=False),
]
__add_signers(keys, params.owner, params.signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def revoke(params: RevokeParams) -> TransactionInstruction:
"""Creates a transaction instruction that revokes delegate authority for a given account.
Example:
>>> account, owner, token = PublicKey(1), PublicKey(2), PublicKey(3)
>>> params = RevokeParams(
... account=account, owner=owner, program_id=token
... )
>>> type(revoke(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The revoke instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.REVOKE, args=None))
keys = [AccountMeta(pubkey=params.account, is_signer=False, is_writable=True)]
__add_signers(keys, params.owner, params.signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def set_authority(params: SetAuthorityParams) -> TransactionInstruction:
"""Creates a transaction instruction to sets a new authority of a mint or account.
Example:
>>> account, current_authority, new_authority, token = (
... PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
... )
>>> params = SetAuthorityParams(
... account=account,
... authority=AuthorityType.ACCOUNT_OWNER,
... current_authority=current_authority,
... new_authority=new_authority,
... program_id=token,
... )
>>> type(set_authority(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The set authority instruction.
"""
new_authority, opt = (params.new_authority, 1) if params.new_authority else (PublicKey(0), 0)
data = INSTRUCTIONS_LAYOUT.build(
dict(
instruction_type=InstructionType.SET_AUTHORITY,
args=dict(authority_type=params.authority, new_authority_option=opt, new_authority=bytes(new_authority)),
)
)
keys = [AccountMeta(pubkey=params.account, is_signer=False, is_writable=True)]
__add_signers(keys, params.current_authority, params.signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def mint_to(params: MintToParams) -> TransactionInstruction:
"""Creates a transaction instruction to mint new tokens to an account.
The native mint does not support minting.
Example:
>>> dest, mint, mint_authority, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = MintToParams(
... amount=123,
... dest=dest,
... mint=mint,
... mint_authority=mint_authority,
... program_id=token,
... )
>>> type(mint_to(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The mint-to instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.MINT_TO, args=dict(amount=params.amount)))
return __mint_to_instruction(params, data)
def burn(params: BurnParams) -> TransactionInstruction:
"""Creates a transaction instruction to burns tokens by removing them from an account.
Example:
>>> account, mint, owner, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = BurnParams(
... amount=123, account=account, mint=mint, owner=owner, program_id=token,
... )
>>> type(burn(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The burn instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.BURN, args=dict(amount=params.amount)))
return __burn_instruction(params, data)
def close_account(params: CloseAccountParams) -> TransactionInstruction:
"""Creates a transaction instruction to close an account by transferring all its SOL to the destination account.
Non-native accounts may only be closed if its token amount is zero.
Example:
>>> account, dest, owner, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = CloseAccountParams(
... account=account, dest=dest, owner=owner, program_id=token)
>>> type(close_account(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The close-account instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(dict(instruction_type=InstructionType.CLOSE_ACCOUNT, args=None))
keys = [
AccountMeta(pubkey=params.account, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.dest, is_signer=False, is_writable=True),
]
__add_signers(keys, params.owner, params.signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def freeze_account(params: FreezeAccountParams) -> TransactionInstruction:
"""Creates a transaction instruction to freeze an initialized account using the mint's freeze_authority (if set).
Example:
>>> account, mint, authority, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = FreezeAccountParams(
... account=account, mint=mint, authority=authority, program_id=token)
>>> type(freeze_account(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The freeze-account instruction.
"""
return __freeze_or_thaw_instruction(params, InstructionType.FREEZE_ACCOUNT)
def thaw_account(params: ThawAccountParams) -> TransactionInstruction:
"""Creates a transaction instruction to thaw a frozen account using the Mint's freeze_authority (if set).
Example:
>>> account, mint, authority, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = ThawAccountParams(
... account=account, mint=mint, authority=authority, program_id=token)
>>> type(thaw_account(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The thaw-account instruction.
"""
return __freeze_or_thaw_instruction(params, InstructionType.THAW_ACCOUNT)
def transfer_checked(params: TransferCheckedParams) -> TransactionInstruction:
"""This instruction differs from `transfer` in that the token mint and decimals value is asserted by the caller.
Example:
>>> dest, mint, owner, source, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4), PublicKey(5)
>>> params = TransferCheckedParams(
... amount=1000,
... decimals=6,
... dest=dest,
... mint=mint,
... owner=owner,
... program_id=token,
... source=source,
... )
>>> type(transfer_checked(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The transfer-checked instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(
dict(instruction_type=InstructionType.TRANSFER2, args=dict(amount=params.amount, decimals=params.decimals))
)
keys = [
AccountMeta(pubkey=params.source, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.mint, is_signer=False, is_writable=False),
AccountMeta(pubkey=params.dest, is_signer=False, is_writable=True),
]
__add_signers(keys, params.owner, params.signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def approve_checked(params: ApproveCheckedParams) -> TransactionInstruction:
"""This instruction differs from `approve` in that the token mint and decimals value is asserted by the caller.
Example:
>>> delegate, mint, owner, source, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4), PublicKey(5)
>>> params = ApproveCheckedParams(
... amount=1000,
... decimals=6,
... delegate=delegate,
... mint=mint,
... owner=owner,
... program_id=token,
... source=source,
... )
>>> type(approve_checked(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The approve-checked instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(
dict(instruction_type=InstructionType.APPROVE2, args=dict(amount=params.amount, decimals=params.decimals))
)
keys = [
AccountMeta(pubkey=params.source, is_signer=False, is_writable=True),
AccountMeta(pubkey=params.mint, is_signer=False, is_writable=False),
AccountMeta(pubkey=params.delegate, is_signer=False, is_writable=False),
]
__add_signers(keys, params.owner, params.signers)
return TransactionInstruction(keys=keys, program_id=params.program_id, data=data)
def mint_to_checked(params: MintToCheckedParams) -> TransactionInstruction:
"""This instruction differs from `mint_to` in that the decimals value is asserted by the caller.
Example:
>>> dest, mint, mint_authority, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = MintToCheckedParams(
... amount=123,
... decimals=6,
... dest=dest,
... mint=mint,
... mint_authority=mint_authority,
... program_id=token,
... )
>>> type(mint_to_checked(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The mint-to-checked instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(
dict(instruction_type=InstructionType.MINT_TO2, args=dict(amount=params.amount, decimals=params.decimals))
)
return __mint_to_instruction(params, data)
def burn_checked(params: BurnCheckedParams) -> TransactionInstruction:
"""This instruction differs from `burn` in that the decimals value is asserted by the caller.
Example:
>>> account, mint, owner, token = PublicKey(1), PublicKey(2), PublicKey(3), PublicKey(4)
>>> params = BurnCheckedParams(
... amount=123, account=account, decimals=6, mint=mint, owner=owner, program_id=token,
... )
>>> type(burn_checked(params))
<class 'solana.transaction.TransactionInstruction'>
Returns:
The burn-checked instruction.
"""
data = INSTRUCTIONS_LAYOUT.build(
dict(instruction_type=InstructionType.BURN2, args=dict(amount=params.amount, decimals=params.decimals))
)
return __burn_instruction(params, data)
def get_associated_token_address(owner: PublicKey, mint: PublicKey) -> PublicKey:
"""Derives the associated token address for the given wallet address and token mint.
Returns:
The public key of the derived associated token address.
"""
key, _ = PublicKey.find_program_address(
seeds=[bytes(owner), bytes(TOKEN_PROGRAM_ID), bytes(mint)], program_id=ASSOCIATED_TOKEN_PROGRAM_ID
)
return key
def create_associated_token_account(payer: PublicKey, owner: PublicKey, mint: PublicKey) -> TransactionInstruction:
"""Creates a transaction instruction to create an associated token account.
Returns:
The instruction to create the associated token account.
"""
associated_token_address = get_associated_token_address(owner, mint)
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,
)