Skip to content
This repository was archived by the owner on Jan 22, 2025. It is now read-only.

Commit 1526c74

Browse files
v1.16: spl: Bump token-2022 and friends (backport of #33453) (#33465)
* spl: Bump token-2022 and friends (#33453) * token: Update to 4.0.0 * token-2022: Bump and support new account and instruction types * Update token-2022 in fetch_spl / program-test * Fixup downstream uses * Mint and destination were flipped in 0.9.0 * Don't use `convert_pubkey` * Bump spl dependencies to versions which avoid recompilations (cherry picked from commit de38b05) # Conflicts: # Cargo.lock # Cargo.toml # account-decoder/Cargo.toml # programs/sbf/Cargo.lock * Fix toml conflicts * Update lockfiles * Bump proc-macro2 down to 1.0.60, lowest compatible version * Bump down hashbrown used by borsh --------- Co-authored-by: Jon Cinque <[email protected]>
1 parent d5adf45 commit 1526c74

23 files changed

+1370
-313
lines changed

Cargo.lock

Lines changed: 258 additions & 88 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -359,11 +359,13 @@ solana-vote-program = { path = "programs/vote", version = "=1.16.16" }
359359
solana-zk-keygen = { path = "zk-keygen", version = "=1.16.16" }
360360
solana-zk-token-proof-program = { path = "programs/zk-token-proof", version = "=1.16.16" }
361361
solana-zk-token-sdk = { path = "zk-token-sdk", version = "=1.16.16" }
362-
spl-associated-token-account = "=1.1.3"
362+
spl-associated-token-account = "=2.2.0"
363363
spl-instruction-padding = "0.1"
364-
spl-memo = "=3.0.1"
365-
spl-token = "=3.5.0"
366-
spl-token-2022 = "=0.6.1"
364+
spl-memo = "=4.0.0"
365+
spl-pod = "=0.1.0"
366+
spl-token = "=4.0.0"
367+
spl-token-2022 = "=0.9.0"
368+
spl-token-metadata-interface = "=0.2.0"
367369
static_assertions = "1.1.0"
368370
stream-cancel = "0.8.1"
369371
strum = "0.24"
@@ -413,8 +415,10 @@ ntapi = { git = "https://github.com/solana-labs/ntapi", rev = "97ede981a1777883f
413415
# * spl-associated-token-account
414416
# * spl-instruction-padding
415417
# * spl-memo
418+
# * spl-pod
416419
# * spl-token
417420
# * spl-token-2022
421+
# * spl-token-metadata-interface
418422
#
419423
# They, in turn, depend on a number of crates that we also include directly using `path`
420424
# specifications. For example, `spl-token` depends on `solana-program`. And we explicitly specify

account-decoder/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,12 @@ solana-config-program = { workspace = true }
2424
solana-sdk = { workspace = true }
2525
spl-token = { workspace = true, features = ["no-entrypoint"] }
2626
spl-token-2022 = { workspace = true, features = ["no-entrypoint"] }
27+
spl-token-metadata-interface = { workspace = true }
2728
thiserror = { workspace = true }
2829
zstd = { workspace = true }
2930

31+
[dev-dependencies]
32+
spl-pod = { workspace = true }
33+
3034
[package.metadata.docs.rs]
3135
targets = ["x86_64-unknown-linux-gnu"]

account-decoder/src/parse_token.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -290,12 +290,10 @@ mod test {
290290
use {
291291
super::*,
292292
crate::parse_token_extension::{UiMemoTransfer, UiMintCloseAuthority},
293-
spl_token_2022::{
294-
extension::{
295-
immutable_owner::ImmutableOwner, memo_transfer::MemoTransfer,
296-
mint_close_authority::MintCloseAuthority, ExtensionType, StateWithExtensionsMut,
297-
},
298-
pod::OptionalNonZeroPubkey,
293+
spl_pod::optional_keys::OptionalNonZeroPubkey,
294+
spl_token_2022::extension::{
295+
immutable_owner::ImmutableOwner, memo_transfer::MemoTransfer,
296+
mint_close_authority::MintCloseAuthority, ExtensionType, StateWithExtensionsMut,
299297
},
300298
};
301299

@@ -506,10 +504,11 @@ mod test {
506504
delegate: COption::None,
507505
delegated_amount: 0,
508506
};
509-
let account_size = ExtensionType::get_account_len::<Account>(&[
507+
let account_size = ExtensionType::try_calculate_account_len::<Account>(&[
510508
ExtensionType::ImmutableOwner,
511509
ExtensionType::MemoTransfer,
512-
]);
510+
])
511+
.unwrap();
513512
let mut account_data = vec![0; account_size];
514513
let mut account_state =
515514
StateWithExtensionsMut::<Account>::unpack_uninitialized(&mut account_data).unwrap();
@@ -586,7 +585,8 @@ mod test {
586585
fn test_parse_token_mint_with_extensions() {
587586
let owner_pubkey = SplTokenPubkey::new_from_array([3; 32]);
588587
let mint_size =
589-
ExtensionType::get_account_len::<Mint>(&[ExtensionType::MintCloseAuthority]);
588+
ExtensionType::try_calculate_account_len::<Mint>(&[ExtensionType::MintCloseAuthority])
589+
.unwrap();
590590
let mint_base = Mint {
591591
mint_authority: COption::Some(owner_pubkey),
592592
supply: 42,

account-decoder/src/parse_token_extension.rs

Lines changed: 164 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use {
66
solana_program::pubkey::Pubkey,
77
solana_zk_token_sdk::zk_token_elgamal::pod::ElGamalPubkey,
88
},
9+
spl_token_metadata_interface::state::TokenMetadata,
910
};
1011

1112
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
@@ -24,15 +25,21 @@ pub enum UiExtension {
2425
InterestBearingConfig(UiInterestBearingConfig),
2526
CpiGuard(UiCpiGuard),
2627
PermanentDelegate(UiPermanentDelegate),
27-
UnparseableExtension,
2828
NonTransferableAccount,
29+
ConfidentialTransferFeeConfig(UiConfidentialTransferFeeConfig),
30+
ConfidentialTransferFeeAmount(UiConfidentialTransferFeeAmount),
31+
TransferHook(UiTransferHook),
32+
TransferHookAccount(UiTransferHookAccount),
33+
MetadataPointer(UiMetadataPointer),
34+
TokenMetadata(UiTokenMetadata),
35+
UnparseableExtension,
2936
}
3037

3138
pub fn parse_extension<S: BaseState>(
3239
extension_type: &ExtensionType,
3340
account: &StateWithExtensions<S>,
3441
) -> UiExtension {
35-
match &extension_type {
42+
match extension_type {
3643
ExtensionType::Uninitialized => UiExtension::Uninitialized,
3744
ExtensionType::TransferFeeConfig => account
3845
.get_extension::<extension::transfer_fee::TransferFeeConfig>()
@@ -50,10 +57,18 @@ pub fn parse_extension<S: BaseState>(
5057
.get_extension::<extension::confidential_transfer::ConfidentialTransferMint>()
5158
.map(|&extension| UiExtension::ConfidentialTransferMint(extension.into()))
5259
.unwrap_or(UiExtension::UnparseableExtension),
60+
ExtensionType::ConfidentialTransferFeeConfig => account
61+
.get_extension::<extension::confidential_transfer_fee::ConfidentialTransferFeeConfig>()
62+
.map(|&extension| UiExtension::ConfidentialTransferFeeConfig(extension.into()))
63+
.unwrap_or(UiExtension::UnparseableExtension),
5364
ExtensionType::ConfidentialTransferAccount => account
5465
.get_extension::<extension::confidential_transfer::ConfidentialTransferAccount>()
5566
.map(|&extension| UiExtension::ConfidentialTransferAccount(extension.into()))
5667
.unwrap_or(UiExtension::UnparseableExtension),
68+
ExtensionType::ConfidentialTransferFeeAmount => account
69+
.get_extension::<extension::confidential_transfer_fee::ConfidentialTransferFeeAmount>()
70+
.map(|&extension| UiExtension::ConfidentialTransferFeeAmount(extension.into()))
71+
.unwrap_or(UiExtension::UnparseableExtension),
5772
ExtensionType::DefaultAccountState => account
5873
.get_extension::<extension::default_account_state::DefaultAccountState>()
5974
.map(|&extension| UiExtension::DefaultAccountState(extension.into()))
@@ -77,6 +92,22 @@ pub fn parse_extension<S: BaseState>(
7792
.map(|&extension| UiExtension::PermanentDelegate(extension.into()))
7893
.unwrap_or(UiExtension::UnparseableExtension),
7994
ExtensionType::NonTransferableAccount => UiExtension::NonTransferableAccount,
95+
ExtensionType::MetadataPointer => account
96+
.get_extension::<extension::metadata_pointer::MetadataPointer>()
97+
.map(|&extension| UiExtension::MetadataPointer(extension.into()))
98+
.unwrap_or(UiExtension::UnparseableExtension),
99+
ExtensionType::TokenMetadata => account
100+
.get_variable_len_extension::<TokenMetadata>()
101+
.map(|extension| UiExtension::TokenMetadata(extension.into()))
102+
.unwrap_or(UiExtension::UnparseableExtension),
103+
ExtensionType::TransferHook => account
104+
.get_extension::<extension::transfer_hook::TransferHook>()
105+
.map(|&extension| UiExtension::TransferHook(extension.into()))
106+
.unwrap_or(UiExtension::UnparseableExtension),
107+
ExtensionType::TransferHookAccount => account
108+
.get_extension::<extension::transfer_hook::TransferHookAccount>()
109+
.map(|&extension| UiExtension::TransferHookAccount(extension.into()))
110+
.unwrap_or(UiExtension::UnparseableExtension),
80111
}
81112
}
82113

@@ -251,9 +282,7 @@ impl From<extension::permanent_delegate::PermanentDelegate> for UiPermanentDeleg
251282
pub struct UiConfidentialTransferMint {
252283
pub authority: Option<String>,
253284
pub auto_approve_new_accounts: bool,
254-
pub auditor_encryption_pubkey: Option<String>,
255-
pub withdraw_withheld_authority_encryption_pubkey: Option<String>,
256-
pub withheld_amount: String,
285+
pub auditor_elgamal_pubkey: Option<String>,
257286
}
258287

259288
impl From<extension::confidential_transfer::ConfidentialTransferMint>
@@ -263,19 +292,44 @@ impl From<extension::confidential_transfer::ConfidentialTransferMint>
263292
confidential_transfer_mint: extension::confidential_transfer::ConfidentialTransferMint,
264293
) -> Self {
265294
let authority: Option<Pubkey> = confidential_transfer_mint.authority.into();
266-
let auditor_encryption_pubkey: Option<ElGamalPubkey> =
267-
confidential_transfer_mint.auditor_encryption_pubkey.into();
268-
let withdraw_withheld_authority_encryption_pubkey: Option<ElGamalPubkey> =
269-
confidential_transfer_mint
270-
.withdraw_withheld_authority_encryption_pubkey
271-
.into();
295+
let auditor_elgamal_pubkey: Option<ElGamalPubkey> =
296+
confidential_transfer_mint.auditor_elgamal_pubkey.into();
272297
Self {
273298
authority: authority.map(|pubkey| pubkey.to_string()),
274299
auto_approve_new_accounts: confidential_transfer_mint.auto_approve_new_accounts.into(),
275-
auditor_encryption_pubkey: auditor_encryption_pubkey.map(|pubkey| pubkey.to_string()),
276-
withdraw_withheld_authority_encryption_pubkey:
277-
withdraw_withheld_authority_encryption_pubkey.map(|pubkey| pubkey.to_string()),
278-
withheld_amount: format!("{}", confidential_transfer_mint.withheld_amount),
300+
auditor_elgamal_pubkey: auditor_elgamal_pubkey.map(|pubkey| pubkey.to_string()),
301+
}
302+
}
303+
}
304+
305+
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
306+
#[serde(rename_all = "camelCase")]
307+
pub struct UiConfidentialTransferFeeConfig {
308+
pub authority: Option<String>,
309+
pub withdraw_withheld_authority_elgamal_pubkey: Option<String>,
310+
pub harvest_to_mint_enabled: bool,
311+
pub withheld_amount: String,
312+
}
313+
314+
impl From<extension::confidential_transfer_fee::ConfidentialTransferFeeConfig>
315+
for UiConfidentialTransferFeeConfig
316+
{
317+
fn from(
318+
confidential_transfer_fee_config: extension::confidential_transfer_fee::ConfidentialTransferFeeConfig,
319+
) -> Self {
320+
let authority: Option<Pubkey> = confidential_transfer_fee_config.authority.into();
321+
let withdraw_withheld_authority_elgamal_pubkey: Option<ElGamalPubkey> =
322+
confidential_transfer_fee_config
323+
.withdraw_withheld_authority_elgamal_pubkey
324+
.into();
325+
Self {
326+
authority: authority.map(|pubkey| pubkey.to_string()),
327+
withdraw_withheld_authority_elgamal_pubkey: withdraw_withheld_authority_elgamal_pubkey
328+
.map(|pubkey| pubkey.to_string()),
329+
harvest_to_mint_enabled: confidential_transfer_fee_config
330+
.harvest_to_mint_enabled
331+
.into(),
332+
withheld_amount: format!("{}", confidential_transfer_fee_config.withheld_amount),
279333
}
280334
}
281335
}
@@ -284,7 +338,7 @@ impl From<extension::confidential_transfer::ConfidentialTransferMint>
284338
#[serde(rename_all = "camelCase")]
285339
pub struct UiConfidentialTransferAccount {
286340
pub approved: bool,
287-
pub encryption_pubkey: String,
341+
pub elgamal_pubkey: String,
288342
pub pending_balance_lo: String,
289343
pub pending_balance_hi: String,
290344
pub available_balance: String,
@@ -295,7 +349,6 @@ pub struct UiConfidentialTransferAccount {
295349
pub maximum_pending_balance_credit_counter: u64,
296350
pub expected_pending_balance_credit_counter: u64,
297351
pub actual_pending_balance_credit_counter: u64,
298-
pub withheld_amount: String,
299352
}
300353

301354
impl From<extension::confidential_transfer::ConfidentialTransferAccount>
@@ -306,7 +359,7 @@ impl From<extension::confidential_transfer::ConfidentialTransferAccount>
306359
) -> Self {
307360
Self {
308361
approved: confidential_transfer_account.approved.into(),
309-
encryption_pubkey: format!("{}", confidential_transfer_account.encryption_pubkey),
362+
elgamal_pubkey: format!("{}", confidential_transfer_account.elgamal_pubkey),
310363
pending_balance_lo: format!("{}", confidential_transfer_account.pending_balance_lo),
311364
pending_balance_hi: format!("{}", confidential_transfer_account.pending_balance_hi),
312365
available_balance: format!("{}", confidential_transfer_account.available_balance),
@@ -332,7 +385,99 @@ impl From<extension::confidential_transfer::ConfidentialTransferAccount>
332385
actual_pending_balance_credit_counter: confidential_transfer_account
333386
.actual_pending_balance_credit_counter
334387
.into(),
335-
withheld_amount: format!("{}", confidential_transfer_account.withheld_amount),
388+
}
389+
}
390+
}
391+
392+
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
393+
#[serde(rename_all = "camelCase")]
394+
pub struct UiConfidentialTransferFeeAmount {
395+
pub withheld_amount: String,
396+
}
397+
398+
impl From<extension::confidential_transfer_fee::ConfidentialTransferFeeAmount>
399+
for UiConfidentialTransferFeeAmount
400+
{
401+
fn from(
402+
confidential_transfer_fee_amount: extension::confidential_transfer_fee::ConfidentialTransferFeeAmount,
403+
) -> Self {
404+
Self {
405+
withheld_amount: format!("{}", confidential_transfer_fee_amount.withheld_amount),
406+
}
407+
}
408+
}
409+
410+
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
411+
#[serde(rename_all = "camelCase")]
412+
pub struct UiMetadataPointer {
413+
pub authority: Option<String>,
414+
pub metadata_address: Option<String>,
415+
}
416+
417+
impl From<extension::metadata_pointer::MetadataPointer> for UiMetadataPointer {
418+
fn from(metadata_pointer: extension::metadata_pointer::MetadataPointer) -> Self {
419+
let authority: Option<Pubkey> = metadata_pointer.authority.into();
420+
let metadata_address: Option<Pubkey> = metadata_pointer.metadata_address.into();
421+
Self {
422+
authority: authority.map(|pubkey| pubkey.to_string()),
423+
metadata_address: metadata_address.map(|pubkey| pubkey.to_string()),
424+
}
425+
}
426+
}
427+
428+
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
429+
#[serde(rename_all = "camelCase")]
430+
pub struct UiTokenMetadata {
431+
pub update_authority: Option<String>,
432+
pub mint: String,
433+
pub name: String,
434+
pub symbol: String,
435+
pub uri: String,
436+
pub additional_metadata: Vec<(String, String)>,
437+
}
438+
439+
impl From<TokenMetadata> for UiTokenMetadata {
440+
fn from(token_metadata: TokenMetadata) -> Self {
441+
let update_authority: Option<Pubkey> = token_metadata.update_authority.into();
442+
Self {
443+
update_authority: update_authority.map(|pubkey| pubkey.to_string()),
444+
mint: token_metadata.mint.to_string(),
445+
name: token_metadata.name,
446+
symbol: token_metadata.symbol,
447+
uri: token_metadata.uri,
448+
additional_metadata: token_metadata.additional_metadata,
449+
}
450+
}
451+
}
452+
453+
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
454+
#[serde(rename_all = "camelCase")]
455+
pub struct UiTransferHook {
456+
pub authority: Option<String>,
457+
pub program_id: Option<String>,
458+
}
459+
460+
impl From<extension::transfer_hook::TransferHook> for UiTransferHook {
461+
fn from(transfer_hook: extension::transfer_hook::TransferHook) -> Self {
462+
let authority: Option<Pubkey> = transfer_hook.authority.into();
463+
let program_id: Option<Pubkey> = transfer_hook.program_id.into();
464+
Self {
465+
authority: authority.map(|pubkey| pubkey.to_string()),
466+
program_id: program_id.map(|pubkey| pubkey.to_string()),
467+
}
468+
}
469+
}
470+
471+
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
472+
#[serde(rename_all = "camelCase")]
473+
pub struct UiTransferHookAccount {
474+
pub transferring: bool,
475+
}
476+
477+
impl From<extension::transfer_hook::TransferHookAccount> for UiTransferHookAccount {
478+
fn from(transfer_hook: extension::transfer_hook::TransferHookAccount) -> Self {
479+
Self {
480+
transferring: transfer_hook.transferring.into(),
336481
}
337482
}
338483
}

fetch-spl.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ fetch_program() {
4545
}
4646

4747
fetch_program token 3.5.0 TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA BPFLoader2111111111111111111111111111111111
48-
fetch_program token-2022 0.6.0 TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb BPFLoaderUpgradeab1e11111111111111111111111
48+
fetch_program token-2022 0.9.0 TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb BPFLoaderUpgradeab1e11111111111111111111111
4949
fetch_program memo 1.0.0 Memo1UhkJRfHyvLMcVucJwxXeuD728EqVDDwQDxFMNo BPFLoader1111111111111111111111111111111111
5050
fetch_program memo 3.0.0 MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr BPFLoader2111111111111111111111111111111111
5151
fetch_program associated-token-account 1.1.2 ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL BPFLoader2111111111111111111111111111111111

ledger/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ bs58 = { workspace = true }
7474
matches = { workspace = true }
7575
solana-account-decoder = { workspace = true }
7676
solana-logger = { workspace = true }
77+
spl-pod = { workspace = true }
7778
test-case = { workspace = true }
7879

7980
[build-dependencies]

0 commit comments

Comments
 (0)