Marketplace

Dubhe ships a built-in marketplace for trading UserStorage records, so you don’t have to build escrow and settlement yourself. It supports two categories:

  • Unique items — non-fungible, single-slot records (a specific sword, a land plot).
  • Fungible resources — stackable balances (gold, tokens), traded by amount.

Enabling it: listable

Mark a resource listable: true in dubhe.config.ts; dubhe generate then produces the listing/buy wrappers for that resource:

resources: {
  sword: { listable: true, fields: { power: 'u32' } },         // unique item
  gold:  { listable: true, fungible: true, fields: { amount: 'u64' } } // fungible
}

See Resources config for the full annotation reference.

Fees

Fees are configured globally in DappHub:

ParameterDefaultMeaning
marketplace_fee_bps300 (3%)Fee on each sale, in basis points of the listing price
marketplace_dapp_share_bps5_000 (50%)Share of the fee credited to DappStorage; the rest goes to the framework treasury

The DApp admin can change the DApp’s share (0–100%) via update_marketplace_dapp_share; the overall fee rate is set by the framework admin.

Marketplace writes bypass write_count. buy_record, buy_fungible_record, restore_record, expire_listing, etc. write to UserStorage directly and do not consume unsettled-write quota (see Storage Fees). Each purchase instead pays the marketplace fee above.

Unique items

FunctionWhoEffect
take_recordseller (owner)Removes the record from the seller’s storage, returns a Listing<CoinType> to share
buy_recordbuyerTransfers the record into the buyer’s storage, splits proceeds + fee, returns change
restore_recordsellerCancels the listing and returns the record to the seller
expire_listinganyoneAfter listed_until, returns the record to the seller
// List (only the canonical_owner can list — session keys cannot)
let listing = dapp_system::take_record<DappKey, SUI>(
    dapp_key::new(), seller_storage, record_key, price, listed_until, ctx
);
transfer::public_share_object(listing);
 
// Buy
let change = dapp_system::buy_record<DappKey, SUI>(
    dapp_key::new(), dapp_hub, dapp_storage, listing, buyer_storage, payment, ctx
);

buy_record aborts if the buyer is the seller (no_permission), the listing has expired (scene_expired), or payment is insufficient (insufficient_payment).

Fungible resources

FunctionWhoEffect
take_fungible_recordsellerDeducts a listed amount from the seller’s balance
buy_fungible_recordbuyerAdds the listed amount to the buyer’s balance (accumulates)
cancel_fungible_listingsellerReturns the listed amount to the seller (additive)
expire_fungible_listinganyoneAfter the deadline, returns the amount to the seller

Fungible buys accumulate onto the buyer’s existing balance (overflow-checked with u256) and share the same self-trade / expiry / payment guards as buy_record.

Reading listings (client)

Marketplace listings are indexed in the marketplace_listings table. Query them with the GraphQL client helper:

const listings = await graphqlClient.getMarketplaceListings({
  dappKey,
  status: 'listed' // 'listed' | 'sold' | 'cancelled' | 'expired'
  // recordType, seller, first, after
});

See the Indexer reference and GraphQL Client for details.

Full API

For exact signatures and abort conditions of every marketplace function, see the dubhe-dapp skill’s dapp-api reference (Marketplace section).