🔗 On chain Collections

Perpetual3 offers an innovative way for merchants to publish on-chain collections directly.

Currently, our system supports Algorand for this functionality. This feature brings to the platform a whole new level of interactivity and exclusivity. Here are the types of on-chain collections that can be published by merchants:

  1. Phygital without Max Supply or Time Limits: This type of collection is for physical goods that have a digital counterpart represented as a NFT. There are no restrictions on the supply or availability of these collections, meaning they can be minted and purchased without any constraints on quantity or time.

  2. Phygital with Max Supply: Similar to the previous type, these collections represent physical goods that have a digital counterpart represented as a NFT. However, in this case, there is a limit on the total number of items that can be minted. This creates a scarcity factor that can drive the value of items within the collection.

  3. Phygital with Time Limits: This type also represents physical goods with a phygital counterpart represented as a NFT, but with an added constraint of time. The items in these collections can only be bought within a certain timeframe, adding an element of urgency and exclusivity to the collection, time limits are enforced using round numbers.

  4. Token Gated: These collections are accessible only to holders of specific tokens. This allows for the creation of exclusive collections and experiences for token holders. For instance, a merchant could create a collection that is only accessible to their token holders, effectively rewarding them with exclusive access to certain goods or experiences.

As Perpetual3 continues to evolve, we aim to add support for more types of collections and blockchain networks. This will enable our platform to cater to a larger user base and offer more flexibility to our merchants.

Perpetual3 makes use of PyTeal, a Python language binding for Algorand Smart Contracts (ASC1), to define the on-chain collections. The provided code snippet outlines the creation of an on-chain collection.

@Subroutine(TealType.none)
def collection_init():
    collection_name = Txn.application_args[1]
    merchant_pubkey = Txn.application_args[2]
    collection_max_supply = Txn.application_args[3]
    collection_first_valid = Txn.application_args[4]
    collection_last_valid = Txn.application_args[5]
    collection_image_url = Txn.application_args[6]
    collection_requirement_type = Txn.application_args[7]
    collection_requirement_ID = Txn.application_args[8]
    # phygital, tokengate, phygitaltokengate
    collection_type = Txn.application_args[9]

    fees_calculator = ScratchVar(TealType.uint64)

    baseBox = Sha256(Concat(collection_name, merchant_pubkey,
                     Txn.sender(), collection_type))

    fees_payment = Gtxn[1]

    collectionMintedAmount = Concat(baseBox, Bytes("A"))
    collectionMaxSupply = Concat(baseBox, Bytes("B"))
    collectionFirstValid = Concat(baseBox, Bytes("C"))
    collectionLastValid = Concat(baseBox, Bytes("D"))
    collectionImageUrl = Concat(baseBox, Bytes("E"))
    collectionrequirementTypeBoxName = Concat(baseBox, Bytes("F"))
    collectionrequirementIDBoxName = Concat(baseBox, Bytes("G"))

    return Seq([
        fees_calculator.store(Mul(Int(2500), Int(7))),
        fees_calculator.store(Mul(Int(400), Len(Concat(
            collectionMintedAmount, collectionMaxSupply, collectionLastValid, collectionImageUrl)))),

        Assert(fees_payment.amount() >= fees_calculator.load()),
        Assert(fees_payment.receiver() == Global.current_application_address()),

        App.box_put(collectionMintedAmount, Itob(Int(0))),
        App.box_put(collectionMaxSupply, collection_max_supply),
        App.box_put(collectionFirstValid, collection_first_valid),
        App.box_put(collectionLastValid, collection_last_valid),
        App.box_put(collectionImageUrl, collection_image_url),
        App.box_put(collectionrequirementTypeBoxName,
                    collection_requirement_type),
        App.box_put(collectionrequirementIDBoxName, collection_requirement_ID),
    ])

In the context of this code:

  1. The application arguments define the parameters of the collection.

  2. A ScratchVar is defined to calculate the fee required for the operation.

  3. The baseBox is a hashed concatenation of collection_name, merchant pub key, the transaction sender, and collection_type.

  4. Multiple storage locations (App.box_put()) are defined to store various aspects of the collection, such as the max supply, first valid, last valid, image URL, and requirement ID.

  5. The transaction fees are calculated and asserted, ensuring they meet the required amount for storing data in box storage.

Remember that all the collections' data is stored in Algorand's "box" storage associated with smart contracts, ensuring security and immutability of data. As a developer or merchant, you can interact with this smart contract to initialize collections with different attributes.

Last updated