Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(move/examples): implementation of kiosk marketplace extension using kiosk rules #4156

Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/examples/move/nft_marketplace/Move.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[package]
name = "nft_marketplace"
edition = "2024.beta"

[dependencies]
Iota = { local = "../../../../crates/iota-framework/packages/iota-framework" }
Kiosk = { local = "../../../../kiosk" }

# For remote import, use the `{ git = "...", subdir = "...", rev = "..." }`.
# Revision can be a branch, a tag, and a commit hash.
# MyRemotePackage = { git = "https://some.remote/host.git", subdir = "remote/path", rev = "main" }

# For local dependencies use `local = path`. Path is relative to the package root
# Local = { local = "../path/to" }

# To resolve a version conflict and force a specific version for dependency
# override use `override = true`
# Override = { local = "../conflicting/version", override = true }

[addresses]
nft_marketplace = "0x0"

# Named addresses will be accessible in Move as `@name`. They're also exported:
# for example, `std = "0x1"` is exported by the Standard Library.
# alice = "0xA11CE"

[dev-dependencies]
# The dev-dependencies section allows overriding dependencies for `--test` and
# `--dev` modes. You can introduce test-only dependencies here.
# Local = { local = "../path/to/dev-build" }

[dev-addresses]
# The dev-addresses section allows overwriting named addresses for the `--test`
# and `--dev` modes.
# alice = "0xB0B"
185 changes: 185 additions & 0 deletions docs/examples/move/nft_marketplace/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
# Marketplace Guide

The `marketplace_extension.move` module provides a straightforward implementation of a marketplace extension. To utilize it, follow the steps outlined below.
The `item_for_market.move` contains mocked item data for use within the marketplace.
nonast marked this conversation as resolved.
Show resolved Hide resolved
The `rental_extension.move` is an extension adds functionality to enable item rentals.

## Steps to Use the Marketplace

### 1. Connect to the Network

Connect to the IOTA network (e.g., using a faucet to obtain tokens).

### 2. Install Kiosk

By installation, we mean creating a Kiosk object and an OwnerCap, then transferring them to the caller.
Run the following command to install the Kiosk module:
miker83z marked this conversation as resolved.
Show resolved Hide resolved

```bash
iota client call \
--package 0x2 \
--module kiosk \
--function default
```

After publishing, export the following variables:

- `KIOSK_ID`: The ID of installed Kiosk object.
- `KIOSK_CAP_ID`: The ID if the installed Kiosk's onwer cap

Check warning on line 28 in docs/examples/move/nft_marketplace/README.md

View workflow job for this annotation

GitHub Actions / typos / Spell Check with Typos

"onwer" should be "owner".
nonast marked this conversation as resolved.
Show resolved Hide resolved

### 3. Publish `nft_marketplace` package

#### 3.1(Optional) Publish Kiosk rules modules if these are not present in the network you are using

Publish Kiosk rules modules(package):

```bash
iota client publish $IOTA_REPO_DIR/kiosk
```

After publishing, export the following variable:

- `RULES_PACKAGE_ID`: The ID of rules package.
valeriyr marked this conversation as resolved.
Show resolved Hide resolved

#### 3.2 Publish marketplace package

```bash
iota client publish $IOTA_REPO_DIR/docs/examples/move/nft_marketplace
```

After publishing, export the following variables:

- `MARKETPLACE_PACKAGE_ID`: The ID of whole marketplace package.
- `MARKETPLACE_PUBLISHER_ID`: The ID of the publisher object created during marketplace package publishing."

### 4. Create an Clothing Store Item

Create an item, for instance:

```bash
iota client call \
--package $MARKETPLACE_PACKAGE_ID \
--module clothing_store \
--function new_jeans
```

After creation, export the following variable:

miker83z marked this conversation as resolved.
Show resolved Hide resolved
- `CLOTHING_STORE_ITEM_ID`: The ID of the published item (in this case, Jeans).

### 5. Create a Transfer Policy

`TransferPolicy` is a generic shared object acting as a central authority enforcing everyone to check their purchase is valid against the defined policy before the purchased item is transferred to the buyers. Object is specified by concrete type.
`default` function creates `TransferPolicy` object and an `TransferPolicyCap`, then transferring them to the caller.

`TransferPolicyCap` object serves as proof of ownership of the `TransferPolicy` object.
A capability granting the owner permission to `add/remove` rules as well as to `withdraw` and `destroy_and_withdraw` the `TransferPolicy`.

Set up a transfer policy for the created item using the command:
miker83z marked this conversation as resolved.
Show resolved Hide resolved

```bash
iota client call \
--package 0x2 \
--module transfer_policy \
--function default \
--gas-budget 10000000 \
--args $MARKETPLACE_PUBLISHER_ID \
--type-args "$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans"
```

After publishing, export the following variables:

- `ITEM_TRANS_POLICY`: The ID of the item transfer policy object.
- `ITEM_TRANS_POLICY_CAP`: The ID of the item transfer policy object owner capability"

### 6. Install the Extension on the Kiosk

The install function enables installation of the Marketplace extension in a kiosk.
Under the hood it invokes `kiosk_extension::add` that adds extension to the Kiosk via dynamic field.
Install the marketplace extension on the created kiosk using the command:
miker83z marked this conversation as resolved.
Show resolved Hide resolved

