From 1ab3a6f344857051d6443c7bcdfa7a7285df77b3 Mon Sep 17 00:00:00 2001 From: CanvasL <746591811@qq.com> Date: Fri, 27 Sep 2024 22:50:27 +0800 Subject: [PATCH] feat: initialize --- .../puppet/programs/puppet/src/constants.rs | 1 - .../programs/puppet/src/instructions/bind.rs | 7 +- .../src/instructions/bind_collection.rs | 10 ++- .../puppet/src/instructions/initialize.rs | 30 ++++++++ .../programs/puppet/src/instructions/mod.rs | 2 + extensions/puppet/programs/puppet/src/lib.rs | 4 ++ .../programs/puppet/src/state/global.rs | 7 ++ .../puppet/programs/puppet/src/state/mod.rs | 2 + extensions/puppet/tests/puppet.ts | 70 +++++++++++++------ 9 files changed, 102 insertions(+), 31 deletions(-) create mode 100644 extensions/puppet/programs/puppet/src/instructions/initialize.rs create mode 100644 extensions/puppet/programs/puppet/src/state/global.rs diff --git a/extensions/puppet/programs/puppet/src/constants.rs b/extensions/puppet/programs/puppet/src/constants.rs index 5195d14..543be25 100644 --- a/extensions/puppet/programs/puppet/src/constants.rs +++ b/extensions/puppet/programs/puppet/src/constants.rs @@ -1,6 +1,5 @@ use anchor_lang::prelude::Pubkey; -pub const DEPHY_ID_PROGRAM: Pubkey = Pubkey::new_from_array([10u8, 104u8, 87u8, 71u8, 135u8, 225u8, 232u8, 69u8, 21u8, 185u8, 195u8, 236u8, 216u8, 23u8, 119u8, 79u8, 176u8, 27u8, 100u8, 193u8, 237u8, 38u8, 213u8, 50u8, 121u8, 184u8, 103u8, 109u8, 227u8, 77u8, 99u8, 44u8]); pub const SPL_2022_PROGRAM: Pubkey = Pubkey::new_from_array([6u8, 221u8, 246u8, 225u8, 238u8, 117u8, 143u8, 222u8, 24u8, 66u8, 93u8, 188u8, 228u8, 108u8, 205u8, 218u8, 182u8, 26u8, 252u8, 77u8, 131u8, 185u8, 13u8, 39u8, 254u8, 189u8, 249u8, 40u8, 216u8, 161u8, 139u8, 252u8]); pub const PRODUCT_MINT_SEED_PREFIX: &[u8; 16] = b"DePHY_ID-PRODUCT"; pub const DEVICE_MINT_SEED_PREFIX: &[u8; 15] = b"DePHY_ID-DEVICE"; diff --git a/extensions/puppet/programs/puppet/src/instructions/bind.rs b/extensions/puppet/programs/puppet/src/instructions/bind.rs index 6b382bc..af40cac 100644 --- a/extensions/puppet/programs/puppet/src/instructions/bind.rs +++ b/extensions/puppet/programs/puppet/src/instructions/bind.rs @@ -1,6 +1,6 @@ -use crate::constants::{DEVICE_MINT_SEED_PREFIX, DEPHY_ID_PROGRAM, SPL_2022_PROGRAM}; +use crate::constants::{DEVICE_MINT_SEED_PREFIX, SPL_2022_PROGRAM}; use crate::errors::ErrorCode; -use crate::state::{DeviceBinding, DeviceCollectionBinding, MplBinding, MplCollectionBinding}; +use crate::state::{DeviceBinding, DeviceCollectionBinding, Global, MplBinding, MplCollectionBinding}; use anchor_lang::prelude::*; use anchor_spl::{ associated_token::get_associated_token_address_with_program_id, @@ -45,6 +45,7 @@ pub struct Bind<'info> { pub mpl_binding: Account<'info, MplBinding>, pub device_collection_binding: Account<'info, DeviceCollectionBinding>, pub mpl_collection_binding: Account<'info, MplCollectionBinding>, + pub global: Account<'info, Global>, #[account(mut)] pub owner: Signer<'info>, #[account(mut)] @@ -69,7 +70,7 @@ pub fn bind(ctx: Context, params: BindParams) -> Result<()> { ctx.accounts.mpl_collection_binding.device_collection.as_ref(), params.device.as_ref(), ], - &DEPHY_ID_PROGRAM, + &ctx.accounts.global.dephy_id_program, ); let device_ata = get_associated_token_address_with_program_id( diff --git a/extensions/puppet/programs/puppet/src/instructions/bind_collection.rs b/extensions/puppet/programs/puppet/src/instructions/bind_collection.rs index 2e3f59b..f914f79 100644 --- a/extensions/puppet/programs/puppet/src/instructions/bind_collection.rs +++ b/extensions/puppet/programs/puppet/src/instructions/bind_collection.rs @@ -1,5 +1,5 @@ -use crate::constants::{DEPHY_ID_PROGRAM, PRODUCT_MINT_SEED_PREFIX}; -use crate::state::{DeviceCollectionBinding, MplCollectionBinding}; +use crate::constants::PRODUCT_MINT_SEED_PREFIX; +use crate::state::{DeviceCollectionBinding, Global, MplCollectionBinding}; use anchor_lang::prelude::*; #[derive(Accounts)] @@ -12,7 +12,7 @@ pub struct BindCollection<'info> { constraint = product_mint.key() == params.device_collection, seeds = [PRODUCT_MINT_SEED_PREFIX, vendor.key().as_ref(), params.product_metadata_name.as_ref()], bump, - seeds::program = dephy_id_program.key() + seeds::program = global.dephy_id_program.key() )] pub product_mint: AccountInfo<'info>, /// CHECK: We will manually verify the metadata structure @@ -36,9 +36,7 @@ pub struct BindCollection<'info> { bump )] pub mpl_collection_binding: Account<'info, MplCollectionBinding>, - /// CHECK: This is the hardcoded DePhy ID Program address passed in as an AccountInfo - #[account(address = DEPHY_ID_PROGRAM)] - pub dephy_id_program: AccountInfo<'info>, + pub global: Account<'info, Global>, #[account(mut)] pub vendor: Signer<'info>, #[account(mut)] diff --git a/extensions/puppet/programs/puppet/src/instructions/initialize.rs b/extensions/puppet/programs/puppet/src/instructions/initialize.rs new file mode 100644 index 0000000..1618cf2 --- /dev/null +++ b/extensions/puppet/programs/puppet/src/instructions/initialize.rs @@ -0,0 +1,30 @@ +use crate::state::Global; +use anchor_lang::prelude::*; + +#[derive(AnchorSerialize, AnchorDeserialize, Debug, Clone)] +pub struct InitializeParams { + pub dephy_id_program: Pubkey, +} + +#[derive(Accounts)] +#[instruction(params: InitializeParams)] +pub struct Initialize<'info> { + #[account( + init, + payer = payer, + space = 8 + 32 + 1, + seeds = [b"global", payer.key().as_ref()], + bump, + )] + pub global: Account<'info, Global>, + #[account(mut)] + pub payer: Signer<'info>, + pub rent: Sysvar<'info, Rent>, + pub system_program: Program<'info, System>, +} + +pub fn initialize(ctx: Context, params: InitializeParams) -> Result<()> { + let global = &mut ctx.accounts.global; + global.dephy_id_program = params.dephy_id_program; + Ok(()) +} diff --git a/extensions/puppet/programs/puppet/src/instructions/mod.rs b/extensions/puppet/programs/puppet/src/instructions/mod.rs index 5d896ae..bdd8bec 100644 --- a/extensions/puppet/programs/puppet/src/instructions/mod.rs +++ b/extensions/puppet/programs/puppet/src/instructions/mod.rs @@ -1,3 +1,4 @@ +pub mod initialize; pub mod bind_collection; pub mod bind; pub mod check_bound_by_device; @@ -5,6 +6,7 @@ pub mod check_bound_by_nft; pub mod get_nft_by_device; pub mod get_device_by_nft; +pub use initialize::*; pub use bind_collection::*; pub use bind::*; pub use check_bound_by_device::*; diff --git a/extensions/puppet/programs/puppet/src/lib.rs b/extensions/puppet/programs/puppet/src/lib.rs index 0f48357..7cb7621 100644 --- a/extensions/puppet/programs/puppet/src/lib.rs +++ b/extensions/puppet/programs/puppet/src/lib.rs @@ -12,6 +12,10 @@ declare_id!("6nxvjh3D3kLkkb25sgRUdyomfYqeoUv7gfRFgcScy6jN"); pub mod puppet { use super::*; + pub fn initialize(ctx: Context, params: InitializeParams) -> Result<()> { + instructions::initialize(ctx, params) + } + pub fn bind_collection(ctx: Context, params: BindCollectionParams) -> Result<()> { instructions::bind_collection(ctx, params) } diff --git a/extensions/puppet/programs/puppet/src/state/global.rs b/extensions/puppet/programs/puppet/src/state/global.rs new file mode 100644 index 0000000..95fb12f --- /dev/null +++ b/extensions/puppet/programs/puppet/src/state/global.rs @@ -0,0 +1,7 @@ +use anchor_lang::prelude::*; + +#[account] +pub struct Global { + pub dephy_id_program: Pubkey, + pub bump: u8, +} \ No newline at end of file diff --git a/extensions/puppet/programs/puppet/src/state/mod.rs b/extensions/puppet/programs/puppet/src/state/mod.rs index 02c8bce..dbcdd28 100644 --- a/extensions/puppet/programs/puppet/src/state/mod.rs +++ b/extensions/puppet/programs/puppet/src/state/mod.rs @@ -1,8 +1,10 @@ +pub mod global; pub mod device_collection_binding; pub mod mpl_collection_binding; pub mod device_binding; pub mod mpl_binding; +pub use global::*; pub use device_collection_binding::*; pub use mpl_collection_binding::*; pub use device_binding::*; diff --git a/extensions/puppet/tests/puppet.ts b/extensions/puppet/tests/puppet.ts index d4260f5..bb8ac19 100644 --- a/extensions/puppet/tests/puppet.ts +++ b/extensions/puppet/tests/puppet.ts @@ -32,6 +32,7 @@ import { Puppet } from "../target/types/puppet"; const CLI_DIR = "../../cli"; const KEY_PATH = "tests/key.json"; const DEVICE_PATH = "tests/device.json"; +const DEPHY_ID_PROGEAM = "hdMghjD73uASxgJXi6e1mGPsXqnADMsrqB1bveqABP1"; const execPromise = promisify(exec); describe("puppet program", () => { @@ -56,6 +57,9 @@ describe("puppet program", () => { let mplAta: PublicKey; let mplMetadata: PublicKey; + // global PDA + let globalPDA: PublicKey; + // binding PDA let deviceCollectionBindingPDA: PublicKey; let mplCollectionBindingPDA: PublicKey; @@ -83,9 +87,11 @@ describe("puppet program", () => { product = new PublicKey(productPubkeyStr); // create activated device - const { devicePubKey: devicePubKeyStr, deviceMint: deviceMintStr, deviceAta: deviceAtaStr } = await createDevice( - product.toString(), - ); + const { + devicePubKey: devicePubKeyStr, + deviceMint: deviceMintStr, + deviceAta: deviceAtaStr, + } = await createDevice(product.toString()); console.log("devicePubKey:", devicePubKeyStr); console.log("deviceMint:", deviceMintStr); console.log("deviceAta:", deviceAtaStr); @@ -104,7 +110,11 @@ describe("puppet program", () => { console.log("mplCollection:", mplCollection.toString()); // create mpl nft - const {mplMint: mplMintStr, mplMetadata: mplMetadataStr, mplAta: mplAtaStr} = await createMplNft( + const { + mplMint: mplMintStr, + mplMetadata: mplMetadataStr, + mplAta: mplAtaStr, + } = await createMplNft( provider.connection, payer, "test nft", @@ -118,6 +128,21 @@ describe("puppet program", () => { mplAta = new PublicKey(mplAtaStr); mplMetadata = new PublicKey(mplMetadataStr); + await program.methods + .initialize({ + dephyIdProgram: new PublicKey(DEPHY_ID_PROGEAM), + }) + .accounts({ + payer: payer.publicKey, + }) + .signers([payer]) + .rpc(); + + const [globalPubkey] = PublicKey.findProgramAddressSync( + [Buffer.from("global"), payer.publicKey.toBuffer()], + program.programId + ); + const [deviceCollectionBindingPubkey] = PublicKey.findProgramAddressSync( [Buffer.from("device_collection_binding"), product.toBuffer()], program.programId @@ -138,12 +163,18 @@ describe("puppet program", () => { program.programId ); + globalPDA = globalPubkey; deviceCollectionBindingPDA = deviceCollectionBindingPubkey; mplCollectionBindingPDA = mplCollectionBindingPubkey; deviceBindingPDA = deviceBindingPubkey; mplBindingPDA = mplBindingPubkey; }); + it("initialized", async () => { + const global = await program.account.global.fetch(globalPDA); + assert.equal(global.dephyIdProgram.toString(), DEPHY_ID_PROGEAM); + }); + it("binds device collection and mpl collection", async () => { await program.methods .bindCollection({ @@ -152,6 +183,7 @@ describe("puppet program", () => { mplCollection, }) .accounts({ + global: globalPDA, vendor: payer.publicKey, payer: payer.publicKey, mplCollection, @@ -183,11 +215,12 @@ describe("puppet program", () => { mplAta, }) .accounts({ + global: globalPDA, mplMetadata, mplAssociatedToken: mplAta, deviceAssociatedToken: deviceAta, deviceCollectionBinding: deviceCollectionBindingPDA, - mplCollectionBinding: mplCollectionBindingPDA, + mplCollectionBinding: mplCollectionBindingPDA, owner: payer.publicKey, payer: payer.publicKey, }) @@ -221,27 +254,18 @@ async function executeCommandInDirectory( } const createProduct = async (name: string) => { - const command = `cargo run create-product --vendor ../extensions/puppet/${KEY_PATH} '${name}' 'SYMBOL' 'METADATA_URI' -m desc="First Product by Example Vendor" -u http://127.0.0.1:8899 -p hdMghjD73uASxgJXi6e1mGPsXqnADMsrqB1bveqABP1` - console.log(command) + const command = `cargo run create-product --vendor ../extensions/puppet/${KEY_PATH} '${name}' 'SYMBOL' 'METADATA_URI' -m desc="First Product by Example Vendor" -u http://127.0.0.1:8899 -p hdMghjD73uASxgJXi6e1mGPsXqnADMsrqB1bveqABP1`; - const productMint = await executeCommandInDirectory( - CLI_DIR, - command - ); + const productMint = await executeCommandInDirectory(CLI_DIR, command); return productMint.trimEnd(); }; -const createDevice = async ( - productMint: string, -) => { - const command = `cargo run dev-create-activated-device --vendor ../extensions/puppet/${KEY_PATH} --product ${productMint} --device ../extensions/puppet/${DEVICE_PATH} --user ../extensions/puppet/${KEY_PATH} 'DEVICE#1' -u http://127.0.0.1:8899 -p hdMghjD73uASxgJXi6e1mGPsXqnADMsrqB1bveqABP1` +const createDevice = async (productMint: string) => { + const command = `cargo run dev-create-activated-device --vendor ../extensions/puppet/${KEY_PATH} --product ${productMint} --device ../extensions/puppet/${DEVICE_PATH} --user ../extensions/puppet/${KEY_PATH} 'DEVICE#1' -u http://127.0.0.1:8899 -p hdMghjD73uASxgJXi6e1mGPsXqnADMsrqB1bveqABP1`; - const str = await executeCommandInDirectory( - CLI_DIR, - command, - ); + const str = await executeCommandInDirectory(CLI_DIR, command); - const [devicePubKey, deviceMint, deviceAta] = str.trimEnd().split(',') + const [devicePubKey, deviceMint, deviceAta] = str.trimEnd().split(","); return { devicePubKey, @@ -327,5 +351,9 @@ const createMplNft = async ( const mplMetadata = findMetadataPda(umi, { mint: mplMint.publicKey }); - return {mplMint: mplMint.publicKey.toString(), mplAta: mplAta.toString(), mplMetadata: mplMetadata.toString().split(',')[0]}; + return { + mplMint: mplMint.publicKey.toString(), + mplAta: mplAta.toString(), + mplMetadata: mplMetadata.toString().split(",")[0], + }; };