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

Set authority as an option #56

Merged
merged 3 commits into from
Apr 10, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
16 changes: 13 additions & 3 deletions clients/js/asset/src/generated/types/proxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,33 @@ import {
struct,
u8,
} from '@metaplex-foundation/umi/serializers';
import {
NullablePublicKey,
NullablePublicKeyArgs,
getNullablePublicKeySerializer,
} from '../../hooked';

export type Proxy = {
program: PublicKey;
seeds: Array<number>;
bump: number;
authority: PublicKey;
authority: NullablePublicKey;
};

export type ProxyArgs = Proxy;
export type ProxyArgs = {
program: PublicKey;
seeds: Array<number>;
bump: number;
authority: NullablePublicKeyArgs;
};

export function getProxySerializer(): Serializer<ProxyArgs, Proxy> {
return struct<Proxy>(
[
['program', publicKeySerializer()],
['seeds', array(u8(), { size: 32 })],
['bump', u8()],
['authority', publicKeySerializer()],
['authority', getNullablePublicKeySerializer()],
],
{ description: 'Proxy' }
) as Serializer<ProxyArgs, Proxy>;
Expand Down
30 changes: 22 additions & 8 deletions clients/js/proxy/test/create.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,14 @@ import { generateSigner } from '@metaplex-foundation/umi';
import test from 'ava';
import { createUmi } from './_setup';
import { create } from '../src';
import { Discriminator, Standard, State, fetchAsset } from '@nifty-oss/asset';
import {
Discriminator,
ExtensionType,
Standard,
State,
fetchAsset,
getExtension,
} from '@nifty-oss/asset';
import { findProxiedAssetPda } from '../src/pda';

test('it can create a proxied asset', async (t) => {
Expand All @@ -22,12 +29,19 @@ test('it can create a proxied asset', async (t) => {
}).sendAndConfirm(umi);

// Then an asset was created with the correct data.
t.like(
await fetchAsset(umi, findProxiedAssetPda(umi, { stub: stub.publicKey })),
{
discriminator: Discriminator.Asset,
state: State.Unlocked,
standard: Standard.Proxied,
}
const asset = await fetchAsset(
umi,
findProxiedAssetPda(umi, { stub: stub.publicKey })
);
t.like(asset, {
discriminator: Discriminator.Asset,
state: State.Unlocked,
standard: Standard.Proxied,
});

// And the asset has a proxy extension.
const proxy = getExtension(asset, ExtensionType.Proxy);
t.like(proxy, {
authority: owner.publicKey,
});
});
7 changes: 2 additions & 5 deletions clients/rust/asset/src/generated/types/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//! [https://github.com/metaplex-foundation/kinobi]
//!

use crate::hooked::NullablePublicKey;
use borsh::BorshDeserialize;
use borsh::BorshSerialize;
use solana_program::pubkey::Pubkey;
Expand All @@ -19,9 +20,5 @@ pub struct Proxy {
pub program: Pubkey,
pub seeds: [u8; 32],
pub bump: u8,
#[cfg_attr(
feature = "serde",
serde(with = "serde_with::As::<serde_with::DisplayFromStr>")
)]
pub authority: Pubkey,
pub authority: NullablePublicKey,
}
2 changes: 1 addition & 1 deletion configs/kinobi-asset.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,7 @@ kinobi.update(
}),
k.structFieldTypeNode({
name: "authority",
type: k.publicKeyTypeNode(),
type: k.definedTypeLinkNode("nullablePublicKey", "hooked"),
}),
]),
}),
Expand Down
27 changes: 12 additions & 15 deletions programs/asset/types/src/extensions/grouping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -157,20 +157,19 @@ impl GroupingBuilder {
}

/// Add a new attribute to the extension.
pub fn set(&mut self, max_size: Option<u64>, delegate: Option<Pubkey>) -> &mut Self {
pub fn set(&mut self, max_size: Option<u64>, delegate: Option<&Pubkey>) -> &mut Self {
// setting the data replaces any existing data
self.0.clear();

self.0.extend_from_slice(&u64::to_le_bytes(0));
self.0
.extend_from_slice(&u64::to_le_bytes(max_size.unwrap_or(0)));

let delegate = if let Some(delegate) = delegate {
delegate.to_bytes()
if let Some(delegate) = delegate {
self.0.extend_from_slice(delegate.as_ref());
} else {
Pubkey::default().to_bytes()
};
self.0.extend_from_slice(&delegate);
self.0.extend_from_slice(Pubkey::default().as_ref());
}

self
}
Expand All @@ -197,11 +196,9 @@ impl Deref for GroupingBuilder {
#[cfg(test)]
mod tests {
use solana_program::sysvar;
use std::ops::Deref;

use crate::{
extensions::{ExtensionBuilder, GroupingBuilder},
state::NullablePubkey,
};
use crate::extensions::{ExtensionBuilder, GroupingBuilder};

#[test]
fn test_set_max_size() {
Expand Down Expand Up @@ -230,14 +227,14 @@ mod tests {
fn test_set_delegate() {
// set delegate to a pubkey
let mut builder = GroupingBuilder::default();
builder.set(None, Some(sysvar::ID));
builder.set(None, Some(&sysvar::ID));
let grouping = builder.build();

assert!(grouping.delegate.value().is_some());
assert_eq!(
grouping.delegate.value().unwrap(),
&NullablePubkey::new(sysvar::ID)
);

if let Some(delegate) = grouping.delegate.value() {
assert_eq!(delegate.deref(), &sysvar::ID);
}

// set delegate to None
builder.set(None, None);
Expand Down
46 changes: 38 additions & 8 deletions programs/asset/types/src/extensions/proxy.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use podded::pod::PodOption;
use solana_program::pubkey::Pubkey;
use std::{fmt::Debug, ops::Deref};

use crate::error::Error;
use crate::{error::Error, state::NullablePubkey};

use super::{ExtensionBuilder, ExtensionData, ExtensionDataMut, ExtensionType, Lifecycle};

Expand All @@ -22,7 +23,7 @@ pub struct Proxy<'a> {
pub bump: &'a u8,

/// Authority of the proxy extension.
pub authority: &'a Pubkey,
pub authority: &'a PodOption<NullablePubkey>,
}

impl<'a> ExtensionData<'a> for Proxy<'a> {
Expand Down Expand Up @@ -130,14 +131,19 @@ impl ProxyBuilder {
program: &Pubkey,
seeds: &[u8; 32],
bump: u8,
authority: &Pubkey,
authority: Option<&Pubkey>,
) -> &mut Self {
// setting the data replaces any existing data
self.0.clear();
self.0.extend_from_slice(program.as_ref());
self.0.extend_from_slice(seeds);
self.0.push(bump);
self.0.extend_from_slice(authority.as_ref());

if let Some(authority) = authority {
self.0.extend_from_slice(authority.as_ref());
} else {
self.0.extend_from_slice(Pubkey::default().as_ref());
}

self
}
Expand Down Expand Up @@ -171,19 +177,43 @@ impl Deref for ProxyBuilder {

#[cfg(test)]
mod tests {
use std::ops::Deref;

use crate::extensions::{ExtensionData, Proxy, ProxyBuilder};
use solana_program::{pubkey::Pubkey, system_program};
use solana_program::system_program;

#[test]
fn test_set() {
// default delegate address
// default authority address
let mut builder = ProxyBuilder::default();
builder.set(&system_program::ID, &[1u8; 32], 254, &Pubkey::default());
builder.set(&system_program::ID, &[1u8; 32], 254, None);
let proxy = Proxy::from_bytes(&builder);

assert_eq!(proxy.program, &system_program::ID);
assert_eq!(proxy.seeds, &[1u8; 32]);
assert_eq!(proxy.bump, &254);
assert_eq!(proxy.authority, &Pubkey::default());
assert!(proxy.authority.value().is_none());
}

#[test]
fn test_set_authority() {
// default authority address
let mut builder = ProxyBuilder::default();
builder.set(
&system_program::ID,
&[1u8; 32],
254,
Some(&solana_program::sysvar::ID),
);
let proxy = Proxy::from_bytes(&builder);

assert_eq!(proxy.program, &system_program::ID);
assert_eq!(proxy.seeds, &[1u8; 32]);
assert_eq!(proxy.bump, &254);
assert!(proxy.authority.value().is_some());

if let Some(authority) = proxy.authority.value() {
assert_eq!(authority.deref(), &solana_program::sysvar::ID);
}
}
}
2 changes: 1 addition & 1 deletion programs/proxy/src/processor/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ pub fn process_create(
program_id,
&ctx.accounts.stub.key.to_bytes(),
bump,
ctx.accounts.owner.key,
Some(ctx.accounts.owner.key),
)
.data();

Expand Down
2 changes: 1 addition & 1 deletion programs/proxy/src/processor/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ pub fn process_instruction<'a>(
return create::process_create(program_id, CreateAccounts::context(accounts)?, metadata);
}

// if it is not an instruction from the `Proxy program`, we try to match it
// if it is not an instruction from the `Proxy`` program, we try to match it
febo marked this conversation as resolved.
Show resolved Hide resolved
// on the Nifty Asset interface

if let Ok(instruction) = Interface::try_from_slice(instruction_data) {
Expand Down