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 commit44c9e16of 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
CALLER_PRIVATE_KEY- Private key of an account that submits the transaction. Follow this guide to create and fund an account with some test tokens on Porcini (testnet) if you don't have one yet.
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:bidSource 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