### Sui Kiosk Extension Module Example Source: https://kiosk.page/kiosk-extensions/extensions-api/index An example demonstrating the basic structure of a Sui Kiosk extension module, showing how to import and utilize the `kiosk_extension` module. ```sui module example::my_extension { use sui::kiosk_extension; // ... } ``` -------------------------------- ### Install Kiosk Extension with Place Permission Source: https://kiosk.page/print Demonstrates implementing the `add` function for an extension that requires the 'place' permission, using a Witness struct for authorization. ```Sui Move module examples::letterbox_ext { // ... dependencies /// 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) } } ``` -------------------------------- ### Define Extension Permissions (Move) Source: https://kiosk.page/print Defines the expected permissions for an extension using a u128 bitmap. This example sets the 'place' permission. ```Move module examples::letterbox_ext { // ... dependencies /// 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 and request `place` permission. public fun add(kiosk: &mut Kiosk, cap: &KioskOwnerCap, ctx: &mut TxContext) { kiosk_extension::add(Extension {}, kiosk, cap, PERMISSIONS, ctx) } } ``` -------------------------------- ### Implement Sui Kiosk Extension `add` Function Source: https://kiosk.page/kiosk-extensions/extensions-api/adding-an-extension This Rust code snippet demonstrates the implementation of the `add` function for a Sui Kiosk extension. It defines the required permissions and a witness struct for authorization, then calls the `kiosk_extension::add` function with the necessary parameters. ```rust module examples::letterbox_ext { // ... dependencies /// 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) } } ``` -------------------------------- ### Immutable Borrow Example (Sui Move) Source: https://kiosk.page/kiosk/borrowing Demonstrates how to immutably borrow an asset from a Kiosk using the `kiosk::borrow` function in Sui Move. This function returns an immutable reference to the asset. ```rust module examples::immutable_borrow use sui::object::ID; use sui::kiosk::{Self, Kiosk, KioskOwnerCap}; public fun immutable_borrow_example(self: &Kiosk, cap: &KioskOwnerCap, item_id: ID): &T { kiosk::borrow(self, cap, item_id) } ``` -------------------------------- ### Sui Kiosk Market Extension Example Source: https://kiosk.page/print This Sui module demonstrates a custom Kiosk extension for a marketplace. It includes custom event definitions for item listings and delistings, along with functions to add the extension to a Kiosk and to perform custom list and delist operations that emit these events. The code follows the general principles of the list-purchase flow but omits purchase cap and storage details for brevity, directing users to the Extensions API for more information. ```Sui module examples::marketplace_ext { use sui::kiosk::{Self, Kiosk, KioskOwnerCap, PurchaseCap}; use sui::tx_context::TxContext; use sui::object::{Self, ID}; use sui::kiosk_extension; use sui::event; /// Trying to delist an item in someone else’s Kiosk const ENotOwner: u64 = 0; /// A custom extension flag struct Extension has drop {} // === Events === /// A custom event for a new listing. We only emit Kiosk ID and the price, /// because other fields such as “sender” are already a part of the event. /// And the type `T` here allows filtering events by type. struct MarketItemListed has copy, drop { kiosk: ID, item_id: ID, price: u64 } /// A custom event for delisting. We only emit Kiosk ID and Item ID, /// because the rest can be identified on the indexing side struct MarketItemDelisted has copy, drop { kiosk: ID, item_id: ID } // Similarly, a purchase event can be implemented // struct MarketItemPurchased has copy, drop { ... } /// Installs the extension into user’s Kiosk. public fun add( self: &mut Kiosk, cap: &KioskOwnerCap, ctx: &mut TxContext ) { kiosk_extension::add(Extension {}, self, cap, 0, ctx) } /// Custom list function which emits an event specific to the Extension public fun list( self: &mut Kiosk, cap: &KioskOwnerCap, item_id: ID, price: u64, ctx: &mut TxContext ) { // omitting the purchase cap and storage parts // see Extensions API for details event::emit(MarketItemListed { kiosk: object::id(&self), item_id, price, }) } /// Custom delist function which emits public fun delist( self: &mut Kiosk, cap: &KioskOwnerCap, item_id: ID, ) { assert!(kiosk::has_access(self, cap), ENotOwner); event::emit(MarketItemDelisted { kiosk: object::id(&self), item_id }) } // } ``` -------------------------------- ### Implement Dummy Rule for Sui TransferPolicy Source: https://kiosk.page/transfer-policy/writing-rules This Move module demonstrates a basic 'dummy_rule' that can be added to a Sui TransferPolicy. It includes a RuleWitness, a Config struct, an 'add' function to register the rule with the policy, and a 'pay' function to process a transfer request and add a receipt, optionally collecting SUI fees. ```Move module examples::dummy_rule { use sui::coin::Coin; use sui::sui::SUI; use sui::transfer_policy::{ Self as policy, TransferPolicy, TransferPolicyCap, TransferRequest }; /// The Rule Witness; has no fields and is used as a /// static authorization method for the rule. struct Rule has drop {} /// Configuration struct with any fields (as long as it /// has `drop`). Managed by the Rule module. struct Config has store, drop {} /// Function that adds a Rule to the `TransferPolicy`. /// Requires `TransferPolicyCap` to make sure the rules are /// added only by the publisher of T. public fun add( policy: &mut TransferPolicy, cap: &TransferPolicyCap ) { policy::add_rule(Rule {}, policy, cap, Config {}) } /// Action function - perform a certain action (any, really) /// and pass in the `TransferRequest` so it gets the Receipt. /// Receipt is a Rule Witness, so there's no way to create /// it anywhere else but in this module. /// /// This example also illustrates that Rules can add Coin /// to the balance of the TransferPolicy allowing creators to /// collect fees. public fun pay( policy: &mut TransferPolicy, request: &mut TransferRequest, payment: Coin ) { policy::add_to_balance(Rule {}, policy, payment); policy::add_receipt(Rule {}, request); } } ``` -------------------------------- ### Mutable Borrow Example (Sui Move) Source: https://kiosk.page/kiosk/borrowing Illustrates how to mutably borrow an asset from a Kiosk using the `kiosk::borrow_mut` function in Sui Move. This is only possible if the asset is not listed. ```rust module examples::mutable_borrow use sui::object::ID; use sui::kiosk::{Self, Kiosk, KioskOwnerCap}; public fun mutable_borrow_example( self: &mut Kiosk, cap: &KioskOwnerCap, item_id: ID ): &mut T { kiosk::borrow_mut(self, cap, item_id) } ``` -------------------------------- ### Create VAT Transfer Policy Source: https://kiosk.page/print This Move code example demonstrates how to create a TransferPolicy for the 'VAT' type. It includes functions to create the policy, confirm requests, and initialize the module. The 'VAT' struct serves as an authority for creating and resolving TransferRequests. ```sui module tax::vat { use sui::tx_context::{sender, TxContext}; use sui::transfer_policy::{Self, TransferPolicy}; /// The authority defines the `VAT` type. It is never initialized and only /// used to create and resolve `TransferRequest`s. struct VAT has drop {} /// The publisher creates and shares a `TransferPolicy` for the `VAT` type. public fun create_policy(pub: &Publisher, ctx: &mut TxContext) { let (policy, policy_cap) = transfer_policy::new_policy(pub, ctx); sui::transfer::public_share_object(policy); sui::transfer::public_transfer(policy_cap, sender(ctx)); } /// Can be called directly in the `TransferPolicy` module; does not need a /// custom implementation. This code is for illustration purposes only. public fun confirm_request( policy: &TransferPolicy, request: TransferRequest ) { transfer_policy::confirm_request(policy, request); } /// Using the OTW (VAT), create the Publisher object and transfer it to the /// transaction sender. fun init(otw: VAT, ctx: &mut TxContext) { sui::package::claim_and_keep(otw, ctx); } } ``` -------------------------------- ### Sui Move Capability Rule Implementation Source: https://kiosk.page/transfer-policy/writing-rules This snippet shows the implementation of a generic Capability rule in Sui Move. Similar to the Witness pattern, it allows for authorization based on a Capability type `Cap`. The `add` function sets the rule, specifying the Capability type, and the `confirm` function verifies the action by requiring a reference to the Capability. ```Move module examples::capability_rule { // skipping dependencies /// Changing the type parameter name for better readability struct Rule has drop {} struct Config {} /// Absolutely identical to the witness setting public fun add(/* ... */) { policy::add_rule(Rule {}, policy, cap, Config {}) } /// Almost the same with the Witness requirement, only now we /// require a reference to the type. public fun confirm( cap: &Cap, /* ... */ ) { assert!(policy::has_rule>(policy), ERuleNotSet); policy::add_receipt(Rule {}, request) } } ``` -------------------------------- ### Sui Kiosk Marketplace Extension Example Source: https://kiosk.page/building-with-kiosk/custom-event-handlers-in-extensions This Move module provides a basic implementation of a Sui Kiosk extension for a marketplace. It includes custom events for listing and delisting items, along with functions to add the extension to a Kiosk and perform custom listing and delisting operations. The code illustrates how to emit custom events with specific data. ```move /// This module follows the default Kiosk functionality without anything added. /// Practically the example does not have any value and serves the illustration /// purpose as well as a potential base for custom extensions module examples::marketplace_ext { use sui::kiosk::{Self, Kiosk, KioskOwnerCap, PurchaseCap}; use sui::tx_context::TxContext; use sui::object::{Self, ID}; use sui::kiosk_extension; use sui::event; /// Trying to delist an item in someone else’s Kiosk const ENotOwner: u64 = 0; /// A custom extension flag struct Extension has drop {} // === Events === /// A custom event for a new listing. We only emit Kiosk ID and the price, /// because other fields such as “sender” are already a part of the event. /// And the type `T` here allows filtering events by type. struct MarketItemListed has copy, drop { kiosk: ID, item_id: ID, price: u64 } /// A custom event for delisting. We only emit Kiosk ID and Item ID, /// because the rest can be identified on the indexing side struct MarketItemDelisted has copy, drop { kiosk: ID, item_id: ID } // Similarly, a purchase event can be implemented // struct MarketItemPurchased has copy, drop { ... } /// Installs the extension into user’s Kiosk. public fun add( self: &mut Kiosk, cap: &KioskOwnerCap, ctx: &mut TxContext ) { kiosk_extension::add(Extension {}, self, cap, 0, ctx) } /// Custom list function which emits an event specific to the Extension public fun list( self: &mut Kiosk, cap: &KioskOwnerCap, item_id: ID, price: u64, ctx: &mut TxContext ) { // omitting the purchase cap and storage parts // see Extensions API for details event::emit(MarketItemListed { kiosk: object::id(&self), item_id, price, }) } /// Custom delist function which emits public fun delist( self: &mut Kiosk, cap: &KioskOwnerCap, item_id: ID, ) { assert!(kiosk::has_access(self, cap), ENotOwner); event::emit(MarketItemDelisted { kiosk: object::id(&self), item_id }) } // } ``` -------------------------------- ### Implement Time-Based Trading Rule in Sui Source: https://kiosk.page/transfer-policy/writing-rules This module introduces a time-based rule for Sui Kiosk transfers, restricting trading until a specified start time. The `confirm_time` function verifies that the current timestamp is after the configured start time before allowing the transfer. ```Sui module examples::time_rule { // skipping some dependencies use sui::clock::{Self, Clock}; struct Rule has drop {} struct Config has store, drop { start_time: u64 } /// Start time is yet to come const ETooSoon: u64 = 0; /// Add a Rule that enables purchases after a certain time public fun add(/* skip default fields */, start_time: u64) { policy::add_rule(Rule {}, policy, cap, Config { start_time }) } /// Pass in the Clock and prove that current time value is higher /// than the `start_time` public fun confirm_time( policy: &TransferPolicy, request: &mut TransferRequest, clock: &Clock ) { let config: &Config = policy::get_rule(Rule {}, policy) assert!(clock::timestamp_ms(clock) >= config.start_time, ETooSoon); policy::add_receipt(Rule {}, request) } } ``` -------------------------------- ### Implement Time-Based Trading Rule in Sui Source: https://kiosk.page/print This module introduces a time-based rule for Sui Kiosk transfers, restricting trading until a specified start time. The `confirm_time` function verifies that the current timestamp is after the configured start time before allowing the transfer. ```Sui module examples::time_rule { // skipping some dependencies use sui::clock::{Self, Clock}; struct Rule has drop {} struct Config has store, drop { start_time: u64 } /// Start time is yet to come const ETooSoon: u64 = 0; /// Add a Rule that enables purchases after a certain time public fun add(/* skip default fields */, start_time: u64) { policy::add_rule(Rule {}, policy, cap, Config { start_time }) } /// Pass in the Clock and prove that current time value is higher /// than the `start_time` public fun confirm_time( policy: &TransferPolicy, request: &mut TransferRequest, clock: &Clock ) { let config: &Config = policy::get_rule(Rule {}, policy) assert!(clock::timestamp_ms(clock) >= config.start_time, ETooSoon); policy::add_receipt(Rule {}, request) } } ``` -------------------------------- ### Create Kiosk using CLI Source: https://kiosk.page/print This bash command demonstrates how to create a default Kiosk using the Sui client. It specifies the package, module, and function to call, along with a gas budget for the transaction. ```bash sui client call \ --package 0x2 \ --module kiosk \ --function default \ --gas-budget 1000000000 ``` -------------------------------- ### Place Item using Sui SDK (JavaScript) Source: https://kiosk.page/kiosk/place-and-take Demonstrates how to place an item into a Sui Kiosk using the `@mysten/kiosk` library in JavaScript. It involves creating a transaction, defining arguments for the item, kiosk, and owner capability, and then calling the `place` function. ```javascript import { place } from '@mysten/kiosk'; let tx = new TransactionBuilder(); let itemArg = tx.object(''); let kioskArg = tx.object(''); let kioskOwnerCapArg = tx.object(''); place(tx, '', kioskArg, kioskOwnerCapArg, item); ``` ```javascript let tx = new TransactionBuilder(); let itemArg = tx.object(''); let kioskArg = tx.object(''); let kioskOwnerCapArg = tx.object(''); tx.moveCall({ target: '0x2::kiosk::place', arguments: [ kioskArg, kioskOwnerCapArg, itemArg ], typeArguments: [ '' ] }) ``` -------------------------------- ### Place Item using Sui CLI (Bash) Source: https://kiosk.page/kiosk/place-and-take Provides the command-line interface command to place an item into a Sui Kiosk. This involves specifying the package, module, function, arguments for kiosk, owner capability, item, and the type argument for the item. ```bash sui client call \ --package 0x2 \ --module kiosk \ --function place \ --args "" "" "" \ --type-args "" \ --gas-budget 1000000000 ``` -------------------------------- ### Kiosk Demo: List/Purchase Flow with TypeScript and React Source: https://kiosk.page/building-with-kiosk/demo-applications Illustrates a simple list and purchase flow using TypeScript, React, and the Kiosk SDK. This application serves as a reference for building interactive client applications with Kiosk functionality. ```TypeScript // Code for Kiosk Demo is located in the Sui repository under the dapps/kiosk directory. ``` -------------------------------- ### Place Item in Kiosk - Sui CLI Source: https://kiosk.page/print Provides the command-line interface command to place an item into a Kiosk. It specifies the package, module, function, arguments for Kiosk, OwnerCap, and Item, and the item type. ```bash sui client call \ --package 0x2 \ --module kiosk \ --function place \ --args "" "" "" \ --type-args "" \ --gas-budget 1000000000 ``` -------------------------------- ### Withdraw from Sui Kiosk (TypeScript) Source: https://kiosk.page/kiosk/withdrawing-profits Demonstrates how to withdraw a specific amount or all profits from a Sui Kiosk using the `@mysten/kiosk` library in TypeScript. Requires transaction block setup and object IDs for the kiosk and capability. ```typescript import { withdrawFromKiosk } from '@mysten/kiosk'; let tx = new TransactionBlock(); let kioskArg = tx.object(''); let capArg = tx.object(''); // The amount can be `null` to withdraw everything or a specific amount let amount = ''; let withdrawAll = null; let coin = withdrawFromKiosk(tx, kioskArg, capArg, amount); ``` -------------------------------- ### Take Item using Sui SDK (JavaScript) Source: https://kiosk.page/kiosk/place-and-take Illustrates how to take an item from a Sui Kiosk using the `@mysten/kiosk` library in JavaScript. This includes preparing the transaction, defining arguments for the item ID, kiosk, and owner capability, calling the `take` function, and transferring the item. ```javascript import { take } from '@mysten/kiosk'; let tx = new TransactionBuilder(); let itemId = tx.pure('', 'address'); let kioskArg = tx.object(''); let kioskOwnerCapArg = tx.object(''); let item = take('', kioskArg, kioskOwnerCapArg, itemId); tx.transferObjects([ item ], tx.pure(sender, 'address')); ``` ```javascript let tx = new TransactionBuilder(); let itemId = tx.pure('', 'address'); let kioskArg = tx.object(''); let kioskOwnerCapArg = tx.object(''); let item = tx.moveCall({ target: '0x2::kiosk::take', arguments: [ kioskArg, kioskOwnerCapArg, itemId ], typeArguments: [ '' ] }); ``` -------------------------------- ### Create Kiosk with moveCall - TypeScript Source: https://kiosk.page/print Shows how to create a new Kiosk using a `moveCall` to the `kiosk::new` function. It also includes transferring the owner capability and sharing the Kiosk publicly. ```typescript let tx = new TransactionBuilder(); let [kiosk, kioskOwnerCap] = tx.moveCall({ target: '0x2::kiosk::new' }); tx.transferObjects([ kioskOwnerCap ], tx.pure(sender, 'address')); tx.moveCall({ target: '0x2::transfer::public_share_object', arguments: [ kiosk ], typeArguments: '0x2::kiosk::Kiosk' }) ``` -------------------------------- ### Implement Royalty Fee Rule in Sui Source: https://kiosk.page/transfer-policy/writing-rules This module implements a royalty fee rule for the Sui Kiosk system. It calculates a fee based on a percentage of the amount paid for an item, configurable in basis points. The `pay` function allows buyers to pay the required amount, and the fee is added to the policy's balance. ```Sui module examples::royalty_rule { // skipping dependencies const MAX_BP: u16 = 10_000; struct Rule has drop {} /// In this implementation Rule has a configuration - `amount_bp` /// which is the percentage of the `paid` in basis points. struct Config has store, drop { amount_bp: u16 } /// When a Rule is added, configuration details are specified public fun add( policy: &mut TransferPolicy, cap: &TransferPolicyCap, amount_bp: u16 ) { assert!(amount_bp <= MAX_BP, 0); policy::add_rule(Rule {}, policy, cap, Config { amount_bp }) } /// To get the Receipt, the buyer must call this function and pay /// the required amount; the amount is calculated dynamically and /// it is more convenient to use a mutable reference public fun pay( policy: &mut TransferPolicy, request: &mut TransferRequest, payment: &mut Coin, ctx: &mut TxContext ) { // using the getter to read the paid amount let paid = policy::paid(request); let config: &Config = policy::get_rule(Rule {}, policy); let amount = (((paid as u128) * (config.amount_bp as u128) / MAX_BP) as u64); assert!(coin::value(payment) >= amount, EInsufficientAmount); let fee = coin::split(payment, amount, ctx); policy::add_to_balance(Rule {}, policy, fee); policy::add_receipt(Rule {}, request) } } ``` -------------------------------- ### Create Default Kiosk (Sui CLI) Source: https://kiosk.page/kiosk/create Creates a default Kiosk using the Sui command-line interface. This command targets the `default` function within the `kiosk` module. ```bash sui client call \ --package 0x2 \ --module kiosk \ --function default \ --gas-budget 1000000000 ``` -------------------------------- ### Create and Share Kiosk (TypeScript) Source: https://kiosk.page/print This TypeScript code snippet demonstrates how to create a new Kiosk and share it using the `@mysten/kiosk` library. It initializes a transaction builder and calls the `createKioskAndShare` function, then transfers the `KioskOwnerCap` to a specified sender address. ```TypeScript import { createKioskAndShare } from '@mysten/kiosk'; let tx = new TransactionBuilder(); let kioskOwnerCap = createKioskAndShare(tx); tx.transferObjects([ kioskOwnerCap ], tx.pure(sender, 'address')); ``` -------------------------------- ### Sui Move Witness Rule Implementation Source: https://kiosk.page/transfer-policy/writing-rules This snippet demonstrates the implementation of a generic Witness rule in Sui Move. It allows for authorization based on a specified Witness type, enabling custom logic integration with TransferPolicy. The `add` function sets the rule, requiring a Witness type `W`, and the `confirm` function verifies the action by accepting a witness of type `W`. ```Move module examples::witness_rule { // skipping dependencies /// Rule is either not set or the Witness does not match the expectation const ERuleNotSet: u64 = 0; /// This Rule requires a witness of type W, see the implementation struct Rule has drop {} struct Config has store, drop {} /// No special arguments are required to set this Rule, but the /// publisher now needs to specify a Witness type public fun add(/* .... */) { policy::add_rule(Rule {}, policy, cap, Config {}) } /// To confirm the action, buyer needs to pass in a witness /// which should be acquired either by calling some function or /// integrated into a more specific hook of a marketplace / /// trading module public fun confirm( _: W, policy: &TransferPolicy, request: &mut TransferRequest ) { assert!(policy::has_rule>(policy), ERuleNotSet); policy::add_receipt(Rule {}, request) } } ``` -------------------------------- ### Kiosk CLI: Pure JavaScript Implementation of Kiosk Functionality Source: https://kiosk.page/building-with-kiosk/demo-applications Implements Kiosk functionality using pure JavaScript, demonstrating best practices for various actions. This application is suitable for developers looking for a straightforward JavaScript-based integration with Kiosk. ```JavaScript // Code for Kiosk CLI is located in the Sui repository under the dapps/kiosk-cli path. ``` -------------------------------- ### Create Kiosk with createKiosk - TypeScript Source: https://kiosk.page/print Demonstrates creating a Kiosk and obtaining its owner capability using the `createKiosk` function. It then shares the Kiosk publicly and transfers the owner capability to a specified sender address. ```typescript import { createKiosk } from '@mysten/kiosk'; let tx = new TransactionBuilder(); let [kiosk, kioskOwnerCap] = createKiosk(tx); tx.transferObjects([ kioskOwnerCap ], tx.pure(sender, 'address')); tx.moveCall({ target: '0x2::transfer::public_share_object', arguments: [ kiosk ], typeArguments: '0x2::kiosk::Kiosk' }) ``` -------------------------------- ### PTB-Friendly Borrowing with Kiosk SDK Source: https://kiosk.page/print Illustrates PTB-friendly borrowing using the Kiosk SDK's `borrowValue` and `returnValue` functions. This allows borrowing and returning an item within the same transaction, enforced by a 'Hot Potato' mechanism. ```typescript import { borrowValue, returnValue } from '@sui/kiosk-sdk'; let tx = new TransactionBuilder(); let itemType = 'ITEM_TYPE'; let itemId = tx.pure('', 'address'); let kioskArg = tx.object(''); let capArg = tx.object(''); let [item, promise] = borrowValue(tx, itemType, kioskArg, capArg, itemId); // freely mutate or reference the `item` // any calls are available as long as they take a reference // `returnValue` must be explicitly called returnValue(tx, itemType, kioskArg, item, promise); ``` ```typescript let tx = new TransactionBuilder(); let itemType = 'ITEM_TYPE'; let itemId = tx.pure('', 'address'); let kioskArg = tx.object(''); let capArg = tx.object(''); let [item, promise] = tx.moveCall({ target: '0x2::kiosk::borrow_val', arguments: [ kioskArg, capArg, itemId ], typeArguments: [ itemType ], }); // freely mutate or reference the `item` // any calls are available as long as they take a reference // `returnValue` must be explicitly called tx.moveCall({ target: '0x2::kiosk::return_val', arguments: [ kioskArg, item, promise ], typeArguments: [ itemType ], }); ``` -------------------------------- ### Move: Dummy Rule for Transfer Policy Source: https://kiosk.page/print Implements a basic 'dummy_rule' for Sui's TransferPolicy. This rule requires no specific configuration and can optionally accept SUI coins for fee collection. It demonstrates the structure for creating custom rules, including a witness, config, add function, and action function. ```Move module examples::dummy_rule { use sui::coin::Coin; use sui::sui::SUI; use sui::transfer_policy::{ Self as policy, TransferPolicy, TransferPolicyCap, TransferRequest }; /// The Rule Witness; has no fields and is used as a /// static authorization method for the rule. struct Rule has drop {} /// Configuration struct with any fields (as long as it /// has `drop`). Managed by the Rule module. struct Config has store, drop {} /// Function that adds a Rule to the `TransferPolicy`. /// Requires `TransferPolicyCap` to make sure the rules are /// added only by the publisher of T. public fun add( policy: &mut TransferPolicy, cap: &TransferPolicyCap ) { policy::add_rule(Rule {}, policy, cap, Config {}) } /// Action function - perform a certain action (any, really) /// and pass in the `TransferRequest` so it gets the Receipt. /// Receipt is a Rule Witness, so there's no way to create /// it anywhere else but in this module. /// /// This example also illustrates that Rules can add Coin /// to the balance of the TransferPolicy allowing creators to /// collect fees. public fun pay( policy: &mut TransferPolicy, request: &mut TransferRequest, payment: Coin ) { policy::add_to_balance(Rule {}, policy, payment); policy::add_receipt(Rule {}, request); } } ``` -------------------------------- ### TypeScript: List an Asset for Sale (Kiosk SDK) Source: https://kiosk.page/print This TypeScript code uses the Kiosk SDK to list an asset for sale. It requires a TransactionBlock, Kiosk and Capability arguments, the Item ID and Type, and the price in MIST. The `list` function from '@mysten/kiosk' is used. ```typescript import { list } from '@mysten/kiosk'; let tx = new TransactionBlock(); let kioskArg = tx.object(''); let capArg = tx.object(''); let itemId = tx.pure('', 'address'); let itemType = 'ITEM_TYPE'; let price = ''; // in MIST (1 SUI = 10^9 MIST) list(tx, itemType, kioskArg, capArg, itemId, price); ``` -------------------------------- ### Place Item with Permissions Check (Move) Source: https://kiosk.page/print Allows an extension to place an item into the Kiosk after verifying it has the necessary 'place' permission. It uses a witness to identify the extension. ```Move module examples::letterbox_ext { // ... /// 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) { assert!(kiosk_extension::can_place(kiosk), ENotEnoughPermissions) kiosk_extension::place(Extension {}, kiosk, letter, policy) } } ``` -------------------------------- ### Create Kiosk with Custom Storage (TypeScript) Source: https://kiosk.page/kiosk/create Creates a Kiosk using the `kiosk::new` function, allowing for custom storage models. It also shares the Kiosk and transfers the owner capability. ```typescript import { createKiosk } from '@mysten/kiosk'; let tx = new TransactionBuilder(); let [kiosk, kioskOwnerCap] = createKiosk(tx); tx.transferObjects([ kioskOwnerCap ], tx.pure(sender, 'address')); tx.moveCall({ target: '0x2::transfer::public_share_object', arguments: [ kiosk ], typeArguments: '0x2::kiosk::Kiosk' }) ``` -------------------------------- ### Create and Share Kiosk (TypeScript) Source: https://kiosk.page/kiosk/create Creates a new Kiosk and shares it, transferring the KioskOwnerCap to the sender. This uses the `@mysten/kiosk` library. ```typescript import { createKioskAndShare } from '@mysten/kiosk'; let tx = new TransactionBuilder(); let kioskOwnerCap = createKioskAndShare(tx); tx.transferObjects([ kioskOwnerCap ], tx.pure(sender, 'address')); ``` -------------------------------- ### Place Item in Kiosk - TypeScript (moveCall) Source: https://kiosk.page/print Demonstrates placing an item into a Kiosk using a `moveCall` to the `kiosk::place` function. This method requires the Kiosk, KioskOwnerCap, and the item, specifying the item's type as a type argument. ```typescript let tx = new TransactionBuilder(); let itemArg = tx.object(''); let kioskArg = tx.object(''); let kioskOwnerCapArg = tx.object(''); tx.moveCall({ target: '0x2::kiosk::place', arguments: [ kioskArg, kioskOwnerCapArg, itemArg ], typeArguments: [ '' ] }) ``` -------------------------------- ### Place Item in Kiosk - TypeScript (Import) Source: https://kiosk.page/print Illustrates placing an item into a Kiosk using the imported `place` function. It requires the Kiosk object, KioskOwnerCap, and the item to be placed, along with its type. ```typescript import { place } from '@mysten/kiosk'; let tx = new TransactionBuilder(); let itemArg = tx.object(''); let kioskArg = tx.object(''); let kioskOwnerCapArg = tx.object(''); place(tx, '', kioskArg, kioskOwnerCapArg, item); ``` -------------------------------- ### Create Kiosk using Move Call (TypeScript) Source: https://kiosk.page/print This TypeScript snippet shows how to create a Kiosk by making a Move call to the `kiosk::default` function. It utilizes the `TransactionBuilder` to construct the transaction for creating a default Kiosk. ```TypeScript let tx = new TransactionBuilder(); tx.moveCall({ target: '0x2::kiosk::default' }); ``` -------------------------------- ### Mutable Borrowing in Kiosk Source: https://kiosk.page/print Shows how to mutably borrow an item from a Kiosk using `kiosk::borrow_mut`. This is useful when modifications are needed, but requires a published module for PTB compatibility. ```rust module examples::mutable_borrow use sui::object::ID; use sui::kiosk::{Self, Kiosk, KioskOwnerCap}; public fun mutable_borrow_example( self: &mut Kiosk, cap: &KioskOwnerCap, item_id: ID ): &mut T { kiosk::borrow_mut(self, cap, item_id) } } ``` -------------------------------- ### Immutable Borrowing in Kiosk Source: https://kiosk.page/print Demonstrates how to immutably borrow an item from a Kiosk using the `kiosk::borrow` function. This function requires the Kiosk, an owner capability, and the item's ID. ```rust module examples::immutable_borrow use sui::object::ID; use sui::kiosk::{Self, Kiosk, KioskOwnerCap}; public fun immutable_borrow_example(self: &Kiosk, cap: &KioskOwnerCap, item_id: ID): &T { kiosk::borrow(self, cap, item_id) } } ``` -------------------------------- ### Sui CLI: List an Asset for Sale Source: https://kiosk.page/print This command lists an asset for sale in the Kiosk. It requires the Kiosk ID, Capability ID, Item ID, the price, and the Item Type. A gas budget is also specified. ```bash sui client call \ --package 0x2 \ --module kiosk \ --function list \ --args "" "" "" "" \ --type-args "ITEM_TYPE" \ --gas-budget 1000000000 ``` -------------------------------- ### TypeScript: List an Asset for Sale (Move Call) Source: https://kiosk.page/print This TypeScript code demonstrates listing an asset for sale using a direct `moveCall` to the Kiosk module. It specifies the target module, arguments (Kiosk, Capability, Item ID, Price), and type arguments (Item Type). ```typescript let tx = new TransactionBlock(); let kioskArg = tx.object(''); let capArg = tx.object(''); let itemId = tx.pure('', 'address'); let itemType = 'ITEM_TYPE'; let priceArg = tx.pure('', 'u64'); // in MIST (1 SUI = 10^9 MIST) tx.moveCall({ target: '0x2::kiosk::list', arguments: [ kioskArg, capArg, itemId, priceArg ], typeArguments: [ itemType ] }); ``` -------------------------------- ### Create Default Kiosk (TypeScript) Source: https://kiosk.page/kiosk/create Creates a default Kiosk using a move call to the `kiosk::default` function. This is a simpler method for Kiosk creation. ```typescript let tx = new TransactionBuilder(); tx.moveCall({ target: '0x2::kiosk::default' }); ``` -------------------------------- ### PTB-Friendly Borrowing with Kiosk SDK (TypeScript) Source: https://kiosk.page/kiosk/borrowing Shows how to use the Kiosk SDK's `borrowValue` and `returnValue` functions for PTB-friendly borrowing in TypeScript. This allows taking an asset and returning it within the same transaction. ```typescript import { borrowValue, returnValue } from '@sui/kiosk-sdk'; let tx = new TransactionBuilder(); let itemType = 'ITEM_TYPE'; let itemId = tx.pure('', 'address'); let kioskArg = tx.object(''); let capArg = tx.object(''); let [item, promise] = borrowValue(tx, itemType, kioskArg, capArg, itemId); // freely mutate or reference the `item` // any calls are available as long as they take a reference // `returnValue` must be explicitly called returnValue(tx, itemType, kioskArg, item, promise); ``` -------------------------------- ### Access Kiosk 'place' Function with Permissions (Sui Move) Source: https://kiosk.page/kiosk-extensions/extensions-api/extension-permissions This Sui Move code demonstrates how an extension can access the 'place' function within the Kiosk. It includes an assertion to check if the extension has the necessary 'place' permission before executing the action. ```rust module examples::letterbox_ext { // ... /// 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) { assert!(kiosk_extension::can_place(kiosk), ENotEnoughPermissions) kiosk_extension::place(Extension {}, kiosk, letter, policy) } } ```