solana指令解析-associated token account(ATA)
什么是associated token account(ATA)?
associated token account 称为关联代币账户,通过ATAP创建,用来保存有关特定代币、其余额及其所有者的信息。它是与特定代币账户(可以理解为以太坊的erc20合约)关联的账户。 ATA 允许用户对该代币进行交易和管理。
- solana中将erc20代币称为SPL代币(solana中一个代币,仅仅是一个归Token合约管理的普通的Account对象,即代币账户。关于具体相关说明,可参考:https://www.solanazh.com/course/1-3
- 参考学习:(推荐) https://www.alchemy.com/overviews/associated-token-account
AssociatedTokenAccountProgramID:
ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL
什么是Associated Token Account Program(ATAP)?
- Associated Token Account Program称关联代币程序(ATAP)是每个 ATA 的父程序。提供了将用户的钱包地址映射到他们持有的关联代币帐户的机制(ATA)。允许发送者为接收者创建关联的token帐户,以便token传输正常进行。
- ATAP能够确保如果一个用户想要向另一个用户发送token,接收者能够获得该token,即使他没有相应令牌的 ATA
token转账:
参考:【Token 轉帳交易部分】https://www.blocktempo.com/understand-solana-accounts-tokens-transactions-and-asset-security/
- 前提:默认账户A拥有’USDT’代币
- 拥有指定代币的用户拥有通过ATAP 创建的关联代币账户(ATA) (简单来说,拥有usdt代币的账户将会拥有一个由ATAP创建的一个与USDT代币关联的ATA账户,用来存储这个账户拥有的USDT代币的余额)
- 账户之间的token转账交易直接发生在账户的 ATA 之间,需要注意的是:在 token 转账指令中,source 和 destination 地址通常指的是 ATA 地址,而不是转账双方的直接账户地址
associated token account指令汇总
指令 | 值 | 说明 |
---|---|---|
CreateAssociatedTokenAccount | 0 | 创建一个关联代币账户(account已存在会报错) |
CreateIdempotent | 1 | 创建一个幂等的(具有幂等性质的)关联代币账户,即多次执行同一操作,结果都是一样的。(account已存在不会报错) |
RecoverNested | 2 | 用于从嵌套的关联代币账户中转移资金并关闭它。 |
源码地址:github.com/blocto/solana-go-sdk/program/associated_token_account
1.CreateAssociatedTokenAccount
该指令用于创建一个关联代币账户。在 Solana 区块链上,当用户需要与特定代币进行交互时,需要先创建一个关联代币账户,以便存储该代币的余额信息。该指令允许用户创建一个新的关联代币账户。
- 如果AssociatedTokenAccount已经存在,将会返回错误
1.1源码
type CreateParam struct {
Funder common.PublicKey
Owner common.PublicKey
Mint common.PublicKey
AssociatedTokenAccount common.PublicKey
}
// Create creates an associated token account for the given wallet address and token mint. Return an error if the account exists.
func Create(param CreateParam) types.Instruction {
data, err := borsh.Serialize(struct {
Instruction Instruction
}{
Instruction: InstructionCreate,
})
if err != nil {
panic(err)
}
return types.Instruction{
ProgramID: common.SPLAssociatedTokenAccountProgramID,
Accounts: []types.AccountMeta{
{PubKey: param.Funder, IsSigner: true, IsWritable: true},
{PubKey: param.AssociatedTokenAccount, IsSigner: false, IsWritable: true},
{PubKey: param.Owner, IsSigner: false, IsWritable: false},
{PubKey: param.Mint, IsSigner: false, IsWritable: false},
{PubKey: common.SystemProgramID, IsSigner: false, IsWritable: false},
{PubKey: common.TokenProgramID, IsSigner: false, IsWritable: false},
{PubKey: common.SysVarRentPubkey, IsSigner: false, IsWritable: false},
},
Data: data,
}
}
1.2 指令参数:
Funder
:用于支付交易费用的账户的公钥。Owner
:新关联代币账户的所有者的公钥。所有者是新关联代币账户的实际控制者,具有对该账户进行操作的权限。Mint
:与新关联代币账户关联的代币的公钥。代币的发行者可以通过该公钥查看关联的代币账户。AssociatedTokenAccount
:要创建的关联代币账户的公钥。
1.3AccountMate
- PubKey: 账户的公钥
- IsSigner :表示该账户是否需要签名验证。
- IsWritable: 表示该账户是否可以被写入数据
PubKey | IsSigner | IsWritable |
---|---|---|
Funder | true | true |
AssociatedTokenAccount | false | true |
Owner | false | false |
Mint | false | false |
SystemProgramID | false | false |
TokenProgramID | false | false |
SysVarRentPubkey | false | false |
- SystemProgramID表示系统程序的公钥,用于执行 address_lookup_table 指令的程序。值为
11111111111111111111111111111111
- TokenProgramID表示代币程序,是 Solana 区块链上管理代币的标准程序。在创建关联代币账户时,需要指定代币程序以确保账户与代币的管理逻辑一致。值为
TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA
- SysVarRentPubkey是系统变量之一,用于存储账户租金信息。在创建关联代币账户时,需要考虑账户的租金,因此需要引用系统变量来获取相应的信息。值为
SysvarRent111111111111111111111111111111111
2.CreateIdempotent
这个指令与 InstructionCreate 类似,但具有幂等性质。这意味着如果多次执行相同的创建关联代币账户的操作,结果都是相同的。这样的设计可以确保在网络中进行重试或发生错误时,不会导致创建多个相同的账户。
2.1源码
type CreateIdempotentParam struct {
Funder common.PublicKey
Owner common.PublicKey
Mint common.PublicKey
AssociatedTokenAccount common.PublicKey
}
// CreateIdempotent creates an associated token account for the given wallet address and token mint,
// if it doesn't already exist. Returns an error if the account exists, but with a different owner.
func CreateIdempotent(param CreateIdempotentParam) types.Instruction {
data, err := borsh.Serialize(struct {
Instruction Instruction
}{
Instruction: InstructionCreateIdempotent,
})
if err != nil {
panic(err)
}
return types.Instruction{
ProgramID: common.SPLAssociatedTokenAccountProgramID,
Accounts: []types.AccountMeta{
{PubKey: param.Funder, IsSigner: true, IsWritable: true},
{PubKey: param.AssociatedTokenAccount, IsSigner: false, IsWritable: true},
{PubKey: param.Owner, IsSigner: false, IsWritable: false},
{PubKey: param.Mint, IsSigner: false, IsWritable: false},
{PubKey: common.SystemProgramID, IsSigner: false, IsWritable: false},
{PubKey: common.TokenProgramID, IsSigner: false, IsWritable: false},
{PubKey: common.SysVarRentPubkey, IsSigner: false, IsWritable: false},
},
Data: data,
}
}
-
参数与accountmeta与CreateAssociatedTokenAccount 指令一致,参考上文即可
-
如果AssociatedTokenAccount 不存在,则创建一个新的关联代币账户,如果账户已经存在,但所有者不同,则返回错误。
3.RecoverNested
个指令用于从嵌套的关联代币账户中转移资金并关闭它。有时候,用户可能会创建一个关联代币账户,并将其作为另一个关联代币账户的所有者。当需要关闭这个嵌套的关联代币账户时,可以使用该指令将其中的资金转移到其他地方,并关闭该账户。
3.1源码
type RecoverNestedParam struct {
Owner common.PublicKey
OwnerMint common.PublicKey
OwnerAssociatedTokenAccount common.PublicKey
NestedMint common.PublicKey
NestedMintAssociatedTokenAccount common.PublicKey
DestinationAssociatedTokenAccount common.PublicKey
}
// RecoverNested transfers from and closes a nested associated token account: an associated token account owned by an associated token account.
func RecoverNested(param RecoverNestedParam) types.Instruction {
data, err := borsh.Serialize(struct {
Instruction Instruction
}{
Instruction: InstructionRecoverNested,
})
if err != nil {
panic(err)
}
return types.Instruction{
ProgramID: common.SPLAssociatedTokenAccountProgramID,
Accounts: []types.AccountMeta{
{PubKey: param.NestedMintAssociatedTokenAccount, IsSigner: false, IsWritable: true},
{PubKey: param.NestedMint, IsSigner: false, IsWritable: false},
{PubKey: param.DestinationAssociatedTokenAccount, IsSigner: false, IsWritable: true},
{PubKey: param.OwnerAssociatedTokenAccount, IsSigner: false, IsWritable: true},
{PubKey: param.OwnerMint, IsSigner: false, IsWritable: false},
{PubKey: param.Owner, IsSigner: true, IsWritable: true},
{PubKey: common.TokenProgramID, IsSigner: false, IsWritable: false},
},
Data: data,
}
}
3.2指令参数
Owner
:表示要执行恢复操作的账户的公钥。OwnerMint
:表示所属代币的公钥。OwnerAssociatedTokenAccount
:表示所属关联代币账户的公钥。NestedMint
:表示嵌套代币的公钥。NestedMintAssociatedTokenAccount
:表示嵌套关联代币账户的公钥。DestinationAssociatedTokenAccount
:表示目标关联代币账户的公钥。
3.3AccountMeta
PubKey | IsSigner | IsWritable |
---|---|---|
NestedMintAssociatedTokenAccount | false | true |
NestedMint | false | false |
DestinationAssociatedTokenAccount | false | true |
OwnerAssociatedTokenAccount | false | true |
OwnerMint | false | false |
Owner | true | true |
TokenProgramID | false | false |