This tutorial provides a step-by-step guide to building a simple loan management system using Blnk Finance. You’ll learn how to:
Disburse loans to customers.
Calculate and apply interest.
Process repayments.
Monitor loan status effectively.
For this tutorial, we’ll use the Blnk TypeScript SDK for the implementation. If you prefer, you can also refer to the API reference for details on the available endpoints.
Before writing code, it’s crucial to design a money movement map that outlines how money moves in your system. This serves as the blueprint for your implementation.
This map shows three key aspects our lending fund flow:
The Customer Loan Wallet tracks the amount owed by the customer. All loans disbursed to the customer are debited from their loan wallet. A zero balance indicates that all debt has been fully repaid.
The @InterestRevenue records all interest earned from loan customers.
When the loan is disbursed, money is deducted from the Loan Balance to the Main Balance.
Example scenario
* Starting ScenarioAlice Loan Balance: 0.00 USDAlice Main Balance: 0.00 USD* Loan Request Scenario:Alice borrows 500.00 USD* After Loan Disbursement:Alice Loan Balance: - 500.00 USD (debt owed)Alice Main Balance: + 500.00 USD (funds received by customer)
Initiate this transaction in your ledger:
asyncfunctiondisburseLoan(loanBalanceId, customerBalanceId, loanAmount){const blnk =awaitgetBlnk();const{Transactions,LedgerBalances}= blnk;// Generate a unique reference for this transactionconst reference =`LOAN-DISBURSE-${Date.now()}`;const disbursement =awaitTransactions.create({amount: loanAmount,precision:100,reference: reference,currency:"USD",source: loanBalanceId,destination: customerBalanceId,description:"Loan disbursement",allow_overdraft:true,// This allows the loan balance to go negativemeta_data:{transaction_type:"loan_disbursement",}});console.log("Loan disbursed:", disbursement.data);// Create loan status in metadataawaitLedgerBalances.updateMetadata(loanBalanceId,{metadata:{loan_status:"active", pri}});return disbursement.data.transaction_id;}
Next, we need to calculate daily interest based on the formula P∗R∗T, where:
P is the principal (loan amount or remaining balance)
R is the daily interest rate
T is time (1 day for daily interest)
According to our map, interest is transferred from the Loan Balance to the @InterestRevenue.
Example scenario (cont'd)
* After 1 day, with 1% daily interest+5 USD added to @InterestRevenue-5 USD deducted from Loan Balance* Final BalancesAlice Loan Balance: - 505.00 USD (debt owed, including interest)Alice Main Balance: 500.00 USD (funds received by customer)@InterestRevenue: + 5.00 USD (interest earned)
asyncfunctioncalculateAndChargeInterest(loanBalanceId, interestRate){const blnk =awaitgetBlnk();const{Transactions,LedgerBalances}= blnk;// Get current loan balanceconst loanBalance =awaitLedgerBalances.retrieve(loanBalanceId);// Get the principal amount (convert negative balance to positive)const principal =Math.abs(loanBalance.data.balance);// Calculate daily interest amountconst dailyRate = interestRate /365;// Convert annual rate to dailyconst interestAmount = principal * dailyRate;// Round to 2 decimal places and convert to centsconst roundedInterest =Math.round(interestAmount *100)/100;// Generate a unique referenceconst reference =`INTEREST-${Date.now()}`;// Transfer interest from loan balance to interest revenue balanceconst interestTransaction =awaitTransactions.create({amount: roundedInterest,precision:100,reference: reference,currency:"USD",source: loanBalanceId,destination:"@InterestRevenue",description:"Daily interest charge",allow_overdraft:true,// Allow loan balance to go further negativemeta_data:{transaction_type:"interest_charge",interest_rate: interestRate,principal_amount: principal /100,// Convert back to dollars for readability}});console.log("Interest charged:", interestTransaction.data);return interestTransaction.data.transaction_id;}