Module 0x2::kiosk_extension
This module implements the Kiosk Extensions functionality. It allows exposing previously protected (only-owner) methods to third-party apps.
A Kiosk Extension is a module that implements any functionality on top of
the Kiosk
without discarding nor blocking the base. Given that Kiosk
itself is a trading primitive, most of the extensions are expected to be
related to trading. However, there's no limit to what can be built using the
kiosk_extension
module, as it gives certain benefits such as using Kiosk
as the storage for any type of data / assets.
Flow:
- An extension can only be installed by the Kiosk Owner and requires an
authorization via the
KioskOwnerCap
. - When installed, the extension is given a permission bitmap that allows it
to perform certain protected actions (eg
place
,lock
). However, it is possible to install an extension that does not have any permissions. - Kiosk Owner can
disable
the extension at any time, which prevents it from performing any protected actions. The storage is still available to the extension until it is completely removed. - A disabled extension can be
enable
d at any time giving the permissions back to the extension. - An extension permissions follow the all-or-nothing policy. Either all of the requested permissions are granted or none of them (can't install).
Examples:
- An Auction extension can utilize the storage to store Auction-related data
while utilizing the same
Kiosk
object that the items are stored in. - A Marketplace extension that implements custom events and fees for the default trading functionality.
Notes:
-
Trading functionality can utilize the
PurchaseCap
to build a custom logic around the purchase flow. However, it should be carefully managed to prevent asset locking. -
kiosk_extension
is a friend module tokiosk
and has access to its internal functions (such asplace_internal
andlock_internal
to implement custom authorization scheme forplace
andlock
respectively).
use 0x2::bag;
use 0x2::dynamic_field;
use 0x2::kiosk;
use 0x2::object;
use 0x2::transfer_policy;
use 0x2::tx_context;
Struct Extension
The Extension struct contains the data used by the extension and the
configuration for this extension. Stored under the ExtensionKey
dynamic field.
struct Extension has store
Fields
Struct ExtensionKey
The ExtensionKey
is a typed dynamic field key used to store the
extension configuration and data. Ext
is a phantom type that is used
to identify the extension witness.
struct ExtensionKey<Ext> has copy, drop, store
Fields
Constants
Trying to add an extension while not being the owner of the Kiosk.
Extension is trying to access a permissioned action while not having the required permission.
const EExtensionNotAllowed: u64 = 2;
Extension is not installed in the Kiosk.
const EExtensionNotInstalled: u64 = 3;
Value that represents the lock
and place
permission in the
permissions bitmap.
const LOCK: u128 = 2;
Value that represents the place
permission in the permissions bitmap.
const PLACE: u128 = 1;
Function add
Add an extension to the Kiosk. Can only be performed by the owner. The
extension witness is required to allow extensions define their set of
permissions in the custom add
call.
public fun add<Ext: drop>(_ext: Ext, self: &mut kiosk::Kiosk, cap: &kiosk::KioskOwnerCap, permissions: u128, ctx: &mut tx_context::TxContext)
Implementation
Function disable
Revoke permissions from the extension. While it does not remove the extension completely, it keeps it from performing any protected actions. The storage is still available to the extension (until it's removed).
public fun disable<Ext: drop>(self: &mut kiosk::Kiosk, cap: &kiosk::KioskOwnerCap)
Implementation
Function enable
Re-enable the extension allowing it to call protected actions (eg
place
, lock
). By default, all added extensions are enabled. Kiosk
owner can disable them via disable
call.
public fun enable<Ext: drop>(self: &mut kiosk::Kiosk, cap: &kiosk::KioskOwnerCap)
Implementation
Function remove
Remove an extension from the Kiosk. Can only be performed by the owner, the extension storage must be empty for the transaction to succeed.
public fun remove<Ext: drop>(self: &mut kiosk::Kiosk, cap: &kiosk::KioskOwnerCap)
Implementation
Function storage
Get immutable access to the extension storage. Can only be performed by the extension as long as the extension is installed.
public fun storage<Ext: drop>(_ext: Ext, self: &kiosk::Kiosk): &bag::Bag
Implementation
Function storage_mut
Get mutable access to the extension storage. Can only be performed by the extension as long as the extension is installed. Disabling the extension does not prevent it from accessing the storage.
Potentially dangerous: extension developer can keep data in a Bag therefore never really allowing the KioskOwner to remove the extension. However, it is the case with any other solution (1) and this way we prevent intentional extension freeze when the owner wants to ruin a trade (2) - eg locking extension while an auction is in progress.
Extensions should be crafted carefully, and the KioskOwner should be aware of the risks.
public fun storage_mut<Ext: drop>(_ext: Ext, self: &mut kiosk::Kiosk): &mut bag::Bag
Implementation
Function place
Protected action: place an item into the Kiosk. Can be performed by an
authorized extension. The extension must have the place
permission or
a lock
permission.
To prevent non-tradable items from being placed into Kiosk
the method
requires a TransferPolicy
for the placed type to exist.
public fun place<Ext: drop, T: store, key>(_ext: Ext, self: &mut kiosk::Kiosk, item: T, _policy: &transfer_policy::TransferPolicy<T>)
Implementation
Function lock
Protected action: lock an item in the Kiosk. Can be performed by an
authorized extension. The extension must have the lock
permission.
public fun lock<Ext: drop, T: store, key>(_ext: Ext, self: &mut kiosk::Kiosk, item: T, _policy: &transfer_policy::TransferPolicy<T>)
Implementation
Function is_installed
Check whether an extension of type Ext
is installed.
public fun is_installed<Ext: drop>(self: &kiosk::Kiosk): bool
Implementation
Function is_enabled
Check whether an extension of type Ext
is enabled.
public fun is_enabled<Ext: drop>(self: &kiosk::Kiosk): bool
Implementation
Function can_place
Check whether an extension of type Ext
can place
into Kiosk.
public fun can_place<Ext: drop>(self: &kiosk::Kiosk): bool
Implementation
Function can_lock
Check whether an extension of type Ext
can lock
items in Kiosk.
Locking also enables place
.
public fun can_lock<Ext: drop>(self: &kiosk::Kiosk): bool
Implementation
Function extension
Internal: get a read-only access to the Extension.
fun extension<Ext: drop>(self: &kiosk::Kiosk): &kiosk_extension::Extension
Implementation
Function extension_mut
Internal: get a mutable access to the Extension.
fun extension_mut<Ext: drop>(self: &mut kiosk::Kiosk): &mut kiosk_extension::Extension