Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Update External Plugins IX #91

Merged
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,12 @@ export type UpdateCollectionExternalPluginV1InstructionAccounts = {
// Data.
export type UpdateCollectionExternalPluginV1InstructionData = {
discriminator: number;
pluginKey: BaseExternalPluginKey;
key: BaseExternalPluginKey;
updateInfo: BaseExternalPluginUpdateInfo;
};

export type UpdateCollectionExternalPluginV1InstructionDataArgs = {
pluginKey: BaseExternalPluginKeyArgs;
key: BaseExternalPluginKeyArgs;
updateInfo: BaseExternalPluginUpdateInfoArgs;
};

Expand All @@ -72,7 +72,7 @@ export function getUpdateCollectionExternalPluginV1InstructionDataSerializer():
struct<UpdateCollectionExternalPluginV1InstructionData>(
[
['discriminator', u8()],
['pluginKey', getBaseExternalPluginKeySerializer()],
['key', getBaseExternalPluginKeySerializer()],
['updateInfo', getBaseExternalPluginUpdateInfoSerializer()],
],
{ description: 'UpdateCollectionExternalPluginV1InstructionData' }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ impl UpdateCollectionExternalPluginV1InstructionData {
#[derive(BorshSerialize, BorshDeserialize, Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct UpdateCollectionExternalPluginV1InstructionArgs {
pub plugin_key: ExternalPluginKey,
pub key: ExternalPluginKey,
pub update_info: ExternalPluginUpdateInfo,
}

Expand All @@ -119,7 +119,7 @@ pub struct UpdateCollectionExternalPluginV1Builder {
authority: Option<solana_program::pubkey::Pubkey>,
system_program: Option<solana_program::pubkey::Pubkey>,
log_wrapper: Option<solana_program::pubkey::Pubkey>,
plugin_key: Option<ExternalPluginKey>,
key: Option<ExternalPluginKey>,
update_info: Option<ExternalPluginUpdateInfo>,
__remaining_accounts: Vec<solana_program::instruction::AccountMeta>,
}
Expand Down Expand Up @@ -165,8 +165,8 @@ impl UpdateCollectionExternalPluginV1Builder {
self
}
#[inline(always)]
pub fn plugin_key(&mut self, plugin_key: ExternalPluginKey) -> &mut Self {
self.plugin_key = Some(plugin_key);
pub fn key(&mut self, key: ExternalPluginKey) -> &mut Self {
self.key = Some(key);
self
}
#[inline(always)]
Expand Down Expand Up @@ -204,7 +204,7 @@ impl UpdateCollectionExternalPluginV1Builder {
log_wrapper: self.log_wrapper,
};
let args = UpdateCollectionExternalPluginV1InstructionArgs {
plugin_key: self.plugin_key.clone().expect("plugin_key is not set"),
key: self.key.clone().expect("key is not set"),
update_info: self.update_info.clone().expect("update_info is not set"),
};

Expand Down Expand Up @@ -391,7 +391,7 @@ impl<'a, 'b> UpdateCollectionExternalPluginV1CpiBuilder<'a, 'b> {
authority: None,
system_program: None,
log_wrapper: None,
plugin_key: None,
key: None,
update_info: None,
__remaining_accounts: Vec::new(),
});
Expand Down Expand Up @@ -442,8 +442,8 @@ impl<'a, 'b> UpdateCollectionExternalPluginV1CpiBuilder<'a, 'b> {
self
}
#[inline(always)]
pub fn plugin_key(&mut self, plugin_key: ExternalPluginKey) -> &mut Self {
self.instruction.plugin_key = Some(plugin_key);
pub fn key(&mut self, key: ExternalPluginKey) -> &mut Self {
self.instruction.key = Some(key);
self
}
#[inline(always)]
Expand Down Expand Up @@ -493,11 +493,7 @@ impl<'a, 'b> UpdateCollectionExternalPluginV1CpiBuilder<'a, 'b> {
signers_seeds: &[&[&[u8]]],
) -> solana_program::entrypoint::ProgramResult {
let args = UpdateCollectionExternalPluginV1InstructionArgs {
plugin_key: self
.instruction
.plugin_key
.clone()
.expect("plugin_key is not set"),
key: self.instruction.key.clone().expect("key is not set"),
update_info: self
.instruction
.update_info
Expand Down Expand Up @@ -535,7 +531,7 @@ struct UpdateCollectionExternalPluginV1CpiBuilderInstruction<'a, 'b> {
authority: Option<&'b solana_program::account_info::AccountInfo<'a>>,
system_program: Option<&'b solana_program::account_info::AccountInfo<'a>>,
log_wrapper: Option<&'b solana_program::account_info::AccountInfo<'a>>,
plugin_key: Option<ExternalPluginKey>,
key: Option<ExternalPluginKey>,
update_info: Option<ExternalPluginUpdateInfo>,
/// Additional instruction accounts `(AccountInfo, is_writable, is_signer)`.
__remaining_accounts: Vec<(
Expand Down
295 changes: 295 additions & 0 deletions clients/rust/tests/update_external_plugins.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,295 @@
#![cfg(feature = "test-sbf")]
pub mod setup;
use mpl_core::{
instructions::UpdateExternalPluginV1Builder,
types::{
DataStore, DataStoreInitInfo, DataStoreUpdateInfo, ExternalCheckResult, ExternalPlugin,
ExternalPluginInitInfo, ExternalPluginKey, ExternalPluginSchema, ExternalPluginUpdateInfo,
HookableLifecycleEvent, LifecycleHook, LifecycleHookInitInfo, LifecycleHookUpdateInfo,
Oracle, OracleInitInfo, OracleUpdateInfo, PluginAuthority, UpdateAuthority,
ValidationResultsOffset,
},
};
pub use setup::*;

use solana_program::pubkey;
use solana_program_test::tokio;
use solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer, transaction::Transaction};

#[tokio::test]
async fn test_update_lifecycle_hook() {
let mut context = program_test().start_with_context().await;

let asset = Keypair::new();
create_asset(
&mut context,
CreateAssetHelperArgs {
owner: None,
payer: None,
asset: &asset,
data_state: None,
name: None,
uri: None,
authority: None,
update_authority: None,
collection: None,
plugins: vec![],
external_plugins: vec![ExternalPluginInitInfo::LifecycleHook(
LifecycleHookInitInfo {
hooked_program: pubkey!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),
init_plugin_authority: Some(PluginAuthority::UpdateAuthority),
lifecycle_checks: Some(vec![(
HookableLifecycleEvent::Transfer,
ExternalCheckResult { flags: 1 },
)]),
extra_accounts: None,
data_authority: Some(PluginAuthority::UpdateAuthority),
schema: None,
},
)],
},
)
.await
.unwrap();

let owner = context.payer.pubkey();
let update_authority = context.payer.pubkey();
assert_asset(
&mut context,
AssertAssetHelperArgs {
asset: asset.pubkey(),
owner,
update_authority: Some(UpdateAuthority::Address(update_authority)),
name: None,
uri: None,
plugins: vec![],
external_plugins: vec![ExternalPlugin::LifecycleHook(LifecycleHook {
hooked_program: pubkey!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),
extra_accounts: None,
data_authority: Some(PluginAuthority::UpdateAuthority),
schema: ExternalPluginSchema::Binary,
})],
},
)
.await;

let ix = UpdateExternalPluginV1Builder::new()
.asset(asset.pubkey())
.payer(context.payer.pubkey())
.key(ExternalPluginKey::LifecycleHook(pubkey!(
"MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"
)))
.update_info(ExternalPluginUpdateInfo::LifecycleHook(
LifecycleHookUpdateInfo {
lifecycle_checks: None,
extra_accounts: None,
schema: Some(ExternalPluginSchema::Json),
},
))
.instruction();

let tx = Transaction::new_signed_with_payer(
&[ix],
Some(&context.payer.pubkey()),
&[&context.payer],
context.last_blockhash,
);

context.banks_client.process_transaction(tx).await.unwrap();

assert_asset(
&mut context,
AssertAssetHelperArgs {
asset: asset.pubkey(),
owner,
update_authority: Some(UpdateAuthority::Address(update_authority)),
name: None,
uri: None,
plugins: vec![],
external_plugins: vec![ExternalPlugin::LifecycleHook(LifecycleHook {
hooked_program: pubkey!("MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr"),
extra_accounts: None,
data_authority: Some(PluginAuthority::UpdateAuthority),
schema: ExternalPluginSchema::Json,
})],
},
)
.await;
}

#[tokio::test]
async fn test_update_oracle() {
let mut context = program_test().start_with_context().await;

let asset = Keypair::new();
create_asset(
&mut context,
CreateAssetHelperArgs {
owner: None,
payer: None,
asset: &asset,
data_state: None,
name: None,
uri: None,
authority: None,
update_authority: None,
collection: None,
plugins: vec![],
external_plugins: vec![ExternalPluginInitInfo::Oracle(OracleInitInfo {
base_address: Pubkey::default(),
init_plugin_authority: Some(PluginAuthority::UpdateAuthority),
lifecycle_checks: Some(vec![(
HookableLifecycleEvent::Transfer,
ExternalCheckResult { flags: 1 },
)]),
pda: None,
results_offset: None,
})],
},
)
.await
.unwrap();

let owner = context.payer.pubkey();
let update_authority = context.payer.pubkey();
assert_asset(
&mut context,
AssertAssetHelperArgs {
asset: asset.pubkey(),
owner,
update_authority: Some(UpdateAuthority::Address(update_authority)),
name: None,
uri: None,
plugins: vec![],
external_plugins: vec![ExternalPlugin::Oracle(Oracle {
base_address: Pubkey::default(),
pda: None,
results_offset: ValidationResultsOffset::NoOffset,
})],
},
)
.await;

let ix = UpdateExternalPluginV1Builder::new()
.asset(asset.pubkey())
.payer(context.payer.pubkey())
.key(ExternalPluginKey::Oracle(Pubkey::default()))
.update_info(ExternalPluginUpdateInfo::Oracle(OracleUpdateInfo {
lifecycle_checks: None,
pda: None,
results_offset: Some(ValidationResultsOffset::Custom(10)),
}))
.instruction();

let tx = Transaction::new_signed_with_payer(
&[ix],
Some(&context.payer.pubkey()),
&[&context.payer],
context.last_blockhash,
);

context.banks_client.process_transaction(tx).await.unwrap();

assert_asset(
&mut context,
AssertAssetHelperArgs {
asset: asset.pubkey(),
owner,
update_authority: Some(UpdateAuthority::Address(update_authority)),
name: None,
uri: None,
plugins: vec![],
external_plugins: vec![ExternalPlugin::Oracle(Oracle {
base_address: Pubkey::default(),
pda: None,
results_offset: ValidationResultsOffset::Custom(10),
})],
},
)
.await;
}

#[tokio::test]
async fn test_update_data_store() {
let mut context = program_test().start_with_context().await;

let asset = Keypair::new();
create_asset(
&mut context,
CreateAssetHelperArgs {
owner: None,
payer: None,
asset: &asset,
data_state: None,
name: None,
uri: None,
authority: None,
update_authority: None,
collection: None,
plugins: vec![],
external_plugins: vec![ExternalPluginInitInfo::DataStore(DataStoreInitInfo {
init_plugin_authority: Some(PluginAuthority::UpdateAuthority),
data_authority: PluginAuthority::UpdateAuthority,
schema: None,
})],
},
)
.await
.unwrap();

let owner = context.payer.pubkey();
let update_authority = context.payer.pubkey();
assert_asset(
&mut context,
AssertAssetHelperArgs {
asset: asset.pubkey(),
owner,
update_authority: Some(UpdateAuthority::Address(update_authority)),
name: None,
uri: None,
plugins: vec![],
external_plugins: vec![ExternalPlugin::DataStore(DataStore {
data_authority: PluginAuthority::UpdateAuthority,
schema: ExternalPluginSchema::Binary,
})],
},
)
.await;

let ix = UpdateExternalPluginV1Builder::new()
.asset(asset.pubkey())
.payer(context.payer.pubkey())
.key(ExternalPluginKey::DataStore(
PluginAuthority::UpdateAuthority,
))
.update_info(ExternalPluginUpdateInfo::DataStore(DataStoreUpdateInfo {
schema: Some(ExternalPluginSchema::Json),
}))
.instruction();

let tx = Transaction::new_signed_with_payer(
&[ix],
Some(&context.payer.pubkey()),
&[&context.payer],
context.last_blockhash,
);

context.banks_client.process_transaction(tx).await.unwrap();

assert_asset(
&mut context,
AssertAssetHelperArgs {
asset: asset.pubkey(),
owner,
update_authority: Some(UpdateAuthority::Address(update_authority)),
name: None,
uri: None,
plugins: vec![],
external_plugins: vec![ExternalPlugin::DataStore(DataStore {
data_authority: PluginAuthority::UpdateAuthority,
schema: ExternalPluginSchema::Json,
})],
},
)
.await;
}
Loading