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

use sg721-metadata-onchain #104

Merged
merged 3 commits into from
Sep 4, 2024
Merged

Conversation

taitruong
Copy link
Collaborator

@taitruong taitruong commented Aug 28, 2024

This PR uses sg721-metadata-onchain contract. It allows incoming NFTs with onchain metadata. If there is no onchain data, then None is used in Metadata.

Comment on lines -730 to -753
// parse token data and check whether it is of type NftExtension
let extension: Option<NftExtensionMsg> = match data {
Some(data) => from_json::<NftExtension>(data)
.ok()
.map(|ext| NftExtensionMsg {
animation_url: ext.animation_url,
attributes: ext.attributes,
background_color: ext.background_color,
description: ext.description,
external_url: ext.external_url,
image: ext.image,
image_data: ext.image_data,
youtube_url: ext.youtube_url,
name: ext.name,
}),
None => None,
};

let msg = cw721_metadata_onchain::msg::ExecuteMsg::Mint {
token_id: id.into(),
token_uri: uri,
owner: receiver.to_string(),
extension,
};
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Outsourced to mint_msg() for re-use.

Comment on lines 119 to 183
fn mint_msg(
&self,
token_id: String,
token_uri: Option<String>,
owner: String,
data: Option<Binary>,
) -> StdResult<Binary> {
// parse token data and check whether it is of type NftExtension
let extension: Metadata = match data {
Some(data) => {
match from_json::<NftExtension>(data).ok().map(|ext| Metadata {
animation_url: ext.animation_url,
attributes: ext.attributes.map(|traits| {
traits
.into_iter()
.map(|t| Trait {
trait_type: t.trait_type,
value: t.value,
display_type: t.display_type,
})
.collect()
}),
background_color: ext.background_color,
description: ext.description,
external_url: ext.external_url,
image: ext.image,
image_data: ext.image_data,
youtube_url: ext.youtube_url,
name: ext.name,
}) {
Some(extension) => extension,
None => Metadata {
animation_url: None,
attributes: None,
background_color: None,
description: None,
external_url: None,
image: None,
image_data: None,
youtube_url: None,
name: None,
},
}
}
None => Metadata {
animation_url: None,
attributes: None,
background_color: None,
description: None,
external_url: None,
image: None,
image_data: None,
youtube_url: None,
name: None,
},
};

let msg = sg721_metadata_onchain::ExecuteMsg::Mint {
token_id,
token_uri,
owner,
extension,
};
to_json_binary(&msg)
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sg-ics721 implementation with Metadata

Comment on lines +709 to +718
data: Some(to_json_binary(&NftExtension {
image: Some("https://ark.pass/image.png".to_string()),
external_url: Some(
"https://interchain.arkprotocol.io".to_string(),
),
description: Some("description".to_string()),
..Default::default()
}))
.transpose()
.unwrap(),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

test case for token 1 with metadata. token 2 is unchanged and has no metadata

Comment on lines +800 to +809
assert_eq!(
token_info.extension,
Some(NftExtension {
image: Some("https://ark.pass/image.png".to_string()),
external_url: Some("https://interchain.arkprotocol.io".to_string()),
description: Some("description".to_string()),
..Default::default()
})
);
let token_info: cw721::msg::NftInfoResponse<DefaultOptionalNftExtension> = test
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transferred NFT 1 with onchain data

Comment on lines +820 to +825
assert_eq!(
token_info.extension,
Some(NftExtension {
..Default::default()
})
);
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

transferred NFT 2 with no onchain data

// parse token data and check whether it is of type NftExtension
let extension: Metadata = match data {
Some(data) => {
match from_json::<NftExtension>(data).ok().map(|ext| Metadata {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since everything here is being added from .ext I wonder if we could put this mapping into a helper function

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we cant, sg-ics721 requires struct of type Metadata, whilst ics721 requires NftExtensionMsg. See comments below.

) -> StdResult<Binary> {
// parse token data and check whether it is of type NftExtension
let extension: Option<NftExtensionMsg> = match data {
Some(data) => from_json::<NftExtension>(data)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we put that other parse in a function I think we could re-use it here?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we cant, sg-ics721 requires struct of type Metadata, whilst ics721 requires NftExtensionMsg

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity how similar are those messages?

Copy link
Collaborator Author

@taitruong taitruong Sep 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are 100% the same. Created a new issue here: public-awesome/launchpad#695

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks

},
};

let msg = sg721_metadata_onchain::ExecuteMsg::Mint {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so my question here is, does every meta data load resolve into a metadata_onchain type message? Wondering if there is a different struct for off-chain metadata?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of offchain metadata:

  • extension is empty onchain Metadata (with None values for each prop like image and attributes)
  • token_uri is used for offchain data, e.g. refers to an IPFS link with offchain metadata. Here JSON file on IPFS is exactly the same type for Metadata (as defined by ERC721).

So SG NFT mint is done by this:

        let msg = cw721_metadata_onchain::msg::ExecuteMsg::Mint {
            token_id,
            token_uri, // holds off-chain metadata
            owner,
            extension, // holds on-chain metadata
        };

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just wondering here, if off chain metadata is minted in this way, shouldn't we not use an execute message from cw721_onchain such as to not confuse the developer? I think the data is fine just coming from the cw721_metadata_onchain directory might be a bit misleading.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh my bad (wrong example given above). This is an sg-implementation, proper code is using this:

        let msg = sg721_metadata_onchain::ExecuteMsg::Mint {
            token_id,
            token_uri, // holds off-chain metadata
            owner,
            extension, // holds on-chain metadata
        };
        to_json_binary(&msg)

Please note that mint_msg() returns StdResult<Binary> for ics721 and sg-ics721.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Resolved in discord, name is coming from external repo

Ok(WasmMsg::Execute {
contract_addr: nft_contract.to_string(),
msg: to_json_binary(&msg)?,
msg: self.mint_msg(id.into(), uri, receiver.to_string(), data)?,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@humanalgorithm look here where mint_msg is called. This happens here in as part of callback_create_vouchers call in Ics721Execute trait.

Copy link
Member

@shanev shanev left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@taitruong taitruong added this pull request to the merge queue Sep 4, 2024
Merged via the queue into main with commit eb47798 Sep 4, 2024
4 checks passed
@taitruong taitruong deleted the sg_ics721_with_onchain_metadata branch September 4, 2024 20:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants