From c34758da9eec69779ccda2794dcfbc2704392e8b Mon Sep 17 00:00:00 2001 From: Novus Nota <68142933+novusnota@users.noreply.github.com> Date: Thu, 26 Dec 2024 16:16:37 +0100 Subject: [PATCH] feat(docs): onchain metadata creation for NFTs and Jettons (#1236) --- CHANGELOG.md | 1 + docs/src/content/docs/cookbook/jettons.mdx | 47 +++++++++++ docs/src/content/docs/cookbook/nfts.mdx | 92 ++++++++++++++++++++++ 3 files changed, 140 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1ab9fcc8f..7a26a1c71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added a note on `dump()` being computationally expensive: PR [#1189](https://github.com/tact-lang/tact/pull/1189) - Fixed links in Chinese translation: PR [#1206](https://github.com/tact-lang/tact/pull/1206) - Added a note on 255 being the maximum number of messages that can be sent during action phase: PR [#1237](https://github.com/tact-lang/tact/pull/1237) +- Added onchain metadata creation for NFTs and Jettons to the cookbook: PR [#1236](https://github.com/tact-lang/tact/pull/1236) ### Release contributors diff --git a/docs/src/content/docs/cookbook/jettons.mdx b/docs/src/content/docs/cookbook/jettons.mdx index 329421f75..9ca6204ce 100644 --- a/docs/src/content/docs/cookbook/jettons.mdx +++ b/docs/src/content/docs/cookbook/jettons.mdx @@ -360,6 +360,53 @@ fun calculateJettonWalletAddress( } ``` +### Onchain metadata creation + +```tact +/// https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#jetton-metadata-example-offchain +fun composeJettonMetadata( + name: String, // full name + description: String, // text description of the Jetton + symbol: String, // "stock ticker" symbol without the $ prefix, like USDT or SCALE + image: String, // link to the image + // There could be other data, see: + // https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#jetton-metadata-attributes +): Cell { + let dict: map = emptyMap(); + dict.set(sha256("name"), name.asMetadataCell()); + dict.set(sha256("description"), description.asMetadataCell()); + dict.set(sha256("symbol"), symbol.asMetadataCell()); + dict.set(sha256("image"), image.asMetadataCell()); + + return beginCell() + .storeUint(0, 8) // a null byte prefix + .storeMaybeRef(dict.asCell()!!) // 1 as a single bit, then a reference + .endCell(); +} + +// Taking flight! +fun poorMansLaunchPad() { + let jettonMetadata = composeJettonMetadata( + "Best Jetton", + "A very descriptive description describing the jetton descriptively", + "JETTON", + "...link to ipfs or somewhere trusted...", + ); +} + +// Prefixes the String with a single null byte and converts it to a Cell +// The null byte prefix is used to express metadata in various standards, like NFT or Jetton +inline extends fun asMetadataCell(self: String): Cell { + return beginTailString().concat(self).toCell(); +} +``` + +:::note[Useful links:] + + [Token Data Standard in TEPs](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#jetton-metadata-attributes) + +::: + :::tip[Hey there!] Didn't find your favorite example of Jetton usage? Have cool implementations in mind? [Contributions are welcome!](https://github.com/tact-lang/tact/issues) diff --git a/docs/src/content/docs/cookbook/nfts.mdx b/docs/src/content/docs/cookbook/nfts.mdx index 613e83459..770d5dee3 100644 --- a/docs/src/content/docs/cookbook/nfts.mdx +++ b/docs/src/content/docs/cookbook/nfts.mdx @@ -323,6 +323,98 @@ contract Example { } ``` +## Onchain metadata creation + +### NFT Collection {#onchain-metadata-nft-collection} + +```tact +/// https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-metadata-attributes +fun composeCollectionMetadata( + name: String, // full name + description: String, // text description of the NFT + image: String, // link to the image + // There could be other data, see: + // https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-metadata-attributes +): Cell { + let dict: map = emptyMap(); + dict.set(sha256("name"), name.asMetadataCell()); + dict.set(sha256("description"), description.asMetadataCell()); + dict.set(sha256("image"), image.asMetadataCell()); + + return beginCell() + .storeUint(0, 8) // a null byte prefix + .storeMaybeRef(dict.asCell()!!) // 1 as a single bit, then a reference + .endCell(); +} + +// Taking flight! +fun poorMansLaunchPad() { + let collectionMetadata = composeCollectionMetadata( + "Best Collection", + "A very descriptive description describing the collection descriptively", + "...link to ipfs or somewhere trusted...", + ); +} + +// Prefixes the String with a single null byte and converts it to a Cell +// The null byte prefix is used to express metadata in various standards, like NFT or Jetton +inline extends fun asMetadataCell(self: String): Cell { + return beginTailString().concat(self).toCell(); +} +``` + +:::note[Useful links:] + + [Token Data Standard in TEPs](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-metadata-attributes)\ + [Off-chain NFT metadata by GetGems](https://github.com/getgems-io/nft-contracts/blob/main/docs/metadata.md) + +::: + +### NFT Item {#onchain-metadata-nft-item} + +```tact +/// https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-metadata-attributes +fun composeItemMetadata( + name: String, // full name + description: String, // text description of the NFT + image: String, // link to the image + // There could be other data, see: + // https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-metadata-attributes +): Cell { + let dict: map = emptyMap(); + dict.set(sha256("name"), name.asMetadataCell()); + dict.set(sha256("description"), description.asMetadataCell()); + dict.set(sha256("image"), image.asMetadataCell()); + + return beginCell() + .storeUint(0, 8) // a null byte prefix + .storeMaybeRef(dict.asCell()!!) // 1 as a single bit, then a reference + .endCell(); +} + +// Taking flight! +fun poorMansLaunchPad() { + let itemMetadata = composeItemMetadata( + "Best Item", + "A very descriptive description describing the item descriptively", + "...link to ipfs or somewhere trusted...", + ); +} + +// Prefixes the String with a single null byte and converts it to a Cell +// The null byte prefix is used to express metadata in various standards, like NFT or Jetton +inline extends fun asMetadataCell(self: String): Cell { + return beginTailString().concat(self).toCell(); +} +``` + +:::note[Useful links:] + + [Token Data Standard in TEPs](https://github.com/ton-blockchain/TEPs/blob/master/text/0064-token-data-standard.md#nft-metadata-attributes)\ + [Off-chain NFT metadata by GetGems](https://github.com/getgems-io/nft-contracts/blob/main/docs/metadata.md) + +::: + :::tip[Hey there!] Didn't find your favorite example of a NFT communication? Have cool implementations in mind? [Contributions are welcome!](https://github.com/tact-lang/tact/issues)