```bash
iota client call \
--package $MARKETPLACE_PACKAGE_ID \
--module marketplace_extension \
--function install \
--args $KIOSK_ID $KIOSK_CAP_ID
valeriyr marked this conversation as resolved.
Show resolved Hide resolved
```

### 7. Set a Price for the Item

Set the price for the item:

```bash
iota client call \
--package $MARKETPLACE_PACKAGE_ID \
--module marketplace_extension \
--function set_price \
--args $KIOSK_ID $KIOSK_CAP_ID $CLOTHING_STORE_ITEM_ID 50000 \
--type-args "$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans"
```

### 8.(Optional) Set Royalties

Royalties are a percentage of the item's price or revenue paid to the owner for the use or sale of their asset.

Set royalties for the item:
miker83z marked this conversation as resolved.
Show resolved Hide resolved

```bash
iota client call \
--package $MARKETPLACE_PACKAGE_ID \
--module marketplace_extension \
--function setup_royalties \
--args $ITEM_TRANS_POLICY $ITEM_TRANS_POLICY_CAP 5000 2000 \
--type-args "$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans"
```

### 9. Buy an Item:

#### 9.1 Get the Item Price:

```bash
iota client ptb \
--move-call $MARKETPLACE_PACKAGE_ID::marketplace_extension::get_item_price "<$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans>" @$KIOSK_ID @$CLOTHING_STORE_ITEM_ID --assign item_price \
```

#### 9.2(Optional) Calculate rolyalties of the Item:
nonast marked this conversation as resolved.
Show resolved Hide resolved

```bash
--move-call $RULES_PACKAGE_ID::royalty_rule::fee_amount "<$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans>" @$ITEM_TRANS_POLICY item_price --assign royalties_amount \
```

#### 9.3 Create a payment coin with a specific amount (price + optional royalties):

```bash
--split-coins gas "[item_price, royalties_amount]" --assign payment_coins \
--merge-coins payment_coins.0 "[payment_coins.1]" \
```

#### 9.4 Buy an Item using `payment_coins.0`:

Here, when we buy an item, we pay the owner the item's price. If the royalty rule is enabled, an additional royalty fee, calculated as a percentage of the initial item price, is also paid. Once both payments are completed, the item is ready for transferring to the buyer.

To purchase the item:
miker83z marked this conversation as resolved.
Show resolved Hide resolved

```bash
--move-call $MARKETPLACE_PACKAGE_ID::marketplace_extension::buy_item "<$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans>" @$KIOSK_ID @$ITEM_TRANS_POLICY @$CLOTHING_STORE_ITEM_ID payment_coins.0 --assign purchased_item
```

#### 9.5 Transfer an Item to the buyer:

```bash
--move-call 0x2::transfer::public_transfer "<$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans>" purchased_item @<buyer address> \
```

The final purchase PTB request, including royalties, should look like this:

```bash
iota client ptb \
--move-call $MARKETPLACE_PACKAGE_ID::marketplace_extension::get_item_price "<$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans>" @$KIOSK_ID @$CLOTHING_STORE_ITEM_ID --assign item_price \
--move-call $RULES_PACKAGE_ID::royalty_rule::fee_amount "<$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans>" @$ITEM_TRANS_POLICY item_price --assign royalties_amount \
--split-coins gas "[item_price, royalties_amount]" --assign payment_coins \
--merge-coins payment_coins.0 "[payment_coins.1]" \
--move-call $MARKETPLACE_PACKAGE_ID::marketplace_extension::buy_item "<$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans>" @$KIOSK_ID @$ITEM_TRANS_POLICY @$CLOTHING_STORE_ITEM_ID payment_coins.0 --assign purchased_item \
--move-call 0x2::transfer::public_transfer "<$MARKETPLACE_PACKAGE_ID::clothing_store::Jeans>" purchased_item @<buyer address>
```
60 changes: 60 additions & 0 deletions docs/examples/move/nft_marketplace/sources/clothing_store.move
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/// Module provides `mock` items for using them in marketplace and rental extensions.
#[allow(lint(self_transfer))]
module nft_marketplace::clothing_store {
Dkwcs marked this conversation as resolved.
Show resolved Hide resolved
use iota::package;
/// One Time Witness.
public struct CLOTHING_STORE has drop {}


fun init(otw: CLOTHING_STORE, ctx: &mut TxContext) {
valeriyr marked this conversation as resolved.
Show resolved Hide resolved
package::claim_and_keep(otw, ctx)
}

public struct TShirt has key, store {
id: UID,
}

public struct Jacket has key, store {
id: UID,
}

public struct Shoes has key, store {
id: UID,
}

public struct Jeans has key, store {
id: UID,
}

public fun new_tshirt(ctx: &mut TxContext) {
let tshirt = TShirt {
id: object::new(ctx),
};

transfer::public_transfer(tshirt, ctx.sender());
}

public fun new_jeans(ctx: &mut TxContext) {
let jeans = Jeans {
id: object::new(ctx),
};

transfer::public_transfer(jeans, ctx.sender());
}

public fun new_shoes(ctx: &mut TxContext) {
let shoes = Shoes {
id: object::new(ctx),
};

transfer::public_transfer(shoes, ctx.sender());
}

public fun new_jacket(ctx: &mut TxContext) {
let jacket = Jacket {
id: object::new(ctx),
};

transfer::public_transfer(jacket, ctx.sender());
}
}
Loading
Loading