Skip to main content

Purchasing from a kiosk

One of the base functionalities of the SDK is a seamless purchasing flow, allowing for ease of rules resolving (hiding away the calls). The SDK supports all four rules by default, and works for TESTNET and MAINNET. To support other networks, follow the instructions in the Introduction.

How to purchase

By default, the SDK places the item in the caller's kiosk, unless there's a lock rule, in which case it locks it.

Them following is an example of a purchase call.

const item = {
itemType: '0x..::hero::Hero',
itemId: '0x..',
price: 100000n,
sellerKiosk: '0xSellerKiosk',
};

// Assume `kioskClient` and `cap` are supplied to the function as explained in the previous section.
const tx = new Transaction();
const kioskTx = new KioskTransaction({ transaction: tx, kioskClient, cap });

await kioskTx.purchaseAndResolve({
itemType: item.itemType,
itemId: item.itemId,
price: item.price,
sellerKiosk: item.sellerKiosk,
});

kioskTx.finalize();

// Sign and execute transaction.
await signAndExecuteTransaction({ tx });

The function queries for a TransferPolicy for that item, and if a policy is found, it automatically resolves all the rules, one by one. You can add a custom rule resolver in the KioskClient instance, with instructions on how to resolve a custom rule. Read more in the next section.

Supporting a custom rule

You can use the purchaseAndResolve function to support a custom rule.

const kioskClient = new KioskClient({...});
const myCustomRule = {
rule: `0xMyRuleAddress::game_rule::Rule`,
packageId: `0xMyRuleAddress`,
// The resolving function. This is called when calling the `purchaseAndResolve`.
resolveRuleFunction: (params: RuleResolvingParams) => {
// By knowing the params we have here, we can extract the variables we need to resolve this rule.
const { transaction, itemType, packageId, extraArgs } = params;
const { gamePass } = extraArgs;
if(!gamePass) throw new Error("GamePass not supplied");

// Calls the game's rule prove function, which could, for example
// allow rules to resolve only if the holder has a gamePass object.
transaction.moveCall({
target: `${packageId}::game_rule::prove_pass`,
typeArguments: [itemType],
arguments: [transferRequest, transaction.object(gamePass)],
});
},
};
// This allows rules resolution from the `purchaseAndResolve` function.
kioskClient.addRuleResolver(myCustomRule);

// Assume `cap` is supplied to the function as explained in the introduction section.
const tx = new Transaction();
const kioskTx = new KioskTransaction({ transaction: tx, kioskClient, cap });

await kioskTx.purchaseAndResolve({
itemType: item.itemType,
itemId: item.itemId,
price: item.price,
sellerKiosk: item.sellerKiosk,
extraArgs: {
gamePass: '0xMyGamePassObjectId'
}
});

kioskTx.finalize();

// Sign and execute transaction.
await signAndExecuteTransaction({ tx });
// For reference, here's the RuleResolvingParams contents.
type RuleResolvingParams = {
transaction: Transaction;
itemType: string;
itemId: string;
price: string;
policyId: ObjectArgument;
kiosk: ObjectArgument;
ownedKiosk: ObjectArgument;
ownedKioskCap: ObjectArgument;
transferRequest: TransactionArgument;
purchasedItem: TransactionArgument;
packageId: string;
extraArgs: Record<string, any>; // extraParams contains more possible {key, values} to pass for custom rules.
};