> For the complete documentation index, see [llms.txt](/llms.txt)

# Migrating from Kiosk SDK V1

Migrate from Kiosk SDK v1 to the current version with the builder-pattern API.



The original version of Kiosk SDK provided basic experimentation with the Kiosk API. The new version
of the SDK (0.7+) provides a more robust experience for building kiosk/transfer policy transactions.

The new SDK offers a builder-pattern API, which provides better autocomplete capabilities, and also
makes code more readable.

While a one-to-one mapping between the old and new SDK is not possible, the following examples
should help you get started.

> An important benefit of the new SDK is that it works seamlessly with Personal Kiosk, which was not
> the case with the previous SDK (you would always have to wrap the transaction with `borrow_cap` /
> `return_cap` calls depending on whether the kiosk is personal or not).

## Placing an item to kiosk and listing it for sale

The following example is from the original Kiosk SDK V1 documentation.

### Before

```typescript
import { placeAndList } from '@mysten/kiosk';
import { Transaction } from '@mysten/sui/transactions';

const placeAndListToKiosk = async () => {
	const kiosk = 'SomeKioskId';
	const kioskCap = 'KioskCapObjectId';
	const itemType = '0xItemAddr::some:ItemType';
	const item = 'SomeItemId';
	const price = '100000';

	const tx = new Transaction();

	placeAndList(tx, itemType, kiosk, kioskCap, item, price);

	// ... continue to sign and execute the transaction
	// ...
};
```

### After

Using the new SDK, you can build the same transaction as follows:

```typescript
import { kiosk, KioskTransaction } from '@mysten/kiosk';
import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';

// You need to do this only once and re-use it in the application.
const client = new SuiJsonRpcClient({
	url: getJsonRpcFullnodeUrl('mainnet'),
	network: 'mainnet',
}).$extend(kiosk());

const placeAndListToKiosk = async () => {
	// Assume you have saved the user's preferred kiosk Cap somewhere in your app's state.
	const { kioskOwnerCaps } = await client.kiosk.getOwnedKiosks({ address: '0xSomeAddress' });

	const tx = new Transaction();

	// Assume you use the first owned kiosk.
	new KioskTransaction({ transaction: tx, kioskClient: client.kiosk, cap: kioskOwnerCaps[0] })
		.placeAndList({
			itemType: '0xItemAddr::some:ItemType',
			item: 'SomeItemId',
			price: '100000',
		})
		.finalize();

	// ... continue to sign and execute the transaction
};
```

## Create a new kiosk

The following example is from the original Kiosk SDK V1 documentation.

### Before

```typescript
import { createKioskAndShare } from '@mysten/kiosk';
import { Transaction } from '@mysten/sui/transactions';

const createKiosk = async () => {
	const accountAddress = '0xSomeSuiAddress';

	const tx = new Transaction();
	const kiosk_cap = createKioskAndShare(tx);

	tx.transferObjects([kiosk_cap], accountAddress);

	// ... continue to sign and execute the transaction
	// ...
};
```

### After

Using the new SDK, you can build the same transaction as follows:

```typescript
import { kiosk, KioskTransaction } from '@mysten/kiosk';
import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';

// You need to do this only once and re-use it in the application.
const client = new SuiJsonRpcClient({
	url: getJsonRpcFullnodeUrl('mainnet'),
	network: 'mainnet',
}).$extend(kiosk());

const createKiosk = async () => {
	const tx = new Transaction();

	const kioskTx = new KioskTransaction({ transaction: tx, kioskClient: client.kiosk });

	kioskTx.create().shareAndTransferCap('0xSomeSuiAddress').finalize();

	// ... continue to sign and execute the transaction
};
```

## Purchasing an item and resolving rules

The following example is from the original Kiosk SDK V1 documentation.

### Before

```typescript
import {
	queryTransferPolicy,
	purchaseAndResolvePolicies,
	place,
	testnetEnvironment,
} from '@mysten/kiosk';
import { SuiJsonRpcClient } from '@mysten/sui/jsonRpc';

const client = new SuiJsonRpcClient({
	url: 'https://fullnode.testnet.sui.io:443',
});

// The kiosk we're purchasing from.
const kioskId = `0xSomeKioskAddress`;
// A sample item retrieved from `fetchKiosk` function (or hard-coded).
const item = {
	isLocked: false,
	objectId: '0xb892d61a9992a10c9453efcdbd14ca9720d7dc1000a2048224209c9e544ed223',
	type: '0x52852c4ba80040395b259c641e70b702426a58990ff73cecf5afd31954429090::test::TestItem',
	listing: {
		isExclusive: false,
		listingId: '0x368b512ff2514dbea814f26ec9a3d41198c00e8ed778099961e9ed22a9f0032b',
		price: '20000000000', // in MIST
	},
};
const ownedKiosk = `0xMyKioskAddress`;
const ownedKioskCap = `0xMyKioskOwnerCap`;

const purchaseItem = async (item, kioskId) => {
	// Fetch the policy of the item (could be an array, if there's more than one transfer policy)
	const policies = await queryTransferPolicy(client, item.type);
	// Selecting the first one for simplicity.
	const policyId = policy[0]?.id;
	// Initialize transaction.
	const tx = new Transaction();

	// Both are required if there is a `kiosk_lock_rule`.
	// Optional otherwise. Function throws an error if there's a kiosk_lock_rule and these are missing.
	const extraParams = {
		ownedKiosk,
		ownedKioskCap,
	};
	// Define the environment.
	// To use a custom package address for rules, you could call:
	// const environment = customEnvironment('<PackageAddress>');
	const environment = testnetEnvironment;

	// Extra params. Optional, but required if the user tries to resolve a `kiosk_lock_rule`.
	// Purchases the item. Supports `kiosk_lock_rule`, `royalty_rule` (accepts combination too).
	const result = purchaseAndResolvePolicies(
		tx,
		item.type,
		item.listing.price,
		kioskId,
		item.objectId,
		policy[0],
		environment,
		extraParams,
	);

	// result = {item: <the_purchased_item>, canTransfer: true/false // depending on whether there was a kiosk lock rule }
	// If the item didn't have a kiosk_lock_rule, you need to do something with it.
	// For example, place it in your own kiosk. (demonstrated below)
	if (result.canTransfer) place(tx, item.type, ownedKiosk, ownedKioskCap, result.item);

	// ...finally, sign PTB & execute it.
};
```

