/generator

A collection of libraries and smart contracts to facilitate dynamic NFT metadata and image generation on Solana with the Metaplex standard. This is used in a variety of ways in the ecosystem to create dynamic and on-chain NFTs

Primary LanguageTypeScriptGNU Affero General Public License v3.0AGPL-3.0

Generator

Background

Generator encompasses serverless functions and smart contracts for rendering generative NFTs. The API defines a standard way to point to indicate pointers to any on-chain data that will be dynamically read and returned into the metadata of the NFT. In addition, there is an implementation of an on-chain mapping that fits this API spec to allow for more complex updating of this mapping. Generator works well with standard NFT collections and fits within the Metaplex NFT standard. It also composes with other programs in the NFT infrastructure ecosystem.

Addresses

Program addresses are the same on devnet, testnet, and mainnet-beta.

Documentation

Generator is mainly an API that is designed to fit within the metaplex NFT standard, but bring the composability of on-chain data directly into the NFTs. This allows for more complex NFT use cases to compose directly with the attributes of the NFT while still maintaining compatibility with all wallet and marketplaces. Because this generator is dynamic, it means any time you view or load the NFT it will pull fresh on-chain data. Being serverless also means there is no dependency on infrastructure and scales horizontally. The long term vision of this project is to either adopt these practices within apps directly so they do not need to rely on the API, or run the API on a decentralized computing platform. For the time being, it serves to fit dynamic NFTs into the existing Solana NFT rails.

Dynamic Attributes

Dynamic attributes have a separate parameters that allows for generic setting of any attributes on the NFT based on other on-chain data

  • uri

    • The uri field to provide the existing base metadata
  • attrs

    • attrs= is a list of "attribute group" objects separates by ; semi-colons
    • Each "attribute group" can contain optional scopes, denoted with . and then contains one or more "field groups"
    • If scoped, the scopes should precede the field group and be in the format of {address}.{accountName}. where address is the account address and accountName is the name of this account to deserialize into. This account will be queried from on-chain and deserialized using the given accountName and the IDL for the owning program
    • Following the scopes, will be "field groups", where each field group can contain key:value:display_type separated by :. Each piece is optional. If scoped, the value will be looked up in the corresponding account by name. If not scoped, the value will be used as a string value.
    • Attributes come in the form with the following fallback logic allowing for 1, 2 or 3 fields specified in the field group
    const fieldGroup = fieldGroupString.split(":")
    const attribute = {
      "display_type": fieldGroup[0],
      value: scopeData
        ? scopeData[fieldGroup[1] ?? fieldGroup[0]].toString()
        : fieldGroup[1] ?? fieldGroup[0],
      trait_type: fieldGroup[2] ?? fieldGroup[0],
    }