Search…
⌃K
Links

Collateral-Free Integration Guide

reNFT collateral-free contract flows
The following discussion applies to v5.0.0 of the SDK.

Lend/Rent NFTs In-App

To interact with our smart contract, we'd recommend using our SDK.
The ReNFT object takes in an ethers Signer and an optional contract address if not using the default collateral-free contract.
import { Sylvester } from "@renft/sdk";
const renft = new Sylvester(signer);
We name our contracts after famous cats. You can find the name mappings here. Sylvester is the code-name for the collateral free contract.

Batching

Any of the following functions support batching as shown below for the Lend instruction where the user lends an AstroCat and a CatPlsr in the same function call:
import { NFTStandard, PaymentToken, packPrice } from "@renft/sdk";
const astroCatLendingArgs = [
NFTStandard.E1155,
"0x0db8c099b426677f575d512874d45a767e9acc3c",
"1",
1,
1,
packPrice("1"),
PaymentToken.WETH,
];
const catPlsrLendingArgs = [
NFTStandard.E1155,
"0x0db8c099b426677f575d512874d45a767e9acc3c",
"2",
1,
1,
packPrice("0.5"),
PaymentToken.WETH,
];
const lendingArgs = astroCatLendingArgs.map((value, index) => {
return [value, catPlsrLendingArgs[index]];
});
await renft.lend(...lendingArgs);

Lend

import { NFTStandard, PaymentToken, packPrice } from "@renft/sdk";
const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendAmount = 1; // qty of the NFT to lend
const maxRentDuration = 1; // in days
const dailyRentPrice = packPrice("1");
const paymentToken = PaymentToken.WETH;
await renft.lend(
[nftStandard],
[nftAddress],
[tokenID],
[lendAmount],
[maxRentDuration],
[dailyRentPrice],
[paymentToken]
);

Rent

import { NFTStandard } from "@renft/sdk";
const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1"; // this information is pulled from the subgraph
const rentDuration = 1; // in days
const rentAmount = 1;
await renft.rent(
[nftStandard],
[nftAddress],
[tokenID],
[lendingID],
[rentDuration],
[rentAmount]
);

Stop Rent

Even though no real posession of the NFT is given, the renter must signal that they have concluded "using" the NFT with this call. If the renter fails to do so, then the lender can invoke "Claim Rent" explained below, to redeem the full amount of rent. Note that "Stop Lend" will be blocked until the user calls "Claim Rent" first.
import { NFTStandard } from "@renft/sdk";
const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1"; // from subgraph
const rentingID = "1"; // from subgraph
await renft.stopRent(
[nftStandard],
[nftAddress],
[tokenID],
[lendingID],
[rentingID],
);

Claim Rent

import { NFTStandard } from "@renft/sdk";
const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1";
const rentingID = "1";
await renft.claimRent(
[nftStandard],
[nftAddress],
[tokenID],
[lendingID],
[rentingID],
);

Stop Lend

import { NFTStandard } from "@renft/sdk";
const nftStandard = NFTStandard.E1155;
const nftAddress = "0x0db8c099b426677f575d512874d45a767e9acc3c";
const tokenID = "1";
const lendingID = "1";
await renft.stopLend(
[nftStandard],
[nftAddress],
[tokenID],
[lendingID],
);

Query Loan/Rental Status

Our current indexing solution is provided by The Graph. Feel free to experiment with our subgraph (renft-registy) in the Playground tab.
To query our subgraph, send an HTTP POST request to https://api.studio.thegraph.com/query/3020/renft-registry/1.0.1 whose body is a GraphQL query.
Here are some example queries:
Get 5 lendings after skipping 5 where the NFT's address is: 0x0db8c099b426677f575d512874d45a767e9acc3c sorted by dailyRentPrice in descending order (if you are ever having issues with subgraph when you are using nft addresses, lower case the address).
{
lendings(where: {nftAddress: "0x0db8c099b426677f575d512874d45a767e9acc3c"}, orderDirection: desc, orderBy: dailyRentPrice, first: 5, skip: 5) {
id,
lenderAddress,
maxRentDuration,
dailyRentPrice,
paymentToken,
lendAmount,
nftAddress,
tokenID,
is721,
lentAt
}
}
Get lending by id.
{
lending(id: "1") {
id,
lenderAddress,
maxRentDuration,
dailyRentPrice,
paymentToken,
lendAmount,
nftAddress,
tokenID,
is721,
lentAt
}
}
Get rentings for renter 0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41 ordered by rentDuration in ascending order
{
rentings(where: {renterAddress: "0x4976fb03C32e5B8cfe2b6cCB31c09Ba78EBaBa41", expired: false}, orderDirection: asc, orderBy: rentDuration) {
id,
renterAddress,
rentDuration,
rentedAt,
rentAmount,
lending {
id,
tokenID,
nftAddress,
dailyRentPrice,
paymentToken,
lenderAddress
},
}
}

Unpacking Data

Prices are returned in a custom format (rationale for this format was to fit the lending into a single storage slot). To unpack them, use our SDK's unpackPrice function:
import { PaymentToken, unpackPrice } from "@renft/sdk";
const parsePaymentToken = (tkn: string): PaymentToken => {
switch (tkn) {
case "0":
return PaymentToken.SENTINEL;
case "1":
return PaymentToken.WETH;
case "2":
return PaymentToken.DAI;
case "3":
return PaymentToken.USDC;
case "4":
return PaymentToken.USDT;
case "5":
return PaymentToken.TUSD;
default:
return PaymentToken.DAI;
}
};
const lendingsDataToLendings = (
theGraphLendings: TheGraphLending[]
) => {
const theGraphToLending = (theGraphLending: TheGraphLending) => {
return {
lendingID: theGraphLending.id,
lenderAddress: theGraphLending.lenderAddress,
dailyRentPrice: unpackPrice(theGraphLending.dailyRentPrice),
maxRentDuration: Number(theGraphLending.maxRentDuration),
lendAmount: Number(theGraphLending.lendAmount),
paymentToken: parsePaymentToken(theGraphLending.paymentToken),
lentAt: Number(theGraphLending.lentAt),
};
};
return theGraphLendings.map(theGraphToLending);
};