### After

Using the new SDK, you can build the same transaction as follows:

> This works with both personal and non-personal kiosks.

```typescript
import { kiosk, KioskTransaction } from '@mysten/kiosk';
import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';

// You need to do this only once and re-use it in the application.
const client = new SuiJsonRpcClient({
	url: getJsonRpcFullnodeUrl('mainnet'),
	network: 'mainnet',
}).$extend(kiosk());

// An Item as returned from `client.kiosk.getKiosk()` call.
const item = {
	isLocked: false,
	objectId: '0xb892d61a9992a10c9453efcdbd14ca9720d7dc1000a2048224209c9e544ed223',
	type: '0x52852c4ba80040395b259c641e70b702426a58990ff73cecf5afd31954429090::test::TestItem',
	kioskId: '0xSomeKioskAddress',
	listing: {
		isExclusive: false,
		listingId: '0x368b512ff2514dbea814f26ec9a3d41198c00e8ed778099961e9ed22a9f0032b',
		price: '20000000000', // in MIST
	},
};

const purchase = async () => {
	// Assume you have saved the user's preferred kiosk Cap somewhere in your app's state.
	// You wouldn't need to query this for every purchase.
	const { kioskOwnerCaps } = await client.kiosk.getOwnedKiosks({ address: '0xSomeAddress' });

	const tx = new Transaction();

	const kioskTx = new KioskTransaction({
		transaction: tx,
		kioskClient: client.kiosk,
		cap: kioskOwnerCaps[0],
	});

	// Purchase the item and resolve the rules.
	await kioskTx.purchaseAndResolve({
		itemType: item.type,
		itemId: item.objectId,
		price: item.listing.price,
		sellerKiosk: item.kioskId,
	});

	kioskTx.finalize();
};
```

## Attach rules to transfer policy

The following example was taken from the original Kiosk SDK V1 documentation.

### Before

```typescript
import {
	attachKioskLockRule,
	attachRoyaltyRule,
	createTransferPolicy,
	percentageToBasisPoints,
	testnetEnvironment,
} from '@mysten/kiosk';
import { Transaction } from '@mysten/sui/transactions';

// Attaches a royalty rule of 1% or 0.1 SUI (whichever is bigger)
// as well as a kiosk lock, making the objects tradeable only from/to a kiosk.
const attachStrongRoyalties = async () => {
	const type = 'SomePackageId::type::MyType'; // the Type for which we're attaching rules.
	const policyId = 'policyObjectId'; // the transfer Policy ID that was created for that Type.
	const transferPolicyCap = 'transferPolicyCapId'; // the transferPolicyCap for that policy.

	// Royalties configuration.
	const percentage = 2.55; // 2.55%
	const minAmount = 100_000_000; // 0.1 SUI.

	// The environment on which we're referencing the rules package.
	// Use `mainnetEnvironment` for mainnet.
	const environment = testnetEnvironment;

	const tx = new Transaction();

	attachKioskLockRule(tx, type, policyId, policyCapId, environment);
	attachRoyaltyRule(
		tx,
		type,
		policyId,
		policyCapId,
		percentageToBasisPoints(percentage),
		minAmount,
		environment,
	);

	// ... continue to sign and execute the transaction
	// ...
};
```

### After

On the new SDK, the same transaction can be built as follows:

```typescript
import { kiosk, TransferPolicyTransaction, percentageToBasisPoints } from '@mysten/kiosk';
import { SuiJsonRpcClient, getJsonRpcFullnodeUrl } from '@mysten/sui/jsonRpc';

// You need to do this only once and re-use it in the application.
const client = new SuiJsonRpcClient({
	url: getJsonRpcFullnodeUrl('mainnet'),
	network: 'mainnet',
}).$extend(kiosk());

const adjustPolicy = async () => {
	const tx = new Transaction();

	// You could have more than one cap, since you can create more than one transfer policy.
	const policyCaps = await client.kiosk.getOwnedTransferPoliciesByType({
		type: `SomePackageId::type::MyType`,
		address: '0xOwnerAddress',
	});

	new TransferPolicyTransaction({ transaction: tx, kioskClient: client.kiosk, cap: policyCaps[0] })
		.addRoyaltyRule(percentageToBasisPoints(2.55), 100_000_000)
		.addLockRule();

	// ... continue to sign and execute the transaction
	// ...
};
```
