Integration steps described here are meant to be followed after getting everything done in the quickstart.
Please check Stash SDK Quickstart before reading this article.

Accessing the Contracts

All Stash contracts included in Stash Renting Protocol are loaded during the initialization of the SDK. Assuming that you have created a Stash object by initializing the SDK, it's possible to access to the contracts through contractsattribute:

import { Stash } from "@stash-renting-sdk/core";
const stash = new Stash(<apiKey>, <signer>, <chain>, <nftContracts>);
const contracts = stash.contracts;

This attribute has a mapping structure with type CoreContracts whose declaration can be seen under src/types.ts:

type CoreContracts = {
    market: Market;
    wrapperFactory: WrapperFactory;

Using Market Contract

In order to perform main operations on NFTs such as lending or renting, you need to use the market contract to make the respective calls.

You can access the market contract as follows:

const contracts = stash.contracts;
const market = contracts.market;

After that, it's possible to call any market contract function easily. The example below illustrates how to make a lendcall to the market contract:

const txn = await market.lend(tokenId, nftStandard, expiry, pricePerDay, ETHEREUM_USDT.address, 0, buyPrice, maxRentalDays);

Using Wrapper Factory Contract

In case the NFT to be lent is not rent-compliant, it needs to be wrapped and a new wNFT needs to be minted to make the lending possible. For such cases, you need to use the wrapper factory contract.

You can access the wrapper factory contract as follows:

const contracts = stash.contracts;
const wrapperFactory = contracts.wrapperFactory;

The code sample shows how to make a wrap call with a given NFT:

const txn = await wrapperFactory.wrap(tokenId, nftStandard);

Response Structure

Each basic operation (e.g. lending and renting) made in Stash Renting SDK has two callback parameters which allow developers to retrieve the successful response or to catch the error output. Through that, it gets much more easier to track down various failure cases and to adapt the UI state or the UX flow based on the outcomes of the operations.

The response object for successful operations are encapsulated in StashResponse class, which has the following declaration:

class StashResponse {
    transactions: StashTransaction[];
    args: {};

    constructor(_transactions: StashTransaction[] = [], _args: {} = {}) {
        this.transactions = _transactions;
        this.args = _args;

StashTransaction offers a way to store each transaction hash alongside with the respective receiver (e.g. in payout operations):

class StashTransaction {
    txn_hash: String = "";
    receiver: String | null;

    constructor(_txn_hash: String, _receiver: String | null = null) {
        this.txn_hash = _txn_hash;
        this.receiver = _receiver;

The response of failed operations are encapsulated in StashError class with the declaration:

export class StashError {
    transactions: StashTransaction[];
    message: string;
    code: number;

    constructor(_message: string, _code: number, _transactions: StashTransaction[] = []) {
        this.message = _message;
        this.code = _code;
        this.transactions = _transactions;