# Marketplace SDK instructions
## Intro
The marketplace supports a number of different strategies for selling hypercerts, one of which is the fractional sale. This strategy allows you to sell of a portion of your hypercert (for example: anywhere between 10 and a 100 units), for a minimum price per unit.
:::warning
:warning: functionality available from version `hypercerts-org/marketplace-sdk@0.0.19`
:::
## VoiceDeck
According to the [designs by VoiceDeck](https://www.figma.com/file/GyA5raT78DnEbungrDTC8Y/VoiceDeck?type=design&node-id=1491-77197&mode=design&t=zsrsvauxZVx3v8sk-4) we will provide some steps that could accomplish the desired functionality. Keep in mind that all prices have to be in WEI, which we won't do here for the sake of clarity.
1. Mint a hypercert
2. Register the hypercert for sale
- Example calculation: the hypercert consists of 2000 units
- The project needs $1000
- The price per unit will therefore be `const pricePerUnit = 1000 / 2000` ($0.50)
- The entire hypercert will be sold, so `const minUnitsToKeep = 0`
- You want people to donate at least $1 per donation. So `const minUnitAmount = 2`
- People should be able to fund the entire project at once, so `const maxUnitAmount = 2000`
3. Some example math for funding a project
- If a user wants to donate $5, he would have to buy 10 units, against the specified minimum price of $0.50 per unit.
4. Listing all donators for a project:
- Using the hypercerts SDK (not the marketplace SDK) you can retreive a list of all fractions. Every fraction represents a donation. The owners of these fractions are the people that have donated. The combined size of all fractions for a single owner tells you the amount of money that that user has donated.
## Putting up a hypercert for sale - example code
```typescript=
import { HypercertExchangeClient } from "@hypercerts-org/marketplace-sdk";
import { parseEther } from "viem
import { waitForTransactionReceipt } from "viem/actions";
const hypercertExchangeClient = new HypercertExchangeClient(
chainId,
provider,
signer
);
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
currency: '0xABC' // Optional, address of the currency used for the sale. Defaults to WETH for now (0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9).
});
// Grant the TransferManager the right the transfer assets on behalf od the LooksRareProtocol
if (!isTransferManagerApproved) {
const tx = await hypercertExchangeClient
.grantTransferManagerApproval()
.call();
await waitForTransactionReceipt(walletClientData, {
hash: tx.hash as `0x${string}`,
});
}
// Approve the collection items to be transferred by the TransferManager
if (!isCollectionApproved) {
const tx = await hypercertExchangeClient.approveAllCollectionItems(
maker.collection
);
await waitForTransactionReceipt(walletClientData, {
hash: tx.hash as `0x${string}`,
});
}
// Sign your maker order
const signature = await hypercertExchangeClient.signMakerOrder(maker);
await hypercertExchangeClient.registerOrder({
order,
signature,
});
```
## Fetching open MakerAsks from the marketplace API - example code
```typescript=
const { data: orders } =
await hypercertExchangeClient.api.fetchOrdersByHypercertId({
hypercertId,
chainId,
});
```
Which will give a response with the following properties
```json
[
{
"id":"9027a798-cb05-49ab-8ec9-0f45a1a9d6f1",
"createdAt":"2024-02-11T19:17:02.305689+00:00",
"quoteType":1,
"globalNonce":"0",
"orderNonce":"45",
// Means it's a fractional sale
"strategyId":10,
"collectionType":2,
"collection":"0xa16DFb32Eb140a6f3F2AC68f41dAd8c7e83C4941",
"currency":"0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9",
"signer":"0x59266D85D94666D037C1e32dAa8FaC9E95CdaFEf",
"startTime":1707679014,
"endTime":1707765414,
// Minimum price per unit
"price":"10000",
"signature":"0x4c96b0f09909e4d5059baea4d18b6a9d53cace96d700be1672e440db1ffac38c072fc1f18e8d59be91df76e0d55cb0e91e6bfc02bb9143cc16cdf62918299a981b",
"additionalParameters":"0x0000000000000000000000000000000000000000000000000000000000000014000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000000000140000000000000000000000000000000000000000000000000000000000000000",
"chainId":11155111,
"subsetNonce":0,
"itemIds":[
// This is the ID of the fraction being sold.
"34708801425935723273264209958040357568513"
],
"amounts":[
1
]
}
]
```
## Buying a part of a hypercert - example code
```typescript=
import { HypercertExchangeClient } from "@hypercerts-org/marketplace-sdk";
import { parseEther } from "viem";
import { waitForTransactionReceipt } from "viem/actions";
const buyFractionalSale = (
// Chain that the sale takes place on
chainId: number,
// Address of the buyer
address: string,
// Order retreived from API
order: Order,
// Price to pay per unit in WEI, should be >= the requested price
pricePerUnitToPay: BigNumberish,
// Number of units to buy, should be minUnits < unitAmount < maxUnits
unitAmount: BigNumberish
) => {
const hypercertExchangeClient = new HypercertExchangeClient(
chainId,
provider,
signer
);
// Create taker bid
const takerOrder = hypercertExchangeClient.createFractionalSaleTakerBid(
order,
address,
unitAmount,
pricePerUnit
);
try {
// Set approval for exchange to spend funds
const totalPrice = BigInt(order.price) * BigInt(unitAmount);
const approveTx = await hypercertExchangeClient.approveErc20(
order.currency, // Be sure to set the allowance for the correct currency
totalPrice
);
await waitForTransactionReceipt(walletClientData, {
hash: approveTx.hash as `0x${string}`,
});
} catch (e) {
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) {
console.error(e);
}
};
```