This document maps the complete lifecycle of the collateralized asset-backed financing form the fraction protocol, to the available backend APIs and api-client methods.
- First, deploy the asset-backed financing market as an admin
- Then the admin can grant the issuer role to create a campaign
- Issuers create campaigns that collateralize and fractionalize a pre-deployed asset
- Admins validate the sale by changing their state and the investment occurs
- The financing is then monitored off-chain to ensure the collateral value does not drop below the financed value
- The campaign may enter resolution states, such as a margin call or default
- Finally, investors exit their position when the issuer purchases the fraction

Sale states within an asset-backed financing flow
Phase 1: Market Deployment
Before any campaigns can be created, the asset-backed financing market itself must be deployed. This is a one-time setup action per market.
API Client Call:
await apiClient.lending.deploy({
// Request body containing all market parameters
chainId: 1,
adminAddress: "0x...", // Address of the market admin
lending: {
minInterest: 0, // Minimum interest rate in basis points (0%)
maxInterest: 10000, // Maximum interest rate in basis points (100%)
minDuration: "2592000", // Minimum duration in seconds (30 days)
maxDuration: "31536000", // Maximum duration in seconds (365 days)
minimumProportionOverObligation: "1200000000000000000", // 120% (1.2 in 18 decimals)
},
discount: {
burnForDiscount: {
burnableTokenAddress: "0x...", // Address of the reputation token for discounts
},
},
});API Endpoint: POST /v0/buyback/deploy
After the transaction is mined, you can get the marketAddress by parsing the MarketDeployed event from the transaction receipt.
API Client Call:
const { marketAddress } = await apiClient.fractions.market.getMarketDeployedEvent({
chainId: 1,
hash: "0x...", // Transaction hash from deploy
});API Endpoint: GET /v0/fractions/markets/deployEvent
Phase 2: Grant roles
After the market is deployed, roles must be granted to key participants.
Grant Issuer Role
The issuer needs the FRACTIONS_ISSUER_ROLE to create campaigns.
API Client Call:
await apiClient.fractions.roles.grantRole({
chainId: "11155111", // supported chain id string from schema
marketAddress: marketAddress,
users: ["0x..."], // Issuer/borrower address(es)
role: "ISSUER",
});API Endpoint: POST /v0/fractions/roles/grant
Grant Liquidator Role
The liquidator needs appropriate permissions to execute liquidations.
API Client Call:
await apiClient.fractions.roles.grantRole({
chainId: "11155111",
marketAddress: marketAddress,
users: ["0x..."], // Liquidator address(es)
role: "LIQUIDATOR",
});API Endpoint: POST /v0/fractions/roles/grant
Grant Investor Role
Investor don't need a role to purchase a fraction in this template. Please reach out if you need an explicit investor role in addition to the compliance rules.
Phase 3: Campaign Initialization
1. Asset Preparation
The issuer (borrower) must approve the platform's wrapper contract to transfer the RWA NFT (or other collateral).
API Client Call:
// For ERC-721 NFTs
await apiClient.fractions.approvals.approveWrapperToSpendErc721({
wrapperAddress: "0x...", // Address of the wrapper contract
erc721Address: "0x...", // Address of the NFT contract
});API Endpoint: POST /v0/fractions/fractions/approveWrapperAsErc721Spender
2. Campaign Creation
The borrower creates the lending campaign, defining all its parameters.
API Client Call:
await apiClient.lending.createSale({
chainId: 1,
market: "0x...", // Lending market address from Phase 1 deployment
// Collateral assets to be wrapped and locked
wrapped: [
{
type: "ERC721",
address: "0x1234567890abcdef1234567890abcdef12345678", // RWA NFT contract
tokenIds: ["42"], // Specific NFT token ID(s) used as collateral
},
],
// Funding token configuration (what investors pay to fund the loan)
funding: [
{
token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48", // USDC contract address
amountPerPacket: "1000000", // 1 USDC (6 decimals) per funding packet
},
// Multiple funding tokens can be supported:
// {
// token: "0x6B175474E89094C44Da98b954EedeAC495271d0F", // DAI contract
// amountPerPacket: "1000000000000000000", // 1 DAI (18 decimals) per packet
// },
],
// Fraction token configuration (ERC1155 tokens representing loan positions)
fractions: {
name: "RWA Backed Loan Fractions",
symbol: "RWALOAN",
amount: "100000", // 100,000 fractions = $100k max loan at $1 per fraction
},
// Campaign time boundaries
timeBoundary: {
start: "2025-11-01T00:00:00Z", // Purchase window opens
end: "2025-12-01T00:00:00Z", // Purchase window closes (1 month)
},
// Capitalization limits
cap: {
soft: "50000", // Soft cap: 50,000 packets ($50k minimum to proceed)
hard: "100000", // Hard cap: 100,000 packets ($100k maximum)
softPerAccount: "100", // Min $100 per investor (optional)
hardPerAccount: "10000", // Max $10k per investor (optional)
},
// Buyback (loan repayment) configuration
buyback: {
durationSeconds: 15780000, // 6 months (182.5 days) for loan repayment
interestPercentage: 1000, // 10% annual interest (10% = 1000 basis points)
liquidationLimitPercentage: 12000, // 120% - liquidation triggers at this ratio
marginCallLimitPercentage: 14000, // 140% - margin call triggers at this ratio
},
// Refund address if campaign fails to reach soft cap
refundAddress: "0x...", // Address to receive collateral back if not funded
// Packets per fraction ratio (typically 1:1)
amountOfPacketsPerFraction: "1", // 1 funding packet = 1 fraction
// Optional: Discount configuration for burning reputation tokens
discounts: {
burnForDiscount: {
burnableToken: "0x...", // Reputation token address
burnAmounts: ["100000000000000000", "1000000000000000000"], // 0.1 and 1.0 tokens
discountPercentages: [5000, 10000], // 50% and 100% fee discounts
},
},
});API Endpoint: POST /v0/buyback/createSale
After the transaction is mined, you can get the campaignId by parsing the FractionsCreated event from the transaction receipt.
API Client Call:
const { campaignId } = await apiClient.fractions.sales.getFractionsCreatedEvent({
chainId: 1,
hash: "0x...", // Transaction hash from createSale
});API Endpoint: GET /v0/fractions/sales/getFractionsCreatedEvent
Phase 4: State Transitions, Validation and Investment
State 1: FRACTIONS_CREATED → APPROVED_FOR_FUNDING
FRACTIONS_CREATED → APPROVED_FOR_FUNDING1. Oracle Price Validation
The platform sets the initial collateral price.
API Client Call:
await apiClient.lending.setCollateralPrice({
market: "0x...",
campaignId: "1",
collateralPriceInFundingPackets: "200000000000", // $200k worth in funding packets
});API Endpoint: POST /v0/buyback/setCollateralPrice
2. Approve Campaign for Funding
The platform admin approves the campaign, moving it to the funding stage.
API Client Call:
await apiClient.fractions.sales.approveSale({
marketAddress: "0x...",
campaignId: "1",
});API Endpoint: POST /v0/fractions/sales/approve
State 2: APPROVED_FOR_FUNDING → FUNDED
APPROVED_FOR_FUNDING → FUNDED1. Investment Phase
Investors purchase fractions, effectively funding the loan.
API Client Call (for each investor):
await apiClient.lending.purchase({
chainId: 1,
market: "0x...",
campaignId: "1",
amountToBuy: "5000", // Investor wants to fund $5k worth of fractions
});API Endpoint: POST /v0/buyback/purchase
2. Complete Funding
After the purchase window ends, an automatic transition (or an admin action) moves the campaign to the FUNDED state.
API Client Call:
await apiClient.fractions.sales.completeSale({
marketAddress: "0x...",
campaignId: "1",
});API Endpoint: POST /v0/fractions/sales/complete
State 3: FUNDED → STARTED
FUNDED → STARTEDThe borrower receives the loan funds. This is handled by the ReceiveSkeletonFacet.receiveFunds function in the smart contract, which is not directly exposed via an API endpoint in the current implementation. This is typically an automatic step or triggered by the borrower directly on-chain.
Phase 5: Loan Monitoring & Risk Management
This phase is handled by off-chain services that monitor collateral prices via oracles and trigger alerts. There are no direct API calls for this continuous process, but the setCollateralPrice endpoint can be used to update prices.
Phase 6: Loan Resolution Scenarios
Scenario A: Normal Borrower Buyback
The borrower repays the loan plus interest.
API Client Call:
await apiClient.lending.buyback({
chainId: 1,
market: "0x...",
campaignId: "1",
buybackPacketsAmount: "110000", // Total obligation in packets (principal + interest)
});API Endpoint: POST /v0/buyback/buyback
Scenario B: Liquidator Intervention
A liquidator can also call the buyback endpoint if the loan is in a liquidatable state. The call is identical to the borrower's buyback.
Phase 7: Investor Exit & Fee Structure
Investors claim their principal and interest after a successful buyback.
API Client Call:
await apiClient.fractions.sales.receiveFundsAfterNonFunded({
market: "0x...",
campaignId: "1",
amountOfFractions: "5000", // Number of fractions the investor owns
isDiscounted: true, // or false, depending on reputation token usage
upperGenesisId: "...", // if isDiscounted is true
});API Endpoint: POST /v0/fractions/sales/receiveFundsAfterNonFunded
