spl: Bump token-2022 to v1 (#34412)

* Update toml and lockfiles

* account-decoder: Add group and group member extensions

* transaction-status: Add token group + pointer extensions

* program-test: Update token-2022 binary
This commit is contained in:
Jon Cinque 2023-12-21 20:19:10 -05:00 committed by GitHub
parent 2fd0bae71e
commit 8a8466cd86
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 577 additions and 23 deletions

38
Cargo.lock generated
View File

@ -5259,6 +5259,7 @@ dependencies = [
"spl-pod",
"spl-token",
"spl-token-2022",
"spl-token-group-interface",
"spl-token-metadata-interface",
"thiserror",
"zstd",
@ -7193,6 +7194,12 @@ dependencies = [
"syn 2.0.42",
]
[[package]]
name = "solana-security-txt"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183"
[[package]]
name = "solana-send-transaction-service"
version = "1.18.0"
@ -7850,9 +7857,9 @@ dependencies = [
[[package]]
name = "spl-associated-token-account"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "385e31c29981488f2820b2022d8e731aae3b02e6e18e2fd854e4c9a94dc44fc3"
checksum = "992d9c64c2564cc8f63a4b508bf3ebcdf2254b0429b13cd1d31adb6162432a5f"
dependencies = [
"assert_matches",
"borsh 0.10.3",
@ -7958,9 +7965,9 @@ dependencies = [
[[package]]
name = "spl-tlv-account-resolution"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9"
checksum = "3f7020347c07892c08560d230fbb8a980316c9e198e22b198b7b9d951ff96047"
dependencies = [
"bytemuck",
"solana-program",
@ -7987,9 +7994,9 @@ dependencies = [
[[package]]
name = "spl-token-2022"
version = "0.9.0"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4abf34a65ba420584a0c35f3903f8d727d1f13ababbdc3f714c6b065a686e86"
checksum = "d697fac19fd74ff472dfcc13f0b442dd71403178ce1de7b5d16f83a33561c059"
dependencies = [
"arrayref",
"bytemuck",
@ -7997,16 +8004,31 @@ dependencies = [
"num-traits",
"num_enum 0.7.1",
"solana-program",
"solana-security-txt",
"solana-zk-token-sdk",
"spl-memo",
"spl-pod",
"spl-token",
"spl-token-group-interface",
"spl-token-metadata-interface",
"spl-transfer-hook-interface",
"spl-type-length-value",
"thiserror",
]
[[package]]
name = "spl-token-group-interface"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b889509d49fa74a4a033ca5dae6c2307e9e918122d97e58562f5c4ffa795c75d"
dependencies = [
"bytemuck",
"solana-program",
"spl-discriminator",
"spl-pod",
"spl-program-error",
]
[[package]]
name = "spl-token-metadata-interface"
version = "0.2.0"
@ -8023,9 +8045,9 @@ dependencies = [
[[package]]
name = "spl-transfer-hook-interface"
version = "0.3.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "051d31803f873cabe71aec3c1b849f35248beae5d19a347d93a5c9cccc5d5a9b"
checksum = "7aabdb7c471566f6ddcee724beb8618449ea24b399e58d464d6b5bc7db550259"
dependencies = [
"arrayref",
"bytemuck",

View File

@ -389,12 +389,13 @@ solana-zk-keygen = { path = "zk-keygen", version = "=1.18.0" }
solana-zk-token-proof-program = { path = "programs/zk-token-proof", version = "=1.18.0" }
solana-zk-token-sdk = { path = "zk-token-sdk", version = "=1.18.0" }
solana_rbpf = "=0.8.0"
spl-associated-token-account = "=2.2.0"
spl-associated-token-account = "=2.3.0"
spl-instruction-padding = "0.1"
spl-memo = "=4.0.0"
spl-pod = "=0.1.0"
spl-token = "=4.0.0"
spl-token-2022 = "=0.9.0"
spl-token-2022 = "=1.0.0"
spl-token-group-interface = "=0.1.0"
spl-token-metadata-interface = "=0.2.0"
static_assertions = "1.1.0"
stream-cancel = "0.8.2"

View File

@ -23,6 +23,7 @@ solana-config-program = { workspace = true }
solana-sdk = { workspace = true }
spl-token = { workspace = true, features = ["no-entrypoint"] }
spl-token-2022 = { workspace = true, features = ["no-entrypoint"] }
spl-token-group-interface = { workspace = true }
spl-token-metadata-interface = { workspace = true }
thiserror = { workspace = true }
zstd = { workspace = true }

View File

@ -6,6 +6,7 @@ use {
solana_program::pubkey::Pubkey,
solana_zk_token_sdk::zk_token_elgamal::pod::ElGamalPubkey,
},
spl_token_group_interface::state::{TokenGroup, TokenGroupMember},
spl_token_metadata_interface::state::TokenMetadata,
};
@ -32,6 +33,10 @@ pub enum UiExtension {
TransferHookAccount(UiTransferHookAccount),
MetadataPointer(UiMetadataPointer),
TokenMetadata(UiTokenMetadata),
GroupPointer(UiGroupPointer),
GroupMemberPointer(UiGroupMemberPointer),
TokenGroup(UiTokenGroup),
TokenGroupMember(UiTokenGroupMember),
UnparseableExtension,
}
@ -108,6 +113,22 @@ pub fn parse_extension<S: BaseState>(
.get_extension::<extension::transfer_hook::TransferHookAccount>()
.map(|&extension| UiExtension::TransferHookAccount(extension.into()))
.unwrap_or(UiExtension::UnparseableExtension),
ExtensionType::GroupPointer => account
.get_extension::<extension::group_pointer::GroupPointer>()
.map(|&extension| UiExtension::GroupPointer(extension.into()))
.unwrap_or(UiExtension::UnparseableExtension),
ExtensionType::GroupMemberPointer => account
.get_extension::<extension::group_member_pointer::GroupMemberPointer>()
.map(|&extension| UiExtension::GroupMemberPointer(extension.into()))
.unwrap_or(UiExtension::UnparseableExtension),
ExtensionType::TokenGroup => account
.get_extension::<TokenGroup>()
.map(|&extension| UiExtension::TokenGroup(extension.into()))
.unwrap_or(UiExtension::UnparseableExtension),
ExtensionType::TokenGroupMember => account
.get_extension::<TokenGroupMember>()
.map(|&extension| UiExtension::TokenGroupMember(extension.into()))
.unwrap_or(UiExtension::UnparseableExtension),
}
}
@ -481,3 +502,78 @@ impl From<extension::transfer_hook::TransferHookAccount> for UiTransferHookAccou
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct UiGroupPointer {
pub authority: Option<String>,
pub group_address: Option<String>,
}
impl From<extension::group_pointer::GroupPointer> for UiGroupPointer {
fn from(group_pointer: extension::group_pointer::GroupPointer) -> Self {
let authority: Option<Pubkey> = group_pointer.authority.into();
let group_address: Option<Pubkey> = group_pointer.group_address.into();
Self {
authority: authority.map(|pubkey| pubkey.to_string()),
group_address: group_address.map(|pubkey| pubkey.to_string()),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct UiGroupMemberPointer {
pub authority: Option<String>,
pub member_address: Option<String>,
}
impl From<extension::group_member_pointer::GroupMemberPointer> for UiGroupMemberPointer {
fn from(member_pointer: extension::group_member_pointer::GroupMemberPointer) -> Self {
let authority: Option<Pubkey> = member_pointer.authority.into();
let member_address: Option<Pubkey> = member_pointer.member_address.into();
Self {
authority: authority.map(|pubkey| pubkey.to_string()),
member_address: member_address.map(|pubkey| pubkey.to_string()),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct UiTokenGroup {
pub update_authority: Option<String>,
pub mint: String,
pub size: u32,
pub max_size: u32,
}
impl From<TokenGroup> for UiTokenGroup {
fn from(token_group: TokenGroup) -> Self {
let update_authority: Option<Pubkey> = token_group.update_authority.into();
Self {
update_authority: update_authority.map(|pubkey| pubkey.to_string()),
mint: token_group.mint.to_string(),
size: token_group.size.into(),
max_size: token_group.max_size.into(),
}
}
}
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "camelCase")]
pub struct UiTokenGroupMember {
pub mint: String,
pub group: String,
pub member_number: u32,
}
impl From<TokenGroupMember> for UiTokenGroupMember {
fn from(member: TokenGroupMember) -> Self {
Self {
mint: member.mint.to_string(),
group: member.group.to_string(),
member_number: member.member_number.into(),
}
}
}

View File

@ -30,7 +30,7 @@ static SPL_PROGRAMS: &[(Pubkey, Pubkey, &[u8])] = &[
(
spl_token_2022::ID,
solana_sdk::bpf_loader_upgradeable::ID,
include_bytes!("programs/spl_token_2022-0.9.0.so"),
include_bytes!("programs/spl_token_2022-1.0.0.so"),
),
(
spl_memo_1_0::ID,

Binary file not shown.

View File

@ -4670,6 +4670,7 @@ dependencies = [
"solana-sdk",
"spl-token",
"spl-token-2022",
"spl-token-group-interface",
"spl-token-metadata-interface",
"thiserror",
"zstd",
@ -6294,6 +6295,12 @@ dependencies = [
"syn 2.0.42",
]
[[package]]
name = "solana-security-txt"
version = "1.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "468aa43b7edb1f9b7b7b686d5c3aeb6630dc1708e86e31343499dd5c4d775183"
[[package]]
name = "solana-send-transaction-service"
version = "1.18.0"
@ -6776,9 +6783,9 @@ dependencies = [
[[package]]
name = "spl-associated-token-account"
version = "2.2.0"
version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "385e31c29981488f2820b2022d8e731aae3b02e6e18e2fd854e4c9a94dc44fc3"
checksum = "992d9c64c2564cc8f63a4b508bf3ebcdf2254b0429b13cd1d31adb6162432a5f"
dependencies = [
"assert_matches",
"borsh 0.10.3",
@ -6874,9 +6881,9 @@ dependencies = [
[[package]]
name = "spl-tlv-account-resolution"
version = "0.4.0"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "062e148d3eab7b165582757453632ffeef490c02c86a48bfdb4988f63eefb3b9"
checksum = "3f7020347c07892c08560d230fbb8a980316c9e198e22b198b7b9d951ff96047"
dependencies = [
"bytemuck",
"solana-program",
@ -6903,9 +6910,9 @@ dependencies = [
[[package]]
name = "spl-token-2022"
version = "0.9.0"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e4abf34a65ba420584a0c35f3903f8d727d1f13ababbdc3f714c6b065a686e86"
checksum = "d697fac19fd74ff472dfcc13f0b442dd71403178ce1de7b5d16f83a33561c059"
dependencies = [
"arrayref",
"bytemuck",
@ -6913,16 +6920,31 @@ dependencies = [
"num-traits",
"num_enum 0.7.1",
"solana-program",
"solana-security-txt",
"solana-zk-token-sdk",
"spl-memo",
"spl-pod",
"spl-token",
"spl-token-group-interface",
"spl-token-metadata-interface",
"spl-transfer-hook-interface",
"spl-type-length-value",
"thiserror",
]
[[package]]
name = "spl-token-group-interface"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b889509d49fa74a4a033ca5dae6c2307e9e918122d97e58562f5c4ffa795c75d"
dependencies = [
"bytemuck",
"solana-program",
"spl-discriminator",
"spl-pod",
"spl-program-error",
]
[[package]]
name = "spl-token-metadata-interface"
version = "0.2.0"
@ -6939,9 +6961,9 @@ dependencies = [
[[package]]
name = "spl-transfer-hook-interface"
version = "0.3.0"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "051d31803f873cabe71aec3c1b849f35248beae5d19a347d93a5c9cccc5d5a9b"
checksum = "7aabdb7c471566f6ddcee724beb8618449ea24b399e58d464d6b5bc7db550259"
dependencies = [
"arrayref",
"bytemuck",

View File

@ -4,9 +4,9 @@ use {
},
extension::{
confidential_transfer::*, confidential_transfer_fee::*, cpi_guard::*,
default_account_state::*, interest_bearing_mint::*, memo_transfer::*, metadata_pointer::*,
mint_close_authority::*, permanent_delegate::*, reallocate::*, transfer_fee::*,
transfer_hook::*,
default_account_state::*, group_member_pointer::*, group_pointer::*,
interest_bearing_mint::*, memo_transfer::*, metadata_pointer::*, mint_close_authority::*,
permanent_delegate::*, reallocate::*, transfer_fee::*, transfer_hook::*,
},
serde_json::{json, Map, Value},
solana_account_decoder::parse_token::{token_amount_to_ui_amount, UiAccountState},
@ -233,7 +233,9 @@ pub fn parse_token(
| AuthorityType::ConfidentialTransferMint
| AuthorityType::TransferHookProgramId
| AuthorityType::ConfidentialTransferFeeConfig
| AuthorityType::MetadataPointer => "mint",
| AuthorityType::MetadataPointer
| AuthorityType::GroupPointer
| AuthorityType::GroupMemberPointer => "mint",
AuthorityType::AccountOwner | AuthorityType::CloseAccount => "account",
};
let mut value = json!({
@ -650,6 +652,30 @@ pub fn parse_token(
account_keys,
)
}
TokenInstruction::GroupPointerExtension => {
if instruction.data.len() < 2 {
return Err(ParseInstructionError::InstructionNotParsable(
ParsableProgram::SplToken,
));
}
parse_group_pointer_instruction(
&instruction.data[1..],
&instruction.accounts,
account_keys,
)
}
TokenInstruction::GroupMemberPointerExtension => {
if instruction.data.len() < 2 {
return Err(ParseInstructionError::InstructionNotParsable(
ParsableProgram::SplToken,
));
}
parse_group_member_pointer_instruction(
&instruction.data[1..],
&instruction.accounts,
account_keys,
)
}
}
}
@ -669,6 +695,8 @@ pub enum UiAuthorityType {
TransferHookProgramId,
ConfidentialTransferFeeConfig,
MetadataPointer,
GroupPointer,
GroupMemberPointer,
}
impl From<AuthorityType> for UiAuthorityType {
@ -689,6 +717,8 @@ impl From<AuthorityType> for UiAuthorityType {
UiAuthorityType::ConfidentialTransferFeeConfig
}
AuthorityType::MetadataPointer => UiAuthorityType::MetadataPointer,
AuthorityType::GroupPointer => UiAuthorityType::GroupPointer,
AuthorityType::GroupMemberPointer => UiAuthorityType::GroupMemberPointer,
}
}
}
@ -716,6 +746,10 @@ pub enum UiExtensionType {
ConfidentialTransferFeeAmount,
MetadataPointer,
TokenMetadata,
GroupPointer,
GroupMemberPointer,
TokenGroup,
TokenGroupMember,
}
impl From<ExtensionType> for UiExtensionType {
@ -747,6 +781,10 @@ impl From<ExtensionType> for UiExtensionType {
}
ExtensionType::MetadataPointer => UiExtensionType::MetadataPointer,
ExtensionType::TokenMetadata => UiExtensionType::TokenMetadata,
ExtensionType::GroupPointer => UiExtensionType::GroupPointer,
ExtensionType::GroupMemberPointer => UiExtensionType::GroupMemberPointer,
ExtensionType::TokenGroup => UiExtensionType::TokenGroup,
ExtensionType::TokenGroupMember => UiExtensionType::TokenGroupMember,
}
}
}

View File

@ -0,0 +1,189 @@
use {
super::*,
spl_token_2022::{
extension::group_member_pointer::instruction::*,
instruction::{decode_instruction_data, decode_instruction_type},
},
};
pub(in crate::parse_token) fn parse_group_member_pointer_instruction(
instruction_data: &[u8],
account_indexes: &[u8],
account_keys: &AccountKeys,
) -> Result<ParsedInstructionEnum, ParseInstructionError> {
match decode_instruction_type(instruction_data)
.map_err(|_| ParseInstructionError::InstructionNotParsable(ParsableProgram::SplToken))?
{
GroupMemberPointerInstruction::Initialize => {
check_num_token_accounts(account_indexes, 1)?;
let InitializeInstructionData {
authority,
member_address,
} = *decode_instruction_data(instruction_data).map_err(|_| {
ParseInstructionError::InstructionNotParsable(ParsableProgram::SplToken)
})?;
let mut value = json!({
"mint": account_keys[account_indexes[0] as usize].to_string(),
});
let map = value.as_object_mut().unwrap();
if let Some(authority) = Option::<Pubkey>::from(authority) {
map.insert("authority".to_string(), json!(authority.to_string()));
}
if let Some(member_address) = Option::<Pubkey>::from(member_address) {
map.insert(
"memberAddress".to_string(),
json!(member_address.to_string()),
);
}
Ok(ParsedInstructionEnum {
instruction_type: "initializeGroupMemberPointer".to_string(),
info: value,
})
}
GroupMemberPointerInstruction::Update => {
check_num_token_accounts(account_indexes, 2)?;
let UpdateInstructionData { member_address } =
*decode_instruction_data(instruction_data).map_err(|_| {
ParseInstructionError::InstructionNotParsable(ParsableProgram::SplToken)
})?;
let mut value = json!({
"mint": account_keys[account_indexes[0] as usize].to_string(),
});
let map = value.as_object_mut().unwrap();
if let Some(member_address) = Option::<Pubkey>::from(member_address) {
map.insert(
"memberAddress".to_string(),
json!(member_address.to_string()),
);
}
parse_signers(
map,
1,
account_keys,
account_indexes,
"authority",
"multisigAuthority",
);
Ok(ParsedInstructionEnum {
instruction_type: "updateGroupMemberPointer".to_string(),
info: value,
})
}
}
}
#[cfg(test)]
mod test {
use {super::*, solana_sdk::pubkey::Pubkey, spl_token_2022::solana_program::message::Message};
#[test]
fn test_parse_group_member_pointer_instruction() {
let mint_pubkey = Pubkey::new_unique();
let authority = Pubkey::new_unique();
let member_address = Pubkey::new_unique();
// Initialize variations
let init_ix = initialize(
&spl_token_2022::id(),
&mint_pubkey,
Some(authority),
Some(member_address),
)
.unwrap();
let mut message = Message::new(&[init_ix], None);
let compiled_instruction = &mut message.instructions[0];
assert_eq!(
parse_token(
compiled_instruction,
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "initializeGroupMemberPointer".to_string(),
info: json!({
"mint": mint_pubkey.to_string(),
"authority": authority.to_string(),
"memberAddress": member_address.to_string(),
})
}
);
let init_ix = initialize(&spl_token_2022::id(), &mint_pubkey, None, None).unwrap();
let mut message = Message::new(&[init_ix], None);
let compiled_instruction = &mut message.instructions[0];
assert_eq!(
parse_token(
compiled_instruction,
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "initializeGroupMemberPointer".to_string(),
info: json!({
"mint": mint_pubkey.to_string(),
})
}
);
// Single owner Update
let update_ix = update(
&spl_token_2022::id(),
&mint_pubkey,
&authority,
&[],
Some(member_address),
)
.unwrap();
let mut message = Message::new(&[update_ix], None);
let compiled_instruction = &mut message.instructions[0];
assert_eq!(
parse_token(
compiled_instruction,
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "updateGroupMemberPointer".to_string(),
info: json!({
"mint": mint_pubkey.to_string(),
"authority": authority.to_string(),
"memberAddress": member_address.to_string(),
})
}
);
// Multisig Update
let multisig_pubkey = Pubkey::new_unique();
let multisig_signer0 = Pubkey::new_unique();
let multisig_signer1 = Pubkey::new_unique();
let update_ix = update(
&spl_token_2022::id(),
&mint_pubkey,
&multisig_pubkey,
&[&multisig_signer0, &multisig_signer1],
Some(member_address),
)
.unwrap();
let mut message = Message::new(&[update_ix], None);
let compiled_instruction = &mut message.instructions[0];
assert_eq!(
parse_token(
compiled_instruction,
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "updateGroupMemberPointer".to_string(),
info: json!({
"mint": mint_pubkey.to_string(),
"memberAddress": member_address.to_string(),
"multisigAuthority": multisig_pubkey.to_string(),
"signers": vec![
multisig_signer0.to_string(),
multisig_signer1.to_string(),
],
})
}
);
}
}

View File

@ -0,0 +1,183 @@
use {
super::*,
spl_token_2022::{
extension::group_pointer::instruction::*,
instruction::{decode_instruction_data, decode_instruction_type},
},
};
pub(in crate::parse_token) fn parse_group_pointer_instruction(
instruction_data: &[u8],
account_indexes: &[u8],
account_keys: &AccountKeys,
) -> Result<ParsedInstructionEnum, ParseInstructionError> {
match decode_instruction_type(instruction_data)
.map_err(|_| ParseInstructionError::InstructionNotParsable(ParsableProgram::SplToken))?
{
GroupPointerInstruction::Initialize => {
check_num_token_accounts(account_indexes, 1)?;
let InitializeInstructionData {
authority,
group_address,
} = *decode_instruction_data(instruction_data).map_err(|_| {
ParseInstructionError::InstructionNotParsable(ParsableProgram::SplToken)
})?;
let mut value = json!({
"mint": account_keys[account_indexes[0] as usize].to_string(),
});
let map = value.as_object_mut().unwrap();
if let Some(authority) = Option::<Pubkey>::from(authority) {
map.insert("authority".to_string(), json!(authority.to_string()));
}
if let Some(group_address) = Option::<Pubkey>::from(group_address) {
map.insert("groupAddress".to_string(), json!(group_address.to_string()));
}
Ok(ParsedInstructionEnum {
instruction_type: "initializeGroupPointer".to_string(),
info: value,
})
}
GroupPointerInstruction::Update => {
check_num_token_accounts(account_indexes, 2)?;
let UpdateInstructionData { group_address } =
*decode_instruction_data(instruction_data).map_err(|_| {
ParseInstructionError::InstructionNotParsable(ParsableProgram::SplToken)
})?;
let mut value = json!({
"mint": account_keys[account_indexes[0] as usize].to_string(),
});
let map = value.as_object_mut().unwrap();
if let Some(group_address) = Option::<Pubkey>::from(group_address) {
map.insert("groupAddress".to_string(), json!(group_address.to_string()));
}
parse_signers(
map,
1,
account_keys,
account_indexes,
"authority",
"multisigAuthority",
);
Ok(ParsedInstructionEnum {
instruction_type: "updateGroupPointer".to_string(),
info: value,
})
}
}
}
#[cfg(test)]
mod test {
use {super::*, solana_sdk::pubkey::Pubkey, spl_token_2022::solana_program::message::Message};
#[test]
fn test_parse_group_pointer_instruction() {
let mint_pubkey = Pubkey::new_unique();
let authority = Pubkey::new_unique();
let group_address = Pubkey::new_unique();
// Initialize variations
let init_ix = initialize(
&spl_token_2022::id(),
&mint_pubkey,
Some(authority),
Some(group_address),
)
.unwrap();
let mut message = Message::new(&[init_ix], None);
let compiled_instruction = &mut message.instructions[0];
assert_eq!(
parse_token(
compiled_instruction,
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "initializeGroupPointer".to_string(),
info: json!({
"mint": mint_pubkey.to_string(),
"authority": authority.to_string(),
"groupAddress": group_address.to_string(),
})
}
);
let init_ix = initialize(&spl_token_2022::id(), &mint_pubkey, None, None).unwrap();
let mut message = Message::new(&[init_ix], None);
let compiled_instruction = &mut message.instructions[0];
assert_eq!(
parse_token(
compiled_instruction,
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "initializeGroupPointer".to_string(),
info: json!({
"mint": mint_pubkey.to_string(),
})
}
);
// Single owner Update
let update_ix = update(
&spl_token_2022::id(),
&mint_pubkey,
&authority,
&[],
Some(group_address),
)
.unwrap();
let mut message = Message::new(&[update_ix], None);
let compiled_instruction = &mut message.instructions[0];
assert_eq!(
parse_token(
compiled_instruction,
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "updateGroupPointer".to_string(),
info: json!({
"mint": mint_pubkey.to_string(),
"authority": authority.to_string(),
"groupAddress": group_address.to_string(),
})
}
);
// Multisig Update
let multisig_pubkey = Pubkey::new_unique();
let multisig_signer0 = Pubkey::new_unique();
let multisig_signer1 = Pubkey::new_unique();
let update_ix = update(
&spl_token_2022::id(),
&mint_pubkey,
&multisig_pubkey,
&[&multisig_signer0, &multisig_signer1],
Some(group_address),
)
.unwrap();
let mut message = Message::new(&[update_ix], None);
let compiled_instruction = &mut message.instructions[0];
assert_eq!(
parse_token(
compiled_instruction,
&AccountKeys::new(&message.account_keys, None)
)
.unwrap(),
ParsedInstructionEnum {
instruction_type: "updateGroupPointer".to_string(),
info: json!({
"mint": mint_pubkey.to_string(),
"groupAddress": group_address.to_string(),
"multisigAuthority": multisig_pubkey.to_string(),
"signers": vec![
multisig_signer0.to_string(),
multisig_signer1.to_string(),
],
})
}
);
}
}

View File

@ -4,6 +4,8 @@ pub(super) mod confidential_transfer;
pub(super) mod confidential_transfer_fee;
pub(super) mod cpi_guard;
pub(super) mod default_account_state;
pub(super) mod group_member_pointer;
pub(super) mod group_pointer;
pub(super) mod interest_bearing_mint;
pub(super) mod memo_transfer;
pub(super) mod metadata_pointer;