Contracts
Marketplace contract
The market Move package behind Rare Marketplace: listings, offers, offer pools, swaps, raffles, bundles, fees, events and PTB examples.
The market package runs trading on Rare Marketplace. It covers fixed-price listings for kiosk and wallet items, item, collection and trait offers, offer pools, item-for-item swaps, raffles, bundles and the crate shop. It depends on the Sui framework and on Mysten's kiosk rules package (royalty_rule, kiosk_lock_rule, personal_kiosk_rule, floor_price_rule).
On this page, PACKAGE_ID is the latest package id, T is the item type, and every amount is in MIST. Shared objects are passed as normal object inputs: the SDK resolves initialSharedVersion.
Modules
Shared objects and caps
Listings, offers and bids are deleted when they close, so a listing that no longer exists is no longer live.
barter::Swap, barter::Unwind, bundle::Checkout, bundle::Handover and bundle::Unstack are hot potatoes: they have no abilities and must be consumed in the same PTB that created them.
Rules every call follows
- Config gate. Every call that opens an order or fills one takes
&Configand aborts with101while the market is paused, or102when this package version is retired. Cancels, refunds, payouts and unlistings never takeConfig, so neither a pause nor an upgrade can lock your items or SUI. - No contention. Buys and fills read
Configby&. Each order, offer, pool, raffle, bundle and swap is its own shared object, so trades on different objects never wait on each other. The collection'sTransferPolicyis taken&mutwhenever royalty is paid, becauseroyalty_rule::paywrites to it. - Transfer policies. Calls that move an item into a kiosk satisfy the four standard rules: they pay royalty, lock the item when the policy has a lock rule (otherwise they place it), and prove the personal kiosk and floor price rules. They return the
TransferRequest<T>. You add receipts for any other rule and call0x2::transfer_policy::confirm_request<T>(policy, request). The item is already in its destination when the request comes back. - Payments are
&mut Coin<SUI>. Each call splits off exactly what it needs and you keep the rest. Calls that pay you return aCoin<SUI>. - Deliveries to someone who is not signing (offer fills, bundle bids, items a swap maker receives) go into a kiosk that has the
courierextension, and only if that kiosk'sowneris the recipient. Set this up once withcourier::openorcourier::enable. - Type names.
kindin events and offer terms istype_name::with_defining_ids<T>(). In JSON it is the type string without the0xprefix.
Listings
sale_kiosk: kiosk items
Use this for any type that has a TransferPolicy. The item stays in the seller's kiosk, listed exclusively through a PurchaseCap held by the order, so it can only leave through this module.
public fun post<T: key + store>(
cfg: &Config,
kiosk: &mut Kiosk,
kiosk_cap: &KioskOwnerCap,
item: ID,
ask: u64,
ctx: &mut TxContext,
): IDLists item at ask and returns the order id. cut = ask * listing_bps / 10000, and the item is listed in the kiosk at ask - cut. Aborts: 211 when ask is 0.
public fun buy<T: key + store>(
order: KioskOrder<T>,
cfg: &Config,
kiosk: &mut Kiosk, // the seller's kiosk
dest: &mut Kiosk, // the buyer's kiosk
dest_cap: &KioskOwnerCap,
policy: &mut TransferPolicy<T>,
pay: &mut Coin<SUI>,
ctx: &mut TxContext,
): TransferRequest<T>Buys the item into the buyer's kiosk. Takes ask from pay, sends cut to the treasury, then pays royalty on ask - cut from the same coin. Confirm the returned request. Aborts: 212 wrong seller kiosk, 214 when pay is below ask, 901 when what is left cannot cover the royalty.
public fun take<T: key + store>(
order: KioskOrder<T>,
cfg: &Config,
kiosk: &mut Kiosk,
pay: &mut Coin<SUI>,
ctx: &mut TxContext,
): (T, TransferRequest<T>)Raw purchase. You get the item and the request and resolve the policy yourself, for example with clearing::settle_into(policy, &mut request, item, kiosk, kiosk_cap, royalty_coin), then confirm.
public fun reprice<T: key + store>(order: KioskOrder<T>, cfg: &Config, kiosk: &mut Kiosk, kiosk_cap: &KioskOwnerCap, ask: u64, ctx: &mut TxContext): ID
public fun pull<T: key + store>(order: KioskOrder<T>, kiosk: &mut Kiosk, kiosk_cap: &KioskOwnerCap)reprice replaces the order with a new one and returns the new id. pull unlists and is never gated. Both need the kiosk's owner cap (212 wrong kiosk, 213 no access).
The buyer pays ask plus royalty. The treasury gets cut. The seller's kiosk profits get ask - cut, which the seller withdraws with 0x2::kiosk::withdraw.
sale_escrow: wallet items
For types without a TransferPolicy. This path cannot enforce a policy, so route any type that has one to sale_kiosk.
public fun post<T: key + store>(cfg: &Config, item: T, ask: u64, ctx: &mut TxContext): ID
public fun take<T: key + store>(order: EscrowOrder<T>, cfg: &Config, pay: &mut Coin<SUI>, ctx: &mut TxContext): T
public fun reprice<T: key + store>(order: &mut EscrowOrder<T>, cfg: &Config, ask: u64, ctx: &mut TxContext)
public fun pull<T: key + store>(order: EscrowOrder<T>, ctx: &mut TxContext): Ttake sends cut to the treasury and ask - cut to the maker's address, and returns the item. reprice and pull are maker only (202). pull is never gated. Aborts: 201 zero ask, 203 short payment.
Sweeps
There is no sweep function. A sweep is one PTB that calls sale_kiosk::buy (or sale_escrow::take) once per order and passes the same payment coin to every call. Each call splits off what it needs, so you do not need a SplitCoins per listing. Orders are independent objects, so a sweep only touches the orders and seller kiosks involved.
Offers
offer: item, collection and trait offers
public fun place<T: key + store>(
cfg: &Config,
policy: &TransferPolicy<T>,
scope: u8, // 0 any item of T, 1 one item, 2 any item in a Merkle set
item: Option<ID>, // scope 1 only
root: Option<vector<u8>>, // scope 2 only, 32 bytes
each: u64, // price per unit, paid to the seller
qty: u64,
until_ms: Option<u64>, // expiry, none for no expiry
dest: Option<ID>, // your courier-enabled kiosk, needed for kiosk fills
pay: &mut Coin<SUI>,
clock: &Clock,
ctx: &mut TxContext,
): IDEscrows qty * (each + fee + reserve), where fee = each * offer_bps / 10000 and reserve = clearing::royalty_due(policy, each). Scope 1 needs item and qty = 1. Aborts: 301 bad scope arguments, 302 zero price, 303 zero quantity, 304 expiry in the past, 305 short payment.
place_unruled<T> takes the same arguments without policy and sets reserve = 0. Kiosk fills of a type whose policy charges royalty then abort with 901. Wallet fills still work.
public fun fill<T: key + store>(
offer: &mut Offer<T>,
cfg: &Config,
seller_kiosk: &mut Kiosk,
seller_cap: &KioskOwnerCap,
item: ID,
dest: &mut Kiosk, // must be the offer's dest kiosk
policy: &mut TransferPolicy<T>,
proof: vector<vector<u8>>, // empty unless scope 2
clock: &Clock,
ctx: &mut TxContext,
): (Coin<SUI>, TransferRequest<T>)Sells a kiosk item into the offer. The item is bought out of the seller's kiosk at each and delivered into the maker's kiosk through courier. Royalty comes out of the offer's reserve and the unused reserve for that unit goes back to the maker. Returns the seller's proceeds (each, in full) and the request to confirm. Aborts: 307 no units left, 308 expired, 309 wrong item, 310 not in the set, 311 wrong type, 312 offer has no dest, 313 wrong dest, 802 the dest kiosk is not the maker's, 901 reserve short.
public fun fill_owned<T: key + store>(offer: &mut Offer<T>, cfg: &Config, item: T, proof: vector<vector<u8>>, clock: &Clock, ctx: &mut TxContext): Coin<SUI>
public fun revoke<T>(offer: Offer<T>, ctx: &mut TxContext): Coin<SUI>
public fun retire<T>(offer: Offer<T>, clock: &Clock, ctx: &mut TxContext)fill_owned sells a wallet item: it goes to the maker's address, the reserve goes back to the maker and the seller gets each. revoke is maker only (306) and refunds the whole remaining escrow, fees included. It is never gated. retire can be called by anyone once the offer is expired or fully filled (314 otherwise) and sends the escrow to the maker.
Views: terms, maker, escrowed, units_left, unit_price, unit_fee, unit_reserve, scope_any(), scope_item(), scope_set().
Trait offers (scope 2)
The bidder commits a Merkle root over the eligible item ids. The seller passes the proof for their item.
- Leaf:
blake2b256(0x00 || bcs(id)). - Node:
blake2b256(0x01 || min(a, b) || max(a, b)), in lexicographic byte order. - Proof: the sibling hashes from leaf to root.
merkle::leaf, merkle::join and merkle::contains compute the same thing on chain.
offer_pool: many offers on one balance
One balance backs up to 128 offers. Each member reserves its full escrow from the pool, and held can never exceed funds.
public fun new(cfg: &Config, label: Option<String>, ctx: &mut TxContext): OfferPool // unshared
public fun share(pool: OfferPool)
public fun deposit(pool: &mut OfferPool, pay: Coin<SUI>, ctx: &mut TxContext)
public fun withdraw(pool: &mut OfferPool, amount: u64, ctx: &mut TxContext): Coin<SUI>
public fun add<T: key + store>(pool: &mut OfferPool, cfg: &Config, policy: &TransferPolicy<T>, scope: u8, item: Option<ID>, root: Option<vector<u8>>, each: u64, qty: u64, until_ms: Option<u64>, dest: Option<ID>, clock: &Clock, ctx: &mut TxContext): ID
public fun fill<T: key + store>(pool: &mut OfferPool, member: ID, cfg: &Config, seller_kiosk: &mut Kiosk, seller_cap: &KioskOwnerCap, item: ID, dest: &mut Kiosk, policy: &mut TransferPolicy<T>, proof: vector<vector<u8>>, clock: &Clock, ctx: &mut TxContext): (Coin<SUI>, TransferRequest<T>)
public fun fill_owned<T: key + store>(pool: &mut OfferPool, member: ID, cfg: &Config, item: T, proof: vector<vector<u8>>, clock: &Clock, ctx: &mut TxContext): Coin<SUI>
public fun drop_member(pool: &mut OfferPool, member: ID, ctx: &mut TxContext)
public fun prune(pool: &mut OfferPool, member: ID, clock: &Clock)
public fun close(pool: OfferPool, ctx: &mut TxContext): Coin<SUI>Create the pool with new, deposit and add members in the same PTB, then share it. fill and fill_owned follow the same rules as the offer versions, and a filled-out member is deleted. add_unruled<T> adds a member with no royalty reserve. deposit, withdraw, relabel, drop_member and close are maker only (351). withdraw is limited to funds - held (352). prune lets anyone remove an expired or filled-out member (355). withdraw, drop_member and close are never gated. Aborts: 353 more than 128 members, 354 unknown member.
Swaps (barter)
A swap trades items and SUI between a maker and a taker, both sides in kiosks.
The maker builds the deal in one PTB:
public fun draft(cfg: &Config, maker_kiosk: &mut Kiosk, kiosk_cap: &KioskOwnerCap, want: vector<ID>, ask_sui: u64, bid_sui: u64, taker: Option<address>, ttl_epochs: u64, pay: &mut Coin<SUI>, ctx: &mut TxContext): Deal
public fun pledge<T: key + store>(deal: &mut Deal, maker_kiosk: &mut Kiosk, kiosk_cap: &KioskOwnerCap, item: ID, ctx: &mut TxContext)
public fun publish(deal: Deal)draft enables courier on the maker's kiosk, pays the swap fee (bid_sui * swap_bps / 10000 + swap_flat) and escrows bid_sui. The kiosk owner must be the sender (402). pledge adds each offered item (it must not be listed, 416). publish shares the deal (405 when nothing is offered). Up to 32 wanted items, with no duplicates (414, 415).
The taker settles in one PTB:
public fun begin(deal: &mut Deal, cfg: &Config, pay: &mut Coin<SUI>, ctx: &mut TxContext): Swap
public fun hand<T: key + store>(swap: &mut Swap, deal: &mut Deal, maker_kiosk: &mut Kiosk, taker_kiosk: &mut Kiosk, taker_cap: &KioskOwnerCap, policy: &mut TransferPolicy<T>, item: ID, pay: &mut Coin<SUI>, ctx: &mut TxContext): TransferRequest<T>
public fun receive<T: key + store>(swap: &mut Swap, deal: &mut Deal, taker_kiosk: &mut Kiosk, taker_cap: &KioskOwnerCap, maker_kiosk: &mut Kiosk, policy: &mut TransferPolicy<T>, item: ID, pay: &mut Coin<SUI>, ctx: &mut TxContext): TransferRequest<T>
public fun finish(swap: Swap, deal: Deal, ctx: &mut TxContext)begin checks the deal is live (404), not expired (406) and that the sender is the named taker, if any (407). It takes ask_sui from pay and sends ask_sui * fee_bps / 10000 of it to the treasury. Call hand once per offered item (it moves into the taker's kiosk) and receive once per wanted item (it moves into the maker's kiosk through courier, and the taker is paid an even part of bid_sui). Royalty for both comes from pay. finish aborts unless every item moved (411). Confirm every returned request. If a side has no items, its SUI goes straight to the other party.
To cancel, call unwind(&mut Deal), then restore<T> per pledged item, then unwound. The maker can always unwind. Anyone can once epoch > expiry_epoch (412 otherwise). The escrowed SUI goes back to the maker. Unwinding is never gated.
Raffles
public fun open_kiosk<T: key + store>(cfg: &Config, policy: &TransferPolicy<T>, kiosk: &mut Kiosk, kiosk_cap: &KioskOwnerCap, item: ID, price: u64, min_tickets: u64, max_tickets: u64, ends_ms: u64, clock: &Clock, ctx: &mut TxContext): ID
public fun open_owned<T: key + store>(cfg: &Config, prize: T, price: u64, min_tickets: u64, max_tickets: u64, ends_ms: u64, clock: &Clock, ctx: &mut TxContext): ID
public fun buy<T>(raffle: &mut Raffle<T>, cfg: &Config, qty: u64, pay: &mut Coin<SUI>, clock: &Clock, ctx: &mut TxContext)
entry fun draw<T>(raffle: &mut Raffle<T>, rnd: &Random, clock: &Clock, ctx: &mut TxContext)open_kiosk keeps the prize in the host's kiosk under an exclusive cap and binds the policy. open_owned escrows a wallet item. Limits: 1 <= min_tickets <= max_tickets <= 1,000,000 (502), price above 0 (501), and ends_ms in the future and within 30 days (503). buy works before ends_ms (505) up to max_tickets (506).
draw is an entry function that reads 0x8 (Random). Anyone can call it once the raffle has ended or sold out (509) with at least min_tickets sold (510). Because a call that uses Random cannot be followed by other commands, settlement is a separate transaction:
settle_kiosk<T>(raffle, host_kiosk, policy): TransferRequest<T>: anyone. The prize goes into a new kiosk owned by the winner (personal when the policy needs it). The policy must be the bound one (518).claim_kiosk<T>(raffle, host_kiosk, policy, kiosk, kiosk_cap): TransferRequest<T>: winner only (512), into their own kiosk.settle_owned<T>(raffle): anyone, for wallet prizes.
The pot pays the fee to the treasury, then (for kiosk prizes) royalty on the sale price, and the rest to the host. void cancels a raffle: the host before any sale, anyone after the end with too few tickets sold, or anyone when a drawn raffle has gone unsettled for 7 days. After void, anyone can call refund<T>(raffle, holder) to pay a ticket holder back in full and reclaim_kiosk<T> to return a kiosk prize, and dispose deletes the raffle once everything is returned. None of these are gated.
Bundles
The maker lists several kiosk items as one lot:
public fun draft(cfg: &Config, ctx: &mut TxContext): Bundle
public fun stack<T: key + store>(bundle: &mut Bundle, kiosk: &mut Kiosk, kiosk_cap: &KioskOwnerCap, item: ID, ctx: &mut TxContext)
public fun publish(bundle: Bundle, ask: u64, seal: Option<vector<u8>>)At most 32 items (603). The price is split evenly across the items and the last item takes the remainder. seal is an optional sealed reserve for bids: commitment(reserve, salt) = blake2b256(bcs(reserve) || salt). reseal changes it later. Unlisting is unstack, restore<T> per item, then unstacked, and is never gated.
A buyer takes the whole bundle in one PTB:
public fun checkout(bundle: &mut Bundle, cfg: &Config, pay: &mut Coin<SUI>, _ctx: &mut TxContext): Checkout
public fun collect<T: key + store>(co: &mut Checkout, bundle: &mut Bundle, seller_kiosk: &mut Kiosk, dest: &mut Kiosk, dest_cap: &KioskOwnerCap, policy: &mut TransferPolicy<T>, item: ID, royalty: &mut Coin<SUI>, ctx: &mut TxContext): TransferRequest<T>
public fun checkout_done(co: Checkout, bundle: Bundle, cfg: &Config, ctx: &mut TxContext)checkout takes ask + ask * bundle_bps / 10000 (607 if short). Call collect once per item, then checkout_done, which aborts unless every item was collected (610).
Bids escrow amount + amount * bundle_bps / 10000 + reserve, where reserve is the royalty budget, and name the bidder's courier-enabled kiosk as dest:
public fun bid(bundle: &Bundle, cfg: &Config, amount: u64, reserve: u64, until_ms: u64, dest: ID, pay: &mut Coin<SUI>, clock: &Clock, ctx: &mut TxContext): ID
public fun withdraw_bid(b: BundleBid, ctx: &mut TxContext): Coin<SUI>
public fun lapse_bid(b: BundleBid, clock: &Clock, ctx: &mut TxContext)withdraw_bid is bidder only and never gated. lapse_bid returns an expired bid to its bidder and anyone can call it. To accept, call accept(bundle, bid, cfg, reveal, salt, clock), then deliver<T> per item, then accepted. The maker can accept any bid without a reveal. Anyone else needs the reveal of the sealed reserve (615), and the bid must be at least the reserve (616). A reveal that lands on chain, even in a failed transaction, discloses the reserve, so reseal after using it.
Crate shop
public fun buy(shop: &Shop, cfg: &Config, tier: u8, qty: u64, max_unit: u64, pay: &mut Coin<SUI>, ctx: &mut TxContext)Pays price * qty to the treasury. max_unit protects you from a price change. Aborts: 701 bad tier, 702 zero quantity, 703 unit price above max_unit, 704 short payment, 705 shop closed. Default tiers are 1, 30, 75 and 200 SUI.
Courier and clearing helpers
public fun open(personal: bool, ctx: &mut TxContext): ID
public fun enable(kiosk: &mut Kiosk, cap: &KioskOwnerCap, ctx: &mut TxContext)
public fun ready(kiosk: &Kiosk): boolcourier::open creates and shares a kiosk for the sender with deliveries enabled. With personal = true the owner cap is wrapped as a PersonalKioskCap, which collections with a personal kiosk rule require. courier::enable installs (or re-enables) the extension on an existing kiosk. For a personal kiosk, pass the cap borrowed from your PersonalKioskCap.
public fun royalty_due<T: key + store>(policy: &TransferPolicy<T>, paid: u64): u64
public fun needs_lock<T>(policy: &TransferPolicy<T>): bool
public fun needs_personal<T>(policy: &TransferPolicy<T>): bool
public fun settle_into<T: key + store>(policy: &mut TransferPolicy<T>, req: &mut TransferRequest<T>, item: T, kiosk: &mut Kiosk, cap: &KioskOwnerCap, royalty: &mut Coin<SUI>, ctx: &mut TxContext): u64royalty_due quotes the royalty on a payment (0 without a royalty rule). settle_into stows an item you bought into your kiosk, satisfies the standard rules, pays royalty from royalty and returns the amount paid.
Fees and royalties
Every rate starts at 10 bps (0.1%), with no flat swap fee. Rates are capped at 500 bps each and the flat fee at 1 SUI (103). Changes are queued with the ConfigCap and take effect only after a 48 hour delay, through config::apply, which anyone can call. Fees round down, so a fee on an amount below 1,000 MIST is 0 and the trade goes through without one.
Royalties follow the collection's own TransferPolicy (royalty_rule). On a kiosk listing the buyer pays royalty on top, computed on the kiosk price ask - cut. On offers it comes from the reserve the maker escrowed. On swaps and bundle purchases it comes from the pay or royalty coin you pass in. Read a quote with clearing::royalty_due.
Events
All events are in PACKAGE_ID::events, with the original package id in their type. Field order never changes, so decode them from BCS with these layouts.
Error codes
Examples
These use @mysten/sui with the Transaction builder. Replace the placeholder ids with the values from the status box above.
Buy a kiosk listing
import { Transaction } from "@mysten/sui/transactions";
const PACKAGE_ID = "0x..."; // latest market package id
const CONFIG_ID = "0x..."; // shared market::config::Config
export function buyListing(
tx: Transaction,
l: {
orderId: string; // KioskOrder id (the `order` field of KioskPosted)
sellerKiosk: string; // `maker_kiosk`
itemType: string; // T, for example "0xabc::nft::Nft"
policyId: string; // shared TransferPolicy<T>
ask: bigint; // in MIST
},
buyer: { kiosk: string; kioskCap: string },
) {
// Pay the ask plus a royalty quote. Royalty is charged on `ask - cut`,
// so a quote on `ask` is an upper bound and the change comes back.
const [due] = tx.moveCall({
target: `${PACKAGE_ID}::clearing::royalty_due`,
typeArguments: [l.itemType],
arguments: [tx.object(l.policyId), tx.pure.u64(l.ask)],
});
const [pay] = tx.splitCoins(tx.gas, [l.ask]);
const [royalty] = tx.splitCoins(tx.gas, [due]);
tx.mergeCoins(pay, [royalty]);
const [request] = tx.moveCall({
target: `${PACKAGE_ID}::sale_kiosk::buy`,
typeArguments: [l.itemType],
arguments: [
tx.object(l.orderId),
tx.object(CONFIG_ID),
tx.object(l.sellerKiosk),
tx.object(buyer.kiosk),
tx.object(buyer.kioskCap),
tx.object(l.policyId),
pay,
],
});
tx.moveCall({
target: "0x2::transfer_policy::confirm_request",
typeArguments: [l.itemType],
arguments: [tx.object(l.policyId), request],
});
tx.mergeCoins(tx.gas, [pay]); // return the change
}To sweep, call sale_kiosk::buy once per listing with the same pay coin, funded with the sum of the asks and royalty quotes.
If the buyer has no kiosk yet, create one in the same PTB with 0x2::kiosk::new, pass it to buy, then share it and send the cap to the buyer:
const [kiosk, kioskCap] = tx.moveCall({ target: "0x2::kiosk::new" });
// ... sale_kiosk::buy with `kiosk` and `kioskCap` as dest and dest_cap ...
tx.moveCall({
target: "0x2::transfer::public_share_object",
typeArguments: ["0x2::kiosk::Kiosk"],
arguments: [kiosk],
});
tx.transferObjects([kioskCap], sender);Collections with a personal kiosk rule need a personal kiosk instead.
List a kiosk item
tx.moveCall({
target: `${PACKAGE_ID}::sale_kiosk::post`,
typeArguments: [itemType],
arguments: [
tx.object(CONFIG_ID),
tx.object(kioskId),
tx.object(kioskCapId),
tx.pure.id(itemId),
tx.pure.u64(5_000_000_000n), // ask: 5 SUI, buyer pays this plus royalty
],
});Place a collection offer
const SCOPE_ANY = 0;
const each = 2_000_000_000n; // 2 SUI per item
const qty = 3n;
// Escrow is qty * (each + fee + reserve):
// fee = each * offer_bps / 10000 (offer_bps from the Config object)
// reserve = clearing::royalty_due(policy, each)
// Fund at least that much. Whatever the call does not use stays in `pay`.
const budget = qty * (each + fee + reserve);
const [pay] = tx.splitCoins(tx.gas, [budget]);
tx.moveCall({
target: `${PACKAGE_ID}::offer::place`,
typeArguments: [itemType],
arguments: [
tx.object(CONFIG_ID),
tx.object(policyId),
tx.pure.u8(SCOPE_ANY),
tx.pure.option("address", null), // item: none for scope 0
tx.pure.option("vector<u8>", null), // root: none for scope 0
tx.pure.u64(each),
tx.pure.u64(qty),
tx.pure.option("u64", Date.now() + 7 * 86_400_000), // expires in 7 days
tx.pure.option("address", myCourierKioskId), // dest kiosk for kiosk fills
pay,
tx.object("0x6"),
],
});
tx.mergeCoins(tx.gas, [pay]);myCourierKioskId must be a kiosk you own with the courier extension installed (courier::open or courier::enable).
Sell into an offer from your kiosk
const [proceeds, request] = tx.moveCall({
target: `${PACKAGE_ID}::offer::fill`,
typeArguments: [itemType],
arguments: [
tx.object(offerId),
tx.object(CONFIG_ID),
tx.object(myKioskId),
tx.object(myKioskCapId),
tx.pure.id(itemId),
tx.object(destKioskId), // the offer's `dest_kiosk` from OfferPlaced
tx.object(policyId),
tx.pure.vector("vector<u8>", []), // Merkle proof for trait offers, else empty
tx.object("0x6"),
],
});
tx.moveCall({
target: "0x2::transfer_policy::confirm_request",
typeArguments: [itemType],
arguments: [tx.object(policyId), request],
});
tx.transferObjects([proceeds], sender);If the item is listed natively in your kiosk, delist it first with 0x2::kiosk::delist. For pool members, call offer_pool::fill with the pool id and the member id in front of the same arguments.
