NFT Marketplace
The Lootex SDK provides a comprehensive set of functions for interacting with NFT marketplaces. These functions allow you to list NFTs for sale, make offers, buy NFTs, and manage orders.
Core Functions
List NFTs for Sale
The list
function allows you to create listing orders for your NFTs:
import { list, encodeBulkOrderSignature } from 'lootex/order';
const params = {
client: lootexClient,
chainId: 1, // Ethereum mainnet
accountAddress: '0x...', // Your wallet address
data: [
{
tokenAddress: '0x...', // NFT contract address
tokenId: '1', // Token ID
tokenType: 'ERC721', // or 'ERC1155'
quantity: '1',
pricePerToken: '1_000_000_000_000_000_000_000', // 1 ETH
currency: '0x...', // leave it empty for using native currency1
startTime: Math.floor(Date.now() / 1000),
endTime: Math.floor(Date.now() / 1000) + 30 * 24 * 60 * 60, // 30 days
}
],
enableBulkOrder: false // Set to true for multiple listings in one transaction
};
const { steps } = await list(params);
// Execute the steps
for (const step of steps) {
if (step.id === 'approve-tokens') {
console.log('Approving tokens...');
for (const item of step.items) {
if (item.type === 'transaction') {
const hash = await walletClient.sendTransaction(item.data);
console.log(`Approval transaction sent: ${hash}`);
}
}
} else if (step.id === 'create-orders') {
console.log('Creating order...');
// Sign the orders
const signTypedDataItems = step.items.filter(
(item) => item.type === 'signTypedData'
);
const signatures = await Promise.all(
signTypedDataItems.map((item) =>
walletClient.signTypedData(item.data)
)
);
// Submit the orders
const postItem = step.items.find((item) => item.type === 'post');
if (postItem) {
const body = postItem.body.map((order, index) => ({
...order,
signature: step.needEncodeProofAndSignature
? encodeBulkOrderSignature(index, order.proof, signatures[index])
: signatures[index],
}))
const result = await apiClient.request({
method: 'POST',
path: postItem.endpoint,
body,
});
}
}
}
Buy NFTs
The buy
function allows you to purchase listed NFTs:
import { buy } from 'lootex/order';
const params = {
client: lootexClient,
chainId: 1,
accountAddress: '0x...', // Buyer's wallet address
orders: [order], // LootexOrder object(s)
};
const { steps } = await buy(params);
// Execute the steps
for (const step of steps) {
if (step.id === 'approve-tokens') {
console.log('Approving tokens...');
for (const item of step.items) {
if (item.type === 'transaction') {
const hash = await walletClient.sendTransaction({
...item.data,
value: item.data.value ? BigInt(item.data.value) : undefined,
});
console.log(`Approval transaction sent: ${hash}`);
}
}
} else if (step.id === 'approve-aggregator') {
console.log('Approving aggregator...');
for (const item of step.items) {
if (item.type === 'transaction') {
const hash = await walletClient.sendTransaction({
...item.data,
value: item.data.value ? BigInt(item.data.value) : undefined,
});
console.log(`Aggregator approval transaction sent: ${hash}`);
}
}
} else if (step.id === 'exchange') {
console.log('Executing exchange...');
for (const item of step.items) {
if (item.type === 'transaction') {
const hash = await walletClient.sendTransaction({
...item.data,
value: item.data.value ? BigInt(item.data.value) : undefined,
});
console.log(`Exchange transaction sent: ${hash}`);
}
}
}
}
Make Offers
The makeOffer
function allows you to make offers on NFTs:
import { makeOffer } from 'lootex/order';
const params = {
client: lootexClient,
chainId: 1,
accountAddress: '0x...', // Your wallet address
data: {
tokenAddress: '0x...', // NFT contract address
tokenId: '1', // Token ID (optional for collection offers)
tokenType: 'ERC721',
quantity: '1',
price: '1.0', // Offer price
currency: '0x...', // Currency contract address
startTime: Math.floor(Date.now() / 1000),
endTime: Math.floor(Date.now() / 1000) + 7 * 24 * 60 * 60, // 7 days
}
};
const { steps } = await makeOffer(params);
// Execute the steps (similar to list function)
// 1. Handle approve-tokens step if needed
// 2. Handle create-orders step for signing and submitting the offer
Accept Offers
The acceptOffer
function allows NFT owners to accept offers:
import { acceptOffer } from 'lootex/order';
const params = {
client: lootexClient,
chainId: 1,
accountAddress: '0x...', // NFT owner's wallet address
order: offerOrder, // LootexOrder object
};
const { steps } = await acceptOffer(params);
// Execute the steps (similar to buy function)
// 1. Handle approve-tokens step if needed
// 2. Handle approve-aggregator step if needed
// 3. Handle exchange step for completing the transaction
Understanding Steps
All marketplace functions return a steps
array that needs to be executed in sequence. Each step can contain different types of items:
Common Step Types
-
approve-tokens
- Handles token approvals for ERC20, ERC721, or ERC1155 tokens
- Contains transaction items that need to be sent to the blockchain
-
approve-aggregator
- Handles approvals for the Lootex aggregator contract
- Required for some operations involving multiple tokens or orders
-
create-orders
- Used when creating new listings or offers
- Contains items for signing orders (
signTypedData
) - Contains a post item for submitting the signed orders to Lootex API
-
exchange
- Handles the actual exchange of tokens
- Contains transaction items for executing the trade
Step Items
Each step can contain different types of items:
-
transaction
{ type: 'transaction'; data: { to: `0x${string}`; data: `0x${string}`; value?: string; }; }
-
signTypedData
{ type: 'signTypedData'; data: { domain: object; types: object; message: object; primaryType: string; }; }
-
post
{ type: 'post'; endpoint: string; body: object | object[]; }
Order Types
The SDK uses the LootexOrder
type to represent orders in the marketplace. Here’s the structure of a LootexOrder:
type LootexOrder = {
id: string;
hash: `0x${string}`;
chainId: number;
exchangeAddress: `0x${string}`;
category: 'listing' | 'offer';
offerer: `0x${string}`;
price: number;
perPrice: number;
priceSymbol: string;
startTime: number;
endTime: number;
// ... other properties
};
Helper Functions
The SDK provides several helper functions for working with orders:
getOrderAvailableQuantity(order)
: Get the available quantity for an ordergetOrderQuantity(order)
: Get the total quantity of an ordergetMaxAcceptOfferQuantity(order, availableAmount)
: Calculate the maximum quantity that can be accepted for an offer
Error Handling
All marketplace functions will throw errors if:
- Required parameters are missing
- The chain ID is not supported
- The user has insufficient balance
- The user has not approved the required tokens
- The order is invalid or expired
Make sure to implement proper error handling in your application:
try {
const result = await buy(params);
} catch (error) {
console.error('Failed to buy NFT:', error);
}
Best Practices
- Always check order validity before executing transactions
- Implement proper approval flows for tokens
- Handle both ERC721 and ERC1155 token types appropriately
- Set reasonable expiration times for listings and offers
- Implement proper error handling and user feedback
- Execute all steps in the correct order
- Verify transaction success after each step
- Keep track of transaction hashes for reference
Advanced Features
Bulk Operations
The SDK supports bulk operations for listings and purchases:
// Bulk listing
const bulkListResult = await list({
...params,
enableBulkOrder: true,
data: [/* multiple NFT listing data */]
});
// Bulk purchase
const bulkBuyResult = await buy({
...params,
orders: [/* multiple LootexOrder objects */]
});
Collection Offers
You can make offers on entire collections by omitting the tokenId
when creating an offer:
const collectionOfferResult = await makeOffer({
...params,
data: {
tokenAddress: '0x...', // Collection address
tokenType: 'ERC721',
// tokenId is omitted for collection offers
// ... other parameters
}
});