Skip to content

Marketplace (Native API example) ​

Register a marketplace, list NFTs for sale or auction, buy and bid. Reference: marketplace pallet.

Copied from Futureverse’s futureversecom/trn-examples, deleted with its GitHub organisation, at commit 44c9e16 of 2024-10-31. Apache-2.0: license. Before you run it, read Running the examples.

Offline destinations

Some places this page points to did not answer when last checked:

  • docs-beta.therootnetwork.com — does not resolve (checked 2026-10-18)
  • stackblitz.com/github/futureversecom — StackBlitz loads these projects from the deleted futureversecom organisation on GitHub (checked 2026-10-18)

Run in StackBlitz (repository deleted, checked 2026-10-18) · Pallet Documentation (offline, checked 2026-10-18)

IMPORTANT

Ensure the following ENV vars are available before running the examples

Examples ​

bash
# change your working directory to this example first
cd examples/substrate/use-marketplace

# export all required environments
export CALLER_PRIVATE_KEY=

# register a new marketplace
pnpm call:registerMarketplace

# list a bundle of NFTs as fixed price sell
pnpm call:sell

# buy a listing
pnpm call:buy

# list a bundle NFT as auction
pnpm call:auction

# submit a bid to an auction listing
pnpm call:bid

Source files ​

src/auction.ts ​

ts
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import { XRP_ASSET_ID } from "@trne/utils/porcini-assets";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";
import assert from "node:assert";

interface OwnedTokens {
	0: number;
	1: number;
	2: number[];
}

/**
 * Use `marketplace.auctionNft` to list an NFT for auction sale on the marketplace (id = 1).
 *
 * Assumes caller has NFT of collection id 1124 and XRP to pay gas.
 */
withChainApi("porcini", async (api, caller, logger) => {
	const collectionId = 1124;
	const marketplaceId = 1;
	const paymentAsset = XRP_ASSET_ID;
	const reservePrice = 1_000_000; // 1 XRP
	const duration = 100; // the listing will expire in 100 blocks

	const ownedTokens = (await api.rpc.nft.ownedTokens(
		collectionId,
		caller.address,
		0,
		1
	)) as unknown as OwnedTokens;
	const serialNumbers = ownedTokens[2];
	assert(serialNumbers.length);

	logger.info(
		{
			parameters: {
				collectionId,
				serialNumbers,
				paymentAsset,
				reservePrice,
				duration,
				marketplaceId,
			},
		},
		`create a "marketplace.sellNft" extrinsic`
	);

	const extrinsic = api.tx.marketplace.auctionNft(
		collectionId,
		serialNumbers,
		paymentAsset,
		reservePrice,
		duration,
		marketplaceId
	);

	const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
	const [openEvent] = filterExtrinsicEvents(result.events, ["Marketplace.AuctionOpen"]);

	logger.info(
		{
			result: {
				extrinsicId,
				blockNumber: result.blockNumber,
				openEvent: formatEventData(openEvent.event),
			},
		},
		"receive result"
	);
});

src/bid.ts ​

ts
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";
import assert from "node:assert";

/**
 * Use `marketplace.bid` extrinsic to submit a bid on a listing.
 *
 * Assume caller has balance of required token to buy and XRP to pay for gas.
 */
withChainApi("porcini", async (api, caller, logger) => {
	const collectionId = 1124;
	// pick up the first available listing
	const collectionListing = (
		await api.query.marketplace.openCollectionListings.keys(collectionId)
	).shift();

	assert(collectionListing);
	const {
		args: [, listingId],
	} = collectionListing;

	const amount = 1_000_000; // 1 XRP

	logger.info(
		{
			parameters: {
				listingId: listingId.toString(),
				amount,
			},
		},
		`create a "nft.bid" extrinsic`
	);
	const extrinsic = api.tx.marketplace.bid(listingId, amount);

	logger.info(`dispatch extrinsic from caller="${caller.address}"`);
	const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
	const [bidEvent] = filterExtrinsicEvents(result.events, ["Marketplace.Bid"]);

	logger.info(
		{
			result: {
				extrinsicId,
				blockNumber: result.blockNumber,
				bidEvent: formatEventData(bidEvent.event),
			},
		},
		"receive result"
	);
});

src/buy.ts ​

ts
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";
import assert from "node:assert";

/**
 * Use `marketplace.buy` extrinsic to buy NFT from a listing.
 *
 * Assume caller has balance of required token to buy and XRP to pay for gas.
 */
