Overview
This example demonstrates how to integrate IOTA Repstation into a DeFi lending platform to create a comprehensive credit scoring system. The platform uses reputation data to assess borrower creditworthiness, set interest rates, and determine loan limits.Architecture
Credit Score Components
The lending platform combines multiple reputation factors:- Global Reputation: Cross-platform trustworthiness
- Lending History: Previous loan performance within the platform
- Transaction Volume: Historical deal activity and amounts
- Category Performance: Specific performance in financial categories
- Recency Weight: More recent ratings have higher impact
Platform Integration
1. Setup Credit Scoring Engine
Copy
// credit-engine.ts
import { RepstationClient } from '@repstation/sdk';
interface CreditProfile {
walletAddress: string;
creditScore: number; // 300-850 (traditional credit range)
riskTier: 'AAA' | 'AA' | 'A' | 'BBB' | 'BB' | 'B' | 'C';
maxLoanAmount: number;
interestRateAdjustment: number; // Basis points adjustment
reputation: {
global: { average: number; count: number };
lending: { average: number; count: number };
};
}
class CreditScoringEngine {
private reputation: RepstationClient;
constructor() {
this.reputation = new RepstationClient({
network: 'mainnet',
packageId: process.env.REPSTATION_PACKAGE_ID!
});
}
async calculateCreditScore(walletAddress: string): Promise<CreditProfile> {
// Get reputation profile
const reputationResult = await this.reputation.getReputationProfile({
walletAddress
});
if (!reputationResult.success || !reputationResult.profile) {
return this.getDefaultProfile(walletAddress);
}
const profile = reputationResult.profile;
// Extract lending-specific reputation
const lendingReputation = profile.appScoped.find(
app => app.appOwner === process.env.LENDING_APP_OWNER
);
// Calculate credit score (300-850 range)
const creditScore = this.calculateScore(profile, lendingReputation);
// Determine risk tier
const riskTier = this.getRiskTier(creditScore);
// Calculate loan limits and rates
const maxLoanAmount = this.calculateMaxLoan(creditScore, profile);
const interestRateAdjustment = this.calculateRateAdjustment(riskTier);
return {
walletAddress,
creditScore,
riskTier,
maxLoanAmount,
interestRateAdjustment,
reputation: {
global: profile.global,
lending: lendingReputation?.stats || { average: 0, count: 0 }
}
};
}
private calculateScore(
profile: any,
lendingReputation?: any
): number {
const baseScore = 500; // Starting point
// Global reputation factor (0-150 points)
const globalFactor = Math.min(
(profile.global.average / 100) * 150,
150
);
// Lending history factor (0-100 points)
const lendingFactor = lendingReputation
? Math.min((lendingReputation.stats.average / 100) * 100, 100)
: 0;
// Activity factor based on rating count (0-100 points)
const activityFactor = Math.min(
Math.log(profile.global.count + 1) * 20,
100
);
// Consistency bonus for lending reputation (0-50 points)
const consistencyBonus = lendingReputation && lendingReputation.stats.count >= 5
? Math.min(lendingReputation.stats.average >= 80 ? 50 : 25, 50)
: 0;
const totalScore = Math.round(
baseScore + globalFactor + lendingFactor + activityFactor + consistencyBonus
);
return Math.min(Math.max(totalScore, 300), 850); // Clamp to valid range
}
private getRiskTier(creditScore: number): CreditProfile['riskTier'] {
if (creditScore >= 800) return 'AAA';
if (creditScore >= 750) return 'AA';
if (creditScore >= 700) return 'A';
if (creditScore >= 650) return 'BBB';
if (creditScore >= 600) return 'BB';
if (creditScore >= 550) return 'B';
return 'C';
}
private calculateMaxLoan(creditScore: number, profile: any): number {
const baseLoan = 1000; // $1000 base loan
const scoreMultiplier = (creditScore - 300) / 550; // 0-1 range
const activityMultiplier = Math.min(Math.log(profile.global.count + 1) / 5, 3);
return Math.round(baseLoan * (1 + scoreMultiplier * 10) * activityMultiplier);
}
private calculateRateAdjustment(riskTier: CreditProfile['riskTier']): number {
// Basis points adjustment to base interest rate
const adjustments = {
'AAA': -200, // 2% discount
'AA': -100, // 1% discount
'A': -50, // 0.5% discount
'BBB': 0, // No adjustment
'BB': 100, // 1% premium
'B': 250, // 2.5% premium
'C': 500 // 5% premium
};
return adjustments[riskTier];
}
private getDefaultProfile(walletAddress: string): CreditProfile {
return {
walletAddress,
creditScore: 500, // Neutral score for new users
riskTier: 'BBB',
maxLoanAmount: 1000,
interestRateAdjustment: 200, // 2% premium for unknown users
reputation: {
global: { average: 0, count: 0 },
lending: { average: 0, count: 0 }
}
};
}
}
2. Loan Application Process
Copy
// loan-service.ts
import { CreditScoringEngine } from './credit-engine';
interface LoanApplication {
borrower: string;
amount: number;
duration: number; // days
purpose: string;
collateralAddress?: string;
}
interface LoanOffer {
maxAmount: number;
interestRate: number;
duration: number;
creditProfile: CreditProfile;
terms: string[];
}
class LoanService {
private creditEngine: CreditScoringEngine;
private reputation: RepstationClient;
constructor() {
this.creditEngine = new CreditScoringEngine();
this.reputation = new RepstationClient({
network: 'mainnet',
packageId: process.env.REPSTATION_PACKAGE_ID!
});
}
async assessLoanApplication(application: LoanApplication): Promise<LoanOffer> {
// Get credit profile
const creditProfile = await this.creditEngine.calculateCreditScore(
application.borrower
);
// Calculate interest rate
const baseRate = 0.08; // 8% base APR
const adjustedRate = baseRate + (creditProfile.interestRateAdjustment / 10000);
// Determine max loan amount
const maxAmount = Math.min(
application.amount,
creditProfile.maxLoanAmount
);
// Generate loan terms
const terms = this.generateLoanTerms(creditProfile, application);
return {
maxAmount,
interestRate: adjustedRate,
duration: application.duration,
creditProfile,
terms
};
}
async approveLoan(
application: LoanApplication,
offer: LoanOffer
): Promise<string> {
// Create reputation deal for the loan
const dealResult = await this.reputation.openDealAdmin({
signer: process.env.LENDING_ADMIN_WALLET!,
admin_cap_id: process.env.LENDING_ADMIN_CAP!,
party_b: application.borrower,
subject_ref: {
type: 'LOAN',
id: `loan-${Date.now()}`
},
amount: offer.maxAmount.toString()
});
if (!dealResult.success) {
throw new Error('Failed to create reputation deal');
}
// Store loan in database
const loan = await this.createLoanRecord({
...application,
amount: offer.maxAmount,
interestRate: offer.interestRate,
reputationDealId: dealResult.deal_id!,
creditScore: offer.creditProfile.creditScore,
riskTier: offer.creditProfile.riskTier
});
return loan.id;
}
private generateLoanTerms(
creditProfile: CreditProfile,
application: LoanApplication
): string[] {
const terms = [
`Credit Score: ${creditProfile.creditScore} (${creditProfile.riskTier})`,
`Maximum loan amount: $${creditProfile.maxLoanAmount.toLocaleString()}`,
`Interest rate adjustment: ${creditProfile.interestRateAdjustment >= 0 ? '+' : ''}${creditProfile.interestRateAdjustment} basis points`
];
// Add reputation-based terms
if (creditProfile.reputation.global.count === 0) {
terms.push('New user: Additional verification required');
terms.push('Collateral requirement: 120% of loan value');
} else if (creditProfile.creditScore >= 750) {
terms.push('High credit score: Reduced collateral requirement (110%)');
terms.push('Fast approval: Decision within 24 hours');
} else if (creditProfile.creditScore < 600) {
terms.push('Enhanced monitoring: Weekly check-ins required');
terms.push('Higher collateral requirement: 150% of loan value');
}
return terms;
}
}
3. Loan Lifecycle Management
Copy
// loan-lifecycle.ts
class LoanLifecycleManager {
private reputation: RepstationClient;
constructor() {
this.reputation = new RepstationClient({
network: 'mainnet',
packageId: process.env.REPSTATION_PACKAGE_ID!
});
}
async activateLoan(loanId: string, borrowerSignature: string): Promise<void> {
const loan = await this.getLoan(loanId);
// Accept the reputation deal
await this.reputation.acceptDeal({
signer: loan.borrower,
deal_id: loan.reputationDealId
});
// Update loan status
await this.updateLoanStatus(loanId, 'ACTIVE');
// Disburse funds
await this.disburseFunds(loan);
}
async completeLoanRepayment(loanId: string): Promise<void> {
const loan = await this.getLoan(loanId);
// Close the reputation deal
await this.reputation.closeDeal({
signer: process.env.LENDING_ADMIN_WALLET!,
deal_id: loan.reputationDealId
});
// Update loan status
await this.updateLoanStatus(loanId, 'COMPLETED');
// Automatically rate successful repayment
await this.rateSuccessfulRepayment(loan);
}
async handleLoanDefault(loanId: string): Promise<void> {
const loan = await this.getLoan(loanId);
// Close the reputation deal
await this.reputation.closeDeal({
signer: process.env.LENDING_ADMIN_WALLET!,
deal_id: loan.reputationDealId
});
// Update loan status
await this.updateLoanStatus(loanId, 'DEFAULTED');
// Rate the default negatively
await this.rateDefault(loan);
}
private async rateSuccessfulRepayment(loan: any): Promise<void> {
const paymentScore = this.calculatePaymentScore(loan);
// Rate multiple aspects of the loan performance
const categories = [
{ name: 'repayment_reliability', score: paymentScore },
{ name: 'communication', score: loan.communicationScore || 85 },
{ name: 'loan_compliance', score: loan.complianceScore || 90 }
];
for (const category of categories) {
await this.reputation.rate({
signer: process.env.LENDING_ADMIN_WALLET!,
deal_id: loan.reputationDealId,
score: category.score,
category: category.name
});
}
}
private async rateDefault(loan: any): Promise<void> {
// Rate default with low scores
await this.reputation.rate({
signer: process.env.LENDING_ADMIN_WALLET!,
deal_id: loan.reputationDealId,
score: 20, // Very low score for default
category: 'repayment_reliability'
});
await this.reputation.rate({
signer: process.env.LENDING_ADMIN_WALLET!,
deal_id: loan.reputationDealId,
score: 30,
category: 'loan_compliance'
});
}
private calculatePaymentScore(loan: any): number {
const daysLate = loan.totalDaysLate || 0;
const baseScore = 95;
// Deduct points for late payments
const latePaymentPenalty = Math.min(daysLate * 2, 40);
// Bonus for early repayment
const earlyRepaymentBonus = loan.earlyRepayment ? 5 : 0;
return Math.max(baseScore - latePaymentPenalty + earlyRepaymentBonus, 20);
}
}
4. Credit Dashboard Component
Copy
// components/CreditDashboard.tsx
import React, { useState, useEffect } from 'react';
import { CreditScoringEngine } from '../services/credit-engine';
interface CreditDashboardProps {
walletAddress: string;
}
export function CreditDashboard({ walletAddress }: CreditDashboardProps) {
const [creditProfile, setCreditProfile] = useState<CreditProfile | null>(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
loadCreditProfile();
}, [walletAddress]);
const loadCreditProfile = async () => {
try {
const creditEngine = new CreditScoringEngine();
const profile = await creditEngine.calculateCreditScore(walletAddress);
setCreditProfile(profile);
} catch (error) {
console.error('Failed to load credit profile:', error);
} finally {
setLoading(false);
}
};
if (loading) {
return <div className="loading">Loading credit profile...</div>;
}
if (!creditProfile) {
return <div className="error">Failed to load credit profile</div>;
}
return (
<div className="credit-dashboard">
<div className="credit-score-display">
<div className="score-circle">
<span className="score">{creditProfile.creditScore}</span>
<span className="label">Credit Score</span>
</div>
<div className="risk-tier">
<span className={`tier ${creditProfile.riskTier.toLowerCase()}`}>
{creditProfile.riskTier}
</span>
</div>
</div>
<div className="credit-details">
<div className="detail-card">
<h3>Loan Capacity</h3>
<p className="amount">${creditProfile.maxLoanAmount.toLocaleString()}</p>
<p className="description">Maximum loan amount available</p>
</div>
<div className="detail-card">
<h3>Interest Rate</h3>
<p className="rate">
{creditProfile.interestRateAdjustment >= 0 ? '+' : ''}
{(creditProfile.interestRateAdjustment / 100).toFixed(2)}%
</p>
<p className="description">Adjustment to base rate</p>
</div>
<div className="detail-card">
<h3>Global Reputation</h3>
<p className="score">{creditProfile.reputation.global.average}/100</p>
<p className="count">({creditProfile.reputation.global.count} ratings)</p>
</div>
<div className="detail-card">
<h3>Lending History</h3>
<p className="score">{creditProfile.reputation.lending.average}/100</p>
<p className="count">({creditProfile.reputation.lending.count} loans)</p>
</div>
</div>
<div className="improvement-tips">
<h3>Improve Your Credit Score</h3>
<CreditImprovementTips creditProfile={creditProfile} />
</div>
</div>
);
}
function CreditImprovementTips({ creditProfile }: { creditProfile: CreditProfile }) {
const tips = [];
if (creditProfile.reputation.global.count < 5) {
tips.push({
title: "Build Transaction History",
description: "Complete more deals on integrated platforms to build your reputation",
impact: "+20-40 points"
});
}
if (creditProfile.reputation.lending.count === 0) {
tips.push({
title: "Start with Small Loans",
description: "Successfully complete smaller loans to build lending-specific reputation",
impact: "+30-50 points"
});
}
if (creditProfile.reputation.global.average < 80) {
tips.push({
title: "Improve Service Quality",
description: "Focus on excellent communication and timely delivery in your transactions",
impact: "+10-30 points"
});
}
return (
<div className="tips-list">
{tips.map((tip, index) => (
<div key={index} className="tip-card">
<h4>{tip.title}</h4>
<p>{tip.description}</p>
<span className="impact">Potential impact: {tip.impact}</span>
</div>
))}
</div>
);
}
5. Loan Application Form
Copy
// components/LoanApplicationForm.tsx
import React, { useState } from 'react';
import { LoanService } from '../services/loan-service';
import { CreditDashboard } from './CreditDashboard';
export function LoanApplicationForm({ walletAddress }: { walletAddress: string }) {
const [application, setApplication] = useState({
amount: '',
duration: '30',
purpose: '',
collateralAddress: ''
});
const [offer, setOffer] = useState<LoanOffer | null>(null);
const [loading, setLoading] = useState(false);
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
try {
const loanService = new LoanService();
const loanOffer = await loanService.assessLoanApplication({
borrower: walletAddress,
amount: parseInt(application.amount),
duration: parseInt(application.duration),
purpose: application.purpose,
collateralAddress: application.collateralAddress || undefined
});
setOffer(loanOffer);
} catch (error) {
console.error('Failed to assess loan application:', error);
} finally {
setLoading(false);
}
};
const handleAcceptOffer = async () => {
if (!offer) return;
try {
const loanService = new LoanService();
const loanId = await loanService.approveLoan(
{
borrower: walletAddress,
amount: parseInt(application.amount),
duration: parseInt(application.duration),
purpose: application.purpose
},
offer
);
alert(`Loan approved! Loan ID: ${loanId}`);
} catch (error) {
console.error('Failed to approve loan:', error);
}
};
return (
<div className="loan-application">
<CreditDashboard walletAddress={walletAddress} />
<form onSubmit={handleSubmit} className="application-form">
<h2>Apply for a Loan</h2>
<div className="form-group">
<label>Loan Amount ($)</label>
<input
type="number"
value={application.amount}
onChange={(e) => setApplication({...application, amount: e.target.value})}
placeholder="Enter amount"
required
/>
</div>
<div className="form-group">
<label>Duration (days)</label>
<select
value={application.duration}
onChange={(e) => setApplication({...application, duration: e.target.value})}
>
<option value="30">30 days</option>
<option value="60">60 days</option>
<option value="90">90 days</option>
<option value="180">180 days</option>
</select>
</div>
<div className="form-group">
<label>Purpose</label>
<textarea
value={application.purpose}
onChange={(e) => setApplication({...application, purpose: e.target.value})}
placeholder="Describe the purpose of this loan"
rows={3}
required
/>
</div>
<div className="form-group">
<label>Collateral Address (Optional)</label>
<input
type="text"
value={application.collateralAddress}
onChange={(e) => setApplication({...application, collateralAddress: e.target.value})}
placeholder="0x..."
/>
</div>
<button type="submit" disabled={loading}>
{loading ? 'Assessing...' : 'Get Loan Offer'}
</button>
</form>
{offer && (
<div className="loan-offer">
<h3>Loan Offer</h3>
<div className="offer-details">
<div className="detail">
<label>Approved Amount:</label>
<span>${offer.maxAmount.toLocaleString()}</span>
</div>
<div className="detail">
<label>Interest Rate:</label>
<span>{(offer.interestRate * 100).toFixed(2)}% APR</span>
</div>
<div className="detail">
<label>Credit Score:</label>
<span>{offer.creditProfile.creditScore} ({offer.creditProfile.riskTier})</span>
</div>
</div>
<div className="loan-terms">
<h4>Terms & Conditions</h4>
<ul>
{offer.terms.map((term, index) => (
<li key={index}>{term}</li>
))}
</ul>
</div>
<div className="offer-actions">
<button onClick={handleAcceptOffer} className="accept-btn">
Accept Offer
</button>
<button onClick={() => setOffer(null)} className="decline-btn">
Decline
</button>
</div>
</div>
)}
</div>
);
}
Key Benefits
For Lenders
- Risk Assessment: Comprehensive credit scoring using blockchain reputation
- Automated Underwriting: Reputation-based loan approval process
- Default Prediction: Historical performance indicators
- Cross-Platform Insights: Global user behavior analysis
For Borrowers
- Portable Credit History: Reputation follows across platforms
- Transparent Scoring: Clear understanding of credit factors
- Improved Access: Good reputation enables better loan terms
- Incentive Alignment: Motivation to maintain positive reputation
For the Ecosystem
- Reduced Information Asymmetry: Shared reputation data
- Lower Default Rates: Better risk assessment
- Financial Inclusion: Credit access for underbanked users
- Standardized Scoring: Consistent metrics across platforms
Implementation Considerations
Risk Management
- Implement minimum reputation thresholds
- Use collateral requirements based on credit scores
- Monitor borrower behavior during loan terms
- Implement early warning systems for potential defaults
Regulatory Compliance
- Ensure compliance with local lending regulations
- Implement proper KYC/AML procedures
- Maintain audit trails for all transactions
- Consider data privacy requirements
Security
- Secure wallet integration for signatures
- Multi-signature approval for large loans
- Smart contract audits for loan terms
- Proper key management for admin operations