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::Listing
Initialises 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::ID
Creates 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::ID
Creates 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
Market
type does not correspond tovenue_id
on theListing
MarketWitness
does not correspond toMarket
type- 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
Market
type does not correspond tovenue_id
on theListing
MarketWitness
does not correspond toMarket
type- Underlying
Inventory
is not aWarehouse
and 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
Market
type does not correspond tovenue_id
on theListing
MarketWitness
does not correspond toMarket
type- Underlying
Inventory
is not aWarehouse
and there is no supply user_commitment
does 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
Inventory
with the given ID does not existInventory
with 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::ID
Adds 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::ID
Adds 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::Proceeds
Borrow 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::Proceeds
Mutably 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,
): bool
Returns 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::Venue
Borrow 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,
): &Market
Borrow 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::Venue
Mutably 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 Market
Mutably 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,
): bool
Returns 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,
)