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

ICS721 v2: cw721 v19 with creator and onchain extensioms (aka metadata) #103

Merged
merged 21 commits into from
Aug 17, 2024

Conversation

taitruong
Copy link
Collaborator

@taitruong taitruong commented Aug 11, 2024

This is ics721 v2 using cw721 v19 (includes collection extension (metadata) and creator):

  • instantiates cw721 v19 on initial NFT transfer
    • transfers optional collection extension(e.g. description, royalties, ...)
    • sets creator, using cw721 admin
  • SG specifics
    • collection data is retrieved from sg721
    • also sg721 is instantiated on initial transfer
  • tranfers optional NFT extensions and mints NFT with extension (onchain metadata)
  • tests covered:
    • source NFT can be of version v15, v16, v17, v18, and v19
    • escrowed, instantiated collection is ofc always v19
  • other
    • updated libs

@taitruong taitruong changed the title wip: onchain metadata v19 ICS721 v2: creator and onchain metadata v19 Aug 14, 2024
@taitruong taitruong changed the title ICS721 v2: creator and onchain metadata v19 ICS721 v2: cw721 v19 with creator and onchain extensioms (aka metadata) Aug 14, 2024
&cw721_base::msg::QueryMsg::<Empty>::ContractInfo {},
#[allow(deprecated)]
// For now we use `ContractInfo` which is known across all version, whilst `GetCollectionInfoAndExtension` is only available in v0.19 and higher
&cw721_metadata_onchain::msg::QueryMsg::ContractInfo {},
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

This is where collection metadata is retrieved. cw721 v18 and below only holds name and symbol. Whilst v19 holds creator and royalty info.

Comment on lines +29 to +40
let royalty_info = collection_info.royalty_info.map(|r| RoyaltyInfo {
payment_address: Addr::unchecked(r.payment_address),
share: r.share,
});
let extension = Some(CollectionExtension {
description: collection_info.description,
image: collection_info.image,
external_link: collection_info.external_link,
explicit_content: collection_info.explicit_content,
start_trading_time: collection_info.start_trading_time,
royalty_info,
});
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here sg-ics721 overrides default implementation and gets collection data from sg721-base via CollectionInfo query.

Comment on lines +646 to +660
let collection_info_extension_msg =
collection_data
.extension
.map(|ext| cw721::msg::CollectionExtensionMsg {
description: Some(ext.description),
image: Some(ext.image),
external_link: ext.external_link,
explicit_content: ext.explicit_content,
start_trading_time: ext.start_trading_time,
royalty_info: ext.royalty_info.map(|r| RoyaltyInfoResponse {
payment_address: cw721_admin_or_ics721_admin_or_ics721_creator, // r.payment_address cant be used, since it is from another chain
share: r.share,
}),
});
instantiate_msg.collection_info_extension = collection_info_extension_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.

on ibc receive for initial transfer, collection extension is passed to cw721 instantiate message.

Comment on lines +425 to +426
// incase there is none in the storage, this is the 'home' chain, so metadata is retrieved from the cw721 contract
None => info.extension.map(|ext| to_json_binary(&ext)).transpose()?,
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Here, on source chain, nft extension (metadata) is retrieved and passed in ibc packet.

Comment on lines +730 to +746
// 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,
};
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

On receive, ics721 checks whether ibc packet holds nft extensions - if so NFT is minted with onchain metadata.

Comment on lines +457 to +463
t.deepEqual(
wasmCollectionData,
osmoCollectionData,
`collection data must match: ${JSON.stringify(
wasmCollectionData
)} vs ${JSON.stringify(osmoCollectionData)}`
);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

integration check whether collection extension on target chain matches with source chain

const osmoNftInfo = await nftInfo(osmoClient, osmoCw721, tokenId);
t.truthy(osmoNftInfo.extension);
// assert nft with extension is same
t.deepEqual(wasmNftInfo, osmoNftInfo);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

check for nft onchain metadata

@@ -746,6 +847,471 @@ test.serial("transfer NFT: wasmd -> osmo", async (t) => {
t.is(wasmAddr, tokenOwner.owner);
});

test.serial("transfer NFT v16: wasm -> osmo", async (t) => {
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

same test, but with cw721 v16 on source chain

Comment on lines +925 to +929
t.deepEqual(
wasmCollectionData.name,
osmoCollectionData.name,
`name must match: ${wasmCollectionData.name} vs ${osmoCollectionData.name}`
);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

cw721 only holds name and symbole in collection extension

const osmoNftInfo = await nftInfo(osmoClient, osmoCw721, tokenId);
t.truthy(osmoNftInfo.extension);
// assert nft with extension is same
t.deepEqual(wasmNftInfo, osmoNftInfo);
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

cw721 v16 and higher holds same nft extension (as defined by erc721 spec).

@taitruong taitruong enabled auto-merge August 14, 2024 19:13
@taitruong taitruong added this pull request to the merge queue Aug 17, 2024
Merged via the queue into public-awesome:main with commit d182e22 Aug 17, 2024
1 check passed
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