metaplex-foundation / mpl-token-metadata

Program to attach additional data to Fungible or Non-Fungible tokens on Solana.
https://developers.metaplex.com/token-metadata
Other
99 stars 42 forks source link

mpl_token_metadata::accounts::Metadata::from_bytes() fails #68

Open julianbraha opened 7 months ago

julianbraha commented 7 months ago

I'm trying to decode some token metadata, and mpl_token_metadata::accounts::Metadata::from_bytes() works for most tokens, but it's failing for 2 that I've found.

The raw data is encoded in base64, so I've written a function like this:

// decode the base64 string, then decode those bytes to metadata
fn decode_base64_to_metadata(data: String) -> Metadata {
    let decoded_base64: Vec<u8> =
        base64::Engine::decode(&base64::engine::general_purpose::STANDARD, data).unwrap();

    Metadata::from_bytes(&decoded_base64).unwrap()
}

But the last line Metadata::from_bytes(&decoded_base64).unwrap() is panicking when I call the function with these two strings:

  1. BIujMfe1f4+f62sriKcmF5frjExh19LNVTFjEoOTb4ZALGkR7Ylov5UYZr/5UvSvSNprO4d+aL0S4JjpVvWiOb4VAAAATG9sbGFwYWxvb3phIDIwMTggQXJ0BgAAADExNDgzMxAAAABsb2xsYXBhbG9vemFhcnQzAAABAQAAAIujMfe1f4+f62sriKcmF5frjExh19LNVTFjEoOTb4ZAAWQAASAgICAgAAABAQAAAIujMfe1f4+f62sriKcmF5frjExh19LNVTFjEoOTb4ZAAWQAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==

and:

  1. BNUAmMn7BYQUxe8+WzdLfzW1gKg4MPTOih9dR4ffxbCuffD7fiz0KEiFGG+ecMNdO7HiYZdCLK3sFCG+HSXWHN8gAAAARmx1bmsgRG9ua2V5ICM1Mjg0AAAAAAAAAAAAAAAAAAAKAAAARkxVTksAAAAAAMgAAABodHRwczovL2Fyd2VhdmUubmV0L1N2TC1Mc2NCZ3I1LW9jTEJWeXJSdEdfcDNHNDZPNTJJcE1KaXRoWE5xQzgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPQBAQIAAADVAJjJ+wWEFMXvPls3S381tYCoODD0zoofXUeH38WwrgEAvkiveUxiDgbILHv60zihQvroPzQHmLg7cfM4sKkmrtsAZAEBAf0AAQFbL7vcSRP9/ZYiXPFua2KDNbcdW/gYhL9tUUZW1HrZwgAza8zyJZA4AfNZvjo5NXQ0ZE34CUGp3EjvNwAZ1QCYyfsFhBTF7z5bN0t/NbWAqDgw9M6KH11Hh9/FsK4AGQEBAf0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==

The panics I get are:

`Err` value: Custom { kind: InvalidInput, error: "Invalid Option representation: 32. The first byte must be 0 or 1" }

and

`Err` value: Custom { kind: InvalidInput, error: "Invalid Option representation: 51. The first byte must be 0 or 1" }

However, it works just fine for many others, for example:

If you attempt to decode these using https://www.base64decode.org/, then you'll see in the text that they correspond to Flunk Donkey #5284, BOB IS THE TICKER, and Lollapalooza 2018 Art

I'm using the latest version of the mpl-token-metadata crate (3.2.3) and the latest version of the base64 crate (0.21.5).

febo commented 6 months ago

Can you try Metadata::safe_deserialize to see if this works?

KartikSoneji commented 5 months ago

That does work, at least for the ones I tried. Thanks!

taimurey commented 5 months ago

how are you fetching metadata for the token? Tried using find_pda but it returns the program address. is there any method to fetch the data?

KartikSoneji commented 5 months ago

@taimurey find_pda() will only derive the pda address. You have to use an RPC Client to actually make an RPC call and fetch the data from the chain.

See: metaboss_lib/src/decode/mod.rs:41-48

pub fn decode_metadata(client: &RpcClient, pubkey: &Pubkey) -> Result<Metadata, DecodeError> {
    let account_data = client
        .get_account_data(pubkey)
        .map_err(|e| DecodeError::ClientError(e.kind))?;

    Metadata::safe_deserialize(&mut account_data.as_ref())
        .map_err(|e| DecodeError::DecodeMetadataFailed(e.to_string()))
}
taimurey commented 5 months ago

Thanks a lot, Kartik!

iamnotstatic commented 3 months ago

I can see this issue is till open this is how i manage to get to work, incase anyone still needs it

let metadata = Metadata::find_pda(&token_a_pub);
let account_data = connection.get_account_data(&metadata.0).unwrap();
let safe_deserialize_data = Metadata::safe_deserialize(&account_data);