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

Adding ability to use update delegate for Reroll #5

Merged
merged 3 commits into from
Aug 11, 2024
Merged
Show file tree
Hide file tree
Changes from all 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
4 changes: 2 additions & 2 deletions .github/.env
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ CARGO_TERM_COLOR=always
NODE_VERSION=20.x
PROGRAMS=["mpl-hybrid"]
RUST_VERSION=1.75.0
SOLANA_VERSION=1.18.15
SOLANA_VERSION=1.18.21
COMMIT_USER_NAME=github-actions
[email protected]
DEPLOY_SOLANA_VERSION=1.18.15
DEPLOY_SOLANA_VERSION=1.18.21
13 changes: 13 additions & 0 deletions clients/js/src/generated/errors/mplHybrid.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,19 @@ export class NumericalOverflowError extends ProgramError {
codeToErrorMap.set(0x177b, NumericalOverflowError);
nameToErrorMap.set('NumericalOverflow', NumericalOverflowError);

/** InvalidUpdateAuthority: Invalid Update Authority */
export class InvalidUpdateAuthorityError extends ProgramError {
override readonly name: string = 'InvalidUpdateAuthority';

readonly code: number = 0x177c; // 6012

constructor(program: Program, cause?: Error) {
super('Invalid Update Authority', program, cause);
}
}
codeToErrorMap.set(0x177c, InvalidUpdateAuthorityError);
nameToErrorMap.set('InvalidUpdateAuthority', InvalidUpdateAuthorityError);

/**
* Attempts to resolve a custom program error from the provided error code.
* @category Errors
Expand Down
2 changes: 1 addition & 1 deletion clients/js/src/generated/instructions/captureV1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
// Accounts.
export type CaptureV1InstructionAccounts = {
owner: Signer;
authority?: Signer;
authority?: PublicKey | Pda | Signer;
escrow: PublicKey | Pda;
asset: PublicKey | Pda;
collection: PublicKey | Pda;
Expand Down
2 changes: 1 addition & 1 deletion clients/js/src/generated/instructions/releaseV1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ import {
// Accounts.
export type ReleaseV1InstructionAccounts = {
owner: Signer;
authority?: Signer;
authority?: PublicKey | Pda | Signer;
escrow: PublicKey | Pda;
asset: PublicKey | Pda;
collection: PublicKey | Pda;
Expand Down
98 changes: 97 additions & 1 deletion clients/js/test/capture.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
string,
publicKey as publicKeySerializer,
} from '@metaplex-foundation/umi/serializers';
import { transfer } from '@metaplex-foundation/mpl-core';
import { addCollectionPlugin, transfer } from '@metaplex-foundation/mpl-core';
import {
captureV1,
EscrowV1,
Expand Down Expand Up @@ -103,3 +103,99 @@ test('it can swap tokens for an asset', async (t) => {
token: tokenMint.publicKey,
}).sendAndConfirm(umi);
});

test('it can swap tokens for an asset as UpdateDelegate', async (t) => {
// Given a Umi instance using the project's plugin.
const umi = await createUmi();
const feeLocation = generateSigner(umi);
const { assets, collection } = await createCoreCollection(umi);
const tokenMint = generateSigner(umi);
await createFungible(umi, {
name: 'Test Token',
uri: 'www.fungible.com',
sellerFeeBasisPoints: {
basisPoints: 0n,
identifier: '%',
decimals: 2,
},
mint: tokenMint,
}).sendAndConfirm(umi);

await mintV1(umi, {
mint: tokenMint.publicKey,
tokenStandard: TokenStandard.Fungible,
tokenOwner: umi.identity.publicKey,
amount: 1000,
}).sendAndConfirm(umi);

const escrow = umi.eddsa.findPda(MPL_HYBRID_PROGRAM_ID, [
string({ size: 'variable' }).serialize('escrow'),
publicKeySerializer().serialize(collection.publicKey),
]);

// Transfer the assets to the escrow.
// eslint-disable-next-line no-restricted-syntax
for (const asset of assets) {
// eslint-disable-next-line no-await-in-loop
await transfer(umi, {
asset,
collection,
newOwner: escrow,
}).sendAndConfirm(umi);
}

await initEscrowV1(umi, {
escrow,
collection: collection.publicKey,
token: tokenMint.publicKey,
feeLocation: feeLocation.publicKey,
name: 'Test Escrow',
uri: 'www.test.com',
max: 9,
min: 0,
amount: 5,
feeAmount: 1,
// eslint-disable-next-line no-bitwise
path: 1 << Path.RerollMetadata,
solFeeAmount: 1000000n,
}).sendAndConfirm(umi);

await addCollectionPlugin(umi, {
collection: collection.publicKey,
plugin: {
type: 'UpdateDelegate',
additionalDelegates: [],
authority: { type: 'Address', address: publicKey(escrow) },
},
}).sendAndConfirm(umi);

const escrowData = await fetchEscrowV1(umi, escrow);

t.like(escrowData, <EscrowV1>{
publicKey: publicKey(escrow),
collection: collection.publicKey,
token: tokenMint.publicKey,
feeLocation: feeLocation.publicKey,
name: 'Test Escrow',
uri: 'www.test.com',
max: 9n,
min: 0n,
amount: 5n,
feeAmount: 1n,
count: 1n,
// eslint-disable-next-line no-bitwise
path: 1 << Path.RerollMetadata,
bump: escrow[1],
solFeeAmount: 1_000_000n,
});

await captureV1(umi, {
owner: umi.identity,
authority: escrow,
escrow,
asset: assets[0].publicKey,
collection: collection.publicKey,
feeProjectAccount: escrowData.feeLocation,
token: tokenMint.publicKey,
}).sendAndConfirm(umi);
});
86 changes: 86 additions & 0 deletions clients/js/test/release.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
string,
publicKey as publicKeySerializer,
} from '@metaplex-foundation/umi/serializers';
import { addCollectionPlugin } from '@metaplex-foundation/mpl-core';
import {
EscrowV1,
fetchEscrowV1,
Expand Down Expand Up @@ -91,3 +92,88 @@ test('it can swap an asset for tokens', async (t) => {
token: tokenMint.publicKey,
}).sendAndConfirm(umi);
});

test('it can swap an asset for tokens as UpdateDelegate', async (t) => {
// Given a Umi instance using the project's plugin.
const umi = await createUmi();
const feeLocation = generateSigner(umi);
const { assets, collection } = await createCoreCollection(umi);
const tokenMint = generateSigner(umi);
await createFungible(umi, {
name: 'Test Token',
uri: 'www.fungible.com',
sellerFeeBasisPoints: {
basisPoints: 0n,
identifier: '%',
decimals: 2,
},
mint: tokenMint,
}).sendAndConfirm(umi);

const escrow = umi.eddsa.findPda(MPL_HYBRID_PROGRAM_ID, [
string({ size: 'variable' }).serialize('escrow'),
publicKeySerializer().serialize(collection.publicKey),
]);

await mintV1(umi, {
mint: tokenMint.publicKey,
tokenStandard: TokenStandard.Fungible,
tokenOwner: escrow,
amount: 1000,
}).sendAndConfirm(umi);

await initEscrowV1(umi, {
escrow,
collection: collection.publicKey,
token: tokenMint.publicKey,
feeLocation: feeLocation.publicKey,
name: 'Test Escrow',
uri: 'www.test.com',
max: 9,
min: 0,
amount: 5,
feeAmount: 1,
// eslint-disable-next-line no-bitwise
path: 1 << Path.RerollMetadata,
solFeeAmount: 1000000n,
}).sendAndConfirm(umi);

await addCollectionPlugin(umi, {
collection: collection.publicKey,
plugin: {
type: 'UpdateDelegate',
additionalDelegates: [],
authority: { type: 'Address', address: publicKey(escrow) },
},
}).sendAndConfirm(umi);

const escrowData = await fetchEscrowV1(umi, escrow);

t.like(escrowData, <EscrowV1>{
publicKey: publicKey(escrow),
collection: collection.publicKey,
token: tokenMint.publicKey,
feeLocation: feeLocation.publicKey,
name: 'Test Escrow',
uri: 'www.test.com',
max: 9n,
min: 0n,
amount: 5n,
feeAmount: 1n,
count: 1n,
// eslint-disable-next-line no-bitwise
path: 1 << Path.RerollMetadata,
bump: escrow[1],
solFeeAmount: 1_000_000n,
});

await releaseV1(umi, {
owner: umi.identity,
authority: escrow,
escrow,
asset: assets[0].publicKey,
collection: collection.publicKey,
feeProjectAccount: escrowData.feeLocation,
token: tokenMint.publicKey,
}).sendAndConfirm(umi);
});
3 changes: 3 additions & 0 deletions clients/rust/src/generated/errors/mpl_hybrid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ pub enum MplHybridError {
/// 6011 (0x177B) - Numerical Overflow
#[error("Numerical Overflow")]
NumericalOverflow,
/// 6012 (0x177C) - Invalid Update Authority
#[error("Invalid Update Authority")]
InvalidUpdateAuthority,
}

impl solana_program::program_error::PrintProgramError for MplHybridError {
Expand Down
31 changes: 18 additions & 13 deletions clients/rust/src/generated/instructions/capture_v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use borsh::{BorshDeserialize, BorshSerialize};
pub struct CaptureV1 {
pub owner: solana_program::pubkey::Pubkey,

pub authority: solana_program::pubkey::Pubkey,
pub authority: (solana_program::pubkey::Pubkey, bool),

pub escrow: solana_program::pubkey::Pubkey,

Expand Down Expand Up @@ -59,8 +59,8 @@ impl CaptureV1 {
self.owner, true,
));
accounts.push(solana_program::instruction::AccountMeta::new(
self.authority,
true,
self.authority.0,
self.authority.1,
));
accounts.push(solana_program::instruction::AccountMeta::new(
self.escrow,
Expand Down Expand Up @@ -164,7 +164,7 @@ impl CaptureV1InstructionData {
#[derive(Default)]
pub struct CaptureV1Builder {
owner: Option<solana_program::pubkey::Pubkey>,
authority: Option<solana_program::pubkey::Pubkey>,
authority: Option<(solana_program::pubkey::Pubkey, bool)>,
escrow: Option<solana_program::pubkey::Pubkey>,
asset: Option<solana_program::pubkey::Pubkey>,
collection: Option<solana_program::pubkey::Pubkey>,
Expand Down Expand Up @@ -192,8 +192,12 @@ impl CaptureV1Builder {
self
}
#[inline(always)]
pub fn authority(&mut self, authority: solana_program::pubkey::Pubkey) -> &mut Self {
self.authority = Some(authority);
pub fn authority(
&mut self,
authority: solana_program::pubkey::Pubkey,
as_signer: bool,
) -> &mut Self {
self.authority = Some((authority, as_signer));
self
}
#[inline(always)]
Expand Down Expand Up @@ -360,7 +364,7 @@ impl CaptureV1Builder {
pub struct CaptureV1CpiAccounts<'a, 'b> {
pub owner: &'b solana_program::account_info::AccountInfo<'a>,

pub authority: &'b solana_program::account_info::AccountInfo<'a>,
pub authority: (&'b solana_program::account_info::AccountInfo<'a>, bool),

pub escrow: &'b solana_program::account_info::AccountInfo<'a>,

Expand Down Expand Up @@ -398,7 +402,7 @@ pub struct CaptureV1Cpi<'a, 'b> {

pub owner: &'b solana_program::account_info::AccountInfo<'a>,

pub authority: &'b solana_program::account_info::AccountInfo<'a>,
pub authority: (&'b solana_program::account_info::AccountInfo<'a>, bool),

pub escrow: &'b solana_program::account_info::AccountInfo<'a>,

Expand Down Expand Up @@ -493,8 +497,8 @@ impl<'a, 'b> CaptureV1Cpi<'a, 'b> {
true,
));
accounts.push(solana_program::instruction::AccountMeta::new(
*self.authority.key,
true,
*self.authority.0.key,
self.authority.1,
));
accounts.push(solana_program::instruction::AccountMeta::new(
*self.escrow.key,
Expand Down Expand Up @@ -569,7 +573,7 @@ impl<'a, 'b> CaptureV1Cpi<'a, 'b> {
let mut account_infos = Vec::with_capacity(16 + 1 + remaining_accounts.len());
account_infos.push(self.__program.clone());
account_infos.push(self.owner.clone());
account_infos.push(self.authority.clone());
account_infos.push(self.authority.0.clone());
account_infos.push(self.escrow.clone());
account_infos.push(self.asset.clone());
account_infos.push(self.collection.clone());
Expand Down Expand Up @@ -653,8 +657,9 @@ impl<'a, 'b> CaptureV1CpiBuilder<'a, 'b> {
pub fn authority(
&mut self,
authority: &'b solana_program::account_info::AccountInfo<'a>,
as_signer: bool,
) -> &mut Self {
self.instruction.authority = Some(authority);
self.instruction.authority = Some((authority, as_signer));
self
}
#[inline(always)]
Expand Down Expand Up @@ -876,7 +881,7 @@ impl<'a, 'b> CaptureV1CpiBuilder<'a, 'b> {
struct CaptureV1CpiBuilderInstruction<'a, 'b> {
__program: &'b solana_program::account_info::AccountInfo<'a>,
owner: Option<&'b solana_program::account_info::AccountInfo<'a>>,
authority: Option<&'b solana_program::account_info::AccountInfo<'a>>,
authority: Option<(&'b solana_program::account_info::AccountInfo<'a>, bool)>,
escrow: Option<&'b solana_program::account_info::AccountInfo<'a>>,
asset: Option<&'b solana_program::account_info::AccountInfo<'a>>,
collection: Option<&'b solana_program::account_info::AccountInfo<'a>>,
Expand Down
Loading
Loading