Skip to content

Commit

Permalink
move 2024 kiosk
Browse files Browse the repository at this point in the history
  • Loading branch information
damirka committed Nov 5, 2024
1 parent d38f141 commit 2b04810
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 74 deletions.
115 changes: 56 additions & 59 deletions docs/content/standards/kiosk-apps.mdx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Kiosk Apps
description: Kiosk apps are a way to extend the functionality of Sui Kiosk while keeping the core functionality intact. You can develop apps to add new features to a kiosk without having to modify the core code or move the assets elsewhere.
description: Kiosk apps are a way to extend the functionality of Sui Kiosk while keeping the core functionality intact. You can develop apps to add new features to a kiosk without having to modify the core code or move the assets elsewhere.
---

Kiosk apps are a way to extend the functionality of Sui Kiosk while keeping the core functionality intact. You can develop apps to add new features to a kiosk without having to modify the core code or move the assets elsewhere.
Expand All @@ -24,7 +24,6 @@ Kiosk can carry additional dynamic fields and dynamic object fields. The `uid_mu

Function signature:


`kiosk::uid_mut_as_owner(self: &mut Kiosk, cap: &KioskOwnerCap): &mut UID`

### The public uid getter
Expand All @@ -36,28 +35,27 @@ Anyone can read the `uid` of kiosks. This allows third party modules to read the
You can attach custom dynamic fields to your kiosks that anyone can then read (but only you can modify), you can use this to implement basic apps. For example, a Kiosk Name app where you as the kiosk owner can set a name for the kiosk, attach it as a dynamic field, and make it readable by anyone.

```move
module examples::kiosk_name_ext {
use std::string::String;
use std::option::{Self, Option};
use sui::dynamic_field as df;
use sui::kiosk::{Self, Kiosk, KioskOwnerCap};
/// The dynamic field key for the Kiosk Name Extension
struct KioskName has copy, store, drop {}
/// Add a name to the Kiosk (in this implementation can be called only once)
public fun add(self: &mut Kiosk, cap: &KioskOwnerCap, name: String) {
let uid_mut = kiosk::uid_mut_as_owner(self, cap);
df::add(uid_mut, KioskName {}, name)
}
module examples::kiosk_name_ext;
use std::string::String;
use sui::dynamic_field as df;
use sui::kiosk::{Self, Kiosk, KioskOwnerCap};
/// The dynamic field key for the Kiosk Name Extension
struct KioskName has copy, store, drop {}
/// Try read the name of the Kiosk - if set - return Some(String), if not - None
public fun name(self: &Kiosk): Option<String> {
if (df::exists_(kiosk::uid(self), KioskName {})) {
option::some(*df::borrow(kiosk::uid(self), KioskName {}))
} else {
option::none()
}
/// Add a name to the Kiosk (in this implementation can be called only once)
public fun add(self: &mut Kiosk, cap: &KioskOwnerCap, name: String) {
let uid_mut = self.uid_mut_as_owner(cap);
df::add(uid_mut, KioskName {}, name)
}
/// Try read the name of the Kiosk - if set - return Some(String), if not - None
public fun name(self: &Kiosk): Option<String> {
if (df::exists_(self.uid(), KioskName {})) {
option::some(*df::borrow(self.uid(), KioskName {}))
} else {
option::none()
}
}
```
Expand All @@ -75,11 +73,11 @@ In addition to limited and constrained access to storage, app permissions are al
The `kiosk_extension` module addresses concerns over owner bottlenecks and provides more guarantees for storage access. The module provides a set of functions that enable you to perform certain actions in the kiosk without the kiosk owner's involvement and have a guarantee that the storage of the app is not tampered with.

```move
module example::my_extension {
use sui::kiosk_extension;
module example::my_extension;
// ...
}
use sui::kiosk_extension;
// ...
```

## App lifecycle
Expand All @@ -100,19 +98,21 @@ For the app to function, the kiosk owner first needs to install it. To achieve t
The signature of the `kiosk_extension::add` function requires the app witness, making it impossible to install an app without an explicit implementation. The following example shows how to implement the `add` function for an app that requires the `place` permission:

```move
module examples::letterbox_ext {
// ... dependencies
module examples::letterbox_ext;
/// The expected set of permissions for extension. It requires `place`.
const PERMISSIONS: u128 = 1;
use sui::kiosk_extension;
/// The Witness struct used to identify and authorize the extension.
struct Extension has drop {}
// ... dependencies
/// Install the Mallbox extension into the Kiosk.
public fun add(kiosk: &mut Kiosk, cap: &KioskOwnerCap, ctx: &mut TxContext) {
kiosk_extension::add(Extension {}, kiosk, cap, PERMISSIONS, ctx)
}
/// The expected set of permissions for extension. It requires `place`.
const PERMISSIONS: u128 = 1;
/// The Witness struct used to identify and authorize the extension.
struct Extension has drop {}
/// Install the Mallbox extension into the Kiosk.
public fun add(kiosk: &mut Kiosk, cap: &KioskOwnerCap, ctx: &mut TxContext) {
kiosk_extension::add(Extension {}, kiosk, cap, PERMISSIONS, ctx)
}
```

Expand Down Expand Up @@ -142,19 +142,18 @@ Currently, Sui Kiosk has only two permissions: `place` (first bit) and `lock` an
It's considered good practice to define a constant containing permissions of the app:

```move
module examples::letterbox_ext {
// ... dependencies
module examples::letterbox_ext;
// ... dependencies
/// The expected set of permissions for the app. It requires `place`.
const PERMISSIONS: u128 = 1;
/// The expected set of permissions for the app. It requires `place`.
const PERMISSIONS: u128 = 1;
/// The witness struct used to identify and authorize the app.
struct Extension has drop {}
/// The witness struct used to identify and authorize the app.
struct Extension has drop {}
/// Install the Mallbox app into the kiosk and request `place` permission.
public fun add(kiosk: &mut Kiosk, cap: &KioskOwnerCap, ctx: &mut TxContext) {
kiosk_extension::add(Extension {}, kiosk, cap, PERMISSIONS, ctx)
}
/// Install the Mallbox app into the kiosk and request `place` permission.
public fun add(kiosk: &mut Kiosk, cap: &KioskOwnerCap, ctx: &mut TxContext) {
kiosk_extension::add(Extension {}, kiosk, cap, PERMISSIONS, ctx)
}
```

Expand All @@ -163,18 +162,17 @@ module examples::letterbox_ext {
If an app requests and is granted permissions (and isn't disabled), it can access protected functions. The following example shows how to access the `place` function:

```move
module examples::letterbox_ext {
// ...
module examples::letterbox_ext;
// ...
/// Emitted when trying to place an item without permissions.
const ENotEnoughPermissions: u64 = 1;
/// Emitted when trying to place an item without permissions.
const ENotEnoughPermissions: u64 = 1;
/// Place a letter into the kiosk without the `KioskOwnerCap`.
public fun place(kiosk: &mut Kiosk, letter: Letter, policy: &TransferPolicy<T>) {
assert!(kiosk_extension::can_place<Extension>(kiosk), ENotEnoughPermissions)
/// Place a letter into the kiosk without the `KioskOwnerCap`.
public fun place(kiosk: &mut Kiosk, letter: Letter, policy: &TransferPolicy<T>) {
assert!(kiosk_extension::can_place<Extension>(kiosk), ENotEnoughPermissions)
kiosk_extension::place(Extension {}, kiosk, letter, policy)
}
kiosk_extension::place(Extension {}, kiosk, letter, policy)
}
```
Currently, two functions are available:
Expand Down Expand Up @@ -211,7 +209,7 @@ Use the `disable<Ext>(kiosk: &mut Kiosk, cap: &KioskOwnerCap)` function to disab

**Example PTB**

```move
```javascript
let txb = new TransactionBuilder();
let kioskArg = tx.object('<ID>');
let capArg = tx.object('<ID>');
Expand All @@ -231,7 +229,7 @@ The call fails if the storage is not empty.

**Example PTB**

```move
```javascript
let txb = new TransactionBuilder();
let kioskArg = tx.object('<ID>');
let capArg = tx.object('<ID>');
Expand All @@ -247,4 +245,3 @@ txb.moveCall({

- [NFT Rental](../guides/developer/nft/nft-rental.mdx): An example implementation of the Kiosk Apps standard that enables renting NFTs.
- [NFT Rental repository](https://github.com/MystenLabs/sui/tree/main/examples/move/nft-rental): GitHub repo that contains the source code for the NFT Rental app.

28 changes: 13 additions & 15 deletions docs/content/standards/kiosk.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -372,13 +372,12 @@ You can always borrow an asset from a kiosk immutably. You can use the `kiosk::b
### Immutably borrow an asset using Sui Move

```move
module examples::immutable_borrow {
use sui::object::ID;
use sui::kiosk::{Self, Kiosk, KioskOwnerCap};
module examples::immutable_borrow;
public fun immutable_borrow_example<T>(self: &Kiosk, cap: &KioskOwnerCap, item_id: ID): &T {
kiosk::borrow(self, cap, item_id)
}
use sui::kiosk::{Self, Kiosk, KioskOwnerCap};
public fun immutable_borrow_example<T>(self: &Kiosk, cap: &KioskOwnerCap, item_id: ID): &T {
self.borrow(cap, item_id)
}
```

Expand All @@ -389,15 +388,14 @@ You can mutably borrow an asset from a kiosk if it is not listed. You can use th
### Mutably borrow an asset using Sui Move

```move
module examples::mutable_borrow
use sui::object::ID;
use sui::kiosk::{Self, Kiosk, KioskOwnerCap};
public fun mutable_borrow_example<T>(
self: &mut Kiosk, cap: &KioskOwnerCap, item_id: ID
): &mut T {
kiosk::borrow_mut(self, cap, item_id)
}
module examples::mutable_borrow;
use sui::kiosk::{Self, Kiosk, KioskOwnerCap};
public fun mutable_borrow_example<T>(
self: &mut Kiosk, cap: &KioskOwnerCap, item_id: ID
): &mut T {
self.borrow_mut(cap, item_id)
}
```

Expand Down

0 comments on commit 2b04810

Please sign in to comment.