From sui-dev-agents
Builds NFT marketplaces on SUI with Kiosk's transfer policies and royalty enforcement. Covers listing, delisting, purchasing, and trading NFTs with programmable rules.
How this skill is triggered — by the user, by Claude, or both
Slash command
/sui-dev-agents:sui-kioskThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
**Official NFT trading standard with transfer policies and royalties.**
Official NFT trading standard with transfer policies and royalties.
Targets: @mysten/kiosk 1.2.6 (^1.2), @mysten/sui 2.17.0 (^2.16). Tested: 2026-05-21.
Compatibility notes: @mysten/[email protected] types KioskCompatibleClient as SuiJsonRpcClient | SuiGraphQLClient only — SuiGrpcClient is not accepted. Re-check on the next minor bump.
Kiosk provides:
use sui::kiosk::{Self, Kiosk, KioskOwnerCap};
public fun create_kiosk(ctx: &mut TxContext): (Kiosk, KioskOwnerCap) {
kiosk::new(ctx)
}
public fun list_nft<T: key + store>(
kiosk: &mut Kiosk,
cap: &KioskOwnerCap,
nft: T,
price: u64
) {
kiosk::place_and_list<T>(kiosk, cap, nft, price);
}
use sui::transfer_policy::{Self, TransferPolicy};
use sui::coin::Coin;
use sui::sui::SUI;
public fun purchase_nft<T: key + store>(
kiosk: &mut Kiosk,
item_id: ID,
payment: Coin<SUI>,
policy: &TransferPolicy<T>,
ctx: &mut TxContext
): T {
let (nft, request) = kiosk::purchase<T>(kiosk, item_id, payment);
// Confirm transfer policy
transfer_policy::confirm_request(policy, request);
nft
}
use sui::transfer_policy::{Self, TransferPolicy, TransferPolicyCap};
// Create policy with royalty rule
public fun create_royalty_policy<T>(
publisher: &Publisher,
royalty_bps: u64, // Basis points (e.g., 500 = 5%)
ctx: &mut TxContext
): (TransferPolicy<T>, TransferPolicyCap<T>) {
let (policy, cap) = transfer_policy::new<T>(publisher, ctx);
// Add royalty rule
royalty_rule::add<T>(
&mut policy,
&cap,
royalty_bps,
ctx
);
(policy, cap)
}
// @check:skip
import { Transaction } from '@mysten/sui/transactions';
// List NFT for sale
async function listNFT(kioskId: string, nftId: string, price: number) {
const tx = new Transaction();
tx.moveCall({
target: '0x2::kiosk::place_and_list',
arguments: [
tx.object(kioskId),
tx.object(kioskOwnerCapId),
tx.object(nftId),
tx.pure.u64(BigInt(price))
],
typeArguments: [`${PACKAGE_ID}::nft::NFT`]
});
return await signAndExecute({ transaction: tx });
}
// Purchase NFT
async function purchaseNFT(
kioskId: string,
nftId: string,
paymentCoinId: string,
policyId: string
) {
const tx = new Transaction();
tx.moveCall({
target: '0x2::kiosk::purchase',
arguments: [
tx.object(kioskId),
tx.pure.id(nftId),
tx.object(paymentCoinId)
],
typeArguments: [`${PACKAGE_ID}::nft::NFT`]
});
// Confirm transfer policy
tx.moveCall({
target: '0x2::transfer_policy::confirm_request',
arguments: [
tx.object(policyId),
// ... transfer request
]
});
return await signAndExecute({ transaction: tx });
}
❌ Bypassing Kiosk transfer policies
kiosk::purchase and transfer_policy::confirm_request❌ Not checking NFT ownership before listing
kiosk::has_item before listing❌ Forgetting to delist before transfer
kiosk::delist before any transfer operation❌ Hardcoding royalty percentages
❌ Not handling zero-price listings
Query Kiosk docs:
// @check:skip
const kioskInfo = await sui_docs_query({
type: "docs",
target: "kiosk",
query: "transfer policy and royalty implementation"
});
Standard, secure, royalty-enabled NFT trading!
npx claudepluginhub first-mover-tw/sui-dev-agents --plugin sui-dev-agentsProvides behavioral guidelines to reduce common LLM coding mistakes, focusing on simplicity, surgical changes, assumption surfacing, and verifiable success criteria.
Searches, retrieves, and installs Agent Skills from prompts.chat registry using MCP tools like search_skills and get_skill. Activates for finding skills, browsing catalogs, or extending Claude.