gmsol/utils/workarounds/optional.rs
1use anchor_client::{
2 anchor_lang::ToAccountMetas,
3 solana_sdk::{instruction::AccountMeta, pubkey::Pubkey},
4};
5
6/// Change the `pubkey` of any readonly, non-signer [`AccountMeta`]
7/// with the `pubkey` equal to the original program id to the new one.
8///
9/// This is a workaround since Anchor will automatically set optional accounts
10/// to the Program ID of the program that defines them when they are `None`s,
11/// if we use the same program but with different Program IDs, the optional
12/// accounts will be set to the wrong addresses.
13///
14/// ## Warning
15/// Use this function only if you fully understand the implications.
16pub fn fix_optional_account_metas(
17 accounts: impl ToAccountMetas,
18 original: &Pubkey,
19 current: &Pubkey,
20) -> Vec<AccountMeta> {
21 let mut metas = accounts.to_account_metas(None);
22 if *original == *current {
23 // No-op in this case.
24 return metas;
25 }
26 metas.iter_mut().for_each(|meta| {
27 if !meta.is_signer && !meta.is_writable && meta.pubkey == *original {
28 // We consider it a `None` account. If it is not, please do not use this function.
29 meta.pubkey = *current;
30 }
31 });
32 metas
33}