withChainApi("porcini", async (api, caller, logger) => {
	const collectionId = 1124;
	// pick up the first available listing
	const collectionListing = (
		await api.query.marketplace.openCollectionListings.keys(collectionId)
	).shift();

	assert(collectionListing);
	const {
		args: [, listingId],
	} = collectionListing;

	logger.info(
		{
			parameters: {
				listingId: listingId.toString(),
			},
		},
		`create a "nft.buy" extrinsic`
	);
	const extrinsic = api.tx.marketplace.buy(listingId);

	logger.info(`dispatch extrinsic from caller="${caller.address}"`);
	const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
	const [completeEvent] = filterExtrinsicEvents(result.events, [
		"Marketplace.FixedPriceSaleComplete",
	]);

	logger.info(
		{
			result: {
				extrinsicId,
				blockNumber: result.blockNumber,
				completeEvent: formatEventData(completeEvent.event),
			},
		},
		"receive result"
	);
});

src/registerMarketplace.ts ​

ts
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";

/**
 * Use `marketplace.registerMarketplace` to register a new marketplace
 *
 * Assumes caller has XRP to pay gas.
 */
withChainApi("porcini", async (api, caller, logger) => {
	const marketplaceAccount = caller.address;
	const entitlement = 10_000; // One percent

	logger.info(
		{
			parameters: {
				marketplaceAccount,
				entitlement,
			},
		},
		`create a "marketplace.registerMarketplace" extrinsic`
	);
	const extrinsic = api.tx.marketplace.registerMarketplace(marketplaceAccount, entitlement);

	logger.info(`dispatch extrinsic from caller="${caller.address}"`);
	const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
	const [registerEvent] = filterExtrinsicEvents(result.events, ["Marketplace.MarketplaceRegister"]);

	logger.info(
		{
			result: {
				extrinsicId,
				blockNumber: result.blockNumber,
				registerEvent: formatEventData(registerEvent.event),
			},
		},
		"receive result"
	);
});

src/sell.ts ​

ts
import { filterExtrinsicEvents } from "@trne/utils/filterExtrinsicEvents";
import { formatEventData } from "@trne/utils/formatEventData";
import { XRP_ASSET_ID } from "@trne/utils/porcini-assets";
import { sendExtrinsic } from "@trne/utils/sendExtrinsic";
import { withChainApi } from "@trne/utils/withChainApi";
import assert from "node:assert";

interface OwnedTokens {
	0: number;
	1: number;
	2: number[];
}

/**
 * Use `marketplace.sellNft` to list an NFT for fixed-price sale on the marketplace (id = 1).
 *
 * Assumes caller has NFT of collection id 1124 and XRP to pay gas.
 */
withChainApi("porcini", async (api, caller, logger) => {
	const collectionId = 1124;
	const marketplaceId = 1;
	const paymentAsset = XRP_ASSET_ID;
	const fixedPrice = 1_000_000; // 1 XRP
	const duration = 100; // the listing will expire in 100 blocks

	const ownedTokens = (await api.rpc.nft.ownedTokens(
		collectionId,
		caller.address,
		0,
		1
	)) as unknown as OwnedTokens;
	const serialNumbers = ownedTokens[2];
	assert(serialNumbers.length);

	logger.info(
		{
			parameters: {
				collectionId,
				serialNumbers,
				paymentAsset,
				fixedPrice,
				duration,
				marketplaceId,
			},
		},
		`create a "marketplace.sellNft" extrinsic`
	);
	const extrinsic = api.tx.marketplace.sellNft(
		collectionId,
		serialNumbers,
		null, // buyer
		paymentAsset,
		fixedPrice,
		duration,
		marketplaceId
	);

	logger.info(`dispatch extrinsic from caller="${caller.address}"`);
	const { result, extrinsicId } = await sendExtrinsic(extrinsic, caller, { log: logger });
	const [saleEvent] = filterExtrinsicEvents(result.events, ["Marketplace.FixedPriceSaleList"]);

	logger.info(
		{
			result: {
				extrinsicId,
				blockNumber: result.blockNumber,
				saleEvent: formatEventData(saleEvent.event),
			},
		},
		"receive result"
	);
});

package.json ​

json
{
  "scripts": {
    "call": "tsx --tsconfig ../../../tsconfig.json",
    "call:registerMarketplace": "pnpm call src/registerMarketplace.ts",
    "call:sell": "pnpm call src/sell.ts",
    "call:buy": "pnpm call src/buy.ts",
    "call:auction": "pnpm call src/auction.ts",
    "call:bid": "pnpm call src/bid.ts"
  }
}
Source: futureversecom/trn-examples, examples/substrate/use-marketplace (deleted) · commit 44c9e16, 2024-10-31 · Apache-2.0, license · part of Code examples

Curated independently. Source-attributed reference for The Root Network. Not affiliated with Futureverse / TRN Labs.