Module for an NFT Listing
A Listing allows creators to sell their NFTs to the primary market using
bespoke market primitives, such as FixedPriceMarket and
DutchAuctionMarket.
Listing can be standalone or be attached to Marketplace.
Associated Marketplace objects may stipulate a fee policy, the
marketplace admin can decide to create a custom fee policy for each
Listing.
Listing may define multiple Inventory objects which themselves can
define multiple markets.
In consequence, each Listing may tier it's sales into different NFT
rarities, but may also want to sell one NFT inventory through different
sales channels.
For example, a creator might want to auction a rare tier of their
collection or provide an instant-buy option for users not wanting to
participate in the auction.
Alternatively, an inventory listing may want to sell NFTs for multiple
fungible tokens.
In essence, Listing is a shared object that provides a safe API to the
underlying inventories which are unprotected.
Structs
listing::Listing has store, key
listing::Listing has store, key
Fields:
| Name | Type | Description |
|---|---|---|
id
|
object::UID
|
|
marketplace_id
|
option::Option<typed_id::TypedID<marketplace::Marketplace>>
|
The ID of the marketplace if any |
admin
|
address
|
The address of the |
receiver
|
address
|
The address of the receiver of funds |
proceeds
|
proceeds::Proceeds
|
Proceeds object holds the balance of fungible tokens acquired from the sale of the listing |
venues
|
object_table::ObjectTable<object::ID, venue::Venue>
|
Main object that holds all venues part of the listing |
inventories
|
object_bag::ObjectBag
|
Main object that holds all inventories part of the listing |
custom_fee
|
object_box::ObjectBox
|
Field with Object Box holding a Custom Fee implementation if any. In case this box is empty the calculation will applied on the default fee object in the associated Marketplace |
listing::RequestToJoin has store, key
listing::RequestToJoin has store, key
Fields:
| Name | Type | Description |
|---|---|---|
id
|
object::UID
|
|
marketplace_id
|
typed_id::TypedID<marketplace::Marketplace>
|
An ephemeral object representing the intention of a Listing admin
to join a given Marketplace.
listing::CreateListingEvent has copy, drop
listing::CreateListingEvent has copy, drop
Fields:
| Name | Type | Description |
|---|---|---|
listing_id
|
object::ID
|
Event signalling that a Listing was created
listing::DeleteListingEvent has copy, drop
listing::DeleteListingEvent has copy, drop
Fields:
| Name | Type | Description |
|---|---|---|
listing_id
|
object::ID
|
Event signalling that a Listing was deleted
listing::NftSoldEvent has copy, drop
listing::NftSoldEvent has copy, drop
Fields:
| Name | Type | Description |
|---|---|---|
nft
|
object::ID
|
|
price
|
u64
|
|
ft_type
|
ascii::String
|
|
nft_type
|
ascii::String
|
|
buyer
|
address
|
Event signalling that Nft was sold by Listing
Methods
public fun new(
listing_admin: address,
receiver: address,
ctx: &mut tx_context::TxContext,
): listing::Listing
public fun new(
listing_admin: address,
receiver: address,
ctx: &mut tx_context::TxContext,
): listing::ListingInitialises a Listing object and returns it.
public entry fun init_listing(
listing_admin: address,
receiver: address,
ctx: &mut tx_context::TxContext,
)
public entry fun init_listing(
listing_admin: address,
receiver: address,
ctx: &mut tx_context::TxContext,
)Initialises a standalone Listing object.
public entry fun init_venue<Market: store>(
listing: &mut listing::Listing,
market: Market,
is_whitelisted: bool,
ctx: &mut tx_context::TxContext,
)
public entry fun init_venue<Market: store>(
listing: &mut listing::Listing,
market: Market,
is_whitelisted: bool,
ctx: &mut tx_context::TxContext,
)Initializes a Venue on Listing
Panics
Panics if transaction sender is not listing admin.
public fun create_venue<Market: store>(
listing: &mut listing::Listing,
market: Market,
is_whitelisted: bool,
ctx: &mut tx_context::TxContext,
): object::ID
public fun create_venue<Market: store>(
listing: &mut listing::Listing,
market: Market,
is_whitelisted: bool,
ctx: &mut tx_context::TxContext,
): object::IDCreates a Venue on Listing and returns it's ID
Panics
Panics if transaction sender is not listing admin.
public entry fun init_warehouse<C>(
listing: &mut listing::Listing,
collection: &collection::Collection<C>,
ctx: &mut tx_context::TxContext,
)
public entry fun init_warehouse<C>(
listing: &mut listing::Listing,
collection: &collection::Collection<C>,
ctx: &mut tx_context::TxContext,
)Initializes an empty Warehouse on Listing
Requires that transaction sender is collection creator registered in
CreatorsDomain.
Panics
Panics if transaction sender is not listing admin or creator.
public fun create_warehouse<C>(
witness: witness::Witness<C>,
listing: &mut listing::Listing,
ctx: &mut tx_context::TxContext,
): object::ID
public fun create_warehouse<C>(
witness: witness::Witness<C>,
listing: &mut listing::Listing,
ctx: &mut tx_context::TxContext,
): object::IDCreates an empty Warehouse on Listing and returns it's ID
Function transparently wraps Warehouse in Inventory, therefore, the
returned ID is that of the Inventory not the Warehouse.
Panics
Panics if transaction sender is not listing admin.
public fun pay<FT>(
listing: &mut listing::Listing,
balance: balance::Balance<FT>,
quantity: u64,
)
public fun pay<FT>(
listing: &mut listing::Listing,
balance: balance::Balance<FT>,
quantity: u64,
)Pay for Nft sale and direct funds to Listing proceeds
public fun emit_sold_event<FT, C>(
nft: &nft::Nft<C>,
price: u64,
)
public fun emit_sold_event<FT, C>(
nft: &nft::Nft<C>,
price: u64,
)Emits NftSoldEvent for provided Nft
Buyer is set to the logical_owner of the Nft.
public fun pay_and_emit_sold_event<FT, C>(
listing: &mut listing::Listing,
nft: &nft::Nft<C>,
balance: &mut balance::Balance<FT>,
price: u64,
)
public fun pay_and_emit_sold_event<FT, C>(
listing: &mut listing::Listing,
nft: &nft::Nft<C>,
balance: &mut balance::Balance<FT>,
price: u64,
)Pay for Nft sale, direct fund to Listing proceeds, and emit sale
events.
Will charge price from the provided Balance object.
Panics
Panics if balance is not enough to fund price
public fun buy_nft<C, FT, Market: store, MarketWitness: drop>(
witness: MarketWitness,
listing: &mut listing::Listing,
inventory_id: object::ID,
venue_id: object::ID,
owner: address,
price: u64,
balance: &mut balance::Balance<FT>,
ctx: &mut tx_context::TxContext,
):
nft::Nft<C>
public fun buy_nft<C, FT, Market: store, MarketWitness: drop>(
witness: MarketWitness,
listing: &mut listing::Listing,
inventory_id: object::ID,
venue_id: object::ID,
owner: address,
price: u64,
balance: &mut balance::Balance<FT>,
ctx: &mut tx_context::TxContext,
):
nft::Nft<C>Buys an NFT from an Inventory
Only venues registered on the Listing have authorization to withdraw
from an Inventory, therefore this operation must be authorized using
a witness that corresponds to the market contract.
Endpoint will redeem NFTs sequentially, if you need random withdrawal
use buy_pseudorandom_nft or buy_random_nft.
Panics
Markettype does not correspond tovenue_idon theListingMarketWitnessdoes not correspond toMarkettype- No supply is available from underlying
Inventory
public fun buy_pseudorandom_nft<C, FT, Market: store, MarketWitness: drop>(
witness: MarketWitness,
listing: &mut listing::Listing,
inventory_id: object::ID,
venue_id: object::ID,
owner: address,
price: u64,
balance: &mut balance::Balance<FT>,
ctx: &mut tx_context::TxContext,
):
nft::Nft<C>
public fun buy_pseudorandom_nft<C, FT, Market: store, MarketWitness: drop>(
witness: MarketWitness,
listing: &mut listing::Listing,
inventory_id: object::ID,
venue_id: object::ID,
owner: address,
price: u64,
balance: &mut balance::Balance<FT>,
ctx: &mut tx_context::TxContext,
):
nft::Nft<C>Buys a pseudo-random NFT from an Inventory
Only venues registered on the Listing have authorization to withdraw
from an Inventory, therefore this operation must be authorized using
a witness that corresponds to the market contract.
Endpoint is susceptible to validator prediction of the resulting index,
use buy_random_nft instead.
Panics
Markettype does not correspond tovenue_idon theListingMarketWitnessdoes not correspond toMarkettype- Underlying
Inventoryis not aWarehouseand there is no supply
public fun buy_random_nft<C, FT, Market: store, MarketWitness: drop>(
witness: MarketWitness,
listing: &mut listing::Listing,
commitment: warehouse::RedeemCommitment,
user_commitment: vector<u8>,
inventory_id: object::ID,
venue_id: object::ID,
owner: address,
price: u64,
balance: &mut balance::Balance<FT>,
ctx: &mut tx_context::TxContext,
):
nft::Nft<C>
public fun buy_random_nft<C, FT, Market: store, MarketWitness: drop>(
witness: MarketWitness,
listing: &mut listing::Listing,
commitment: warehouse::RedeemCommitment,
user_commitment: vector<u8>,
inventory_id: object::ID,
venue_id: object::ID,
owner: address,
price: u64,
balance: &mut balance::Balance<FT>,
ctx: &mut tx_context::TxContext,
):
nft::Nft<C>Buys a random NFT from Inventory
Requires a RedeemCommitment created by the user in a separate
transaction to ensure that validators may not bias results favorably.
You can obtain a RedeemCommitment by calling
warehouse::init_redeem_commitment.
Only venues registered on the Listing have authorization to withdraw
from an Inventory, therefore this operation must be authorized using
a witness that corresponds to the market contract.
Panics
Markettype does not correspond tovenue_idon theListingMarketWitnessdoes not correspond toMarkettype- Underlying
Inventoryis not aWarehouseand there is no supply user_commitmentdoes not match the hashed commitment inRedeemCommitment
public entry fun request_to_join_marketplace(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
ctx: &mut tx_context::TxContext,
)
public entry fun request_to_join_marketplace(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
ctx: &mut tx_context::TxContext,
)To be called by the Listing administrator, to declare the intention
of joining a Marketplace. This is the first step to join a marketplace.
Joining a Marketplace is a two step process in which both the
Listing admin and the Marketplace admin need to declare their
intention to partner up.
public entry fun accept_listing_request(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
ctx: &mut tx_context::TxContext,
)
public entry fun accept_listing_request(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
ctx: &mut tx_context::TxContext,
)To be called by the Marketplace administrator, to accept the Listing
request to join. This is the second step to join a marketplace.
Joining a Marketplace is a two step process in which both the
Listing admin and the Marketplace admin need to declare their
intention to partner up.
public entry fun add_fee<FeeType: store + key>(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
fee: FeeType,
ctx: &mut tx_context::TxContext,
)
public entry fun add_fee<FeeType: store + key>(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
fee: FeeType,
ctx: &mut tx_context::TxContext,
)Adds a fee object to the Listing's custom_fee
Can only be called by the Marketplace admin
public entry fun add_venue(
listing: &mut listing::Listing,
venue: venue::Venue,
ctx: &mut tx_context::TxContext,
)
public entry fun add_venue(
listing: &mut listing::Listing,
venue: venue::Venue,
ctx: &mut tx_context::TxContext,
)Adds a Venue to the Listing
Panics
Panics if inventory that Venue is assigned to does not exist or if
transaction sender is not the listing admin.
public entry fun add_nft<C>(
listing: &mut listing::Listing,
inventory_id: object::ID,
nft: nft::Nft<C>,
ctx: &mut tx_context::TxContext,
)
public entry fun add_nft<C>(
listing: &mut listing::Listing,
inventory_id: object::ID,
nft: nft::Nft<C>,
ctx: &mut tx_context::TxContext,
)Adds an Nft to a Warehouse on the Listing
To avoid shared consensus during mass minting, Warehouse can be
constructed as a private object and later inserted into the Listing.
Panics
Inventorywith the given ID does not existInventorywith the given ID is not aWarehouse- Transaction sender is not the listing admin
public entry fun add_inventory<C>(
listing: &mut listing::Listing,
inventory: inventory::Inventory<C>,
ctx: &mut tx_context::TxContext,
)
public entry fun add_inventory<C>(
listing: &mut listing::Listing,
inventory: inventory::Inventory<C>,
ctx: &mut tx_context::TxContext,
)Adds Inventory to Listing
Inventory is a type-erased wrapper around Warehouse or Factory.
To create a new inventory call inventory::from_warehouse or
inventory::from_factory.
Panics
Panics if transaction sender is not the listing admin
public entry fun add_warehouse<C>(
listing: &mut listing::Listing,
collection: &collection::Collection<C>,
warehouse: warehouse::Warehouse<C>,
ctx: &mut tx_context::TxContext,
)
public entry fun add_warehouse<C>(
listing: &mut listing::Listing,
collection: &collection::Collection<C>,
warehouse: warehouse::Warehouse<C>,
ctx: &mut tx_context::TxContext,
)Adds Warehouse to Listing
Function transparently wraps Warehouse in Inventory, therefore, the
returned ID is that of the Inventory not the Warehouse.
Panics
Panics if transaction sender is not listing admin or creator registered
in CreatorsDomain.
public fun insert_warehouse<C>(
witness: witness::Witness<C>,
listing: &mut listing::Listing,
warehouse: warehouse::Warehouse<C>,
ctx: &mut tx_context::TxContext,
): object::ID
public fun insert_warehouse<C>(
witness: witness::Witness<C>,
listing: &mut listing::Listing,
warehouse: warehouse::Warehouse<C>,
ctx: &mut tx_context::TxContext,
): object::IDAdds Warehouse to Listing and returns it's ID
Function transparently wraps Warehouse in Inventory, therefore, the
returned ID is that of the Inventory not the Warehouse.
Panics
Panics if transaction sender is not listing admin.
public entry fun add_factory<C>(
listing: &mut listing::Listing,
collection: &collection::Collection<C>,
factory: factory::Factory<C>,
ctx: &mut tx_context::TxContext,
)
public entry fun add_factory<C>(
listing: &mut listing::Listing,
collection: &collection::Collection<C>,
factory: factory::Factory<C>,
ctx: &mut tx_context::TxContext,
)Adds Factory to Listing
Function transparently wraps Factory in Inventory, therefore, the
returned ID is that of the Inventory not the Factory.
Panics
Panics if transaction sender is not listing admin or creator registered
in CreatorsDomain.
public fun insert_factory<C>(
witness: witness::Witness<C>,
listing: &mut listing::Listing,
factory: factory::Factory<C>,
ctx: &mut tx_context::TxContext,
): object::ID
public fun insert_factory<C>(
witness: witness::Witness<C>,
listing: &mut listing::Listing,
factory: factory::Factory<C>,
ctx: &mut tx_context::TxContext,
): object::IDAdds Factory to Listing and returns it's ID
Function transparently wraps Factory in Inventory, therefore, the
returned ID is that of the Inventory not the Factory.
Panics
Panics if transaction sender is not listing admin.
public entry fun sale_on(
listing: &mut listing::Listing,
venue_id: object::ID,
ctx: &mut tx_context::TxContext,
)
public entry fun sale_on(
listing: &mut listing::Listing,
venue_id: object::ID,
ctx: &mut tx_context::TxContext,
)Set market's live status to true therefore making the NFT sale live.
To be called by the Listing admin.
public entry fun sale_off(
listing: &mut listing::Listing,
venue_id: object::ID,
ctx: &mut tx_context::TxContext,
)
public entry fun sale_off(
listing: &mut listing::Listing,
venue_id: object::ID,
ctx: &mut tx_context::TxContext,
)Set market's live status to false therefore pausing or stopping the
NFT sale. To be called by the Listing admin.
public entry fun sale_on_delegated(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
venue_id: object::ID,
ctx: &mut tx_context::TxContext,
)
public entry fun sale_on_delegated(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
venue_id: object::ID,
ctx: &mut tx_context::TxContext,
)Set market's live status to true therefore making the NFT sale live.
To be called by the Marketplace admin.
public entry fun sale_off_delegated(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
venue_id: object::ID,
ctx: &mut tx_context::TxContext,
)
public entry fun sale_off_delegated(
marketplace: &marketplace::Marketplace,
listing: &mut listing::Listing,
venue_id: object::ID,
ctx: &mut tx_context::TxContext,
)Set market's live status to false therefore pausing or stopping the
NFT sale. To be called by the Marketplace admin.
public entry fun collect_proceeds<FT>(
listing: &mut listing::Listing,
ctx: &mut tx_context::TxContext,
)
public entry fun collect_proceeds<FT>(
listing: &mut listing::Listing,
ctx: &mut tx_context::TxContext,
)To be called by Listing admins for standalone Listings.
Standalone Listings do not envolve marketplace fees, and therefore
the listing admin can freely call this entrypoint.
public fun contains_custom_fee(listing: &listing::Listing): bool
public fun contains_custom_fee(listing: &listing::Listing): bool
public fun custom_fee(listing: &listing::Listing):
&object_box::ObjectBox
public fun custom_fee(listing: &listing::Listing):
&object_box::ObjectBox
public fun borrow_proceeds(listing: &listing::Listing):
&proceeds::Proceeds
public fun borrow_proceeds(listing: &listing::Listing):
&proceeds::ProceedsBorrow the Listing's Proceeds
public fun borrow_proceeds_mut(listing: &mut listing::Listing):
&mut proceeds::Proceeds
public fun borrow_proceeds_mut(listing: &mut listing::Listing):
&mut proceeds::ProceedsMutably borrow the Listing's Proceeds
public fun contains_venue(
listing: &listing::Listing,
venue_id: object::ID,
): bool
public fun contains_venue(
listing: &listing::Listing,
venue_id: object::ID,
): boolReturns whether Venue with given ID exists
public fun borrow_venue(
listing: &listing::Listing,
venue_id: object::ID,
): &venue::Venue
public fun borrow_venue(
listing: &listing::Listing,
venue_id: object::ID,
): &venue::VenueBorrow the listing's Venue
Panics
Panics if Venue does not exist.
public fun borrow_market<Market: store>(
listing: &listing::Listing,
venue_id: object::ID,
): &Market
public fun borrow_market<Market: store>(
listing: &listing::Listing,
venue_id: object::ID,
): &MarketBorrow the listing's Market
Panics
Panics if Market does not exist.
public fun venue_internal_mut<Market: store, Witness: drop>(
_witness: Witness,
listing: &mut listing::Listing,
venue_id: object::ID,
):
&mut venue::Venue
public fun venue_internal_mut<Market: store, Witness: drop>(
_witness: Witness,
listing: &mut listing::Listing,
venue_id: object::ID,
):
&mut venue::VenueMutably borrow the listing's Venue
Venue and inventories are unprotected therefore only market modules
registered on a Venue can gain mutable access to it.
Panics
Panics if witness does not originate from the same module as market.
public fun market_internal_mut<Market: store, Witness: drop>(
witness: Witness,
listing: &mut listing::Listing,
venue_id: object::ID,
):
&mut Market
public fun market_internal_mut<Market: store, Witness: drop>(
witness: Witness,
listing: &mut listing::Listing,
venue_id: object::ID,
):
&mut MarketMutably borrow the Listing's Market
Market is unprotected therefore only market modules registered
on a Venue can gain mutable access to it.
Panics
Panics if witness does not originate from the same module as market.
public fun contains_inventory<C>(
listing: &listing::Listing,
inventory_id: object::ID,
): bool
public fun contains_inventory<C>(
listing: &listing::Listing,
inventory_id: object::ID,
): boolReturns whether Inventory with given ID exists
public fun borrow_inventory<C>(
listing: &listing::Listing,
inventory_id: object::ID,
): &inventory::Inventory<C>
public fun borrow_inventory<C>(
listing: &listing::Listing,
inventory_id: object::ID,
): &inventory::Inventory<C>Borrow the listing's Inventory
Panics
Panics if Inventory does not exist.
public fun inventory_internal_mut<C, Market: store, Witness: drop>(
witness: Witness,
listing: &mut listing::Listing,
venue_id: object::ID,
inventory_id: object::ID,
):
&mut inventory::Inventory<C>
public fun inventory_internal_mut<C, Market: store, Witness: drop>(
witness: Witness,
listing: &mut listing::Listing,
venue_id: object::ID,
inventory_id: object::ID,
):
&mut inventory::Inventory<C>Mutably borrow a Warehouse
Warehouse is unprotected therefore only market modules
registered on a Venue can gain mutable access to it.
Panics
Panics if witness does not originate from the same module as market.
public fun supply<C>(
listing: &listing::Listing,
inventory_id: object::ID,
): option::Option<u64>
public fun supply<C>(
listing: &listing::Listing,
inventory_id: object::ID,
): option::Option<u64>Returns how many NFTs can be withdrawn
Returns none if the supply is uncapped
Panics
Panics if Warehouse or Listing with the ID does not exist
public fun assert_listing_marketplace_match(
marketplace: &marketplace::Marketplace,
listing: &listing::Listing,
)
public fun assert_listing_marketplace_match(
marketplace: &marketplace::Marketplace,
listing: &listing::Listing,
)
public fun assert_listing_admin(
listing: &listing::Listing,
ctx: &mut tx_context::TxContext,
)
public fun assert_listing_admin(
listing: &listing::Listing,
ctx: &mut tx_context::TxContext,
)
public fun assert_correct_admin(
marketplace: &marketplace::Marketplace,
listing: &listing::Listing,
ctx: &mut tx_context::TxContext,
)
public fun assert_correct_admin(
marketplace: &marketplace::Marketplace,
listing: &listing::Listing,
ctx: &mut tx_context::TxContext,
)
public fun assert_default_fee(listing: &listing::Listing)
public fun assert_default_fee(listing: &listing::Listing)
public fun assert_venue(
listing: &listing::Listing,
venue_id: object::ID,
)
public fun assert_venue(
listing: &listing::Listing,
venue_id: object::ID,
)
public fun assert_inventory<C>(
listing: &listing::Listing,
inventory_id: object::ID,
)
public fun assert_inventory<C>(
listing: &listing::Listing,
inventory_id: object::ID,
)