Skip to main content

Selling parts of a fraction

This strategy enables users to buy a self-specified number of units of the fraction being put up for sale. See the implementation here

Creating the sale

const { maker, isCollectionApproved, isTransferManagerApproved } =
await hypercertExchangeClient.createFractionalSaleMakerAsk({
startTime: Math.floor(Date.now() / 1000), // Use it to create an order that will be valid in the future (Optional, Default to now)
endTime: Math.floor(Date.now() / 1000) + 86400, // If you use a timestamp in ms, the function will revert
price: parseEther("1"), // Be careful to use a price in wei, this example is for 1 ETH
itemIds: [tokenId.toString()], // Token id of the NFT(s) you want to sell, add several ids to create a bundle
minUnitAmount: 10, // Minimum amount of units to sell per sale
maxUnitAmount: 100, // Maximum amount of units to sell per sale
minUnitsToKeep: 50, // Minimum amount of units to keep after the sale
sellLeftoverFraction: true, // If you want to sell the leftover fraction
});

The minUnitAmount and maxUnitAmount parameters are used to define the range of units that can be sold in a single transaction. The minUnitsToKeep parameter is used to define the minimum amount of units that the seller wants to keep after all sales. The sellLeftoverFraction parameter is used to define if the remainder fraction should be up for sale, meaning that a user can buy less units then the minUnitAmount, but only if those are the last remaining units that are up for sale.

Completing the sale

// Create taker bid
const takerOrder = hypercertExchangeClient.createFractionalSaleTakerBid(
order,
address,
unitAmount,
pricePerUnit
);

try {
// Set approval for exchange to spend funds
// Note that we set the approval for the total price to be paid for all units
const totalPrice = BigInt(order.price) * BigInt(unitAmount);
const approveTx = await hypercertExchangeClient.approveErc20(
order.currency,
totalPrice
);
await waitForTransactionReceipt(walletClientData, {
hash: approveTx.hash as `0x${string}`
});
} catch (e) {
// Handle error
console.error(e);
}

try {
// Perform the trade
const { call } = hypercertExchangeClient.executeOrder(
order,
takerOrder,
order.signature
);
const tx = await call();
await waitForTransactionReceipt(walletClientData, {
hash: tx.hash as `0x${string}`
});
} catch (e) {
// Handle error
console.error(e);
}

Note that the number of units to be bought has to be specified, and the price per unit has to be provided as well. It's possible for the buyer to pay a higher price per unit if desired, for example in the case of a donation.

Also note that the erc20 has to be approved for the total price of the units to be bought, e.g. totalPrice = BigInt(order.price) * BigInt(unitAmount).